feat(devfs): S1 —— 暴露 /dev/fb0 并让用户态可达 /dev/*(含 ioctl)
devfs:新增 /dev/fb0(framebuffer_device),提供 ioctl(FB_GET_INFO) 回填几何/格式/物理区间,并新增 devfs_file.mmap_info 虚方法(默认不可映射)把物理区间交给内核 mmap 用;main.vp 在 devfs_init 后登记它。输入设备(/dev/input/keyboard、/dev/input/mouse)此前已存在,本轮起从用户态可达。 用户态可达性:Process 增 fd_kind[](0=FAT32 fileobj*,1=devfs_fd+1),OPEN 对 "/dev/" 前缀改走 devfs,READ/WRITE/CLOSE 按 kind 分派;Process.exit 只对 kind=0 调 fat32.close(把 devfs fd 当 fileobj* 会跑飞)。fd 种类常量放在 process.vp 供 syscall.vp 引用,避免 process 反向 import devfs(devfs→keyboard/mouse→intr.idt→sched→process 会成环)。 新增 IOCTL syscall(Linux 号 16,本轮开始实现):只放给 devfs 设备,SDK 侧 vpsdk/fs.vp 加 ioctl() 助手。
This commit is contained in:
1 parent
ca72ddbbf7
commit
f4c653958e
6 files changed
+156
-4
No files matched your search
@@ -104,6 +104,9 @@ virtual class devfs_file:
|
||||
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
|
||||
# mmap 支持:默认不可映射(返回 -1)。可映射设备(/dev/fb0)覆写它,
|
||||
# 把自己的物理区间交给内核 mmap 去映射进用户地址空间。
|
||||
def mmap_info(self, fd: int, out_phys: uint64*, out_size: uint64*) -> int: return -1
|
||||
|
||||
|
||||
class _DevFSObject:
|
||||
@@ -272,6 +275,12 @@ class _DevFSObject:
|
||||
file_ptr: devfs_file* = fd_table[fd].file
|
||||
return file_ptr.ioctl(fd, cmd, arg)
|
||||
|
||||
def get_mmap_info(self, fd: int, out_phys: uint64*, out_size: uint64*) -> 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.mmap_info(fd, out_phys, out_size)
|
||||
|
||||
def list_directory(self, path: const str,
|
||||
buffer: str,
|
||||
size: uint32) -> int:
|
||||
@@ -313,6 +322,9 @@ def devfs_write(fd: int, buffer: const rawptr, size: uint32) -> int:
|
||||
def devfs_ioctl(fd: int, cmd: uint32, arg: rawptr) -> int:
|
||||
return DevFSObject.ioctl(fd, cmd, arg)
|
||||
|
||||
def devfs_get_mmap_info(fd: int, out_phys: uint64*, out_size: uint64*) -> int:
|
||||
return DevFSObject.get_mmap_info(fd, out_phys, out_size)
|
||||
|
||||
def devfs_list_directory(path: const str, buffer: str, size: uint32) -> int:
|
||||
return DevFSObject.list_directory(path, buffer, size)
|
||||
|
||||
@@ -446,3 +458,72 @@ def devfs_register_mouse() -> int:
|
||||
mse_file.__init__()
|
||||
mouse.init()
|
||||
return devfs_create_file("/dev/input/mouse", mse_file, None)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# /dev/fb0:framebuffer 设备(供用户态图形壳 explorer 接管桌面绘制)。
|
||||
# · read/write 不支持(-1):像素由用户态经 mmap 取到线性地址后直接写;
|
||||
# · ioctl(FB_GET_INFO):把几何/格式/物理区间回填进用户缓冲(FbInfo);
|
||||
# · mmap_info:把本设备的物理区间交给内核 mmap 映射进用户地址空间。
|
||||
# 本节点只记录 BootInfo 里的物理地址与几何,不自己持有 framebuffer 映射。
|
||||
# ============================================================================
|
||||
define FB_GET_INFO = 0x4600
|
||||
|
||||
@__attribute__(packed)
|
||||
class FbInfo:
|
||||
width: uint32
|
||||
height: uint32
|
||||
pitch: uint32
|
||||
format: uint32
|
||||
size: uint64
|
||||
phys: uint64
|
||||
|
||||
virtual class framebuffer_device(devfs_file):
|
||||
fb_phys: uint64
|
||||
fb_size: uint64
|
||||
fb_w: uint32
|
||||
fb_h: uint32
|
||||
fb_pitch: uint32
|
||||
fb_format: uint32
|
||||
|
||||
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 -1
|
||||
|
||||
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int:
|
||||
return -1
|
||||
|
||||
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
|
||||
if request != FB_GET_INFO or not arg:
|
||||
return -1
|
||||
info: FbInfo* = FbInfo*(uint64(arg))
|
||||
info.width = self.fb_w
|
||||
info.height = self.fb_h
|
||||
info.pitch = self.fb_pitch
|
||||
info.format = self.fb_format
|
||||
info.size = self.fb_size
|
||||
info.phys = self.fb_phys
|
||||
return 0
|
||||
|
||||
def mmap_info(self, fd: int, out_phys: uint64*, out_size: uint64*) -> int:
|
||||
if out_phys: *out_phys = self.fb_phys
|
||||
if out_size: *out_size = self.fb_size
|
||||
return 0
|
||||
|
||||
fb0_file: framebuffer_device* = framebuffer_device()
|
||||
|
||||
def devfs_register_fb0(fb: rawptr, width: int, height: int, pitch: int, format: int, size: uint64) -> int:
|
||||
global fb0_file
|
||||
fb0_file.__init__()
|
||||
fb0_file.fb_phys = uint64(fb)
|
||||
fb0_file.fb_size = size
|
||||
fb0_file.fb_w = uint32(width)
|
||||
fb0_file.fb_h = uint32(height)
|
||||
fb0_file.fb_pitch = uint32(pitch)
|
||||
fb0_file.fb_format = uint32(format)
|
||||
return devfs_create_file("/dev/fb0", fb0_file, None)
|
||||
@@ -9,6 +9,7 @@ import string
|
||||
import mm.mm as mm
|
||||
import paging.paging as paging
|
||||
import execrunner.elf as elf
|
||||
import drivers.devfs.devfs as devfs
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -29,7 +30,8 @@ enum Syscall:
|
||||
STAT = 4 # stat(path, info)(结构体仍是本系统的 fileinfo)
|
||||
SEEK = 8 # lseek(fd, offset, whence)(whence 目前恒 0 = SEEK_SET)
|
||||
MMAP = 9 # mmap(size) → VA(ABI 待向 Linux 的 addr/len/prot/flags/fd/off 靠拢)
|
||||
MUNMAP = 11 # munmap(ptr, size)(目前空实现)
|
||||
MUNMAP = 11 # munmap(ptr, size)(目前空实现)
|
||||
IOCTL = 16 # ioctl(fd, request, arg):设备控制(当前用于 /dev/fb0 查几何)
|
||||
YIELD = 24 # sched_yield()
|
||||
THREAD_CREATE = 56 # clone():建用户线程,返回 tid
|
||||
SPAWN = 59 # execve():加载并运行新 ELF,返回 pid
|
||||
@@ -209,9 +211,32 @@ def SET_CURSOR(win_id: int, cursor_t: int) -> int:
|
||||
desktop.set_cursor_type(win_id, cursor_t)
|
||||
return 0
|
||||
|
||||
def _is_dev_path(path: const str) -> int:
|
||||
"""路径是否以 "/dev/" 开头(走 devfs 设备节点而不是 FAT32)。逐字符比较,不引 str 库。"""
|
||||
if path[0] != 47: return 0 # '/'
|
||||
if path[1] != 100: return 0 # 'd'
|
||||
if path[2] != 101: return 0 # 'e'
|
||||
if path[3] != 118: return 0 # 'v'
|
||||
if path[4] != 47: return 0 # '/'
|
||||
return 1
|
||||
|
||||
def OPEN(path_ptr: str, mode: uint32) -> int:
|
||||
p: process.Process* = _current_proc()
|
||||
path: const str = path_ptr
|
||||
# /dev/* 走 devfs 设备节点(serial / 输入 / fb…),其余仍走 FAT32 文件系统。
|
||||
# 判据用逐字符比较(不引 str 库函数):"/dev/" = 47 '/'、100 'd'、101 'e'、118 'v'、47 '/'。
|
||||
if _is_dev_path(path):
|
||||
dfd: int = devfs.devfs_open(path, int(mode))
|
||||
if dfd < 0:
|
||||
return -1
|
||||
fd: int = _fd_alloc(p)
|
||||
if fd < 0:
|
||||
devfs.devfs_close(dfd)
|
||||
return -1
|
||||
# 存 devfs_fd+1:devfs fd 0 是合法值,直接用会与"空槽位"混淆
|
||||
p.fd_table[fd] = rawptr(uint64(dfd + 1))
|
||||
p.fd_kind[fd] = process.FD_KIND_DEVFS
|
||||
return fd
|
||||
fat32.lock()
|
||||
fp: rawptr = fat32.open(path, uint8(mode))
|
||||
if not fp:
|
||||
@@ -223,6 +248,7 @@ def OPEN(path_ptr: str, mode: uint32) -> int:
|
||||
fat32.unlock()
|
||||
return -1
|
||||
p.fd_table[fd] = fp
|
||||
p.fd_kind[fd] = process.FD_KIND_FAT32
|
||||
fat32.unlock()
|
||||
return fd
|
||||
|
||||
@@ -233,6 +259,10 @@ def CLOSE(fd: int) -> int:
|
||||
fp: rawptr = p.fd_table[fd]
|
||||
if not fp:
|
||||
return int(fat32_types.FRESULT.FR_INVALID_OBJECT)
|
||||
if p.fd_kind[fd] == process.FD_KIND_DEVFS:
|
||||
res_dev: int = devfs.devfs_close(int(uint64(fp)) - 1)
|
||||
_fd_free(p, fd)
|
||||
return res_dev
|
||||
fat32.lock()
|
||||
res: int = int(fat32.close(fp))
|
||||
fat32.unlock()
|
||||
@@ -246,6 +276,8 @@ def READ(fd: int, buf_ptr: rawptr, count: uint32) -> int:
|
||||
fp: rawptr = p.fd_table[fd]
|
||||
if not fp:
|
||||
return -1
|
||||
if p.fd_kind[fd] == process.FD_KIND_DEVFS:
|
||||
return devfs.devfs_read(int(uint64(fp)) - 1, buf_ptr, count)
|
||||
fat32.lock()
|
||||
br: uint32 = fat32.read(fp, buf_ptr, count)
|
||||
fat32.unlock()
|
||||
@@ -258,11 +290,24 @@ def WRITE(fd: int, buf_ptr: rawptr, count: uint32) -> int:
|
||||
fp: rawptr = p.fd_table[fd]
|
||||
if not fp:
|
||||
return -1
|
||||
if p.fd_kind[fd] == process.FD_KIND_DEVFS:
|
||||
return devfs.devfs_write(int(uint64(fp)) - 1, buf_ptr, count)
|
||||
fat32.lock()
|
||||
bw: uint32 = fat32.write(fp, buf_ptr, count)
|
||||
fat32.unlock()
|
||||
return int(bw)
|
||||
|
||||
def IOCTL(fd: int, request: uint32, arg: rawptr) -> int:
|
||||
"""设备控制(Linux ioctl 的子集):当前只有 devfs 设备支持,用于 /dev/fb0 查几何。"""
|
||||
p: process.Process* = _current_proc()
|
||||
if fd < 0 or fd >= process.PROC_MAX_FDS:
|
||||
return -1
|
||||
if not p.fd_used[fd]:
|
||||
return -1
|
||||
if p.fd_kind[fd] != process.FD_KIND_DEVFS:
|
||||
return -1
|
||||
return devfs.devfs_ioctl(int(uint64(p.fd_table[fd])) - 1, request, arg)
|
||||
|
||||
def SEEK(fd: int, offset: uint32) -> int:
|
||||
p: process.Process* = _current_proc()
|
||||
if fd < 0 or fd >= process.PROC_MAX_FDS:
|
||||
@@ -418,6 +463,8 @@ export def syscall_handler(num: uint64, arg1: uint64, arg2: uint64, arg3: uint64
|
||||
elif n == int(Syscall.WRITE):
|
||||
buf_ptr: rawptr = rawptr(arg2)
|
||||
return uint64(WRITE(int(arg1), buf_ptr, uint32(arg3)))
|
||||
elif n == int(Syscall.IOCTL):
|
||||
return uint64(IOCTL(int(arg1), uint32(arg2), rawptr(arg3)))
|
||||
elif n == int(Syscall.SEEK):
|
||||
return uint64(SEEK(int(arg1), uint32(arg2)))
|
||||
elif n == int(Syscall.TELL):
|
||||
|
||||
@@ -284,6 +284,9 @@ class ViperKernel:
|
||||
devfs.devfs_register_serial1()
|
||||
devfs.devfs_register_keyboard()
|
||||
devfs.devfs_register_mouse()
|
||||
# /dev/fb0:把 framebuffer 的物理区间与几何登记成设备节点,供用户态图形壳
|
||||
# explorer 经 open + ioctl(FB_GET_INFO) + mmap 接管屏幕绘制(S1)。
|
||||
devfs.devfs_register_fb0(fb, width, height, pitch, fb_format, fb_size)
|
||||
|
||||
serial.puts("[main] sched started\n")
|
||||
|
||||
|
||||
@@ -14,7 +14,12 @@ define PROC_BLOCKED = 2
|
||||
define PROC_DONE = 3
|
||||
define MAX_PROCESSES = 8
|
||||
define MAX_PROC_THREADS = 8
|
||||
define PROC_MAX_FDS = 16
|
||||
define PROC_MAX_FDS = 16
|
||||
# fd 种类(process.fd_kind[])。定义放这里、由 intr/syscall.vp 以 process.FD_KIND_* 引用,
|
||||
# 这样 process.vp 不必 import devfs —— devfs → keyboard/mouse → intr.idt → sched → process
|
||||
# 会形成环,不能让 process 反向依赖 devfs。
|
||||
define FD_KIND_FAT32 = 0
|
||||
define FD_KIND_DEVFS = 1
|
||||
define PROC_MAX_DIRS = 8
|
||||
define KERN_STACK_SIZE = 8192
|
||||
define USER_STACK_SIZE = 65536
|
||||
@@ -39,6 +44,10 @@ class Process:
|
||||
name: [32]char
|
||||
fd_table: [PROC_MAX_FDS]rawptr
|
||||
fd_used: [PROC_MAX_FDS]uint8
|
||||
# 0 = FAT32 文件(fd_table[i] 里是 fileobj*);1 = devfs 设备(fd_table[i] 里是
|
||||
# devfs_fd+1,+1 只为避开"devfs fd 0"与空指针的歧义)。READ/WRITE/CLOSE/IOCTL 与
|
||||
# Process.exit 都必须按它分派 —— 把 devfs fd 当 fileobj* 解引用会直接跑飞。
|
||||
fd_kind: [PROC_MAX_FDS]uint8
|
||||
dir_table: [PROC_MAX_DIRS]rawptr
|
||||
dir_used: [PROC_MAX_DIRS]uint8
|
||||
dir_pool: [PROC_MAX_DIRS]fat32_types.dirobj
|
||||
@@ -56,10 +65,15 @@ class Process:
|
||||
for i in range(PROC_MAX_FDS):
|
||||
if self.fd_used[i]:
|
||||
fp: rawptr = self.fd_table[i]
|
||||
if fp:
|
||||
# devfs 设备 fd 绝不能当 fileobj* 交给 fat32.close —— 那会把 devfs_fd+1
|
||||
# 当指针解引用而跑飞。devfs 的 fd 表是独立的另一张;正规退出路径本来就不
|
||||
# 回收 fd(见 intr/syscall.vp 的 EXIT 不调 Process.exit),这里只清槽位,
|
||||
# app 自己调 CLOSE 时才走 devfs_close。
|
||||
if fp and self.fd_kind[i] == FD_KIND_FAT32:
|
||||
fat32.close(fp)
|
||||
self.fd_used[i] = 0
|
||||
self.fd_table[i] = None
|
||||
self.fd_kind[i] = 0
|
||||
for i in range(PROC_MAX_DIRS):
|
||||
if self.dir_used[i]:
|
||||
dp: rawptr = self.dir_table[i]
|
||||
@@ -117,6 +131,7 @@ class ProcessManager:
|
||||
for j in range(PROC_MAX_FDS):
|
||||
p.fd_used[j] = 0
|
||||
p.fd_table[j] = None
|
||||
p.fd_kind[j] = 0
|
||||
for j in range(PROC_MAX_DIRS):
|
||||
p.dir_used[j] = 0
|
||||
p.dir_table[j] = None
|
||||
@@ -179,6 +194,7 @@ class ProcessManager:
|
||||
for j in range(PROC_MAX_FDS):
|
||||
p.fd_used[j] = 0
|
||||
p.fd_table[j] = None
|
||||
p.fd_kind[j] = 0
|
||||
for j in range(PROC_MAX_DIRS):
|
||||
p.dir_used[j] = 0
|
||||
p.dir_table[j] = None
|
||||
|
||||
@@ -55,6 +55,10 @@ def closedir(dd: int) -> int:
|
||||
def stat(path: const str, info: rawptr) -> int:
|
||||
return int(syscall._syscall3(uint64(syscall.Syscall.STAT), uint64(path), uint64(info), 0))
|
||||
|
||||
def ioctl(fd: int, request: uint32, arg: rawptr) -> int:
|
||||
"""设备控制(Linux ioctl 子集)。当前只有 devfs 设备(如 /dev/fb0)实现了它。"""
|
||||
return int(syscall._syscall3(uint64(syscall.Syscall.IOCTL), uint64(fd), uint64(request), uint64(arg)))
|
||||
|
||||
class FileIO:
|
||||
_fd: int
|
||||
_pos: uint32
|
||||
|
||||
+2
-1
@@ -13,7 +13,8 @@ enum Syscall:
|
||||
STAT = 4 # stat(path, info)(结构体仍是本系统的 fileinfo)
|
||||
SEEK = 8 # lseek(fd, offset, whence)(whence 目前恒 0 = SEEK_SET)
|
||||
MMAP = 9 # mmap(size) → VA(ABI 待向 Linux 的 addr/len/prot/flags/fd/off 靠拢)
|
||||
MUNMAP = 11 # munmap(ptr, size)(目前空实现)
|
||||
MUNMAP = 11 # munmap(ptr, size)(目前空实现)
|
||||
IOCTL = 16 # ioctl(fd, request, arg):设备控制(当前用于 /dev/fb0 查几何)
|
||||
YIELD = 24 # sched_yield()
|
||||
THREAD_CREATE = 56 # clone():建用户线程,返回 tid
|
||||
SPAWN = 59 # execve():加载并运行新 ELF,返回 pid
|
||||
|
||||
Reference in new issue
Block a user