根因:bootloader 只按 kernel 文件大小 AllocatePages(.bss 不占文件),于是 .bss 尾部(ticks/_perf_* 等全局量)与主线程栈区(0x60000~0x80000)在 memmap 里仍是 EfiConventionalMemory,被内核 mm 的堆 arena 当作空闲内存占用 → 内核全局量被写坏、 堆元数据被反向破坏,最终桌面线程栈上的 va_list 被改坏,vsnprintf 读 %d 变参时 #GP(rip=0x130d45, err=0x0)。 - linker.ld: .bss 末尾加 LONG(0) 强制 PROGBITS,使 kernel.bin 的 FileSize 涵盖 .bss,bootloader 的 PagesNeeded 得以预留整块内核镜像(含 .bss) - mm.init: 新增 KernelAddr/KernelEnd,挑 arena 时把与内核镜像 [kernel_PhysAddr, __bss_end) 重叠的 region 起点抬到镜像末端(不整段丢弃) - main.vp: 取 __bss_end 并传入 mm.init - boot.c: ExitBootServices 前用 AllocatePages(AllocateAddress, EfiLoaderData) 占位内核栈区 0x60000~0x80000,使其在 memmap 中标记已用 另含在途整理:多处补显式收窄转换(uint8()/uint16() 等)、kbd_svc 构造改为 kbd_svc.__init__() 等。
449 lines
15 KiB
Plaintext
449 lines
15 KiB
Plaintext
import drivers.serial.uart.serial as serial
|
|
import string
|
|
import viperlib
|
|
|
|
|
|
define MAX_FILE_DESCRIPTORS = 64
|
|
define MAX_DEVICE_FILES = 32
|
|
define MAX_DIRECTORIES = 16
|
|
define PATH_BUFFER_SIZE = 256
|
|
|
|
directories: [MAX_DIRECTORIES]devfs_directory = [0]
|
|
static directory_count: int = 0
|
|
|
|
files: [MAX_DEVICE_FILES]devfs_file = [0]
|
|
static file_count: int = 0
|
|
|
|
|
|
class _fd_table:
|
|
file: devfs_file*
|
|
flags: int
|
|
|
|
fd_table: [MAX_FILE_DESCRIPTORS]_fd_table = [0]
|
|
|
|
|
|
class devfs_directory:
|
|
name: [64]char
|
|
parent: devfs_directory*
|
|
|
|
@staticmethod
|
|
def find(path: const str, root_directory: devfs_directory*) -> devfs_directory*:
|
|
if not path or string.strchr(path, '/') != path: return None
|
|
if not root_directory: return None
|
|
|
|
current_dir: devfs_directory* = root_directory
|
|
result: [PATH_BUFFER_SIZE]str
|
|
token = string.split(path, "/", result, PATH_BUFFER_SIZE)
|
|
|
|
# `for i in result` 按 NULL 终止语义遍历(i8* 元素,split 尾哨兵 NULL 停):
|
|
# 编译器 _handle_array_iter 已实现"长度上限 + 解引用为空提前终止"。
|
|
for i in result:
|
|
found: bool = False
|
|
for d in range(directory_count):
|
|
dirp: devfs_directory = &directories[d]
|
|
if dirp.parent == current_dir and string.samestr(dirp.name, i):
|
|
current_dir = dirp
|
|
found = True
|
|
break
|
|
if not found: return None
|
|
|
|
return current_dir
|
|
|
|
@staticmethod
|
|
def find_child(name: const str, parent: devfs_directory*) -> devfs_directory*:
|
|
for d in range(directory_count):
|
|
dirp: devfs_directory = &directories[d]
|
|
if dirp.parent == parent and string.samestr(dirp.name, name):
|
|
return dirp
|
|
return None
|
|
|
|
@staticmethod
|
|
def list_subdirs(dir_ptr: devfs_directory*, buffer: str, size: uint32, pos: int) -> int:
|
|
for d in range(directory_count):
|
|
dirp: devfs_directory = &directories[d]
|
|
if dirp.parent == dir_ptr:
|
|
name_len: int = int(string.strlen(dirp.name))
|
|
if pos + name_len + 1 > size:
|
|
break
|
|
string.strcpy(buffer + pos, dirp.name)
|
|
pos += name_len
|
|
buffer[pos] = '\n'
|
|
pos += 1
|
|
return pos
|
|
|
|
|
|
virtual class devfs_file:
|
|
name: [64]char
|
|
private_data: rawptr
|
|
parent_dir: devfs_directory*
|
|
|
|
@staticmethod
|
|
def find_in_dir(file_name: const str, dir_ptr: devfs_directory*) -> devfs_file*:
|
|
for f in range(file_count):
|
|
fp: devfs_file* = &files[f]
|
|
if fp.parent_dir == dir_ptr and string.samestr(fp.name, file_name):
|
|
return fp
|
|
return None
|
|
|
|
@staticmethod
|
|
def list_in_dir(dir_ptr: devfs_directory*, buffer: str, size: uint32, pos: int) -> int:
|
|
for f in range(file_count):
|
|
filep: devfs_file* = &files[f]
|
|
if filep.parent_dir == dir_ptr:
|
|
name_len: int = int(string.strlen(filep.name))
|
|
if pos + name_len + 1 > size:
|
|
break
|
|
string.strcpy(buffer + pos, filep.name)
|
|
pos += name_len
|
|
buffer[pos] = '\n'
|
|
pos += 1
|
|
return pos
|
|
|
|
def open(self, path: const str, flags: int) -> int: return 0
|
|
def close(self, fd: int) -> int: return 0
|
|
def read(self, fd: int, buffer: rawptr, size: uint32) -> int: return 0
|
|
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int: return 0
|
|
def ioctl(self, fd: int, request: int, arg: rawptr) -> int: return 0
|
|
|
|
|
|
class _DevFSObject:
|
|
root_directory: devfs_directory*
|
|
|
|
def __init__(self):
|
|
global directory_count, file_count
|
|
self.root_directory = None
|
|
directory_count = 0
|
|
file_count = 0
|
|
string.memset(&directories, 0, devfs_directory.__sizeof__() * MAX_DIRECTORIES)
|
|
string.memset(&files, 0, devfs_file.__sizeof__() * MAX_DEVICE_FILES)
|
|
string.memset(&fd_table, 0, _fd_table.__sizeof__() * MAX_FILE_DESCRIPTORS)
|
|
|
|
def create_single_dir(self, parent: devfs_directory*, dir_name: const str) -> devfs_directory*:
|
|
global directory_count
|
|
if not parent or not dir_name: return None
|
|
if directory_count >= MAX_DIRECTORIES: return None
|
|
if string.strlen(dir_name) >= 64: return None
|
|
|
|
new_dir: devfs_directory* = &directories[directory_count]
|
|
directory_count += 1
|
|
|
|
string.strcpy(new_dir.name, dir_name)
|
|
new_dir.parent = parent
|
|
|
|
return new_dir
|
|
|
|
def find_or_create_directory(self, path: const str) -> devfs_directory*:
|
|
global directory_count
|
|
if not path or string.samestr(path, "/"): return None
|
|
|
|
if not self.root_directory:
|
|
self.root_directory = &directories[directory_count]
|
|
directory_count += 1
|
|
string.strcpy(self.root_directory.name, "")
|
|
self.root_directory.parent = None
|
|
current: devfs_directory* = self.root_directory
|
|
buf: [PATH_BUFFER_SIZE]char
|
|
string.memset(&buf, 0, PATH_BUFFER_SIZE)
|
|
buf_idx: int = 0
|
|
p: int = 0
|
|
if path[p] == '/': p += 1
|
|
while path[p] != '\0':
|
|
if path[p] == '/':
|
|
if buf_idx > 0:
|
|
found_child: devfs_directory* = devfs_directory.find_child(buf, current)
|
|
if not found_child:
|
|
found_child = self.create_single_dir(current, buf)
|
|
if not found_child: return None
|
|
current = found_child
|
|
string.memset(&buf, 0, PATH_BUFFER_SIZE)
|
|
buf_idx = 0
|
|
p += 1
|
|
else:
|
|
buf[buf_idx] = path[p]
|
|
buf_idx += 1
|
|
p += 1
|
|
if buf_idx > 0:
|
|
found_child: devfs_directory* = devfs_directory.find_child(buf, current)
|
|
if not found_child:
|
|
found_child = self.create_single_dir(current, buf)
|
|
if not found_child: return None
|
|
current = found_child
|
|
return current
|
|
|
|
def init(self) -> int:
|
|
self.create_directory("/dev")
|
|
self.create_directory("/dev/input")
|
|
return 0
|
|
|
|
def create_directory(self, path: const str) -> int:
|
|
dir_ptr: devfs_directory* = self.find_or_create_directory(path)
|
|
return 0 if dir_ptr else -1
|
|
|
|
def create_file(self, path: const str, file_ptr: devfs_file*, private_data: rawptr) -> int:
|
|
global file_count
|
|
path_copy: [PATH_BUFFER_SIZE]char
|
|
string.memset(&path_copy, 0, PATH_BUFFER_SIZE)
|
|
string.strcpy(&path_copy, path)
|
|
|
|
last_slash: str = string.strrchr(path_copy, '/')
|
|
|
|
if not last_slash: return -1
|
|
|
|
last_slash[0] = '\0'
|
|
dir_path = path_copy
|
|
file_name: str = last_slash + 1
|
|
|
|
dir_ptr: devfs_directory* = self.find_or_create_directory(dir_path)
|
|
if not dir_ptr: return -1
|
|
if devfs_file.find_in_dir(file_name, dir_ptr): return -1
|
|
if file_count >= MAX_DEVICE_FILES: return -1
|
|
|
|
if file_ptr:
|
|
string.strcpy(file_ptr.name, file_name)
|
|
file_ptr.private_data = private_data
|
|
file_ptr.parent_dir = dir_ptr
|
|
files[file_count] = *file_ptr
|
|
else:
|
|
new_file: devfs_file* = &files[file_count]
|
|
string.strcpy(new_file.name, file_name)
|
|
new_file.private_data = private_data
|
|
new_file.parent_dir = dir_ptr
|
|
|
|
file_count += 1
|
|
return 0
|
|
|
|
def open(self, path: const str, flags: int) -> int:
|
|
path_copy: [PATH_BUFFER_SIZE]char
|
|
string.memset(&path_copy, 0, PATH_BUFFER_SIZE)
|
|
string.strcpy(&path_copy, path)
|
|
|
|
last_slash: str = string.strrchr(path_copy, '/')
|
|
|
|
if not last_slash: return -1
|
|
|
|
last_slash[0] = '\0'
|
|
dir_path = path_copy
|
|
file_name: str = last_slash + 1
|
|
|
|
dir_ptr: devfs_directory* = devfs_directory.find(dir_path, self.root_directory)
|
|
if not dir_ptr: return -1
|
|
|
|
file_ptr: devfs_file* = devfs_file.find_in_dir(file_name, dir_ptr)
|
|
if not file_ptr: return -1
|
|
|
|
fd: int = -1
|
|
for i in range(MAX_FILE_DESCRIPTORS):
|
|
if not fd_table[i].file:
|
|
fd = i
|
|
break
|
|
if fd == -1: return -1
|
|
|
|
ret: int = file_ptr.open(path, flags)
|
|
if ret != 0: return ret
|
|
|
|
fd_table[fd].file = file_ptr
|
|
fd_table[fd].flags = flags
|
|
return fd
|
|
|
|
def close(self, fd: int) -> int:
|
|
if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file:
|
|
return -1
|
|
file_ptr: devfs_file* = fd_table[fd].file
|
|
file_ptr.close(fd)
|
|
fd_table[fd].file = None
|
|
fd_table[fd].flags = 0
|
|
return 0
|
|
|
|
def read(self, fd: int, buffer: rawptr, size: uint32) -> int:
|
|
if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file:
|
|
return -1
|
|
file_ptr: devfs_file* = fd_table[fd].file
|
|
return file_ptr.read(fd, buffer, size)
|
|
|
|
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int:
|
|
if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file:
|
|
return -1
|
|
file_ptr: devfs_file* = fd_table[fd].file
|
|
return file_ptr.write(fd, buffer, size)
|
|
|
|
def ioctl(self, fd: int, cmd: uint32, arg: rawptr) -> int:
|
|
if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file:
|
|
return -1
|
|
file_ptr: devfs_file* = fd_table[fd].file
|
|
return file_ptr.ioctl(fd, cmd, arg)
|
|
|
|
def list_directory(self, path: const str,
|
|
buffer: str,
|
|
size: uint32) -> int:
|
|
dir_ptr: devfs_directory* = devfs_directory.find(path, self.root_directory)
|
|
if not dir_ptr or not buffer or size == 0: return -1
|
|
|
|
pos: int = devfs_directory.list_subdirs(dir_ptr, buffer, size, 0)
|
|
pos = devfs_file.list_in_dir(dir_ptr, buffer, size, pos)
|
|
|
|
return pos
|
|
|
|
DevFSObject: _DevFSObject* = _DevFSObject()
|
|
|
|
|
|
def devfs_init() -> int:
|
|
global DevFSObject
|
|
DevFSObject.__init__()
|
|
DevFSObject.init()
|
|
return 0
|
|
|
|
def devfs_create_directory(path: const str) -> int:
|
|
return DevFSObject.create_directory(path)
|
|
|
|
def devfs_create_file(path: const str, file_ptr: devfs_file*, private_data: rawptr) -> int:
|
|
return DevFSObject.create_file(path, file_ptr, private_data)
|
|
|
|
def devfs_open(path: const str, flags: int) -> int:
|
|
return DevFSObject.open(path, flags)
|
|
|
|
def devfs_close(fd: int) -> int:
|
|
return DevFSObject.close(fd)
|
|
|
|
def devfs_read(fd: int, buffer: rawptr, size: uint32) -> int:
|
|
return DevFSObject.read(fd, buffer, size)
|
|
|
|
def devfs_write(fd: int, buffer: const rawptr, size: uint32) -> int:
|
|
return DevFSObject.write(fd, buffer, size)
|
|
|
|
def devfs_ioctl(fd: int, cmd: uint32, arg: rawptr) -> int:
|
|
return DevFSObject.ioctl(fd, cmd, arg)
|
|
|
|
def devfs_list_directory(path: const str, buffer: str, size: uint32) -> int:
|
|
return DevFSObject.list_directory(path, buffer, size)
|
|
|
|
serial0_file: devfs_file* = devfs_file()
|
|
|
|
def serial0_open(self: rawptr, path: const str, flags: int) -> int:
|
|
serial.puts("[serial0] open: ")
|
|
serial.puts(path)
|
|
serial.puts("\n")
|
|
return 0
|
|
|
|
def serial0_close(self: rawptr, fd: int) -> int:
|
|
serial.puts("[serial0] close\n")
|
|
return 0
|
|
|
|
def serial0_read(self: rawptr, fd: int, buffer: rawptr, size: uint32) -> int:
|
|
serial.puts("[serial0] read\n")
|
|
return 0
|
|
|
|
def serial0_write(self: rawptr, fd: int, buffer: const rawptr, size: uint32) -> int:
|
|
serial.puts("[serial0] write\n")
|
|
serial.puts(buffer)
|
|
serial.puts("\n")
|
|
return size
|
|
|
|
def devfs_register_serial0() -> int:
|
|
global serial0_file
|
|
serial0_file.__init__()
|
|
serial0_file.open = serial0_open
|
|
serial0_file.close = serial0_close
|
|
serial0_file.read = serial0_read
|
|
serial0_file.write = serial0_write
|
|
return devfs_create_file("/dev/serial0", serial0_file, None)
|
|
|
|
|
|
virtual class serial1_device(devfs_file):
|
|
def open(self, path: const str, flags: int) -> int:
|
|
serial.puts("[serial1] open: ")
|
|
serial.puts(path)
|
|
serial.puts("\n")
|
|
return 0
|
|
|
|
def close(self, fd: int) -> int:
|
|
serial.puts("[serial1] close\n")
|
|
return 0
|
|
|
|
def read(self, fd: int, buffer: rawptr, size: uint32) -> int:
|
|
serial.puts("[serial1] read\n")
|
|
return 0
|
|
|
|
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int:
|
|
serial.puts("[serial1] write\n")
|
|
serial.puts(str(buffer))
|
|
serial.puts("\n")
|
|
return size
|
|
|
|
serial1_file: serial1_device* = serial1_device()
|
|
|
|
def devfs_register_serial1() -> int:
|
|
global serial1_file
|
|
serial1_file.__init__()
|
|
return devfs_create_file("/dev/serial1", serial1_file, None)
|
|
|
|
import drivers.input.keyboard.keyboard as keyboard
|
|
import drivers.input.mouse.mouse as mouse
|
|
|
|
|
|
virtual class keyboard_device(devfs_file):
|
|
def open(self, path: const str, flags: int) -> int:
|
|
return 0
|
|
|
|
def close(self, fd: int) -> int:
|
|
return 0
|
|
|
|
def read(self, fd: int, buffer: rawptr, size: uint32) -> int:
|
|
count: uint32 = 0
|
|
while count < size and keyboard.has_data():
|
|
sc: uint8 = keyboard.read_scancode()
|
|
ch: char = keyboard.scancode_to_ascii(sc)
|
|
if ch != '\0':
|
|
char*(buffer)[count] = ch
|
|
count += 1
|
|
return count
|
|
|
|
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int:
|
|
return -1
|
|
|
|
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
|
|
return 0
|
|
|
|
kbd_file: keyboard_device* = keyboard_device()
|
|
|
|
def devfs_register_keyboard() -> int:
|
|
global kbd_file
|
|
kbd_file.__init__()
|
|
keyboard.init()
|
|
return devfs_create_file("/dev/input/keyboard", kbd_file, None)
|
|
|
|
|
|
virtual class mouse_device(devfs_file):
|
|
def open(self, path: const str, flags: int) -> int:
|
|
return 0
|
|
|
|
def close(self, fd: int) -> int:
|
|
return 0
|
|
|
|
def read(self, fd: int, buffer: rawptr, size: uint32) -> int:
|
|
if not mouse.has_data(): return 0
|
|
pkt: mouse.mouse_packet
|
|
mouse.read_packet(&pkt)
|
|
if size >= 1:
|
|
uint8*(buffer)[0] = pkt.buttons
|
|
|
|
if size >= 9:
|
|
buf: uint32* = uint32*(uint64(buffer) + 1)
|
|
int32*(buf)[0] = mouse.get_x()
|
|
int32*(buf)[1] = mouse.get_y()
|
|
return 9
|
|
return 1
|
|
|
|
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int:
|
|
return -1
|
|
|
|
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
|
|
return 0
|
|
|
|
mse_file: mouse_device* = mouse_device()
|
|
|
|
def devfs_register_mouse() -> int:
|
|
global mse_file
|
|
mse_file.__init__()
|
|
mouse.init()
|
|
return devfs_create_file("/dev/input/mouse", mse_file, None)
|