Boot the kernel, optionally injecting an FS image and a pid-1 user binary, and optionally pre-loading a UART session. Returns the VM (for post-run peeks), the final outcome, and the captured UART output. Set up a booted kernel VM (RAM layout + optional FS image + pid-1 user binary + front-loaded UART input) without running it, so callers can either run it in one shot (boot_kernel) or step it manua
(
kernel: &AssembledOutput,
user: Option<&AssembledOutput>,
fs_image: Option<&[u8]>,
input: &str,
)
| 83 | .expect("write fs image PA"); |
| 84 | vm.write_ram(FS_META_PA + 8, &(image.len() as u64).to_le_bytes()) |
| 85 | .expect("write fs image size"); |
| 86 | vm.write_ram(FS_IMAGE_PA, image).expect("write fs image"); |
| 87 | } |
| 88 | |
| 89 | if let Some(u) = user { |
| 90 | let mut flat = u.to_flat_binary(); |
| 91 | let page = 4096usize; |
| 92 | flat.resize(flat.len().div_ceil(page) * page, 0u8); |
| 93 | let entry_off = u.symbol_address("_start").expect("_start missing"); |
| 94 | let entry_va = USER_CODE_VA + entry_off; |
| 95 | let user_size = flat.len() as u64; |
| 96 | vm.write_ram(USER_META_PA, &entry_va.to_le_bytes()) |
| 97 | .expect("write user entry VA"); |
| 98 | vm.write_ram(USER_META_PA + 8, &user_size.to_le_bytes()) |
| 99 | .expect("write user size"); |
| 100 | vm.write_ram(USER_BINARY_PA, &flat) |
| 101 | .expect("write user binary"); |
| 102 | } |
| 103 | |
| 104 | for b in input.bytes() { |
| 105 | vm.push_uart_rx(b); |
| 106 | } |
| 107 | |
| 108 | vm |
| 109 | } |
| 110 | |
| 111 | fn boot_kernel( |
| 112 | kernel: &AssembledOutput, |
| 113 | user: Option<&AssembledOutput>, |
| 114 | fs_image: Option<&[u8]>, |
| 115 | input: &str, |
| 116 | max_steps: u64, |
| 117 | ) -> (VirtualMachine, StepOutcome, String) { |
| 118 | let mut vm = setup_kernel_vm(kernel, user, fs_image, input); |
| 119 | let run = vm.run(max_steps); |
| 120 | (vm, run.outcome, run.uart_output) |
| 121 | } |
| 122 | |
| 123 | // A hosted user program injected as pid 1 must spawn and exit with code 0. |
| 124 | fn assert_user_exit_ok(uart: &str, outcome: &StepOutcome, label: &str) { |