fix(vkernel): 预留内核 .bss 与栈区,修堆 arena 覆盖未预留内核内存
根因: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__() 等。
This commit is contained in:
1 parent
52728bc8da
commit
0919a058a8
17 files changed
+148
-105
No files matched your search
@@ -215,7 +215,7 @@ class _CPUObject:
|
||||
string.memset(&self.tss, 0, self.tss.__sizeof__())
|
||||
self.tss.io_map_base = self.tss.__sizeof__()
|
||||
string.memset(&_per_cpu, 0, per_cpu_data.__sizeof__())
|
||||
gdt.setTSS64(5, uint64(&self.tss), self.tss.__sizeof__() - 1)
|
||||
gdt.setTSS64(5, uint64(&self.tss), int(self.tss.__sizeof__() - 1))
|
||||
gdt.flush()
|
||||
# IA32_KERNEL_GS_BASE holds the per_cpu address for swapgs.
|
||||
# When entering from Ring 3, swapgs swaps IA32_GS_BASE (0) with
|
||||
@@ -245,7 +245,7 @@ class _CPUObject:
|
||||
# 下标按字节偏移且被截断为 i8(只写低字节、偏移不乘 4)。
|
||||
brand_addr: uint64 = uint64(uint32*(info.brand_string))
|
||||
for i in range(3):
|
||||
cpuid(0x80000002 + i, &res)
|
||||
cpuid(int(0x80000002 + i), &res)
|
||||
off_b: uint64 = uint64(i) * 16
|
||||
*(uint32*(brand_addr + off_b + 0)) = res.eax
|
||||
*(uint32*(brand_addr + off_b + 4)) = res.ebx
|
||||
|
||||
@@ -62,7 +62,7 @@ class devfs_directory:
|
||||
for d in range(directory_count):
|
||||
dirp: devfs_directory = &directories[d]
|
||||
if dirp.parent == dir_ptr:
|
||||
name_len: int = string.strlen(dirp.name)
|
||||
name_len: int = int(string.strlen(dirp.name))
|
||||
if pos + name_len + 1 > size:
|
||||
break
|
||||
string.strcpy(buffer + pos, dirp.name)
|
||||
@@ -90,7 +90,7 @@ virtual class devfs_file:
|
||||
for f in range(file_count):
|
||||
filep: devfs_file* = &files[f]
|
||||
if filep.parent_dir == dir_ptr:
|
||||
name_len: int = string.strlen(filep.name)
|
||||
name_len: int = int(string.strlen(filep.name))
|
||||
if pos + name_len + 1 > size:
|
||||
break
|
||||
string.strcpy(buffer + pos, filep.name)
|
||||
@@ -115,8 +115,8 @@ class _DevFSObject:
|
||||
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)
|
||||
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
|
||||
@@ -283,14 +283,12 @@ class _DevFSObject:
|
||||
|
||||
return pos
|
||||
|
||||
DevFSObject: _DevFSObject*
|
||||
_DevFSObject_instance: _DevFSObject
|
||||
DevFSObject: _DevFSObject* = _DevFSObject()
|
||||
|
||||
|
||||
def devfs_init() -> int:
|
||||
global DevFSObject, _DevFSObject_instance
|
||||
DevFSObject = &_DevFSObject_instance
|
||||
_DevFSObject_instance = _DevFSObject()
|
||||
global DevFSObject
|
||||
DevFSObject.__init__()
|
||||
DevFSObject.init()
|
||||
return 0
|
||||
|
||||
@@ -318,7 +316,7 @@ def devfs_ioctl(fd: int, cmd: uint32, arg: rawptr) -> int:
|
||||
def devfs_list_directory(path: const str, buffer: str, size: uint32) -> int:
|
||||
return DevFSObject.list_directory(path, buffer, size)
|
||||
|
||||
serial0_file: devfs_file
|
||||
serial0_file: devfs_file* = devfs_file()
|
||||
|
||||
def serial0_open(self: rawptr, path: const str, flags: int) -> int:
|
||||
serial.puts("[serial0] open: ")
|
||||
@@ -342,7 +340,7 @@ def serial0_write(self: rawptr, fd: int, buffer: const rawptr, size: uint32) ->
|
||||
|
||||
def devfs_register_serial0() -> int:
|
||||
global serial0_file
|
||||
serial0_file = devfs_file()
|
||||
serial0_file.__init__()
|
||||
serial0_file.open = serial0_open
|
||||
serial0_file.close = serial0_close
|
||||
serial0_file.read = serial0_read
|
||||
@@ -371,11 +369,11 @@ virtual class serial1_device(devfs_file):
|
||||
serial.puts("\n")
|
||||
return size
|
||||
|
||||
serial1_file: serial1_device
|
||||
serial1_file: serial1_device* = serial1_device()
|
||||
|
||||
def devfs_register_serial1() -> int:
|
||||
global serial1_file
|
||||
serial1_file = serial1_device()
|
||||
serial1_file.__init__()
|
||||
return devfs_create_file("/dev/serial1", serial1_file, None)
|
||||
|
||||
import drivers.input.keyboard.keyboard as keyboard
|
||||
@@ -405,11 +403,11 @@ virtual class keyboard_device(devfs_file):
|
||||
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
|
||||
return 0
|
||||
|
||||
kbd_file: keyboard_device
|
||||
kbd_file: keyboard_device* = keyboard_device()
|
||||
|
||||
def devfs_register_keyboard() -> int:
|
||||
global kbd_file
|
||||
kbd_file = keyboard_device()
|
||||
kbd_file.__init__()
|
||||
keyboard.init()
|
||||
return devfs_create_file("/dev/input/keyboard", kbd_file, None)
|
||||
|
||||
@@ -441,10 +439,10 @@ virtual class mouse_device(devfs_file):
|
||||
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
|
||||
return 0
|
||||
|
||||
mse_file: mouse_device
|
||||
mse_file: mouse_device* = mouse_device()
|
||||
|
||||
def devfs_register_mouse() -> int:
|
||||
global mse_file
|
||||
mse_file = mouse_device()
|
||||
mse_file.__init__()
|
||||
mouse.init()
|
||||
return devfs_create_file("/dev/input/mouse", mse_file, None)
|
||||
@@ -10,7 +10,7 @@ def cmos_read(reg: uint8) -> uint8:
|
||||
return asm.inb(rtc_cmos_data)
|
||||
|
||||
def bcd_to_bin(bcd: uint8) -> uint8:
|
||||
return (bcd >> 4) * 10 + (bcd & 0x0F)
|
||||
return uint8((bcd >> 4) * 10 + (bcd & 0x0F))
|
||||
|
||||
def get_rtc_time() -> uint32:
|
||||
while cmos_read(0x0A) & 0x80: pass
|
||||
@@ -28,17 +28,17 @@ def get_rtc_time() -> uint32:
|
||||
day = bcd_to_bin(day)
|
||||
mon = bcd_to_bin(mon)
|
||||
year = bcd_to_bin(year)
|
||||
fat_year: uint16 = uint16(year) + 2000 - 1980
|
||||
fat_year: uint16 = uint16(uint16(year) + 2000 - 1980)
|
||||
if fat_year > 127: fat_year = 127
|
||||
fat_date: uint16 = (fat_year << 9) | (uint16(mon) << 5) | uint16(day)
|
||||
fat_time: uint16 = (uint16(hour) << 11) | (uint16(min_) << 5) | (uint16(sec) / 2)
|
||||
fat_date: uint16 = uint16((fat_year << 9) | (uint16(mon) << 5) | uint16(day))
|
||||
fat_time: uint16 = uint16((uint16(hour) << 11) | (uint16(min_) << 5) | (uint16(sec) / 2))
|
||||
return (uint32(fat_date) << 16) | uint32(fat_time)
|
||||
|
||||
def get_fattime() -> uint32:
|
||||
return get_rtc_time()
|
||||
|
||||
def to_year(ft: uint32) -> uint16:
|
||||
return uint16((ft >> 25) & 0x7F) + 1980
|
||||
return uint16(uint16((ft >> 25) & 0x7F) + 1980)
|
||||
|
||||
def to_month(ft: uint32) -> uint8:
|
||||
return uint8((ft >> 21) & 0x0F)
|
||||
@@ -56,8 +56,8 @@ def to_second(ft: uint32) -> uint8:
|
||||
return uint8((ft & 0x1F) * 2)
|
||||
|
||||
def make(year: uint16, month: uint8, day: uint8, hour: uint8, minute: uint8, second: uint8) -> uint32:
|
||||
fat_year: uint16 = year - 1980
|
||||
fat_year: uint16 = uint16(year - 1980)
|
||||
if fat_year > 127: fat_year = 127
|
||||
fat_date: uint16 = (fat_year << 9) | (uint16(month) << 5) | uint16(day)
|
||||
fat_time: uint16 = (uint16(hour) << 11) | (uint16(minute) << 5) | (uint16(second) / 2)
|
||||
fat_date: uint16 = uint16((fat_year << 9) | (uint16(month) << 5) | uint16(day))
|
||||
fat_time: uint16 = uint16((uint16(hour) << 11) | (uint16(minute) << 5) | (uint16(second) / 2))
|
||||
return (uint32(fat_date) << 16) | uint32(fat_time)
|
||||
@@ -168,7 +168,7 @@ class lfn_entry:
|
||||
def sfn_checksum(name: const str) -> uint8:
|
||||
sum: uint8 = 0
|
||||
for i in range(11):
|
||||
sum = ((sum & 1) << 7) + (sum >> 1) + name[i]
|
||||
sum = uint8(((sum & 1) << 7) + (sum >> 1) + name[i])
|
||||
return sum
|
||||
|
||||
def uni2oem_placeholder(uni: uint16, cp: uint16) -> uint16:
|
||||
@@ -233,7 +233,7 @@ def sfn_from_lfn(lfn: const str, sfn: str):
|
||||
if ch == '.':
|
||||
dot_pos = si; si += 1; ext_i = 0; continue
|
||||
uc: char
|
||||
if ch >= 'a' and ch <= 'z': uc = ch - 32
|
||||
if ch >= 'a' and ch <= 'z': uc = char(ch - 32)
|
||||
elif ch == ' ': uc = '_'
|
||||
elif ch == '+' or ch == ',' or ch == ';' or ch == '=' or ch == '[' or ch == ']': uc = '_'
|
||||
else: uc = ch
|
||||
@@ -722,8 +722,8 @@ class volinfo:
|
||||
for i in range(11):
|
||||
a: char = self.win[entry_offset_in_sector + i]
|
||||
b: char = sfn[i]
|
||||
if a >= 'a' and a <= 'z': a = a - 32
|
||||
if b >= 'a' and b <= 'z': b = b - 32
|
||||
if a >= 'a' and a <= 'z': a = char(a - 32)
|
||||
if b >= 'a' and b <= 'z': b = char(b - 32)
|
||||
if a != b:
|
||||
match_found = 0
|
||||
break
|
||||
@@ -732,11 +732,11 @@ class volinfo:
|
||||
lfn_matched: int = 1
|
||||
li: int = 0
|
||||
for name_ch in name:
|
||||
lfn_ch: uint16 = *(uint16*(uint64(lfn_buf) + li * 2))
|
||||
lfn_low: uint16 = lfn_ch
|
||||
if lfn_low >= 65 and lfn_low <= 90: lfn_low = lfn_low + 32
|
||||
lfn_ch: uint16 = *(uint16*(uint64(lfn_buf) + li * 2))
|
||||
lfn_low: uint16 = uint16(lfn_ch)
|
||||
if lfn_low >= 65 and lfn_low <= 90: lfn_low = uint16(lfn_low + 32)
|
||||
n_low: uint16 = uint16(name_ch)
|
||||
if n_low >= 65 and n_low <= 90: n_low = n_low + 32
|
||||
if n_low >= 65 and n_low <= 90: n_low = uint16(n_low + 32)
|
||||
if lfn_low != n_low:
|
||||
lfn_matched = 0
|
||||
break
|
||||
|
||||
@@ -88,7 +88,7 @@ def read_scancode() -> uint8:
|
||||
return code
|
||||
|
||||
def scancode_to_ascii(scancode: uint8) -> char:
|
||||
code: uint8 = scancode & ~uint8(KEY_RELEASED)
|
||||
code: uint8 = uint8(scancode & ~uint8(KEY_RELEASED))
|
||||
if code >= 128: return '\0'
|
||||
shifted: bool = (shift_l or shift_r) != 0
|
||||
if caps_lock and code >= 0x10 and code <= 0x32:
|
||||
|
||||
@@ -64,7 +64,7 @@ def init() -> int:
|
||||
_ide_initialized = 1
|
||||
return IDError.IDE_ERR_NONE
|
||||
|
||||
def readSector(lba: uint32, buffer: t.CPtr) -> int:
|
||||
def readSector(lba: uint32, buffer: rawptr) -> int:
|
||||
if buffer is None: return IDError.IDE_ERR_BUFFER_NULL
|
||||
err: IDError = waitReady(IDE_baseport_PRIMARY)
|
||||
if err != IDError.IDE_ERR_NONE:
|
||||
@@ -84,8 +84,8 @@ def readSector(lba: uint32, buffer: t.CPtr) -> int:
|
||||
buf: uint16* = uint16*(buffer)
|
||||
for j in range(256):
|
||||
*buf = asm.inw(0x1F0)
|
||||
# buf 为字节指针(uint16|t.CPtr → i8*),每次按 u16 读写须前进 2 字节
|
||||
buf = buf + 2
|
||||
# buf 是 i16*(uint16*):+1 表示前进 1 个元素 = 2 字节,256 次恰好填满 512B
|
||||
buf = buf + 1
|
||||
first_byte: uint8 = *(uint8*(buffer))
|
||||
# viperlib.snprintf(c.Addr(dbg), 120, "[readSector] lba=%lu status=0x%02x first=%02x\n", lba, uint32(st2), uint32(first_byte))
|
||||
# serial.puts(dbg)
|
||||
@@ -108,14 +108,9 @@ def writeSector(lba: uint32, buffer: const rawptr) -> int:
|
||||
for j in range(256):
|
||||
val: uint16 = *buf
|
||||
asm.outw(0x1F0, val)
|
||||
# [待复核·指针缩放] 下面这行注释声称 "uint16|t.CPtr → i8*(字节指针),每次前进 2 字节",
|
||||
# 但 `X | t.CPtr` 的联合类型当前解析为 Ptr(X)(见联合类型解析与 includes/memhub.vp 中
|
||||
# `t.CUInt64T(x, t.CPtr)` 的既有用法)——若 `buf` 实际是 u16*,则 `buf + 2` 前进的是
|
||||
# 4 字节(GEP 按元素缩放),本循环 256 次会读满 1KB 而不是 512B,且越界读到缓冲区之后。
|
||||
# 结论待定(需一次 IR 取证:看 `buf + 2` 生成的是 getelementptr i16 还是 i8)。
|
||||
# 与按整数加法推进地址、不依赖指针元素类型的写法(同仓另有此类)对齐后再改;
|
||||
# `| t.CPtr` → `rawptr[T]` 迁移时一并复核,见 Debugger/rawptr-migration-and-fastfail.md。
|
||||
buf = buf + 2
|
||||
# buf 是 i16*(uint16*):+1 表示前进 1 个元素 = 2 字节,256 次恰好读完 512B
|
||||
# (IR 取证:`buf + 2` 生成 getelementptr ..., i16,按元素缩放 → +4 字节,越界)
|
||||
buf = buf + 1
|
||||
asm.outb(0x1F7, 0xE7)
|
||||
waitReady(IDE_baseport_PRIMARY)
|
||||
return IDError.IDE_ERR_NONE
|
||||
|
||||
@@ -20,13 +20,13 @@ class Vec3:
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
def Sub(self, b: Vec3) -> Vec3*:
|
||||
def Sub(self, b: Vec3) -> Vec3:
|
||||
return Vec3(self.x - b.x, self.y - b.y, self.z - b.z)
|
||||
def Cross(self, b: Vec3) -> Vec3*:
|
||||
def Cross(self, b: Vec3) -> Vec3:
|
||||
return Vec3(self.y * b.z - self.z * b.y, self.z * b.x - self.x * b.z, self.x * b.y - self.y * b.x)
|
||||
def Dot(self, b: Vec3) -> float:
|
||||
return self.x * b.x + self.y * b.y + self.z * b.z
|
||||
def Norm(self) -> Vec3*:
|
||||
def Norm(self) -> Vec3:
|
||||
l = math.sqrtf(self.Dot(self))
|
||||
return Vec3(self.x / l, self.y / l, self.z / l)
|
||||
|
||||
@@ -39,7 +39,7 @@ def Mat4_Identity() -> Mat4*:
|
||||
m.m[0][0] = 1; m.m[1][1] = 1; m.m[2][2] = 1; m.m[3][3] = 1
|
||||
return m
|
||||
|
||||
def Mat4_Mul(a: Mat4, b: Mat4) -> Mat4*:
|
||||
def Mat4_Mul(a: Mat4*, b: Mat4*) -> Mat4*:
|
||||
res: Mat4 = Mat4()
|
||||
string.memset(&res, 0, Mat4.__sizeof__())
|
||||
for i in range(4):
|
||||
@@ -48,7 +48,7 @@ def Mat4_Mul(a: Mat4, b: Mat4) -> Mat4*:
|
||||
res.m[i][j] += a.m[i][k] * b.m[k][j]
|
||||
return res
|
||||
|
||||
def Mat4_MulVec(m: Mat4, v: Vec3) -> Vec3*:
|
||||
def Mat4_MulVec(m: Mat4*, v: Vec3*) -> Vec3:
|
||||
x: float = m.m[0][0] * v.x + m.m[0][1] * v.y + m.m[0][2] * v.z + m.m[0][3]
|
||||
y: float = m.m[1][0] * v.x + m.m[1][1] * v.y + m.m[1][2] * v.z + m.m[1][3]
|
||||
z: float = m.m[2][0] * v.x + m.m[2][1] * v.y + m.m[2][2] * v.z + m.m[2][3]
|
||||
@@ -65,7 +65,7 @@ def Mat4_Perspective(fov: float, aspect: float, zn: float, zf: float) -> Mat4*:
|
||||
m.m[2][2] = zf / (zn - zf); m.m[2][3] = (zf * zn) / (zn - zf); m.m[3][2] = -1
|
||||
return m
|
||||
|
||||
def Mat4_LookAt(eye: Vec3, target: Vec3, up: Vec3) -> Mat4*:
|
||||
def Mat4_LookAt(eye: Vec3, target: Vec3, up: Vec3) -> Mat4:
|
||||
zaxis: Vec3 = eye.Sub(target).Norm()
|
||||
xaxis: Vec3 = up.Cross(zaxis).Norm()
|
||||
yaxis: Vec3 = zaxis.Cross(xaxis)
|
||||
@@ -76,7 +76,7 @@ def Mat4_LookAt(eye: Vec3, target: Vec3, up: Vec3) -> Mat4*:
|
||||
m.m[3][3] = 1
|
||||
return m
|
||||
|
||||
def Mat4_Translate(x: float, y: float, z: float) -> Mat4*:
|
||||
def Mat4_Translate(x: float, y: float, z: float) -> Mat4:
|
||||
m: Mat4 = Mat4_Identity()
|
||||
m.m[0][3] = x; m.m[1][3] = y; m.m[2][3] = z
|
||||
return m
|
||||
@@ -132,7 +132,7 @@ class Renderer:
|
||||
if e2 > -dy: err -= dy; x0 += sx
|
||||
if e2 < dx: err += dx; y0 += sy
|
||||
|
||||
def DrawTriangle(self, v0: Vec3, v1: Vec3, v2: Vec3, col: uint32):
|
||||
def DrawTriangle(self, v0: Vec3*, v1: Vec3*, v2: Vec3*, col: uint32):
|
||||
if v0.z < float(0.0) or v1.z < float(0.0) or v2.z < float(0.0): return
|
||||
if (v0.x > float(10.0) or v0.x < float(-10.0) or v0.y > float(10.0) or v0.y < float(-10.0) or
|
||||
v1.x > float(10.0) or v1.x < float(-10.0) or v1.y > float(10.0) or v1.y < float(-10.0) or
|
||||
@@ -259,7 +259,7 @@ class Scene3D:
|
||||
Vec3(-1, -1, -1), Vec3(-1, -1, 1), Vec3(-1, 1, -1), Vec3(-1, 1, 1),
|
||||
Vec3( 1, -1, -1), Vec3( 1, -1, 1), Vec3( 1, 1, -1), Vec3( 1, 1, 1)
|
||||
]
|
||||
for i in range(8): v[i] = *Mat4_MulVec(mvp, &v[i])
|
||||
for i in range(8): v[i] = Mat4_MulVec(mvp, &v[i])
|
||||
faces: t.CArray[t.CArray[int, 3], 12] = [
|
||||
[0, 2, 1], [1, 2, 3], [4, 1, 5], [4, 0, 1], [6, 3, 2], [6, 7, 3],
|
||||
[4, 6, 0], [0, 6, 2], [5, 7, 4], [4, 7, 6], [1, 3, 5], [5, 3, 7]
|
||||
@@ -277,7 +277,7 @@ class Scene3D:
|
||||
v[1] = Vec3(center.x+radius*math.sinf(theta1)*math.cosf(phi2), center.y+radius*math.cosf(theta1), center.z+radius*math.sinf(theta1)*math.sinf(phi2))
|
||||
v[2] = Vec3(center.x+radius*math.sinf(theta2)*math.cosf(phi1), center.y+radius*math.cosf(theta2), center.z+radius*math.sinf(theta2)*math.sinf(phi1))
|
||||
v[3] = Vec3(center.x+radius*math.sinf(theta2)*math.cosf(phi2), center.y+radius*math.cosf(theta2), center.z+radius*math.sinf(theta2)*math.sinf(phi2))
|
||||
for k in range(4): v[k] = *Mat4_MulVec(mvp, &v[k])
|
||||
for k in range(4): v[k] = Mat4_MulVec(mvp, &v[k])
|
||||
self.renderer.DrawTriangle(&v[0], &v[1], &v[2], col)
|
||||
self.renderer.DrawTriangle(&v[1], &v[3], &v[2], col)
|
||||
|
||||
|
||||
@@ -368,12 +368,12 @@ class _VGAScreenDriver:
|
||||
if x < 0 or x >= self.fw or y < 0 or y >= self.fh: return
|
||||
offset: int = y * self.fp + x * 4
|
||||
# 解析RGBA分量
|
||||
r: uchar = (color >> 16) & 0xFF
|
||||
g: uchar = (color >> 8) & 0xFF
|
||||
b: uchar = color & 0xFF
|
||||
a: uchar = (color >> 24) & 0xFF
|
||||
r: uchar = uchar((color >> 16) & 0xFF)
|
||||
g: uchar = uchar((color >> 8) & 0xFF)
|
||||
b: uchar = uchar((color >> 0) & 0xFF)
|
||||
a: uchar = uchar((color >> 24) & 0xFF)
|
||||
# 根据硬件格式写入像素
|
||||
match self.ColorFormat:
|
||||
switch self.ColorFormat:
|
||||
case __ColorFormat.ColorFormat_BGRA:
|
||||
self.fb[offset + 0] = b
|
||||
fb[offset + 1] = g
|
||||
@@ -392,7 +392,7 @@ class _VGAScreenDriver:
|
||||
fb[offset + 0] = r
|
||||
fb[offset + 1] = g
|
||||
fb[offset + 2] = b
|
||||
case _:
|
||||
default:
|
||||
# 降级到BGRA
|
||||
fb[offset + 0] = b
|
||||
fb[offset + 1] = g
|
||||
@@ -407,10 +407,10 @@ class _VGAScreenDriver:
|
||||
PixelSize: int = 3 if self.ColorFormat == __ColorFormat.ColorFormat_BGR or self.ColorFormat == __ColorFormat.ColorFormat_RGB else 4
|
||||
RowSize: int = self.fw * PixelSize
|
||||
# 解析清除颜色的RGBA分量
|
||||
r: uchar = (color >> 16) & 0xFF
|
||||
g: uchar = (color >> 8 ) & 0xFF
|
||||
b: uchar = (color) & 0xFF
|
||||
a: uchar = (color >> 24) & 0xFF
|
||||
r: uchar = uchar((color >> 16) & 0xFF)
|
||||
g: uchar = uchar((color >> 8) & 0xFF)
|
||||
b: uchar = uchar((color >> 0) & 0xFF)
|
||||
a: uchar = uchar((color >> 24) & 0xFF)
|
||||
# 逐行填充,比逐像素调用SetPixel快得多
|
||||
for y in range(self.fh):
|
||||
row_ptr: uchar* = fb + y * fp
|
||||
@@ -450,7 +450,7 @@ class _VGAScreenDriver:
|
||||
ch: uchar = uchar(cr)
|
||||
if ch >= 128: ch = DEFAULT_CHAR
|
||||
# 预解析背景色Alpha,避免内层循环重复计算
|
||||
bg_alpha: uint8 = (bgcolor >> 24) & 0xFF
|
||||
bg_alpha: uint8 = uint8((bgcolor >> 24) & 0xFF)
|
||||
draw_bg: int = (bg_alpha != 0) # 背景是否需要绘制
|
||||
# 渲染8x16点阵字符
|
||||
for fy in range(FONT_HEIGHT):
|
||||
|
||||
+11
-11
@@ -119,23 +119,23 @@ def set_tss_rsp0(rsp0: uint64):
|
||||
|
||||
def setGate(num: int, base: uint64, limit: uint32, access: uint8, gran: uint8):
|
||||
global gdt
|
||||
gdt[num].limit_low = (limit & 0xFFFF)
|
||||
gdt[num].base_low = (base & 0xFFFF)
|
||||
gdt[num].base_middle = (base >> 16) & 0xFF
|
||||
gdt[num].base_high = (base >> 24) & 0xFF
|
||||
gdt[num].granularity = ((limit >> 16) & 0x0F) | (gran & 0xF0)
|
||||
gdt[num].access = access
|
||||
gdt[num].limit_low = uint16(limit & 0xFFFF)
|
||||
gdt[num].base_low = uint16(base & 0xFFFF)
|
||||
gdt[num].base_middle = uint8((base >> 16) & 0xFF)
|
||||
gdt[num].base_high = uint8((base >> 24) & 0xFF)
|
||||
gdt[num].granularity = uint8((limit >> 16) & 0x0F) | (gran & 0xF0)
|
||||
gdt[num].access = uint8(access)
|
||||
|
||||
def setTSS64(num: int, base: uint64, limit: uint32):
|
||||
global gdt
|
||||
# 64 位 TSS 描述符占 16 字节(GDT 两项),复用同一地址按 gdt_entry64 整体写入:
|
||||
# 前 8 字节为常规描述符字段,后 8 字节为 base[63:32] + 保留 0
|
||||
e: gdt_entry64* = gdt_entry64*(&gdt[num])
|
||||
e.limit_low = limit & 0xFFFF
|
||||
e.base_low = base & 0xFFFF
|
||||
e.base_middle = (base >> 16) & 0xFF
|
||||
e.limit_low = uint16(limit & 0xFFFF)
|
||||
e.base_low = uint16(base & 0xFFFF)
|
||||
e.base_middle = uint8((base >> 16) & 0xFF)
|
||||
e.access = 0x89
|
||||
e.granularity = (limit >> 16) & 0x0F
|
||||
e.base_high = (base >> 24) & 0xFF
|
||||
e.granularity = uint8((limit >> 16) & 0x0F)
|
||||
e.base_high = uint8((base >> 24) & 0xFF)
|
||||
e.base_upper = uint32(base >> 32)
|
||||
e.reserved = 0
|
||||
@@ -76,12 +76,12 @@ extern def isr_default()
|
||||
|
||||
def setGate(num: int, base: uint64, sel: uint16, flags: uint8):
|
||||
global idt
|
||||
idt[num].base_low = (base & 0xFFFF)
|
||||
idt[num].base_middle = (base >> 16) & 0xFFFF
|
||||
idt[num].base_high = (base >> 32) & 0xFFFFFFFF
|
||||
idt[num].selector = sel
|
||||
idt[num].base_low = uint16(base & 0xFFFF)
|
||||
idt[num].base_middle = uint16((base >> 16) & 0xFFFF)
|
||||
idt[num].base_high = uint32((base >> 32) & 0xFFFFFFFF)
|
||||
idt[num].selector = uint16(sel)
|
||||
idt[num].ist_attr = 0
|
||||
idt[num].type_attr = flags
|
||||
idt[num].type_attr = uint8(flags)
|
||||
idt[num].reserved1 = 0
|
||||
|
||||
def isrCommonhandler(interrupt: int):
|
||||
|
||||
+12
-8
@@ -28,7 +28,6 @@ import services.mouse as mse_svc
|
||||
import services.desktop as desktop
|
||||
import intr.syscall as syscall
|
||||
import execrunner.elf as elf
|
||||
import t, c
|
||||
import asm
|
||||
|
||||
|
||||
@@ -125,11 +124,11 @@ class ViperKernel:
|
||||
serial.puts("[main] kernel init done\n")
|
||||
|
||||
fb: rawptr = rawptr(BootInfo.framebuffer_addr)
|
||||
width: uint64 = BootInfo.framebuffer_width
|
||||
height: uint64 = BootInfo.framebuffer_height
|
||||
pitch: uint64 = BootInfo.framebuffer_pitch
|
||||
fb_format: uint64 = BootInfo.framebuffer_format
|
||||
fb_size: uint64 = BootInfo.framebuffer_size
|
||||
width: int = int(BootInfo.framebuffer_width)
|
||||
height: int = int(BootInfo.framebuffer_height)
|
||||
pitch: int = int(BootInfo.framebuffer_pitch)
|
||||
fb_format: int = int(BootInfo.framebuffer_format)
|
||||
fb_size: uint64 = BootInfo.framebuffer_size
|
||||
# [DBG] 打印 BootInfo 指针与 memmap 原始字段,定位全 0 根因(用后移除)
|
||||
_dbbuf: [140]char
|
||||
viperlib.snprintf(&_dbbuf, 140, "[main] BootInfo=0x%lx mmap=0x%lx mmsz=%lu mmd=%lu fb=0x%lx\n",
|
||||
@@ -147,13 +146,19 @@ class ViperKernel:
|
||||
serial.puts(&_dbraw)
|
||||
serial.puts("\n[DB] dump end\n")
|
||||
|
||||
# 内核镜像末端(含 .bss;__bss_end 见 VKernel/linker.ld):传给 mm.init 使其在挑选
|
||||
# 堆 arena 时排除整块内核镜像 —— .bss 不占文件大小,bootloader 只按文件大小预留页,
|
||||
# 否则 .bss 尾部(ticks/_perf_* 等全局量)会落在 memmap 空闲区里被堆占用。
|
||||
_kern_end: uint64 = 0
|
||||
__asm__(f"lea {asmout(_kern_end, ASM_DESCR.OUTPUT_REG)}, [rip + __bss_end]",
|
||||
op=[ASM_DESCR.CLOBBER_MEMORY])
|
||||
if BootInfo is not None:
|
||||
paging.init(BootInfo.MemmapAddr, BootInfo.MemmapSize)
|
||||
fb_pages: uint64 = (fb_size + uint64(0xFFF)) >> uint64(12)
|
||||
for fpi in range(fb_pages):
|
||||
fva: uint64 = uint64(fb) + fpi * uint64(0x1000)
|
||||
paging.MapPage(fva, fva, paging.PTE_WRITABLE | paging.PTE_PCD)
|
||||
mm.init(BootInfo.MemmapAddr, BootInfo.MemmapSize, BootInfo.MemmapDescSize, BootInfo.framebuffer_addr, fb_size)
|
||||
mm.init(BootInfo.MemmapAddr, BootInfo.MemmapSize, BootInfo.MemmapDescSize, BootInfo.framebuffer_addr, fb_size, BootInfo.kernel_PhysAddr, _kern_end)
|
||||
pt_pool_buf: rawptr = mm.malloc(uint64(513) * uint64(4096))
|
||||
paging.init_pool(pt_pool_buf, uint64(513) * uint64(4096))
|
||||
else:
|
||||
@@ -354,4 +359,3 @@ def _start() -> int:
|
||||
asm.hlt()
|
||||
sched.Scheduler._yield()
|
||||
return 0
|
||||
|
||||
+19
-5
@@ -117,7 +117,7 @@ class _BuddySystemObject:
|
||||
block: memory_block* = memory_block*(cur_addr)
|
||||
block.size = block_size
|
||||
block.state = BLOCK_FREE
|
||||
block.order = order
|
||||
block.order = uint8(order)
|
||||
block.next = None
|
||||
block.prev = None
|
||||
if order <= MAX_ORDER:
|
||||
@@ -139,12 +139,12 @@ class _BuddySystemObject:
|
||||
new_block: memory_block* = memory_block*(uint64(block) + new_block_size)
|
||||
new_block.size = new_block_size
|
||||
new_block.state = BLOCK_FREE
|
||||
new_block.order = current_order
|
||||
new_block.order = uint8(current_order)
|
||||
new_block.next = None
|
||||
new_block.prev = None
|
||||
# 更新原块大小和阶数
|
||||
block.size = new_block_size
|
||||
block.order = current_order
|
||||
block.order = uint8(current_order)
|
||||
# 将新块添加到对应阶数的空闲链表
|
||||
if current_order <= MAX_ORDER:
|
||||
new_block.next = self.buddy.free_lists[current_order]
|
||||
@@ -175,7 +175,7 @@ class _BuddySystemObject:
|
||||
# 合并块
|
||||
merged_block: memory_block* = block if block < buddy else buddy
|
||||
merged_block.size = get_block_size(order + 1)
|
||||
merged_block.order = order + 1
|
||||
merged_block.order = uint8(order + 1)
|
||||
block = merged_block
|
||||
order += 1
|
||||
return block
|
||||
@@ -448,7 +448,7 @@ def free_memory_regions():
|
||||
memory_regions = None
|
||||
|
||||
# 初始化内存管理系统
|
||||
def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr: uint64 = 0, FbSize: uint64 = 0):
|
||||
def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr: uint64 = 0, FbSize: uint64 = 0, KernelAddr: uint64 = 0, KernelEnd: uint64 = 0):
|
||||
global BuddySystemObject
|
||||
start_addr: rawptr = None
|
||||
size: uint64 = 0
|
||||
@@ -476,6 +476,20 @@ def init(MemmapAddr: uint64, MemmapSize: uint64, MemmapDescSize: uint64, FbAddr:
|
||||
fb_end: uint64 = FbAddr + FbSize
|
||||
if start < fb_end and end > FbAddr:
|
||||
continue
|
||||
# 排除内核镜像区([KernelAddr, KernelEnd),含 .bss):bootloader 只按
|
||||
# 文件大小预留页,.bss 不占文件 → 其尾部留在 memmap 的 EfiConventionalMemory
|
||||
# 里。若不排除,堆 arena 会用这段内存写 memory_block 头/用户数据,与内核
|
||||
# 全局量(ticks/_perf_* 等)互相破坏,并进一步搞乱堆元数据。
|
||||
# 内核镜像位于常规内存低端,故把与该区间重叠的 region 起点抬到镜像末端,
|
||||
# 而不是整段丢弃(整段丢弃会连带弃掉镜像之上的一大片可用内存)。
|
||||
if KernelEnd > KernelAddr:
|
||||
if end <= KernelEnd:
|
||||
continue
|
||||
if start < KernelEnd:
|
||||
start = KernelEnd
|
||||
region_size = end - start
|
||||
if end <= start:
|
||||
continue
|
||||
if etype == MEMORY_TYPE_AVAILABLE:
|
||||
if region_size > best_avail_size:
|
||||
best_avail_size = region_size
|
||||
|
||||
@@ -99,7 +99,7 @@ def setMask(irq: uint8):
|
||||
else:
|
||||
port = PIC2_DATA
|
||||
irq -= 8
|
||||
value = asm.inb(port) | (1 << irq)
|
||||
value = uint8(asm.inb(port) | (1 << irq))
|
||||
asm.outb(port, value)
|
||||
asm.io_wait() # 确保命令生效
|
||||
|
||||
@@ -114,6 +114,6 @@ def clearMask(irq: uint8):
|
||||
else:
|
||||
port = PIC2_DATA
|
||||
irq -= 8
|
||||
value = asm.inb(port) & ~(1 << irq)
|
||||
value = uint8(asm.inb(port) & ~(1 << irq))
|
||||
asm.outb(port, value)
|
||||
asm.io_wait() # 确保命令生效
|
||||
@@ -18,9 +18,9 @@ def pit_init(frequency: int):
|
||||
asm.io_wait()
|
||||
|
||||
# 写入低字节
|
||||
asm.outb(PIT_CHANNEL0, divisor & 0xFF)
|
||||
asm.outb(PIT_CHANNEL0, uint8(divisor & 0xFF))
|
||||
asm.io_wait()
|
||||
|
||||
# 写入高字节
|
||||
asm.outb(PIT_CHANNEL0, (divisor >> 8) & 0xFF)
|
||||
asm.outb(PIT_CHANNEL0, uint8((divisor >> 8) & 0xFF))
|
||||
asm.io_wait()
|
||||
@@ -2,7 +2,6 @@ import drivers.input.keyboard.keyboard as keyboard
|
||||
import drivers.usb.hid.usb_kbd as usb_kbd
|
||||
import drivers.serial.uart.serial as serial
|
||||
import sched.sched as sched
|
||||
import viperlib
|
||||
|
||||
|
||||
define SERVICE_KEYBOARD = 1
|
||||
@@ -17,8 +16,6 @@ class KeyboardService:
|
||||
self.running = 0
|
||||
self.usb_kbd_th = None
|
||||
|
||||
kbd_svc: KeyboardService
|
||||
|
||||
|
||||
def kbd_thread(arg: rawptr) -> int:
|
||||
serial.puts("[kbd_svc] started\n")
|
||||
@@ -39,9 +36,12 @@ def usb_kbd_thread(arg: rawptr) -> int:
|
||||
sched.Scheduler._yield()
|
||||
return 0
|
||||
|
||||
|
||||
kbd_svc: KeyboardService = KeyboardService()
|
||||
|
||||
def start() -> int:
|
||||
global kbd_svc
|
||||
kbd_svc = KeyboardService()
|
||||
kbd_svc.__init__()
|
||||
keyboard.init()
|
||||
serial.puts("[kbd_svc] PS/2 keyboard initialized, IRQ1 installed\n")
|
||||
usb_kbd.init()
|
||||
|
||||
@@ -26,6 +26,13 @@ SECTIONS {
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(COMMON)
|
||||
/* 强制本输出段为 PROGBITS 并占用文件空间:.bss 默认是 NOBITS(不占文件),
|
||||
于是 kernel.bin 的 FileSize 不包含 .bss。bootloader 只按文件大小预留物理页
|
||||
(PagesNeeded = KernelSize/4096),.bss 尾部(ticks/_perf_* 等全局量)便留在
|
||||
未预留的 EfiConventionalMemory 里,被 mm 的堆 arena 覆盖 → 破坏内核全局量、
|
||||
并反过来破坏堆元数据。加一条数据语句(LONG)即让整段 .bss 写入 kernel.bin。 */
|
||||
. = ALIGN(16);
|
||||
LONG(0);
|
||||
__bss_end = .;
|
||||
}
|
||||
|
||||
|
||||
+25
@@ -464,6 +464,31 @@ EFI_STATUS ExitBootServicesAndJumpToKernel(
|
||||
Print(L"Final FB: 0x%lx | %lux%lu | pitch %lu | format %lu\r\n",
|
||||
framebuffer_addr, framebuffer_width, framebuffer_height, framebuffer_pitch, framebuffer_format);
|
||||
|
||||
// ==========================
|
||||
// 预留内核栈区(BOOTLOADER_STACK_BOTTOM ~ BOOTLOADER_STACK_TOP)
|
||||
// ==========================
|
||||
// 跳转内核后此区是主线程栈,但它在 memmap 里默认仍是 EfiConventionalMemory。
|
||||
// 若不占位,内核 mm 堆可能把这段内存当空闲区分配 → 主线程栈被堆数据覆盖。
|
||||
// 必须在 GetMemoryMap 之前用 AllocatePages 显式占位(AllocateAddress +
|
||||
// EfiLoaderData),使其在捕获的 memmap 中标记为已用。
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS StackAddr = BOOTLOADER_STACK_BOTTOM;
|
||||
UINTN StackPages = (UINTN)((BOOTLOADER_STACK_TOP - BOOTLOADER_STACK_BOTTOM) / 0x1000ULL);
|
||||
EFI_STATUS StackStatus = SystemTable->BootServices->AllocatePages(
|
||||
AllocateAddress,
|
||||
EfiLoaderData,
|
||||
StackPages,
|
||||
&StackAddr
|
||||
);
|
||||
if (EFI_ERROR(StackStatus)) {
|
||||
Print(L"Warning: Reserve boot stack region (0x%lx-0x%lx) failed - %r\r\n",
|
||||
BOOTLOADER_STACK_BOTTOM, BOOTLOADER_STACK_TOP, StackStatus);
|
||||
} else {
|
||||
Print(L"Boot stack region reserved: 0x%lx-0x%lx (%lu pages)\r\n",
|
||||
BOOTLOADER_STACK_BOTTOM, BOOTLOADER_STACK_TOP, StackPages);
|
||||
}
|
||||
}
|
||||
|
||||
// ==========================
|
||||
// ExitBootServices 流程
|
||||
// ==========================
|
||||
|
||||
Reference in new issue
Block a user