code wiki / _hdl_build / nx_bootcap.nx
nx_bootcap.nx source
↩ module page · 90 lines · 4589 B
1// nx_bootcap.nx -- ONE boot-and-capture primitive for every organ that needs to know what the
2// live kernel actually SAID.
3//
4// WHY: measuring a kernel means booting the ARTIFACT and reading its serial -- not parsing a log
5// ABOUT the artifact, which can be stale, written by a different build, or absent entirely. That
6// boot-and-capture block had already been copy-pasted into nx_nishios_kernel_gate and
7// nx_kernel_adoption and was about to land in nx_kernel_census as a third copy; three copies of a
8// measurement primitive is three chances for the rulers to silently disagree about what booted.
9//
10// Also owns the TWO-ROOTS resolution: the buildroot keeps the image under runtime/_hdl_build/
11// while the live serving root keeps it at ./ -- one name, two roots. Callers get the resolved
12// path back so they can PRINT which artifact they actually measured; a ruler that will not say
13// which artifact it read is not reporting a measurement.
14// license_tier: ORIGINAL
15import "rv64im_min_sim.nx"
16import "rv64im_min_csr.nx"
17import "rv64im_min_clint.nx"
18import "rv64im_min_uart.nx"
19import "rv64im_min_virtio.nx"
20import "rv64im_min_nvme.nx"
21
22const BOOTCAP_MEM_BASE: i64 = 0x80000000
23const BOOTCAP_MEM_SIZE: i64 = 65536
24const BOOTCAP_MAX_STEPS: i64 = 100000
25// res[] slots the caller reads back
26const BOOTCAP_R_HALTED: i64 = 0
27const BOOTCAP_R_CODE: i64 = 1
28const BOOTCAP_R_STEPS: i64 = 2
29const BOOTCAP_R_TXN: i64 = 3
30const BOOTCAP_R_N: i64 = 4
31
32// Boot `img` on a FRESH machine (every device re-allocated, so run N cannot contaminate run N+1
33// -- the negative-control runs depend on that isolation) and capture the UART. Returns tx count.
34func bootcap_run(img: *u8, ilen: i64, tx_buf: *u8, txcap: i64, res: *i64) -> i64 {
35 let rf_storage: *i64 = (sys_mmap(8 * NX_RV64IM_RF_N_REGS)) as *i64
36 let csr_storage: *i64 = (sys_mmap(8 * NX_CSR_SLOT_N)) as *i64
37 let clint_storage: *i64 = (sys_mmap(8 * NX_CLINT_SLOT_N)) as *i64
38 let uart_storage: *i64 = (sys_mmap(8 * NX_UART_SLOT_N)) as *i64
39 let virtio_storage:*i64 = (sys_mmap(8 * NX_VIRTIO_SLOT_N)) as *i64
40 let vnet_storage: *i64 = (sys_mmap(8 * NX_VIRTIO_SLOT_N)) as *i64
41 let nvme_storage: *i64 = (sys_mmap(8 * NX_NVME_SLOT_N)) as *i64
42 let nndev_storage: *i64 = (sys_mmap(8 * NX_NNDEV_SLOT_N)) as *i64
43 let mmu_storage: *i64 = (sys_mmap(8 * NX_MMU_SLOT_N)) as *i64
44 let mem: *u8 = sys_mmap(BOOTCAP_MEM_SIZE)
45 let rf: *NxRv64imRegfile = (sys_mmap(64)) as *NxRv64imRegfile
46 let csr: *NxRv64imCsrFile = (sys_mmap(64)) as *NxRv64imCsrFile
47 let clint: *NxClint = (sys_mmap(64)) as *NxClint
48 let uart: *NxUart = (sys_mmap(64)) as *NxUart
49 let virtio:*NxVirtioMmio = (sys_mmap(64)) as *NxVirtioMmio
50 let vnet: *NxVirtioMmio = (sys_mmap(64)) as *NxVirtioMmio
51 let nvme: *NxNvmeCtrl = (sys_mmap(64)) as *NxNvmeCtrl
52 let nndev: *NxNnDev = (sys_mmap(64)) as *NxNnDev
53 let mmu: *NxMmu = (sys_mmap(64)) as *NxMmu
54 let sim: *NxRv64imSim = (sys_mmap(128)) as *NxRv64imSim
55 nx_rv64im_rf_init(rf, rf_storage)
56 nx_rv64im_csr_init(csr, csr_storage, 0)
57 nx_clint_init(clint, clint_storage)
58 nx_uart_init(uart, uart_storage, tx_buf, txcap)
59 nx_virtio_init(virtio, virtio_storage)
60 nx_virtio_init_net(vnet, vnet_storage)
61 nx_nvme_init(nvme, nvme_storage)
62 nx_nndev_init(nndev, nndev_storage)
63 nx_mmu_init(mmu, mmu_storage)
64 nx_rv64im_sim_init(sim, rf, csr, clint, uart, BOOTCAP_MEM_BASE, mem, BOOTCAP_MEM_SIZE, 0)
65 nx_rv64im_sim_attach_virtio(sim, virtio)
66 nx_rv64im_sim_attach_virtio_net(sim, vnet)
67 nx_rv64im_sim_attach_nvme(sim, nvme)
68 nx_rv64im_sim_attach_nndev(sim, nndev)
69 nx_rv64im_sim_attach_mmu(sim, mmu)
70 var i: i64 = 0
71 while i < ilen { mem[i] = img[i]; i = i + 1 }
72 nx_rv64im_sim_run(sim, BOOTCAP_MAX_STEPS)
73 let cnt: i64 = nx_uart_tx_count(uart)
74 res[BOOTCAP_R_HALTED] = sim.halted
75 res[BOOTCAP_R_CODE] = sim.halt_code
76 res[BOOTCAP_R_STEPS] = sim.steps
77 res[BOOTCAP_R_TXN] = cnt
78 return cnt
79}
80
81// Resolve the kernel image across the two roots. Returns the buffer (0 if neither exists) and
82// writes the byte length to lenp[0]; `outpath` receives which path actually answered.
83func bootcap_load(primary: *u8, alt: *u8, lenp: *i64, outpath: *i64) -> *u8 {
84 var img: *u8 = sys_read_file(primary, lenp)
85 if lenp[0] > 0 { outpath[0] = primary as i64; return img }
86 img = sys_read_file(alt, lenp)
87 if lenp[0] > 0 { outpath[0] = alt as i64; return img }
88 outpath[0] = primary as i64
89 return 0 as *u8
90}