From 5f5a119f06ae3b26c62f0cde73f44331892289df Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Sun, 27 Sep 2026 15:05:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(vkernel):=20schedule=5Fint=5Ftransfer=20?= =?UTF-8?q?=E7=9A=84=20toggle=20=E5=BD=A2=E5=8F=82=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=80=BC=E4=BC=A0=E9=80=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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。 --- VKernel/Kernel/drivers/core/cpu/apic.vp | 144 +- VKernel/Kernel/drivers/core/cpu/cpu.vp | 271 +- VKernel/Kernel/drivers/core/cpu/fpu.vp | 22 +- VKernel/Kernel/drivers/devfs/devfs copy._vp | 385 -- VKernel/Kernel/drivers/devfs/devfs.vp | 282 +- VKernel/Kernel/drivers/fs/fat32/example_fs.vp | 43 +- VKernel/Kernel/drivers/fs/fat32/fat32.vp | 68 +- VKernel/Kernel/drivers/fs/fat32/fat32_core.vp | 1 - VKernel/Kernel/drivers/fs/fat32/fat32_dir.vp | 1 - .../Kernel/drivers/fs/fat32/fat32_diskio.vp | 22 +- VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp | 79 +- VKernel/Kernel/drivers/fs/fat32/fat32_part.vp | 49 +- VKernel/Kernel/drivers/fs/fat32/fat32_time.vp | 1 - .../Kernel/drivers/fs/fat32/fat32_types.vp | 3216 ++++++++--------- VKernel/Kernel/drivers/fs/fat32/fileio.vp | 2 - .../Kernel/drivers/input/keyboard/keyboard.vp | 36 +- VKernel/Kernel/drivers/input/mouse/mouse.vp | 44 +- VKernel/Kernel/drivers/serial/uart/serial.vp | 47 +- VKernel/Kernel/drivers/serial/uart/su8250.vp | 54 +- VKernel/Kernel/drivers/storage/ide/ide.vp | 87 +- VKernel/Kernel/drivers/usb/hid/hid.vp | 28 +- VKernel/Kernel/drivers/usb/hid/usb_kbd.vp | 27 +- VKernel/Kernel/drivers/usb/hid/usb_mouse.vp | 33 +- VKernel/Kernel/drivers/usb/pci.vp | 32 +- VKernel/Kernel/drivers/usb/uhci.vp | 204 +- VKernel/Kernel/execrunner/elf.vp | 4 +- VKernel/Kernel/main.vp | 149 +- VKernel/Kernel/paging/paging.vp | 7 + 28 files changed, 2360 insertions(+), 2978 deletions(-) delete mode 100644 VKernel/Kernel/drivers/devfs/devfs copy._vp diff --git a/VKernel/Kernel/drivers/core/cpu/apic.vp b/VKernel/Kernel/drivers/core/cpu/apic.vp index 748afbc..f5f1c5d 100644 --- a/VKernel/Kernel/drivers/core/cpu/apic.vp +++ b/VKernel/Kernel/drivers/core/cpu/apic.vp @@ -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 diff --git a/VKernel/Kernel/drivers/core/cpu/cpu.vp b/VKernel/Kernel/drivers/core/cpu/cpu.vp index c9bfc4f..dbd4124 100644 --- a/VKernel/Kernel/drivers/core/cpu/cpu.vp +++ b/VKernel/Kernel/drivers/core/cpu/cpu.vp @@ -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]) diff --git a/VKernel/Kernel/drivers/core/cpu/fpu.vp b/VKernel/Kernel/drivers/core/cpu/fpu.vp index b0c91fb..fc774ab 100644 --- a/VKernel/Kernel/drivers/core/cpu/fpu.vp +++ b/VKernel/Kernel/drivers/core/cpu/fpu.vp @@ -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]) diff --git a/VKernel/Kernel/drivers/devfs/devfs copy._vp b/VKernel/Kernel/drivers/devfs/devfs copy._vp deleted file mode 100644 index 053c9bc..0000000 --- a/VKernel/Kernel/drivers/devfs/devfs copy._vp +++ /dev/null @@ -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) diff --git a/VKernel/Kernel/drivers/devfs/devfs.vp b/VKernel/Kernel/drivers/devfs/devfs.vp index 688b7a5..74cbd50 100644 --- a/VKernel/Kernel/drivers/devfs/devfs.vp +++ b/VKernel/Kernel/drivers/devfs/devfs.vp @@ -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 diff --git a/VKernel/Kernel/drivers/fs/fat32/example_fs.vp b/VKernel/Kernel/drivers/fs/fat32/example_fs.vp index 1e4599e..5f9fca3 100644 --- a/VKernel/Kernel/drivers/fs/fat32/example_fs.vp +++ b/VKernel/Kernel/drivers/fs/fat32/example_fs.vp @@ -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. 删除文件和目录 diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32.vp b/VKernel/Kernel/drivers/fs/fat32/fat32.vp index bddcb96..e3c4fef 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32.vp @@ -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) diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_core.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_core.vp index 1a90c49..e2f4b45 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_core.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_core.vp @@ -1,6 +1,5 @@ from stdint import * import fat32_types as types -import t, c _read32 = types._read32 diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_dir.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_dir.vp index 5f85280..dcec3bf 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_dir.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_dir.vp @@ -1,6 +1,5 @@ from stdint import * import fat32_types as types -import t, c sfn_checksum = types.sfn_checksum diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_diskio.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_diskio.vp index 818e5f1..b7ddc56 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_diskio.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_diskio.vp @@ -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 diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp index 8926055..8c5976f 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_mkfs.vp @@ -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 diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_part.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_part.vp index 594e49f..e4090b4 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_part.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_part.vp @@ -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 diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_time.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_time.vp index 494be9d..ebdb0ce 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_time.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_time.vp @@ -1,5 +1,4 @@ from stdint import * -import t, c import asm diff --git a/VKernel/Kernel/drivers/fs/fat32/fat32_types.vp b/VKernel/Kernel/drivers/fs/fat32/fat32_types.vp index 59a4611..b9bcb3c 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fat32_types.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fat32_types.vp @@ -1,5 +1,4 @@ from stdint import * -import t, c import spinlock import string import fat32_diskio as diskio @@ -7,1774 +6,1681 @@ import fat32_time as ftime import viperlib import drivers.serial.uart.serial as serial -def _read32(buf: uint8 | t.CPtr, off: uint32) -> uint32: - return uint32(buf[off]) | (uint32(buf[off + 1]) << 8) | (uint32(buf[off + 2]) << 16) | (uint32(buf[off + 3]) << 24) +def _read32(buf: uint8*, off: uint32) -> uint32: + return uint32(buf[off]) | (uint32(buf[off + 1]) << 8) | (uint32(buf[off + 2]) << 16) | (uint32(buf[off + 3]) << 24) -def _read16(buf: uint8 | t.CPtr, off: uint32) -> uint16: - return uint16(buf[off]) | (uint16(buf[off + 1]) << 8) +def _read16(buf: uint8*, off: uint32) -> uint16: + return uint16(buf[off]) | (uint16(buf[off + 1]) << 8) -def _write32(buf: uint8 | t.CPtr, off: uint32, val: uint32): - buf[off + 0] = uint8(val & 0xFF) - buf[off + 1] = uint8((val >> 8) & 0xFF) - buf[off + 2] = uint8((val >> 16) & 0xFF) - buf[off + 3] = uint8((val >> 24) & 0xFF) +def _write32(buf: uint8*, off: uint32, val: uint32): + buf[off + 0] = uint8(val & 0xFF) + buf[off + 1] = uint8((val >> 8) & 0xFF) + buf[off + 2] = uint8((val >> 16) & 0xFF) + buf[off + 3] = uint8((val >> 24) & 0xFF) -def _write16(buf: uint8 | t.CPtr, off: uint32, val: uint16): - buf[off + 0] = uint8(val & 0xFF) - buf[off + 1] = uint8((val >> 8) & 0xFF) +def _write16(buf: uint8*, off: uint32, val: uint16): + buf[off + 0] = uint8(val & 0xFF) + buf[off + 1] = uint8((val >> 8) & 0xFF) -SECTOR_SIZE: t.CDefine = 512 -ENTRY_SIZE: t.CDefine = 32 -CLUSTER_FREE: t.CDefine = 0x00000000 -CLUSTER_EOC_MIN: t.CDefine = 0x0FFFFFF8 -CLUSTER_EOC_MAX: t.CDefine = 0x0FFFFFFF -CLUSTER_BAD: t.CDefine = 0x0FFFFFF7 -CLUSTER_ROOT: t.CDefine = 0x00000002 -FAT_MASK: t.CDefine = 0x0FFFFFFF -FAT_RESERVED: t.CDefine = 0xF0000000 +define SECTOR_SIZE = 512 +define ENTRY_SIZE = 32 +define CLUSTER_FREE = 0x00000000 +define CLUSTER_EOC_MIN = 0x0FFFFFF8 +define CLUSTER_EOC_MAX = 0x0FFFFFFF +define CLUSTER_BAD = 0x0FFFFFF7 +define CLUSTER_ROOT = 0x00000002 +define FAT_MASK = 0x0FFFFFFF +define FAT_RESERVED = 0xF0000000 -MAX_LFN: t.CDefine = 255 -LFN_ENTRY_CHARS: t.CDefine = 13 -LFN_ATTR: t.CDefine = 0x0F -LFN_FLAG_LAST: t.CDefine = 0x40 -SFN_NAME_LEN: t.CDefine = 8 -SFN_EXT_LEN: t.CDefine = 3 -SFN_DELETED: t.CDefine = 0xE5 -SFN_DOT: t.CDefine = 0x05 -SFN_FREE: t.CDefine = 0x00 +define MAX_LFN = 255 +define LFN_ENTRY_CHARS = 13 +define LFN_ATTR = 0x0F +define LFN_FLAG_LAST = 0x40 +define SFN_NAME_LEN = 8 +define SFN_EXT_LEN = 3 +define SFN_DELETED = 0xE5 +define SFN_DOT = 0x05 +define SFN_FREE = 0x00 -MAX_HANDLES: t.CDefine = 32 -MAX_LOCKS: t.CDefine = 32 -PATH_MAX: t.CDefine = 260 -NAME_MAX: t.CDefine = 255 -DEPTH_MAX: t.CDefine = 32 +define MAX_HANDLES = 32 +define MAX_LOCKS = 32 +define PATH_MAX = 260 +define NAME_MAX = 255 +define DEPTH_MAX = 32 -FA_READ: t.CDefine = 0x01 -FA_WRITE: t.CDefine = 0x02 -FA_OPEN_EXISTING: t.CDefine = 0x00 -FA_CREATE_NEW: t.CDefine = 0x04 -FA_CREATE_ALWAYS: t.CDefine = 0x08 -FA_OPEN_ALWAYS: t.CDefine = 0x10 -FA_OPEN_APPEND: t.CDefine = 0x30 -FA_READ_MASK: t.CDefine = 0x0F +define FA_READ = 0x01 +define FA_WRITE = 0x02 +define FA_OPEN_EXISTING = 0x00 +define FA_CREATE_NEW = 0x04 +define FA_CREATE_ALWAYS = 0x08 +define FA_OPEN_ALWAYS = 0x10 +define FA_OPEN_APPEND = 0x30 +define FA_READ_MASK = 0x0F -AM_RDO: t.CDefine = 0x01 -AM_HID: t.CDefine = 0x02 -AM_SYS: t.CDefine = 0x04 -AM_VOL: t.CDefine = 0x08 -AM_DIR: t.CDefine = 0x10 -AM_ARC: t.CDefine = 0x20 -AM_LFN: t.CDefine = 0x0F -AM_ANY: t.CDefine = 0x3F +define AM_RDO = 0x01 +define AM_HID = 0x02 +define AM_SYS = 0x04 +define AM_VOL = 0x08 +define AM_DIR = 0x10 +define AM_ARC = 0x20 +define AM_LFN = 0x0F +define AM_ANY = 0x3F -FS_FAT32: t.CDefine = 3 +define FS_FAT32 = 3 -CTRL_SYNC: t.CDefine = 0 -GET_SECTOR_COUNT: t.CDefine = 1 -GET_SECTOR_SIZE: t.CDefine = 2 -GET_BLOCK_SIZE: t.CDefine = 3 -CTRL_TRIM: t.CDefine = 4 +define CTRL_SYNC = 0 +define GET_SECTOR_COUNT = 1 +define GET_SECTOR_SIZE = 2 +define GET_BLOCK_SIZE = 3 +define CTRL_TRIM = 4 -STA_NOINIT: t.CDefine = 0x01 -STA_NODISK: t.CDefine = 0x02 -STA_PROTECT: t.CDefine = 0x04 +define STA_NOINIT = 0x01 +define STA_NODISK = 0x02 +define STA_PROTECT = 0x04 -DEV_DISK: t.CDefine = 0 +define DEV_DISK = 0 -ENTRIES_PER_SECTOR: t.CDefine = 512 / 32 +define ENTRIES_PER_SECTOR = 512 / 32 -class FRESULT(t.CEnum): - FR_OK: t.State = 0 - FR_DISK_ERR: t.State - FR_INT_ERR: t.State - FR_NOT_READY: t.State - FR_NO_FILE: t.State - FR_NO_PATH: t.State - FR_INVALID_NAME: t.State - FR_DENIED: t.State - FR_EXIST: t.State - FR_INVALID_OBJECT: t.State - FR_WRITE_PROTECTED: t.State - FR_INVALID_DRIVE: t.State - FR_NOT_ENABLED: t.State - FR_NO_FILESYSTEM: t.State - FR_MKFS_ABORTED: t.State - FR_TIMEOUT: t.State - FR_LOCKED: t.State - FR_NOT_ENOUGH_CORE: t.State - FR_TOO_MANY_OPEN_FILES: t.State - FR_INVALID_PARAMETER: t.State +enum FRESULT: + FR_OK + FR_DISK_ERR, FR_INT_ERR + FR_NOT_READY, FR_NO_FILE, FR_NO_PATH + FR_INVALID_NAME, FR_DENIED, FR_EXIST + FR_INVALID_OBJECT, FR_WRITE_PROTECTED, FR_INVALID_DRIVE + FR_NOT_ENABLED, FR_NO_FILESYSTEM + FR_MKFS_ABORTED, FR_TIMEOUT, FR_LOCKED + FR_NOT_ENOUGH_CORE, FR_TOO_MANY_OPEN_FILES, FR_INVALID_PARAMETER -class DRESULT(t.CEnum): - RES_OK: t.State = 0 - RES_ERROR: t.State - RES_WRPRT: t.State - RES_NOTRDY: t.State - RES_PARERR: t.State +enum DRESULT: + RES_OK, RES_ERROR, RES_WRPRT, RES_NOTRDY, RES_PARERR -@c.Attribute(t.attr.packed) +@__attribute(packed) class bpb: - BS_jmpBoot: t.CArray[uint8, 3] - BS_OEMName: t.CArray[t.CChar, 8] - BPB_BytsPerSec: uint16 - BPB_SecPerClus: uint8 - BPB_RsvdSecCnt: uint16 - BPB_NumFATs: uint8 - BPB_RootEntCnt: uint16 - BPB_TotSec16: uint16 - BPB_Media: uint8 - BPB_FATSz16: uint16 - BPB_SecPerTrk: uint16 - BPB_NumHeads: uint16 - BPB_HiddSec: uint32 - BPB_TotSec32: uint32 - BPB_FATSz32: uint32 - BPB_ExtFlags: uint16 - BPB_FSVer: uint16 - BPB_RootClus: uint32 - BPB_FSInfo: uint16 - BPB_BkBootSec: uint16 - BPB_Reserved: t.CArray[uint8, 12] - BS_DrvNum: uint8 - BS_Reserved1: uint8 - BS_BootSig: uint8 - BS_VolID: uint32 - BS_VolLab: t.CArray[t.CChar, 11] - BS_FilSysType: t.CArray[t.CChar, 8] + BS_jmpBoot: [3]uint8 + BS_OEMName: [8]char + BPB_BytsPerSec: uint16 + BPB_SecPerClus: uint8 + BPB_RsvdSecCnt: uint16 + BPB_NumFATs: uint8 + BPB_RootEntCnt: uint16 + BPB_TotSec16: uint16 + BPB_Media: uint8 + BPB_FATSz16: uint16 + BPB_SecPerTrk: uint16 + BPB_NumHeads: uint16 + BPB_HiddSec: uint32 + BPB_TotSec32: uint32 + BPB_FATSz32: uint32 + BPB_ExtFlags: uint16 + BPB_FSVer: uint16 + BPB_RootClus: uint32 + BPB_FSInfo: uint16 + BPB_BkBootSec: uint16 + BPB_Reserved: [12]uint8 + BS_DrvNum: uint8 + BS_Reserved1: uint8 + BS_BootSig: uint8 + BS_VolID: uint32 + BS_VolLab: [11]char + BS_FilSysType: [8]char -@c.Attribute(t.attr.packed) +@__attribute__(packed) class fsinfo: - FSI_LeadSig: uint32 - FSI_Reserved1: t.CArray[uint8, 480] - FSI_StrucSig: uint32 - FSI_Free_Count: uint32 - FSI_Nxt_Free: uint32 - FSI_Reserved2: t.CArray[uint8, 12] - FSI_TrailSig: uint32 + FSI_LeadSig: uint32 + FSI_Reserved1: [480]uint8 + FSI_StrucSig: uint32 + FSI_Free_Count: uint32 + FSI_Nxt_Free: uint32 + FSI_Reserved2: [12]uint8 + FSI_TrailSig: uint32 -@c.Attribute(t.attr.packed) +@__attribute__(packed) class dirent: - DIR_Name: t.CArray[t.CChar, 11] - DIR_Attr: uint8 - DIR_NTRes: uint8 - DIR_CrtTimeTenth: uint8 - DIR_CrtTime: uint16 - DIR_CrtDate: uint16 - DIR_LstAccDate: uint16 - DIR_FstClusHI: uint16 - DIR_WrtTime: uint16 - DIR_WrtDate: uint16 - DIR_FstClusLO: uint16 - DIR_FileSize: uint32 + DIR_Name: [11]char + DIR_Attr: uint8 + DIR_NTRes: uint8 + DIR_CrtTimeTenth: uint8 + DIR_CrtTime: uint16 + DIR_CrtDate: uint16 + DIR_LstAccDate: uint16 + DIR_FstClusHI: uint16 + DIR_WrtTime: uint16 + DIR_WrtDate: uint16 + DIR_FstClusLO: uint16 + DIR_FileSize: uint32 -@c.Attribute(t.attr.packed) +@c.Attribute(packed) class lfn_entry: - LDIR_Ord: uint8 - LDIR_Name1: t.CArray[uint16, 5] - LDIR_Attr: uint8 - LDIR_Type: uint8 - LDIR_Chksum: uint8 - LDIR_Name2: t.CArray[uint16, 6] - LDIR_FstClusLO: uint16 - LDIR_Name3: t.CArray[uint16, 2] + LDIR_Ord: uint8 + LDIR_Name1: [5]uint16 + LDIR_Attr: uint8 + LDIR_Type: uint8 + LDIR_Chksum: uint8 + LDIR_Name2: [6]uint16 + LDIR_FstClusLO: uint16 + LDIR_Name3: [2]uint16 -def sfn_checksum(name: t.CConst | t.CChar | t.CPtr) -> uint8: - sum: uint8 = 0 - i: int - for i in range(11): - sum = ((sum & 1) << 7) + (sum >> 1) + name[i] - return sum +def sfn_checksum(name: const str) -> uint8: + sum: uint8 = 0 + for i in range(11): + sum = ((sum & 1) << 7) + (sum >> 1) + name[i] + return sum def uni2oem_placeholder(uni: uint16, cp: uint16) -> uint16: - if uni < 0x80: return uni - return uint16(0x003F) + if uni < 0x80: return uni + return uint16(0x003F) -def lfn_get_char(entry_bytes: uint8 | t.CPtr, idx: int) -> uint16: - if idx < 5: - off: int = 1 + idx * 2 - elif idx < 11: - off = 14 + (idx - 5) * 2 - else: - off = 28 + (idx - 11) * 2 - lo: uint8 = c.Deref(uint8(uint64(entry_bytes) + off, t.CPtr)) - hi: uint8 = c.Deref(uint8(uint64(entry_bytes) + off + 1, t.CPtr)) - return uint16(lo) | uint16(uint16(hi) << 8) +def lfn_get_char(entry_bytes: uint8*, idx: int) -> uint16: + if idx < 5: + off: int = 1 + idx * 2 + elif idx < 11: + off = 14 + (idx - 5) * 2 + else: + off = 28 + (idx - 11) * 2 + lo: uint8 = *(uint8*(uint64(entry_bytes) + off)) + hi: uint8 = *(uint8*(uint64(entry_bytes) + off + 1)) + return uint16(lo) | uint16(uint16(hi) << 8) -def lfn_set_char(entry_bytes: uint8 | t.CPtr, idx: int, ch: uint16): - if idx < 5: - off: int = 1 + idx * 2 - elif idx < 11: - off = 14 + (idx - 5) * 2 - else: - off = 28 + (idx - 11) * 2 - # c.Set(类型转换表达式, 值) 是坏模式:translate_c_set 对非 c.Deref 的 - # Call 直接 return b_val(静默不写)。必须 c.Set(c.Deref(ptr), 值) = *ptr = 值。 - # 此前 lfn_set_char/lfn_extract 从未写入 entry_bytes/lfn_buf → LFN 条目 - # 读写全失效 → dir_find 的 LFN 匹配(gargantua.elf 等长文件名)永远失败。 - c.Set(c.Deref(uint8(uint64(entry_bytes) + off, t.CPtr)), uint8(ch & 0xFF)) - c.Set(c.Deref(uint8(uint64(entry_bytes) + off + 1, t.CPtr)), uint8(ch >> 8)) +def lfn_set_char(entry_bytes: uint8*, idx: int, ch: uint16): + if idx < 5: + off: int = 1 + idx * 2 + elif idx < 11: + off = 14 + (idx - 5) * 2 + else: + off = 28 + (idx - 11) * 2 + # c.Set(类型转换表达式, 值) 是坏模式:translate_c_set 对非 c.Deref 的 + # Call 直接 return b_val(静默不写)。必须 c.Set(c.Deref(ptr), 值) = *ptr = 值。 + # 此前 lfn_set_char/lfn_extract 从未写入 entry_bytes/lfn_buf → LFN 条目 + # 读写全失效 → dir_find 的 LFN 匹配(gargantua.elf 等长文件名)永远失败。 + *(uint8*(uint64(entry_bytes) + off)) = uint8(ch & 0xFF) + *(uint8*(uint64(entry_bytes) + off + 1)) = uint8(ch >> 8) -def lfn_extract(entry_bytes: uint8 | t.CPtr, lfn: uint16 | t.CPtr, ord_val: uint8) -> int: - seq: int = (ord_val & 0x3F) - 1 - base: int = seq * LFN_ENTRY_CHARS - i: int - for i in range(LFN_ENTRY_CHARS): - # 越界钳制:lfn 缓冲为 uint16[MAX_LFN+1](256 槽)。base=(ord&0x3F-1)*13, - # ord&0x3F 在畸形/损坏 LFN 目录项下可达 63 → base 最大 806,原实现直接 - # 按下标写 → 越界写。合法短名(≤255 字符 + 终止符)不受影响。 - if base + i > MAX_LFN: - return -1 - ch: uint16 = lfn_get_char(entry_bytes, i) - if ch == 0x0000 or ch == 0xFFFF: - c.Set(c.Deref(uint16(uint64(lfn) + (base + i) * 2, t.CPtr)), 0) - return base + i - c.Set(c.Deref(uint16(uint64(lfn) + (base + i) * 2, t.CPtr)), ch) - if ord_val & LFN_FLAG_LAST: - if base + LFN_ENTRY_CHARS <= MAX_LFN: - c.Set(c.Deref(uint16(uint64(lfn) + (base + LFN_ENTRY_CHARS) * 2, t.CPtr)), 0) - return base + LFN_ENTRY_CHARS +def lfn_extract(entry_bytes: uint8*, lfn: uint16*, ord_val: uint8) -> int: + seq: int = (ord_val & 0x3F) - 1 + base: int = seq * LFN_ENTRY_CHARS + for i in range(LFN_ENTRY_CHARS): + # 越界钳制:lfn 缓冲为 uint16[MAX_LFN+1](256 槽)。base=(ord&0x3F-1)*13, + # ord&0x3F 在畸形/损坏 LFN 目录项下可达 63 → base 最大 806,原实现直接 + # 按下标写 → 越界写。合法短名(≤255 字符 + 终止符)不受影响。 + if base + i > MAX_LFN: + return -1 + ch: uint16 = lfn_get_char(entry_bytes, i) + if ch == 0x0000 or ch == 0xFFFF: + *(uint16*(uint64(lfn) + (base + i) * 2)) = 0 + return base + i + *(uint16*(uint64(lfn) + (base + i) * 2)) = ch + if ord_val & LFN_FLAG_LAST: + if base + LFN_ENTRY_CHARS <= MAX_LFN: + *(uint16*(uint64(lfn) + (base + LFN_ENTRY_CHARS) * 2)) = 0 + return base + LFN_ENTRY_CHARS -def sfn_from_lfn(lfn: t.CConst | t.CChar | t.CPtr, sfn: t.CChar | t.CPtr): - string.memset(sfn, 0x20, 11) - if c.Deref(lfn) == '.' and c.Deref(lfn + 1) == 0: - sfn[0] = '.'; sfn[11] = 0; return - if c.Deref(lfn) == '.' and c.Deref(lfn + 1) == '.' and c.Deref(lfn + 2) == 0: - sfn[0] = '.'; sfn[1] = '.'; sfn[11] = 0; return - si: int = 0 - dot_pos: int = -1 - i: int = 0 - ext_i: int = 0 - for ch in lfn: - if ch == '.': - dot_pos = si; si += 1; ext_i = 0; continue - uc: t.CChar - if ch >= 'a' and ch <= 'z': uc = ch - 32 - elif ch == ' ': uc = '_' - elif ch == '+' or ch == ',' or ch == ';' or ch == '=' or ch == '[' or ch == ']': uc = '_' - else: uc = ch - if dot_pos < 0: - if i < 8: sfn[i] = uc; i += 1 - else: - if ext_i < 3: sfn[8 + ext_i] = uc; ext_i += 1 - si += 1 - # 主名超 8 字符:生成 8.3 短名(前 6 字符 + ~1),对齐 FAT32 规范 - # (此前直接截断到 8 字符 → "gargantua.elf" 生成 "GARGANTU.ELF", - # 与磁盘的 "GARGAN~1.ELF" 不匹配 → dir_find 找不到 → FR_NO_FILE) - if dot_pos > 8: - sfn[6] = '~' - sfn[7] = '1' - sfn[11] = 0 - # [DIAG] 定位 sfn 缺扩展名(Hello 显示 HELLO 空格):打印 name 与 dot_pos/ext_i - _dsf: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(_dsf), 80, "[sfn2] dot=%d i=%d ext=%d sfn=%.11s\n", dot_pos, i, ext_i, sfn) - serial.puts(c.Addr(_dsf)) +def sfn_from_lfn(lfn: const str, sfn: str): + string.memset(sfn, 0x20, 11) + if *lfn == '.' and *(lfn + 1) == 0: + sfn[0] = '.'; sfn[11] = 0; return + if *lfn == '.' and *(lfn + 1) == '.' and *(lfn + 2) == 0: + sfn[0] = '.'; sfn[1] = '.'; sfn[11] = 0; return + si: int = 0 + dot_pos: int = -1 + i: int = 0 + ext_i: int = 0 + for ch in lfn: + if ch == '.': + dot_pos = si; si += 1; ext_i = 0; continue + uc: char + if ch >= 'a' and ch <= 'z': uc = ch - 32 + elif ch == ' ': uc = '_' + elif ch == '+' or ch == ',' or ch == ';' or ch == '=' or ch == '[' or ch == ']': uc = '_' + else: uc = ch + if dot_pos < 0: + if i < 8: sfn[i] = uc; i += 1 + else: + if ext_i < 3: sfn[8 + ext_i] = uc; ext_i += 1 + si += 1 + # 主名超 8 字符:生成 8.3 短名(前 6 字符 + ~1),对齐 FAT32 规范 + # (此前直接截断到 8 字符 → "gargantua.elf" 生成 "GARGANTU.ELF", + # 与磁盘的 "GARGAN~1.ELF" 不匹配 → dir_find 找不到 → FR_NO_FILE) + if dot_pos > 8: + sfn[6] = '~' + sfn[7] = '1' + sfn[11] = 0 -def sfn_to_str(sfn: t.CConst | t.CChar | t.CPtr, out: t.CChar | t.CPtr): - i: int = 0 - j: int = 0 - for i in range(8): - if sfn[i] == 0x20: break - if sfn[i] == 0x05: out[j] = 0xE5 - else: out[j] = sfn[i] - j += 1 - if sfn[8] != 0x20: - out[j] = '.'; j += 1 - for i in range(8, 11): - if sfn[i] == 0x20: break - out[j] = sfn[i]; j += 1 - out[j] = 0 -def _split_path(path: t.CConst | t.CChar | t.CPtr, parent_out: t.CChar | t.CPtr, name_out: t.CChar | t.CPtr): - # parent_out/name_out 分别按 PATH_MAX(260)/NAME_MAX(255) 截断, - # 避免超长 path 无界复制越界写调用方缓冲(pp[260]/fn[256] 等)。 - pi: int = 0; last_sep: int = -1 - for ch in path: - if pi >= PATH_MAX - 1: break - parent_out[pi] = ch - if ch == '/' or ch == '\\': last_sep = pi - pi += 1 - parent_out[pi] = 0 - if last_sep >= 0: - ni: int = 0 - fi: int - for fi in range(last_sep + 1, pi): - if ni >= NAME_MAX: break - name_out[ni] = path[fi] - ni += 1 - name_out[ni] = 0 - parent_out[last_sep] = 0 - else: - ni2: int = 0 - fi2: int - for fi2 in range(pi): - if ni2 >= NAME_MAX: break - name_out[ni2] = path[fi2] - ni2 += 1 - name_out[ni2] = 0 - parent_out[0] = '/'; parent_out[1] = 0 +def sfn_to_str(sfn: const str, out: str): + j: int = 0 + for i in range(8): + if sfn[i] == 0x20: break + if sfn[i] == 0x05: out[j] = 0xE5 + else: out[j] = sfn[i] + j += 1 + if sfn[8] != 0x20: + out[j] = '.'; j += 1 + for i in range(8, 11): + if sfn[i] == 0x20: break + out[j] = sfn[i]; j += 1 + out[j] = 0 + +def _split_path(path: const str, parent_out: str, name_out: str): + # parent_out/name_out 分别按 PATH_MAX(260)/NAME_MAX(255) 截断, + # 避免超长 path 无界复制越界写调用方缓冲(pp[260]/fn[256] 等)。 + pi: int = 0; last_sep: int = -1 + for ch in path: + if pi >= PATH_MAX - 1: break + parent_out[pi] = ch + if ch == '/' or ch == '\\': last_sep = pi + pi += 1 + parent_out[pi] = 0 + if last_sep >= 0: + ni: int = 0 + fi: int + for fi in range(last_sep + 1, pi): + if ni >= NAME_MAX: break + name_out[ni] = path[fi] + ni += 1 + name_out[ni] = 0 + parent_out[last_sep] = 0 + else: + ni2: int = 0 + fi2: int + for fi2 in range(pi): + if ni2 >= NAME_MAX: break + name_out[ni2] = path[fi2] + ni2 += 1 + name_out[ni2] = 0 + parent_out[0] = '/'; parent_out[1] = 0 class fileinfo: - file_size: uint32 = 0 - attr: uint8 = 0 - ctime: uint16 = 0 - cdate: uint16 = 0 - mtime: uint16 = 0 - mdate: uint16 = 0 - adate: uint16 = 0 - fname: t.CArray[t.CChar, 256] - altname: t.CArray[t.CChar, 13] + file_size: uint32 = 0 + attr: uint8 = 0 + ctime: uint16 = 0 + cdate: uint16 = 0 + mtime: uint16 = 0 + mdate: uint16 = 0 + adate: uint16 = 0 + fname: [256]char + altname: [13]char class filelock: - cluster: uint32 = 0 - dir_sector: uint64 = 0 - dir_offset: uint32 = 0 - in_use: int = 0 - shared_count: int = 0 - exclusive: int = 0 + cluster: uint32 = 0 + dir_sector: uint64 = 0 + dir_offset: uint32 = 0 + in_use: int = 0 + shared_count: int = 0 + exclusive: int = 0 -@t.Object class volinfo: - lock: spinlock._spinlock - mounted: int = 0 - pdrv: uint8 = 0 - sector_size: uint16 = 512 - cluster_size: uint32 = 0 - cluster_sectors: uint8 = 0 - fat_start: uint64 = 0 - fat_size: uint32 = 0 - data_start: uint64 = 0 - root_cluster: uint32 = 2 - total_sectors: uint64 = 0 - total_clusters: uint32 = 0 - free_clusters: uint32 = 4294967295 - last_alloc: uint32 = 2 - fsinfo_sector: uint16 = 0 - backup_sector: uint16 = 6 - vol_id: uint32 = 0 - vol_label: t.CArray[t.CChar, 12] - num_fats: uint8 = 2 - reserved_sectors: uint16 = 0 - hidden_sectors: uint32 = 0 - winsect: uint64 = 0xFFFFFFFFFFFFFFFF - win_dirty: int = 0 - win: t.CArray[uint8, 512] - fat_winsect: uint64 = 0xFFFFFFFFFFFFFFFF - fat_win_dirty: int = 0 - fat_win: t.CArray[uint8, 512] - metadata: uint32 = 0 - last_error: uint32 = 0 + lock: spinlock._spinlock + mounted: int = 0 + pdrv: uint8 = 0 + sector_size: uint16 = 512 + cluster_size: uint32 = 0 + cluster_sectors: uint8 = 0 + fat_start: uint64 = 0 + fat_size: uint32 = 0 + data_start: uint64 = 0 + root_cluster: uint32 = 2 + total_sectors: uint64 = 0 + total_clusters: uint32 = 0 + free_clusters: uint32 = 4294967295 + last_alloc: uint32 = 2 + fsinfo_sector: uint16 = 0 + backup_sector: uint16 = 6 + vol_id: uint32 = 0 + vol_label: [12]char + num_fats: uint8 = 2 + reserved_sectors: uint16 = 0 + hidden_sectors: uint32 = 0 + winsect: uint64 = 0xFFFFFFFFFFFFFFFF + win_dirty: int = 0 + win: [512]uint8 + fat_winsect: uint64 = 0xFFFFFFFFFFFFFFFF + fat_win_dirty: int = 0 + fat_win: [512]uint8 + metadata: uint32 = 0 + last_error: uint32 = 0 - def win_read(self, sector: uint64) -> FRESULT: - if self.winsect == sector: return FRESULT.FR_OK - if self.win_dirty: - res: FRESULT = self.win_flush() - if res != FRESULT.FR_OK: return res - abs_sector: uint64 = sector + uint64(self.hidden_sectors) - self.lock.lock() - win_addr: t.CPtr = c.Addr(self.win[0]) - res2: DRESULT = diskio.read(self.pdrv, win_addr, uint32(abs_sector), 1) - self.lock.unlock() - if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR - # [DIAG] 定位 win[0..1] 被清零(L271 win=00 00 20...):区分读错扇区 - # vs 读后被覆盖——打印 abs_sector 与读后 win 前 4 字节。 - _dwr: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_dwr), 96, "[wr] sec=%lx abs=%lx hid=%lx w0=%02x %02x %02x %02x\n", - sector, abs_sector, uint64(self.hidden_sectors), - self.win[0], self.win[1], self.win[2], self.win[3]) - serial.puts(c.Addr(_dwr)) - self.winsect = sector - return FRESULT.FR_OK + def win_read(self, sector: uint64) -> FRESULT: + if self.winsect == sector: return FRESULT.FR_OK + if self.win_dirty: + res: FRESULT = self.win_flush() + if res != FRESULT.FR_OK: return res + abs_sector: uint64 = sector + uint64(self.hidden_sectors) + self.lock.lock() + win_addr: rawptr = &self.win[0] + res2: DRESULT = diskio.read(self.pdrv, win_addr, uint32(abs_sector), 1) + self.lock.unlock() + if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR + self.winsect = sector + return FRESULT.FR_OK - def win_flush(self) -> FRESULT: - if not self.win_dirty: return FRESULT.FR_OK - abs_sector: uint64 = self.winsect + uint64(self.hidden_sectors) - self.lock.lock() - res: DRESULT = diskio.write(self.pdrv, c.Addr(self.win[0]), uint32(abs_sector), 1) - self.lock.unlock() - if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR - self.win_dirty = 0 - return FRESULT.FR_OK + def win_flush(self) -> FRESULT: + if not self.win_dirty: return FRESULT.FR_OK + abs_sector: uint64 = self.winsect + uint64(self.hidden_sectors) + self.lock.lock() + res: DRESULT = diskio.write(self.pdrv, &self.win[0], uint32(abs_sector), 1) + self.lock.unlock() + if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR + self.win_dirty = 0 + return FRESULT.FR_OK - def fat_win_read(self, sector: uint64) -> FRESULT: - if self.fat_winsect == sector: return FRESULT.FR_OK - if self.fat_win_dirty: - res: FRESULT = self.fat_win_flush() - if res != FRESULT.FR_OK: return res - abs_sector: uint64 = sector + uint64(self.hidden_sectors) - self.lock.lock() - res2: DRESULT = diskio.read(self.pdrv, c.Addr(self.fat_win[0]), uint32(abs_sector), 1) - self.lock.unlock() - if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR - self.fat_winsect = sector - return FRESULT.FR_OK + def fat_win_read(self, sector: uint64) -> FRESULT: + if self.fat_winsect == sector: return FRESULT.FR_OK + if self.fat_win_dirty: + res: FRESULT = self.fat_win_flush() + if res != FRESULT.FR_OK: return res + abs_sector: uint64 = sector + uint64(self.hidden_sectors) + self.lock.lock() + res2: DRESULT = diskio.read(self.pdrv, &self.fat_win[0], uint32(abs_sector), 1) + self.lock.unlock() + if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR + self.fat_winsect = sector + return FRESULT.FR_OK - def fat_win_flush(self) -> FRESULT: - if not self.fat_win_dirty: return FRESULT.FR_OK - abs_sector: uint64 = self.fat_winsect + uint64(self.hidden_sectors) - self.lock.lock() - res: DRESULT = diskio.write(self.pdrv, c.Addr(self.fat_win[0]), uint32(abs_sector), 1) - self.lock.unlock() - if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR - self.fat_win_dirty = 0 - return FRESULT.FR_OK + def fat_win_flush(self) -> FRESULT: + if not self.fat_win_dirty: return FRESULT.FR_OK + abs_sector: uint64 = self.fat_winsect + uint64(self.hidden_sectors) + self.lock.lock() + res: DRESULT = diskio.write(self.pdrv, &self.fat_win[0], uint32(abs_sector), 1) + self.lock.unlock() + if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR + self.fat_win_dirty = 0 + return FRESULT.FR_OK - def flush_all(self) -> FRESULT: - res: FRESULT = self.win_flush() - if res != FRESULT.FR_OK: return res - return self.fat_win_flush() + def flush_all(self) -> FRESULT: + res: FRESULT = self.win_flush() + if res != FRESULT.FR_OK: return res + return self.fat_win_flush() - def fat_read(self, cluster: uint32) -> uint32: - if cluster < 2 or cluster >= self.total_clusters + 2: return 0 - fat_offset: uint64 = uint64(cluster) * 4 - fat_sector: uint64 = self.fat_start + (fat_offset / 512) - fat_offset_in_sector: uint32 = uint32(fat_offset % 512) - res: FRESULT = self.fat_win_read(fat_sector) - if res != FRESULT.FR_OK: return 0 - return _read32(c.Addr(self.fat_win[0]), fat_offset_in_sector) & FAT_MASK + def fat_read(self, cluster: uint32) -> uint32: + if cluster < 2 or cluster >= self.total_clusters + 2: return 0 + fat_offset: uint64 = uint64(cluster) * 4 + fat_sector: uint64 = self.fat_start + (fat_offset / 512) + fat_offset_in_sector: uint32 = uint32(fat_offset % 512) + res: FRESULT = self.fat_win_read(fat_sector) + if res != FRESULT.FR_OK: return 0 + return _read32(&self.fat_win[0], fat_offset_in_sector) & FAT_MASK - def fat_write(self, cluster: uint32, value: uint32) -> FRESULT: - if cluster < 2 or cluster >= self.total_clusters + 2: return FRESULT.FR_INVALID_PARAMETER - fat_offset: uint64 = uint64(cluster) * 4 - fat_sector: uint64 = self.fat_start + (fat_offset / 512) - fat_offset_in_sector: uint32 = uint32(fat_offset % 512) - res: FRESULT = self.fat_win_read(fat_sector) - if res != FRESULT.FR_OK: return res - old: uint32 = _read32(c.Addr(self.fat_win[0]), fat_offset_in_sector) - new_val: uint32 = (old & FAT_RESERVED) | (value & FAT_MASK) - _write32(c.Addr(self.fat_win[0]), fat_offset_in_sector, new_val) - self.fat_win_dirty = 1 - res = self.fat_win_flush() - if res != FRESULT.FR_OK: return res - if self.num_fats >= 2: - mirror_sector: uint64 = fat_sector + uint64(self.fat_size) - res2: FRESULT = self.fat_win_read(mirror_sector) - if res2 != FRESULT.FR_OK: return res2 - mirror_old: uint32 = _read32(c.Addr(self.fat_win[0]), fat_offset_in_sector) - mirror_new: uint32 = (mirror_old & FAT_RESERVED) | (value & FAT_MASK) - _write32(c.Addr(self.fat_win[0]), fat_offset_in_sector, mirror_new) - self.fat_win_dirty = 1 - res3: FRESULT = self.fat_win_flush() - if res3 != FRESULT.FR_OK: return res3 - return FRESULT.FR_OK + def fat_write(self, cluster: uint32, value: uint32) -> FRESULT: + if cluster < 2 or cluster >= self.total_clusters + 2: return FRESULT.FR_INVALID_PARAMETER + fat_offset: uint64 = uint64(cluster) * 4 + fat_sector: uint64 = self.fat_start + (fat_offset / 512) + fat_offset_in_sector: uint32 = uint32(fat_offset % 512) + res: FRESULT = self.fat_win_read(fat_sector) + if res != FRESULT.FR_OK: return res + old: uint32 = _read32(&self.fat_win[0], fat_offset_in_sector) + new_val: uint32 = (old & FAT_RESERVED) | (value & FAT_MASK) + _write32(&self.fat_win[0], fat_offset_in_sector, new_val) + self.fat_win_dirty = 1 + res = self.fat_win_flush() + if res != FRESULT.FR_OK: return res + if self.num_fats >= 2: + mirror_sector: uint64 = fat_sector + uint64(self.fat_size) + res2: FRESULT = self.fat_win_read(mirror_sector) + if res2 != FRESULT.FR_OK: return res2 + mirror_old: uint32 = _read32(&self.fat_win[0], fat_offset_in_sector) + mirror_new: uint32 = (mirror_old & FAT_RESERVED) | (value & FAT_MASK) + _write32(&self.fat_win[0], fat_offset_in_sector, mirror_new) + self.fat_win_dirty = 1 + res3: FRESULT = self.fat_win_flush() + if res3 != FRESULT.FR_OK: return res3 + return FRESULT.FR_OK - def cluster_alloc(self) -> uint32: - clust: uint32 = self.last_alloc - i: uint32 - for i in range(self.total_clusters): - clust += 1 - if clust >= self.total_clusters + 2: clust = 2 - entry: uint32 = self.fat_read(clust) - if entry == CLUSTER_FREE: - res: FRESULT = self.fat_write(clust, CLUSTER_EOC_MAX) - if res != FRESULT.FR_OK: return 0 - self.last_alloc = clust - if self.free_clusters != 0xFFFFFFFF: self.free_clusters -= 1 - return clust - return 0 + def cluster_alloc(self) -> uint32: + clust: uint32 = self.last_alloc + i: uint32 + for i in range(self.total_clusters): + clust += 1 + if clust >= self.total_clusters + 2: clust = 2 + entry: uint32 = self.fat_read(clust) + if entry == CLUSTER_FREE: + res: FRESULT = self.fat_write(clust, CLUSTER_EOC_MAX) + if res != FRESULT.FR_OK: return 0 + self.last_alloc = clust + if self.free_clusters != 0xFFFFFFFF: self.free_clusters -= 1 + return clust + return 0 - def cluster_free_chain(self, start_cluster: uint32) -> FRESULT: - if start_cluster < 2: return FRESULT.FR_OK - clust: uint32 = start_cluster - while clust >= 2 and clust < CLUSTER_EOC_MIN: - next_clust: uint32 = self.fat_read(clust) - if next_clust == 0: break - res: FRESULT = self.fat_write(clust, CLUSTER_FREE) - if res != FRESULT.FR_OK: return res - if self.free_clusters != 0xFFFFFFFF: self.free_clusters += 1 - clust = next_clust - return FRESULT.FR_OK + def cluster_free_chain(self, start_cluster: uint32) -> FRESULT: + if start_cluster < 2: return FRESULT.FR_OK + clust: uint32 = start_cluster + while clust >= 2 and clust < CLUSTER_EOC_MIN: + next_clust: uint32 = self.fat_read(clust) + if next_clust == 0: break + res: FRESULT = self.fat_write(clust, CLUSTER_FREE) + if res != FRESULT.FR_OK: return res + if self.free_clusters != 0xFFFFFFFF: self.free_clusters += 1 + clust = next_clust + return FRESULT.FR_OK - def cluster_extend(self, cluster: uint32) -> uint32: - new_clust: uint32 = self.cluster_alloc() - if new_clust == 0: return 0 - if cluster >= 2: - res: FRESULT = self.fat_write(cluster, new_clust) - if res != FRESULT.FR_OK: - self.fat_write(new_clust, CLUSTER_FREE) - return 0 - return new_clust + def cluster_extend(self, cluster: uint32) -> uint32: + new_clust: uint32 = self.cluster_alloc() + if new_clust == 0: return 0 + if cluster >= 2: + res: FRESULT = self.fat_write(cluster, new_clust) + if res != FRESULT.FR_OK: + self.fat_write(new_clust, CLUSTER_FREE) + return 0 + return new_clust - def cluster_get_next(self, cluster: uint32) -> uint32: - if cluster < 2: return 0 - entry: uint32 = self.fat_read(cluster) - if entry >= CLUSTER_EOC_MIN and entry <= CLUSTER_EOC_MAX: return 0 - if entry == CLUSTER_FREE or entry == CLUSTER_BAD: return 0 - return entry + def cluster_get_next(self, cluster: uint32) -> uint32: + if cluster < 2: return 0 + entry: uint32 = self.fat_read(cluster) + if entry >= CLUSTER_EOC_MIN and entry <= CLUSTER_EOC_MAX: return 0 + if entry == CLUSTER_FREE or entry == CLUSTER_BAD: return 0 + return entry - def cluster_to_sector(self, cluster: uint32) -> uint64: - if cluster < 2: return 0 - return self.data_start + uint64(cluster - 2) * uint64(self.cluster_sectors) + def cluster_to_sector(self, cluster: uint32) -> uint64: + if cluster < 2: return 0 + return self.data_start + uint64(cluster - 2) * uint64(self.cluster_sectors) - def entries_per_cluster(self) -> uint32: - return uint32(self.cluster_sectors) * (512 / ENTRY_SIZE) + def entries_per_cluster(self) -> uint32: + return uint32(self.cluster_sectors) * (512 / ENTRY_SIZE) - def is_eoc(self, cluster: uint32) -> int: - return 1 if (cluster >= CLUSTER_EOC_MIN and cluster <= CLUSTER_EOC_MAX) else 0 + def is_eoc(self, cluster: uint32) -> int: + return 1 if (cluster >= CLUSTER_EOC_MIN and cluster <= CLUSTER_EOC_MAX) else 0 - def fsinfo_read(self) -> FRESULT: - if self.fsinfo_sector == 0: return FRESULT.FR_OK - res: FRESULT = self.win_read(uint64(self.fsinfo_sector)) - if res != FRESULT.FR_OK: return res - lead_sig: uint32 = _read32(c.Addr(self.win[0]), 0) - struc_sig: uint32 = _read32(c.Addr(self.win[0]), 484) - trail_sig: uint32 = _read32(c.Addr(self.win[0]), 508) - if lead_sig != 0x41615252 or struc_sig != 0x61417272 or trail_sig != 0xAA550000: - self.free_clusters = 0xFFFFFFFF - self.last_alloc = 2 - return FRESULT.FR_OK - free_count: uint32 = _read32(c.Addr(self.win[0]), 488) - nxt_free: uint32 = _read32(c.Addr(self.win[0]), 492) - if free_count <= self.total_clusters: self.free_clusters = free_count - if nxt_free >= 2 and nxt_free < self.total_clusters + 2: self.last_alloc = nxt_free - return FRESULT.FR_OK + def fsinfo_read(self) -> FRESULT: + if self.fsinfo_sector == 0: return FRESULT.FR_OK + res: FRESULT = self.win_read(uint64(self.fsinfo_sector)) + if res != FRESULT.FR_OK: return res + lead_sig: uint32 = _read32(&self.win[0], 0) + struc_sig: uint32 = _read32(&self.win[0], 484) + trail_sig: uint32 = _read32(&self.win[0], 508) + if lead_sig != 0x41615252 or struc_sig != 0x61417272 or trail_sig != 0xAA550000: + self.free_clusters = 0xFFFFFFFF + self.last_alloc = 2 + return FRESULT.FR_OK + free_count: uint32 = _read32(&self.win[0], 488) + nxt_free: uint32 = _read32(&self.win[0], 492) + if free_count <= self.total_clusters: self.free_clusters = free_count + if nxt_free >= 2 and nxt_free < self.total_clusters + 2: self.last_alloc = nxt_free + return FRESULT.FR_OK - def fsinfo_write(self) -> FRESULT: - if self.fsinfo_sector == 0: return FRESULT.FR_OK - res: FRESULT = self.win_read(uint64(self.fsinfo_sector)) - if res != FRESULT.FR_OK: return res - _write32(c.Addr(self.win[0]), 0, 0x41615252) - _write32(c.Addr(self.win[0]), 484, 0x61417272) - _write32(c.Addr(self.win[0]), 488, self.free_clusters) - _write32(c.Addr(self.win[0]), 492, self.last_alloc) - _write32(c.Addr(self.win[0]), 508, 0xAA550000) - self.win_dirty = 1 - return self.win_flush() + def fsinfo_write(self) -> FRESULT: + if self.fsinfo_sector == 0: return FRESULT.FR_OK + res: FRESULT = self.win_read(uint64(self.fsinfo_sector)) + if res != FRESULT.FR_OK: return res + _write32(&self.win[0], 0, 0x41615252) + _write32(&self.win[0], 484, 0x61417272) + _write32(&self.win[0], 488, self.free_clusters) + _write32(&self.win[0], 492, self.last_alloc) + _write32(&self.win[0], 508, 0xAA550000) + self.win_dirty = 1 + return self.win_flush() - def count_free_clusters(self) -> uint32: - free_cnt: uint32 = 0 - clust: uint32 - for clust in range(2, self.total_clusters + 2): - entry: uint32 = self.fat_read(clust) - if entry == CLUSTER_FREE: free_cnt += 1 - self.free_clusters = free_cnt - return free_cnt + def count_free_clusters(self) -> uint32: + free_cnt: uint32 = 0 + clust: uint32 + for clust in range(2, self.total_clusters + 2): + entry: uint32 = self.fat_read(clust) + if entry == CLUSTER_FREE: free_cnt += 1 + self.free_clusters = free_cnt + return free_cnt - def mount(self) -> FRESULT: - if self.mounted: return FRESULT.FR_OK - res: DRESULT = diskio.status(self.pdrv) - if res != DRESULT.RES_OK: - res = diskio.init(self.pdrv) - if res != DRESULT.RES_OK: return FRESULT.FR_NOT_READY - res2: FRESULT = self.win_read(0) - if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - bps: uint16 = _read16(c.Addr(self.win[0]), 11) - spc: uint8 = self.win[13] - rsc: uint16 = _read16(c.Addr(self.win[0]), 14) - nf: uint8 = self.win[16] - root_ent: uint16 = _read16(c.Addr(self.win[0]), 17) - fat16sz: uint16 = _read16(c.Addr(self.win[0]), 22) - tot32: uint32 = _read32(c.Addr(self.win[0]), 32) - fat32sz: uint32 = _read32(c.Addr(self.win[0]), 36) - root_clus: uint32 = _read32(c.Addr(self.win[0]), 44) - sig0: uint8 = self.win[510] - sig1: uint8 = self.win[511] - if bps != 512: return FRESULT.FR_NO_FILESYSTEM - if spc == 0 or (spc & (spc - 1)) != 0: return FRESULT.FR_NO_FILESYSTEM - if rsc == 0: return FRESULT.FR_NO_FILESYSTEM - if nf == 0: return FRESULT.FR_NO_FILESYSTEM - if root_ent != 0 or fat16sz != 0: return FRESULT.FR_NO_FILESYSTEM - if fat32sz == 0: return FRESULT.FR_NO_FILESYSTEM - if tot32 == 0: return FRESULT.FR_NO_FILESYSTEM - if sig0 != 0x55 or sig1 != 0xAA: return FRESULT.FR_NO_FILESYSTEM - fsinfo_sec: uint16 = _read16(c.Addr(self.win[0]), 48) - bkboot_sec: uint16 = _read16(c.Addr(self.win[0]), 50) - self.sector_size = 512 - self.cluster_sectors = spc - self.cluster_size = uint32(spc) * 512 - self.num_fats = nf - self.reserved_sectors = rsc - self.fat_size = fat32sz - self.fat_start = uint64(rsc) - self.total_sectors = uint64(tot32) - self.root_cluster = root_clus - self.fsinfo_sector = fsinfo_sec - self.backup_sector = bkboot_sec - self.vol_id = _read32(c.Addr(self.win[0]), 67) - data_sectors: uint64 = self.total_sectors - uint64(rsc) - uint64(uint64(nf) * uint64(fat32sz)) - self.total_clusters = uint32(data_sectors / uint64(spc)) - self.data_start = self.fat_start + uint64(uint64(nf) * uint64(fat32sz)) - self.last_alloc = 2 - self.free_clusters = 0xFFFFFFFF - self.fsinfo_read() - self.mounted = 1 - return FRESULT.FR_OK + def mount(self) -> FRESULT: + if self.mounted: return FRESULT.FR_OK + res: DRESULT = diskio.status(self.pdrv) + if res != DRESULT.RES_OK: + res = diskio.init(self.pdrv) + if res != DRESULT.RES_OK: return FRESULT.FR_NOT_READY + res2: FRESULT = self.win_read(0) + if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + bps: uint16 = _read16(&self.win[0], 11) + spc: uint8 = self.win[13] + rsc: uint16 = _read16(&self.win[0], 14) + nf: uint8 = self.win[16] + root_ent: uint16 = _read16(&self.win[0], 17) + fat16sz: uint16 = _read16(&self.win[0], 22) + tot32: uint32 = _read32(&self.win[0], 32) + fat32sz: uint32 = _read32(&self.win[0], 36) + root_clus: uint32 = _read32(&self.win[0], 44) + sig0: uint8 = self.win[510] + sig1: uint8 = self.win[511] + if bps != 512: return FRESULT.FR_NO_FILESYSTEM + if spc == 0 or (spc & (spc - 1)) != 0: return FRESULT.FR_NO_FILESYSTEM + if rsc == 0: return FRESULT.FR_NO_FILESYSTEM + if nf == 0: return FRESULT.FR_NO_FILESYSTEM + if root_ent != 0 or fat16sz != 0: return FRESULT.FR_NO_FILESYSTEM + if fat32sz == 0: return FRESULT.FR_NO_FILESYSTEM + if tot32 == 0: return FRESULT.FR_NO_FILESYSTEM + if sig0 != 0x55 or sig1 != 0xAA: return FRESULT.FR_NO_FILESYSTEM + fsinfo_sec: uint16 = _read16(&self.win[0], 48) + bkboot_sec: uint16 = _read16(&self.win[0], 50) + self.sector_size = 512 + self.cluster_sectors = spc + self.cluster_size = uint32(spc) * 512 + self.num_fats = nf + self.reserved_sectors = rsc + self.fat_size = fat32sz + self.fat_start = uint64(rsc) + self.total_sectors = uint64(tot32) + self.root_cluster = root_clus + self.fsinfo_sector = fsinfo_sec + self.backup_sector = bkboot_sec + self.vol_id = _read32(&self.win[0], 67) + data_sectors: uint64 = self.total_sectors - uint64(rsc) - uint64(uint64(nf) * uint64(fat32sz)) + self.total_clusters = uint32(data_sectors / uint64(spc)) + self.data_start = self.fat_start + uint64(uint64(nf) * uint64(fat32sz)) + self.last_alloc = 2 + self.free_clusters = 0xFFFFFFFF + self.fsinfo_read() + self.mounted = 1 + return FRESULT.FR_OK - def unmount(self) -> FRESULT: - if not self.mounted: return FRESULT.FR_OK - res: FRESULT = self.flush_all() - if res != FRESULT.FR_OK: return res - self.fsinfo_write() - self.mounted = 0 - self.winsect = 0xFFFFFFFFFFFFFFFF - self.win_dirty = 0 - self.fat_winsect = 0xFFFFFFFFFFFFFFFF - self.fat_win_dirty = 0 - return FRESULT.FR_OK + def unmount(self) -> FRESULT: + if not self.mounted: return FRESULT.FR_OK + res: FRESULT = self.flush_all() + if res != FRESULT.FR_OK: return res + self.fsinfo_write() + self.mounted = 0 + self.winsect = 0xFFFFFFFFFFFFFFFF + self.win_dirty = 0 + self.fat_winsect = 0xFFFFFFFFFFFFFFFF + self.fat_win_dirty = 0 + return FRESULT.FR_OK - def _zero_cluster(self, cluster: uint32) -> FRESULT: - sector: uint64 = self.cluster_to_sector(cluster) - s: uint32 - for s in range(self.cluster_sectors): - res: FRESULT = self.win_read(sector + uint64(s)) - if res != FRESULT.FR_OK: return res - string.memset(c.Addr(self.win[0]), 0, 512) - self.win_dirty = 1 - res2: FRESULT = self.win_flush() - if res2 != FRESULT.FR_OK: return res2 - return FRESULT.FR_OK + def _zero_cluster(self, cluster: uint32) -> FRESULT: + sector: uint64 = self.cluster_to_sector(cluster) + s: uint32 + for s in range(self.cluster_sectors): + res: FRESULT = self.win_read(sector + uint64(s)) + if res != FRESULT.FR_OK: return res + string.memset(&self.win[0], 0, 512) + self.win_dirty = 1 + res2: FRESULT = self.win_flush() + if res2 != FRESULT.FR_OK: return res2 + return FRESULT.FR_OK - def file_cluster_seek(self, first_cluster: uint32, pos: uint32) -> uint32: - if first_cluster < 2: return 0 - cluster: uint32 = first_cluster - cluster_num: uint32 = pos / self.cluster_size - i: uint32 - for i in range(cluster_num): - next_c: uint32 = self.cluster_get_next(cluster) - if next_c == 0: return 0 - cluster = next_c - return cluster + def file_cluster_seek(self, first_cluster: uint32, pos: uint32) -> uint32: + if first_cluster < 2: return 0 + cluster: uint32 = first_cluster + cluster_num: uint32 = pos / self.cluster_size + i: uint32 + for i in range(cluster_num): + next_c: uint32 = self.cluster_get_next(cluster) + if next_c == 0: return 0 + cluster = next_c + return cluster - def file_find_last_cluster(self, first_cluster: uint32) -> uint32: - if first_cluster < 2: return 0 - cluster: uint32 = first_cluster - while True: - next_c: uint32 = self.cluster_get_next(cluster) - if next_c == 0: return cluster - cluster = next_c + def file_find_last_cluster(self, first_cluster: uint32) -> uint32: + if first_cluster < 2: return 0 + cluster: uint32 = first_cluster + while True: + next_c: uint32 = self.cluster_get_next(cluster) + if next_c == 0: return cluster + cluster = next_c - def _read_entry_from_dir(self, dp: dirobj | t.CPtr) -> FRESULT: - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - return self.win_read(entry_sector) + def _read_entry_from_dir(self, dp: dirobj*) -> FRESULT: + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + return self.win_read(entry_sector) - def _write_dirent_now(self, eo: uint32): - now: uint32 = ftime.get_fattime() - fat_time: uint16 = uint16(now & 0xFFFF) - fat_date: uint16 = uint16((now >> 16) & 0xFFFF) - _write16(c.Addr(self.win[0]), eo + 14, fat_time) - _write16(c.Addr(self.win[0]), eo + 16, fat_date) - _write16(c.Addr(self.win[0]), eo + 18, fat_date) - _write16(c.Addr(self.win[0]), eo + 22, fat_time) - _write16(c.Addr(self.win[0]), eo + 24, fat_date) + def _write_dirent_now(self, eo: uint32): + now: uint32 = ftime.get_fattime() + fat_time: uint16 = uint16(now & 0xFFFF) + fat_date: uint16 = uint16((now >> 16) & 0xFFFF) + _write16(&self.win[0], eo + 14, fat_time) + _write16(&self.win[0], eo + 16, fat_date) + _write16(&self.win[0], eo + 18, fat_date) + _write16(&self.win[0], eo + 22, fat_time) + _write16(&self.win[0], eo + 24, fat_date) - def dir_offset_to_sector(self, start_cluster: uint32, offset: uint32) -> uint64: - epc: uint32 = self.entries_per_cluster() - cluster: uint32 = start_cluster - cluster_idx: uint32 = offset / epc - i: uint32 - for i in range(cluster_idx): - next_c: uint32 = self.cluster_get_next(cluster) - if next_c == 0: return 0 - cluster = next_c - off_in_cluster: uint32 = offset % epc - return self.cluster_to_sector(cluster) + uint64(off_in_cluster / (512 / ENTRY_SIZE)) + def dir_offset_to_sector(self, start_cluster: uint32, offset: uint32) -> uint64: + epc: uint32 = self.entries_per_cluster() + cluster: uint32 = start_cluster + cluster_idx: uint32 = offset / epc + i: uint32 + for i in range(cluster_idx): + next_c: uint32 = self.cluster_get_next(cluster) + if next_c == 0: return 0 + cluster = next_c + off_in_cluster: uint32 = offset % epc + return self.cluster_to_sector(cluster) + uint64(off_in_cluster / (512 / ENTRY_SIZE)) - def dir_next_cluster(self, dp: dirobj | t.CPtr) -> FRESULT: - next_clust: uint32 = self.cluster_get_next(dp.cluster) - if next_clust == 0: return FRESULT.FR_NO_FILE - dp.cluster = next_clust - dp.sector = self.cluster_to_sector(next_clust) - dp.offset = 0 - return FRESULT.FR_OK + def dir_next_cluster(self, dp: dirobj*) -> FRESULT: + next_clust: uint32 = self.cluster_get_next(dp.cluster) + if next_clust == 0: return FRESULT.FR_NO_FILE + dp.cluster = next_clust + dp.sector = self.cluster_to_sector(next_clust) + dp.offset = 0 + return FRESULT.FR_OK - def dir_open(self, dp: dirobj | t.CPtr, cluster: uint32) -> FRESULT: - dp.vol = self - dp.start_cluster = cluster - dp.cluster = cluster - dp.sector = self.cluster_to_sector(cluster) - dp.offset = 0 - dp.is_open = 1 - dp.lfn_ofs = 0xFFFFFFFF - dp.lfn_cluster = 0 - self.winsect = 0xFFFFFFFFFFFFFFFF - return FRESULT.FR_OK + def dir_open(self, dp: dirobj*, cluster: uint32) -> FRESULT: + dp.vol = self + dp.start_cluster = cluster + dp.cluster = cluster + dp.sector = self.cluster_to_sector(cluster) + dp.offset = 0 + dp.is_open = 1 + dp.lfn_ofs = 0xFFFFFFFF + dp.lfn_cluster = 0 + self.winsect = 0xFFFFFFFFFFFFFFFF + return FRESULT.FR_OK - def dir_read_entry(self, dp: dirobj | t.CPtr, lfn_buf: uint16 | t.CPtr) -> FRESULT: - lfn_started: int = 0 - dp.lfn_ofs = 0xFFFFFFFF - dp.lfn_cluster = 0 - while True: - epc: uint32 = self.entries_per_cluster() - if dp.offset >= epc: - res: FRESULT = self.dir_next_cluster(dp) - if res != FRESULT.FR_OK: return res - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res2: FRESULT = self.win_read(entry_sector) - if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - first_byte: uint8 = self.win[entry_offset_in_sector] - if first_byte == SFN_FREE: - return FRESULT.FR_NO_FILE - attr: uint8 = self.win[entry_offset_in_sector + 11] - if first_byte == SFN_DELETED: - lfn_started = 0 - dp.lfn_ofs = 0xFFFFFFFF - dp.lfn_cluster = 0 - dp.offset += 1 - continue - if attr == LFN_ATTR: - if lfn_buf: - ord_val: uint8 = first_byte - if ord_val & LFN_FLAG_LAST: - lfn_started = 1 - dp.lfn_ofs = dp.offset - dp.lfn_cluster = dp.cluster - if lfn_started: - entry_bytes: uint8 | t.CPtr = uint8(c.Addr(self.win[entry_offset_in_sector]), t.CPtr) - lfn_extract(entry_bytes, lfn_buf, ord_val) - dp.offset += 1 - continue - if attr == AM_VOL: - dp.offset += 1 - continue - if dp.lfn_ofs == 0xFFFFFFFF: - dp.lfn_ofs = dp.offset - dp.lfn_cluster = dp.cluster - return FRESULT.FR_OK + def dir_read_entry(self, dp: dirobj*, lfn_buf: uint16*) -> FRESULT: + lfn_started: int = 0 + dp.lfn_ofs = 0xFFFFFFFF + dp.lfn_cluster = 0 + while True: + epc: uint32 = self.entries_per_cluster() + if dp.offset >= epc: + res: FRESULT = self.dir_next_cluster(dp) + if res != FRESULT.FR_OK: return res + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res2: FRESULT = self.win_read(entry_sector) + if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + first_byte: uint8 = self.win[entry_offset_in_sector] + if first_byte == SFN_FREE: + return FRESULT.FR_NO_FILE + attr: uint8 = self.win[entry_offset_in_sector + 11] + if first_byte == SFN_DELETED: + lfn_started = 0 + dp.lfn_ofs = 0xFFFFFFFF + dp.lfn_cluster = 0 + dp.offset += 1 + continue + if attr == LFN_ATTR: + if lfn_buf: + ord_val: uint8 = first_byte + if ord_val & LFN_FLAG_LAST: + lfn_started = 1 + dp.lfn_ofs = dp.offset + dp.lfn_cluster = dp.cluster + if lfn_started: + entry_bytes: uint8* = uint8*(&self.win[entry_offset_in_sector]) + lfn_extract(entry_bytes, lfn_buf, ord_val) + dp.offset += 1 + continue + if attr == AM_VOL: + dp.offset += 1 + continue + if dp.lfn_ofs == 0xFFFFFFFF: + dp.lfn_ofs = dp.offset + dp.lfn_cluster = dp.cluster + return FRESULT.FR_OK - def dir_find(self, dp: dirobj | t.CPtr, name: t.CConst | t.CChar | t.CPtr, lfn_buf: uint16 | t.CPtr) -> FRESULT: - sfn: t.CArray[t.CChar, 12] - sfn_from_lfn(name, c.Addr(sfn[0])) - # [DIAG] sfn 生成字节 hex(hello.elf 应 HELLO..ELF,异常时显示 sfn=H) - _dbhs: t.CArray[t.CChar, 64] - viperlib.snprintf(c.Addr(_dbhs), 64, "[sfn] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - sfn[0], sfn[1], sfn[2], sfn[3], sfn[4], sfn[5], - sfn[6], sfn[7], sfn[8], sfn[9], sfn[10]) - serial.puts(c.Addr(_dbhs)) - _dbg_sfn: t.CArray[t.CChar, 16] - _si: int - for _si in range(11): - _dbg_sfn[_si] = sfn[_si] - _dbg_sfn[11] = 0 - serial.puts("[dir_find] searching for: ") - serial.puts(name) - serial.puts(" sfn=") - serial.puts(c.Addr(_dbg_sfn[0])) - serial.puts("\n") - _db0: t.CArray[t.CChar, 120] - viperlib.snprintf(c.Addr(_db0), 120, "[dir_find] dp: sect=0x%lx off=%lu clust=%lu winsect=0x%lx\n", dp.sector, dp.offset, dp.cluster, self.winsect) - serial.puts(_db0) - _find_count: int = 0 - while True: - res: FRESULT = self.dir_read_entry(dp, lfn_buf) - if res != FRESULT.FR_OK: - _db2: t.CArray[t.CChar, 80] - viperlib.snprintf(c.Addr(_db2), 80, "[dir_find] dir_read_entry failed res=%d offset=%lu\n", int(res), dp.offset) - serial.puts(_db2) - # [DIAG] win 缓冲内容 dump(磁盘数据正确但运行时 win 被污染时可见) - _dbw: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_dbw), 96, "[dir_find] win=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x ws=%lx\n", - self.win[0], self.win[1], self.win[2], self.win[3], - self.win[4], self.win[5], self.win[6], self.win[7], - self.win[8], self.win[9], self.win[10], self.win[11], - self.win[12], self.win[13], self.win[14], self.win[15], self.winsect) - serial.puts(c.Addr(_dbw)) - return res - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res2: FRESULT = self.win_read(entry_sector) - if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - match_found: int = 1 - i: int - for i in range(11): - a: t.CChar = self.win[entry_offset_in_sector + i] - b: t.CChar = sfn[i] - if a >= 'a' and a <= 'z': a = a - 32 - if b >= 'a' and b <= 'z': b = b - 32 - if a != b: - match_found = 0 - break - if match_found: return FRESULT.FR_OK - if dp.offset < 10: - _db3: t.CArray[t.CChar, 80] - _fb: uint8 = self.win[entry_offset_in_sector] - _at: uint8 = self.win[entry_offset_in_sector + 11] - viperlib.snprintf(c.Addr(_db3), 80, "[dir_find] off=%lu fb=0x%02x attr=0x%02x sfn=%.11s\n", dp.offset, _fb, _at, c.Addr(self.win[entry_offset_in_sector])) - serial.puts(_db3) - if lfn_buf and dp.lfn_ofs != 0xFFFFFFFF and dp.lfn_ofs < dp.offset: - lfn_matched: int = 1 - li: int = 0 - for name_ch in name: - lfn_ch: uint16 = c.Deref(uint16(uint64(lfn_buf) + li * 2, t.CPtr)) - lfn_low: uint16 = lfn_ch - if lfn_low >= 65 and lfn_low <= 90: lfn_low = lfn_low + 32 - n_low: uint16 = uint16(name_ch) - if n_low >= 65 and n_low <= 90: n_low = n_low + 32 - if lfn_low != n_low: - lfn_matched = 0 - break - li += 1 - if lfn_matched: - lfn_end: uint16 = c.Deref(uint16(uint64(lfn_buf) + li * 2, t.CPtr)) - if lfn_end == 0 or lfn_end == 0xFFFF: - return FRESULT.FR_OK - dp.offset += 1 + def dir_find(self, dp: dirobj*, name: const str, lfn_buf: uint16*) -> FRESULT: + sfn: [12]char + sfn_from_lfn(name, &sfn[0]) + while True: + res: FRESULT = self.dir_read_entry(dp, lfn_buf) + if res != FRESULT.FR_OK: + return res + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res2: FRESULT = self.win_read(entry_sector) + if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + match_found: int = 1 + i: int + for i in range(11): + a: t.CChar = self.win[entry_offset_in_sector + i] + b: t.CChar = sfn[i] + if a >= 'a' and a <= 'z': a = a - 32 + if b >= 'a' and b <= 'z': b = b - 32 + if a != b: + match_found = 0 + break + if match_found: return FRESULT.FR_OK + if lfn_buf and dp.lfn_ofs != 0xFFFFFFFF and dp.lfn_ofs < dp.offset: + lfn_matched: int = 1 + li: int = 0 + for name_ch in name: + lfn_ch: uint16 = *(uint16*(uint64(lfn_buf) + li * 2)) + lfn_low: uint16 = lfn_ch + if lfn_low >= 65 and lfn_low <= 90: lfn_low = lfn_low + 32 + n_low: uint16 = uint16(name_ch) + if n_low >= 65 and n_low <= 90: n_low = n_low + 32 + if lfn_low != n_low: + lfn_matched = 0 + break + li += 1 + if lfn_matched: + lfn_end: uint16 = *(uint16*(uint64(lfn_buf) + li * 2)) + if lfn_end == 0 or lfn_end == 0xFFFF: + return FRESULT.FR_OK + dp.offset += 1 - def dir_get_entry_info(self, dp: dirobj | t.CPtr, info: fileinfo | t.CPtr, lfn_buf: uint16 | t.CPtr) -> FRESULT: - res: FRESULT = self._read_entry_from_dir(dp) - if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - # [DIAG] 定位 win 缓冲污染:磁盘根目录 off=0 应为 "APP" attr=0x10 size=0, - # 但运行时显示 (None) size=523360 → win 内容与磁盘不符。 - _dge: t.CArray[t.CChar, 128] - viperlib.snprintf(c.Addr(_dge), 128, - "[dge] off=%lu w0=%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x attr=%02x size=%lu winsect=%lx\n", - dp.offset, self.win[0], self.win[1], self.win[2], self.win[3], - self.win[4], self.win[5], self.win[6], self.win[7], self.win[8], - self.win[9], self.win[10], self.win[11 + 0], _read32(c.Addr(self.win[0]), 28), self.winsect) - serial.puts(c.Addr(_dge)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - off: uint32 = entry_offset_in_sector - raw_attr: uint8 = self.win[off + 11] - info.attr = raw_attr - info.ctime = _read16(c.Addr(self.win[0]), off + 14) - info.cdate = _read16(c.Addr(self.win[0]), off + 16) - info.adate = _read16(c.Addr(self.win[0]), off + 18) - info.mtime = _read16(c.Addr(self.win[0]), off + 22) - info.mdate = _read16(c.Addr(self.win[0]), off + 24) - info.file_size = _read32(c.Addr(self.win[0]), off + 28) - sfn_ptr: t.CChar | t.CPtr = t.CChar(c.Addr(self.win[0]) + off, t.CPtr) - sfn_to_str(sfn_ptr, c.Addr(info.altname[0])) - if dp.lfn_ofs != 0xFFFFFFFF and dp.lfn_ofs < dp.offset and lfn_buf: - lfn_ptr: uint16 | t.CPtr = lfn_buf - oi: int = 0 - for i in range(MAX_LFN): - ch: uint16 = c.Deref(lfn_ptr) - if ch == 0: break - if ch < 0x80: - info.fname[oi] = t.CChar(ch) - else: - oem_ch: uint16 = uni2oem_placeholder(ch, 0) - if oem_ch < 0x80: info.fname[oi] = t.CChar(oem_ch) - else: info.fname[oi] = '?' - oi += 1 - lfn_ptr = uint16(uint64(lfn_ptr) + 2, t.CPtr) - info.fname[oi] = 0 - else: - sfn_to_str(sfn_ptr, c.Addr(info.fname[0])) - return FRESULT.FR_OK + def dir_get_entry_info(self, dp: dirobj*, info: fileinfo*, lfn_buf: uint16*) -> FRESULT: + res: FRESULT = self._read_entry_from_dir(dp) + if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + off: uint32 = entry_offset_in_sector + raw_attr: uint8 = self.win[off + 11] + info.attr = raw_attr + info.ctime = _read16(&self.win[0], off + 14) + info.cdate = _read16(&self.win[0], off + 16) + info.adate = _read16(&self.win[0], off + 18) + info.mtime = _read16(&self.win[0], off + 22) + info.mdate = _read16(&self.win[0], off + 24) + info.file_size = _read32(&self.win[0], off + 28) + sfn_ptr: str = str(&self.win[0] + off) + sfn_to_str(sfn_ptr, &info.altname[0]) + if dp.lfn_ofs != 0xFFFFFFFF and dp.lfn_ofs < dp.offset and lfn_buf: + lfn_ptr: uint16* = lfn_buf + oi: int = 0 + for i in range(MAX_LFN): + ch: uint16 = *lfn_ptr + if ch == 0: break + if ch < 0x80: + info.fname[oi] = char(ch) + else: + oem_ch: uint16 = uni2oem_placeholder(ch, 0) + if oem_ch < 0x80: info.fname[oi] = char(oem_ch) + else: info.fname[oi] = '?' + oi += 1 + lfn_ptr = uint16*(uint64(lfn_ptr) + 2) + info.fname[oi] = 0 + else: + sfn_to_str(sfn_ptr, &info.fname[0]) + return FRESULT.FR_OK - def dir_add_entry(self, dp: dirobj | t.CPtr, name: t.CConst | t.CChar | t.CPtr, attr: uint8, first_cluster: uint32, file_size: uint32, dir_sector_out: uint64 | t.CPtr, dir_offset_out: uint32 | t.CPtr) -> FRESULT: - sfn: t.CArray[t.CChar, 12] - sfn_from_lfn(name, c.Addr(sfn[0])) - lfn_entries: int = 0 - len_: int = 0 - for _ in name: len_ += 1 - if len_ > 12: - lfn_entries = (len_ + LFN_ENTRY_CHARS - 1) / LFN_ENTRY_CHARS - total_entries: int = lfn_entries + 1 - cur_cluster: uint32 = dp.cluster - cur_sector: uint64 = dp.sector - cur_offset: uint32 = dp.offset - found: int = 0 - consecutive: int = 0 - start_offset: uint32 = 0 - start_cluster: uint32 = 0 - epc: uint32 = self.entries_per_cluster() - while not found: - if cur_offset >= epc: - next_clust: uint32 = self.cluster_get_next(cur_cluster) - if next_clust == 0: - new_clust: uint32 = self.cluster_extend(cur_cluster) - if new_clust == 0: return FRESULT.FR_DENIED - self._zero_cluster(new_clust) - cur_cluster = new_clust - cur_sector = self.cluster_to_sector(new_clust) - cur_offset = 0 - else: - cur_cluster = next_clust - cur_sector = self.cluster_to_sector(next_clust) - cur_offset = 0 - es: uint64 = cur_sector + (cur_offset / (512 / ENTRY_SIZE)) - eo: uint32 = (cur_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res: FRESULT = self.win_read(es) - if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - first_byte: uint8 = self.win[eo] - if first_byte == SFN_FREE or first_byte == SFN_DELETED: - if consecutive == 0: - start_offset = cur_offset - start_cluster = cur_cluster - consecutive += 1 - if consecutive >= total_entries: - found = 1 - break - else: - consecutive = 0 - cur_offset += 1 - write_cluster: uint32 = start_cluster - write_sector: uint64 = self.cluster_to_sector(start_cluster) - write_offset: uint32 = start_offset - if lfn_entries > 0: - le: int - for le in range(lfn_entries): - if write_offset >= epc: - next_c: uint32 = self.cluster_get_next(write_cluster) - if next_c == 0: return FRESULT.FR_INT_ERR - write_cluster = next_c - write_sector = self.cluster_to_sector(next_c) - write_offset = 0 - es2: uint64 = write_sector + (write_offset / (512 / ENTRY_SIZE)) - eo2: uint32 = (write_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res2: FRESULT = self.win_read(es2) - if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - ord_val: uint8 = uint8(lfn_entries - le) - if le == 0: ord_val |= LFN_FLAG_LAST - self.win[eo2 + 0] = ord_val - self.win[eo2 + 11] = LFN_ATTR - self.win[eo2 + 12] = 0 - self.win[eo2 + 13] = sfn_checksum(c.Addr(sfn[0])) - self.win[eo2 + 26] = 0 - self.win[eo2 + 27] = 0 - base: int = (lfn_entries - 1 - le) * LFN_ENTRY_CHARS - j: int - for j in range(LFN_ENTRY_CHARS): - idx: int = base + j - ch: uint16 - if idx < len_: ch = uint16(name[idx]) - elif idx == len_: ch = 0x0000 - else: ch = 0xFFFF - if j < 5: - self.win[eo2 + 1 + j * 2] = uint8(ch & 0xFF) - self.win[eo2 + 2 + j * 2] = uint8((ch >> 8) & 0xFF) - elif j < 11: - self.win[eo2 + 14 + (j - 5) * 2] = uint8(ch & 0xFF) - self.win[eo2 + 15 + (j - 5) * 2] = uint8((ch >> 8) & 0xFF) - else: - self.win[eo2 + 28 + (j - 11) * 2] = uint8(ch & 0xFF) - self.win[eo2 + 29 + (j - 11) * 2] = uint8((ch >> 8) & 0xFF) - self.win_dirty = 1 - self.win_flush() - write_offset += 1 - if write_offset >= epc: - next_c2: uint32 = self.cluster_get_next(write_cluster) - if next_c2 == 0: return FRESULT.FR_INT_ERR - write_cluster = next_c2 - write_sector = self.cluster_to_sector(next_c2) - write_offset = 0 - es3: uint64 = write_sector + (write_offset / (512 / ENTRY_SIZE)) - eo3: uint32 = (write_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res3: FRESULT = self.win_read(es3) - if res3 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - string.memset(c.Addr(self.win[eo3]), 0, 32) - i: int - for i in range(11): self.win[eo3 + i] = sfn[i] - self.win[eo3 + 11] = attr - self.win[eo3 + 12] = 0 - self.win[eo3 + 13] = 0 - self._write_dirent_now(eo3) - _write16(c.Addr(self.win[0]), eo3 + 20, uint16((first_cluster >> 16) & 0xFFFF)) - _write16(c.Addr(self.win[0]), eo3 + 26, uint16(first_cluster & 0xFFFF)) - _write32(c.Addr(self.win[0]), eo3 + 28, file_size) - self.win_dirty = 1 - self.win_flush() - c.Set(c.Deref(uint64(dir_sector_out, t.CPtr)), es3) - c.Set(c.Deref(uint32(dir_offset_out, t.CPtr)), eo3) - return FRESULT.FR_OK + def dir_add_entry(self, dp: dirobj*, name: const str, attr: uint8, first_cluster: uint32, file_size: uint32, dir_sector_out: uint64*, dir_offset_out: uint32*) -> FRESULT: + sfn: [12]char + sfn_from_lfn(name, &sfn[0]) + lfn_entries: int = 0 + len_: int = 0 + for _ in name: len_ += 1 + if len_ > 12: + lfn_entries = (len_ + LFN_ENTRY_CHARS - 1) / LFN_ENTRY_CHARS + total_entries: int = lfn_entries + 1 + cur_cluster: uint32 = dp.cluster + cur_sector: uint64 = dp.sector + cur_offset: uint32 = dp.offset + found: int = 0 + consecutive: int = 0 + start_offset: uint32 = 0 + start_cluster: uint32 = 0 + epc: uint32 = self.entries_per_cluster() + while not found: + if cur_offset >= epc: + next_clust: uint32 = self.cluster_get_next(cur_cluster) + if next_clust == 0: + new_clust: uint32 = self.cluster_extend(cur_cluster) + if new_clust == 0: return FRESULT.FR_DENIED + self._zero_cluster(new_clust) + cur_cluster = new_clust + cur_sector = self.cluster_to_sector(new_clust) + cur_offset = 0 + else: + cur_cluster = next_clust + cur_sector = self.cluster_to_sector(next_clust) + cur_offset = 0 + es: uint64 = cur_sector + (cur_offset / (512 / ENTRY_SIZE)) + eo: uint32 = (cur_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res: FRESULT = self.win_read(es) + if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + first_byte: uint8 = self.win[eo] + if first_byte == SFN_FREE or first_byte == SFN_DELETED: + if consecutive == 0: + start_offset = cur_offset + start_cluster = cur_cluster + consecutive += 1 + if consecutive >= total_entries: + found = 1 + break + else: + consecutive = 0 + cur_offset += 1 + write_cluster: uint32 = start_cluster + write_sector: uint64 = self.cluster_to_sector(start_cluster) + write_offset: uint32 = start_offset + if lfn_entries > 0: + le: int + for le in range(lfn_entries): + if write_offset >= epc: + next_c: uint32 = self.cluster_get_next(write_cluster) + if next_c == 0: return FRESULT.FR_INT_ERR + write_cluster = next_c + write_sector = self.cluster_to_sector(next_c) + write_offset = 0 + es2: uint64 = write_sector + (write_offset / (512 / ENTRY_SIZE)) + eo2: uint32 = (write_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res2: FRESULT = self.win_read(es2) + if res2 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + ord_val: uint8 = uint8(lfn_entries - le) + if le == 0: ord_val |= LFN_FLAG_LAST + self.win[eo2 + 0] = ord_val + self.win[eo2 + 11] = LFN_ATTR + self.win[eo2 + 12] = 0 + self.win[eo2 + 13] = sfn_checksum(&sfn[0]) + self.win[eo2 + 26] = 0 + self.win[eo2 + 27] = 0 + base: int = (lfn_entries - 1 - le) * LFN_ENTRY_CHARS + j: int + for j in range(LFN_ENTRY_CHARS): + idx: int = base + j + ch: uint16 + if idx < len_: ch = uint16(name[idx]) + elif idx == len_: ch = 0x0000 + else: ch = 0xFFFF + if j < 5: + self.win[eo2 + 1 + j * 2] = uint8(ch & 0xFF) + self.win[eo2 + 2 + j * 2] = uint8((ch >> 8) & 0xFF) + elif j < 11: + self.win[eo2 + 14 + (j - 5) * 2] = uint8(ch & 0xFF) + self.win[eo2 + 15 + (j - 5) * 2] = uint8((ch >> 8) & 0xFF) + else: + self.win[eo2 + 28 + (j - 11) * 2] = uint8(ch & 0xFF) + self.win[eo2 + 29 + (j - 11) * 2] = uint8((ch >> 8) & 0xFF) + self.win_dirty = 1 + self.win_flush() + write_offset += 1 + if write_offset >= epc: + next_c2: uint32 = self.cluster_get_next(write_cluster) + if next_c2 == 0: return FRESULT.FR_INT_ERR + write_cluster = next_c2 + write_sector = self.cluster_to_sector(next_c2) + write_offset = 0 + es3: uint64 = write_sector + (write_offset / (512 / ENTRY_SIZE)) + eo3: uint32 = (write_offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res3: FRESULT = self.win_read(es3) + if res3 != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + string.memset(&self.win[eo3], 0, 32) + i: int + for i in range(11): self.win[eo3 + i] = sfn[i] + self.win[eo3 + 11] = attr + self.win[eo3 + 12] = 0 + self.win[eo3 + 13] = 0 + self._write_dirent_now(eo3) + _write16(&self.win[0], eo3 + 20, uint16((first_cluster >> 16) & 0xFFFF)) + _write16(&self.win[0], eo3 + 26, uint16(first_cluster & 0xFFFF)) + _write32(&self.win[0], eo3 + 28, file_size) + self.win_dirty = 1 + self.win_flush() + *((uint64*(dir_sector_out))) = es3 + *((uint32*(dir_offset_out))) = eo3 + return FRESULT.FR_OK - def dir_update_entry(self, dir_sector: uint64, dir_offset: uint32, first_cluster: uint32, file_size: uint32, attr: uint8) -> FRESULT: - res: FRESULT = self.win_read(dir_sector) - if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - self.win[dir_offset + 11] = attr - _write16(c.Addr(self.win[0]), dir_offset + 20, uint16((first_cluster >> 16) & 0xFFFF)) - _write16(c.Addr(self.win[0]), dir_offset + 26, uint16(first_cluster & 0xFFFF)) - _write32(c.Addr(self.win[0]), dir_offset + 28, file_size) - self._write_dirent_now(dir_offset) - self.win_dirty = 1 - return self.win_flush() + def dir_update_entry(self, dir_sector: uint64, dir_offset: uint32, first_cluster: uint32, file_size: uint32, attr: uint8) -> FRESULT: + res: FRESULT = self.win_read(dir_sector) + if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + self.win[dir_offset + 11] = attr + _write16(&self.win[0], dir_offset + 20, uint16((first_cluster >> 16) & 0xFFFF)) + _write16(&self.win[0], dir_offset + 26, uint16(first_cluster & 0xFFFF)) + _write32(&self.win[0], dir_offset + 28, file_size) + self._write_dirent_now(dir_offset) + self.win_dirty = 1 + return self.win_flush() - def dir_delete_entry(self, dp: dirobj | t.CPtr) -> FRESULT: - start_off: uint32 = dp.lfn_ofs if dp.lfn_ofs != 0xFFFFFFFF else dp.offset - end_off: uint32 = dp.offset - cur_off: uint32 = start_off - cur_cluster: uint32 = dp.lfn_cluster if dp.lfn_ofs != 0xFFFFFFFF else dp.cluster - epc: uint32 = self.entries_per_cluster() - while cur_off <= end_off: - off_in_clus: uint32 = cur_off % epc - if off_in_clus == 0 and cur_off != start_off: - next_c: uint32 = self.cluster_get_next(cur_cluster) - if next_c == 0: return FRESULT.FR_INT_ERR - cur_cluster = next_c - sector_base: uint64 = self.cluster_to_sector(cur_cluster) - es: uint64 = sector_base + uint64(off_in_clus / (512 / ENTRY_SIZE)) - eo: uint32 = (off_in_clus % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res: FRESULT = self.win_read(es) - if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - self.win[eo] = SFN_DELETED - self.win_dirty = 1 - res2: FRESULT = self.win_flush() - if res2 != FRESULT.FR_OK: return res2 - cur_off += 1 - return FRESULT.FR_OK + def dir_delete_entry(self, dp: dirobj*) -> FRESULT: + start_off: uint32 = dp.lfn_ofs if dp.lfn_ofs != 0xFFFFFFFF else dp.offset + end_off: uint32 = dp.offset + cur_off: uint32 = start_off + cur_cluster: uint32 = dp.lfn_cluster if dp.lfn_ofs != 0xFFFFFFFF else dp.cluster + epc: uint32 = self.entries_per_cluster() + while cur_off <= end_off: + off_in_clus: uint32 = cur_off % epc + if off_in_clus == 0 and cur_off != start_off: + next_c: uint32 = self.cluster_get_next(cur_cluster) + if next_c == 0: return FRESULT.FR_INT_ERR + cur_cluster = next_c + sector_base: uint64 = self.cluster_to_sector(cur_cluster) + es: uint64 = sector_base + uint64(off_in_clus / (512 / ENTRY_SIZE)) + eo: uint32 = (off_in_clus % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res: FRESULT = self.win_read(es) + if res != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + self.win[eo] = SFN_DELETED + self.win_dirty = 1 + res2: FRESULT = self.win_flush() + if res2 != FRESULT.FR_OK: return res2 + cur_off += 1 + return FRESULT.FR_OK - def follow_path(self, dp: dirobj | t.CPtr, path: t.CConst | t.CChar | t.CPtr, lfn_buf: uint16 | t.CPtr) -> FRESULT: - cluster: uint32 = self.root_cluster - pi: int = 0 - if path[0] >= '0' and path[0] <= '9': - if path[1] == ':': - pi = 2 - elif path[1] == 0: - self.dir_open(dp, cluster) - return FRESULT.FR_OK - elif (path[0] >= 'A' and path[0] <= 'Z') or (path[0] >= 'a' and path[0] <= 'z'): - if path[1] == ':': - pi = 2 - if path[pi] == '/' or path[pi] == '\\': pi += 1 - while path[pi] == '/' or path[pi] == '\\': pi += 1 - if path[pi] == 0: - self.dir_open(dp, cluster) - return FRESULT.FR_OK - while True: - component: t.CArray[t.CChar, 256] - ci: int = 0 - while path[pi] != 0 and path[pi] != '/' and path[pi] != '\\' and ci < 255: - component[ci] = path[pi] - ci += 1; pi += 1 - component[ci] = 0 - if ci == 0: break - while path[pi] == '/' or path[pi] == '\\': pi += 1 - if ci == 2 and component[0] == '.' and component[1] == '.': - if cluster == self.root_cluster: - pass - else: - self.dir_open(dp, cluster) - dotdot_name: t.CArray[t.CChar, 256] - dotdot_name[0] = '.'; dotdot_name[1] = '.'; dotdot_name[2] = 0 - res_dd: FRESULT = self.dir_find(dp, c.Addr(dotdot_name[0]), lfn_buf) - if res_dd == FRESULT.FR_OK: - self._read_entry_from_dir(dp) - dd_eo: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - dd_off: uint32 = dd_eo - dd_ch: uint32 = uint32(self.win[dd_off + 20]) | (uint32(self.win[dd_off + 21]) << 8) - dd_cl: uint32 = uint32(self.win[dd_off + 26]) | (uint32(self.win[dd_off + 27]) << 8) - dd_clus: uint32 = (dd_ch << 16) | dd_cl - if dd_clus == 0: dd_clus = self.root_cluster - cluster = dd_clus - if path[pi] == 0: - self.dir_open(dp, cluster) - return FRESULT.FR_OK - continue - else: - cluster = self.root_cluster - if path[pi] == 0: - self.dir_open(dp, cluster) - return FRESULT.FR_OK - continue - if path[pi] == 0: - self.dir_open(dp, cluster) - return FRESULT.FR_OK - continue - if ci == 1 and component[0] == '.': - if path[pi] == 0: - self.dir_open(dp, cluster) - return FRESULT.FR_OK - continue - self.dir_open(dp, cluster) - res: FRESULT = self.dir_find(dp, c.Addr(component[0]), lfn_buf) - if res != FRESULT.FR_OK: return res - self._read_entry_from_dir(dp) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - off: uint32 = entry_offset_in_sector - entry_attr: uint8 = self.win[off + 11] - clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) - clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) - entry_cluster: uint32 = (clus_hi << 16) | clus_lo - if path[pi] == 0: return FRESULT.FR_OK - if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH - cluster = entry_cluster - return FRESULT.FR_NO_PATH + def follow_path(self, dp: dirobj*, path: const str, lfn_buf: uint16*) -> FRESULT: + cluster: uint32 = self.root_cluster + pi: int = 0 + if path[0] >= '0' and path[0] <= '9': + if path[1] == ':': + pi = 2 + elif path[1] == 0: + self.dir_open(dp, cluster) + return FRESULT.FR_OK + elif (path[0] >= 'A' and path[0] <= 'Z') or (path[0] >= 'a' and path[0] <= 'z'): + if path[1] == ':': + pi = 2 + if path[pi] == '/' or path[pi] == '\\': pi += 1 + while path[pi] == '/' or path[pi] == '\\': pi += 1 + if path[pi] == 0: + self.dir_open(dp, cluster) + return FRESULT.FR_OK + while True: + component: [256]char + ci: int = 0 + while path[pi] != 0 and path[pi] != '/' and path[pi] != '\\' and ci < 255: + component[ci] = path[pi] + ci += 1; pi += 1 + component[ci] = 0 + if ci == 0: break + while path[pi] == '/' or path[pi] == '\\': pi += 1 + if ci == 2 and component[0] == '.' and component[1] == '.': + if cluster == self.root_cluster: + pass + else: + self.dir_open(dp, cluster) + dotdot_name: [256]char + dotdot_name[0] = '.'; dotdot_name[1] = '.'; dotdot_name[2] = 0 + res_dd: FRESULT = self.dir_find(dp, &dotdot_name[0], lfn_buf) + if res_dd == FRESULT.FR_OK: + self._read_entry_from_dir(dp) + dd_eo: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + dd_off: uint32 = dd_eo + dd_ch: uint32 = uint32(self.win[dd_off + 20]) | (uint32(self.win[dd_off + 21]) << 8) + dd_cl: uint32 = uint32(self.win[dd_off + 26]) | (uint32(self.win[dd_off + 27]) << 8) + dd_clus: uint32 = (dd_ch << 16) | dd_cl + if dd_clus == 0: dd_clus = self.root_cluster + cluster = dd_clus + if path[pi] == 0: + self.dir_open(dp, cluster) + return FRESULT.FR_OK + continue + else: + cluster = self.root_cluster + if path[pi] == 0: + self.dir_open(dp, cluster) + return FRESULT.FR_OK + continue + if path[pi] == 0: + self.dir_open(dp, cluster) + return FRESULT.FR_OK + continue + if ci == 1 and component[0] == '.': + if path[pi] == 0: + self.dir_open(dp, cluster) + return FRESULT.FR_OK + continue + self.dir_open(dp, cluster) + res: FRESULT = self.dir_find(dp, &component[0], lfn_buf) + if res != FRESULT.FR_OK: return res + self._read_entry_from_dir(dp) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo + if path[pi] == 0: return FRESULT.FR_OK + if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH + cluster = entry_cluster + return FRESULT.FR_NO_PATH - def mkdir_create_dir_entries(self, new_cluster: uint32, parent_cluster: uint32) -> FRESULT: - sector: uint64 = self.cluster_to_sector(new_cluster) - res: FRESULT = self.win_read(sector) - if res != FRESULT.FR_OK: return res - string.memset(c.Addr(self.win[0]), 0, 512) - self.win[0] = '.'; self.win[1] = ' '; self.win[2] = ' '; self.win[3] = ' ' - self.win[4] = ' '; self.win[5] = ' '; self.win[6] = ' '; self.win[7] = ' ' - self.win[8] = ' '; self.win[9] = ' '; self.win[10] = ' ' - self.win[11] = AM_DIR - _write16(c.Addr(self.win[0]), 20, uint16((new_cluster >> 16) & 0xFFFF)) - _write16(c.Addr(self.win[0]), 26, uint16(new_cluster & 0xFFFF)) - self._write_dirent_now(0) - self.win[32] = '.'; self.win[33] = '.'; self.win[34] = ' '; self.win[35] = ' ' - self.win[36] = ' '; self.win[37] = ' '; self.win[38] = ' '; self.win[39] = ' ' - self.win[40] = ' '; self.win[41] = ' '; self.win[42] = ' ' - self.win[11 + 32] = AM_DIR - _write16(c.Addr(self.win[0]), 20 + 32, uint16((parent_cluster >> 16) & 0xFFFF)) - _write16(c.Addr(self.win[0]), 26 + 32, uint16(parent_cluster & 0xFFFF)) - self._write_dirent_now(32) - self.win_dirty = 1 - return self.win_flush() + def mkdir_create_dir_entries(self, new_cluster: uint32, parent_cluster: uint32) -> FRESULT: + sector: uint64 = self.cluster_to_sector(new_cluster) + res: FRESULT = self.win_read(sector) + if res != FRESULT.FR_OK: return res + string.memset(&self.win[0], 0, 512) + self.win[0] = '.'; self.win[1] = ' '; self.win[2] = ' '; self.win[3] = ' ' + self.win[4] = ' '; self.win[5] = ' '; self.win[6] = ' '; self.win[7] = ' ' + self.win[8] = ' '; self.win[9] = ' '; self.win[10] = ' ' + self.win[11] = AM_DIR + _write16(&self.win[0], 20, uint16((new_cluster >> 16) & 0xFFFF)) + _write16(&self.win[0], 26, uint16(new_cluster & 0xFFFF)) + self._write_dirent_now(0) + self.win[32] = '.'; self.win[33] = '.'; self.win[34] = ' '; self.win[35] = ' ' + self.win[36] = ' '; self.win[37] = ' '; self.win[38] = ' '; self.win[39] = ' ' + self.win[40] = ' '; self.win[41] = ' '; self.win[42] = ' ' + self.win[11 + 32] = AM_DIR + _write16(&self.win[0], 20 + 32, uint16((parent_cluster >> 16) & 0xFFFF)) + _write16(&self.win[0], 26 + 32, uint16(parent_cluster & 0xFFFF)) + self._write_dirent_now(32) + self.win_dirty = 1 + return self.win_flush() - def file_open(self, path: t.CConst | t.CChar | t.CPtr, mode: uint8) -> fileobj | t.CPtr: - self.last_error = FRESULT.FR_OK - if not self.mounted: - self.last_error = FRESULT.FR_NOT_ENABLED - return None - dp: dirobj - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if mode & FA_CREATE_NEW: - if res == FRESULT.FR_OK: - self.last_error = FRESULT.FR_EXIST - return None - if res != FRESULT.FR_NO_FILE and res != FRESULT.FR_NO_PATH: - self.last_error = res - return None - need_create: int = 0 - if (mode & FA_CREATE_NEW): need_create = 1 - if (mode & FA_OPEN_ALWAYS) and res == FRESULT.FR_NO_FILE: need_create = 1 - if (mode & FA_CREATE_ALWAYS) and res == FRESULT.FR_NO_FILE: need_create = 1 - if need_create: - pp: t.CArray[t.CChar, 260] - fn: t.CArray[t.CChar, 256] - _split_path(path, c.Addr(pp[0]), c.Addr(fn[0])) - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res2: FRESULT = self.follow_path(c.Addr(dp), c.Addr(pp[0]), uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res2 != FRESULT.FR_OK: - self.last_error = res2 - return None - nc: uint32 = 0 - if mode & FA_WRITE: - nc = self.cluster_alloc() - if nc == 0: - self.last_error = FRESULT.FR_DENIED - return None - self._zero_cluster(nc) - ds: uint64 = 0 - do: uint32 = 0 - res3: FRESULT = self.dir_add_entry(c.Addr(dp), c.Addr(fn[0]), AM_ARC, nc, 0, c.Addr(ds), c.Addr(do)) - if res3 != FRESULT.FR_OK: - if nc >= 2: self.cluster_free_chain(nc) - self.last_error = res3 - return None - fp: fileobj | t.CPtr = handle_alloc() - if fp is None: - if nc >= 2: self.cluster_free_chain(nc) - self.last_error = FRESULT.FR_TOO_MANY_OPEN_FILES - return None - fp.vol = self - fp.is_open = 1 - fp.is_dir = 0 - fp.first_cluster = nc - fp.current_cluster = nc - fp.file_size = 0 - fp.file_pos = 0 - fp.dir_sector = ds - fp.dir_offset = do - fp.attr = AM_ARC - fp.flags = mode - fp.err = 0 - fp.lock_count = 0 - fp.buf_sect = 0xFFFFFFFFFFFFFFFF - fp.buf_dirty = 0 - if mode & FA_WRITE: - lock_acquire(ds, do, 1) - fp.lock_count = 1 - return fp - if res != FRESULT.FR_OK: - self.last_error = res - return None - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res_wr: FRESULT = self.win_read(entry_sector) - if res_wr != FRESULT.FR_OK: - self.last_error = res_wr - return None - off: uint32 = entry_offset_in_sector - entry_attr: uint8 = self.win[off + 11] - if entry_attr & AM_DIR: - self.last_error = FRESULT.FR_DENIED - return None - if mode & FA_WRITE: - if entry_attr & AM_RDO: - self.last_error = FRESULT.FR_DENIED - return None - lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, mode) - if lres != FRESULT.FR_OK: - self.last_error = lres - return None - clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) - clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) - entry_cluster: uint32 = (clus_hi << 16) | clus_lo - entry_size: uint32 = _read32(c.Addr(self.win[0]), off + 28) - fp2: fileobj | t.CPtr = handle_alloc() - if fp2 is None: - self.last_error = FRESULT.FR_TOO_MANY_OPEN_FILES - return None - fp2.vol = self - fp2.is_open = 1 - fp2.is_dir = 0 - fp2.first_cluster = entry_cluster - fp2.current_cluster = entry_cluster - fp2.file_size = entry_size - fp2.file_pos = 0 - fp2.dir_sector = entry_sector - fp2.dir_offset = entry_offset_in_sector - fp2.attr = entry_attr - fp2.flags = mode - fp2.err = 0 - fp2.lock_count = 0 - fp2.buf_sect = 0xFFFFFFFFFFFFFFFF - fp2.buf_dirty = 0 - if mode & FA_WRITE: - lock_acquire(entry_sector, entry_offset_in_sector, 1) - fp2.lock_count = 1 - if mode & FA_CREATE_ALWAYS: - if entry_cluster >= 2: self.cluster_free_chain(entry_cluster) - fp2.first_cluster = 0 - fp2.current_cluster = 0 - fp2.file_size = 0 - fp2.file_pos = 0 - self.dir_update_entry(entry_sector, entry_offset_in_sector, 0, 0, entry_attr) - if mode & FA_OPEN_APPEND: - fp2.file_pos = entry_size - fp2.current_cluster = self.file_cluster_seek(entry_cluster, entry_size) - return fp2 + def file_open(self, path: const str, mode: uint8) -> fileobj*: + self.last_error = FRESULT.FR_OK + if not self.mounted: + self.last_error = FRESULT.FR_NOT_ENABLED + return None + dp: dirobj + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0])) + if mode & FA_CREATE_NEW: + if res == FRESULT.FR_OK: + self.last_error = FRESULT.FR_EXIST + return None + if res != FRESULT.FR_NO_FILE and res != FRESULT.FR_NO_PATH: + self.last_error = res + return None + need_create: int = 0 + if (mode & FA_CREATE_NEW): need_create = 1 + if (mode & FA_OPEN_ALWAYS) and res == FRESULT.FR_NO_FILE: need_create = 1 + if (mode & FA_CREATE_ALWAYS) and res == FRESULT.FR_NO_FILE: need_create = 1 + if need_create: + pp: [260]char + fn: [256]char + _split_path(path, &pp[0], &fn[0]) + string.memset(&lfn_buf, 0, 256 * 2) + res2: FRESULT = self.follow_path(&dp, &pp[0], uint16*(&lfn_buf[0])) + if res2 != FRESULT.FR_OK: + self.last_error = res2 + return None + nc: uint32 = 0 + if mode & FA_WRITE: + nc = self.cluster_alloc() + if nc == 0: + self.last_error = FRESULT.FR_DENIED + return None + self._zero_cluster(nc) + ds: uint64 = 0 + do: uint32 = 0 + res3: FRESULT = self.dir_add_entry(&dp, &fn[0], AM_ARC, nc, 0, &ds, &do) + if res3 != FRESULT.FR_OK: + if nc >= 2: self.cluster_free_chain(nc) + self.last_error = res3 + return None + fp: fileobj* = handle_alloc() + if fp is None: + if nc >= 2: self.cluster_free_chain(nc) + self.last_error = FRESULT.FR_TOO_MANY_OPEN_FILES + return None + fp.vol = self + fp.is_open = 1 + fp.is_dir = 0 + fp.first_cluster = nc + fp.current_cluster = nc + fp.file_size = 0 + fp.file_pos = 0 + fp.dir_sector = ds + fp.dir_offset = do + fp.attr = AM_ARC + fp.flags = mode + fp.err = 0 + fp.lock_count = 0 + fp.buf_sect = 0xFFFFFFFFFFFFFFFF + fp.buf_dirty = 0 + if mode & FA_WRITE: + lock_acquire(ds, do, 1) + fp.lock_count = 1 + return fp + if res != FRESULT.FR_OK: + self.last_error = res + return None + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res_wr: FRESULT = self.win_read(entry_sector) + if res_wr != FRESULT.FR_OK: + self.last_error = res_wr + return None + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] + if entry_attr & AM_DIR: + self.last_error = FRESULT.FR_DENIED + return None + if mode & FA_WRITE: + if entry_attr & AM_RDO: + self.last_error = FRESULT.FR_DENIED + return None + lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, mode) + if lres != FRESULT.FR_OK: + self.last_error = lres + return None + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo + entry_size: uint32 = _read32(&self.win[0], off + 28) + fp2: fileobj* = handle_alloc() + if fp2 is None: + self.last_error = FRESULT.FR_TOO_MANY_OPEN_FILES + return None + fp2.vol = self + fp2.is_open = 1 + fp2.is_dir = 0 + fp2.first_cluster = entry_cluster + fp2.current_cluster = entry_cluster + fp2.file_size = entry_size + fp2.file_pos = 0 + fp2.dir_sector = entry_sector + fp2.dir_offset = entry_offset_in_sector + fp2.attr = entry_attr + fp2.flags = mode + fp2.err = 0 + fp2.lock_count = 0 + fp2.buf_sect = 0xFFFFFFFFFFFFFFFF + fp2.buf_dirty = 0 + if mode & FA_WRITE: + lock_acquire(entry_sector, entry_offset_in_sector, 1) + fp2.lock_count = 1 + if mode & FA_CREATE_ALWAYS: + if entry_cluster >= 2: self.cluster_free_chain(entry_cluster) + fp2.first_cluster = 0 + fp2.current_cluster = 0 + fp2.file_size = 0 + fp2.file_pos = 0 + self.dir_update_entry(entry_sector, entry_offset_in_sector, 0, 0, entry_attr) + if mode & FA_OPEN_APPEND: + fp2.file_pos = entry_size + fp2.current_cluster = self.file_cluster_seek(entry_cluster, entry_size) + return fp2 - def file_delete(self, path: t.CConst | t.CChar | t.CPtr) -> FRESULT: - if not self.mounted: return FRESULT.FR_NOT_ENABLED - dp: dirobj - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res != FRESULT.FR_OK: return res - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res_wr: FRESULT = self.win_read(entry_sector) - if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: uint32 = entry_offset_in_sector - entry_attr: uint8 = self.win[off + 11] - if entry_attr & AM_RDO: return FRESULT.FR_DENIED - if entry_attr & AM_DIR: return FRESULT.FR_DENIED - lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, FA_WRITE) - if lres != FRESULT.FR_OK: return FRESULT.FR_LOCKED - clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) - clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) - entry_cluster: uint32 = (clus_hi << 16) | clus_lo - res2: FRESULT = self.dir_delete_entry(c.Addr(dp)) - if res2 != FRESULT.FR_OK: return res2 - if entry_cluster >= 2: self.cluster_free_chain(entry_cluster) - return FRESULT.FR_OK + def file_delete(self, path: const str) -> FRESULT: + if not self.mounted: return FRESULT.FR_NOT_ENABLED + dp: dirobj + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0])) + if res != FRESULT.FR_OK: return res + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res_wr: FRESULT = self.win_read(entry_sector) + if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] + if entry_attr & AM_RDO: return FRESULT.FR_DENIED + if entry_attr & AM_DIR: return FRESULT.FR_DENIED + lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, FA_WRITE) + if lres != FRESULT.FR_OK: return FRESULT.FR_LOCKED + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo + res2: FRESULT = self.dir_delete_entry(&dp) + if res2 != FRESULT.FR_OK: return res2 + if entry_cluster >= 2: self.cluster_free_chain(entry_cluster) + return FRESULT.FR_OK - def file_rename(self, old_path: t.CConst | t.CChar | t.CPtr, new_path: t.CConst | t.CChar | t.CPtr) -> FRESULT: - if not self.mounted: return FRESULT.FR_NOT_ENABLED - dp: dirobj - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), old_path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res != FRESULT.FR_OK: return res - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res_wr: FRESULT = self.win_read(entry_sector) - if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: uint32 = entry_offset_in_sector - entry_attr: uint8 = self.win[off + 11] - clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) - clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) - entry_cluster: uint32 = (clus_hi << 16) | clus_lo - entry_size: uint32 = _read32(c.Addr(self.win[0]), off + 28) - lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, FA_WRITE) - if lres != FRESULT.FR_OK: return FRESULT.FR_LOCKED - new_parent: t.CArray[t.CChar, 260] - new_fname: t.CArray[t.CChar, 256] - _split_path(new_path, c.Addr(new_parent[0]), c.Addr(new_fname[0])) - dp2: dirobj - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res2: FRESULT = self.follow_path(c.Addr(dp2), c.Addr(new_parent[0]), uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res2 != FRESULT.FR_OK: return FRESULT.FR_NO_PATH - new_dir_sector: uint64 = 0 - new_dir_offset: uint32 = 0 - res3: FRESULT = self.dir_add_entry(c.Addr(dp2), c.Addr(new_fname[0]), entry_attr, entry_cluster, entry_size, c.Addr(new_dir_sector), c.Addr(new_dir_offset)) - if res3 != FRESULT.FR_OK: return res3 - res4: FRESULT = self.dir_delete_entry(c.Addr(dp)) - if res4 != FRESULT.FR_OK: return res4 - return FRESULT.FR_OK + def file_rename(self, old_path: const str, new_path: const str) -> FRESULT: + if not self.mounted: return FRESULT.FR_NOT_ENABLED + dp: dirobj + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, old_path, uint16*(&lfn_buf[0])) + if res != FRESULT.FR_OK: return res + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res_wr: FRESULT = self.win_read(entry_sector) + if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo + entry_size: uint32 = _read32(&self.win[0], off + 28) + lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, FA_WRITE) + if lres != FRESULT.FR_OK: return FRESULT.FR_LOCKED + new_parent: [260]char + new_fname: [256]char + _split_path(new_path, &new_parent[0], &new_fname[0]) + dp2: dirobj + string.memset(&lfn_buf, 0, 256 * 2) + res2: FRESULT = self.follow_path(&dp2, &new_parent[0], uint16*(&lfn_buf[0])) + if res2 != FRESULT.FR_OK: return FRESULT.FR_NO_PATH + new_dir_sector: uint64 = 0 + new_dir_offset: uint32 = 0 + res3: FRESULT = self.dir_add_entry(&dp2, &new_fname[0], entry_attr, entry_cluster, entry_size, &new_dir_sector, &new_dir_offset) + if res3 != FRESULT.FR_OK: return res3 + res4: FRESULT = self.dir_delete_entry(&dp) + if res4 != FRESULT.FR_OK: return res4 + return FRESULT.FR_OK - def file_stat(self, path: t.CConst | t.CChar | t.CPtr, info: fileinfo | t.CPtr) -> FRESULT: - if not self.mounted: return FRESULT.FR_NOT_ENABLED - dp: dirobj - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res != FRESULT.FR_OK: return res - return self.dir_get_entry_info(c.Addr(dp), info, uint16(c.Addr(lfn_buf[0]), t.CPtr)) + def file_stat(self, path: const str, info: fileinfo*) -> FRESULT: + if not self.mounted: return FRESULT.FR_NOT_ENABLED + dp: dirobj + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0])) + if res != FRESULT.FR_OK: return res + return self.dir_get_entry_info(&dp, info, uint16*(&lfn_buf[0])) - def dir_make(self, path: t.CConst | t.CChar | t.CPtr) -> FRESULT: - if not self.mounted: return FRESULT.FR_NOT_ENABLED - dp: dirobj - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res == FRESULT.FR_OK: return FRESULT.FR_EXIST - parent_path: t.CArray[t.CChar, 260] - dir_name: t.CArray[t.CChar, 256] - _split_path(path, c.Addr(parent_path[0]), c.Addr(dir_name[0])) - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res2: FRESULT = self.follow_path(c.Addr(dp), c.Addr(parent_path[0]), uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res2 != FRESULT.FR_OK: return FRESULT.FR_NO_PATH - parent_cluster: uint32 = dp.cluster - new_cluster: uint32 = self.cluster_alloc() - if new_cluster == 0: return FRESULT.FR_DENIED - self._zero_cluster(new_cluster) - dir_sector: uint64 = 0 - dir_offset: uint32 = 0 - res3: FRESULT = self.dir_add_entry(c.Addr(dp), c.Addr(dir_name[0]), AM_DIR, new_cluster, 0, c.Addr(dir_sector), c.Addr(dir_offset)) - if res3 != FRESULT.FR_OK: - self.cluster_free_chain(new_cluster) - return res3 - res4: FRESULT = self.mkdir_create_dir_entries(new_cluster, parent_cluster) - if res4 != FRESULT.FR_OK: - self.cluster_free_chain(new_cluster) - return res4 - return FRESULT.FR_OK + def dir_make(self, path: const str) -> FRESULT: + if not self.mounted: return FRESULT.FR_NOT_ENABLED + dp: dirobj + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0])) + if res == FRESULT.FR_OK: return FRESULT.FR_EXIST + parent_path: [260]char + dir_name: [256]char + _split_path(path, &parent_path[0], &dir_name[0]) + string.memset(&lfn_buf, 0, 256 * 2) + res2: FRESULT = self.follow_path(&dp, &parent_path[0], uint16*(&lfn_buf[0])) + if res2 != FRESULT.FR_OK: return FRESULT.FR_NO_PATH + parent_cluster: uint32 = dp.cluster + new_cluster: uint32 = self.cluster_alloc() + if new_cluster == 0: return FRESULT.FR_DENIED + self._zero_cluster(new_cluster) + dir_sector: uint64 = 0 + dir_offset: uint32 = 0 + res3: FRESULT = self.dir_add_entry(&dp, &dir_name[0], AM_DIR, new_cluster, 0, &dir_sector, &dir_offset) + if res3 != FRESULT.FR_OK: + self.cluster_free_chain(new_cluster) + return res3 + res4: FRESULT = self.mkdir_create_dir_entries(new_cluster, parent_cluster) + if res4 != FRESULT.FR_OK: + self.cluster_free_chain(new_cluster) + return res4 + return FRESULT.FR_OK - def dir_open_path(self, path: t.CConst | t.CChar | t.CPtr, dp: dirobj | t.CPtr) -> FRESULT: - if not self.mounted: return FRESULT.FR_NOT_ENABLED - pi: int = 0 - if path[0] >= '0' and path[0] <= '9': - if path[1] == ':' or path[1] == 0: - pi = 2 - if path[1] == 0: - self.dir_open(dp, self.root_cluster) - return FRESULT.FR_OK - if path[pi] == '/' or path[pi] == '\\': pi += 1 - while path[pi] == '/' or path[pi] == '\\': pi += 1 - is_root: int = 1 if path[pi] == 0 else 0 - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(dp, path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res != FRESULT.FR_OK: return res - if is_root: return FRESULT.FR_OK - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res_wr: FRESULT = self.win_read(entry_sector) - if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: uint32 = entry_offset_in_sector - entry_attr: uint8 = self.win[off + 11] - if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH - clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) - clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) - entry_cluster: uint32 = (clus_hi << 16) | clus_lo - return self.dir_open(dp, entry_cluster) + def dir_open_path(self, path: const str, dp: dirobj*) -> FRESULT: + if not self.mounted: return FRESULT.FR_NOT_ENABLED + pi: int = 0 + if path[0] >= '0' and path[0] <= '9': + if path[1] == ':' or path[1] == 0: + pi = 2 + if path[1] == 0: + self.dir_open(dp, self.root_cluster) + return FRESULT.FR_OK + if path[pi] == '/' or path[pi] == '\\': pi += 1 + while path[pi] == '/' or path[pi] == '\\': pi += 1 + is_root: int = 1 if path[pi] == 0 else 0 + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0])) + if res != FRESULT.FR_OK: return res + if is_root: return FRESULT.FR_OK + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res_wr: FRESULT = self.win_read(entry_sector) + if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] + if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo + return self.dir_open(dp, entry_cluster) - def dir_read(self, dp: dirobj | t.CPtr, info: fileinfo | t.CPtr) -> FRESULT: - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.dir_read_entry(dp, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res != FRESULT.FR_OK: return res - res2: FRESULT = self.dir_get_entry_info(dp, info, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - dp.offset += 1 - return res2 + def dir_read(self, dp: dirobj*, info: fileinfo*) -> FRESULT: + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.dir_read_entry(dp, uint16*(&lfn_buf[0])) + if res != FRESULT.FR_OK: return res + res2: FRESULT = self.dir_get_entry_info(dp, info, uint16*(&lfn_buf[0])) + dp.offset += 1 + return res2 - def dir_remove(self, path: t.CConst | t.CChar | t.CPtr) -> FRESULT: - if not self.mounted: return FRESULT.FR_NOT_ENABLED - dp: dirobj - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res != FRESULT.FR_OK: return res - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res_wr: FRESULT = self.win_read(entry_sector) - if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: uint32 = entry_offset_in_sector - entry_attr: uint8 = self.win[off + 11] - if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH - clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) - clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) - entry_cluster: uint32 = (clus_hi << 16) | clus_lo - if entry_cluster >= 2: - check_dp: dirobj - self.dir_open(c.Addr(check_dp), entry_cluster) - lfn_buf2: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf2), 0, 256 * 2) - while True: - check_res: FRESULT = self.dir_read_entry(c.Addr(check_dp), uint16(c.Addr(lfn_buf2[0]), t.CPtr)) - if check_res != FRESULT.FR_OK: break - c_off: uint32 = (check_dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - c_sec: uint64 = check_dp.sector + (check_dp.offset / (512 / ENTRY_SIZE)) - self.win_read(c_sec) - c_name0: uint8 = self.win[c_off] - c_name1: uint8 = self.win[c_off + 1] - check_dp.offset += 1 - if c_name0 == '.' and (c_name1 == '.' or c_name1 == 0x20): - continue - return FRESULT.FR_DENIED - lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, FA_WRITE) - if lres != FRESULT.FR_OK: return FRESULT.FR_LOCKED - res2: FRESULT = self.dir_delete_entry(c.Addr(dp)) - if res2 != FRESULT.FR_OK: return res2 - if entry_cluster >= 2: self.cluster_free_chain(entry_cluster) - return FRESULT.FR_OK + def dir_remove(self, path: const str) -> FRESULT: + if not self.mounted: return FRESULT.FR_NOT_ENABLED + dp: dirobj + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0])) + if res != FRESULT.FR_OK: return res + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res_wr: FRESULT = self.win_read(entry_sector) + if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + off: uint32 = entry_offset_in_sector + entry_attr: uint8 = self.win[off + 11] + if not (entry_attr & AM_DIR): return FRESULT.FR_NO_PATH + clus_hi: uint32 = uint32(self.win[off + 20]) | (uint32(self.win[off + 21]) << 8) + clus_lo: uint32 = uint32(self.win[off + 26]) | (uint32(self.win[off + 27]) << 8) + entry_cluster: uint32 = (clus_hi << 16) | clus_lo + if entry_cluster >= 2: + check_dp: dirobj + self.dir_open(&check_dp, entry_cluster) + lfn_buf2: [256]uint16 + string.memset(&lfn_buf2, 0, 256 * 2) + while True: + check_res: FRESULT = self.dir_read_entry(&check_dp, uint16*(&lfn_buf2[0])) + if check_res != FRESULT.FR_OK: break + c_off: uint32 = (check_dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + c_sec: uint64 = check_dp.sector + (check_dp.offset / (512 / ENTRY_SIZE)) + self.win_read(c_sec) + c_name0: uint8 = self.win[c_off] + c_name1: uint8 = self.win[c_off + 1] + check_dp.offset += 1 + if c_name0 == '.' and (c_name1 == '.' or c_name1 == 0x20): + continue + return FRESULT.FR_DENIED + lres: FRESULT = lock_check(entry_sector, entry_offset_in_sector, FA_WRITE) + if lres != FRESULT.FR_OK: return FRESULT.FR_LOCKED + res2: FRESULT = self.dir_delete_entry(&dp) + if res2 != FRESULT.FR_OK: return res2 + if entry_cluster >= 2: self.cluster_free_chain(entry_cluster) + return FRESULT.FR_OK - def chmod(self, path: t.CConst | t.CChar | t.CPtr, attr: uint8, mask: uint8) -> FRESULT: - if not self.mounted: return FRESULT.FR_NOT_ENABLED - dp: dirobj - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res != FRESULT.FR_OK: return res - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res_wr: FRESULT = self.win_read(entry_sector) - if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: uint32 = entry_offset_in_sector - old_attr: uint8 = self.win[off + 11] - new_attr: uint8 = (old_attr & ~mask) | (attr & mask) - self.win[off + 11] = new_attr - self.win_dirty = 1 - return self.win_flush() + def chmod(self, path: const str, attr: uint8, mask: uint8) -> FRESULT: + if not self.mounted: return FRESULT.FR_NOT_ENABLED + dp: dirobj + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0])) + if res != FRESULT.FR_OK: return res + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res_wr: FRESULT = self.win_read(entry_sector) + if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + off: uint32 = entry_offset_in_sector + old_attr: uint8 = self.win[off + 11] + new_attr: uint8 = (old_attr & ~mask) | (attr & mask) + self.win[off + 11] = new_attr + self.win_dirty = 1 + return self.win_flush() - def utime(self, path: t.CConst | t.CChar | t.CPtr, mtime: uint16, mdate: uint16) -> FRESULT: - if not self.mounted: return FRESULT.FR_NOT_ENABLED - dp: dirobj - lfn_buf: t.CArray[uint16, 256] - string.memset(c.Addr(lfn_buf), 0, 256 * 2) - res: FRESULT = self.follow_path(c.Addr(dp), path, uint16(c.Addr(lfn_buf[0]), t.CPtr)) - if res != FRESULT.FR_OK: return res - entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) - entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE - res_wr: FRESULT = self.win_read(entry_sector) - if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR - off: uint32 = entry_offset_in_sector - self.win[off + 22] = uint8(mtime & 0xFF) - self.win[off + 23] = uint8((mtime >> 8) & 0xFF) - self.win[off + 24] = uint8(mdate & 0xFF) - self.win[off + 25] = uint8((mdate >> 8) & 0xFF) - self.win[off + 18] = uint8(mdate & 0xFF) - self.win[off + 19] = uint8((mdate >> 8) & 0xFF) - self.win_dirty = 1 - return self.win_flush() + def utime(self, path: const str, mtime: uint16, mdate: uint16) -> FRESULT: + if not self.mounted: return FRESULT.FR_NOT_ENABLED + dp: dirobj + lfn_buf: [256]uint16 + string.memset(&lfn_buf, 0, 256 * 2) + res: FRESULT = self.follow_path(&dp, path, uint16*(&lfn_buf[0])) + if res != FRESULT.FR_OK: return res + entry_sector: uint64 = dp.sector + (dp.offset / (512 / ENTRY_SIZE)) + entry_offset_in_sector: uint32 = (dp.offset % (512 / ENTRY_SIZE)) * ENTRY_SIZE + res_wr: FRESULT = self.win_read(entry_sector) + if res_wr != FRESULT.FR_OK: return FRESULT.FR_DISK_ERR + off: uint32 = entry_offset_in_sector + self.win[off + 22] = uint8(mtime & 0xFF) + self.win[off + 23] = uint8((mtime >> 8) & 0xFF) + self.win[off + 24] = uint8(mdate & 0xFF) + self.win[off + 25] = uint8((mdate >> 8) & 0xFF) + self.win[off + 18] = uint8(mdate & 0xFF) + self.win[off + 19] = uint8((mdate >> 8) & 0xFF) + self.win_dirty = 1 + return self.win_flush() -@t.Object class fileobj: - vol: volinfo | t.CPtr - is_open: int = 0 - is_dir: int = 0 - first_cluster: uint32 = 0 - current_cluster: uint32 = 0 - file_size: uint32 = 0 - file_pos: uint32 = 0 - dir_sector: uint64 = 0 - dir_offset: uint32 = 0 - attr: uint8 = 0 - ctime: uint16 = 0 - cdate: uint16 = 0 - mtime: uint16 = 0 - mdate: uint16 = 0 - adate: uint16 = 0 - flags: uint8 = 0 - err: uint8 = 0 - lock_count: int = 0 - buf: t.CArray[uint8, 512] - buf_sect: uint64 = 0 - buf_dirty: int = 0 + vol: volinfo* + is_open: int = 0 + is_dir: int = 0 + first_cluster: uint32 = 0 + current_cluster: uint32 = 0 + file_size: uint32 = 0 + file_pos: uint32 = 0 + dir_sector: uint64 = 0 + dir_offset: uint32 = 0 + attr: uint8 = 0 + ctime: uint16 = 0 + cdate: uint16 = 0 + mtime: uint16 = 0 + mdate: uint16 = 0 + adate: uint16 = 0 + flags: uint8 = 0 + err: uint8 = 0 + lock_count: int = 0 + buf: [512]uint8 + buf_sect: uint64 = 0 + buf_dirty: int = 0 - def buf_flush(self) -> FRESULT: - if not self.buf_dirty: return FRESULT.FR_OK - abs_sect: uint64 = uint64(self.buf_sect) + uint64(self.vol.hidden_sectors) - self.vol.lock.lock() - res: DRESULT = diskio.write(self.vol.pdrv, c.Addr(self.buf[0]), uint32(abs_sect), 1) - self.vol.lock.unlock() - if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR - self.buf_dirty = 0 - return FRESULT.FR_OK + def buf_flush(self) -> FRESULT: + if not self.buf_dirty: return FRESULT.FR_OK + abs_sect: uint64 = uint64(self.buf_sect) + uint64(self.vol.hidden_sectors) + self.vol.lock.lock() + res: DRESULT = diskio.write(self.vol.pdrv, &self.buf[0], uint32(abs_sect), 1) + self.vol.lock.unlock() + if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR + self.buf_dirty = 0 + return FRESULT.FR_OK - def buf_read(self, sector: uint64) -> FRESULT: - if self.buf_sect == sector: return FRESULT.FR_OK - if self.buf_dirty: - res: FRESULT = self.buf_flush() - if res != FRESULT.FR_OK: return res - abs_sect: uint64 = sector + uint64(self.vol.hidden_sectors) - self.vol.lock.lock() - res2: DRESULT = diskio.read(self.vol.pdrv, c.Addr(self.buf[0]), uint32(abs_sect), 1) - self.vol.lock.unlock() - if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR - self.buf_sect = sector - return FRESULT.FR_OK + def buf_read(self, sector: uint64) -> FRESULT: + if self.buf_sect == sector: return FRESULT.FR_OK + if self.buf_dirty: + res: FRESULT = self.buf_flush() + if res != FRESULT.FR_OK: return res + abs_sect: uint64 = sector + uint64(self.vol.hidden_sectors) + self.vol.lock.lock() + res2: DRESULT = diskio.read(self.vol.pdrv, &self.buf[0], uint32(abs_sect), 1) + self.vol.lock.unlock() + if res2 != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR + self.buf_sect = sector + return FRESULT.FR_OK - def close(self) -> FRESULT: - if not self.is_open: return FRESULT.FR_INVALID_OBJECT - res: FRESULT = self.buf_flush() - if res != FRESULT.FR_OK: return res - if self.flags & FA_WRITE: - self.vol.dir_update_entry(self.dir_sector, self.dir_offset, self.first_cluster, self.file_size, self.attr) - if self.lock_count > 0: lock_release(self.dir_sector, self.dir_offset) - self.is_open = 0 - self.lock_count = 0 - return FRESULT.FR_OK + def close(self) -> FRESULT: + if not self.is_open: return FRESULT.FR_INVALID_OBJECT + res: FRESULT = self.buf_flush() + if res != FRESULT.FR_OK: return res + if self.flags & FA_WRITE: + self.vol.dir_update_entry(self.dir_sector, self.dir_offset, self.first_cluster, self.file_size, self.attr) + if self.lock_count > 0: lock_release(self.dir_sector, self.dir_offset) + self.is_open = 0 + self.lock_count = 0 + return FRESULT.FR_OK - def read(self, buff: t.CPtr, btr: uint32, br: uint32 | t.CPtr) -> FRESULT: - if not self.is_open: return FRESULT.FR_INVALID_OBJECT - if not (self.flags & FA_READ): return FRESULT.FR_DENIED - c.Set(c.Deref(br), 0) - # [RD-DIAG] 定位 read_len<64(ehdr 读取失败)根因:打印文件状态 - _rdb: t.CArray[t.CChar, 160] - viperlib.snprintf(c.Addr(_rdb), 160, "[fat32] read: size=%lu fc=%lu cc=%lu pos=%lu btr=%lu\n", - self.file_size, self.first_cluster, self.current_cluster, self.file_pos, btr) - serial.puts(c.Addr(_rdb)) - vol: volinfo | t.CPtr = self.vol - remaining: uint32 = btr - buf_ptr: uint8 | t.CPtr = uint8(buff, t.CPtr) - total_read: uint32 = 0 - while remaining > 0: - if self.file_pos >= self.file_size: break - if self.first_cluster < 2: break - if self.current_cluster < 2 or vol.is_eoc(self.current_cluster): break - cluster_offset: uint32 = self.file_pos % vol.cluster_size - sector_in_cluster: uint32 = cluster_offset / 512 - offset_in_sector: uint32 = cluster_offset % 512 - sector: uint64 = vol.cluster_to_sector(self.current_cluster) + uint64(sector_in_cluster) - can_read_in_sector: uint32 = 512 - offset_in_sector - can_read: uint32 = can_read_in_sector - if can_read > remaining: can_read = remaining - if can_read > self.file_size - self.file_pos: can_read = self.file_size - self.file_pos - if can_read == 0: break - if offset_in_sector == 0 and can_read >= 512: - abs_sect: uint64 = sector + uint64(vol.hidden_sectors) - vol.lock.lock() - res: DRESULT = diskio.read(vol.pdrv, buf_ptr, uint32(abs_sect), 1) - vol.lock.unlock() - if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR - else: - res2: FRESULT = self.buf_read(sector) - if res2 != FRESULT.FR_OK: return res2 - string.memcpy(buf_ptr, c.Addr(self.buf[offset_in_sector]), can_read) - buf_ptr += can_read - self.file_pos += can_read - total_read += can_read - remaining -= can_read - if self.file_pos % vol.cluster_size == 0: - next_c: uint32 = vol.cluster_get_next(self.current_cluster) - if next_c == 0: break - self.current_cluster = next_c - # [RD-DIAG] 打印实际读取字节数 - _rdb2: t.CArray[t.CChar, 96] - viperlib.snprintf(c.Addr(_rdb2), 96, "[fat32] read done: br=%lu\n", total_read) - serial.puts(c.Addr(_rdb2)) - c.Set(c.Deref(br), total_read) - return FRESULT.FR_OK + def read(self, buff: rawptr, btr: uint32, br: uint32*) -> FRESULT: + if not self.is_open: return FRESULT.FR_INVALID_OBJECT + if not (self.flags & FA_READ): return FRESULT.FR_DENIED + *br = 0 + vol: volinfo* = self.vol + remaining: uint32 = btr + buf_ptr: uint8* = uint8*(buff) + total_read: uint32 = 0 + while remaining > 0: + if self.file_pos >= self.file_size: break + if self.first_cluster < 2: break + if self.current_cluster < 2 or vol.is_eoc(self.current_cluster): break + cluster_offset: uint32 = self.file_pos % vol.cluster_size + sector_in_cluster: uint32 = cluster_offset / 512 + offset_in_sector: uint32 = cluster_offset % 512 + sector: uint64 = vol.cluster_to_sector(self.current_cluster) + uint64(sector_in_cluster) + can_read_in_sector: uint32 = 512 - offset_in_sector + can_read: uint32 = can_read_in_sector + if can_read > remaining: can_read = remaining + if can_read > self.file_size - self.file_pos: can_read = self.file_size - self.file_pos + if can_read == 0: break + if offset_in_sector == 0 and can_read >= 512: + abs_sect: uint64 = sector + uint64(vol.hidden_sectors) + vol.lock.lock() + res: DRESULT = diskio.read(vol.pdrv, buf_ptr, uint32(abs_sect), 1) + vol.lock.unlock() + if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR + else: + res2: FRESULT = self.buf_read(sector) + if res2 != FRESULT.FR_OK: return res2 + string.memcpy(buf_ptr, &self.buf[offset_in_sector], can_read) + buf_ptr += can_read + self.file_pos += can_read + total_read += can_read + remaining -= can_read + if self.file_pos % vol.cluster_size == 0: + next_c: uint32 = vol.cluster_get_next(self.current_cluster) + if next_c == 0: break + self.current_cluster = next_c + *br = total_read + return FRESULT.FR_OK - def _extend_to(self, target_pos: uint32) -> FRESULT: - if self.first_cluster < 2: - new_c: uint32 = self.vol.cluster_alloc() - if new_c == 0: return FRESULT.FR_DENIED - self.first_cluster = new_c - self.current_cluster = new_c - self.vol._zero_cluster(new_c) - cur_pos: uint32 = 0 - clust: uint32 = self.first_cluster - while cur_pos + self.vol.cluster_size <= target_pos: - next_c: uint32 = self.vol.cluster_get_next(clust) - if next_c == 0: - new_c2: uint32 = self.vol.cluster_extend(clust) - if new_c2 == 0: return FRESULT.FR_DENIED - self.vol._zero_cluster(new_c2) - next_c = new_c2 - clust = next_c - cur_pos += self.vol.cluster_size - self.current_cluster = clust - return FRESULT.FR_OK + def _extend_to(self, target_pos: uint32) -> FRESULT: + if self.first_cluster < 2: + new_c: uint32 = self.vol.cluster_alloc() + if new_c == 0: return FRESULT.FR_DENIED + self.first_cluster = new_c + self.current_cluster = new_c + self.vol._zero_cluster(new_c) + cur_pos: uint32 = 0 + clust: uint32 = self.first_cluster + while cur_pos + self.vol.cluster_size <= target_pos: + next_c: uint32 = self.vol.cluster_get_next(clust) + if next_c == 0: + new_c2: uint32 = self.vol.cluster_extend(clust) + if new_c2 == 0: return FRESULT.FR_DENIED + self.vol._zero_cluster(new_c2) + next_c = new_c2 + clust = next_c + cur_pos += self.vol.cluster_size + self.current_cluster = clust + return FRESULT.FR_OK - def write(self, buff: t.CConst | t.CPtr, btw: uint32, bw: uint32 | t.CPtr) -> FRESULT: - if not self.is_open: return FRESULT.FR_INVALID_OBJECT - if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED - c.Set(c.Deref(bw), 0) - vol: volinfo | t.CPtr = self.vol - remaining: uint32 = btw - buf_ptr: t.CConst | uint8 | t.CPtr = uint8(buff, t.CPtr) - total_written: uint32 = 0 - while remaining > 0: - if self.first_cluster < 2: - new_c: uint32 = vol.cluster_alloc() - if new_c == 0: return FRESULT.FR_DENIED - self.first_cluster = new_c - self.current_cluster = new_c - vol._zero_cluster(new_c) - if self.current_cluster < 2 or vol.is_eoc(self.current_cluster): - last_c: uint32 = self.current_cluster - if self.first_cluster >= 2 and self.current_cluster < 2: - last_c = vol.file_find_last_cluster(self.first_cluster) - new_c2: uint32 = vol.cluster_extend(last_c) - if new_c2 == 0: return FRESULT.FR_DENIED - if self.first_cluster < 2: self.first_cluster = new_c2 - self.current_cluster = new_c2 - vol._zero_cluster(new_c2) - cluster_offset: uint32 = self.file_pos % vol.cluster_size - sector_in_cluster: uint32 = cluster_offset / 512 - offset_in_sector: uint32 = cluster_offset % 512 - sector: uint64 = vol.cluster_to_sector(self.current_cluster) + uint64(sector_in_cluster) - can_write_in_sector: uint32 = 512 - offset_in_sector - can_write: uint32 = can_write_in_sector - if can_write > remaining: can_write = remaining - if can_write == 0: break - if offset_in_sector == 0 and can_write >= 512: - abs_sect: uint64 = sector + uint64(vol.hidden_sectors) - vol.lock.lock() - res: DRESULT = diskio.write(vol.pdrv, buf_ptr, uint32(abs_sect), 1) - vol.lock.unlock() - if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR - self.buf_sect = 0xFFFFFFFFFFFFFFFF - self.buf_dirty = 0 - else: - res2: FRESULT = self.buf_read(sector) - if res2 != FRESULT.FR_OK: return res2 - string.memcpy(c.Addr(self.buf[offset_in_sector]), buf_ptr, can_write) - self.buf_dirty = 1 - res3: FRESULT = self.buf_flush() - if res3 != FRESULT.FR_OK: return res3 - buf_ptr += can_write - self.file_pos += can_write - total_written += can_write - remaining -= can_write - if self.file_pos > self.file_size: self.file_size = self.file_pos - if self.file_pos % vol.cluster_size == 0: - next_c: uint32 = vol.cluster_get_next(self.current_cluster) - if next_c != 0: self.current_cluster = next_c - c.Set(c.Deref(bw), total_written) - return FRESULT.FR_OK + def write(self, buff: const rawptr, btw: uint32, bw: uint32*) -> FRESULT: + if not self.is_open: return FRESULT.FR_INVALID_OBJECT + if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED + *bw = 0 + vol: volinfo* = self.vol + remaining: uint32 = btw + buf_ptr: const uint8* = uint8*(buff) + total_written: uint32 = 0 + while remaining > 0: + if self.first_cluster < 2: + new_c: uint32 = vol.cluster_alloc() + if new_c == 0: return FRESULT.FR_DENIED + self.first_cluster = new_c + self.current_cluster = new_c + vol._zero_cluster(new_c) + if self.current_cluster < 2 or vol.is_eoc(self.current_cluster): + last_c: uint32 = self.current_cluster + if self.first_cluster >= 2 and self.current_cluster < 2: + last_c = vol.file_find_last_cluster(self.first_cluster) + new_c2: uint32 = vol.cluster_extend(last_c) + if new_c2 == 0: return FRESULT.FR_DENIED + if self.first_cluster < 2: self.first_cluster = new_c2 + self.current_cluster = new_c2 + vol._zero_cluster(new_c2) + cluster_offset: uint32 = self.file_pos % vol.cluster_size + sector_in_cluster: uint32 = cluster_offset / 512 + offset_in_sector: uint32 = cluster_offset % 512 + sector: uint64 = vol.cluster_to_sector(self.current_cluster) + uint64(sector_in_cluster) + can_write_in_sector: uint32 = 512 - offset_in_sector + can_write: uint32 = can_write_in_sector + if can_write > remaining: can_write = remaining + if can_write == 0: break + if offset_in_sector == 0 and can_write >= 512: + abs_sect: uint64 = sector + uint64(vol.hidden_sectors) + vol.lock.lock() + res: DRESULT = diskio.write(vol.pdrv, buf_ptr, uint32(abs_sect), 1) + vol.lock.unlock() + if res != DRESULT.RES_OK: return FRESULT.FR_DISK_ERR + self.buf_sect = 0xFFFFFFFFFFFFFFFF + self.buf_dirty = 0 + else: + res2: FRESULT = self.buf_read(sector) + if res2 != FRESULT.FR_OK: return res2 + string.memcpy(&self.buf[offset_in_sector], buf_ptr, can_write) + self.buf_dirty = 1 + res3: FRESULT = self.buf_flush() + if res3 != FRESULT.FR_OK: return res3 + buf_ptr += can_write + self.file_pos += can_write + total_written += can_write + remaining -= can_write + if self.file_pos > self.file_size: self.file_size = self.file_pos + if self.file_pos % vol.cluster_size == 0: + next_c: uint32 = vol.cluster_get_next(self.current_cluster) + if next_c != 0: self.current_cluster = next_c + *bw = total_written + return FRESULT.FR_OK - def seek(self, offset: uint32) -> FRESULT: - if not self.is_open: return FRESULT.FR_INVALID_OBJECT - if offset > self.file_size: - if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED - gap: uint32 = offset - self.file_size - res: FRESULT = self._extend_to(offset) - if res != FRESULT.FR_OK: return res - old_size: uint32 = self.file_size - zero_buf: t.CArray[uint8, 512] - string.memset(c.Addr(zero_buf[0]), 0, 512) - self.file_pos = old_size - while gap > 0: - chunk: uint32 = gap - if chunk > 512: chunk = 512 - written: uint32 = 0 - res2: FRESULT = self.write(c.Addr(zero_buf[0]), chunk, c.Addr(written)) - if res2 != FRESULT.FR_OK: return res2 - if written == 0: return FRESULT.FR_DENIED - gap -= written - self.file_size = offset - self.vol.dir_update_entry(self.dir_sector, self.dir_offset, self.first_cluster, self.file_size, self.attr) - return FRESULT.FR_OK - self.file_pos = offset - if self.first_cluster < 2: - self.current_cluster = 0 - return FRESULT.FR_OK - self.current_cluster = self.vol.file_cluster_seek(self.first_cluster, offset) - return FRESULT.FR_OK + def seek(self, offset: uint32) -> FRESULT: + if not self.is_open: return FRESULT.FR_INVALID_OBJECT + if offset > self.file_size: + if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED + gap: uint32 = offset - self.file_size + res: FRESULT = self._extend_to(offset) + if res != FRESULT.FR_OK: return res + old_size: uint32 = self.file_size + zero_buf: [512]uint8 + string.memset(&zero_buf[0], 0, 512) + self.file_pos = old_size + while gap > 0: + chunk: uint32 = gap + if chunk > 512: chunk = 512 + written: uint32 = 0 + res2: FRESULT = self.write(&zero_buf[0], chunk, &written) + if res2 != FRESULT.FR_OK: return res2 + if written == 0: return FRESULT.FR_DENIED + gap -= written + self.file_size = offset + self.vol.dir_update_entry(self.dir_sector, self.dir_offset, self.first_cluster, self.file_size, self.attr) + return FRESULT.FR_OK + self.file_pos = offset + if self.first_cluster < 2: + self.current_cluster = 0 + return FRESULT.FR_OK + self.current_cluster = self.vol.file_cluster_seek(self.first_cluster, offset) + return FRESULT.FR_OK - def truncate(self) -> FRESULT: - if not self.is_open: return FRESULT.FR_INVALID_OBJECT - if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED - if self.file_pos >= self.file_size: return FRESULT.FR_OK - vol: volinfo | t.CPtr = self.vol - new_size: uint32 = self.file_pos - if new_size == 0: - if self.first_cluster >= 2: vol.cluster_free_chain(self.first_cluster) - self.first_cluster = 0 - self.current_cluster = 0 - self.file_size = 0 - self.file_pos = 0 - vol.dir_update_entry(self.dir_sector, self.dir_offset, 0, 0, self.attr) - return FRESULT.FR_OK - cluster_at_pos: uint32 = vol.file_cluster_seek(self.first_cluster, new_size) - if cluster_at_pos < 2: return FRESULT.FR_INT_ERR - next_c: uint32 = vol.cluster_get_next(cluster_at_pos) - vol.fat_write(cluster_at_pos, CLUSTER_EOC_MAX) - if next_c >= 2 and next_c < CLUSTER_EOC_MIN: - vol.cluster_free_chain(next_c) - self.file_size = new_size - self.current_cluster = cluster_at_pos - vol.dir_update_entry(self.dir_sector, self.dir_offset, self.first_cluster, new_size, self.attr) - return FRESULT.FR_OK + def truncate(self) -> FRESULT: + if not self.is_open: return FRESULT.FR_INVALID_OBJECT + if not (self.flags & FA_WRITE): return FRESULT.FR_DENIED + if self.file_pos >= self.file_size: return FRESULT.FR_OK + vol: volinfo* = self.vol + new_size: uint32 = self.file_pos + if new_size == 0: + if self.first_cluster >= 2: vol.cluster_free_chain(self.first_cluster) + self.first_cluster = 0 + self.current_cluster = 0 + self.file_size = 0 + self.file_pos = 0 + vol.dir_update_entry(self.dir_sector, self.dir_offset, 0, 0, self.attr) + return FRESULT.FR_OK + cluster_at_pos: uint32 = vol.file_cluster_seek(self.first_cluster, new_size) + if cluster_at_pos < 2: return FRESULT.FR_INT_ERR + next_c: uint32 = vol.cluster_get_next(cluster_at_pos) + vol.fat_write(cluster_at_pos, CLUSTER_EOC_MAX) + if next_c >= 2 and next_c < CLUSTER_EOC_MIN: + vol.cluster_free_chain(next_c) + self.file_size = new_size + self.current_cluster = cluster_at_pos + vol.dir_update_entry(self.dir_sector, self.dir_offset, self.first_cluster, new_size, self.attr) + return FRESULT.FR_OK - def tell(self) -> uint32: - return self.file_pos + def tell(self) -> uint32: + return self.file_pos - def size(self) -> uint32: - return self.file_size + def size(self) -> uint32: + return self.file_size -@t.Object class dirobj: - vol: volinfo | t.CPtr - cluster: uint32 = 0 - start_cluster: uint32 = 0 - sector: uint64 = 0 - offset: uint32 = 0 - is_open: int = 0 - lfn_ofs: uint32 = 4294967295 - lfn_cluster: uint32 = 0 - sfn: t.CArray[t.CChar, 12] + vol: volinfo* + cluster: uint32 = 0 + start_cluster: uint32 = 0 + sector: uint64 = 0 + offset: uint32 = 0 + is_open: int = 0 + lfn_ofs: uint32 = 4294967295 + lfn_cluster: uint32 = 0 + sfn: [12]char - def close(self): - self.is_open = 0 + def close(self): + self.is_open = 0 -handle_table: t.CArray[fileobj, MAX_HANDLES] -lock_table: t.CArray[filelock, MAX_LOCKS] -handles_initialized: t.CStatic | int = 0 +handle_table: [MAX_HANDLES]fileobj +lock_table: [MAX_LOCKS]filelock +handles_initialized: static int = 0 def handles_init(): - global handles_initialized, handle_table, lock_table - if handles_initialized: return - for i in range(MAX_HANDLES): - handle_table[i].is_open = 0 - handle_table[i].lock_count = 0 - for j in range(MAX_LOCKS): - lock_table[j].in_use = 0 - handles_initialized = 1 + global handles_initialized, handle_table, lock_table + if handles_initialized: return + for i in range(MAX_HANDLES): + handle_table[i].is_open = 0 + handle_table[i].lock_count = 0 + for j in range(MAX_LOCKS): + lock_table[j].in_use = 0 + handles_initialized = 1 -def handle_alloc() -> fileobj | t.CPtr: - global handle_table - handles_init() - for i in range(MAX_HANDLES): - if not handle_table[i].is_open: - return c.Addr(handle_table[i]) - # [DIAG] 表满定位:打印 handles_initialized 与前几个 handle 的 is_open + 表地址 - _dha: t.CArray[t.CChar, 120] - viperlib.snprintf(c.Addr(_dha), 120, "[handle] full init=%d h0=%d h1=%d h2=%d h3=%d addr=0x%lx\n", - handles_initialized, handle_table[0].is_open, handle_table[1].is_open, - handle_table[2].is_open, handle_table[3].is_open, uint64(c.Addr(handle_table[0]))) - serial.puts(c.Addr(_dha)) - return None +def handle_alloc() -> fileobj*: + global handle_table + handles_init() + for i in range(MAX_HANDLES): + if not handle_table[i].is_open: + return &handle_table[i] + return None def lock_check(dir_sector: uint64, dir_offset: uint32, mode: uint8) -> FRESULT: - global lock_table - handles_init() - for i in range(MAX_LOCKS): - lk: filelock | t.CPtr = c.Addr(lock_table[i]) - if lk.in_use and lk.dir_sector == dir_sector and lk.dir_offset == dir_offset: - if mode & FA_WRITE: return FRESULT.FR_LOCKED - if lk.exclusive: return FRESULT.FR_LOCKED - return FRESULT.FR_OK + global lock_table + handles_init() + for i in range(MAX_LOCKS): + lk: filelock* = &lock_table[i] + if lk.in_use and lk.dir_sector == dir_sector and lk.dir_offset == dir_offset: + if mode & FA_WRITE: return FRESULT.FR_LOCKED + if lk.exclusive: return FRESULT.FR_LOCKED + return FRESULT.FR_OK def lock_acquire(dir_sector: uint64, dir_offset: uint32, exclusive: int) -> FRESULT: - global lock_table - handles_init() - for i in range(MAX_LOCKS): - lk: filelock | t.CPtr = c.Addr(lock_table[i]) - if not lk.in_use: - lk.in_use = 1 - lk.dir_sector = dir_sector - lk.dir_offset = dir_offset - lk.exclusive = exclusive - lk.shared_count = 1 if not exclusive else 0 - return FRESULT.FR_OK - return FRESULT.FR_TOO_MANY_OPEN_FILES + global lock_table + handles_init() + for i in range(MAX_LOCKS): + lk: filelock* = &lock_table[i] + if not lk.in_use: + lk.in_use = 1 + lk.dir_sector = dir_sector + lk.dir_offset = dir_offset + lk.exclusive = exclusive + lk.shared_count = 1 if not exclusive else 0 + return FRESULT.FR_OK + return FRESULT.FR_TOO_MANY_OPEN_FILES def lock_release(dir_sector: uint64, dir_offset: uint32): - global lock_table - handles_init() - for i in range(MAX_LOCKS): - lk: filelock | t.CPtr = c.Addr(lock_table[i]) - if lk.in_use and lk.dir_sector == dir_sector and lk.dir_offset == dir_offset: - lk.shared_count -= 1 - if lk.shared_count <= 0: lk.in_use = 0 - return + global lock_table + handles_init() + for i in range(MAX_LOCKS): + lk: filelock* = &lock_table[i] + if lk.in_use and lk.dir_sector == dir_sector and lk.dir_offset == dir_offset: + lk.shared_count -= 1 + if lk.shared_count <= 0: lk.in_use = 0 + return diff --git a/VKernel/Kernel/drivers/fs/fat32/fileio.vp b/VKernel/Kernel/drivers/fs/fat32/fileio.vp index 1ff5896..8d2c67d 100644 --- a/VKernel/Kernel/drivers/fs/fat32/fileio.vp +++ b/VKernel/Kernel/drivers/fs/fat32/fileio.vp @@ -1,3 +1 @@ import fat32 - - diff --git a/VKernel/Kernel/drivers/input/keyboard/keyboard.vp b/VKernel/Kernel/drivers/input/keyboard/keyboard.vp index 5a85029..77501c2 100644 --- a/VKernel/Kernel/drivers/input/keyboard/keyboard.vp +++ b/VKernel/Kernel/drivers/input/keyboard/keyboard.vp @@ -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', diff --git a/VKernel/Kernel/drivers/input/mouse/mouse.vp b/VKernel/Kernel/drivers/input/mouse/mouse.vp index 41dd454..38bce65 100644 --- a/VKernel/Kernel/drivers/input/mouse/mouse.vp +++ b/VKernel/Kernel/drivers/input/mouse/mouse.vp @@ -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() diff --git a/VKernel/Kernel/drivers/serial/uart/serial.vp b/VKernel/Kernel/drivers/serial/uart/serial.vp index 7f53cc2..90d6ac1 100644 --- a/VKernel/Kernel/drivers/serial/uart/serial.vp +++ b/VKernel/Kernel/drivers/serial/uart/serial.vp @@ -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 diff --git a/VKernel/Kernel/drivers/serial/uart/su8250.vp b/VKernel/Kernel/drivers/serial/uart/su8250.vp index 173d683..75f846b 100644 --- a/VKernel/Kernel/drivers/serial/uart/su8250.vp +++ b/VKernel/Kernel/drivers/serial/uart/su8250.vp @@ -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 # 读取字符 diff --git a/VKernel/Kernel/drivers/storage/ide/ide.vp b/VKernel/Kernel/drivers/storage/ide/ide.vp index 3add315..34c480b 100644 --- a/VKernel/Kernel/drivers/storage/ide/ide.vp +++ b/VKernel/Kernel/drivers/storage/ide/ide.vp @@ -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) diff --git a/VKernel/Kernel/drivers/usb/hid/hid.vp b/VKernel/Kernel/drivers/usb/hid/hid.vp index cd4806a..b94388e 100644 --- a/VKernel/Kernel/drivers/usb/hid/hid.vp +++ b/VKernel/Kernel/drivers/usb/hid/hid.vp @@ -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) diff --git a/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp b/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp index c971782..2e37a59 100644 --- a/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp +++ b/VKernel/Kernel/drivers/usb/hid/usb_kbd.vp @@ -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: diff --git a/VKernel/Kernel/drivers/usb/hid/usb_mouse.vp b/VKernel/Kernel/drivers/usb/hid/usb_mouse.vp index f6bcab7..f883a2f 100644 --- a/VKernel/Kernel/drivers/usb/hid/usb_mouse.vp +++ b/VKernel/Kernel/drivers/usb/hid/usb_mouse.vp @@ -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 diff --git a/VKernel/Kernel/drivers/usb/pci.vp b/VKernel/Kernel/drivers/usb/pci.vp index 72c954a..2f55048 100644 --- a/VKernel/Kernel/drivers/usb/pci.vp +++ b/VKernel/Kernel/drivers/usb/pci.vp @@ -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) diff --git a/VKernel/Kernel/drivers/usb/uhci.vp b/VKernel/Kernel/drivers/usb/uhci.vp index 50c88aa..8cd2330 100644 --- a/VKernel/Kernel/drivers/usb/uhci.vp +++ b/VKernel/Kernel/drivers/usb/uhci.vp @@ -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) diff --git a/VKernel/Kernel/execrunner/elf.vp b/VKernel/Kernel/execrunner/elf.vp index 8b4f243..ce64478 100644 --- a/VKernel/Kernel/execrunner/elf.vp +++ b/VKernel/Kernel/execrunner/elf.vp @@ -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 diff --git a/VKernel/Kernel/main.vp b/VKernel/Kernel/main.vp index a21fd3c..e59a1d4 100644 --- a/VKernel/Kernel/main.vp +++ b/VKernel/Kernel/main.vp @@ -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() diff --git a/VKernel/Kernel/paging/paging.vp b/VKernel/Kernel/paging/paging.vp index dc71a7b..e8df094 100644 --- a/VKernel/Kernel/paging/paging.vp +++ b/VKernel/Kernel/paging/paging.vp @@ -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)