Repository navigation
Conversation
The kernel held what the loader named of where the system booted from: four partition GUIDs by role, answered as `Loaded` records in the device inventory; the two boot sources, answered whole by `SYS_BOOT_SOURCES`; and a UEFI device-path parse of each source, linked only to refuse the loader's own bytes. The manual gives partition identity to userland and has the kernel parse nothing one program writes for another. The loader now writes one record of all of it (`toyos-bootnames`): the ROOT, slot volume and log partitions, the boot partition where firmware named one, and each source's device path with the PCI function it runs through. It hands the record to the kernel as a fourth boot image beside the file server's and ROOT's, and the kernel keeps its pages read-only and endows the supervisor with them under `boot:names`, as it does ROOT, reading none of it. The supervisor parses the record once at start and panics on one it cannot read: the loader wrote it, so a record that does not parse is another build's loader. Absence is a tag in the record, so no zero GUID or presence flag stands for it. What goes: - `kernel/src/loaded.rs`, `SYS_BOOT_SOURCES`, the inventory's `Loaded` record and `Role`, and the kernel's link to `toyos-devicepath`; - `KernelArgs`' boot-partition fields (two of them read by one log line), its log, ROOT and slot-volume GUIDs and `boot_sources`, and the ABI's `BootSources`, `BootSource`, `Controller` and `Unwritten`; - `dev.loaded.<role>` in inspect, which rendered those records; the supervisor's first line now says the four partitions; - the supervisor's read of the inventory for them, and with it the block service's `--active-unknown`, which only a failed read sent. `KernelArgs::layout` moves from offset 164 to 112: the fields that left were before it. The kernel still reads the word before any field after it; a loader older than this wrote the low half of its ESP's first block there, and the size folded into `LAYOUT` changes as well. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
The loader track promised that every field before `KernelArgs::layout` keeps its offset in every layout, and the field's own contract repeated it. The word moved once, with the fields that left for the supervisor's record. Both now say what holds: the word follows only the fields the kernel reads before it compares it, and what a loader and a kernel on either side of the move read of each other. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Review r1 of #1210 at
|
…xception is said Every field before `KernelArgs::layout` now has its `offset_of!` assert, where three of sixteen did, so the record's "each pinned" is true at compile time. `LAYOUT`'s low byte is asserted non-zero: a loader older than the word's place wrote its partition's first block there, and a partition on a 1 MiB boundary starts at a multiple of 256 blocks at either block size, so such a loader is always refused. The comment and the loader track say that, and that a partition off such a boundary can still equal the word. The kernel-is-small record's stale-text entry for `loaded.rs` goes with the file. Three comments and the manual's line say what they mean: the loader's source is the device firmware loaded it from, both of the supervisor's image handles are handed on unread, and the log partition is named, not read. No built code changes: the asserts are constant, and the two comments in files that carry panic locations keep their line counts. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Review r2 of #1210 at
|
|
Orchestrator, before queueing at f7a54f7 (the head review r2 gave LAND; unchanged since). Review r2's landing precondition is met. Both bench boots of the 3b2d0a9 images ran (r2 accepted them as evidence for this head) and the harness judged the readbacks from a tree at f7a54f7:
On both, the supervisor's device paths, |
`assert!(LAYOUT % 256 != 0)` is clippy's `manual_is_multiple_of`, which the host lint denies; `u32::is_multiple_of` is callable in a constant, so the assert says the same thing with it. The two blank lines left where `sys_boot_sources` was become one. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
Orchestrator: the merge queue removed this PR at f7a54f7 because the Linux lint step was red on clippy's
The implementer's |
The rebase's resolution of the inventory left conflict markers in the commit before this one. The section is main's again, with what #1200 did marked done as #1210 marked its own, and the track's measurement says the kernel this branch leaves. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Problem
The kernel held what the loader named of where the system booted from, and interpreted part of it:
kernel/src/loaded.rs), answered asLoadedrecords in the device inventory;SYS_BOOT_SOURCES;toyos-devicepath), linked into the kernel only to refuse the loader's own bytes;KernelArgs::boot_partition_start_lbaandboot_partition_blocks, read by one log line.The manual gives partition identity to userland and has the kernel parse nothing one program writes for another. The inventory in
issues/the-kernel-is-small-interrupts-post-and-threads-wait.md(#1208) lists this as a removal that waits on no other change; I confirmed its description against the code at9349705cebefore designing.What changes
The loader writes one record of what it named; the kernel carries the record's bytes to the supervisor and reads none of them; the supervisor parses it.
lib/bootnames(toyos-bootnames): the ROOT, slot-volume and log partitions, the boot partition where firmware named one, and for the loader and the slot volume the firmware device path with the PCI function it runs through.Names::encodeis the loader's side andNames::parsethe supervisor's. Absence is a tag, so no zero GUID or presence flag stands for it; the three partitions every boot has are not optional in the type.loader/src/bootsource.rs) builds the record before it exits boot services and puts it inLoaderDatapages of its own, as it does a section of the slot image.BootImagebeside the supervisor's, the file server's and ROOT's (KernelArgs::boot_names): the same checks, the same read-onlySharedMemObject, endowed to the supervisor underboot:names. No new syscall and no new object kind.What goes:
kernel/src/loaded.rs;SYS_BOOT_SOURCES(137) with its ABI and SDK wrappers; the inventory'sLoadedrecord andRole; the ABI'sBootSources,BootSource,ControllerandUnwritten;KernelArgs' four boot-partition fields, its log, ROOT and slot-volume GUIDs andboot_sources; the kernel's dependency ontoyos-devicepath; the two kernel log lines that printed the boot and log partitions.git ls-files 'kernel/src/*.rs': 215 files and 55,378 lines before, 214 and 55,303 after (75 fewer), and the kernel no longer links the 324-line device-path parser.KernelArgsis 440 bytes, from 1,560.Decisions a reviewer should weigh
KernelArgs::layoutmoves from offset 164 to 112, accepted by the orchestrator over 52 reserved bytes in front of it: no loader is deployed, and updates fix forward. What is guaranteed, at compile time: all sixteen fields before the word and the word itself are pinned byoffset_of!, andLAYOUT's low byte is not zero. What a mismatched pair does, read off the code and run on no machine:boot_pml4_addron aarch64), the scanout inpanic_console::arm,rsdp_addrfor the UART. At 112 the old loader wrote the low 32 bits of the first block of the partition firmware loaded it from, or zero where firmware named none. A partition on a 1 MiB boundary starts at a multiple of 256 blocks at 512-byte and at 4 KiB blocks, so its low byte is zero and the word's is not: the kernel panicsboot: the loader wrote KernelArgs layout … and this kernel reads layout 0x545901b8on the panel and the UART, before it reads any field that moved. Not guaranteed: a partition that starts off a 1 MiB boundary, at exactly block 1,415,119,288 modulo 2^32, equals the word; that loader is not refused and the kernel reads moved fields as garbage. The comment atLAYOUTand the loader track say so.loader_handoff_counter. That equals the old0x54590618only for a counter past0x5459<< 48 ticks, decades at any counter rate, so it panics with the same line naming the two words.KernelArgschange since the word exists:updatedoes not replace the loader on the ESP. The record format'sMAGICis a second loader-to-slot version besideLAYOUT; a mismatch in it alone is refused by the supervisor, after the kernel has booted.toyos-abi, which is the kernel's boundary, and the kernel does not link it.dev.loaded.<role>leaves inspect, accepted by the orchestrator as removed with the supervisor's log lines as its replacement and no record owed. It rendered the inventory'sLoadedrecords, which no longer exist; nothing in the tree read those paths but the renderer's own tests.--active-unknowngoes. The supervisor sent it only when its read of the inventory failed; it now holds the names from start, so nothing can send it.Files shared with open PRs
Removing a syscall cannot avoid
sdk/abi/src/syscall.rsandkernel/src/syscall/dispatch.rs, which #1200 and #1204 also change, in other hunks.kernel/src/loader/mod.rsgains one array entry inspawn_supervisor, a few lines above a hunk of #1200's.kernel/src/main.rschanges at the reserved-region list and two log lines; no page-table or mapping code is touched. Nothing of #1202, #1203 or #1131 is touched.Checks
cargo run -- --build-onlycargo run -- --ci hostthe build system, byllvm::tests::the_caller_s_environment_reaches_neither_the_build_nor_the_keyalone, where macOS'sgitshim cannot find Xcode'sgitunder the test's environment (issues/the-llvm-environment-test-breaks-git-on-macos.md); #1208's run reds the same step on a tree with no code change. The new crate's four tests, the supervisor's lifecycle tests, the ABI's and inspect's are among the green. logthe_log_lands_on_the_boot_stick a_host_disk_beside_the_stick_is_left_alone the_data_partition_beside_the_stick_is_designated nvme_disk_boots usbd_drives_the_spare a_clean_stop_proves_its_image console_image_boots a_bent_supervisor a_supervisor_that_fails_early virt_first_entry virt_user_mode virt_smp virt_jobs_at_el2 virt_rebootvirt_reboot_refused_without_psci, which the wordvirt_rebootselected beside the row I meant:STALLED: waiting for the job reboot to end — it went quietafter 18 s. That is the open defectissues/virt-reboot-refused-without-psci-goes-quiet-before-its-job.md, recorded red on main atec8912181with the same line;virt_reboot, the same image with PSCI, is green here as it is there. I did not rerun it. log, and five lines of one x86-64 boot's console: the kernel'sboot: boot names image …+0xf9and the supervisor's fourThe host and image checks were made on the tree of
cccaf1e0f, a commit the rebase replaced.3b2d0a999differs from it by the rebase onto #1208 (records only) and edits to one issue record; no source file differs. The two commits after it change comments, two issue records, the manual's wording and compile-time asserts insdk/abi/src/boot.rs: the only lines that are not comments are thirteenoffset_of!asserts andassert!(LAYOUT % 256 != 0), all inside the constant block.cargo run -- --build-onlyat the headf7a54f7aeexits 0, which compilestoyos-abiand the kernel with the new asserts. Built in the same worktree at3b2d0a999and at the head, 42 of the 45 binaries are byte-identical, the loader among them. The kernel, the supervisor anddoomare not: in each, every allocated section but the build-id note is identical and every symbol keeps its address and size, and what differs is the.llvm.<hash>suffix of ThinLTO-promoted symbol names (15, 243 and 26 symbols) and, for the two programs, the build-id. So the staged images run that revision's code and data exactly, and are not its bytes. No guest check was repeated.The head,
4ef2f55c6, changes two lines afterf7a54f7ae. The assert becomesassert!(!LAYOUT.is_multiple_of(256));: the merge group's Linux lint step refusedLAYOUT % 256 != 0as clippy'smanual_is_multiple_of, which my compile-only check of that commit did not run. And one of the two blank lines left inkernel/src/syscall/machine.rsgoes, review suggestion 5, which moves the line number one panic location in the kernel carries.cargo run -- --ci host lintat the head exits 0 with 5 steps green on macOS arm64 (log); the Linux lint is the merge group's to confirm. The binaries were not compared again at this head.The aarch64 rows apply because the loader's handoff is shared: four of the five I selected are green, and the fifth name's second match is the recorded defect above.
Negative controls on the parser's tests, each a checked patch applied, run and reverted: accepting trailing bytes reds
hostile_bytes_are_refused_by_name; reading the slot and log GUIDs in each other's place redsevery_shape_the_loader_writes_reads_back. Patches and runs.Metal
Both benches booted the images staged at
3b2d0a999, onetestcasesboot each, run by the orchestrator, and I judged the readbacks from the worktree atf7a54f7ae, one commit before the head, withcargo test --test toyos-build -- --metal --metal-readback <dir> <rows>.control_regs,nvme_leaves_the_benchs_disk_alone,usbd_drives_the_type_c_controllercontrol_regs,nvme_leaves_the_benchs_disk_alone,amdvi_translates_the_boot_controller,amdvi_remaps_the_boot_controller,amdvi_usbd_drives_its_own_entryOn each bench the supervisor's four lines agree with the loader's own (T14, AMD bench): the two device paths are the loader's
Boot source:paths character for character, the controller is the one the loader placed (04:00.0and02:00.0), the boot partition and the log are the GUIDs of the loader'sBoot partition:andLog partition:signatures, and the slot volume is the GUID in the slot path'sHD(8,…)node. ROOT's GUID has no loader line to be read against. The kernel's line isboot: boot names image …+0x105on both.The images are the staged revision's: the supervisor says
build 3b2d0a999…in both readbacks, and the kernel's symbol names and the supervisor's build-id in them are that revision's, not the head's, as the comparison above says. The staging requests and logs are beside them.These are installed-disk boots, not USB boots.
toyos-metalwrites the image to the install area of the bench's internal NVMe, after the bench's own four partitions, and boots it once throughBootNext; no bench row boots a stick (issues/no-bench-row-drives-usb-storage-since-the-benches-boot-off-nvme.md). So what the two boots exercise of this change, on real firmware:PciRoot/Pci…/NVMe/HD), andGetLocation()placing the controller;nvme_leaves_the_benchs_disk_alone);@bootnaming the NVMe controller, so the spare xHCI rows find a controller that is not it.What no metal boot exercises: a source whose path runs through a USB node, with
@bootan xHCI and LOG on a stick. A guest row holds that under QEMU's firmware:the_log_lands_on_the_boot_stickboots offusb-storageon an xHCI and is green in the run above; its console is not in the evidence, since a green row keeps none. The path's text form with a USB node is a unit test's. A machine whose firmware names no boot partition, or no device path, is reached by unit tests alone.Not done
🤖 Generated with Claude Code