fix(vkernel): schedule_int_transfer 的 toggle 形参改为值传递
schedule_int_transfer 第 6 形参原为 toggle_ptr: uint8*,却直接转发给 _td_set_token 的值形参 toggle: uint8,命中指针隐式转整数禁令(uhci.vp:160 CastError)。改为 toggle: uint8 值传递,四个调用点去掉取地址,buf 仍以 & 传。同时纳入工作区既有的指针语法迁移:t.CPtr 改 X*、c.Addr 改 &、c.Set(c.Deref(...)) 改 *p = v。
This commit is contained in:
1 parent
2a54e2bafb
commit
5f5a119f06
28 files changed
+2360
-2978
No files matched your search
@@ -9,56 +9,56 @@ import viperlib
|
||||
import t, c
|
||||
|
||||
|
||||
IA32_APIC_BASE: t.CDefine = 0x1B
|
||||
APIC_BASE_MSR_ENABLE: t.CDefine = 0x800
|
||||
APIC_BASE_ADDR_MASK: t.CDefine = 0xFFFFF000
|
||||
define IA32_APIC_BASE = 0x1B
|
||||
define APIC_BASE_MSR_ENABLE = 0x800
|
||||
define APIC_BASE_ADDR_MASK = 0xFFFFF000
|
||||
|
||||
LAPIC_ID: t.CDefine = 0x020
|
||||
LAPIC_VERSION: t.CDefine = 0x030
|
||||
LAPIC_TPR: t.CDefine = 0x080
|
||||
LAPIC_EOI: t.CDefine = 0x0B0
|
||||
LAPIC_LDR: t.CDefine = 0x0D0
|
||||
LAPIC_SVR: t.CDefine = 0x0F0
|
||||
LAPIC_ISR0: t.CDefine = 0x100
|
||||
LAPIC_ICR_LOW: t.CDefine = 0x300
|
||||
LAPIC_ICR_HIGH: t.CDefine = 0x310
|
||||
LAPIC_LVT_TIMER: t.CDefine = 0x320
|
||||
LAPIC_LVT_LINT0: t.CDefine = 0x350
|
||||
LAPIC_LVT_LINT1: t.CDefine = 0x360
|
||||
LAPIC_LVT_ERROR: t.CDefine = 0x370
|
||||
LAPIC_TIMER_INIT: t.CDefine = 0x380
|
||||
LAPIC_TIMER_CURRENT: t.CDefine = 0x390
|
||||
LAPIC_TIMER_DIVIDE: t.CDefine = 0x3E0
|
||||
define LAPIC_ID = 0x020
|
||||
define LAPIC_VERSION = 0x030
|
||||
define LAPIC_TPR = 0x080
|
||||
define LAPIC_EOI = 0x0B0
|
||||
define LAPIC_LDR = 0x0D0
|
||||
define LAPIC_SVR = 0x0F0
|
||||
define LAPIC_ISR0 = 0x100
|
||||
define LAPIC_ICR_LOW = 0x300
|
||||
define LAPIC_ICR_HIGH = 0x310
|
||||
define LAPIC_LVT_TIMER = 0x320
|
||||
define LAPIC_LVT_LINT0 = 0x350
|
||||
define LAPIC_LVT_LINT1 = 0x360
|
||||
define LAPIC_LVT_ERROR = 0x370
|
||||
define LAPIC_TIMER_INIT = 0x380
|
||||
define LAPIC_TIMER_CURRENT = 0x390
|
||||
define LAPIC_TIMER_DIVIDE = 0x3E0
|
||||
|
||||
LAPIC_SVR_ENABLE: t.CDefine = 0x100
|
||||
LAPIC_LVT_MASKED: t.CDefine = 0x10000
|
||||
LAPIC_LVT_DELIVERY_EXTINT: t.CDefine = 0x700
|
||||
LAPIC_LVT_DELIVERY_NMI: t.CDefine = 0x400
|
||||
LAPIC_LVT_TIMER_PERIODIC: t.CDefine = 0x20000
|
||||
define LAPIC_SVR_ENABLE = 0x100
|
||||
define LAPIC_LVT_MASKED = 0x10000
|
||||
define LAPIC_LVT_DELIVERY_EXTINT = 0x700
|
||||
define LAPIC_LVT_DELIVERY_NMI = 0x400
|
||||
define LAPIC_LVT_TIMER_PERIODIC = 0x20000
|
||||
|
||||
LAPIC_ICR_INIT: t.CDefine = 0x500
|
||||
LAPIC_ICR_STARTUP: t.CDefine = 0x600
|
||||
LAPIC_ICR_ASSERT: t.CDefine = 0x4000
|
||||
LAPIC_ICR_DEASSERT: t.CDefine = 0x8000
|
||||
LAPIC_ICR_LEVEL: t.CDefine = 0x8000
|
||||
define LAPIC_ICR_INIT = 0x500
|
||||
define LAPIC_ICR_STARTUP = 0x600
|
||||
define LAPIC_ICR_ASSERT = 0x4000
|
||||
define LAPIC_ICR_DEASSERT = 0x8000
|
||||
define LAPIC_ICR_LEVEL = 0x8000
|
||||
|
||||
MAX_CPUS: t.CDefine = 8
|
||||
AP_TRAMPOLINE_ADDR: t.CDefine = 0x7000
|
||||
# trampoline 机器码字节数(与下方 _trampoline_bin 初始化列表元素数一致)
|
||||
AP_TRAMPOLINE_LEN: t.CDefine = 138
|
||||
define MAX_CPUS = 8
|
||||
define AP_TRAMPOLINE_ADDR = 0x7000
|
||||
# trampoline 机器码字节数
|
||||
define AP_TRAMPOLINE_LEN = 138
|
||||
|
||||
_lapic_base: uint64 = 0
|
||||
_cpu_count: uint32 = 1
|
||||
_lapic_base: uint64 = 0
|
||||
_cpu_count: uint32 = 1
|
||||
_bsp_lapic_id: uint32 = 0
|
||||
_ap_ready: uint32 = 0
|
||||
_ap_ready: uint32 = 0
|
||||
|
||||
def read(offset: uint32) -> uint32:
|
||||
addr: uint64 = _lapic_base + uint64(offset)
|
||||
return c.Deref(uint32(addr, t.CPtr))
|
||||
return *(uint32*(addr))
|
||||
|
||||
def write(offset: uint32, value: uint32):
|
||||
addr: uint64 = _lapic_base + uint64(offset)
|
||||
c.Set(c.Deref(uint32(addr, t.CPtr)), value)
|
||||
*(uint32*(addr)) = value
|
||||
|
||||
def eoi():
|
||||
write(LAPIC_EOI, 0)
|
||||
@@ -86,16 +86,16 @@ def init():
|
||||
@c.Attribute(t.attr.noinline)
|
||||
def detect_cpu_count() -> uint32:
|
||||
res: cpu.cpuid_result
|
||||
cpu.cpuid(0, c.Addr(res))
|
||||
cpu.cpuid(0, &res)
|
||||
max_leaf: uint32 = res.eax
|
||||
|
||||
if max_leaf >= 0x0B:
|
||||
cpu.cpuid_sub(0x0B, 0, c.Addr(res))
|
||||
cpu.cpuid_sub(0x0B, 0, &res)
|
||||
num_threads: uint32 = res.ebx & 0xFFFF
|
||||
if num_threads > 0 and num_threads <= MAX_CPUS:
|
||||
return num_threads
|
||||
|
||||
cpu.cpuid(1, c.Addr(res))
|
||||
cpu.cpuid(1, &res)
|
||||
if res.edx & cpu.CPU_FEATURE_HTT:
|
||||
count: uint32 = (res.ebx >> 16) & 0xFF
|
||||
if count > 0 and count <= MAX_CPUS:
|
||||
@@ -127,7 +127,7 @@ def ap_entry():
|
||||
asm.sti()
|
||||
asm.hlt()
|
||||
|
||||
_trampoline_bin: t.CArray[uint8, AP_TRAMPOLINE_LEN] = [
|
||||
_trampoline_bin: [AP_TRAMPOLINE_LEN]uint8 = [
|
||||
0xFA, # cli
|
||||
0x31, 0xC0, # xor ax, ax
|
||||
0x8E, 0xD8, # mov ds, ax
|
||||
@@ -152,8 +152,8 @@ _trampoline_bin: t.CArray[uint8, AP_TRAMPOLINE_LEN] = [
|
||||
0x0F, 0x22, 0xD8, # mov cr3, eax
|
||||
0xB9, 0x80, 0x00, 0x00, 0xC0, # mov ecx, 0xC0000080 (EFER)
|
||||
0x0F, 0x32, # rdmsr
|
||||
# 0x83 C8 只能编码 1 字节立即数;0x100 须用 0x81 C8 imm32(6 字节)。
|
||||
# 原写 0x83 会把后 4 字节 00 01 00 00 当作下一条指令执行(N7)。
|
||||
# 0x83 C8 只能编码 1 字节立即数;0x100 须用 0x81 C8 imm32(6 字节)。
|
||||
# 原写 0x83 会把后 4 字节 00 01 00 00 当作下一条指令执行(N7)。
|
||||
0x81, 0xC8, 0x00, 0x01, 0x00, 0x00, # or eax, 0x100 (LME)
|
||||
0x0F, 0x79, # wrmsr
|
||||
0x0F, 0x20, 0xC0, # mov eax, cr0
|
||||
@@ -176,39 +176,38 @@ _trampoline_bin: t.CArray[uint8, AP_TRAMPOLINE_LEN] = [
|
||||
]
|
||||
|
||||
def _setup_trampoline(entry_addr: uint64, stack_addr: uint64, cr3_val: uint64):
|
||||
dest: uint8 | t.CPtr = uint8(AP_TRAMPOLINE_ADDR, t.CPtr)
|
||||
src: uint8 | t.CPtr = c.Addr(_trampoline_bin)
|
||||
i: int
|
||||
dest: uint8* = uint8*(AP_TRAMPOLINE_ADDR)
|
||||
src: uint8* = &_trampoline_bin
|
||||
for i in range(AP_TRAMPOLINE_LEN):
|
||||
c.Set(c.Deref(dest + uint64(i)), c.Deref(src + uint64(i)))
|
||||
*(dest + uint64(i)) = *(src + uint64(i))
|
||||
|
||||
gdt_ptr_addr: uint64 = AP_TRAMPOLINE_ADDR + 0x0E00
|
||||
c.Set(c.Deref(uint16(gdt_ptr_addr, t.CPtr)), uint16(23))
|
||||
c.Set(c.Deref(uint64(gdt_ptr_addr + 2, t.CPtr)), uint64(AP_TRAMPOLINE_ADDR + 0x0E10))
|
||||
*(uint16*(gdt_ptr_addr)) = uint16(23)
|
||||
*(uint64*(gdt_ptr_addr + 2)) = uint64(AP_TRAMPOLINE_ADDR + 0x0E10)
|
||||
|
||||
gdt_addr: uint64 = AP_TRAMPOLINE_ADDR + 0x0E10
|
||||
c.Set(c.Deref(uint64(gdt_addr, t.CPtr)), uint64(0))
|
||||
c.Set(c.Deref(uint64(gdt_addr + 8, t.CPtr)), uint64(0x00AF9A000000FFFF))
|
||||
c.Set(c.Deref(uint64(gdt_addr + 16, t.CPtr)), uint64(0x00CF92000000FFFF))
|
||||
*(uint64*(gdt_addr + 0)) = uint64(0)
|
||||
*(uint64*(gdt_addr + 8)) = uint64(0x00AF9A000000FFFF)
|
||||
*(uint64*(gdt_addr + 16)) = uint64(0x00CF92000000FFFF)
|
||||
|
||||
c.Set(c.Deref(uint32(AP_TRAMPOLINE_ADDR + 0x0F00, t.CPtr)), uint32(cr3_val))
|
||||
c.Set(c.Deref(uint64(AP_TRAMPOLINE_ADDR + 0x0F08, t.CPtr)), stack_addr)
|
||||
*(uint32*(AP_TRAMPOLINE_ADDR + 0x0F00)) = uint32(cr3_val)
|
||||
*(uint64*(AP_TRAMPOLINE_ADDR + 0x0F08)) = stack_addr
|
||||
|
||||
gp_addr: uint64 = uint64(c.Addr(gdt.gp))
|
||||
gdt_base: uint64 = c.Deref(uint64(gp_addr + 2, t.CPtr))
|
||||
gdt_limit: uint16 = c.Deref(uint16(gp_addr, t.CPtr))
|
||||
c.Set(c.Deref(uint16(AP_TRAMPOLINE_ADDR + 0x0F10, t.CPtr)), gdt_limit)
|
||||
c.Set(c.Deref(uint64(AP_TRAMPOLINE_ADDR + 0x0F12, t.CPtr)), gdt_base)
|
||||
gp_addr: uint64 = uint64(&gdt.gp)
|
||||
gdt_base: uint64 = *(uint64*(gp_addr + 2))
|
||||
gdt_limit: uint16 = *(uint16*(gp_addr))
|
||||
*(uint16*(AP_TRAMPOLINE_ADDR + 0x0F10)) = gdt_limit
|
||||
*(uint64*(AP_TRAMPOLINE_ADDR + 0x0F12)) = gdt_base
|
||||
|
||||
idt_addr: uint64 = uint64(c.Addr(idt.idt))
|
||||
idt_base: uint64 = c.Deref(uint64(idt_addr + 2, t.CPtr))
|
||||
idt_limit: uint16 = c.Deref(uint16(idt_addr, t.CPtr))
|
||||
c.Set(c.Deref(uint16(AP_TRAMPOLINE_ADDR + 0x0F20, t.CPtr)), idt_limit)
|
||||
c.Set(c.Deref(uint64(AP_TRAMPOLINE_ADDR + 0x0F22, t.CPtr)), idt_base)
|
||||
idt_addr: uint64 = uint64(&idt.idt)
|
||||
idt_base: uint64 = *(uint64*(idt_addr + 2))
|
||||
idt_limit: uint16 = *(uint16*(idt_addr))
|
||||
*(uint16*(AP_TRAMPOLINE_ADDR + 0x0F20)) = idt_limit
|
||||
*(uint64*(AP_TRAMPOLINE_ADDR + 0x0F22)) = idt_base
|
||||
|
||||
# entry 槽位后移到 0x0F30:idt 伪描述符占 0x0F20..0x0F29(limit 2 + base 8),
|
||||
# 原来 entry 放 0x0F28 会与其 base 尾部 2 字节重叠 → lidt 读到被覆盖的基址。
|
||||
c.Set(c.Deref(uint64(AP_TRAMPOLINE_ADDR + 0x0F30, t.CPtr)), entry_addr)
|
||||
# entry 槽位后移到 0x0F30:idt 伪描述符占 0x0F20..0x0F29(limit 2 + base 8),
|
||||
# 原来 entry 放 0x0F28 会与其 base 尾部 2 字节重叠 → lidt 读到被覆盖的基址。
|
||||
*(uint64*(AP_TRAMPOLINE_ADDR + 0x0F30)) = entry_addr
|
||||
|
||||
def start_aps():
|
||||
global _cpu_count, _ap_ready
|
||||
@@ -216,11 +215,9 @@ def start_aps():
|
||||
|
||||
cr3_val: uint64 = 0
|
||||
c.Asm(f"""mov rax, cr3
|
||||
mov {c.AsmOut(cr3_val, t.ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
[t.ASM_DESCR.CLOBBER_RAX])
|
||||
mov {c.AsmOut(cr3_val, t.ASM_DESCR.OUTPUT_REG)}, rax""", op = [t.ASM_DESCR.CLOBBER_RAX])
|
||||
|
||||
stack_size: uint64 = 8192
|
||||
i: uint32
|
||||
for i in range(1, _cpu_count):
|
||||
_ap_ready = 0
|
||||
stack: t.CPtr = mm.malloc(stack_size)
|
||||
@@ -236,10 +233,9 @@ def start_aps():
|
||||
timer.timer_msleep(1)
|
||||
_send_ipi(i, (AP_TRAMPOLINE_ADDR >> 12) & 0xFF, LAPIC_ICR_STARTUP)
|
||||
|
||||
wait: uint32 = 0
|
||||
while _ap_ready == 0 and wait < 5000:
|
||||
for i in range(5000):
|
||||
if _ap_ready != 0: break
|
||||
timer.timer_msleep(1)
|
||||
wait += 1
|
||||
|
||||
def early_init():
|
||||
global _cpu_count, _bsp_lapic_id
|
||||
|
||||
@@ -1,43 +1,41 @@
|
||||
import fpu
|
||||
import asm
|
||||
import intr.gdt as gdt
|
||||
import string
|
||||
import t, c
|
||||
import asm
|
||||
|
||||
IA32_KERNEL_GS_BASE: t.CDefine = 0xC0000102
|
||||
KERN_STACK_SIZE: t.CDefine = 8192
|
||||
define IA32_KERNEL_GS_BASE = 0xC0000102
|
||||
defineKERN_STACK_SIZE = 8192
|
||||
|
||||
|
||||
CPU_FEATURE_FPU: t.CDefine = (1 << 0)
|
||||
CPU_FEATURE_PSE: t.CDefine = (1 << 1)
|
||||
CPU_FEATURE_MSR: t.CDefine = (1 << 2)
|
||||
CPU_FEATURE_PAE: t.CDefine = (1 << 3)
|
||||
CPU_FEATURE_MCE: t.CDefine = (1 << 4)
|
||||
CPU_FEATURE_CX8: t.CDefine = (1 << 5)
|
||||
CPU_FEATURE_APIC: t.CDefine = (1 << 6)
|
||||
CPU_FEATURE_SEP: t.CDefine = (1 << 7)
|
||||
CPU_FEATURE_MTRR: t.CDefine = (1 << 8)
|
||||
CPU_FEATURE_PGE: t.CDefine = (1 << 9)
|
||||
CPU_FEATURE_MCA: t.CDefine = (1 << 10)
|
||||
CPU_FEATURE_CMOV: t.CDefine = (1 << 11)
|
||||
CPU_FEATURE_PAT: t.CDefine = (1 << 12)
|
||||
CPU_FEATURE_PSE36: t.CDefine = (1 << 13)
|
||||
CPU_FEATURE_PSN: t.CDefine = (1 << 14)
|
||||
CPU_FEATURE_CLFSH: t.CDefine = (1 << 15)
|
||||
CPU_FEATURE_DS: t.CDefine = (1 << 16)
|
||||
CPU_FEATURE_ACPI: t.CDefine = (1 << 17)
|
||||
CPU_FEATURE_MMX: t.CDefine = (1 << 18)
|
||||
CPU_FEATURE_FXSR: t.CDefine = (1 << 19)
|
||||
CPU_FEATURE_SSE: t.CDefine = (1 << 20)
|
||||
CPU_FEATURE_SSE2: t.CDefine = (1 << 21)
|
||||
CPU_FEATURE_SS: t.CDefine = (1 << 22)
|
||||
CPU_FEATURE_HTT: t.CDefine = (1 << 23)
|
||||
CPU_FEATURE_TM: t.CDefine = (1 << 24)
|
||||
CPU_FEATURE_PBE: t.CDefine = (1 << 25)
|
||||
define CPU_FEATURE_FPU = (1 << 0)
|
||||
define CPU_FEATURE_PSE = (1 << 1)
|
||||
define CPU_FEATURE_MSR = (1 << 2)
|
||||
define CPU_FEATURE_PAE = (1 << 3)
|
||||
define CPU_FEATURE_MCE = (1 << 4)
|
||||
define CPU_FEATURE_CX8 = (1 << 5)
|
||||
define CPU_FEATURE_APIC = (1 << 6)
|
||||
define CPU_FEATURE_SEP = (1 << 7)
|
||||
define CPU_FEATURE_MTRR = (1 << 8)
|
||||
define CPU_FEATURE_PGE = (1 << 9)
|
||||
define CPU_FEATURE_MCA = (1 << 10)
|
||||
define CPU_FEATURE_CMOV = (1 << 11)
|
||||
define CPU_FEATURE_PAT = (1 << 12)
|
||||
define CPU_FEATURE_PSE36 = (1 << 13)
|
||||
define CPU_FEATURE_PSN = (1 << 14)
|
||||
define CPU_FEATURE_CLFSH = (1 << 15)
|
||||
define CPU_FEATURE_DS = (1 << 16)
|
||||
define CPU_FEATURE_ACPI = (1 << 17)
|
||||
define CPU_FEATURE_MMX = (1 << 18)
|
||||
define CPU_FEATURE_FXSR = (1 << 19)
|
||||
define CPU_FEATURE_SSE = (1 << 20)
|
||||
define CPU_FEATURE_SSE2 = (1 << 21)
|
||||
define CPU_FEATURE_SS = (1 << 22)
|
||||
define CPU_FEATURE_HTT = (1 << 23)
|
||||
define CPU_FEATURE_TM = (1 << 24)
|
||||
define CPU_FEATURE_PBE = (1 << 25)
|
||||
|
||||
class cpu_info(t.CStruct):
|
||||
vendor_id: t.CArray[t.CChar, 13]
|
||||
brand_string: t.CArray[t.CChar, 48]
|
||||
class cpu_info:
|
||||
vendor_id: [13]char
|
||||
brand_string: [48]char
|
||||
features: uint32
|
||||
family: uint32
|
||||
model: uint32
|
||||
@@ -47,16 +45,16 @@ class cpu_info(t.CStruct):
|
||||
ext_family: uint32
|
||||
cpu_freq: uint64
|
||||
|
||||
@c.Attribute(t.attr.packed)
|
||||
@__attribute__(packed)
|
||||
class _tss:
|
||||
# x86_64 TSS 布局:偏移 0 为 4 字节保留字段(对齐 gdt.vp:32 的
|
||||
# "reserved0(4) rsp0(8) ..." 与 tss_buf: t.CArray[uint8, 104])。
|
||||
# 此前写作 uint64 使 RSP0 落在偏移 8、结构体 108B —— 与硬件 104B 布局
|
||||
# 及 gdt 的 tss_buf(104B) 不一致(N6)。
|
||||
reserved0: uint32
|
||||
rsp0: uint64
|
||||
rsp1: uint64
|
||||
rsp2: uint64
|
||||
reserved0: uint32
|
||||
rsp0: uint64
|
||||
rsp1: uint64
|
||||
rsp2: uint64
|
||||
reserved1: uint64
|
||||
ist1: uint64
|
||||
ist2: uint64
|
||||
@@ -69,51 +67,51 @@ class _tss:
|
||||
reserved3: uint16
|
||||
io_map_base: uint16
|
||||
|
||||
class cpuid_result(t.CStruct):
|
||||
class cpuid_result:
|
||||
eax: uint32
|
||||
ebx: uint32
|
||||
ecx: uint32
|
||||
edx: uint32
|
||||
|
||||
@c.Attribute(t.attr.naked)
|
||||
@__attribute__(packed)
|
||||
def _rdmsr_naked():
|
||||
c.Asm(f"""rdmsr
|
||||
__asm__(f"""rdmsr
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
ret""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RDX])
|
||||
op=[ASM_DESCR.CLOBBER_RDX])
|
||||
|
||||
@c.Attribute(t.attr.naked)
|
||||
@__attribute__(packed)
|
||||
def _wrmsr_naked():
|
||||
# msr_write sets ecx=msr, r8=value. wrmsr needs ECX=msr, EDX:EAX=value.
|
||||
# Old code did `mov rax,rcx` (rax=msr) which wrote (value>>32):msr to MSR,
|
||||
# corrupting IA32_KERNEL_GS_BASE -> swapgs -> #GP on gs:[0]. Fixed below.
|
||||
c.Asm(f"""mov rax, r8
|
||||
__asm__(f"""mov rax, r8
|
||||
mov rdx, r8
|
||||
shr rdx, 32
|
||||
wrmsr
|
||||
ret""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RDX])
|
||||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RDX])
|
||||
|
||||
def msr_read(msr: uint32) -> uint64:
|
||||
result: uint64 = 0
|
||||
func: t.CPtr = _rdmsr_naked
|
||||
c.Asm(f"""mov ecx, {c.AsmInp(msr, t.ASM_DESCR.REG_ANY)}
|
||||
call {c.AsmInp(func, t.ASM_DESCR.REG_ANY)}
|
||||
mov {c.AsmOut(result, t.ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX])
|
||||
func: callable = _rdmsr_naked
|
||||
__asm__(f"""mov ecx, {asminp(msr, ASM_DESCR.REG_ANY)}
|
||||
call {asminp(func, ASM_DESCR.REG_ANY)}
|
||||
mov {asmout(result, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX])
|
||||
return result
|
||||
|
||||
def msr_write(msr: uint32, value: uint64):
|
||||
func: t.CPtr = _wrmsr_naked
|
||||
c.Asm(f"""mov ecx, {c.AsmInp(msr, t.ASM_DESCR.REG_ANY)}
|
||||
mov r8, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)}
|
||||
call {c.AsmInp(func, t.ASM_DESCR.REG_ANY)}""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8])
|
||||
func: callable = _wrmsr_naked
|
||||
__asm__(f"""mov ecx, {asminp(msr, ASM_DESCR.REG_ANY)}
|
||||
mov r8, {asminp(value, ASM_DESCR.REG_ANY)}
|
||||
call {asminp(func, ASM_DESCR.REG_ANY)}""",
|
||||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_R8])
|
||||
|
||||
@c.Attribute(t.attr.naked)
|
||||
@__attribute__(packed)
|
||||
def _cpuid_naked():
|
||||
c.Asm(f"""push rbx
|
||||
__asm__(f"""push rbx
|
||||
mov eax, ecx
|
||||
cpuid
|
||||
mov dword ptr [rdx], eax
|
||||
@@ -122,12 +120,12 @@ def _cpuid_naked():
|
||||
mov dword ptr [rdx + 12], edx
|
||||
pop rbx
|
||||
ret""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX,
|
||||
t.ASM_DESCR.CLOBBER_RDX])
|
||||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX,
|
||||
ASM_DESCR.CLOBBER_RDX])
|
||||
|
||||
@c.Attribute(t.attr.naked)
|
||||
@__attribute__(packed)
|
||||
def _cpuid_sub_naked():
|
||||
c.Asm(f"""push rbx
|
||||
__asm__(f"""push rbx
|
||||
mov eax, ecx
|
||||
mov ecx, r8d
|
||||
cpuid
|
||||
@@ -137,37 +135,37 @@ def _cpuid_sub_naked():
|
||||
mov dword ptr [rdx + 12], edx
|
||||
pop rbx
|
||||
ret""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX,
|
||||
t.ASM_DESCR.CLOBBER_RDX])
|
||||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX,
|
||||
ASM_DESCR.CLOBBER_RDX])
|
||||
|
||||
@c.Attribute(t.attr.noinline)
|
||||
def cpuid(leaf: uint32, out: cpuid_result | t.CPtr):
|
||||
func: t.CPtr = _cpuid_naked
|
||||
c.Asm(f"""mov ecx, {c.AsmInp(leaf, t.ASM_DESCR.REG_ANY)}
|
||||
mov rdx, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
|
||||
call {c.AsmInp(func, t.ASM_DESCR.REG_ANY)}""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX,
|
||||
t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8,
|
||||
t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10,
|
||||
t.ASM_DESCR.CLOBBER_R11])
|
||||
@__attribute__(noinline)
|
||||
def cpuid(leaf: uint32, out: cpuid_result*):
|
||||
func: callable = _cpuid_naked
|
||||
__asm__(f"""mov ecx, {asminp(leaf, ASM_DESCR.REG_ANY)}
|
||||
mov rdx, {asminp(out, ASM_DESCR.REG_ANY)}
|
||||
call {asminp(func, ASM_DESCR.REG_ANY)}""",
|
||||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX,
|
||||
ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_R8,
|
||||
ASM_DESCR.CLOBBER_R9, ASM_DESCR.CLOBBER_R10,
|
||||
ASM_DESCR.CLOBBER_R11])
|
||||
|
||||
@c.Attribute(t.attr.noinline)
|
||||
def cpuid_sub(leaf: uint32, sub: uint32, out: cpuid_result | t.CPtr):
|
||||
func: t.CPtr = _cpuid_sub_naked
|
||||
c.Asm(f"""mov ecx, {c.AsmInp(leaf, t.ASM_DESCR.REG_ANY)}
|
||||
mov r8d, {c.AsmInp(sub, t.ASM_DESCR.REG_ANY)}
|
||||
mov rdx, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
|
||||
call {c.AsmInp(func, t.ASM_DESCR.REG_ANY)}""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX,
|
||||
t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8,
|
||||
t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10,
|
||||
t.ASM_DESCR.CLOBBER_R11])
|
||||
@__attribute__(noinline)
|
||||
def cpuid_sub(leaf: uint32, sub: uint32, out: cpuid_result*):
|
||||
func: callable = _cpuid_sub_naked
|
||||
__asm__(f"""mov ecx, {asminp(leaf, ASM_DESCR.REG_ANY)}
|
||||
mov r8d, {asminp(sub, ASM_DESCR.REG_ANY)}
|
||||
mov rdx, {asminp(out, ASM_DESCR.REG_ANY)}
|
||||
call {asminp(func, ASM_DESCR.REG_ANY)}""",
|
||||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX,
|
||||
ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_R8,
|
||||
ASM_DESCR.CLOBBER_R9, ASM_DESCR.CLOBBER_R10,
|
||||
ASM_DESCR.CLOBBER_R11])
|
||||
|
||||
@c.Attribute(t.attr.noinline)
|
||||
@__attribute__(noinline)
|
||||
def detect_features_static() -> uint32:
|
||||
features: uint32 = 0
|
||||
res: cpuid_result
|
||||
cpuid(1, c.Addr(res))
|
||||
cpuid(1, &res)
|
||||
if res.edx & (1 << 0): features |= CPU_FEATURE_FPU
|
||||
if res.edx & (1 << 3): features |= CPU_FEATURE_PSE
|
||||
if res.edx & (1 << 5): features |= CPU_FEATURE_MSR
|
||||
@@ -196,17 +194,16 @@ def detect_features_static() -> uint32:
|
||||
if res.edx & (1 << 30): features |= CPU_FEATURE_PBE
|
||||
return features
|
||||
|
||||
@c.Attribute(t.attr.packed)
|
||||
@__attribute__(packed)
|
||||
class per_cpu_data:
|
||||
user_rsp: uint64
|
||||
user_rsp: uint64
|
||||
kernel_rsp0: uint64
|
||||
current_pid: int
|
||||
_pad0: uint32
|
||||
_pad1: uint64
|
||||
_pad0: uint32
|
||||
_pad1: uint64
|
||||
|
||||
_per_cpu: per_cpu_data
|
||||
|
||||
@t.Object
|
||||
class _CPUObject:
|
||||
tss: _tss
|
||||
features: uint32
|
||||
@@ -215,27 +212,27 @@ class _CPUObject:
|
||||
|
||||
def __init_tss__(self):
|
||||
global _per_cpu
|
||||
string.memset(c.Addr(self.tss), 0, self.tss.__sizeof__())
|
||||
string.memset(&self.tss, 0, self.tss.__sizeof__())
|
||||
self.tss.io_map_base = self.tss.__sizeof__()
|
||||
string.memset(c.Addr(_per_cpu), 0, per_cpu_data.__sizeof__())
|
||||
gdt.setTSS64(5, uint64(c.Addr(self.tss)), self.tss.__sizeof__() - 1)
|
||||
string.memset(&_per_cpu, 0, per_cpu_data.__sizeof__())
|
||||
gdt.setTSS64(5, uint64(&self.tss), 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
|
||||
# IA32_KERNEL_GS_BASE (_per_cpu), making gs: accessible in kernel.
|
||||
# When returning to Ring 3, swapgs swaps back, restoring GS base to 0.
|
||||
msr_write(IA32_KERNEL_GS_BASE, uint64(c.Addr(_per_cpu)))
|
||||
msr_write(IA32_KERNEL_GS_BASE, uint64(&_per_cpu))
|
||||
|
||||
def getInfo(self, info: cpu_info | t.CPtr):
|
||||
def getInfo(self, info: cpu_info*):
|
||||
if not info: return
|
||||
res: cpuid_result
|
||||
cpuid(0, c.Addr(res))
|
||||
(uint32(info.vendor_id, t.CPtr))[0] = res.ebx
|
||||
(uint32(info.vendor_id, t.CPtr))[1] = res.edx
|
||||
(uint32(info.vendor_id, t.CPtr))[2] = res.ecx
|
||||
cpuid(0, &res)
|
||||
uint32*(info.vendor_id)[0] = res.ebx
|
||||
uint32*(info.vendor_id)[1] = res.edx
|
||||
uint32*(info.vendor_id)[2] = res.ecx
|
||||
info.vendor_id[12] = '\0'
|
||||
info.features = self.detectFeatures()
|
||||
cpuid(1, c.Addr(res))
|
||||
cpuid(1, &res)
|
||||
info.stepping = (res.eax >> 0) & 0x0F
|
||||
info.model = (res.eax >> 4) & 0x0F
|
||||
info.family = (res.eax >> 8) & 0x0F
|
||||
@@ -246,21 +243,21 @@ class _CPUObject:
|
||||
# 与 brand_string[48] 等长(此前 range(4) 会写 64 字节 → 越界 16 字节)。
|
||||
# 逐 u32 按字节地址显式写入,避免 uint32|t.CPtr 被降级为 i8* 后
|
||||
# 下标按字节偏移且被截断为 i8(只写低字节、偏移不乘 4)。
|
||||
brand_addr: uint64 = uint64(uint32(info.brand_string, t.CPtr))
|
||||
brand_addr: uint64 = uint64(uint32*(info.brand_string))
|
||||
for i in range(3):
|
||||
cpuid(0x80000002 + i, c.Addr(res))
|
||||
cpuid(0x80000002 + i, &res)
|
||||
off_b: uint64 = uint64(i) * 16
|
||||
c.Set(c.Deref(uint32(brand_addr + off_b, t.CPtr)), res.eax)
|
||||
c.Set(c.Deref(uint32(brand_addr + off_b + 4, t.CPtr)), res.ebx)
|
||||
c.Set(c.Deref(uint32(brand_addr + off_b + 8, t.CPtr)), res.ecx)
|
||||
c.Set(c.Deref(uint32(brand_addr + off_b + 12, t.CPtr)), res.edx)
|
||||
*(uint32*(brand_addr + off_b + 0)) = res.eax
|
||||
*(uint32*(brand_addr + off_b + 4)) = res.ebx
|
||||
*(uint32*(brand_addr + off_b + 8)) = res.ecx
|
||||
*(uint32*(brand_addr + off_b + 12)) = res.edx
|
||||
info.brand_string[47] = '\0'
|
||||
info.cpu_freq = 2000000000
|
||||
|
||||
def detectFeatures(self) -> uint32:
|
||||
features: int32 = 0
|
||||
res: cpuid_result
|
||||
cpuid(1, c.Addr(res))
|
||||
cpuid(1, &res)
|
||||
if res.edx & (1 << 0): features |= CPU_FEATURE_FPU
|
||||
if res.edx & (1 << 3): features |= CPU_FEATURE_PSE
|
||||
if res.edx & (1 << 5): features |= CPU_FEATURE_MSR
|
||||
@@ -290,10 +287,10 @@ class _CPUObject:
|
||||
return features
|
||||
|
||||
def enableInterrupts(self):
|
||||
c.Asm("sti", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
__asm__("sti", [ASM_DESCR.CLOBBER_MEMORY])
|
||||
|
||||
def disableInterrupts(self):
|
||||
c.Asm("cli", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
__asm__("cli", [ASM_DESCR.CLOBBER_MEMORY])
|
||||
|
||||
def enableNmis(self):
|
||||
current: uint8 = asm.inb(0x70)
|
||||
@@ -305,39 +302,39 @@ class _CPUObject:
|
||||
|
||||
def readCR0(self) -> uint64:
|
||||
cr0: uint64
|
||||
c.Asm(f"""mov rax, cr0
|
||||
mov {c.AsmOut(cr0, t.ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
[t.ASM_DESCR.CLOBBER_RAX])
|
||||
__asm__(f"""mov rax, cr0
|
||||
mov {asmout(cr0, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
[ASM_DESCR.CLOBBER_RAX])
|
||||
return cr0
|
||||
|
||||
def writeCR0(self, value: uint64):
|
||||
c.Asm(f"""mov rax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)}
|
||||
__asm__(f"""mov rax, {asminp(value, ASM_DESCR.REG_ANY)}
|
||||
mov cr0, rax""",
|
||||
[t.ASM_DESCR.CLOBBER_RAX])
|
||||
[ASM_DESCR.CLOBBER_RAX])
|
||||
|
||||
def readCR3(self) -> uint64:
|
||||
cr3: uint64
|
||||
c.Asm(f"""mov rax, cr3
|
||||
mov {c.AsmOut(cr3, t.ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
[t.ASM_DESCR.CLOBBER_RAX])
|
||||
__asm__(f"""mov rax, cr3
|
||||
mov {asmout(cr3, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
[ASM_DESCR.CLOBBER_RAX])
|
||||
return cr3
|
||||
|
||||
def writeCR3(self, value: uint64):
|
||||
c.Asm(f"""mov rax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)}
|
||||
__asm__(f"""mov rax, {asminp(value, ASM_DESCR.REG_ANY)}
|
||||
mov cr3, rax""",
|
||||
[t.ASM_DESCR.CLOBBER_RAX])
|
||||
[ASM_DESCR.CLOBBER_RAX])
|
||||
|
||||
def readCR4(self) -> uint64:
|
||||
cr4: uint64
|
||||
c.Asm(f"""mov rax, cr4
|
||||
mov {c.AsmOut(cr4, t.ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
[t.ASM_DESCR.CLOBBER_RAX])
|
||||
__asm__(f"""mov rax, cr4
|
||||
mov {asmout(cr4, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
[ASM_DESCR.CLOBBER_RAX])
|
||||
return cr4
|
||||
|
||||
def writeCR4(self, value: uint64):
|
||||
c.Asm(f"""mov rax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)}
|
||||
__asm__(f"""mov rax, {asminp(value, ASM_DESCR.REG_ANY)}
|
||||
mov cr4, rax""",
|
||||
[t.ASM_DESCR.CLOBBER_RAX])
|
||||
[ASM_DESCR.CLOBBER_RAX])
|
||||
|
||||
def readMSR(self, msr: uint32) -> uint64:
|
||||
return msr_read(msr)
|
||||
@@ -359,20 +356,20 @@ def set_kernel_rsp0(rsp0: uint64):
|
||||
# 传 float/double 时保存 xmm 寄存器触发(serial.printf / snprintf("%.2f") 崩溃根因)。
|
||||
def enable_sse():
|
||||
cr0_v: uint64 = 0
|
||||
c.Asm(f"""mov rax, cr0
|
||||
mov {c.AsmOut(cr0_v, t.ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX])
|
||||
__asm__(f"""mov rax, cr0
|
||||
mov {asmout(cr0_v, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
op=[ASM_DESCR.CLOBBER_RAX])
|
||||
cr0_v = cr0_v & ~uint64(4) # 清 EM(禁止 FPU 仿真)
|
||||
cr0_v = cr0_v | uint64(2) # 置 MP(监控协处理器)
|
||||
c.Asm(f"""mov rax, {c.AsmInp(cr0_v, t.ASM_DESCR.REG_ANY)}
|
||||
__asm__(f"""mov rax, {asminp(cr0_v, ASM_DESCR.REG_ANY)}
|
||||
mov cr0, rax""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX])
|
||||
op=[ASM_DESCR.CLOBBER_RAX])
|
||||
cr4_v: uint64 = 0
|
||||
c.Asm(f"""mov rax, cr4
|
||||
mov {c.AsmOut(cr4_v, t.ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX])
|
||||
__asm__(f"""mov rax, cr4
|
||||
mov {asmout(cr4_v, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||||
op=[ASM_DESCR.CLOBBER_RAX])
|
||||
cr4_v = cr4_v | uint64(0x600) # OSFXSR | OSXMMEXCPT
|
||||
c.Asm(f"""mov rax, {c.AsmInp(cr4_v, t.ASM_DESCR.REG_ANY)}
|
||||
__asm__(f"""mov rax, {asminp(cr4_v, ASM_DESCR.REG_ANY)}
|
||||
mov cr4, rax""",
|
||||
op=[t.ASM_DESCR.CLOBBER_RAX])
|
||||
c.Asm("fninit", op=[t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
op=[ASM_DESCR.CLOBBER_RAX])
|
||||
__asm__("fninit", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||||
@@ -1,21 +1,19 @@
|
||||
import cpu
|
||||
import t, c
|
||||
|
||||
|
||||
# FPU上下文结构体
|
||||
@c.Attribute(t.attr.aligned(16))
|
||||
@__attribute__(aligned(16))
|
||||
class fpu_context:
|
||||
data: t.CArray[uint8, 512] # FXSAVE区域大小
|
||||
data: [512]uint8 # FXSAVE区域大小
|
||||
|
||||
|
||||
@t.Object
|
||||
class _FPUObject:
|
||||
CPUObject: cpu._CPUObject | t.CPtr
|
||||
CPUObject: cpu._CPUObject*
|
||||
# 初始化FPU
|
||||
def __init__(self, CPUObject: cpu._CPUObject | t.CPtr):
|
||||
def __init__(self, CPUObject: cpu._CPUObject*):
|
||||
self.enable()
|
||||
self.CPUObject = CPUObject
|
||||
c.Asm("fninit", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
__asm__("fninit", [ASM_DESCR.CLOBBER_MEMORY])
|
||||
# 启用FPU
|
||||
def enable(self):
|
||||
cr0: uint64 = self.CPUObject.readCR0()
|
||||
@@ -31,7 +29,7 @@ class _FPUObject:
|
||||
# 写入CR4寄存器
|
||||
self.CPUObject.writeCR4(cr4)
|
||||
# 初始化FPU
|
||||
c.Asm("fninit", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
__asm__("fninit", [ASM_DESCR.CLOBBER_MEMORY])
|
||||
# 禁用FPU
|
||||
def disable(self):
|
||||
cr0: uint64 = self.CPUObject.readCR0()
|
||||
@@ -41,10 +39,10 @@ class _FPUObject:
|
||||
# 写入CR0寄存器
|
||||
self.CPUObject.writeCR0(cr0)
|
||||
# 保存FPU上下文
|
||||
def save_context(self, context: fpu_context | t.CPtr):
|
||||
def save_context(self, context: fpu_context*):
|
||||
# 保存FPU状态到内存
|
||||
c.Asm(f"fxsave [{c.AsmInp(context, t.ASM_DESCR.REG_ANY)}]", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
__asm__(f"fxsave [{asminp(context, ASM_DESCR.REG_ANY)}]", [ASM_DESCR.CLOBBER_MEMORY])
|
||||
# 恢复FPU上下文
|
||||
def restore_context(self, context: t.CConst | fpu_context | t.CPtr):
|
||||
def restore_context(self, context: const fpu_context*):
|
||||
# 从内存恢复FPU状态
|
||||
c.Asm(f"fxrstor [{c.AsmInp(context, t.ASM_DESCR.REG_ANY)}]", [t.ASM_DESCR.CLOBBER_MEMORY])
|
||||
__asm__(f"fxrstor [{asminp(context, ASM_DESCR.REG_ANY)}]", [ASM_DESCR.CLOBBER_MEMORY])
|
||||
@@ -1,385 +0,0 @@
|
||||
import drivers.serial.uart.serial as serial
|
||||
import viperstring as string
|
||||
import t, c
|
||||
|
||||
|
||||
MAX_FILE_DESCRIPTORS: t.CDefine = 64
|
||||
MAX_DEVICE_FILES: t.CDefine = 32
|
||||
MAX_DIRECTORIES: t.CDefine = 16
|
||||
PATH_BUFFER_SIZE: t.CDefine = 256
|
||||
|
||||
directories: list[devfs_directory, MAX_DIRECTORIES] = [0]
|
||||
directory_count: t.CStatic | t.CInt = 0
|
||||
|
||||
files: list[devfs_file, MAX_DEVICE_FILES] = [0]
|
||||
file_count: t.CStatic | t.CInt = 0
|
||||
|
||||
|
||||
class _fd_table:
|
||||
file: devfs_file | t.CPtr
|
||||
flags: t.CInt
|
||||
|
||||
fd_table: list[_fd_table, MAX_FILE_DESCRIPTORS] = [0]
|
||||
|
||||
@t.Object
|
||||
class devfs_directory:
|
||||
name: list[t.CChar, 64]
|
||||
parent: 'devfs_directory' | t.CPtr
|
||||
|
||||
@staticmethod
|
||||
def find(path: t.CConst | str,
|
||||
root_directory: devfs_directory | t.CPtr) -> devfs_directory | t.CPtr:
|
||||
if not path or string.strchr(path, '/') != path: return None
|
||||
if not root_directory: return None
|
||||
|
||||
current_dir: devfs_directory | t.CPtr = root_directory
|
||||
result: list[str, PATH_BUFFER_SIZE]
|
||||
token = string.split(path, "/", result)
|
||||
|
||||
for i in result:
|
||||
found: bool = False
|
||||
for d in range(directory_count):
|
||||
dirp: devfs_directory = c.Addr(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: t.CConst | str,
|
||||
parent: devfs_directory | t.CPtr) -> devfs_directory | t.CPtr:
|
||||
for d in range(directory_count):
|
||||
dirp: devfs_directory = c.Addr(directories[d])
|
||||
if dirp.parent == parent and string.samestr(dirp.name, name):
|
||||
return dirp
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def list_subdirs(dir_ptr: devfs_directory | t.CPtr,
|
||||
buffer: str,
|
||||
size: t.CUInt32T,
|
||||
pos: t.CInt) -> t.CInt:
|
||||
for d in range(directory_count):
|
||||
dirp: devfs_directory = c.Addr(directories[d])
|
||||
if dirp.parent == dir_ptr:
|
||||
name_len: t.CInt = 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
|
||||
|
||||
@t.Object
|
||||
@t.CVTable
|
||||
class devfs_file:
|
||||
name: list[t.CChar, 64]
|
||||
private_data: t.CVoid | t.CPtr
|
||||
parent_dir: 'devfs_directory' | t.CPtr
|
||||
|
||||
@staticmethod
|
||||
def find_in_dir(file_name: t.CConst | str,
|
||||
dir_ptr: devfs_directory | t.CPtr) -> devfs_file | t.CPtr:
|
||||
for f in range(file_count):
|
||||
fp: devfs_file | t.CPtr = c.Addr(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 | t.CPtr,
|
||||
buffer: str,
|
||||
size: t.CUInt32T,
|
||||
pos: t.CInt) -> t.CInt:
|
||||
for f in range(file_count):
|
||||
filep: devfs_file | t.CPtr = c.Addr(files[f])
|
||||
if filep.parent_dir == dir_ptr:
|
||||
name_len: t.CInt = 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: t.CConst | str, flags: t.CInt) -> t.CInt:
|
||||
return 0
|
||||
|
||||
def close(self, fd: t.CInt) -> t.CInt:
|
||||
return 0
|
||||
|
||||
def read(self, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt:
|
||||
return 0
|
||||
|
||||
def write(self, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt:
|
||||
return 0
|
||||
|
||||
def ioctl(self, fd: t.CInt, request: t.CInt, arg: t.CVoid | t.CPtr) -> t.CInt:
|
||||
return 0
|
||||
|
||||
@t.Object
|
||||
class _DevFSObject:
|
||||
root_directory: devfs_directory | t.CPtr
|
||||
|
||||
def __init__(self):
|
||||
global directory_count, file_count
|
||||
self.root_directory = None
|
||||
directory_count = 0
|
||||
file_count = 0
|
||||
string.memset(c.Addr(directories), 0, devfs_directory.__sizeof__() * MAX_DIRECTORIES)
|
||||
string.memset(c.Addr(files), 0, devfs_file.__sizeof__() * MAX_DEVICE_FILES)
|
||||
string.memset(c.Addr(fd_table), 0, _fd_table.__sizeof__() * MAX_FILE_DESCRIPTORS)
|
||||
|
||||
def create_single_dir(self, parent: devfs_directory | t.CPtr,
|
||||
dir_name: t.CConst | str) -> devfs_directory | t.CPtr:
|
||||
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 | t.CPtr = c.Addr(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: t.CConst | str) -> devfs_directory | t.CPtr:
|
||||
global directory_count
|
||||
if not path or string.samestr(path, "/"): return None
|
||||
|
||||
if not self.root_directory:
|
||||
self.root_directory = c.Addr(directories[directory_count])
|
||||
directory_count += 1
|
||||
string.strcpy(self.root_directory.name, "")
|
||||
self.root_directory.parent = None
|
||||
|
||||
current: devfs_directory | t.CPtr = self.root_directory
|
||||
buf: list[t.CChar, PATH_BUFFER_SIZE]
|
||||
string.memset(c.Addr(buf), 0, PATH_BUFFER_SIZE)
|
||||
buf_idx: t.CInt = 0
|
||||
p: t.CInt = 0
|
||||
if path[p] == '/':
|
||||
p += 1
|
||||
while path[p] != '\0':
|
||||
if path[p] == '/':
|
||||
if buf_idx > 0:
|
||||
found_child: devfs_directory | t.CPtr = 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(c.Addr(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 | t.CPtr = 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) -> t.CInt:
|
||||
self.create_directory("/dev")
|
||||
self.create_directory("/dev/input")
|
||||
return 0
|
||||
|
||||
def create_directory(self, path: t.CConst | str) -> t.CInt:
|
||||
dir_ptr: devfs_directory | t.CPtr = self.find_or_create_directory(path)
|
||||
return 0 if dir_ptr else -1
|
||||
|
||||
def create_file(self, path: t.CConst | str,
|
||||
private_data: t.CVoid | t.CPtr) -> t.CInt:
|
||||
global file_count
|
||||
path_copy: list[t.CChar, PATH_BUFFER_SIZE]
|
||||
string.memset(c.Addr(path_copy), 0, PATH_BUFFER_SIZE)
|
||||
string.strcpy(path_copy, path)
|
||||
|
||||
last_slash: str | t.CPtr = string.strrchr(path_copy, '/')
|
||||
|
||||
if not last_slash: return -1
|
||||
|
||||
last_slash[0] = '\0'
|
||||
dir_path = path_copy
|
||||
file_name: str | t.CPtr = last_slash + 1
|
||||
|
||||
dir_ptr: devfs_directory | t.CPtr = 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
|
||||
|
||||
new_file: devfs_file | t.CPtr = c.Addr(files[file_count])
|
||||
file_count += 1
|
||||
|
||||
string.strcpy(new_file.name, file_name)
|
||||
new_file.private_data = private_data
|
||||
new_file.parent_dir = dir_ptr
|
||||
|
||||
return 0
|
||||
|
||||
def open(self, path: t.CConst | str, flags: t.CInt) -> t.CInt:
|
||||
path_copy: list[t.CChar, PATH_BUFFER_SIZE]
|
||||
string.memset(c.Addr(path_copy), 0, PATH_BUFFER_SIZE)
|
||||
string.strcpy(path_copy, path)
|
||||
|
||||
last_slash: str | t.CPtr = string.strrchr(path_copy, '/')
|
||||
|
||||
if not last_slash: return -1
|
||||
|
||||
last_slash[0] = '\0'
|
||||
dir_path = path_copy
|
||||
file_name: str | t.CPtr = last_slash + 1
|
||||
|
||||
dir_ptr: devfs_directory | t.CPtr = devfs_directory.find(dir_path, self.root_directory)
|
||||
if not dir_ptr: return -1
|
||||
|
||||
file_ptr: devfs_file | t.CPtr = devfs_file.find_in_dir(file_name, dir_ptr)
|
||||
if not file_ptr: return -1
|
||||
|
||||
if not file_ptr.open:
|
||||
return -1
|
||||
|
||||
fd: t.CInt = -1
|
||||
for i in range(MAX_FILE_DESCRIPTORS):
|
||||
if not fd_table[i].file:
|
||||
fd = i
|
||||
break
|
||||
|
||||
if fd == -1: return -1
|
||||
|
||||
ret: t.CInt = 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: t.CInt) -> t.CInt:
|
||||
if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file:
|
||||
return -1
|
||||
file_ptr: devfs_file | t.CPtr = fd_table[fd].file
|
||||
if file_ptr and file_ptr.close:
|
||||
file_ptr.close(fd)
|
||||
fd_table[fd].file = None
|
||||
fd_table[fd].flags = 0
|
||||
return 0
|
||||
|
||||
def read(self, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt:
|
||||
if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file:
|
||||
return -1
|
||||
file_ptr: devfs_file | t.CPtr = fd_table[fd].file
|
||||
if file_ptr and file_ptr.read:
|
||||
return file_ptr.read(fd, buffer, size)
|
||||
return 0
|
||||
|
||||
def write(self, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt:
|
||||
if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file:
|
||||
return -1
|
||||
file_ptr: devfs_file | t.CPtr = fd_table[fd].file
|
||||
if file_ptr and file_ptr.write:
|
||||
return file_ptr.write(fd, buffer, size)
|
||||
return 0
|
||||
|
||||
def ioctl(self, fd: t.CInt, cmd: t.CUInt32T, arg: t.CVoid | t.CPtr) -> t.CInt:
|
||||
if fd < 0 or fd >= MAX_FILE_DESCRIPTORS or not fd_table[fd].file:
|
||||
return -1
|
||||
file_ptr: devfs_file | t.CPtr = fd_table[fd].file
|
||||
if file_ptr and file_ptr.ioctl:
|
||||
return file_ptr.ioctl(fd, cmd, arg)
|
||||
return 0
|
||||
|
||||
def list_directory(self, path: t.CConst | str,
|
||||
buffer: str,
|
||||
size: t.CUInt32T) -> t.CInt:
|
||||
dir_ptr: devfs_directory | t.CPtr = devfs_directory.find(path, self.root_directory)
|
||||
if not dir_ptr or not buffer or size == 0: return -1
|
||||
|
||||
pos: t.CInt = devfs_directory.list_subdirs(dir_ptr, buffer, size, 0)
|
||||
pos = devfs_file.list_in_dir(dir_ptr, buffer, size, pos)
|
||||
|
||||
return pos
|
||||
|
||||
DevFSObject: _DevFSObject | t.CPtr
|
||||
_DevFSObject_instance: _DevFSObject
|
||||
|
||||
|
||||
def devfs_init() -> t.CInt:
|
||||
global DevFSObject, _DevFSObject_instance
|
||||
DevFSObject = c.Addr(_DevFSObject_instance)
|
||||
_DevFSObject_instance.__init__()
|
||||
DevFSObject.init()
|
||||
return 0
|
||||
|
||||
def devfs_create_directory(path: t.CConst | str) -> t.CInt:
|
||||
return DevFSObject.create_directory(path)
|
||||
|
||||
def devfs_create_file(path: t.CConst | str,
|
||||
private_data: t.CVoid | t.CPtr) -> t.CInt:
|
||||
return DevFSObject.create_file(path, private_data)
|
||||
|
||||
def devfs_open(path: t.CConst | str, flags: t.CInt) -> t.CInt:
|
||||
return DevFSObject.open(path, flags)
|
||||
|
||||
def devfs_close(fd: t.CInt) -> t.CInt:
|
||||
return DevFSObject.close(fd)
|
||||
|
||||
def devfs_read(fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt:
|
||||
return DevFSObject.read(fd, buffer, size)
|
||||
|
||||
def devfs_write(fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt:
|
||||
return DevFSObject.write(fd, buffer, size)
|
||||
|
||||
def devfs_ioctl(fd: t.CInt, cmd: t.CUInt32T, arg: t.CVoid | t.CPtr) -> t.CInt:
|
||||
return DevFSObject.ioctl(fd, cmd, arg)
|
||||
|
||||
def devfs_list_directory(path: t.CConst | str,
|
||||
buffer: str,
|
||||
size: t.CUInt32T) -> t.CInt:
|
||||
return DevFSObject.list_directory(path, buffer, size)
|
||||
|
||||
serial0_file: devfs_file
|
||||
|
||||
def serial0_open(self: t.CVoid | t.CPtr, path: t.CConst | str, flags: t.CInt) -> t.CInt:
|
||||
serial.puts("[serial0] open: ")
|
||||
serial.puts(path)
|
||||
serial.puts("\n")
|
||||
return 0
|
||||
|
||||
def serial0_close(self: t.CVoid | t.CPtr, fd: t.CInt) -> t.CInt:
|
||||
serial.puts("[serial0] close\n")
|
||||
return 0
|
||||
|
||||
def serial0_read(self: t.CVoid | t.CPtr, fd: t.CInt, buffer: t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt:
|
||||
serial.puts("[serial0] read\n")
|
||||
return 0
|
||||
|
||||
def serial0_write(self: t.CVoid | t.CPtr, fd: t.CInt, buffer: t.CConst | t.CVoid | t.CPtr, size: t.CUInt32T) -> t.CInt:
|
||||
serial.puts("[serial0] write\n")
|
||||
serial.puts(str(buffer))
|
||||
serial.puts("\n")
|
||||
return size
|
||||
|
||||
def devfs_register_serial0() -> t.CInt:
|
||||
global serial0_file
|
||||
serial0_file = devfs_file()
|
||||
serial0_file.open = serial0_open
|
||||
serial0_file.close = serial0_close
|
||||
serial0_file.read = serial0_read
|
||||
serial0_file.write = serial0_write
|
||||
serial0_file.ioctl = None
|
||||
return devfs_create_file("/dev/serial0", serial0_file)
|
||||
@@ -1,40 +1,38 @@
|
||||
import drivers.serial.uart.serial as serial
|
||||
import viperstring as string
|
||||
import string
|
||||
import viperlib
|
||||
import t, c
|
||||
|
||||
|
||||
MAX_FILE_DESCRIPTORS: t.CDefine = 64
|
||||
MAX_DEVICE_FILES: t.CDefine = 32
|
||||
MAX_DIRECTORIES: t.CDefine = 16
|
||||
PATH_BUFFER_SIZE: t.CDefine = 256
|
||||
define MAX_FILE_DESCRIPTORS = 64
|
||||
define MAX_DEVICE_FILES = 32
|
||||
define MAX_DIRECTORIES = 16
|
||||
define PATH_BUFFER_SIZE = 256
|
||||
|
||||
directories: t.CArray[devfs_directory, MAX_DIRECTORIES] = [0]
|
||||
directory_count: t.CStatic | int = 0
|
||||
directories: [MAX_DIRECTORIES]devfs_directory = [0]
|
||||
directory_count: static int = 0
|
||||
|
||||
files: t.CArray[devfs_file, MAX_DEVICE_FILES] = [0]
|
||||
file_count: t.CStatic | int = 0
|
||||
files: [MAX_DEVICE_FILES]devfs_file = [0]
|
||||
file_count: static int = 0
|
||||
|
||||
|
||||
class _fd_table:
|
||||
file: devfs_file | t.CPtr
|
||||
file: devfs_file*
|
||||
flags: int
|
||||
|
||||
fd_table: t.CArray[_fd_table, MAX_FILE_DESCRIPTORS] = [0]
|
||||
fd_table: [MAX_FILE_DESCRIPTORS]_fd_table = [0]
|
||||
|
||||
|
||||
@t.Object
|
||||
class devfs_directory:
|
||||
name: t.CArray[t.CChar, 64]
|
||||
parent: 'devfs_directory' | t.CPtr
|
||||
name: [64]char
|
||||
parent: devfs_directory*
|
||||
|
||||
@staticmethod
|
||||
def find(path: t.CConst | str,
|
||||
root_directory: devfs_directory | t.CPtr) -> devfs_directory | t.CPtr:
|
||||
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 | t.CPtr = root_directory
|
||||
result: t.CArray[str, PATH_BUFFER_SIZE]
|
||||
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 停):
|
||||
@@ -42,7 +40,7 @@ class devfs_directory:
|
||||
for i in result:
|
||||
found: bool = False
|
||||
for d in range(directory_count):
|
||||
dirp: devfs_directory = c.Addr(directories[d])
|
||||
dirp: devfs_directory = &directories[d]
|
||||
if dirp.parent == current_dir and string.samestr(dirp.name, i):
|
||||
current_dir = dirp
|
||||
found = True
|
||||
@@ -52,21 +50,17 @@ class devfs_directory:
|
||||
return current_dir
|
||||
|
||||
@staticmethod
|
||||
def find_child(name: t.CConst | str,
|
||||
parent: devfs_directory | t.CPtr) -> devfs_directory | t.CPtr:
|
||||
def find_child(name: const str, parent: devfs_directory*) -> devfs_directory*:
|
||||
for d in range(directory_count):
|
||||
dirp: devfs_directory = c.Addr(directories[d])
|
||||
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 | t.CPtr,
|
||||
buffer: str,
|
||||
size: uint32,
|
||||
pos: int) -> int:
|
||||
def list_subdirs(dir_ptr: devfs_directory*, buffer: str, size: uint32, pos: int) -> int:
|
||||
for d in range(directory_count):
|
||||
dirp: devfs_directory = c.Addr(directories[d])
|
||||
dirp: devfs_directory = &directories[d]
|
||||
if dirp.parent == dir_ptr:
|
||||
name_len: int = string.strlen(dirp.name)
|
||||
if pos + name_len + 1 > size:
|
||||
@@ -77,29 +71,24 @@ class devfs_directory:
|
||||
pos += 1
|
||||
return pos
|
||||
|
||||
@t.Object
|
||||
@t.CVTable
|
||||
class devfs_file:
|
||||
name: t.CArray[t.CChar, 64]
|
||||
private_data: t.CPtr
|
||||
parent_dir: 'devfs_directory' | t.CPtr
|
||||
|
||||
virtual class devfs_file:
|
||||
name: [64]char
|
||||
private_data: rawptr
|
||||
parent_dir: devfs_directory*
|
||||
|
||||
@staticmethod
|
||||
def find_in_dir(file_name: t.CConst | str,
|
||||
dir_ptr: devfs_directory | t.CPtr) -> devfs_file | t.CPtr:
|
||||
def find_in_dir(file_name: const str, dir_ptr: devfs_directory*) -> devfs_file*:
|
||||
for f in range(file_count):
|
||||
fp: devfs_file | t.CPtr = c.Addr(files[f])
|
||||
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 | t.CPtr,
|
||||
buffer: str,
|
||||
size: uint32,
|
||||
pos: int) -> int:
|
||||
def list_in_dir(dir_ptr: devfs_directory*, buffer: str, size: uint32, pos: int) -> int:
|
||||
for f in range(file_count):
|
||||
filep: devfs_file | t.CPtr = c.Addr(files[f])
|
||||
filep: devfs_file* = c.Addr(files[f])
|
||||
if filep.parent_dir == dir_ptr:
|
||||
name_len: int = string.strlen(filep.name)
|
||||
if pos + name_len + 1 > size:
|
||||
@@ -110,42 +99,32 @@ class devfs_file:
|
||||
pos += 1
|
||||
return pos
|
||||
|
||||
def open(self, path: t.CConst | str, flags: int) -> int:
|
||||
return 0
|
||||
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
|
||||
|
||||
def close(self, fd: int) -> int:
|
||||
return 0
|
||||
|
||||
def read(self, fd: int, buffer: t.CPtr, size: uint32) -> int:
|
||||
return 0
|
||||
|
||||
def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int:
|
||||
return 0
|
||||
|
||||
def ioctl(self, fd: int, request: int, arg: t.CPtr) -> int:
|
||||
return 0
|
||||
|
||||
@t.Object
|
||||
class _DevFSObject:
|
||||
root_directory: devfs_directory | t.CPtr
|
||||
root_directory: devfs_directory*
|
||||
|
||||
def __init__(self):
|
||||
global directory_count, file_count
|
||||
self.root_directory = None
|
||||
directory_count = 0
|
||||
file_count = 0
|
||||
string.memset(c.Addr(directories), 0, devfs_directory.__sizeof__() * MAX_DIRECTORIES)
|
||||
string.memset(c.Addr(files), 0, devfs_file.__sizeof__() * MAX_DEVICE_FILES)
|
||||
string.memset(c.Addr(fd_table), 0, _fd_table.__sizeof__() * MAX_FILE_DESCRIPTORS)
|
||||
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 | t.CPtr,
|
||||
dir_name: t.CConst | str) -> devfs_directory | t.CPtr:
|
||||
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 | t.CPtr = c.Addr(directories[directory_count])
|
||||
new_dir: devfs_directory* = c.Addr(directories[directory_count])
|
||||
directory_count += 1
|
||||
|
||||
string.strcpy(new_dir.name, dir_name)
|
||||
@@ -153,50 +132,42 @@ class _DevFSObject:
|
||||
|
||||
return new_dir
|
||||
|
||||
def find_or_create_directory(self, path: t.CConst | str) -> devfs_directory | t.CPtr:
|
||||
def find_or_create_directory(self, path: const str) -> devfs_directory*:
|
||||
global directory_count
|
||||
if not path or string.samestr(path, "/"): return None
|
||||
|
||||
serial.puts("A")
|
||||
if not self.root_directory:
|
||||
self.root_directory = c.Addr(directories[directory_count])
|
||||
directory_count += 1
|
||||
string.strcpy(self.root_directory.name, "")
|
||||
self.root_directory.parent = None
|
||||
|
||||
serial.puts("B")
|
||||
current: devfs_directory | t.CPtr = self.root_directory
|
||||
buf: t.CArray[t.CChar, PATH_BUFFER_SIZE]
|
||||
string.memset(c.Addr(buf), 0, PATH_BUFFER_SIZE)
|
||||
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
|
||||
serial.puts("C")
|
||||
if path[p] == '/': p += 1
|
||||
while path[p] != '\0':
|
||||
if path[p] == '/':
|
||||
if buf_idx > 0:
|
||||
found_child: devfs_directory | t.CPtr = devfs_directory.find_child(buf, current)
|
||||
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(c.Addr(buf), 0, PATH_BUFFER_SIZE)
|
||||
string.memset(&buf, 0, PATH_BUFFER_SIZE)
|
||||
buf_idx = 0
|
||||
p += 1
|
||||
else:
|
||||
buf[buf_idx] = path[p]
|
||||
buf_idx += 1
|
||||
p += 1
|
||||
serial.puts("D")
|
||||
if buf_idx > 0:
|
||||
found_child: devfs_directory | t.CPtr = devfs_directory.find_child(buf, current)
|
||||
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
|
||||
serial.puts("E")
|
||||
|
||||
return current
|
||||
|
||||
def init(self) -> int:
|
||||
@@ -204,19 +175,15 @@ class _DevFSObject:
|
||||
self.create_directory("/dev/input")
|
||||
return 0
|
||||
|
||||
def create_directory(self, path: t.CConst | str) -> int:
|
||||
serial.puts("T1")
|
||||
dir_ptr: devfs_directory | t.CPtr = self.find_or_create_directory(path)
|
||||
serial.puts("T2")
|
||||
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: t.CConst | str,
|
||||
file_ptr: devfs_file | t.CPtr,
|
||||
private_data: t.CPtr) -> int:
|
||||
def create_file(self, path: const str, file_ptr: devfs_file*, private_data: rawptr) -> int:
|
||||
global file_count
|
||||
path_copy: t.CArray[t.CChar, PATH_BUFFER_SIZE]
|
||||
string.memset(c.Addr(path_copy), 0, PATH_BUFFER_SIZE)
|
||||
string.strcpy(path_copy, path)
|
||||
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, '/')
|
||||
|
||||
@@ -226,25 +193,18 @@ class _DevFSObject:
|
||||
dir_path = path_copy
|
||||
file_name: str = last_slash + 1
|
||||
|
||||
dir_ptr: devfs_directory | t.CPtr = self.find_or_create_directory(dir_path)
|
||||
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 devfs_file.find_in_dir(file_name, dir_ptr): return -1
|
||||
if file_count >= MAX_DEVICE_FILES: return -1
|
||||
|
||||
if file_ptr:
|
||||
# [DIAG] 定位 register 阶段 strcpy 目标:打印 file_ptr(用后移除)
|
||||
_dbg3: t.CArray[t.CChar, 80]
|
||||
viperlib.snprintf(c.Addr(_dbg3), 80, "[cf] fp=%lx\n", uint64(file_ptr))
|
||||
serial.puts(c.Addr(_dbg3))
|
||||
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 | t.CPtr = c.Addr(files[file_count])
|
||||
new_file: devfs_file* = c.Addr(files[file_count])
|
||||
string.strcpy(new_file.name, file_name)
|
||||
new_file.private_data = private_data
|
||||
new_file.parent_dir = dir_ptr
|
||||
@@ -252,10 +212,10 @@ class _DevFSObject:
|
||||
file_count += 1
|
||||
return 0
|
||||
|
||||
def open(self, path: t.CConst | str, flags: int) -> int:
|
||||
path_copy: t.CArray[t.CChar, PATH_BUFFER_SIZE]
|
||||
string.memset(c.Addr(path_copy), 0, PATH_BUFFER_SIZE)
|
||||
string.strcpy(path_copy, path)
|
||||
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, '/')
|
||||
|
||||
@@ -265,25 +225,17 @@ class _DevFSObject:
|
||||
dir_path = path_copy
|
||||
file_name: str = last_slash + 1
|
||||
|
||||
dir_ptr: devfs_directory | t.CPtr = devfs_directory.find(dir_path, self.root_directory)
|
||||
dir_ptr: devfs_directory* = devfs_directory.find(dir_path, self.root_directory)
|
||||
if not dir_ptr: return -1
|
||||
|
||||
file_ptr: devfs_file | t.CPtr = devfs_file.find_in_dir(file_name, dir_ptr)
|
||||
file_ptr: devfs_file* = devfs_file.find_in_dir(file_name, dir_ptr)
|
||||
if not file_ptr: return -1
|
||||
|
||||
# [DIAG] 定位 vtable 悬垂:打印 file_ptr 与对象首字段(vtable 指针)(用后移除)
|
||||
_dbg_buf: t.CArray[t.CChar, 96]
|
||||
_dbg_vt: uint64 = uint64(file_ptr, t.CPtr)[0]
|
||||
viperlib.snprintf(c.Addr(_dbg_buf), 96, "[open] fp=%lx vt=%lx\n",
|
||||
uint64(file_ptr), _dbg_vt)
|
||||
serial.puts(c.Addr(_dbg_buf))
|
||||
|
||||
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)
|
||||
@@ -296,34 +248,34 @@ class _DevFSObject:
|
||||
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 | t.CPtr = fd_table[fd].file
|
||||
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: t.CPtr, size: uint32) -> int:
|
||||
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 | t.CPtr = fd_table[fd].file
|
||||
file_ptr: devfs_file* = fd_table[fd].file
|
||||
return file_ptr.read(fd, buffer, size)
|
||||
|
||||
def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int:
|
||||
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 | t.CPtr = fd_table[fd].file
|
||||
file_ptr: devfs_file* = fd_table[fd].file
|
||||
return file_ptr.write(fd, buffer, size)
|
||||
|
||||
def ioctl(self, fd: int, cmd: uint32, arg: t.CPtr) -> int:
|
||||
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 | t.CPtr = fd_table[fd].file
|
||||
file_ptr: devfs_file* = fd_table[fd].file
|
||||
return file_ptr.ioctl(fd, cmd, arg)
|
||||
|
||||
def list_directory(self, path: t.CConst | str,
|
||||
def list_directory(self, path: const str,
|
||||
buffer: str,
|
||||
size: uint32) -> int:
|
||||
dir_ptr: devfs_directory | t.CPtr = devfs_directory.find(path, self.root_directory)
|
||||
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)
|
||||
@@ -331,63 +283,58 @@ class _DevFSObject:
|
||||
|
||||
return pos
|
||||
|
||||
DevFSObject: _DevFSObject | t.CPtr
|
||||
DevFSObject: _DevFSObject*
|
||||
_DevFSObject_instance: _DevFSObject
|
||||
|
||||
|
||||
def devfs_init() -> int:
|
||||
global DevFSObject, _DevFSObject_instance
|
||||
DevFSObject = c.Addr(_DevFSObject_instance)
|
||||
DevFSObject = &_DevFSObject_instance
|
||||
_DevFSObject_instance = _DevFSObject()
|
||||
# _DevFSObject_instance.__init__()
|
||||
DevFSObject.init()
|
||||
return 0
|
||||
|
||||
def devfs_create_directory(path: t.CConst | str) -> int:
|
||||
def devfs_create_directory(path: const str) -> int:
|
||||
return DevFSObject.create_directory(path)
|
||||
|
||||
def devfs_create_file(path: t.CConst | str,
|
||||
file_ptr: devfs_file | t.CPtr,
|
||||
private_data: t.CPtr) -> int:
|
||||
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: t.CConst | str, flags: int) -> int:
|
||||
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: t.CPtr, size: uint32) -> int:
|
||||
def devfs_read(fd: int, buffer: rawptr, size: uint32) -> int:
|
||||
return DevFSObject.read(fd, buffer, size)
|
||||
|
||||
def devfs_write(fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int:
|
||||
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: t.CPtr) -> int:
|
||||
def devfs_ioctl(fd: int, cmd: uint32, arg: rawptr) -> int:
|
||||
return DevFSObject.ioctl(fd, cmd, arg)
|
||||
|
||||
def devfs_list_directory(path: t.CConst | str,
|
||||
buffer: str,
|
||||
size: uint32) -> int:
|
||||
def devfs_list_directory(path: const str, buffer: str, size: uint32) -> int:
|
||||
return DevFSObject.list_directory(path, buffer, size)
|
||||
|
||||
serial0_file: devfs_file
|
||||
|
||||
def serial0_open(self: t.CPtr, path: t.CConst | str, flags: int) -> int:
|
||||
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: t.CPtr, fd: int) -> int:
|
||||
def serial0_close(self: rawptr, fd: int) -> int:
|
||||
serial.puts("[serial0] close\n")
|
||||
return 0
|
||||
|
||||
def serial0_read(self: t.CPtr, fd: int, buffer: t.CPtr, size: uint32) -> int:
|
||||
def serial0_read(self: rawptr, fd: int, buffer: rawptr, size: uint32) -> int:
|
||||
serial.puts("[serial0] read\n")
|
||||
return 0
|
||||
|
||||
def serial0_write(self: t.CPtr, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int:
|
||||
def serial0_write(self: rawptr, fd: int, buffer: const rawptr, size: uint32) -> int:
|
||||
serial.puts("[serial0] write\n")
|
||||
serial.puts(str(buffer))
|
||||
serial.puts("\n")
|
||||
@@ -402,10 +349,9 @@ def devfs_register_serial0() -> int:
|
||||
serial0_file.write = serial0_write
|
||||
return devfs_create_file("/dev/serial0", serial0_file, None)
|
||||
|
||||
@t.Object
|
||||
@t.CVTable
|
||||
class serial1_device(devfs_file):
|
||||
def open(self, path: t.CConst | str, flags: int) -> int:
|
||||
|
||||
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")
|
||||
@@ -415,11 +361,11 @@ class serial1_device(devfs_file):
|
||||
serial.puts("[serial1] close\n")
|
||||
return 0
|
||||
|
||||
def read(self, fd: int, buffer: t.CPtr, size: uint32) -> int:
|
||||
def read(self, fd: int, buffer: rawptr, size: uint32) -> int:
|
||||
serial.puts("[serial1] read\n")
|
||||
return 0
|
||||
|
||||
def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int:
|
||||
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int:
|
||||
serial.puts("[serial1] write\n")
|
||||
serial.puts(str(buffer))
|
||||
serial.puts("\n")
|
||||
@@ -435,31 +381,28 @@ def devfs_register_serial1() -> int:
|
||||
import drivers.input.keyboard.keyboard as keyboard
|
||||
import drivers.input.mouse.mouse as mouse
|
||||
|
||||
@t.Object
|
||||
@t.CVTable
|
||||
class keyboard_device(devfs_file):
|
||||
def open(self, path: t.CConst | str, flags: int) -> int:
|
||||
|
||||
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: t.CPtr, size: uint32) -> int:
|
||||
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: t.CChar = keyboard.scancode_to_ascii(sc)
|
||||
ch: char = keyboard.scancode_to_ascii(sc)
|
||||
if ch != '\0':
|
||||
# c.Set(t.CChar(...)[count], ch) 是 Subscript 左值,translate_c_set
|
||||
# 不处理 → 静默丢弃。改普通下标赋值(AssignGen 支持 Subscript store)。
|
||||
t.CChar(buffer, t.CPtr)[count] = ch
|
||||
char*(buffer)[count] = ch
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def write(self, fd: int, buffer: t.CConst | t.CPtr, size: uint32) -> int:
|
||||
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int:
|
||||
return -1
|
||||
|
||||
def ioctl(self, fd: int, request: int, arg: t.CPtr) -> int:
|
||||
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
|
||||
return 0
|
||||
|
||||
kbd_file: keyboard_device
|
||||
@@ -470,33 +413,32 @@ def devfs_register_keyboard() -> int:
|
||||
keyboard.init()
|
||||
return devfs_create_file("/dev/input/keyboard", kbd_file, None)
|
||||
|
||||
@t.Object
|
||||
@t.CVTable
|
||||
class mouse_device(devfs_file):
|
||||
def open(self, path: t.CConst | str, flags: int) -> int:
|
||||
|
||||
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: t.CPtr, size: uint32) -> int:
|
||||
def read(self, fd: int, buffer: rawptr, size: uint32) -> int:
|
||||
if not mouse.has_data(): return 0
|
||||
pkt: mouse.mouse_packet
|
||||
mouse.read_packet(c.Addr(pkt))
|
||||
mouse.read_packet(&pkt)
|
||||
if size >= 1:
|
||||
uint8(buffer, t.CPtr)[0] = pkt.buttons
|
||||
# 完整包需要 1(buttons) + 4(x) + 4(y) = 9 字节,否则越界写
|
||||
uint8*(buffer)[0] = pkt.buttons
|
||||
|
||||
if size >= 9:
|
||||
buf: uint32 | t.CPtr = t.CPtr(uint64(buffer) + 1)
|
||||
int32(buf, t.CPtr)[0] = mouse.get_x()
|
||||
int32(buf, t.CPtr)[1] = mouse.get_y()
|
||||
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: t.CConst | t.CPtr, size: uint32) -> int:
|
||||
def write(self, fd: int, buffer: const rawptr, size: uint32) -> int:
|
||||
return -1
|
||||
|
||||
def ioctl(self, fd: int, request: int, arg: t.CPtr) -> int:
|
||||
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
|
||||
return 0
|
||||
|
||||
mse_file: mouse_device
|
||||
|
||||
@@ -4,10 +4,9 @@ import fat32_types as types
|
||||
import fat32_part as part
|
||||
import fat32_mkfs as mkfs_mod
|
||||
import string
|
||||
import t, c
|
||||
|
||||
|
||||
def print_fresult(res: types.FRESULT, msg: t.CConst | str) -> int:
|
||||
def print_fresult(res: types.FRESULT, msg: const str) -> int:
|
||||
if res == types.FRESULT.FR_OK:
|
||||
print(f"[成功] {msg}")
|
||||
return 0
|
||||
@@ -16,7 +15,7 @@ def print_fresult(res: types.FRESULT, msg: t.CConst | str) -> int:
|
||||
return -1
|
||||
|
||||
|
||||
def print_fresult_void(res: types.FRESULT, msg: t.CConst | str):
|
||||
def print_fresult_void(res: types.FRESULT, msg: const str):
|
||||
print_fresult(res, msg)
|
||||
|
||||
|
||||
@@ -33,7 +32,7 @@ def example_main() -> int:
|
||||
print(f"找到 {drive_count} 个驱动器")
|
||||
i: int
|
||||
for i in range(drive_count):
|
||||
letter: t.CChar = fs.get_drive_letter(i)
|
||||
letter: char = fs.get_drive_letter(i)
|
||||
part_count: int = fs.get_partition_count(letter)
|
||||
print(f" 驱动器 {i}: {letter}")
|
||||
for j in range(part_count):
|
||||
@@ -97,36 +96,36 @@ def example_main() -> int:
|
||||
print("--- 7. 文件操作 ---")
|
||||
|
||||
# 创建并写入文件
|
||||
fp1: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE)
|
||||
fp1: types.fileobj* = fs.open("/test_dir_1/file1.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE)
|
||||
if fp1 is not None:
|
||||
test_data1: t.CConst | str = "Hello, World!"
|
||||
test_data1: const str = "Hello, World!"
|
||||
written: uint32 = fs.write(fp1, test_data1, 13)
|
||||
print(f"写入文件 /test_dir_1/file1.txt: {written} 字节")
|
||||
fs.close(fp1)
|
||||
|
||||
# 打开追加
|
||||
fp2: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_ALWAYS | types.FA_WRITE | types.FA_OPEN_APPEND)
|
||||
fp2: types.fileobj* = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_ALWAYS | types.FA_WRITE | types.FA_OPEN_APPEND)
|
||||
if fp2 is not None:
|
||||
test_data2: t.CConst | str = " Append data!"
|
||||
test_data2: const str = " Append data!"
|
||||
written2: uint32 = fs.write(fp2, test_data2, 13)
|
||||
print(f"追加写入: {written2} 字节")
|
||||
fs.close(fp2)
|
||||
|
||||
# 读取文件
|
||||
fp3: types.fileobj | t.CPtr = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_EXISTING | types.FA_READ)
|
||||
fp3: types.fileobj* = fs.open("/test_dir_1/file1.txt", types.FA_OPEN_EXISTING | types.FA_READ)
|
||||
if fp3 is not None:
|
||||
buf: t.CArray[uint8, 256]
|
||||
read_bytes: uint32 = fs.read(fp3, c.Addr(buf[0]), 256)
|
||||
buf: [256]uint8
|
||||
read_bytes: uint32 = fs.read(fp3, &buf[0], 256)
|
||||
print(f"读取字节数: {read_bytes}")
|
||||
print(f"文件内容: {t.CChar(c.Addr(buf[0]), t.CPtr)}")
|
||||
print(f"文件内容: {str(&buf[0])}")
|
||||
|
||||
# seek 和 tell
|
||||
fs.seek(fp3, 5)
|
||||
pos: uint32 = fs.tell(fp3)
|
||||
print(f"seek 到位置 5, 当前位置: {pos}")
|
||||
|
||||
read_bytes2: uint32 = fs.read(fp3, c.Addr(buf[0]), 256)
|
||||
print(f"从位置 5 读取: {t.CChar(c.Addr(buf[0]), t.CPtr)}")
|
||||
read_bytes2: uint32 = fs.read(fp3, &buf[0], 256)
|
||||
print(f"从位置 5 读取: {str(&buf[0])}")
|
||||
|
||||
# 获取文件大小
|
||||
fsize: uint32 = fs.size(fp3)
|
||||
@@ -135,13 +134,13 @@ def example_main() -> int:
|
||||
fs.close(fp3)
|
||||
|
||||
# 创建另一个文件
|
||||
fp4: types.fileobj | t.CPtr = fs.open("/test_dir_1/large_file.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE)
|
||||
fp4: types.fileobj* = fs.open("/test_dir_1/large_file.txt", types.FA_CREATE_ALWAYS | types.FA_WRITE)
|
||||
if fp4 is not None:
|
||||
large_data: t.CArray[uint8, 1024]
|
||||
large_data: [1024]uint8
|
||||
k: int
|
||||
for k in range(1024):
|
||||
large_data[k] = uint8(ord('A') + (k % 26))
|
||||
written3: uint32 = fs.write(fp4, c.Addr(large_data[0]), 1024)
|
||||
written3: uint32 = fs.write(fp4, &large_data[0], 1024)
|
||||
print(f"创建大文件, 写入: {written3} 字节")
|
||||
fs.close(fp4)
|
||||
print()
|
||||
@@ -150,7 +149,7 @@ def example_main() -> int:
|
||||
print("--- 8. 文件状态和属性 ---")
|
||||
|
||||
info: types.fileinfo
|
||||
res = fs.stat("/test_dir_1/file1.txt", c.Addr(info))
|
||||
res = fs.stat("/test_dir_1/file1.txt", &info)
|
||||
print_fresult_void(res, "获取文件信息")
|
||||
if res == types.FRESULT.FR_OK:
|
||||
print(f" 文件名: {info.fname}")
|
||||
@@ -184,15 +183,15 @@ def example_main() -> int:
|
||||
print("--- 10. 列出目录 ---")
|
||||
|
||||
dp: types.dirobj
|
||||
res = fs.opendir("/", c.Addr(dp))
|
||||
res = fs.opendir("/", &dp)
|
||||
if res == types.FRESULT.FR_OK:
|
||||
print("根目录内容:")
|
||||
dir_info: types.fileinfo
|
||||
while True:
|
||||
res = fs.readdir(c.Addr(dp), c.Addr(dir_info))
|
||||
res = fs.readdir(&dp, &dir_info)
|
||||
if res != types.FRESULT.FR_OK:
|
||||
break
|
||||
attr_str: t.CArray[t.CChar, 8] = [0]
|
||||
attr_str: [8]char = [0]
|
||||
if dir_info.attr & types.AM_DIR:
|
||||
string.strcat(attr_str, "D")
|
||||
else:
|
||||
@@ -206,7 +205,7 @@ def example_main() -> int:
|
||||
if dir_info.attr & types.AM_ARC:
|
||||
string.strcat(attr_str, "A")
|
||||
print(f" [{attr_str}] {dir_info.fname} ({dir_info.file_size} 字节)")
|
||||
fs.closedir(c.Addr(dp))
|
||||
fs.closedir(&dp)
|
||||
print()
|
||||
|
||||
# 11. 删除文件和目录
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
from stdint import *
|
||||
import string
|
||||
import fat32_types as types
|
||||
import fat32_time as ftime
|
||||
import fat32_mkfs as mkfs_mod
|
||||
import fat32_part as part
|
||||
import fat32_diskio as diskio
|
||||
import sched.sched as sched
|
||||
import viperlib
|
||||
import drivers.serial.uart.serial as serial
|
||||
import t, c
|
||||
|
||||
|
||||
default_fs: types.volinfo = types.volinfo()
|
||||
@@ -17,12 +13,12 @@ _fs_lock: int = 0
|
||||
def lock():
|
||||
global _fs_lock
|
||||
while True:
|
||||
c.Asm("cli")
|
||||
__asm__("cli")
|
||||
if _fs_lock == 0:
|
||||
_fs_lock = 1
|
||||
c.Asm("sti")
|
||||
__asm__("sti")
|
||||
return
|
||||
c.Asm("sti")
|
||||
__asm__("sti")
|
||||
sched.Scheduler._yield()
|
||||
|
||||
def unlock():
|
||||
@@ -32,8 +28,8 @@ def unlock():
|
||||
def mount() -> types.FRESULT:
|
||||
default_fs.pdrv = 0
|
||||
default_fs.hidden_sectors = 0
|
||||
buf: t.CArray[uint8, 512]
|
||||
dres: types.DRESULT = diskio.read(0, c.Addr(buf[0]), 0, 1)
|
||||
buf: [512]uint8
|
||||
dres: types.DRESULT = diskio.read(0, &buf[0], 0, 1)
|
||||
if dres == types.DRESULT.RES_OK:
|
||||
if buf[0] == 0xEB or buf[0] == 0xE9:
|
||||
default_fs.hidden_sectors = 0
|
||||
@@ -100,69 +96,65 @@ def unmount() -> types.FRESULT:
|
||||
def format(sec_per_clus: uint8 = 0, vol_id: uint32 = 0) -> types.FRESULT:
|
||||
return mkfs_mod.mkfs(default_fs.pdrv, sec_per_clus, vol_id)
|
||||
|
||||
def open(path: t.CConst | str, mode: uint8) -> types.fileobj | t.CPtr:
|
||||
def open(path: const str, mode: uint8) -> types.fileobj*:
|
||||
return default_fs.file_open(path, mode)
|
||||
|
||||
def close(fp: types.fileobj | t.CPtr) -> types.FRESULT:
|
||||
def close(fp: types.fileobj*) -> types.FRESULT:
|
||||
return fp.close()
|
||||
|
||||
def read(fp: types.fileobj | t.CPtr, buff: t.CPtr, btr: uint32) -> uint32:
|
||||
def read(fp: types.fileobj*, buff: rawptr, btr: uint32) -> uint32:
|
||||
br: uint32 = 0
|
||||
fp.read(buff, btr, c.Addr(br))
|
||||
# [RD2-DIAG] 确认 br 是否被 c.Set 写入(types 内 total_read=64 但外部可能收不到)
|
||||
_rd2: t.CArray[t.CChar, 96]
|
||||
viperlib.snprintf(c.Addr(_rd2), 96, "[fat32.vp] read br=%lu\n", br)
|
||||
serial.puts(c.Addr(_rd2))
|
||||
fp.read(buff, btr, &br)
|
||||
return br
|
||||
|
||||
def write(fp: types.fileobj | t.CPtr, buff: t.CConst | t.CPtr, btw: uint32) -> uint32:
|
||||
def write(fp: types.fileobj*, buff: const rawptr, btw: uint32) -> uint32:
|
||||
bw: uint32 = 0
|
||||
fp.write(buff, btw, c.Addr(bw))
|
||||
fp.write(buff, btw, &bw)
|
||||
return bw
|
||||
|
||||
def seek(fp: types.fileobj | t.CPtr, offset: uint32) -> types.FRESULT:
|
||||
def seek(fp: types.fileobj*, offset: uint32) -> types.FRESULT:
|
||||
return fp.seek(offset)
|
||||
|
||||
def tell(fp: types.fileobj | t.CPtr) -> uint32:
|
||||
def tell(fp: types.fileobj*) -> uint32:
|
||||
return fp.tell()
|
||||
|
||||
def size(fp: types.fileobj | t.CPtr) -> uint32:
|
||||
def size(fp: types.fileobj*) -> uint32:
|
||||
return fp.size()
|
||||
|
||||
def truncate(fp: types.fileobj | t.CPtr) -> types.FRESULT:
|
||||
def truncate(fp: types.fileobj*) -> types.FRESULT:
|
||||
return fp.truncate()
|
||||
|
||||
def remove(path: t.CConst | str) -> types.FRESULT:
|
||||
def remove(path: const str) -> types.FRESULT:
|
||||
return default_fs.file_delete(path)
|
||||
|
||||
def rename(old_path: t.CConst | str, new_path: t.CConst | str) -> types.FRESULT:
|
||||
def rename(old_path: const str, new_path: const str) -> types.FRESULT:
|
||||
return default_fs.file_rename(old_path, new_path)
|
||||
|
||||
def move(old_path: t.CConst | str, new_path: t.CConst | str) -> types.FRESULT:
|
||||
def move(old_path: const str, new_path: const str) -> types.FRESULT:
|
||||
return default_fs.file_rename(old_path, new_path)
|
||||
|
||||
def stat(path: t.CConst | str, info: types.fileinfo | t.CPtr) -> types.FRESULT:
|
||||
def stat(path: const str, info: types.fileinfo*) -> types.FRESULT:
|
||||
return default_fs.file_stat(path, info)
|
||||
|
||||
def mkdir(path: t.CConst | str) -> types.FRESULT:
|
||||
def mkdir(path: const str) -> types.FRESULT:
|
||||
return default_fs.dir_make(path)
|
||||
|
||||
def rmdir(path: t.CConst | str) -> types.FRESULT:
|
||||
def rmdir(path: const str) -> types.FRESULT:
|
||||
return default_fs.dir_remove(path)
|
||||
|
||||
def opendir(path: t.CConst | str, dp: types.dirobj | t.CPtr) -> types.FRESULT:
|
||||
def opendir(path: const str, dp: types.dirobj*) -> types.FRESULT:
|
||||
return default_fs.dir_open_path(path, dp)
|
||||
|
||||
def readdir(dp: types.dirobj | t.CPtr, info: types.fileinfo | t.CPtr) -> types.FRESULT:
|
||||
def readdir(dp: types.dirobj*, info: types.fileinfo*) -> types.FRESULT:
|
||||
return default_fs.dir_read(dp, info)
|
||||
|
||||
def closedir(dp: types.dirobj | t.CPtr):
|
||||
def closedir(dp: types.dirobj*):
|
||||
dp.is_open = 0
|
||||
|
||||
def chmod(path: t.CConst | str, attr: uint8, mask: uint8) -> types.FRESULT:
|
||||
def chmod(path: const str, attr: uint8, mask: uint8) -> types.FRESULT:
|
||||
return default_fs.chmod(path, attr, mask)
|
||||
|
||||
def utime(path: t.CConst | str, mtime: uint16, mdate: uint16) -> types.FRESULT:
|
||||
def utime(path: const str, mtime: uint16, mdate: uint16) -> types.FRESULT:
|
||||
return default_fs.utime(path, mtime, mdate)
|
||||
|
||||
def get_free() -> uint32:
|
||||
@@ -200,15 +192,15 @@ def scan_drives() -> types.FRESULT:
|
||||
def get_drive_count() -> int:
|
||||
return part.get_drive_count()
|
||||
|
||||
def get_drive_letter(idx: int) -> t.CChar:
|
||||
def get_drive_letter(idx: int) -> char:
|
||||
return part.get_drive_letter(idx)
|
||||
|
||||
def set_drive_letter(idx: int, letter: t.CChar) -> types.FRESULT:
|
||||
def set_drive_letter(idx: int, letter: char) -> types.FRESULT:
|
||||
return part.set_drive_letter(idx, letter)
|
||||
|
||||
def get_partition_count(letter: t.CChar) -> int:
|
||||
def get_partition_count(letter: char) -> int:
|
||||
return part.get_partition_count(letter)
|
||||
|
||||
def is_partition_fat32(letter: t.CChar, part_idx: int) -> int:
|
||||
def is_partition_fat32(letter: char, part_idx: int) -> int:
|
||||
return part.is_partition_fat32(letter, part_idx)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from stdint import *
|
||||
import fat32_types as types
|
||||
import t, c
|
||||
|
||||
|
||||
_read32 = types._read32
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from stdint import *
|
||||
import fat32_types as types
|
||||
import t, c
|
||||
|
||||
|
||||
sfn_checksum = types.sfn_checksum
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import drivers.storage.ide.ide as ide
|
||||
import fat32_types as types
|
||||
import spinlock
|
||||
import string
|
||||
import t, c
|
||||
|
||||
|
||||
MAX_DRIVES: t.CDefine = 4
|
||||
define MAX_DRIVES = 4
|
||||
|
||||
drive_initialized: t.CArray[int, MAX_DRIVES]
|
||||
drive_initialized: [MAX_DRIVES]int
|
||||
drive_lock: spinlock._spinlock = spinlock._spinlock()
|
||||
|
||||
def status(pdrv: uint8) -> types.DRESULT:
|
||||
@@ -28,7 +26,7 @@ def init(pdrv: uint8) -> types.DRESULT:
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
def read(pdrv: uint8, buff: uint8 | t.CPtr, sector: uint32, count: uint32) -> types.DRESULT:
|
||||
def read(pdrv: uint8, buff: uint8*, sector: uint32, count: uint32) -> types.DRESULT:
|
||||
global drive_initialized, drive_lock
|
||||
if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR
|
||||
if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY
|
||||
@@ -42,7 +40,7 @@ def read(pdrv: uint8, buff: uint8 | t.CPtr, sector: uint32, count: uint32) -> ty
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
def write(pdrv: uint8, buff: t.CConst | uint8 | t.CPtr, sector: uint32, count: uint32) -> types.DRESULT:
|
||||
def write(pdrv: uint8, buff: const uint8*, sector: uint32, count: uint32) -> types.DRESULT:
|
||||
global drive_initialized, drive_lock
|
||||
if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR
|
||||
if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY
|
||||
@@ -55,7 +53,7 @@ def write(pdrv: uint8, buff: t.CConst | uint8 | t.CPtr, sector: uint32, count: u
|
||||
drive_lock.unlock()
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
def ioctl(pdrv: uint8, cmd: uint8, buff: t.CPtr) -> types.DRESULT:
|
||||
def ioctl(pdrv: uint8, cmd: uint8, buff: rawptr) -> types.DRESULT:
|
||||
global drive_initialized
|
||||
if pdrv >= MAX_DRIVES: return types.DRESULT.RES_PARERR
|
||||
if not drive_initialized[pdrv]: return types.DRESULT.RES_NOTRDY
|
||||
@@ -63,17 +61,17 @@ def ioctl(pdrv: uint8, cmd: uint8, buff: t.CPtr) -> types.DRESULT:
|
||||
case types.GET_SECTOR_COUNT:
|
||||
disk_size: uint64 = ide.getDiskSize()
|
||||
if disk_size == 0:
|
||||
c.Set(c.Deref(uint32(buff, t.CPtr)), 131072)
|
||||
*(uint32*(buff)) = 131072
|
||||
elif disk_size > 0xFFFFFFFF:
|
||||
c.Set(c.Deref(uint32(buff, t.CPtr)), 0xFFFFFFFF)
|
||||
*(uint32*(buff)) = 0xFFFFFFFF
|
||||
else:
|
||||
c.Set(c.Deref(uint32(buff, t.CPtr)), uint32(disk_size))
|
||||
*(uint32*(buff)) = uint32(disk_size)
|
||||
return types.DRESULT.RES_OK
|
||||
case types.GET_SECTOR_SIZE:
|
||||
c.Set(c.Deref(uint16(buff, t.CPtr)), 512)
|
||||
*(uint16*(buff)) = 512
|
||||
return types.DRESULT.RES_OK
|
||||
case types.GET_BLOCK_SIZE:
|
||||
c.Set(c.Deref(uint32(buff, t.CPtr)), 1)
|
||||
*(uint32*(buff)) = 1
|
||||
return types.DRESULT.RES_OK
|
||||
case types.CTRL_SYNC:
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
@@ -3,7 +3,6 @@ import fat32_types as types
|
||||
import fat32_diskio as diskio
|
||||
import fat32_time as ftime
|
||||
import string
|
||||
import t, c
|
||||
|
||||
|
||||
def _div_round_up(a: uint64, b: uint64) -> uint64:
|
||||
@@ -22,30 +21,30 @@ def _calc_fat_size(total_sectors: uint64, reserved: uint32, sec_per_clus: uint8,
|
||||
|
||||
def _write_boot_sector(pdrv: uint8, total_sectors: uint64, sec_per_clus: uint8, vol_id: uint32, fat_sz: uint32) -> types.DRESULT:
|
||||
buf: t.CArray[uint8, 512]
|
||||
string.memset(c.Addr(buf[0]), 0, 512)
|
||||
string.memset(&buf[0], 0, 512)
|
||||
buf[0] = 0xEB; buf[1] = 0x58; buf[2] = 0x90
|
||||
buf[3] = 'M'; buf[4] = 'S'; buf[5] = 'W'; buf[6] = 'I'; buf[7] = 'N'
|
||||
buf[8] = '4'; buf[9] = '.'; buf[10] = '1'
|
||||
types._write16(c.Addr(buf[0]), 11, 512)
|
||||
types._write16(&buf[0], 11, 512)
|
||||
buf[13] = sec_per_clus
|
||||
types._write16(c.Addr(buf[0]), 14, 32)
|
||||
types._write16(&buf[0], 14, 32)
|
||||
buf[16] = 2
|
||||
types._write16(c.Addr(buf[0]), 17, 0)
|
||||
types._write16(&buf[0], 17, 0)
|
||||
buf[21] = 0xF8
|
||||
types._write16(c.Addr(buf[0]), 22, 0)
|
||||
types._write16(c.Addr(buf[0]), 24, 63)
|
||||
types._write16(c.Addr(buf[0]), 26, 255)
|
||||
types._write32(c.Addr(buf[0]), 28, 0)
|
||||
types._write32(c.Addr(buf[0]), 32, uint32(total_sectors))
|
||||
types._write32(c.Addr(buf[0]), 36, fat_sz)
|
||||
types._write16(c.Addr(buf[0]), 40, 0)
|
||||
types._write16(c.Addr(buf[0]), 42, 0)
|
||||
types._write32(c.Addr(buf[0]), 44, 2)
|
||||
types._write16(c.Addr(buf[0]), 48, 1)
|
||||
types._write16(c.Addr(buf[0]), 50, 6)
|
||||
types._write16(&buf[20], 22, 0)
|
||||
types._write16(&buf[0], 24, 63)
|
||||
types._write16(&buf[0], 26, 255)
|
||||
types._write32(&buf[0], 28, 0)
|
||||
types._write32(&buf[0], 32, uint32(total_sectors))
|
||||
types._write32(&buf[0], 36, fat_sz)
|
||||
types._write16(&buf[0], 40, 0)
|
||||
types._write16(&buf[0], 42, 0)
|
||||
types._write32(&buf[0], 44, 2)
|
||||
types._write16(&buf[0], 48, 1)
|
||||
types._write16(&buf[0], 50, 6)
|
||||
buf[64] = 0x80
|
||||
buf[66] = 0x29
|
||||
types._write32(c.Addr(buf[0]), 67, vol_id)
|
||||
types._write32(&buf[0], 67, vol_id)
|
||||
vol_label: t.CArray[t.CChar, 11]
|
||||
vol_label[0] = 'N'; vol_label[1] = 'O'; vol_label[2] = ' '; vol_label[3] = ' '
|
||||
vol_label[4] = ' '; vol_label[5] = ' '; vol_label[6] = ' '; vol_label[7] = ' '
|
||||
@@ -55,45 +54,45 @@ def _write_boot_sector(pdrv: uint8, total_sectors: uint64, sec_per_clus: uint8,
|
||||
buf[82] = 'F'; buf[83] = 'A'; buf[84] = 'T'; buf[85] = '3'
|
||||
buf[86] = '2'; buf[87] = ' '; buf[88] = ' '; buf[89] = ' '
|
||||
buf[510] = 0x55; buf[511] = 0xAA
|
||||
return diskio.write(pdrv, c.Addr(buf[0]), 0, 1)
|
||||
return diskio.write(pdrv, &buf[0], 0, 1)
|
||||
|
||||
def _write_fsinfo(pdrv: uint8, free_count: uint32, next_free: uint32) -> types.DRESULT:
|
||||
buf: t.CArray[uint8, 512]
|
||||
string.memset(c.Addr(buf[0]), 0, 512)
|
||||
types._write32(c.Addr(buf[0]), 0, 0x41615252)
|
||||
types._write32(c.Addr(buf[0]), 484, 0x61417272)
|
||||
types._write32(c.Addr(buf[0]), 488, free_count)
|
||||
types._write32(c.Addr(buf[0]), 492, next_free)
|
||||
types._write32(c.Addr(buf[0]), 508, 0xAA550000)
|
||||
return diskio.write(pdrv, c.Addr(buf[0]), 1, 1)
|
||||
string.memset(&buf[0], 0, 512)
|
||||
types._write32(&buf[0], 0, 0x41615252)
|
||||
types._write32(&buf[0], 484, 0x61417272)
|
||||
types._write32(&buf[0], 488, free_count)
|
||||
types._write32(&buf[0], 492, next_free)
|
||||
types._write32(&buf[0], 508, 0xAA550000)
|
||||
return diskio.write(pdrv, &buf[0], 1, 1)
|
||||
|
||||
def _init_fat(pdrv: uint8, fat_start: uint64, fat_sz: uint32, root_cluster: uint32) -> types.DRESULT:
|
||||
buf: t.CArray[uint8, 512]
|
||||
string.memset(c.Addr(buf[0]), 0, 512)
|
||||
types._write32(c.Addr(buf[0]), 0, 0x0FFFFFF8)
|
||||
types._write32(c.Addr(buf[0]), 4, 0x0FFFFFFF)
|
||||
types._write32(c.Addr(buf[0]), 8, 0x0FFFFFFF)
|
||||
string.memset(&buf[0], 0, 512)
|
||||
types._write32(&buf[0], 0, 0x0FFFFFF8)
|
||||
types._write32(&buf[0], 4, 0x0FFFFFFF)
|
||||
types._write32(&buf[0], 8, 0x0FFFFFFF)
|
||||
if root_cluster >= 2:
|
||||
cluster_off: uint32 = root_cluster * 4
|
||||
sector_off: uint32 = cluster_off / 512
|
||||
byte_off: uint32 = cluster_off % 512
|
||||
if sector_off == 0:
|
||||
types._write32(c.Addr(buf[0]), byte_off, 0x0FFFFFFF)
|
||||
res: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), uint32(fat_start), 1)
|
||||
types._write32(&buf[0], byte_off, 0x0FFFFFFF)
|
||||
res: types.DRESULT = diskio.write(pdrv, &buf[0], uint32(fat_start), 1)
|
||||
if res != types.DRESULT.RES_OK: return res
|
||||
string.memset(c.Addr(buf[0]), 0, 512)
|
||||
string.memset(&buf[0], 0, 512)
|
||||
s: uint32
|
||||
for s in range(1, fat_sz):
|
||||
res2: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), uint32(fat_start) + s, 1)
|
||||
res2: types.DRESULT = diskio.write(pdrv, &buf[0], uint32(fat_start) + s, 1)
|
||||
if res2 != types.DRESULT.RES_OK: return res2
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
def _init_root_dir(pdrv: uint8, root_sector: uint64, sec_per_clus: uint8) -> types.DRESULT:
|
||||
buf: t.CArray[uint8, 512]
|
||||
string.memset(c.Addr(buf[0]), 0, 512)
|
||||
string.memset(&buf[0], 0, 512)
|
||||
s: uint8
|
||||
for s in range(sec_per_clus):
|
||||
res: types.DRESULT = diskio.write(pdrv, c.Addr(buf[0]), uint32(root_sector + uint64(s)), 1)
|
||||
res: types.DRESULT = diskio.write(pdrv, &buf[0], uint32(root_sector + uint64(s)), 1)
|
||||
if res != types.DRESULT.RES_OK: return res
|
||||
return types.DRESULT.RES_OK
|
||||
|
||||
@@ -108,7 +107,7 @@ def _calc_sec_per_clus(total_sectors: uint64) -> uint8:
|
||||
def mkfs(pdrv: uint8, sec_per_clus: uint8, vol_id: uint32) -> types.FRESULT:
|
||||
if pdrv != types.DEV_DISK: return types.FRESULT.FR_INVALID_DRIVE
|
||||
total_sectors_buf: uint32 = 0
|
||||
diskio.ioctl(pdrv, types.GET_SECTOR_COUNT, c.Addr(total_sectors_buf))
|
||||
diskio.ioctl(pdrv, types.GET_SECTOR_COUNT, &total_sectors_buf)
|
||||
total_sectors: uint64 = uint64(total_sectors_buf)
|
||||
if total_sectors < 65536: return types.FRESULT.FR_MKFS_ABORTED
|
||||
if sec_per_clus == 0: sec_per_clus = _calc_sec_per_clus(total_sectors)
|
||||
@@ -126,11 +125,11 @@ def mkfs(pdrv: uint8, sec_per_clus: uint8, vol_id: uint32) -> types.FRESULT:
|
||||
res2: types.DRESULT = _write_fsinfo(pdrv, free_count, 3)
|
||||
if res2 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR
|
||||
boot_backup: t.CArray[uint8, 512]
|
||||
diskio.read(pdrv, c.Addr(boot_backup[0]), 0, 1)
|
||||
diskio.write(pdrv, c.Addr(boot_backup[0]), 6, 1)
|
||||
diskio.read(pdrv, &boot_backup[0], 0, 1)
|
||||
diskio.write(pdrv, &boot_backup[0], 6, 1)
|
||||
fsinfo_backup: t.CArray[uint8, 512]
|
||||
diskio.read(pdrv, c.Addr(fsinfo_backup[0]), 1, 1)
|
||||
diskio.write(pdrv, c.Addr(fsinfo_backup[0]), 7, 1)
|
||||
diskio.read(pdrv, &fsinfo_backup[0], 1, 1)
|
||||
diskio.write(pdrv, &fsinfo_backup[0], 7, 1)
|
||||
fat_start: uint64 = uint64(reserved)
|
||||
res3: types.DRESULT = _init_fat(pdrv, fat_start, fat_sz, 2)
|
||||
if res3 != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
from stdint import *
|
||||
import fat32_types as types
|
||||
import fat32_diskio as diskio
|
||||
import string
|
||||
import t, c
|
||||
|
||||
|
||||
MAX_VOLUMES: t.CDefine = 4
|
||||
@@ -16,20 +14,21 @@ PART_TYPE_FAT16_LBA: t.CDefine = 0x0E
|
||||
|
||||
class partition_entry:
|
||||
boot_flag: uint8
|
||||
start_chs: t.CArray[uint8, 3]
|
||||
start_chs: [3]uint8
|
||||
part_type: uint8
|
||||
end_chs: t.CArray[uint8, 3]
|
||||
end_chs: [3]uint8
|
||||
start_lba: uint32
|
||||
total_sectors: uint32
|
||||
|
||||
drive_pdrv: t.CArray[uint8, MAX_VOLUMES]
|
||||
drive_num_parts: t.CArray[int, MAX_VOLUMES]
|
||||
drive_letter_map: t.CArray[t.CChar, MAX_VOLUMES]
|
||||
volume_mounted: t.CArray[int, MAX_VOLUMES]
|
||||
part_types: t.CArray[uint8, MAX_VOLUMES * MAX_PARTITIONS]
|
||||
part_start_lbas: t.CArray[uint64, MAX_VOLUMES * MAX_PARTITIONS]
|
||||
part_totals: t.CArray[uint64, MAX_VOLUMES * MAX_PARTITIONS]
|
||||
part_is_fat32: t.CArray[int, MAX_VOLUMES * MAX_PARTITIONS]
|
||||
drive_pdrv: [MAX_VOLUMES]uint8
|
||||
drive_num_parts: [MAX_VOLUMES]int
|
||||
drive_letter_map: [MAX_VOLUMES]char
|
||||
volume_mounted: [MAX_VOLUMES]int
|
||||
part_types: [MAX_VOLUMES * MAX_PARTITIONS]uint8
|
||||
part_start_lbas: [MAX_VOLUMES * MAX_PARTITIONS]uint64
|
||||
part_totals: [MAX_VOLUMES * MAX_PARTITIONS]uint64
|
||||
part_is_fat32: [MAX_VOLUMES * MAX_PARTITIONS]int
|
||||
|
||||
|
||||
num_drives: int = 0
|
||||
|
||||
@@ -37,13 +36,11 @@ def _init():
|
||||
global num_drives, drive_letter_map, volume_mounted, drive_pdrv, drive_num_parts
|
||||
global part_types, part_start_lbas, part_totals, part_is_fat32
|
||||
if num_drives > 0: return
|
||||
i: int
|
||||
for i in range(MAX_VOLUMES):
|
||||
drive_letter_map[i] = 0
|
||||
volume_mounted[i] = 0
|
||||
drive_pdrv[i] = 0
|
||||
drive_num_parts[i] = 0
|
||||
j: int
|
||||
for j in range(MAX_VOLUMES * MAX_PARTITIONS):
|
||||
part_types[j] = 0
|
||||
part_start_lbas[j] = 0
|
||||
@@ -56,8 +53,8 @@ def _part_idx(drive: int, part: int) -> int:
|
||||
def parse_mbr(pdrv: uint8, drive_idx: int) -> types.FRESULT:
|
||||
global num_drives, drive_letter_map, volume_mounted, drive_pdrv, drive_num_parts
|
||||
global part_types, part_start_lbas, part_totals, part_is_fat32
|
||||
buf: t.CArray[uint8, 512]
|
||||
res: types.DRESULT = diskio.read(pdrv, c.Addr(buf[0]), 0, 1)
|
||||
buf: [512]uint8
|
||||
res: types.DRESULT = diskio.read(pdrv, &buf[0], 0, 1)
|
||||
if res != types.DRESULT.RES_OK: return types.FRESULT.FR_DISK_ERR
|
||||
if buf[0] == 0xEB or buf[0] == 0xE9:
|
||||
return types.FRESULT.FR_NO_FILESYSTEM
|
||||
@@ -65,7 +62,6 @@ def parse_mbr(pdrv: uint8, drive_idx: int) -> types.FRESULT:
|
||||
if sig != MBR_SIGNATURE: return types.FRESULT.FR_NO_FILESYSTEM
|
||||
drive_pdrv[drive_idx] = pdrv
|
||||
drive_num_parts[drive_idx] = 0
|
||||
i: int
|
||||
for i in range(4):
|
||||
base: uint32 = 446 + uint32(i * 16)
|
||||
ptype: uint8 = buf[base + 4]
|
||||
@@ -94,7 +90,7 @@ def scan_drives() -> types.FRESULT:
|
||||
if res != types.DRESULT.RES_OK: continue
|
||||
res2: types.FRESULT = parse_mbr(pdrv, num_drives)
|
||||
if res2 == types.FRESULT.FR_OK and drive_num_parts[num_drives] > 0:
|
||||
drive_letter_map[num_drives] = t.CChar(ord('C') + num_drives)
|
||||
drive_letter_map[num_drives] = char(ord('C') + num_drives)
|
||||
else:
|
||||
drive_pdrv[num_drives] = pdrv
|
||||
drive_num_parts[num_drives] = 1
|
||||
@@ -103,37 +99,36 @@ def scan_drives() -> types.FRESULT:
|
||||
part_start_lbas[pidx] = 0
|
||||
part_totals[pidx] = 0
|
||||
part_is_fat32[pidx] = 1
|
||||
drive_letter_map[num_drives] = t.CChar(ord('C') + num_drives)
|
||||
drive_letter_map[num_drives] = char(ord('C') + num_drives)
|
||||
num_drives = num_drives + 1
|
||||
if num_drives >= MAX_VOLUMES: break
|
||||
return types.FRESULT.FR_OK
|
||||
|
||||
def get_drive(letter: t.CChar) -> int:
|
||||
def get_drive(letter: char) -> int:
|
||||
_init()
|
||||
i: int
|
||||
for i in range(num_drives):
|
||||
if drive_letter_map[i] == letter or drive_letter_map[i] == (letter - 32) or drive_letter_map[i] == (letter + 32):
|
||||
return i
|
||||
return -1
|
||||
|
||||
def get_pdrv(letter: t.CChar) -> uint8:
|
||||
def get_pdrv(letter: char) -> uint8:
|
||||
idx: int = get_drive(letter)
|
||||
if idx < 0: return 0
|
||||
return drive_pdrv[idx]
|
||||
|
||||
def get_partition_start(letter: t.CChar, part_idx: int) -> uint64:
|
||||
def get_partition_start(letter: char, part_idx: int) -> uint64:
|
||||
idx: int = get_drive(letter)
|
||||
if idx < 0: return 0
|
||||
if part_idx >= drive_num_parts[idx]: return 0
|
||||
pidx: int = _part_idx(idx, part_idx)
|
||||
return part_start_lbas[pidx]
|
||||
|
||||
def get_partition_count(letter: t.CChar) -> int:
|
||||
def get_partition_count(letter: char) -> int:
|
||||
idx: int = get_drive(letter)
|
||||
if idx < 0: return 0
|
||||
return drive_num_parts[idx]
|
||||
|
||||
def is_partition_fat32(letter: t.CChar, part_idx: int) -> int:
|
||||
def is_partition_fat32(letter: char, part_idx: int) -> int:
|
||||
idx: int = get_drive(letter)
|
||||
if idx < 0: return 0
|
||||
if part_idx >= drive_num_parts[idx]: return 0
|
||||
@@ -143,11 +138,11 @@ def is_partition_fat32(letter: t.CChar, part_idx: int) -> int:
|
||||
def get_drive_count() -> int:
|
||||
return num_drives
|
||||
|
||||
def get_drive_letter(idx: int) -> t.CChar:
|
||||
def get_drive_letter(idx: int) -> char:
|
||||
if idx < 0 or idx >= num_drives: return 0
|
||||
return drive_letter_map[idx]
|
||||
|
||||
def set_drive_letter(idx: int, letter: t.CChar) -> types.FRESULT:
|
||||
def set_drive_letter(idx: int, letter: char) -> types.FRESULT:
|
||||
if idx < 0 or idx >= num_drives: return types.FRESULT.FR_INVALID_PARAMETER
|
||||
drive_letter_map[idx] = letter
|
||||
return types.FRESULT.FR_OK
|
||||
@@ -1,5 +1,4 @@
|
||||
from stdint import *
|
||||
import t, c
|
||||
import asm
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,3 +1 @@
|
||||
import fat32
|
||||
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
import asm
|
||||
import intr.idt as idt
|
||||
import drivers.serial.uart.serial as serial
|
||||
import viperstring as string
|
||||
import string
|
||||
import t, c
|
||||
|
||||
|
||||
KBD_DATA: t.CDefine = 0x60
|
||||
KBD_STATUS: t.CDefine = 0x64
|
||||
KBD_COMMAND: t.CDefine = 0x64
|
||||
define KBD_DATA = 0x60
|
||||
define KBD_STATUS = 0x64
|
||||
define KBD_COMMAND = 0x64
|
||||
|
||||
KBD_BUF_SIZE: t.CDefine = 1024
|
||||
define KBD_BUF_SIZE = 1024
|
||||
|
||||
KEY_RELEASED: t.CDefine = 0x80
|
||||
define KEY_RELEASED = 0x80
|
||||
|
||||
buffer: t.CArray[uint8, KBD_BUF_SIZE]
|
||||
buf_head: t.CStatic | uint32 = 0
|
||||
buf_tail: t.CStatic | uint32 = 0
|
||||
buf_count: t.CStatic | uint32 = 0
|
||||
kbd_irq_cnt: t.CStatic | uint64 = 0
|
||||
buffer: [KBD_BUF_SIZE]uint8
|
||||
buf_head: static uint32 = 0
|
||||
buf_tail: static uint32 = 0
|
||||
buf_count: static uint32 = 0
|
||||
kbd_irq_cnt: static uint64 = 0
|
||||
|
||||
shift_l: t.CStatic | uint8 = 0
|
||||
shift_r: t.CStatic | uint8 = 0
|
||||
ctrl_l: t.CStatic | uint8 = 0
|
||||
alt_l: t.CStatic | uint8 = 0
|
||||
caps_lock: t.CStatic | uint8 = 0
|
||||
shift_l: static uint8 = 0
|
||||
shift_r: static uint8 = 0
|
||||
ctrl_l: static uint8 = 0
|
||||
alt_l: static uint8 = 0
|
||||
caps_lock: static uint8 = 0
|
||||
|
||||
scancode_set1: t.CArray[t.CChar, 128] = [
|
||||
scancode_set1: [128]char = [
|
||||
'\0', '\x1b', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
|
||||
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
|
||||
'\0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', "'", '`', '\0',
|
||||
@@ -37,7 +37,7 @@ scancode_set1: t.CArray[t.CChar, 128] = [
|
||||
'\0'
|
||||
]
|
||||
|
||||
scancode_set1_shift: t.CArray[t.CChar, 128] = [
|
||||
scancode_set1_shift: [128]char = [
|
||||
'\0', '\x1b', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b',
|
||||
'\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
|
||||
'\0', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', '\0',
|
||||
|
||||
@@ -5,15 +5,15 @@ import drivers.serial.uart.serial as serial
|
||||
import t, c
|
||||
|
||||
|
||||
MOUSE_DATA: t.CDefine = 0x60
|
||||
MOUSE_STATUS: t.CDefine = 0x64
|
||||
MOUSE_COMMAND: t.CDefine = 0x64
|
||||
define MOUSE_DATA = 0x60
|
||||
define MOUSE_STATUS = 0x64
|
||||
define MOUSE_COMMAND = 0x64
|
||||
|
||||
MOUSE_BUF_SIZE: t.CDefine = 1024
|
||||
define MOUSE_BUF_SIZE = 1024
|
||||
|
||||
MOUSE_LEFT: t.CDefine = 0x01
|
||||
MOUSE_RIGHT: t.CDefine = 0x02
|
||||
MOUSE_MIDDLE: t.CDefine = 0x04
|
||||
define MOUSE_LEFT = 0x01
|
||||
define MOUSE_RIGHT = 0x02
|
||||
define MOUSE_MIDDLE = 0x04
|
||||
|
||||
class mouse_packet:
|
||||
flags: uint8
|
||||
@@ -21,32 +21,30 @@ class mouse_packet:
|
||||
dy: int8
|
||||
buttons: uint8
|
||||
|
||||
packets: t.CArray[mouse_packet, MOUSE_BUF_SIZE]
|
||||
pack_head: t.CStatic | uint32 = 0
|
||||
pack_tail: t.CStatic | uint32 = 0
|
||||
pack_count: t.CStatic | uint32 = 0
|
||||
mse_irq_cnt: t.CStatic | uint64 = 0
|
||||
packets: [MOUSE_BUF_SIZE]mouse_packet
|
||||
pack_head: static uint32 = 0
|
||||
pack_tail: static uint32 = 0
|
||||
pack_count: static uint32 = 0
|
||||
mse_irq_cnt: static uint64 = 0
|
||||
|
||||
cycle: t.CStatic | uint8 = 0
|
||||
byte1: t.CStatic | uint8 = 0
|
||||
byte2: t.CStatic | int8 = 0
|
||||
byte3: t.CStatic | int8 = 0
|
||||
cycle: static uint8 = 0
|
||||
byte1: static uint8 = 0
|
||||
byte2: static int8 = 0
|
||||
byte3: static int8 = 0
|
||||
|
||||
mouse_x: t.CStatic | int32 = 0
|
||||
mouse_y: t.CStatic | int32 = 0
|
||||
mouse_buttons: t.CStatic | uint8 = 0
|
||||
mouse_x: static int32 = 0
|
||||
mouse_y: static int32 = 0
|
||||
mouse_buttons: static uint8 = 0
|
||||
|
||||
def _wait_read():
|
||||
timeout: uint32 = 100000
|
||||
while timeout > 0:
|
||||
for _ in range(timeout, 0, -1):
|
||||
if (asm.inb(MOUSE_STATUS) & 0x01) != 0: return
|
||||
timeout -= 1
|
||||
|
||||
def _wait_write():
|
||||
timeout: uint32 = 100000
|
||||
while timeout > 0:
|
||||
for _ in range(timeout, 0, -1):
|
||||
if (asm.inb(MOUSE_STATUS) & 0x02) == 0: return
|
||||
timeout -= 1
|
||||
|
||||
def _write_cmd(cmd: uint8):
|
||||
_wait_write()
|
||||
|
||||
@@ -2,75 +2,56 @@ import platform.pch.pic as pic
|
||||
import drivers.serial.uart.su8250 as su8250
|
||||
import asm
|
||||
import viperlib
|
||||
import t, c
|
||||
|
||||
|
||||
# 串口初始化
|
||||
def init():
|
||||
# 初始化COM1端口
|
||||
# Init COM1 port
|
||||
su8250.init(su8250.COM1_PORT)
|
||||
# 启用COM1中断(IRQ4)
|
||||
# COM1(IRQ4)
|
||||
pic.clearMask(4)
|
||||
|
||||
# 发送一个字符到COM1
|
||||
def putc(cr: t.CChar):
|
||||
def putc(cr: char):
|
||||
su8250.putchar(su8250.COM1_PORT, cr)
|
||||
|
||||
def putchar(cr: t.CChar):
|
||||
def putchar(cr: char):
|
||||
su8250.putchar(su8250.COM1_PORT, cr)
|
||||
|
||||
# 从COM1读取一个字符
|
||||
def getchar() -> t.CChar:
|
||||
def getchar() -> char:
|
||||
return su8250.getchar(su8250.COM1_PORT)
|
||||
|
||||
# 发送一个字符串到COM1
|
||||
def puts(s: str):
|
||||
# 逐个字符发送,直接复用putchar的逻辑
|
||||
for i in s:
|
||||
putchar(i)
|
||||
|
||||
# 检查COM1是否有数据可读
|
||||
def isDataAvailable() -> int:
|
||||
return su8250.isDataAvailable(su8250.COM1_PORT)
|
||||
|
||||
# 检查COM1发送缓冲区是否为空
|
||||
def isTransmitEmpty() -> int:
|
||||
return su8250.isTransmitEmpty(su8250.COM1_PORT)
|
||||
|
||||
# 发送32位十六进制值到COM1
|
||||
def put_hex32(value: uint32):
|
||||
hex_digits: t.CArray[t.CChar, None] = ["0123456789ABCDEF"]
|
||||
buffer: t.CArray[t.CChar, 9]
|
||||
hex_digits: []char = ["0123456789ABCDEF"]
|
||||
buffer: [9]char
|
||||
for i in range(7, -1, -1):
|
||||
buffer[i] = hex_digits[value & 0xF]
|
||||
value >>= 4
|
||||
buffer[8] = '\0'
|
||||
puts(buffer)
|
||||
|
||||
|
||||
# 格式化输出到串口(printf 实现,覆盖 libc printf 的裸机缺失)
|
||||
# 内部复用 viperlib.vsnprintf 格式化到栈缓冲,再逐字符送串口。
|
||||
# print(...) 内建映射到 @printf(stdio extern),此定义提供裸机实现。
|
||||
def printf(fmt: t.CConst | str, *args) -> int | t.CExport:
|
||||
export def printf(fmt: const str, *args) -> int:
|
||||
if fmt is None:
|
||||
return 0
|
||||
buf: t.CArray[t.CChar, 1024]
|
||||
n: int = viperlib.vsnprintf(c.Addr(buf), 1024, fmt, args)
|
||||
buf: [1024]char
|
||||
n: int = viperlib.vsnprintf(&buf, 1024, fmt, args)
|
||||
puts(buf)
|
||||
return n
|
||||
|
||||
|
||||
# 刷新输出流:串口是无缓冲直写(putchar 直接写 UART 端口),flush 即空操作。
|
||||
# 覆盖 libc fflush 的裸机缺失(memhub 的诊断/终止路径 call @fflush)。
|
||||
def fflush(stream: t.CConst | t.CPtr) -> int | t.CExport:
|
||||
export def fflush(stream: const rawptr) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
# 系统退出:触发硬件关机(QEMU ACPI/Bochs 关机端口),失败则停机兜底。
|
||||
# 覆盖 libc exit 的裸机缺失(memhub 等致命错误路径 call @exit)。
|
||||
def exit(status: int) -> int | t.CExport:
|
||||
asm.outw(0x604, 0x2000) # QEMU ACPI 关机
|
||||
asm.outw(0xB004, 0x2000) # Bochs/QEMU 备用端口
|
||||
export def exit(status: int) -> int:
|
||||
asm.outw(0x604, 0x2000) # QEMU ACPI shutdown
|
||||
asm.outw(0xB004, 0x2000) # Bochs/QEMU shutdown
|
||||
while True:
|
||||
asm.hlt()
|
||||
return 0
|
||||
@@ -5,38 +5,38 @@ import t, c
|
||||
|
||||
|
||||
# 串口端口定义
|
||||
COM1_PORT: t.CDefine = 0x3F8 # COM1端口地址
|
||||
COM2_PORT: t.CDefine = 0x2F8 # COM2端口地址
|
||||
define COM1_PORT = 0x3F8 # COM1端口地址
|
||||
define COM2_PORT = 0x2F8 # COM2端口地址
|
||||
|
||||
# 8250/16550 UART寄存器偏移
|
||||
UART_RBR: t.CDefine = 0 # 接收缓冲区寄存器(读)
|
||||
UART_THR: t.CDefine = 0 # 发送保持寄存器(写)
|
||||
UART_DLL: t.CDefine = 0 # 除数锁存低位(写,DLAB=1)
|
||||
UART_IER: t.CDefine = 1 # 中断使能寄存器
|
||||
UART_DLM: t.CDefine = 1 # 除数锁存高位(写,DLAB=1)
|
||||
UART_FCR: t.CDefine = 2 # FIFO控制寄存器
|
||||
UART_IIR: t.CDefine = 2 # 中断识别寄存器(读)
|
||||
UART_LCR: t.CDefine = 3 # 线路控制寄存器
|
||||
UART_MCR: t.CDefine = 4 # 调制解调器控制寄存器
|
||||
UART_LSR: t.CDefine = 5 # 线路状态寄存器
|
||||
UART_MSR: t.CDefine = 6 # 调制解调器状态寄存器
|
||||
UART_SCR: t.CDefine = 7 # scratch register
|
||||
define UART_RBR = 0 # 接收缓冲区寄存器(读)
|
||||
define UART_THR = 0 # 发送保持寄存器(写)
|
||||
define UART_DLL = 0 # 除数锁存低位(写,DLAB=1)
|
||||
define UART_IER = 1 # 中断使能寄存器
|
||||
define UART_DLM = 1 # 除数锁存高位(写,DLAB=1)
|
||||
define UART_FCR = 2 # FIFO控制寄存器
|
||||
define UART_IIR = 2 # 中断识别寄存器(读)
|
||||
define UART_LCR = 3 # 线路控制寄存器
|
||||
define UART_MCR = 4 # 调制解调器控制寄存器
|
||||
define UART_LSR = 5 # 线路状态寄存器
|
||||
define UART_MSR = 6 # 调制解调器状态寄存器
|
||||
define UART_SCR = 7 # scratch register
|
||||
|
||||
|
||||
UART_LSR_THRE: t.CDefine = 0x20 # THRE:发送保持寄存器空
|
||||
UART_LSR_TEMT: t.CDefine = 0x40 # TEMT:发送移位寄存器空(真正的发送完成)
|
||||
define UART_LSR_THRE = 0x20 # THRE:发送保持寄存器空
|
||||
define UART_LSR_TEMT = 0x40 # TEMT:发送移位寄存器空(真正的发送完成)
|
||||
|
||||
|
||||
# 线路控制寄存器位定义
|
||||
UART_LCR_DLAB: t.CDefine = 0x80 # 除数锁存访问位
|
||||
UART_LCR_8BIT: t.CDefine = 0x03 # 8位数据位
|
||||
define UART_LCR_DLAB = 0x80 # 除数锁存访问位
|
||||
define UART_LCR_8BIT = 0x03 # 8位数据位
|
||||
|
||||
# 线路状态寄存器位定义
|
||||
UART_LSR_DR: t.CDefine = 0x01 # 数据就绪
|
||||
UART_LSR_THRE: t.CDefine = 0x20 # 发送保持寄存器空
|
||||
define UART_LSR_DR = 0x01 # 数据就绪
|
||||
define UART_LSR_THRE = 0x20 # 发送保持寄存器空
|
||||
|
||||
# 波特率除数(115200 bps)
|
||||
BAUD_115200: t.CDefine = 1
|
||||
define BAUD_115200 = 1
|
||||
|
||||
|
||||
# 初始化UART 8250/16550
|
||||
@@ -70,7 +70,7 @@ def init(port: uint16):
|
||||
|
||||
# 延迟函数
|
||||
def delay(count: int):
|
||||
for i in range(count): c.Asm("nop")
|
||||
for _ in range(count): asm.nop()
|
||||
|
||||
# 检查发送缓冲区是否为空
|
||||
def isTransmitEmpty(port: uint16) -> int:
|
||||
@@ -82,18 +82,18 @@ def putchar(port: uint16, cr: t.CChar):
|
||||
# 直接发送\r,避免递归调用
|
||||
timeout: uint32 = 1000000
|
||||
while ((asm.inb(port + UART_LSR) & UART_LSR_THRE) == 0) and timeout:
|
||||
c.Asm("nop")
|
||||
asm.nop()
|
||||
timeout -= 1
|
||||
if timeout == 0: return
|
||||
asm.outb(port + UART_THR, '\r')
|
||||
timeout = 1000000
|
||||
while ((asm.inb(port + UART_LSR) & UART_LSR_TEMT) == 0) and timeout:
|
||||
c.Asm("nop")
|
||||
asm.nop()
|
||||
timeout -= 1
|
||||
# 2. 等待发送缓冲区为空
|
||||
timeout: uint32 = 1000000
|
||||
while ((asm.inb(port + UART_LSR) & UART_LSR_THRE) == 0) and timeout:
|
||||
c.Asm("nop")
|
||||
asm.nop()
|
||||
timeout -= 1
|
||||
if timeout == 0: return
|
||||
# 3. 发送字符
|
||||
@@ -101,7 +101,7 @@ def putchar(port: uint16, cr: t.CChar):
|
||||
# 4. 等待发送完成
|
||||
timeout = 1000000
|
||||
while ((asm.inb(port + UART_LSR) & UART_LSR_TEMT) == 0) and timeout:
|
||||
c.Asm("nop")
|
||||
asm.nop()
|
||||
timeout -= 1
|
||||
|
||||
# 检查是否有数据可读
|
||||
@@ -109,7 +109,7 @@ def isDataAvailable(port: uint16) -> int:
|
||||
return asm.inb(port + UART_LSR) & UART_LSR_DR
|
||||
|
||||
# 读取一个字符
|
||||
def getchar(port: uint16) -> t.CChar:
|
||||
def getchar(port: uint16) -> char:
|
||||
# 等待数据可用
|
||||
while not isDataAvailable(port): pass
|
||||
# 读取字符
|
||||
|
||||
@@ -1,65 +1,52 @@
|
||||
import asm
|
||||
import t, c
|
||||
import drivers.usb.pci as pci
|
||||
import drivers.serial.uart.serial as serial
|
||||
import viperlib
|
||||
|
||||
|
||||
class IDError(t.CEnum):
|
||||
IDE_ERR_NONE: t.State = 0
|
||||
IDE_ERR_TIMEOUT: t.State
|
||||
IDE_ERR_DEVICE_ERROR: t.State
|
||||
IDE_ERR_DEVICE_BUSY: t.State
|
||||
IDE_ERR_INVALID_PARAM: t.State
|
||||
IDE_ERR_BUFFER_NULL: t.State
|
||||
IDE_ERR_SECTOR_COUNT: t.State
|
||||
IDE_ERR_DEVICE_NOT_READY: t.State
|
||||
IDE_ERR_DEVICE_FAILURE: t.State
|
||||
IDE_ERR_COMMAND_FAILED: t.State
|
||||
IDE_ERR_INVALID_LBA: t.State
|
||||
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
|
||||
|
||||
IDE_baseport_PRIMARY: t.CDefine = 0x1F0
|
||||
IDE_baseport_SECONDARY: t.CDefine = 0x170
|
||||
define IDE_baseport_PRIMARY = 0x1F0
|
||||
define IDE_baseport_SECONDARY = 0x170
|
||||
|
||||
IDE_STATUS_BSY: t.CDefine = 0x80
|
||||
IDE_STATUS_DRDY: t.CDefine = 0x40
|
||||
IDE_STATUS_DF: t.CDefine = 0x20
|
||||
IDE_STATUS_DRQ: t.CDefine = 0x08
|
||||
IDE_STATUS_ERR: t.CDefine = 0x01
|
||||
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
|
||||
|
||||
SECTOR_SIZE: t.CDefine = 512
|
||||
define SECTOR_SIZE = 512
|
||||
|
||||
_ide_initialized: int = 0
|
||||
|
||||
def waitReady(baseport: uint16) -> t.CStatic | IDError:
|
||||
def waitReady(baseport: uint16) -> static IDError:
|
||||
timeout: int = 100000
|
||||
while timeout > 0:
|
||||
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
|
||||
timeout -= 1
|
||||
return IDError.IDE_ERR_TIMEOUT
|
||||
|
||||
def waitDataReady(baseport: uint16) -> t.CStatic | IDError:
|
||||
def waitDataReady(baseport: uint16) -> static IDError:
|
||||
timeout: int = 100000
|
||||
while timeout > 0:
|
||||
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
|
||||
timeout -= 1
|
||||
return IDError.IDE_ERR_TIMEOUT
|
||||
|
||||
def init() -> int:
|
||||
global _ide_initialized
|
||||
if _ide_initialized: return IDError.IDE_ERR_NONE
|
||||
dbg: t.CArray[t.CChar, 120]
|
||||
bus: uint8
|
||||
bus: uint8
|
||||
dev_n: uint8
|
||||
func: uint8
|
||||
func: uint8
|
||||
for bus in range(2):
|
||||
for dev_n in range(32):
|
||||
for func in range(8):
|
||||
@@ -69,28 +56,18 @@ def init() -> int:
|
||||
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))
|
||||
viperlib.snprintf(c.Addr(dbg), 120, "[ide] found at %d:%d:%d cmd=0x%04x\n", int(bus), int(dev_n), int(func), uint32(pci.pci_read16(bus, dev_n, func, 0x04)))
|
||||
serial.puts(dbg)
|
||||
asm.outb(0x3F6, 0x04)
|
||||
i: int
|
||||
for i in range(10000):
|
||||
asm.nop()
|
||||
for _ in range(10000): asm.nop()
|
||||
asm.outb(0x3F6, 0x00)
|
||||
for i in range(10000):
|
||||
asm.nop()
|
||||
for _ in range(10000): asm.nop()
|
||||
status: uint8 = asm.inb(0x1F7)
|
||||
viperlib.snprintf(c.Addr(dbg), 120, "[ide] status=0x%02x\n", uint32(status))
|
||||
serial.puts(dbg)
|
||||
_ide_initialized = 1
|
||||
return IDError.IDE_ERR_NONE
|
||||
|
||||
def readSector(lba: uint32, buffer: t.CPtr) -> int:
|
||||
if buffer is None: return IDError.IDE_ERR_BUFFER_NULL
|
||||
dbg: t.CArray[t.CChar, 120]
|
||||
err: IDError = waitReady(IDE_baseport_PRIMARY)
|
||||
if err != IDError.IDE_ERR_NONE:
|
||||
viperlib.snprintf(c.Addr(dbg), 120, "[readSector] waitReady err=%d\n", int(err))
|
||||
serial.puts(dbg)
|
||||
return err
|
||||
asm.outb(0x3F6, 0x00)
|
||||
asm.outb(0x1F2, 1)
|
||||
@@ -102,21 +79,19 @@ def readSector(lba: uint32, buffer: t.CPtr) -> int:
|
||||
err = waitDataReady(IDE_baseport_PRIMARY)
|
||||
if err != IDError.IDE_ERR_NONE:
|
||||
st: uint8 = asm.inb(0x1F7)
|
||||
viperlib.snprintf(c.Addr(dbg), 120, "[readSector] waitDataReady err=%d status=0x%02x\n", int(err), uint32(st))
|
||||
serial.puts(dbg)
|
||||
return err
|
||||
st2: uint8 = asm.inb(0x1F7)
|
||||
buf: uint16 | t.CPtr = uint16(buffer, t.CPtr)
|
||||
buf: uint16* = uint16*(buffer)
|
||||
for j in range(256):
|
||||
c.Set(c.Deref(buf), asm.inw(0x1F0))
|
||||
*buf = asm.inw(0x1F0)
|
||||
# buf 为字节指针(uint16|t.CPtr → i8*),每次按 u16 读写须前进 2 字节
|
||||
buf = buf + 2
|
||||
first_byte: uint8 = c.Deref(uint8(buffer, t.CPtr))
|
||||
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: t.CConst | t.CPtr) -> int:
|
||||
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
|
||||
@@ -129,11 +104,17 @@ def writeSector(lba: uint32, buffer: t.CConst | t.CPtr) -> int:
|
||||
asm.outb(0x1F7, 0x30)
|
||||
err = waitDataReady(IDE_baseport_PRIMARY)
|
||||
if err != IDError.IDE_ERR_NONE: return err
|
||||
buf: uint16 | t.CPtr = uint16(buffer, t.CPtr)
|
||||
buf: uint16* = uint16*(buffer)
|
||||
for j in range(256):
|
||||
val: uint16 = c.Deref(buf)
|
||||
val: uint16 = *buf
|
||||
asm.outw(0x1F0, val)
|
||||
# buf 为字节指针(uint16|t.CPtr → i8*),每次按 u16 读写须前进 2 字节
|
||||
# [待复核·指针缩放] 下面这行注释声称 "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
|
||||
asm.outb(0x1F7, 0xE7)
|
||||
waitReady(IDE_baseport_PRIMARY)
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
import t, c
|
||||
import drivers.usb.usb as usb
|
||||
|
||||
HID_BOOT_PROTOCOL: t.CDefine = 0
|
||||
HID_REPORT_PROTOCOL: t.CDefine = 1
|
||||
|
||||
HID_KBD_REPORT_SIZE: t.CDefine = 8
|
||||
HID_MOUSE_REPORT_SIZE: t.CDefine = 4
|
||||
define HID_BOOT_PROTOCOL = 0
|
||||
define HID_REPORT_PROTOCOL = 1
|
||||
|
||||
class hid_kbd_report(t.CStruct):
|
||||
define HID_KBD_REPORT_SIZE = 8
|
||||
define HID_MOUSE_REPORT_SIZE = 4
|
||||
|
||||
class hid_kbd_report:
|
||||
modifier: uint8
|
||||
reserved: uint8
|
||||
keycode: t.CArray[uint8, 6]
|
||||
keycode: [6]uint8
|
||||
|
||||
class hid_mouse_report(t.CStruct):
|
||||
class hid_mouse_report:
|
||||
buttons: uint8
|
||||
dx: int8
|
||||
dy: int8
|
||||
wheel: int8
|
||||
|
||||
def init_keyboard(dev: usb.usb_device | t.CPtr) -> int:
|
||||
def init_keyboard(dev: usb.usb_device*) -> int:
|
||||
if dev.iface_class != 0x03: return -1
|
||||
if dev.iface_protocol != 0x01: return -2
|
||||
if dev.ep_in == 0: return -3
|
||||
return 0
|
||||
|
||||
def init_mouse(dev: usb.usb_device | t.CPtr) -> int:
|
||||
def init_mouse(dev: usb.usb_device*) -> int:
|
||||
if dev.iface_class != 0x03: return -1
|
||||
if dev.iface_protocol != 0x02: return -2
|
||||
if dev.ep_in == 0: return -3
|
||||
return 0
|
||||
|
||||
def read_keyboard(dev: usb.usb_device | t.CPtr, report: hid_kbd_report | t.CPtr) -> int:
|
||||
return usb.read_interrupt(dev, c.Addr(report))
|
||||
def read_keyboard(dev: usb.usb_device*, report: hid_kbd_report*) -> int:
|
||||
return usb.read_interrupt(dev, &report) # 存疑
|
||||
|
||||
def read_mouse(dev: usb.usb_device | t.CPtr, report: hid_mouse_report | t.CPtr) -> int:
|
||||
return usb.read_interrupt(dev, c.Addr(report))
|
||||
def read_mouse(dev: usb.usb_device*, report: hid_mouse_report*) -> int:
|
||||
return usb.read_interrupt(dev, &report)
|
||||
@@ -4,28 +4,28 @@ import drivers.usb.hid.hid as hid
|
||||
import drivers.usb.uhci as uhci
|
||||
import drivers.serial.uart.serial as serial
|
||||
|
||||
KBD_BUF_SIZE: t.CDefine = 1024
|
||||
KBD_EVT_PRESS: t.CDefine = 0
|
||||
KBD_EVT_RELEASE: t.CDefine = 1
|
||||
define KBD_BUF_SIZE = 1024
|
||||
define KBD_EVT_PRESS = 0
|
||||
define KBD_EVT_RELEASE = 1
|
||||
|
||||
class usb_kbd_event(t.CStruct):
|
||||
modifier: uint8
|
||||
keycode: uint8
|
||||
class usb_kbd_event:
|
||||
modifier: uint8
|
||||
keycode: uint8
|
||||
event_type: uint8
|
||||
|
||||
kbd_buf: t.CArray[usb_kbd_event, KBD_BUF_SIZE]
|
||||
kbd_buf: [KBD_BUF_SIZE]usb_kbd_event
|
||||
kbd_buf_head: int = 0
|
||||
kbd_buf_tail: int = 0
|
||||
kbd_buf_count: int = 0
|
||||
kbd_dev: usb.usb_device | t.CPtr = None
|
||||
kbd_dev: usb.usb_device* = None
|
||||
kbd_report: hid.hid_kbd_report
|
||||
kbd_prev_keycodes: t.CArray[uint8, 6]
|
||||
kbd_prev_keycodes: [6]uint8
|
||||
kbd_initialized: int = 0
|
||||
kbd_slot_id: int = -1
|
||||
|
||||
def init() -> int:
|
||||
global kbd_dev, kbd_initialized, kbd_slot_id
|
||||
dev: usb.usb_device | t.CPtr = usb.find_hid_device(0x01)
|
||||
dev: usb.usb_device* = usb.find_hid_device(0x01)
|
||||
if dev is None:
|
||||
serial.puts("[usb_kbd] no USB keyboard found\n")
|
||||
return -1
|
||||
@@ -43,13 +43,12 @@ def init() -> int:
|
||||
# 中断传输长度不得超过 kbd_report(8 字节),否则 DMA 越界写全局
|
||||
kbd_pkt_len: uint8 = 8
|
||||
if dev.ep_in_max < 8: kbd_pkt_len = uint8(dev.ep_in_max)
|
||||
uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, kbd_pkt_len, c.Addr(dev.ep_in_toggle), c.Addr(kbd_report))
|
||||
uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, kbd_pkt_len, dev.ep_in_toggle, &kbd_report)
|
||||
return 0
|
||||
|
||||
def _on_int_complete() -> int:
|
||||
global kbd_buf_head, kbd_buf_tail, kbd_buf_count, kbd_prev_keycodes
|
||||
if kbd_initialized == 0: return 0
|
||||
i: int
|
||||
j: int
|
||||
for i in range(6):
|
||||
code: uint8 = kbd_report.keycode[i]
|
||||
@@ -87,11 +86,11 @@ def _on_int_complete() -> int:
|
||||
kbd_buf_count += 1
|
||||
for i in range(6):
|
||||
kbd_prev_keycodes[i] = kbd_report.keycode[i]
|
||||
dev: usb.usb_device | t.CPtr = kbd_dev
|
||||
dev: usb.usb_device* = kbd_dev
|
||||
if dev is not None and kbd_slot_id >= 0:
|
||||
kbd_pkt_len2: uint8 = 8
|
||||
if dev.ep_in_max < 8: kbd_pkt_len2 = uint8(dev.ep_in_max)
|
||||
uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, kbd_pkt_len2, c.Addr(dev.ep_in_toggle), c.Addr(kbd_report))
|
||||
uhci.schedule_int_transfer(kbd_slot_id, dev.addr, dev.ep_in, dev.ls, kbd_pkt_len2, dev.ep_in_toggle, &kbd_report)
|
||||
return 0
|
||||
|
||||
def has_data() -> int:
|
||||
|
||||
@@ -4,26 +4,27 @@ import drivers.usb.hid.hid as hid
|
||||
import drivers.usb.uhci as uhci
|
||||
import drivers.serial.uart.serial as serial
|
||||
|
||||
MOUSE_BUF_SIZE: t.CDefine = 1024
|
||||
|
||||
class usb_mouse_packet(t.CStruct):
|
||||
define MOUSE_BUF_SIZE = 1024
|
||||
|
||||
class usb_mouse_packet:
|
||||
buttons: uint8
|
||||
dx: int16
|
||||
dy: int16
|
||||
wheel: int8
|
||||
dx: int16
|
||||
dy: int16
|
||||
wheel: int8
|
||||
|
||||
mse_buf: t.CArray[usb_mouse_packet, MOUSE_BUF_SIZE]
|
||||
mse_buf_head: int = 0
|
||||
mse_buf_tail: int = 0
|
||||
mse_buf: [MOUSE_BUF_SIZE]usb_mouse_packet
|
||||
mse_buf_head: int = 0
|
||||
mse_buf_tail: int = 0
|
||||
mse_buf_count: int = 0
|
||||
mse_dev: usb.usb_device | t.CPtr = None
|
||||
mse_dev: usb.usb_device* = None
|
||||
mse_report: hid.hid_mouse_report
|
||||
mse_initialized: int = 0
|
||||
mse_slot_id: int = -1
|
||||
|
||||
def init() -> int:
|
||||
global mse_dev, mse_initialized, mse_slot_id
|
||||
dev: usb.usb_device | t.CPtr = usb.find_hid_device(0x02)
|
||||
dev: usb.usb_device* = usb.find_hid_device(0x02)
|
||||
if dev is None:
|
||||
serial.puts("[usb_mse] no USB mouse found\n")
|
||||
return -1
|
||||
@@ -31,9 +32,9 @@ def init() -> int:
|
||||
if hid.init_mouse(dev) != 0:
|
||||
serial.puts("[usb_mse] init failed\n")
|
||||
return -2
|
||||
mse_initialized = 1
|
||||
mse_initialized = 1
|
||||
serial.puts("[usb_mse] initialized\n")
|
||||
mse_slot_id = uhci.register_int_callback(c.Addr(_on_int_complete))
|
||||
mse_slot_id = uhci.register_int_callback(&_on_int_complete)
|
||||
if mse_slot_id < 0:
|
||||
serial.puts("[usb_mse] register callback failed\n")
|
||||
mse_initialized = 0
|
||||
@@ -41,7 +42,7 @@ def init() -> int:
|
||||
# 中断传输长度不得超过 mse_report(4 字节),否则 DMA 越界写全局
|
||||
mse_pkt_len: uint8 = 4
|
||||
if dev.ep_in_max < 4: mse_pkt_len = uint8(dev.ep_in_max)
|
||||
uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, mse_pkt_len, c.Addr(dev.ep_in_toggle), c.Addr(mse_report))
|
||||
uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, mse_pkt_len, dev.ep_in_toggle, &mse_report)
|
||||
return 0
|
||||
|
||||
def _on_int_complete() -> int:
|
||||
@@ -57,18 +58,18 @@ def _on_int_complete() -> int:
|
||||
if mse_buf_tail >= MOUSE_BUF_SIZE:
|
||||
mse_buf_tail = 0
|
||||
mse_buf_count += 1
|
||||
dev: usb.usb_device | t.CPtr = mse_dev
|
||||
dev: usb.usb_device* = mse_dev
|
||||
if dev is not None and mse_slot_id >= 0:
|
||||
mse_pkt_len2: uint8 = 4
|
||||
if dev.ep_in_max < 4: mse_pkt_len2 = uint8(dev.ep_in_max)
|
||||
uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, mse_pkt_len2, c.Addr(dev.ep_in_toggle), c.Addr(mse_report))
|
||||
uhci.schedule_int_transfer(mse_slot_id, dev.addr, dev.ep_in, dev.ls, mse_pkt_len2, dev.ep_in_toggle, &mse_report)
|
||||
return 0
|
||||
|
||||
def has_data() -> int:
|
||||
if mse_buf_count > 0: return 1
|
||||
return 0
|
||||
|
||||
def read_packet(out: usb_mouse_packet | t.CPtr) -> int:
|
||||
def read_packet(out: usb_mouse_packet*) -> int:
|
||||
global mse_buf_head, mse_buf_count
|
||||
if mse_buf_count == 0: return -1
|
||||
out.buttons = mse_buf[mse_buf_head].buttons
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import t, c
|
||||
import asm
|
||||
|
||||
PCI_CONFIG_ADDR: t.CDefine = 0xCF8
|
||||
PCI_CONFIG_DATA: t.CDefine = 0xCFC
|
||||
|
||||
PCI_CLASS_SERIAL_USB: t.CDefine = 0x0C03
|
||||
PCI_CLASS_SERIAL_UHCI: t.CDefine = 0x0C0300
|
||||
PCI_CLASS_SERIAL_OHCI: t.CDefine = 0x0C0310
|
||||
PCI_CLASS_SERIAL_EHCI: t.CDefine = 0x0C0320
|
||||
PCI_CLASS_SERIAL_XHCI: t.CDefine = 0x0C0330
|
||||
define PCI_CONFIG_ADDR = 0xCF8
|
||||
define PCI_CONFIG_DATA = 0xCFC
|
||||
|
||||
PCI_CMD_IO_SPACE: t.CDefine = 0x0001
|
||||
PCI_CMD_BUS_MASTER: t.CDefine = 0x0004
|
||||
define PCI_CLASS_SERIAL_USB = 0x0C03
|
||||
define PCI_CLASS_SERIAL_UHCI = 0x0C0300
|
||||
define PCI_CLASS_SERIAL_OHCI = 0x0C0310
|
||||
define PCI_CLASS_SERIAL_EHCI = 0x0C0320
|
||||
define PCI_CLASS_SERIAL_XHCI = 0x0C0330
|
||||
|
||||
class pci_device(t.CStruct):
|
||||
define PCI_CMD_IO_SPACE = 0x0001
|
||||
define PCI_CMD_BUS_MASTER = 0x0004
|
||||
|
||||
class pci_device:
|
||||
bus: uint8
|
||||
dev: uint8
|
||||
func: uint8
|
||||
@@ -21,7 +22,7 @@ class pci_device(t.CStruct):
|
||||
device_id: uint16
|
||||
class_code: uint32
|
||||
irq: uint8
|
||||
bar: t.CArray[uint32, 6]
|
||||
bar: [6]uint32
|
||||
|
||||
def pci_read32(bus: uint8, dev: uint8, func: uint8, offset: uint8) -> uint32:
|
||||
addr: uint32 = 0x80000000 | (uint32(bus) << 16) | (uint32(dev) << 11) | (uint32(func) << 8) | (uint32(offset) & 0xFC)
|
||||
@@ -52,12 +53,12 @@ def pci_get_class(bus: uint8, dev: uint8, func: uint8) -> uint32:
|
||||
def pci_get_bar(bus: uint8, dev: uint8, func: uint8, bar_idx: uint8) -> uint32:
|
||||
return pci_read32(bus, dev, func, 0x10 + bar_idx * 4)
|
||||
|
||||
def pci_enable_device(dev: pci_device | t.CPtr):
|
||||
def pci_enable_device(dev: pci_device*):
|
||||
cmd: uint16 = pci_read16(dev.bus, dev.dev, dev.func, 0x04)
|
||||
cmd = cmd | PCI_CMD_IO_SPACE | PCI_CMD_BUS_MASTER
|
||||
pci_write32(dev.bus, dev.dev, dev.func, 0x04, uint32(cmd))
|
||||
|
||||
def pci_fill_device(bus: uint8, dev_n: uint8, func: uint8, out: pci_device | t.CPtr):
|
||||
def pci_fill_device(bus: uint8, dev_n: uint8, func: uint8, out: pci_device*):
|
||||
out.bus = bus
|
||||
out.dev = dev_n
|
||||
out.func = func
|
||||
@@ -65,7 +66,6 @@ def pci_fill_device(bus: uint8, dev_n: uint8, func: uint8, out: pci_device | t.C
|
||||
out.device_id = pci_read16(bus, dev_n, func, 0x02)
|
||||
out.class_code = pci_get_class(bus, dev_n, func)
|
||||
out.irq = pci_read8(bus, dev_n, func, 0x3C)
|
||||
i: int
|
||||
for i in range(6):
|
||||
out.bar[i] = pci_get_bar(bus, dev_n, func, uint8(i))
|
||||
|
||||
@@ -84,8 +84,8 @@ def find_uhci() -> uint16:
|
||||
if vendor == 0xFFFF: continue
|
||||
cls: uint32 = pci_get_class(bus, dev_n, func)
|
||||
if cls == PCI_CLASS_SERIAL_UHCI:
|
||||
pci_fill_device(bus, dev_n, func, c.Addr(_uhci_dev))
|
||||
pci_enable_device(c.Addr(_uhci_dev))
|
||||
pci_fill_device(bus, dev_n, func, &_uhci_dev)
|
||||
pci_enable_device(&_uhci_dev)
|
||||
_uhci_found = 1
|
||||
bar: uint32 = _uhci_dev.bar[4]
|
||||
io_base: uint16 = uint16(bar & 0xFFFE)
|
||||
|
||||
+100
-104
@@ -1,7 +1,7 @@
|
||||
import t, c
|
||||
import asm
|
||||
import mm.mm as mm
|
||||
import viperstring as string
|
||||
import string
|
||||
import drivers.serial.uart.serial as serial
|
||||
import platform.pch.timer as timer
|
||||
import intr.idt as idt
|
||||
@@ -9,80 +9,81 @@ import platform.pch.pic as pic
|
||||
import drivers.usb.pci as pci
|
||||
import viperlib
|
||||
|
||||
UHCI_USBCMD: t.CDefine = 0x00
|
||||
UHCI_USBSTS: t.CDefine = 0x02
|
||||
UHCI_USBINTR: t.CDefine = 0x04
|
||||
UHCI_FRNUM: t.CDefine = 0x06
|
||||
UHCI_FLBASEADD: t.CDefine = 0x08
|
||||
UHCI_SOFMOD: t.CDefine = 0x0C
|
||||
UHCI_PORTSC1: t.CDefine = 0x10
|
||||
UHCI_PORTSC2: t.CDefine = 0x12
|
||||
|
||||
UHCI_CMD_RUN: t.CDefine = 0x0001
|
||||
UHCI_CMD_HCRESET: t.CDefine = 0x0002
|
||||
UHCI_CMD_GRESET: t.CDefine = 0x0004
|
||||
UHCI_CMD_MAXPKT: t.CDefine = 0x0080
|
||||
UHCI_CMD_CF: t.CDefine = 0x0040
|
||||
define UHCI_USBCMD = 0x00
|
||||
define UHCI_USBSTS = 0x02
|
||||
define UHCI_USBINTR = 0x04
|
||||
define UHCI_FRNUM = 0x06
|
||||
define UHCI_FLBASEADD = 0x08
|
||||
define UHCI_SOFMOD = 0x0C
|
||||
define UHCI_PORTSC1 = 0x10
|
||||
define UHCI_PORTSC2 = 0x12
|
||||
|
||||
UHCI_STS_HCHALTED: t.CDefine = 0x0020
|
||||
UHCI_STS_USBINT: t.CDefine = 0x0001
|
||||
UHCI_STS_USBERRINT: t.CDefine = 0x0002
|
||||
UHCI_STS_RESUME: t.CDefine = 0x0004
|
||||
UHCI_INTR_TIMEOUT: t.CDefine = 0x0001
|
||||
UHCI_INTR_RESUME: t.CDefine = 0x0002
|
||||
UHCI_INTR_IOC: t.CDefine = 0x0004
|
||||
UHCI_INTR_SHORT: t.CDefine = 0x0008
|
||||
define UHCI_CMD_RUN = 0x0001
|
||||
define UHCI_CMD_HCRESET = 0x0002
|
||||
define UHCI_CMD_GRESET = 0x0004
|
||||
define UHCI_CMD_MAXPKT = 0x0080
|
||||
define UHCI_CMD_CF = 0x0040
|
||||
|
||||
UHCI_PORT_CONNECT: t.CDefine = 0x0001
|
||||
UHCI_PORT_CONNECT_CHANGE: t.CDefine = 0x0002
|
||||
UHCI_PORT_ENABLE: t.CDefine = 0x0004
|
||||
UHCI_PORT_ENABLE_CHANGE: t.CDefine = 0x0008
|
||||
UHCI_PORT_RESET: t.CDefine = 0x0200
|
||||
UHCI_PORT_LOW_SPEED: t.CDefine = 0x0100
|
||||
define UHCI_STS_HCHALTED = 0x0020
|
||||
define UHCI_STS_USBINT = 0x0001
|
||||
define UHCI_STS_USBERRINT = 0x0002
|
||||
define UHCI_STS_RESUME = 0x0004
|
||||
define UHCI_INTR_TIMEOUT = 0x0001
|
||||
define UHCI_INTR_RESUME = 0x0002
|
||||
define UHCI_INTR_IOC = 0x0004
|
||||
define UHCI_INTR_SHORT = 0x0008
|
||||
|
||||
TD_CTRL_ACTIVE: t.CDefine = 0x00800000
|
||||
TD_CTRL_IOC: t.CDefine = 0x01000000
|
||||
TD_CTRL_LS: t.CDefine = 0x04000000
|
||||
TD_CTRL_SPD: t.CDefine = 0x20000000
|
||||
TD_CTRL_CERR_SHIFT: t.CDefine = 27
|
||||
TD_CTRL_CERR_MASK: t.CDefine = 0x18000000
|
||||
define UHCI_PORT_CONNECT = 0x0001
|
||||
define UHCI_PORT_CONNECT_CHANGE = 0x0002
|
||||
define UHCI_PORT_ENABLE = 0x0004
|
||||
define UHCI_PORT_ENABLE_CHANGE = 0x0008
|
||||
define UHCI_PORT_RESET = 0x0200
|
||||
define UHCI_PORT_LOW_SPEED = 0x0100
|
||||
|
||||
TD_TOKEN_SETUP: t.CDefine = 0x2D
|
||||
TD_TOKEN_IN: t.CDefine = 0x69
|
||||
TD_TOKEN_OUT: t.CDefine = 0xE1
|
||||
define TD_CTRL_ACTIVE = 0x00800000
|
||||
define TD_CTRL_IOC = 0x01000000
|
||||
define TD_CTRL_LS = 0x04000000
|
||||
define TD_CTRL_SPD = 0x20000000
|
||||
define TD_CTRL_CERR_SHIFT = 27
|
||||
define TD_CTRL_CERR_MASK = 0x18000000
|
||||
|
||||
TD_TOKEN_DATA0: t.CDefine = 0
|
||||
TD_TOKEN_DATA1: t.CDefine = 1
|
||||
define TD_TOKEN_SETUP = 0x2D
|
||||
define TD_TOKEN_IN = 0x69
|
||||
define TD_TOKEN_OUT = 0xE1
|
||||
|
||||
TD_LINK_TERMINATE: t.CDefine = 0x00000001
|
||||
TD_LINK_QH: t.CDefine = 0x00000002
|
||||
TD_LINK_DEPTH_FIRST: t.CDefine = 0x00000004
|
||||
define TD_TOKEN_DATA0 = 0
|
||||
define TD_TOKEN_DATA1 = 1
|
||||
|
||||
UHCI_NUM_FRAMES: t.CDefine = 1024
|
||||
UHCI_INT_SLOTS: t.CDefine = 4
|
||||
define TD_LINK_TERMINATE = 0x00000001
|
||||
define TD_LINK_QH = 0x00000002
|
||||
define TD_LINK_DEPTH_FIRST = 0x00000004
|
||||
|
||||
class uhci_td(t.CStruct):
|
||||
define UHCI_NUM_FRAMES = 1024
|
||||
define UHCI_INT_SLOTS = 4
|
||||
|
||||
class uhci_td:
|
||||
link: uint32
|
||||
ctrl_status: uint32
|
||||
token: uint32
|
||||
buffer: uint32
|
||||
|
||||
class uhci_qh(t.CStruct):
|
||||
class uhci_qh:
|
||||
link: uint32
|
||||
element: uint32
|
||||
|
||||
class int_slot(t.CStruct):
|
||||
td: uhci_td | t.CPtr
|
||||
callback: int | t.CPtr
|
||||
class int_slot:
|
||||
td: uhci_td*
|
||||
callback: int*
|
||||
active: int
|
||||
qh: uhci_qh | t.CPtr
|
||||
qh: uhci_qh*
|
||||
|
||||
_io_base: uint16 = 0
|
||||
_frame_list: uint32 | t.CPtr = None
|
||||
_ctrl_qh: uhci_qh | t.CPtr = None
|
||||
_bulk_qh: uhci_qh | t.CPtr = None
|
||||
_frame_list: uint32* = None
|
||||
_ctrl_qh: uhci_qh* = None
|
||||
_bulk_qh: uhci_qh* = None
|
||||
_irq: int = -1
|
||||
_int_slots: t.CArray[int_slot, UHCI_INT_SLOTS]
|
||||
_int_slots: [UHCI_INT_SLOTS]int_slot
|
||||
_int_slot_count: int = 0
|
||||
|
||||
def _reg_read16(offset: uint16) -> uint16:
|
||||
@@ -103,40 +104,40 @@ def _uhci_irq_handler() -> int:
|
||||
if (sts & (UHCI_STS_USBINT | UHCI_STS_USBERRINT)) == 0:
|
||||
return 0
|
||||
for si in range(_int_slot_count):
|
||||
slot: int_slot | t.CPtr = c.Addr(_int_slots[si])
|
||||
slot: int_slot* = &_int_slots[si]
|
||||
if slot.active and slot.td is not None and slot.callback is not None:
|
||||
status: uint32 = slot.td.ctrl_status
|
||||
if (status & TD_CTRL_ACTIVE) == 0:
|
||||
slot.active = 0
|
||||
c.Asm(f"""mov rbp, rsp
|
||||
__asm__(f"""mov rbp, rsp
|
||||
and rsp, -16
|
||||
call {c.AsmInp(slot.callback, t.ASM_DESCR.REG_ANY)}
|
||||
call {asminp(slot.callback, ASM_DESCR.REG_ANY)}
|
||||
mov rsp, rbp""",
|
||||
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
|
||||
t.ASM_DESCR.CLOBBER_RBX,
|
||||
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
|
||||
t.ASM_DESCR.CLOBBER_RSI, t.ASM_DESCR.CLOBBER_RDI,
|
||||
t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
|
||||
t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11,
|
||||
t.ASM_DESCR.CLOBBER_RBP])
|
||||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||||
ASM_DESCR.CLOBBER_RBX,
|
||||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11,
|
||||
ASM_DESCR.CLOBBER_RBP])
|
||||
return 0
|
||||
|
||||
def register_int_callback(cb: int | t.CPtr) -> int:
|
||||
def register_int_callback(cb: int*) -> int:
|
||||
global _int_slot_count
|
||||
if _int_slot_count >= UHCI_INT_SLOTS:
|
||||
return -1
|
||||
si: int = _int_slot_count
|
||||
qh: uhci_qh | t.CPtr = mm.malloc_direct(uhci_qh.__sizeof__())
|
||||
qh: uhci_qh* = mm.malloc_direct(uhci_qh.__sizeof__())
|
||||
if qh is None:
|
||||
return -2
|
||||
string.memset(c.Addr(qh), 0, uhci_qh.__sizeof__())
|
||||
string.memset(qh, 0, uhci_qh.__sizeof__())
|
||||
_qh_set_link(qh, 0, 0, 1)
|
||||
_qh_set_element(qh, 0, 1)
|
||||
td: uhci_td | t.CPtr = mm.malloc_direct(uhci_td.__sizeof__())
|
||||
td: uhci_td* = mm.malloc_direct(uhci_td.__sizeof__())
|
||||
if td is None:
|
||||
return -3
|
||||
string.memset(c.Addr(td), 0, uhci_td.__sizeof__())
|
||||
slot: int_slot | t.CPtr = c.Addr(_int_slots[si])
|
||||
string.memset(td, 0, uhci_td.__sizeof__())
|
||||
slot: int_slot* = &_int_slots[si]
|
||||
slot.td = td
|
||||
slot.callback = cb
|
||||
slot.active = 0
|
||||
@@ -145,18 +146,18 @@ def register_int_callback(cb: int | t.CPtr) -> int:
|
||||
_rebuild_int_chain()
|
||||
return si
|
||||
|
||||
def schedule_int_transfer(slot_id: int, dev_addr: uint8, endpoint: uint8, ls: int, max_pkt: uint8, toggle_ptr: uint8 | t.CPtr, buf: t.CPtr):
|
||||
def schedule_int_transfer(slot_id: int, dev_addr: uint8, endpoint: uint8, ls: int, max_pkt: uint8, toggle: uint8, buf: rawptr):
|
||||
if slot_id < 0 or slot_id >= _int_slot_count:
|
||||
return
|
||||
slot: int_slot | t.CPtr = c.Addr(_int_slots[slot_id])
|
||||
td: uhci_td | t.CPtr = slot.td
|
||||
qh: uhci_qh | t.CPtr = slot.qh
|
||||
slot: int_slot* = &_int_slots[slot_id]
|
||||
td: uhci_td* = slot.td
|
||||
qh: uhci_qh* = slot.qh
|
||||
if td is None or qh is None:
|
||||
return
|
||||
string.memset(c.Addr(td), 0, uhci_td.__sizeof__())
|
||||
string.memset(td, 0, uhci_td.__sizeof__())
|
||||
_td_set_link(td, 0, 0, 1)
|
||||
_td_set_ctrl(td, ls, max_pkt)
|
||||
_td_set_token(td, TD_TOKEN_IN, dev_addr, endpoint, toggle_ptr, max_pkt)
|
||||
_td_set_token(td, TD_TOKEN_IN, dev_addr, endpoint, toggle, max_pkt)
|
||||
td.ctrl_status = td.ctrl_status | TD_CTRL_IOC
|
||||
td.buffer = uint32(uint64(buf))
|
||||
_qh_set_element(qh, uint32(uint64(td)), 0)
|
||||
@@ -165,10 +166,10 @@ def schedule_int_transfer(slot_id: int, dev_addr: uint8, endpoint: uint8, ls: in
|
||||
def _rebuild_int_chain():
|
||||
if _int_slot_count == 0:
|
||||
return
|
||||
first_qh: uhci_qh | t.CPtr = None
|
||||
prev_qh: uhci_qh | t.CPtr = None
|
||||
first_qh: uhci_qh* = None
|
||||
prev_qh: uhci_qh* = None
|
||||
for si in range(_int_slot_count):
|
||||
cur_qh: uhci_qh | t.CPtr = _int_slots[si].qh
|
||||
cur_qh: uhci_qh* = _int_slots[si].qh
|
||||
if cur_qh is not None:
|
||||
if first_qh is None:
|
||||
first_qh = cur_qh
|
||||
@@ -181,16 +182,16 @@ def _rebuild_int_chain():
|
||||
qh_addr: uint32 = uint32(uint64(first_qh)) | TD_LINK_QH
|
||||
i: int
|
||||
for i in range(UHCI_NUM_FRAMES):
|
||||
entry_ptr: uint32 | t.CPtr = _frame_list + uint64(i) * 4
|
||||
c.Set(c.Deref(entry_ptr), qh_addr)
|
||||
entry_ptr: uint32* = _frame_list + uint64(i) * 4
|
||||
*entry_ptr = qh_addr
|
||||
|
||||
def _td_set_link(td: uhci_td | t.CPtr, addr: uint32, is_qh: int, terminate: int):
|
||||
def _td_set_link(td: uhci_td*, addr: uint32, is_qh: int, terminate: int):
|
||||
val: uint32 = (addr & 0xFFFFFFF0)
|
||||
if is_qh: val = val | TD_LINK_QH
|
||||
if terminate: val = val | TD_LINK_TERMINATE
|
||||
td.link = val
|
||||
|
||||
def _td_set_token(td: uhci_td | t.CPtr, pid: uint8, dev_addr: uint8, endpoint: uint8, toggle: uint8, max_len: uint16):
|
||||
def _td_set_token(td: uhci_td*, pid: uint8, dev_addr: uint8, endpoint: uint8, toggle: uint8, max_len: uint16):
|
||||
len_bits: uint32
|
||||
if max_len == 0:
|
||||
len_bits = 0x7FF
|
||||
@@ -198,22 +199,22 @@ def _td_set_token(td: uhci_td | t.CPtr, pid: uint8, dev_addr: uint8, endpoint: u
|
||||
len_bits = uint32(max_len) - 1
|
||||
td.token = (uint32(pid) << 0) | (uint32(dev_addr) << 8) | (uint32(endpoint & 0x0F) << 15) | (uint32(toggle & 1) << 19) | (len_bits << 21)
|
||||
|
||||
def _td_set_ctrl(td: uhci_td | t.CPtr, ls: int, maxlen: uint16):
|
||||
def _td_set_ctrl(td: uhci_td*, ls: int, maxlen: uint16):
|
||||
td.ctrl_status = TD_CTRL_ACTIVE | (3 << TD_CTRL_CERR_SHIFT)
|
||||
if ls: td.ctrl_status = td.ctrl_status | TD_CTRL_LS
|
||||
|
||||
def _qh_set_link(qh: uhci_qh | t.CPtr, addr: uint32, is_qh: int, terminate: int):
|
||||
def _qh_set_link(qh: uhci_qh*, addr: uint32, is_qh: int, terminate: int):
|
||||
val: uint32 = (addr & 0xFFFFFFF0)
|
||||
if is_qh: val = val | TD_LINK_QH
|
||||
if terminate: val = val | TD_LINK_TERMINATE
|
||||
qh.link = val
|
||||
|
||||
def _qh_set_element(qh: uhci_qh | t.CPtr, addr: uint32, terminate: int):
|
||||
def _qh_set_element(qh: uhci_qh*, addr: uint32, terminate: int):
|
||||
val: uint32 = (addr & 0xFFFFFFF0)
|
||||
if terminate: val = val | TD_LINK_TERMINATE
|
||||
qh.element = val
|
||||
|
||||
def _wait_for_complete(td: uhci_td | t.CPtr, timeout_ms: int) -> int:
|
||||
def _wait_for_complete(td: uhci_td*, timeout_ms: int) -> int:
|
||||
start: uint64 = timer.timer_get_ticks()
|
||||
deadline: uint64 = start + uint64(timeout_ms)
|
||||
poll_cnt: int = 0
|
||||
@@ -234,7 +235,6 @@ def reset(io_base: uint16) -> int:
|
||||
global _io_base
|
||||
_io_base = io_base
|
||||
_reg_write16(UHCI_USBCMD, UHCI_CMD_HCRESET)
|
||||
i: int
|
||||
for i in range(1000):
|
||||
if (_reg_read16(UHCI_USBCMD) & UHCI_CMD_HCRESET) == 0:
|
||||
break
|
||||
@@ -254,9 +254,6 @@ def init(io_base: uint16) -> int:
|
||||
|
||||
serial.puts("[uhci] allocating frame list...\n")
|
||||
_frame_list = mm.malloc(UHCI_NUM_FRAMES * 4)
|
||||
_dbg_fl: t.CArray[t.CChar, 96]
|
||||
viperlib.snprintf(c.Addr(_dbg_fl), 96, "[dbg] frame_list ret=0x%lx\n", uint64(_frame_list))
|
||||
serial.puts(c.Addr(_dbg_fl))
|
||||
if _frame_list is None:
|
||||
serial.puts("[uhci] frame list alloc failed\n")
|
||||
return -2
|
||||
@@ -266,7 +263,7 @@ def init(io_base: uint16) -> int:
|
||||
if _ctrl_qh is None:
|
||||
serial.puts("[uhci] ctrl_qh alloc failed\n")
|
||||
return -3
|
||||
string.memset(c.Addr(_ctrl_qh), 0, uhci_qh.__sizeof__())
|
||||
string.memset(_ctrl_qh, 0, uhci_qh.__sizeof__())
|
||||
_qh_set_link(_ctrl_qh, 0, 0, 1)
|
||||
_qh_set_element(_ctrl_qh, 0, 1)
|
||||
|
||||
@@ -274,16 +271,15 @@ def init(io_base: uint16) -> int:
|
||||
if _bulk_qh is None:
|
||||
serial.puts("[uhci] bulk_qh alloc failed\n")
|
||||
return -4
|
||||
string.memset(c.Addr(_bulk_qh), 0, uhci_qh.__sizeof__())
|
||||
string.memset(_bulk_qh, 0, uhci_qh.__sizeof__())
|
||||
_qh_set_link(_bulk_qh, 0, 0, 1)
|
||||
_qh_set_element(_bulk_qh, 0, 1)
|
||||
|
||||
serial.puts("[uhci] setting up frame list...\n")
|
||||
qh_addr: uint32 = uint32(c.Addr(_ctrl_qh)) | TD_LINK_QH
|
||||
i: int
|
||||
qh_addr: uint32 = uint32(_ctrl_qh) | TD_LINK_QH
|
||||
for i in range(UHCI_NUM_FRAMES):
|
||||
entry_ptr: uint32 | t.CPtr = _frame_list + uint64(i) * 4
|
||||
c.Set(c.Deref(entry_ptr), qh_addr)
|
||||
entry_ptr: uint32* = _frame_list + uint64(i) * 4
|
||||
*entry_ptr = qh_addr
|
||||
|
||||
_reg_write32(UHCI_FLBASEADD, uint32(uint64(_frame_list)))
|
||||
_reg_write16(UHCI_FRNUM, 0)
|
||||
@@ -370,23 +366,23 @@ def port_is_low_speed(port: int) -> int:
|
||||
if sc & UHCI_PORT_LOW_SPEED: return 1
|
||||
return 0
|
||||
|
||||
def control_transfer(dev_addr: uint8, endpoint: uint8, ls: int, max_pkt: uint8, setup_buf: t.CPtr, data_buf: t.CPtr, data_len: uint16, data_in: int) -> int:
|
||||
def control_transfer(dev_addr: uint8, endpoint: uint8, ls: int, max_pkt: uint8, setup_buf: rawptr, data_buf: rawptr, data_len: uint16, data_in: int) -> int:
|
||||
td_count: int = 2
|
||||
if data_len > 0:
|
||||
td_count = td_count + 1
|
||||
total: uint64 = uint64(td_count) * uhci_td.__sizeof__()
|
||||
tds: uhci_td | t.CPtr = mm.malloc_direct(total)
|
||||
tds: uhci_td* = mm.malloc_direct(total)
|
||||
if tds is None: return -1
|
||||
string.memset(c.Addr(tds), 0, total)
|
||||
string.memset(tds, 0, total)
|
||||
|
||||
setup_td: uhci_td | t.CPtr = tds
|
||||
setup_td: uhci_td* = tds
|
||||
_td_set_link(setup_td, uint32(uint64(tds) + uhci_td.__sizeof__()), 0, 0)
|
||||
_td_set_ctrl(setup_td, ls, 8)
|
||||
_td_set_token(setup_td, TD_TOKEN_SETUP, dev_addr, endpoint, TD_TOKEN_DATA0, 8)
|
||||
setup_td.buffer = uint32(uint64(setup_buf))
|
||||
|
||||
if data_len > 0:
|
||||
data_td: uhci_td | t.CPtr = t.CPtr(uint64(tds) + uhci_td.__sizeof__())
|
||||
data_td: uhci_td* = uhci_td*(uint64(tds) + uhci_td.__sizeof__())
|
||||
_td_set_link(data_td, uint32(uint64(data_td) + uhci_td.__sizeof__()), 0, 0)
|
||||
_td_set_ctrl(data_td, ls, max_pkt)
|
||||
if data_in:
|
||||
@@ -395,7 +391,7 @@ def control_transfer(dev_addr: uint8, endpoint: uint8, ls: int, max_pkt: uint8,
|
||||
_td_set_token(data_td, TD_TOKEN_OUT, dev_addr, endpoint, TD_TOKEN_DATA1, data_len)
|
||||
data_td.buffer = uint32(uint64(data_buf))
|
||||
|
||||
status_td: uhci_td | t.CPtr = t.CPtr(uint64(data_td) + uhci_td.__sizeof__())
|
||||
status_td: uhci_td* = uhci_td*(uint64(data_td) + uhci_td.__sizeof__())
|
||||
_td_set_link(status_td, 0, 0, 1)
|
||||
_td_set_ctrl(status_td, ls, max_pkt)
|
||||
if data_in:
|
||||
@@ -404,7 +400,7 @@ def control_transfer(dev_addr: uint8, endpoint: uint8, ls: int, max_pkt: uint8,
|
||||
_td_set_token(status_td, TD_TOKEN_IN, dev_addr, endpoint, TD_TOKEN_DATA1, 0)
|
||||
status_td.buffer = 0
|
||||
else:
|
||||
status_td: uhci_td | t.CPtr = t.CPtr(uint64(tds) + uhci_td.__sizeof__())
|
||||
status_td: uhci_td* = uhci_td*(uint64(tds) + uhci_td.__sizeof__())
|
||||
_td_set_link(status_td, 0, 0, 1)
|
||||
_td_set_ctrl(status_td, ls, max_pkt)
|
||||
_td_set_token(status_td, TD_TOKEN_IN, dev_addr, endpoint, TD_TOKEN_DATA1, 0)
|
||||
|
||||
@@ -749,7 +749,9 @@ def load_so(path: t.CConst | str) -> t.CPtr:
|
||||
_so_sym_count = 0
|
||||
if hash_vaddr != 0:
|
||||
hash_ptr: t.CPtr = t.CPtr(hash_vaddr + so_load_addr)
|
||||
nchain: uint32 = c.Deref(t.CPtr(uint64(hash_ptr) + 4))
|
||||
# 宽度只由指针的元素类型决定:nchain 是 4 字节字段,必须给出 u32*
|
||||
# (i8* 现在恒读 1 字节)。地址口径不变(hash_ptr + 4 字节)。
|
||||
nchain: uint32 = c.Deref(uint32(uint64(hash_ptr) + 4, t.CPtr))
|
||||
_so_sym_count = int(nchain)
|
||||
elif syment > 0 and strtab_vaddr > symtab_vaddr and symtab_vaddr != 0:
|
||||
sym_tab_size: uint64 = strtab_vaddr - symtab_vaddr
|
||||
|
||||
+67
-82
@@ -35,39 +35,31 @@ import asm
|
||||
kbd_tid: int = -1
|
||||
mse_tid: int = -1
|
||||
|
||||
BootInfo: bootinfo.bootinfo | t.CPtr
|
||||
BootInfo: bootinfo.bootinfo*
|
||||
|
||||
|
||||
@t.Object
|
||||
# @t.CVTable
|
||||
class ViperKernel:
|
||||
BootInfo: bootinfo.bootinfo | t.CPtr
|
||||
VGA: vga._VGAScreenDriver | t.CPtr
|
||||
VGA_drv: vga._VGAScreenDriver
|
||||
BootInfo: bootinfo.bootinfo*
|
||||
VGA: vga._VGAScreenDriver*
|
||||
|
||||
def __init__(self):
|
||||
global BootInfo
|
||||
self.BootInfo = BootInfo
|
||||
# 启用 SSE/FPU:OVMF 启动后 CR4.OSFXSR 未置位,movaps 会 #GP——
|
||||
# 变参函数传 float/double 保存 xmm 寄存器触发(sched started 后崩溃根因)。
|
||||
|
||||
cpu.enable_sse()
|
||||
# 注意:此处不能再写 `BootInfo: bootinfo.bootinfo | t.CPtr = self.BootInfo`
|
||||
# 局部重声明全局名——编译器会创建局部 alloca 却不写入(赋值落全局),
|
||||
# 后续 BootInfo.X 读未初始化局部 → 全 0 → memmap 永不可用。直接用 global。
|
||||
|
||||
serial.init()
|
||||
serial.puts("===== ViperOS VKernel Test\n =====")
|
||||
serial.puts("V2.3.8\n")
|
||||
|
||||
intr.gdt.init()
|
||||
# Set IA32_KERNEL_GS_BASE = &_per_cpu so swapgs in ISR/syscall works.
|
||||
# _CPUObject is never instantiated, so __init_tss__ never runs;
|
||||
# without this, GS base stays 0 and gs:[0] writes hit null -> triple fault.
|
||||
cpu.msr_write(cpu.IA32_KERNEL_GS_BASE, uint64(c.Addr(cpu._per_cpu)))
|
||||
|
||||
cpu.msr_write(cpu.IA32_KERNEL_GS_BASE, uint64(&cpu._per_cpu))
|
||||
serial.puts("[main] gdt init done\n")
|
||||
intr.idt.init()
|
||||
syscall.init()
|
||||
serial.puts("[main] syscall init done\n")
|
||||
|
||||
# 必须在 sti() 之前初始化调度器,否则中断触发时 _sched_ptr 为 NULL 会导致三重故障
|
||||
sched.Scheduler()
|
||||
serial.puts("[main] sched init done\n")
|
||||
|
||||
@@ -90,21 +82,18 @@ class ViperKernel:
|
||||
apic.write(0x350, 0x700) # 再次写 LINT0,验证写粘性
|
||||
_dbg_lint0: uint32 = apic.read(0x350)
|
||||
_dbg_feat: uint32 = cpu.detect_features_static()
|
||||
_dbg_buf: t.CArray[t.CChar, 160]
|
||||
viperlib.snprintf(c.Addr(_dbg_buf), 160,
|
||||
_dbg_buf: [160]char
|
||||
viperlib.snprintf(&_dbg_buf, 160,
|
||||
"[DBG] base=0x%lx ver=0x%x svr=0x%x lint0=0x%x feat=0x%x apic=%d\n",
|
||||
_dbg_base, _dbg_ver, _dbg_svr, _dbg_lint0, _dbg_feat,
|
||||
1 if (_dbg_feat & cpu.CPU_FEATURE_APIC) else 0)
|
||||
serial.puts(c.Addr(_dbg_buf))
|
||||
serial.puts(&_dbg_buf)
|
||||
|
||||
# [DBG] 读回 IDT 门 32,验证 isr32 分发地址是否正确安装(用后移除)
|
||||
_g32: uint64 = (uint64(intr.idt.idt[32].base_low) |
|
||||
(uint64(intr.idt.idt[32].base_middle) << 16) |
|
||||
(uint64(intr.idt.idt[32].base_high) << 32))
|
||||
_g32buf: t.CArray[t.CChar, 96]
|
||||
viperlib.snprintf(c.Addr(_g32buf), 96, "[DBG] idt32 base=0x%lx sel=0x%x type=0x%x\n",
|
||||
_g32, intr.idt.idt[32].selector, intr.idt.idt[32].type_attr)
|
||||
serial.puts(c.Addr(_g32buf))
|
||||
_g32: uint64 = (uint64(intr.idt.idt[32].base_low) | (uint64(intr.idt.idt[32].base_middle) << 16) | (uint64(intr.idt.idt[32].base_high) << 32))
|
||||
_g32buf: [96]char
|
||||
viperlib.snprintf(&_g32buf, 96, "[DBG] idt32 base=0x%lx sel=0x%x type=0x%x\n", _g32, intr.idt.idt[32].selector, intr.idt.idt[32].type_attr)
|
||||
serial.puts(&_g32buf)
|
||||
|
||||
asm.sti()
|
||||
serial.puts("[main] sti done\n")
|
||||
@@ -119,17 +108,17 @@ class ViperKernel:
|
||||
asm.outb(0x20, 0x0B) # OCW3 读 ISR
|
||||
asm.io_wait()
|
||||
_pic_isr: uint8 = asm.inb(0x20)
|
||||
_isrbuf: t.CArray[t.CChar, 48]
|
||||
viperlib.snprintf(c.Addr(_isrbuf), 48, "[DBG] pic_isr=0x%x\n", _pic_isr)
|
||||
serial.puts(c.Addr(_isrbuf))
|
||||
_isrbuf: [48]char
|
||||
viperlib.snprintf(&_isrbuf, 48, "[DBG] pic_isr=0x%x\n", _pic_isr)
|
||||
serial.puts(&_isrbuf)
|
||||
|
||||
timer.timer_msleep(100)
|
||||
serial.puts("[main] msleep done\n")
|
||||
rtc.rtc_init()
|
||||
serial.puts("[main] rtc init done\n")
|
||||
ncpu: uint32 = apic.get_cpu_count()
|
||||
ncpu_cr: t.CArray[t.CChar, 32]
|
||||
viperlib.snprintf(c.Addr(ncpu_cr), 32, "[main] cpu_count=%u\n", ncpu)
|
||||
ncpu_cr: [32]char
|
||||
viperlib.snprintf(&ncpu_cr, 32, "[main] cpu_count=%u\n", ncpu)
|
||||
serial.puts(ncpu_cr)
|
||||
if ncpu > 1:
|
||||
apic.start_aps()
|
||||
@@ -142,22 +131,20 @@ class ViperKernel:
|
||||
fb_format: uint64 = BootInfo.framebuffer_format
|
||||
fb_size: uint64 = BootInfo.framebuffer_size
|
||||
# [DBG] 打印 BootInfo 指针与 memmap 原始字段,定位全 0 根因(用后移除)
|
||||
_dbbuf: t.CArray[t.CChar, 140]
|
||||
viperlib.snprintf(c.Addr(_dbbuf), 140, "[main] BootInfo=0x%lx mmap=0x%lx mmsz=%lu mmd=%lu fb=0x%lx\n",
|
||||
_dbbuf: [140]char
|
||||
viperlib.snprintf(&_dbbuf, 140, "[main] BootInfo=0x%lx mmap=0x%lx mmsz=%lu mmd=%lu fb=0x%lx\n",
|
||||
uint64(BootInfo), BootInfo.MemmapAddr, BootInfo.MemmapSize,
|
||||
BootInfo.MemmapDescSize, BootInfo.framebuffer_addr)
|
||||
serial.puts(c.Addr(_dbbuf))
|
||||
serial.puts(&_dbbuf)
|
||||
# [DBG] 转储 BootInfo 地址处原始 88 字节(用后移除)
|
||||
_dbraw: t.CArray[t.CChar, 16]
|
||||
_dbi: int = 0
|
||||
while _dbi < 88:
|
||||
_dbraw: [16]char
|
||||
for _dbi in range(88):
|
||||
if (_dbi % 16) == 0:
|
||||
viperlib.snprintf(c.Addr(_dbraw), 16, "\n[DB] %04x:", _dbi)
|
||||
serial.puts(c.Addr(_dbraw))
|
||||
_dbv: uint8 = c.Deref(uint8(uint64(BootInfo) + uint64(_dbi), t.CPtr))
|
||||
viperlib.snprintf(c.Addr(_dbraw), 16, " %02x", _dbv)
|
||||
serial.puts(c.Addr(_dbraw))
|
||||
_dbi += 1
|
||||
viperlib.snprintf(&_dbraw, 16, "\n[DB] %04x:", _dbi)
|
||||
serial.puts(&_dbraw)
|
||||
_dbv: uint8 = *(uint8(uint64(BootInfo) + uint64(_dbi)))
|
||||
viperlib.snprintf(&_dbraw, 16, " %02x", _dbv)
|
||||
serial.puts(&_dbraw)
|
||||
serial.puts("\n[DB] dump end\n")
|
||||
|
||||
if BootInfo is not None:
|
||||
@@ -194,29 +181,27 @@ class ViperKernel:
|
||||
serial.puts("[main] initializing FAT32 filesystem\n")
|
||||
scan_res: int = fat32.scan_drives()
|
||||
ndrives: int = fat32.get_drive_count()
|
||||
ndrives_cr: t.CArray[t.CChar, 64]
|
||||
viperlib.snprintf(c.Addr(ndrives_cr), 64, "[fat32] scan_res=%d found %d drives\n", scan_res, ndrives)
|
||||
serial.puts(ndrives_cr)
|
||||
ndrives_cr: [64]char
|
||||
viperlib.snprintf(&ndrives_cr, 64, "[fat32] scan_res=%d found %d drives\n", scan_res, ndrives)
|
||||
serial.puts(&ndrives_cr)
|
||||
|
||||
if ndrives > 0:
|
||||
mount_res: int = fat32.mount()
|
||||
if mount_res == 0:
|
||||
dp: fat32_types.dirobj
|
||||
res: int = fat32.opendir("/", c.Addr(dp))
|
||||
res: int = fat32.opendir("/", &dp)
|
||||
if res == 0:
|
||||
serial.puts("[fat32] listing 0:/\n")
|
||||
count: int = 0
|
||||
while count < 20:
|
||||
for count in range(20):
|
||||
info: fat32_types.fileinfo
|
||||
res2: int = fat32.readdir(c.Addr(dp), c.Addr(info))
|
||||
res2: int = fat32.readdir(&dp, &info)
|
||||
if res2 != 0: break
|
||||
if info.fname[0] == 0: break
|
||||
is_dir: int = 1 if (info.attr & fat32_types.AM_DIR) else 0
|
||||
entry_cr: t.CArray[t.CChar, 300]
|
||||
viperlib.snprintf(c.Addr(entry_cr), 300, " %s size=%lu dir=%d\n", c.Addr(info.fname[0]), info.file_size, is_dir)
|
||||
serial.puts(entry_cr)
|
||||
count = count + 1
|
||||
fat32.closedir(c.Addr(dp))
|
||||
entry_cr: [300]char
|
||||
viperlib.snprintf(&entry_cr, 300, " %s size=%lu dir=%d\n", &info.fname[0], info.file_size, is_dir)
|
||||
serial.puts(&entry_cr)
|
||||
fat32.closedir(&dp)
|
||||
serial.puts("[fat32] directory listing done\n")
|
||||
else:
|
||||
serial.puts("[fat32] failed to open root directory\n")
|
||||
@@ -224,20 +209,20 @@ class ViperKernel:
|
||||
# Load ELF apps BEFORE running destructive FAT32 tests
|
||||
serial.puts("[main] loading ELF apps...\n")
|
||||
dp_apps: fat32_types.dirobj
|
||||
apps_res: int = fat32.opendir("/APPS", c.Addr(dp_apps))
|
||||
apps_res: int = fat32.opendir("/APPS", &dp_apps)
|
||||
if apps_res == 0:
|
||||
serial.puts("[main] APPS dir listing:\n")
|
||||
ac: int = 0
|
||||
while ac < 20:
|
||||
ai: fat32_types.fileinfo
|
||||
ar: int = fat32.readdir(c.Addr(dp_apps), c.Addr(ai))
|
||||
ar: int = fat32.readdir(&dp_apps, &ai)
|
||||
if ar != 0: break
|
||||
if ai.fname[0] == 0: break
|
||||
ae: t.CArray[t.CChar, 300]
|
||||
viperlib.snprintf(c.Addr(ae), 300, " %s size=%lu\n", c.Addr(ai.fname[0]), ai.file_size)
|
||||
serial.puts(ae)
|
||||
ae: [300]char
|
||||
viperlib.snprintf(&ae, 300, " %s size=%lu\n", &ai.fname[0], ai.file_size)
|
||||
serial.puts(&ae)
|
||||
ac = ac + 1
|
||||
fat32.closedir(c.Addr(dp_apps))
|
||||
fat32.closedir(&dp_apps)
|
||||
else:
|
||||
serial.puts("[main] APPS dir not found\n")
|
||||
|
||||
@@ -266,21 +251,21 @@ class ViperKernel:
|
||||
serial.puts("[main] sched started\n")
|
||||
|
||||
fd: int = devfs.devfs_open("/dev/serial0", 0)
|
||||
buf: t.CArray[t.CChar, 64]
|
||||
string.memset(c.Addr(buf), 0, 64)
|
||||
buf: [64]char
|
||||
string.memset(&buf, 0, 64)
|
||||
devfs.devfs_write(fd, "hello from devfs!", 17)
|
||||
devfs.devfs_read(fd, c.Addr(buf), 64)
|
||||
devfs.devfs_read(fd, &buf, 64)
|
||||
devfs.devfs_close(fd)
|
||||
|
||||
cr: t.CArray[t.CChar, 30]
|
||||
string.memset(c.Addr(cr), 0, 30)
|
||||
viperlib.snprintf(c.Addr(cr), 30, "hello %d %.2f", 42, float(0.24))
|
||||
cr: [30]char
|
||||
string.memset(&cr, 0, 30)
|
||||
viperlib.snprintf(&cr, 30, "hello %d %.2f", 42, float(0.24))
|
||||
serial.puts(cr)
|
||||
serial.puts("\n")
|
||||
|
||||
bootinfo_cr: t.CArray[t.CChar, 256]
|
||||
string.memset(c.Addr(bootinfo_cr), 0, 256)
|
||||
viperlib.snprintf(c.Addr(bootinfo_cr), 256, "Bootinfo 0x%016lx %lu %lu %lu %lu %lu map 0x%lx+%lu descsize=%lu",
|
||||
bootinfo_cr: [256]char
|
||||
string.memset(&bootinfo_cr, 0, 256)
|
||||
viperlib.snprintf(&bootinfo_cr, 256, "Bootinfo 0x%016lx %lu %lu %lu %lu %lu map 0x%lx+%lu descsize=%lu",
|
||||
BootInfo.framebuffer_addr,
|
||||
BootInfo.framebuffer_format,
|
||||
BootInfo.framebuffer_width,
|
||||
@@ -294,13 +279,13 @@ class ViperKernel:
|
||||
serial.puts("\n")
|
||||
|
||||
|
||||
a: t.CConst | str = "Hello"
|
||||
serial.puts(c.Addr(a[4])) # o
|
||||
a: const str = "Hello"
|
||||
serial.puts(&a[4]) # o
|
||||
serial.puts("\n")
|
||||
d: t.CConst | int = 42
|
||||
b: t.CConst | int | t.CPtr = c.Addr(d)
|
||||
string.memset(c.Addr(cr), 0, 4)
|
||||
viperlib.snprintf(c.Addr(cr), 30, "%d", b[0]) # 42
|
||||
d: const int = 42
|
||||
b: const int* = &d
|
||||
string.memset(&cr, 0, 4)
|
||||
viperlib.snprintf(&cr, 30, "%d", b[0]) # 42
|
||||
serial.puts(cr)
|
||||
serial.puts("\n")
|
||||
|
||||
@@ -314,8 +299,8 @@ class ViperKernel:
|
||||
mse_svc.start()
|
||||
serial.puts("[main] services started\n")
|
||||
|
||||
self.VGA_drv = vga._VGAScreenDriver(fb, width, height, pitch, fb_format)
|
||||
self.VGA = c.Addr(self.VGA_drv)
|
||||
VGA_drv = vga._VGAScreenDriver(fb, width, height, pitch, fb_format)
|
||||
self.VGA = &VGA_drv
|
||||
self.VGA.Print(100, 100, "ViperOS VKernel Test")
|
||||
serial.puts("你好\n")
|
||||
|
||||
@@ -356,18 +341,18 @@ class ViperKernel:
|
||||
# 合成式类型转换
|
||||
|
||||
|
||||
VKP: ViperKernel | t.CPtr
|
||||
VKP: ViperKernel*
|
||||
# stackrealign:_start 由 bootloader jmp 进入(rsp≡0 mod 16),llc 按 call 约定
|
||||
# 假设入口 rsp≡8 → 帧偏 8 → 变参函数 movaps #GP。动态重对齐栈修复。
|
||||
@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16), t.attr.stackrealign)
|
||||
def _start() -> int:
|
||||
global VKP, BootInfo
|
||||
saved_rdi: t.CUnsignedLong
|
||||
saved_rdi: ulong
|
||||
c.Asm(f"mov {c.AsmOut(saved_rdi, t.ASM_DESCR.OUTPUT_REG)}, rdi",
|
||||
op = [t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RDI])
|
||||
asm.BSSClean()
|
||||
BootInfo = t.CPtr(saved_rdi) # 转为 bootinfo*
|
||||
VKP = c.Addr(ViperKernel())
|
||||
BootInfo = bootinfo*(saved_rdi) # 转为 bootinfo*
|
||||
VKP = &ViperKernel()
|
||||
while True:
|
||||
asm.sti()
|
||||
asm.hlt()
|
||||
|
||||
@@ -447,6 +447,11 @@ def save_pt_range(vaddr_start: uint64, vaddr_end: uint64, save_buf: uint64 | t.C
|
||||
pt_: _p | t.CPtr = t.CType(pd_.entries[pd_idx] & ~uint64(0xFFF), _p, t.CPtr)
|
||||
pt_idx: uint64 = (va >> 12) & 0x1FF
|
||||
saved: uint32 = c.DerefAs(save_count)
|
||||
# [待复核·指针缩放] save_buf 是 `uint64 | t.CPtr`;若该联合解析为 Ptr(u64),则下面的
|
||||
# `* 16` 与 `+ 8` 都会再乘 8(GEP 按元素缩放)⇒ 记录步长 128 字节、字段偏移 64 字节,
|
||||
# 与本处"16 字节一条记录(va 在 +0、pte 在 +8)"的设计不符。若本意是字节偏移,
|
||||
# 需改用整数加法推进地址(或显式 rawptr/字节指针)——迁移到 rawptr[T] 时一并复核,
|
||||
# 见 Debugger/rawptr-migration-and-fastfail.md。结论待定(需一次 IR 取证 GEP 的元素类型)。
|
||||
entry_ptr: uint64 | t.CPtr = save_buf + uint64(saved) * 16
|
||||
c.DerefAs(entry_ptr, va)
|
||||
c.DerefAs(entry_ptr + 8, pt_.entries[pt_idx])
|
||||
@@ -459,6 +464,8 @@ def restore_pt_range(save_buf: uint64 | t.CPtr, save_count: uint32):
|
||||
if not pml4: return
|
||||
i: uint32 = 0
|
||||
while i < save_count:
|
||||
# [待复核·指针缩放] 同 save_pt_range:`* 16` / `+ 8` 若按 Ptr(u64) 缩放会变成 128/64 字节
|
||||
# (该函数必须与 save_pt_range 的写入布局严格一致,两者要一起复核/一起改)。
|
||||
entry_ptr: uint64 | t.CPtr = save_buf + uint64(i) * 16
|
||||
va: uint64 = c.DerefAs(entry_ptr)
|
||||
orig_pte: uint64 = c.DerefAs(entry_ptr + 8)
|
||||
|
||||
Reference in new issue
Block a user