根因: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__() 等。
141 lines
5.4 KiB
Plaintext
141 lines
5.4 KiB
Plaintext
import asm
|
||
import drivers.usb.pci as pci
|
||
|
||
|
||
enum IDError:
|
||
IDE_ERR_NONE, IDE_ERR_TIMEOUT, IDE_ERR_DEVICE_ERROR
|
||
IDE_ERR_DEVICE_BUSY, IDE_ERR_INVALID_PARAM, IDE_ERR_BUFFER_NULL
|
||
IDE_ERR_SECTOR_COUNT, IDE_ERR_DEVICE_NOT_READY, IDE_ERR_DEVICE_FAILURE
|
||
IDE_ERR_COMMAND_FAILED, IDE_ERR_INVALID_LBA
|
||
|
||
define IDE_baseport_PRIMARY = 0x1F0
|
||
define IDE_baseport_SECONDARY = 0x170
|
||
|
||
define IDE_STATUS_BSY = 0x80
|
||
define IDE_STATUS_DRDY = 0x40
|
||
define IDE_STATUS_DF = 0x20
|
||
define IDE_STATUS_DRQ = 0x08
|
||
define IDE_STATUS_ERR = 0x01
|
||
|
||
define SECTOR_SIZE = 512
|
||
|
||
_ide_initialized: int = 0
|
||
|
||
def waitReady(baseport: uint16) -> static IDError:
|
||
timeout: int = 100000
|
||
for _ in range(timeout, 0, -1):
|
||
status: uint8 = asm.inb(baseport + 7)
|
||
if status & IDE_STATUS_DF:
|
||
return IDError.IDE_ERR_DEVICE_FAILURE
|
||
if not status & IDE_STATUS_BSY and status & IDE_STATUS_DRDY:
|
||
return IDError.IDE_ERR_NONE
|
||
return IDError.IDE_ERR_TIMEOUT
|
||
|
||
def waitDataReady(baseport: uint16) -> static IDError:
|
||
timeout: int = 100000
|
||
for _ in range(timeout, 0, -1):
|
||
status: uint8 = asm.inb(baseport + 7)
|
||
if status & IDE_STATUS_ERR: return IDError.IDE_ERR_DEVICE_ERROR
|
||
if status & IDE_STATUS_DF: return IDError.IDE_ERR_DEVICE_FAILURE
|
||
if not status & IDE_STATUS_BSY and (status & IDE_STATUS_DRQ or status & IDE_STATUS_DRDY):
|
||
return IDError.IDE_ERR_NONE
|
||
return IDError.IDE_ERR_TIMEOUT
|
||
|
||
def init() -> int:
|
||
global _ide_initialized
|
||
if _ide_initialized: return IDError.IDE_ERR_NONE
|
||
bus: uint8
|
||
dev_n: uint8
|
||
func: uint8
|
||
for bus in range(2):
|
||
for dev_n in range(32):
|
||
for func in range(8):
|
||
vendor: uint16 = pci.pci_read16(bus, dev_n, func, 0x00)
|
||
if vendor == 0xFFFF: continue
|
||
cls: uint32 = pci.pci_get_class(bus, dev_n, func)
|
||
if cls == 0x010180 or cls == 0x0101:
|
||
cmd: uint16 = pci.pci_read16(bus, dev_n, func, 0x04)
|
||
pci.pci_write32(bus, dev_n, func, 0x04, uint32(cmd | 0x0007))
|
||
asm.outb(0x3F6, 0x04)
|
||
for _ in range(10000): asm.nop()
|
||
asm.outb(0x3F6, 0x00)
|
||
for _ in range(10000): asm.nop()
|
||
status: uint8 = asm.inb(0x1F7)
|
||
_ide_initialized = 1
|
||
return IDError.IDE_ERR_NONE
|
||
|
||
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:
|
||
return err
|
||
asm.outb(0x3F6, 0x00)
|
||
asm.outb(0x1F2, 1)
|
||
asm.outb(0x1F3, uint8(lba & 0xFF))
|
||
asm.outb(0x1F4, uint8((lba >> 8) & 0xFF))
|
||
asm.outb(0x1F5, uint8((lba >> 16) & 0xFF))
|
||
asm.outb(0x1F6, uint8(0xE0 | ((lba >> 24) & 0x0F)))
|
||
asm.outb(0x1F7, 0x20)
|
||
err = waitDataReady(IDE_baseport_PRIMARY)
|
||
if err != IDError.IDE_ERR_NONE:
|
||
st: uint8 = asm.inb(0x1F7)
|
||
return err
|
||
st2: uint8 = asm.inb(0x1F7)
|
||
buf: uint16* = uint16*(buffer)
|
||
for j in range(256):
|
||
*buf = asm.inw(0x1F0)
|
||
# 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)
|
||
return IDError.IDE_ERR_NONE
|
||
|
||
def writeSector(lba: uint32, buffer: const rawptr) -> int:
|
||
if buffer is None: return IDError.IDE_ERR_BUFFER_NULL
|
||
err: IDError = waitReady(IDE_baseport_PRIMARY)
|
||
if err != IDError.IDE_ERR_NONE: return err
|
||
asm.outb(0x3F6, 0x00)
|
||
asm.outb(0x1F2, 1)
|
||
asm.outb(0x1F3, uint8(lba & 0xFF))
|
||
asm.outb(0x1F4, uint8((lba >> 8) & 0xFF))
|
||
asm.outb(0x1F5, uint8((lba >> 16) & 0xFF))
|
||
asm.outb(0x1F6, uint8(0xE0 | ((lba >> 24) & 0x0F)))
|
||
asm.outb(0x1F7, 0x30)
|
||
err = waitDataReady(IDE_baseport_PRIMARY)
|
||
if err != IDError.IDE_ERR_NONE: return err
|
||
buf: uint16* = uint16*(buffer)
|
||
for j in range(256):
|
||
val: uint16 = *buf
|
||
asm.outw(0x1F0, val)
|
||
# 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
|
||
|
||
def getDiskSize() -> uint64:
|
||
err: IDError = waitReady(IDE_baseport_PRIMARY)
|
||
if err != IDError.IDE_ERR_NONE: return 0
|
||
asm.outb(0x1F6, 0xE0)
|
||
asm.outb(0x1F7, 0xEC)
|
||
err = waitDataReady(IDE_baseport_PRIMARY)
|
||
if err != IDError.IDE_ERR_NONE: return 0
|
||
status: uint8 = asm.inb(0x1F7)
|
||
if not status & IDE_STATUS_DRDY: return 0
|
||
if status & IDE_STATUS_ERR: return 0
|
||
identify_data: t.CArray[uint16, 256]
|
||
for i in range(256):
|
||
identify_data[i] = asm.inw(0x1F0)
|
||
totalSectors: uint64 = identify_data[60] | uint64(identify_data[61]) << 16
|
||
if identify_data[83] & (1 << 10):
|
||
lba48_sectors: uint64 = (
|
||
uint64(identify_data[100]) |
|
||
uint64(identify_data[101]) << 16 |
|
||
uint64(identify_data[102]) << 32 |
|
||
uint64(identify_data[103]) << 48)
|
||
if lba48_sectors > totalSectors:
|
||
totalSectors = lba48_sectors
|
||
return totalSectors
|