Loader slimming stage 1: the RTC is UTC, KernelArgs refuses another layout by name, IA32_TSC_ADJUST moves to the kernel - #583
Conversation
…elds that carried it go Owner ruling: the hardware clock is always UTC. The loader no longer asks firmware's GetTime for EFI_TIME::TimeZone, KernelArgs loses rtc_utc_offset_minutes and rtc_utc_offset_known (every field after them moves eight bytes down, the size goes 1280 -> 1272; the const asserts in toyos-abi/src/boot.rs pin each offset, and the three _start reads by hand at 16/32/40 are unmoved), and the kernel anchors one UTC clock off the RTC: UTC_OFFSET_SECS, local_secs and the rtc-zone-east actuator go, and FAT stamps, SYS_CLOCK_REALTIME and SYS_CLOCK_EPOCH all read clock::utc_secs. wall_clock_zone tested the deleted feature and goes; wall_clock_utc (Weekly, as its predecessor) asserts the UTC behaviour that stays: with the host's -rtc base= instant staged, the log file's name, its FAT stamp and SYS_CLOCK_EPOCH all sit within 0..300 s of that instant. Filed: logd still recovers a zone offset from the two clock calls, which is now always zero (issues/design-debt/logd-recovers-a-zone-offset-the-kernel-no-longer-has.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
rootbridge::windows printed every byte of each bridge's Configuration() answer. Nothing reads that line; the windows it decodes and every refusal are still said. Filed: toyos_acpi::Walk::bytes existed for that dump and now has no reader outside its own tests (issues/design-debt/toyos-acpi-walk-bytes-has-no-reader.md). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
Deleted, never rewritten; where one held a real invariant, that clause stays.
1. loaderlog.rs: open's doc, misplaced on volume_handle.
2. main.rs boot_partition: "the one function in this file that does not
[panic]", which was false.
3. main.rs load_kernel_elf: the restatement of toyos-elf's refusals; the
p_filesz <= p_memsz bound is stated where the copy is.
4. main.rs MAX_ESP_FILE: the file-wide philosophy; its one-line doc stays.
5. attempt.rs: the 29-line module essay; "one hand per hang" stays.
6. blackbox.rs harvest: the war story; "a record belongs to the stick that
wrote it" stays.
7. loaderlog.rs ENDS_AT_CHAIN: the philosophy; its one-line doc stays.
8. main.rs start_kernel: two of three unrelated comments over `let loader`
(the println-after-exit fact is stated at the exit); the one about the
loader image stays.
9. main.rs: end_this_pass's second paragraph, and main's copy of the same
explanation over uefi_services::init.
10. Duplicates, one copy kept in toyos_update::policy's header: "firmware
variables can be reset" (toyos-update lib.rs, bootloader floor.rs) and
"the record names only a slot and a digest" (toyos-update record.rs,
bootloader slot.rs's proven).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
Review, round 1, at 6d42256Gate: CI BLOCKER
NOTE
REMOVE
SEND BACK |
… rebuilt on the owner's rulings CLAUDE.md: ToyOS calls no UEFI runtime service; every UEFI call is the loader's. PSCI on ARM64 and the xHCI legacy-ownership handshake are not UEFI calls, which closes both CLAUDE.md blockers. The track: - Stage 1 is what #583 lands: UTC, the hex dump, ten comments, the KernelArgs layout identity, IA32_TSC_ADJUST read by the kernel. The loader's TCO arm stays; wall_clock_utc is the test a zone reds. - Stage 2 scopes every volume lookup to the boot disk with exactly one match, and asks firmware once per pass. - Stage 3 compares one floor per key on a signed security version; the accepted cost of refusing older builds is gone with the build time. - Stage 4 is new: current uefi, the loader's own panic handler, the unsound allocations and relocation unsafes gone, typed KernelArgs, one CRC32. - Stage 5 adopts the Android/libabr tries rules as pure host-tested toyos-update decisions: fresh slot A untried with 3 tries, no bootable slot powers off, the good flag set only past a health gate, and controls for a good flag left set and a floor raised to the table's version. - Stage 8 is new: the kernel arms the TCO before mm::init and takes the read-back the TCO issue's exit needs; only then does the loader's arm go. - Stage 9 rewrites the wedged-report issue's exit and gives the kernel harvest's stale-record check. - Every #539 piece is placed or listed as deleted. the-machine-updates-itself-without-ubuntu.md: stage 2 gets its exit back, and names its wait on the track's --boot-first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
… Walk::bytes go The RTC is UTC, so the offset logd recovered from SYS_CLOCK_EPOCH and SYS_CLOCK_REALTIME could only be zero. Deleted instead of filed: - userland/logd/src/wall.rs, and toyos_wallclock's resolve, Recovery, MAX_EAST_SECS/MAX_WEST_SECS and their six tests. boot_stamp reads clock_epoch once; the startup line says "<civil> UTC". boot_local is boot_secs, since nothing in it is local. - The false zone clauses in toyos-abi's and toyos's clock_realtime docs and toyos-wallclock's header. - toyos_acpi::Walk: with its bytes field gone (its only reader was the loader's hex dump) it wrapped one Result, so memory_windows returns Result<usize, ResourceError>. The six byte asserts go, and so does the_bytes_a_walk_reports_cover_the_descriptor_it_refused, which tested nothing else. - The two issue files the last round filed for these. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
…ck_utc judges SYS_CLOCK_REALTIME with a firmware zone staged Boot ABI. `update` replaces the slot's kernel and leaves the ESP loader, so an old loader can hand a new kernel the old layout. KernelArgs gains `layout: u32` at offset 164, the padding hole the removed zone fields left, so no field moves. The loader writes `LAYOUT` (0x5459_0001); the kernel compares it right after arming the panel, before `blackbox::arm` reads the boot parameter, and on a mismatch starts the UART from `rsdp_addr` (below the word) and panics naming both values. An origin/main loader writes the firmware zone in minutes there (0 on OVMF), which `LAYOUT` can never equal: a const assert keeps it outside -1440..=1440. The actuator `loader-writes-no-layout` makes the loader write 0, and the Nightly test kernel_args_layout_refused boots it and asserts the refusal and that no `black box:` record, the first read of a field after the word, came before it. IA32_TSC_ADJUST is read by the kernel beside report_power_on (`arch::boot::report_counter_origin`, a `boot: IA32_TSC_ADJUST` record) and no longer by the loader. On aarch64 the loader's counter_origin goes and the kernel's hook is empty. wall_clock_utc stages a zone the way firmware names one: a fresh variable store with PcRtc's `RTC` variable (vendor 378D7B65-...-A47826A833E1, UINT32 zone, per edk2 PcRtc.c at QEMU 11.1.1's edk2 4dfdca63) holding -120 minutes. It then judges the log name's hhmmss and the probe's `realtime=` (was `local=`) against the staged instant within MAX_BOOT_DRIFT_SECS, beside the FAT stamp and SYS_CLOCK_EPOCH. The variable-store reader and planter move from update.rs to tests/common/fwvars.rs and take the vendor. Deleted: the rewritten century comment in x86_64/boot.rs, the probe's "both" paragraph, rtc_is_utc's doc and the "two clock syscalls" comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W6rME2DoqwjcYFStYHHY4j
…s controls can fail CLAUDE.md's Firmware paragraph now reads as the orchestrator ruled: the kernel calls no UEFI service, and every UEFI call is the loader's, before ExitBootServices. The loader's GetVariable, SetVariable, GetTime and ResetSystem come before the handover, so the old wording was false of it. The track: - Stage 1 matches #583 at 8565cc5: KernelArgs::layout (0x5459_0001), kernel_args_layout_refused with the loader-writes-no-layout actuator, the probe's realtime=, and the kernel's IA32_TSC_ADJUST line. No test fails without that line, and the stage says so. - Stage 3 drops "why nothing is weaker". A security version admits an older build the same key signed at that version. The floor issue records that as the owner's accepted cost. Raising the version is a reviewed PR that edits one constant and names the security fix. The loader deletes the build-time ToyOSImageFloor- variables instead of leaving them behind. - Stage 4's panic handler writes loader.log and powers off, never resets. Its test panics on a floor planted in 9 bytes, a failure the machine causes. KernelArgs' layout word rises to 0x5459_0002, and kernel_args_last_layout_refused fails if it does not. - Stage 5 refuses a signed kernel the loader cannot load inside verify, so the other slot boots instead of the pass bricking the machine. An install's priority rises above the kept slot's. update --good, run by init at the health gate under the slots claim, writes the good flag, and an image without that claim is never good. Each rule gets a named guest control: update_floor_waits_for_good, update_readonly_stick_boots_nothing (red under `let persisted = true;`) and update_unloadable_kernel_boots_the_other_slot. The slot-table oracle is decoded without production code. - Every #539 piece the review listed is placed or deleted. The #539-only issue names and the stack-offset closure (#584's) are gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review, round 2, at 8565cc5Gate: CI Round 1
BLOCKER
NOTE
REMOVE
SEND BACK |
…not a copy The inline predicate in kernel_main's reservation loop duplicated toyos_rootimage::handoff::held without its checked_add, and no test covered the copy. Both crates were already kernel dependencies, so the loop now builds a Descriptor iterator and calls held(..., block=1) — block 1 because the ELF region is not page-aligned — the same call kernel/src/rootfs.rs already makes for ROOT's image. The architecture's own page is now named (a `loader` array of the four loader allocations, checked, with arch::boot::reserved() appended after) so a later region can't land inside the exempted slot by position. Files the misleading kernel_stack_addr name (toyos-abi/src/boot.rs:8) as an issue for after #583, and removes the tracker entry this branch's exit condition already closes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ames its refusal, and the stale prose the review named goes LAYOUT folds size_of::<KernelArgs>() into the fixed word instead of a hand-bumped constant, so any field added or removed moves it without relying on someone remembering to bump it by hand. fat32_adapter.rs's now() records why FAT gets UTC stamps despite FAT naming local time: the owner ruled the hardware clock is UTC. SYS_CLOCK_REALTIME is now a plain format of SYS_CLOCK_EPOCH; filed as issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md for the ABI discussion its retirement needs, not retired here. Deleted, not rewritten: userland/CLAUDE.md's stale zone-recovery caveat, where-everything-lives.md's zone-recovery clauses, toyos-wallclock's chronology, tests/toyos.rs's rewritten LOADER_TSC doc, and main.rs's rewritten report_power_on clause tying to the moved, untested IA32_TSC_ADJUST read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d-picked Restates the track's LAYOUT/LAST_LAYOUT literals as `0x5459_0000 | size_of::<KernelArgs>()`, so a size change moves the word on its own and `kernel_args_last_layout_refused` catches it; names the remaining gap a same-size reorder or equal-size type swap leaves, closed by pinning every field's offset (not only the prefix's) and `assert!(LAYOUT != LAST_LAYOUT)`; states how stage 5's once variant, which keeps the struct's size, still moves the word and how the kernel refuses an unrecognized discriminant by name instead of reading it out of range; gives `update_dead_service_is_never_good`'s image a live service beside the dead one, so "any named service wrote its byte" is distinguished from "every one did"; has stage 5's PR list which `start_kernel` refusals are the image's; and drops the PR body's Unsure bullet on #583's pushed head, now stale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review, round 3, at 4e07c4dGate: CI Round 2
BLOCKER
NOTE
REMOVE
SEND BACK |
… exactly, SYS_CLOCK_REALTIME's issue reopens as a defect naming every caller, and two false layout-doc clauses go kernel_args_layout_refused matched only the refusal's prefix, so a kernel that printed its own kernel_args.layout in place of toyos_abi::boot::LAYOUT would still pass; it now asserts the full message with LAYOUT's own hex digits. LAYOUT_ZERO_PARAM reads WRITE_NO_LAYOUT_PARAM instead of copying its literal. The SYS_CLOCK_REALTIME issue was status: owner / kind: question, which drops it out of `rg -l '^status: open'` and named no owner; it is a defect nobody is holding, so it is status: open / kind: defect, with the Owner line gone and an exit condition that names toyos::system::clock_realtime and both its callers. toyos-abi/src/boot.rs loses two false doc clauses: LAYOUT's own size folded in does not move on a field added into padding, as `layout` itself was; and two binaries sharing this file does not mean they cannot disagree about the layout, which is why `layout` exists at all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`reserved`'s construction copied `loader` by position, so a fifth region
added to `loader` compiled and passed the containment check but was silently
dropped from what `mm::init` withholds — exactly what mutation-r2.patch had
done to `root_image`. Destructuring `loader` by name (`image`, `elf`,
`black_box`, `root`) makes a fifth element a compile error instead.
The issue's owner line named a role ("whoever lands #583"), not a concrete
owner; it now names PR #583 (wt/toyos-loader1) itself, and drops the line
number citation that rots with the next edit to toyos-abi/src/boot.rs. The
same rotting citation is dropped from main.rs's comment on the
architecture's own reserved page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review, round 4, at 9efc01cCI has no run at 9efc01c: NOT READY FOR REVIEW |
Both sides touched tests/common/wallclock.rs's clock-drift checks and tests/test-durations; every hunk of both survives. tests/common/wallclock.rs: main's #562 ("No QEMU test measures time") replaced the fixed MAX_BOOT_DRIFT_SECS budget with after_the_base(secs, lived), a causality bound measured from the actual elapsed wall time since QEMU's launch. This branch's own commit 1090cf6 ("The RTC keeps UTC") ruled the hardware clock is always UTC and replaced main's zone_from_firmware test (and its rtc-zone-east actuator) with rtc_is_utc, which plants a firmware RTC timezone variable directly via fwvars::plant and asserts the kernel ignores it — FAT name, FAT stamp, SYS_CLOCK_EPOCH and SYS_CLOCK_REALTIME all sit on the staged instant with no offset applied. Kept this branch's rtc_is_utc body (the ABI decision it tests is this branch's own and main never saw it) but put every one of its drift checks on main's after_the_base/lived measurement instead of the deleted MAX_BOOT_DRIFT_SECS, so the branch's checks fit main's "no QEMU test measures time" rule. boot_and_read keeps both signature changes: this branch's firmware_vars: Option<PathBuf> parameter and main's returned Duration (elapsed since launch). undated, no_century and century_from_the_register keep this branch's extra None argument and main's three-way destructure. tests/test-durations: kept watchdog_fed (this branch's own addition, whose test still exists at the merged head). Dropped wall_clock_zone: its test, zone_from_firmware, was deleted by 1090cf6 and replaced by wall_clock_utc, so the entry names a test that no longer exists. Verified on the merged tree: `cargo run -- --ci host` exit 0, `cargo run -- --build-only` exit 0, `cargo test --test toyos-build -- --list` exit 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review, round 5, at 87a9457Gate: Round 3
Merge 87a9457tests/common/wallclock.rs keeps both sides: main's BLOCKERNone. NOTE
REMOVE
LAND AFTER NAMED CHANGES |
Main's #562 deleted this row when it moved watchdog_fed to metal-only; the merge into this branch resurrected it by mistake. Nothing else in the file changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main's #583 made the RTC UTC: `clock` keeps one anchor, BOOT_SECS, and the firmware zone, UTC_OFFSET_SECS and local_secs are gone. The mtime now comes from that same anchor. - kernel/src/clock.rs: main's `init_wall(century_reg)`, BOOT_SECS and its "reads {civil} UTC" line are kept. This branch's utc_nanos is BOOT_SECS * 10^9 plus nanos_since_boot, and utc_secs stays its whole seconds, which is the value main's utc_secs computed. mtime_now stays utc_nanos, or 0 (undated) when the RTC never answered. local_secs_of and mtime_of_local are deleted because no zone is left to convert through. NANOS_PER_SEC becomes pub for the FAT adapter. - kernel/src/fat32_adapter.rs: this branch's `stamp(mtime)` and `now() = stamp(mtime_now())` are kept, now as whole UTC seconds of the mtime. main's refusal-reason moves onto `stamp`: FAT specifies local time, and this stamps UTC because the owner ruled the hardware clock is UTC. `file_mtime` answers modified_unix * 10^9. An undated 0 clamps to FatTime::EPOCH, which is what main's now() gave with no RTC. - tests/toyos.rs: main's wall_clock_utc row, CARRIES entry and dispatch arm replace wall_clock_zone, which main deleted. This branch's file_mtime_survives_a_reboot and file_mtime_undated are kept beside them. - rust: main's pin 9c3eea441d8 (#597) is merged into the fork's wt-toyos-mtime as 90697f1401a, with no conflicts. - issues/filesystem/a-fat-files-mtime-reads-finer-...: "two seconds of local time" is no longer true, so it now reads "two-second units". issues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md is unchanged. Both handlers still read clock::utc_secs, and its value did not change. This branch adds no caller of clock_realtime. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One conflict, kernel/src/arch/aarch64/boot.rs, both hunks kept: main's (#583) new `report_counter_origin`, empty on AArch64 because no register says where the generic timer counts from, which main.rs's `report_power_on` calls on both architectures; and this branch's `timer()`, its doc and its body (the EL1 virtual timer, logged, stopped until the scheduler arms it) in place of main's `owed!` stub. #583's KernelArgs layout word needs nothing on the AArch64 side: the loader writes it in the portable bootloader/src/main.rs, the kernel refuses a foreign one in the portable `kernel_main`, which AArch64's `_start` reaches, and that `_start` reads its four fields by `offset_of!`, so the layout moves under it by construction. Auto-merged, each checked against the branch's own hunk: actuator.rs (main's layout actuator beside this branch's irq-storm and timer-floor), main.rs (main's layout refusal and power-on report beside this branch's `mod hw` and headless GOP), x86_64/boot.rs (main's UTC `clock` and `report_counter_origin` beside this branch's irq-storm/timer-floor refusal), aarch64/mod.rs (#586 drops log-shared-reservation's window from `percpu_fetch_add`; this branch's percpu.rs still calls `log::nested::reserve_window`, which main keeps), clock.rs, sched/kthread.rs, src/build.rs, src/sourcegate.rs, tests/toyos.rs. kernel/src/hw.rs is this branch's alone: main touched neither it nor either architecture's hw.rs. The rust gitlink takes main's 9c3eea44. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings #583, #586, #593, #597, #555, #600, #610 and #611. Every conflicted hunk, and where it went: - rust: 1471893e39c, which merges main's pin 9c3eea441d8 into this branch's 62fa74d7a50 with no conflict (main's three bootstrap commits and this branch's six std files do not meet). Pushed to ToyOSOrg/rust wt-toyos-fsd. - kernel/src/actuator.rs: #583 deletes `rtc-zone-east`, and that deletion stands. This branch's doc for `leak-rollback-selftest` stands, since the FAT reopen control went with the kernel's FAT adapter. - kernel/src/fat32_adapter.rs (modify/delete): the deletion stands. #583's hunk made FAT stamp UTC (`clock::utc_secs`) with the refusal reason at the site. FAT stamping is fsd's on this branch, so it is carried there: `local_secs`, which recovered a zone through `toyos_wallclock::resolve` (deleted by #583) and cited logd's `wall.rs` (deleted by #583), becomes `utc_secs`, `clock_epoch()` alone, with main's reason. fsd no longer depends on toyos-wallclock; userland/Cargo.lock drops the edge. - kernel/src/sched/kthread.rs: #586 deleted `lognest` and `log-storm`, and this branch deleted `iod`, so klogd is the one kernel thread in every build: MAX_KERNEL_TASKS = 1, with no feature split. - issues/kernel/the-kernel-still-creates-threads.md: #586 met K3 and deleted it; this branch meets K5 and deletes it. K6 is blocked on K2 and K4. - userland/logd/src/main.rs: #583's `boot_secs` rename, beside this branch's `Published::new()`, which takes no argument here. The `owed` and `retrying_since` fields stay deleted (this branch). - userland/logd/src/serve.rs: this branch's `serving` flag, with #583's `boot_secs`. - tests/test-durations: #586 deleted `log_conservation_smp1` and this branch deleted `log_backing_read_error`; neither row stays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6SVYFkdvV2t38KzNrESxs
The review's blocker: no AArch64 test could fail on `leaf()`'s Write check. `test_rs_abuse_readonly_copyout` issued its calls with the x86 `syscall` instruction; it now goes through `toyos_abi::syscall`'s typed wrappers, with the target named by a slice over the read-only address (as `tls_dtv_race` does), so it builds for both architectures and its row in the source gate's assembly exemptions goes. - The typed-value arm was `fstat`, whose wrapper returns its `Stat` rather than taking an address. It is now `process_stats` of a child the test spawns first: the same `copy_out` path, reachable through a wrapper that takes the caller's `&mut`. - Every arm runs; the exit status carries one bit per arm that let a write through (1 read-only mmap, 2 own text, 4 straddle, 8 clock page), which the kernel's own exit record prints even once a rewritten clock page has taken logd down. The straddle arm's search for the first unwritable page reports rather than panics when no page refuses, so a kernel that grants every write still reaches the clock arm. - `tests/virtjobcase` runs it as its last job; `virt_job` builds that one binary for AArch64 (`build::build_toyos_bin`, the crate's other binaries do not all build there) and puts it on ROOT for every boot of the case. `virt_readonly_copyout` judges it. The x86 shared run stays and is declared in DRIVEN_AND_SHARED. Also: the device-memory issue now names `user_ptr`'s direct-map copies and `dump_crash_diagnostics` beside `read_user_word`; the arm64 track drops the KernelArgs clause #583 made false; the assembly issue drops its probe count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U6SVYFkdvV2t38KzNrESxs
Stage 1 of the loader slimming: the audit rows that depend on nothing else. Rows 15, 5 and 17 landed, plus the ten comments, and
KernelArgsgained the layout word row 15's move made necessary. Row 13 is left out, for the reason below.Lines against
origin/main(git diff --numstat, matchingtests/anywhere in the path,.mdandissues/as docs, everything else as production): production +149 −718 in 27 files; tests +238 −212 in 10 files, of which the variable-store module's move out oftests/common/update.rsis about 115 each way; issues and docs +22 −5 in 3 files, of which one isissues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md, filed by this branch.Row 15: the RTC keeps UTC
This follows the owner's ruling that the hardware clock is always UTC.
GetTimeforEFI_TIME::TimeZone(rtc_utc_offsetand its call site are gone).toyos-abi/src/boot.rs):KernelArgslosesrtc_utc_offset_minutes,rtc_utc_offset_knownand thertc_utc_offset()getter. Every field fromcmdline_addron moves 8 bytes down, and the size goes from 1280 to 1272. The three hand-coded_startreads (16/32/40) and aarch64'soffset_of!reads sit in front of the removed fields, so they do not move.UTC_OFFSET_SECS,local_secsand thertc-zone-eastactuator are gone. FAT stamps,SYS_CLOCK_REALTIMEandSYS_CLOCK_EPOCHall readclock::utc_secs. Theboot: rtc utc offsetrecord is nowboot: cmdline ….fat32_adapter.rs'snow()names the refusal: FAT specifies local time, and this stamps UTC because the owner ruled the hardware clock is UTC.SYS_CLOCK_EPOCHalone.userland/logd/src/wall.rsis deleted, and so aretoyos_wallclock::resolve,Recovery,MAX_EAST_SECS/MAX_WEST_SECSand their six tests. The startup line says(<civil> UTC).wall_clock_zonetested the deleted feature and is deleted.wall_clock_utc(Weekly) stages the host's-rtc base=instant and a zone the way firmware names one, then judges the log file's name (date andhhmmss), its FAT stamp,SYS_CLOCK_EPOCHandSYS_CLOCK_REALTIME(the probe'srealtime=, formerlylocal=).PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c, at the edk2 commit QEMU 11.1.1 pins (4dfdca63), reads theRTCvariable under the driver'sFILE_GUID378D7B65-8DA9-4773-B6E4-A47826A833E1inPcRtcInit. The value is aUINT32holding(Daylight << 16) | (UINT16)TimeZone, whichGetTimethen returns.OvmfPkgX64.fdfincludes that driver. The staged value is −120 (UTC+2).tests/common/fwvars.rs, moved out oftests/common/update.rsand given a vendor parameter.SYS_CLOCK_REALTIMEis now a plain format ofSYS_CLOCK_EPOCH(both readclock::utc_secs), and retiring it is an ABI discussion this PR does not open: filed asissues/kernel/sys-clock-realtime-is-now-a-format-of-sys-clock-epoch.md(kind: defect,status: open; its exit condition names both callers,userland/compositor/src/render.rsandtests/toyos-rust-tests/src/bin/wall_clock_now.rs, andtoyos::system::clock_realtimeitself).Boot ABI:
KernelArgsnames its layout, and the kernel refuses anotherupdaterewrites only the slot (kernel, cmdline, ROOT) and leaves the ESP loader. So a loader built toorigin/main's layout can hand this kernel 1280 bytes whosecmdline_addrsits where this kernel readsrtc_utc_offset_known.KernelArgs::layout: u32at offset 164, the padding hole the removed fields left. No field moves and the size stays 1272.LAYOUT = 0x5459_0000 | size_of::<KernelArgs>() as u32— the struct's own size folded in. At today's 1272-byte size that is0x5459_04f8. Anorigin/mainloader writes the firmware zone in minutes there, 0 on OVMF. A const assert keepsLAYOUToutside −1440..=1440 as ani32, so no such loader can write it, and0x5459_04f8is neither 0 nor in that range. Deriving it from the size catches a change to the size; it does not catch a reorder at equal size, a type swap, or a field added into padding (aslayoutitself was) — the track's stage 4 (LAST_LAYOUT, typedKernelArgs) is what closes that.kernel_maincompares the word right after arming the panel. That is beforeblackbox::armreads the boot parameter, the first field after the word. On a mismatch it starts the UART fromrsdp_addr, which sits below the word, and panics withboot: the loader wrote KernelArgs layout {found:#x} and this kernel reads layout {LAYOUT:#x}. The same code covers both architectures: one loader writes the struct, andkernel_mainis shared.loader-writes-no-layout(toyos_abi::boot::WRITE_NO_LAYOUT_PARAM) makes the loader write 0. The kernel panics by name if it is armed and the check passed anyway.kernel_args_layout_refused(Nightly) boots with it, and now asserts the refusal's exact text includingtoyos_abi::boot::LAYOUT's own hex digits, not merely the message's fixed prefix — a kernel that printed its ownkernel_args.layouta second time instead ofLAYOUTwould still match the prefix (both are0x0on this control) and is now caught. It also asserts that noblack box:record appeared, since that record is the kernel's first read of a moved field.Row 5: the root-bridge hex dump
The per-bridge hex dump in
bootloader/src/rootbridge.rsis deleted. Refusals and the "no memory window" line are still printed.With the dump gone,
toyos_acpi::Walk::byteshad no reader. The field, its seven assignments and its six test asserts are deleted.Walkthen wrapped a singleResult, somemory_windowsreturnsResult<usize, ResourceError>.the_bytes_a_walk_reports_cover_the_descriptor_it_refused, which tested only the byte count, is deleted.Row 17:
IA32_TSC_ADJUSTis read by the kernelThe kernel now reads the MSR beside
report_power_on, inarch::boot::report_counter_origin, and logs it asboot: IA32_TSC_ADJUST <n>(or… not on this CPU). The loader'sLoader TSC:line carries its two counts only.On aarch64 the loader's
counter_originis deleted, since the kernel already readsCNTFRQ_EL0. The kernel's aarch64 hook is empty.No test judges the moved line.
boot_from_power_ononly prints it in its summary.The ten worst comments (+4 −106)
Each was deleted, not rewritten. Where one held a real invariant, only that clause stays. Commit
6d422562lists all ten. For the two duplicates, the copy kept is intoyos_update::policy's header.Row 13: not done
Deferred; the record is
#582, item 8.Each control patch below was applied as a checked patch (
git apply/manual edit, thengit diffEXIT=0), built (cargo run -- --build-onlyEXIT=0), and reverted in the same script, leavinggit status --porcelainempty for tracked files.Guest runs (the orchestrator's, at
87a94578)kernel_args_layout_refusedkernel-prints-args-word.patchwall_clock_utcwall_clock_rtc_deadwall_clock_rtc_unstablewall_clock_no_centurywall_clock_century_registerrealtime-plus-7200.patchFastThe only change since these runs is the deleted
watchdog_fedline intests/test-durations(main's #562 removed it; the merge brought it back by mistake).Under
layout-check-removed.patch,kernel_args_layout_refusedwas EXIT=1 with "Boot timed out waiting for boot: the loader wrote KernelArgs layout 0x0 and this kernel reads layout 0x" on the console. The kept UART showed "Kernel arguments: layout 0 on loader-writes-no-layout", then "black box: 0x8000000 is this boot's", then "panicked at src/main.rs:284:9: boot: loader-writes-no-layout is armed and the loader wrote this kernel's layout anyway" — the kernel's own check, not the black-box tripwire, is what turns the test red.High-risk: the boot ABI and the wall clock
The wall clock
utc-whole-revert.patchisgit diff HEAD origin/mainover everything outsidetests/andissues/. It reverts the branch's whole production change ontoorigin/main(bc9ccad8) and keeps this head's tests. On that tree the loader reads the staged −120, soSYS_CLOCK_EPOCHlands 7200 s behind the instant. Measured: EXIT=1,SYS_CLOCK_EPOCHanswered 1993792480, −7185s from the staged instant — the whole revert goes red, and the staged firmware zone does reachGetTime.wall_clock_utcis green at this head.realtime-plus-7200.patch(SYS_CLOCK_REALTIME => crate::clock::utc_secs().map(|s| s + 7200).map_or(). Measured: EXIT=1,SYS_CLOCK_REALTIMEanswered a time of day 7202s from the staged instant's.-rtc base=2033-03-07T09:14:25, and the zone as edk2's own RTC driver reads it from its variable store — the CMOS RTC's documented UTC convention, as the owner decided it. Both are set outside the guest and read back off the disk image and the guest's prints.The layout word
layout-check-removed.patchdeletes onlykernel_main's comparison block (kernel/src/main.rs, the two comment lines and theif kernel_args.layout != toyos_abi::boot::LAYOUT { .. panic!(..) }), keeping the word,LAYOUT, the loader's write, theloader-writes-no-layoutactuator and the tripwire that panics if that actuator armed and the check passed anyway. Measured at4e07c4df(above): the boot times out, refused by name.kernel_args.layouta second time in place oftoyos_abi::boot::LAYOUTstill read "…reads layout 0x0" on this control and passed.scratchpad/loader1-r4/kernel-prints-args-word.patchmakes that swap inkernel/src/main.rs; applied, built (cargo run -- --build-onlyEXIT=0), and reverted, leaving the tree clean.kernel_args_layout_refusednow asserts the message's exact hex digits and must turn red under it.LAYOUTshould be: no external spec, no real hardware, no differential implementation.old-layout-loader.patch, which hands the kernelorigin/main's 1280-byte layout as pinned byorigin/main's own offset asserts (164, 168, and 176 on), reads the same0at offset 164 that the plainloader-writes-no-layoutcontrol does, so it is not independent evidence of the check either — only of the fact that a genuinely stale loader is refused by name. Measured: EXIT=0, refusal naming0x0.Unsure
origin/main.🤖 Generated with Claude Code