内核:删掉 SERIAL_PUTS 的枚举项/派发分支/处理函数(内核自身的 serial.puts 是直接驱动调用,不受影响)。SDK:vpsdk/devfs.vp 新增 serial_puts()(惰性 open /dev/serial0 一次 + write),syscall.vp 删掉该成员。 调用点全部切到 devfs.serial_puts:vpsdk/stdio.vp 的 printf、vpsdk/vpui.vp 的 _serial_puts、Apps/Terminal 的 _sdbg、Apps/Explorer 的 _dbg、Libs/SerialLogger 的 log_info/log_warn(.so 同样走设备节点)。顺带清掉因此失效的 import(vpui 的 _syscall、Terminal 的 _syscall、Explorer 的 syscall)。 至此私有段只剩 7 项:TELL/SIZE/OPENDIR/READDIR/CLOSEDIR(可由 lseek/fstat/openat+getdents64 表达)与 LOAD_SO/SO_CALL1(动态库加载待下沉用户层)。
86 lines
3.1 KiB
Plaintext
86 lines
3.1 KiB
Plaintext
import vpsdk.fs as fs
|
||
import vpsdk.syscall as syscall
|
||
import string
|
||
from stdint import *
|
||
|
||
|
||
# ============================================================================
|
||
# devfs 设备层:设备节点路径 + 各设备的专用读写/控制助手。
|
||
#
|
||
# 设备节点由内核在启动时注册(见 VKernel/Kernel/main.vp 的 devfs_register_*),
|
||
# 用户态用普通 open/read/write/ioctl 访问 —— 不再有"设备专用 syscall"。
|
||
# ============================================================================
|
||
|
||
# 路径必须与内核注册名逐字一致
|
||
define DEV_SERIAL0 = "/dev/serial0"
|
||
define DEV_SERIAL1 = "/dev/serial1"
|
||
define DEV_FB0 = "/dev/fb0"
|
||
define DEV_KBD = "/dev/input/keyboard"
|
||
define DEV_MOUSE = "/dev/input/mouse"
|
||
define DEV_DESK = "/dev/desk"
|
||
|
||
# ioctl 命令与返回结构:必须与 VKernel/Kernel/drivers/devfs/devfs.vp 的
|
||
# FB_GET_INFO / FbInfo 逐字段一致(packed;4×u32 + 2×u64 = 32 字节)。
|
||
define FB_GET_INFO = 0x4600
|
||
|
||
@__attribute__(packed)
|
||
class FbInfo:
|
||
width: uint32
|
||
height: uint32
|
||
pitch: uint32
|
||
format: uint32
|
||
size: uint64
|
||
phys: uint64
|
||
|
||
|
||
def fb_open() -> int:
|
||
return fs.open(DEV_FB0, uint32(0))
|
||
|
||
def fb_get_info(fd: int) -> FbInfo:
|
||
"""查 framebuffer 几何 / 格式 / 物理区间。失败时返回全 0(size == 0 即可判失败)。"""
|
||
info: FbInfo
|
||
string.memset(&info, 0, FbInfo.__sizeof__())
|
||
fs.ioctl(fd, uint32(FB_GET_INFO), &info)
|
||
return info
|
||
|
||
def fb_map(fd: int, size: uint64) -> uint64:
|
||
"""把 framebuffer 映射进本进程,返回线性起始地址(0 = 失败),之后可直接写像素。
|
||
|
||
走通用 mmap(fd = 该设备 fd):内核按设备的 mmap_info 把物理区间按页映射进来。
|
||
"""
|
||
return syscall.mmap(0, size, uint64(syscall.PROT_READ | syscall.PROT_WRITE),
|
||
uint64(syscall.MAP_SHARED), uint64(fd), 0)
|
||
|
||
def kbd_open() -> int:
|
||
return fs.open(DEV_KBD, uint32(0))
|
||
|
||
def mouse_open() -> int:
|
||
return fs.open(DEV_MOUSE, uint32(0))
|
||
|
||
def shm_map(fd: int, size: uint64) -> uint64:
|
||
"""把共享内存设备映射进本进程,返回线性起始地址(0 = 失败)。
|
||
|
||
与 fb_map 同一机制(设备 mmap_info 给出的物理区间);不同点在于 /dev/desk
|
||
的区间对**所有**打开者都是同一块物理内存,因此天然可跨进程共享。
|
||
"""
|
||
return syscall.mmap(0, size, uint64(syscall.PROT_READ | syscall.PROT_WRITE),
|
||
uint64(syscall.MAP_SHARED), uint64(fd), 0)
|
||
|
||
# /dev/serial0 的 fd 惰性打开一次(-1 = 还没开;-2 = 开失败过,不再重试)
|
||
_serial_fd: int = -1
|
||
|
||
def serial_puts(msg: const str) -> int:
|
||
"""把字符串写到 /dev/serial0 —— 替代已删除的 SERIAL_PUTS syscall。
|
||
|
||
内核侧 serial0 设备的 write 按 C 字符串输出(内部就是 serial.puts),
|
||
所以这里只需把指针与长度递下去。
|
||
"""
|
||
global _serial_fd
|
||
if _serial_fd == -1:
|
||
_serial_fd = fs.open(DEV_SERIAL0, uint32(0))
|
||
if _serial_fd < 0:
|
||
_serial_fd = -2
|
||
if _serial_fd < 0: return -1
|
||
if msg is None: return -1
|
||
return fs.write(_serial_fd, msg, uint32(string.strlen(msg)))
|