code wiki / _hdl_build / rv64im_min_elf_loader.nx

rv64im_min_elf_loader.nx

buildroot/runtime/_hdl_build/rv64im_min_elf_loader.nx

10391 B269 linesdepth 5pulls 16 transitivereach 6 importersview sourcekind librarytopic rv64im
docsdependenciesstructsconstsfunctions

about

rv64im_min_elf_loader.nx -- ELF64 loader for the RV64IM-min sim. Parses an ELF64 (little-endian, EM_RISCV) byte buffer and copies every PT_LOAD segment into the simulator's mem_buf at the segment's physical address. Sets sim.pc to e_entry. This is what lets the sim boot the actual nishi-os kernel ELF (nishi-os/kernel/nishi-kernel.elf) without hand-coding instructions. Follow-on commits add an end-to-end harness that: 1. Reads kernel ELF bytes via sys_openat + sys_read 2. Calls nx_elf_load to populate sim.mem_buf 3. Runs the sim until halted (or 100k cycles, whichever first) 4. Asserts uart.tx_buf contains the 10 expected [m0-*] markers Status: SEED. 2026-05-26. Loader-only. ELF parsing per the System V ABI (ELF Specification 1.2) + RISC-V ELF psABI.

dependencies 9 imports · 5 importers

nx_syscalls.nx nishi_hdl_primitives.nx rv64im_min_decoder.nx rv64im_min_alu.nx rv64im_min_regfile.nx rv64im_min_csr.nx rv64im_min_clint.nx rv64im_min_uart.nx rv64im_min_sim.nx rv64im_min_elf_loader.nx nx_rv64im_cpu_crosscheck.nx rv64im_min_cpu_crosscheck.nx rv64im_min_hot_report.nx rv64im_min_kernel_boot_smoke.nx rv64im_min_symtab.nx

imports: nx_syscalls.nxnishi_hdl_primitives.nxrv64im_min_decoder.nxrv64im_min_alu.nxrv64im_min_regfile.nxrv64im_min_csr.nxrv64im_min_clint.nxrv64im_min_uart.nxrv64im_min_sim.nx

imported by: nx_rv64im_cpu_crosscheck.nxrv64im_min_cpu_crosscheck.nxrv64im_min_hot_report.nxrv64im_min_kernel_boot_smoke.nxrv64im_min_symtab.nx

structs

134struct NxElfLoad

consts

29const NX_ELF_MAG0: i64 = 0x7f
30const NX_ELF_MAG1: i64 = 0x45 // 'E'
31const NX_ELF_MAG2: i64 = 0x4c // 'L'
32const NX_ELF_MAG3: i64 = 0x46 // 'F'
34const NX_ELF_CLASS_64: i64 = 2 // EI_CLASS = ELFCLASS64
35const NX_ELF_DATA_LSB: i64 = 1 // EI_DATA = ELFDATA2LSB (little-endian)
36const NX_ELF_VERSION_CURRENT: i64 = 1
37const NX_ELF_MACHINE_RISCV: i64 = 243 // EM_RISCV = 0xF3
40const NX_ELF_ET_EXEC: i64 = 2
41const NX_ELF_ET_DYN: i64 = 3
44const NX_ELF_PT_NULL: i64 = 0
45const NX_ELF_PT_LOAD: i64 = 1
46const NX_ELF_PT_DYNAMIC: i64 = 2
47const NX_ELF_PT_INTERP: i64 = 3
48const NX_ELF_PT_NOTE: i64 = 4
49const NX_ELF_PT_PHDR: i64 = 6
50const NX_ELF_PT_GNU_STACK: i64 = 0x6474e551
53const NX_ELF_OFF_E_IDENT: i64 = 0
54const NX_ELF_OFF_E_TYPE: i64 = 16
55const NX_ELF_OFF_E_MACHINE: i64 = 18
56const NX_ELF_OFF_E_VERSION: i64 = 20
57const NX_ELF_OFF_E_ENTRY: i64 = 24
58const NX_ELF_OFF_E_PHOFF: i64 = 32
59const NX_ELF_OFF_E_SHOFF: i64 = 40
60const NX_ELF_OFF_E_FLAGS: i64 = 48
61const NX_ELF_OFF_E_EHSIZE: i64 = 52
62const NX_ELF_OFF_E_PHENTSIZE: i64 = 54
63const NX_ELF_OFF_E_PHNUM: i64 = 56
64const NX_ELF_OFF_E_SHENTSIZE: i64 = 58
65const NX_ELF_OFF_E_SHNUM: i64 = 60
66const NX_ELF_OFF_E_SHSTRNDX: i64 = 62
67const NX_ELF_EHDR_SIZE: i64 = 64
70const NX_ELF_PH_OFF_P_TYPE: i64 = 0
71const NX_ELF_PH_OFF_P_FLAGS: i64 = 4
72const NX_ELF_PH_OFF_P_OFFSET: i64 = 8
73const NX_ELF_PH_OFF_P_VADDR: i64 = 16
74const NX_ELF_PH_OFF_P_PADDR: i64 = 24
75const NX_ELF_PH_OFF_P_FILESZ: i64 = 32
76const NX_ELF_PH_OFF_P_MEMSZ: i64 = 40
77const NX_ELF_PH_OFF_P_ALIGN: i64 = 48
78const NX_ELF_PHDR_SIZE: i64 = 56
81const NX_ELF_OK: i64 = 0
82const NX_ELF_BAD_MAGIC: i64 = 1
83const NX_ELF_NOT_64BIT: i64 = 2
84const NX_ELF_NOT_LITTLE_ENDIAN: i64 = 3
85const NX_ELF_BAD_VERSION: i64 = 4
86const NX_ELF_NOT_RISCV: i64 = 5
87const NX_ELF_BAD_TYPE: i64 = 6
88const NX_ELF_TRUNCATED: i64 = 7
89const NX_ELF_BAD_PHENTSIZE: i64 = 8
90const NX_ELF_SEGMENT_OUT_OF_RANGE: i64 = 9 // segment doesn't fit in sim.mem
91const NX_ELF_FILESZ_GT_MEMSZ: i64 = 10 // malformed: filesz > memsz

functions

99func nx_elf_read_u8(buf: *u8, off: i64) -> i64
called by 1: nx_elf_load_symtab
103func nx_elf_read_u16(buf: *u8, off: i64) -> i64
109func nx_elf_read_u32(buf: *u8, off: i64) -> i64
117func nx_elf_read_u64(buf: *u8, off: i64) -> i64
146func nx_elf_validate_ident(buf: *u8, size: i64) -> i64
171func nx_elf_copy_segment(buf: *u8, buf_size: i64, sim: *NxRv64imSim,
called by 1: nx_elf_load
200func nx_elf_load(buf: *u8, buf_size: i64, sim: *NxRv64imSim, out: *NxElfLoad) -> i64
259func nx_elf_entry(buf: *u8) -> i64
calls 1: nx_elf_read_u64
263func nx_elf_phnum(buf: *u8) -> i64
calls 1: nx_elf_read_u16
267func nx_elf_e_type(buf: *u8) -> i64
calls 1: nx_elf_read_u16