Skip to content

ToyOS's own SHA-256 and SHA-512, as fast as sha2's soft backend, replace the sha2 crate in the loader's and update's image verification, swap, pkg and the build - #812

Merged
Japabu merged 8 commits into
mainfrom
wt/toyos-sha2
Oct 10, 2026

Conversation

@Japabu

@Japabu Japabu commented Oct 9, 2026 •

Copy link
Copy Markdown
Collaborator

The owner's ruling on the dependency audit, "Own SHA-2": every SHA-256 and SHA-512 that ToyOS's own code takes is now toyos-sha2, written here from FIPS 180-4. Head 24e6fb655, which merges main at 5a3b74345 (#810, #816, #817, #821, #823) over ae2aee73c, the merge of 9b691ddce (#808, #801, #807).

What changed, per decision

  • toyos-sha2 is a new member: no_std, forbid(unsafe_code), 255 lines. It implements SHA-256 and SHA-512 per FIPS 180-4 §4.2, §5.1, §5.3, §6.2 and §6.4.
    • SHA-512 is in because toyos-update::sig builds the SSHSIG message over SHA-512(header).
    • It hashes whole bytes only, because no caller has a partial byte.
    • One macro does the buffering and padding for both hashes, and one does the compression, over each hash's word, block, constants and rotations.
  • The compression is as fast as sha2's soft backend. Round 1 was 1.2x slower, and the T14 showed it: the loader's ROOT hash took 2.653 s against main's 2.209 s. Three changes close the gap; they are measured under Speed.
    • The schedule is a sixteen-word ring. Each pass overwrites W(t-16) with W(t), instead of filling a 64- or 80-word array.
    • Rounds and schedule words are written out sixteen to a pass through const generics. Every index into the working variables and the schedule is then a constant; LLVM had kept round 1's rounds as a loop over memory.
    • One call compresses every whole block of an update, with the hash value held in locals between blocks.
    • Maj is written as b ^ ((a ^ b) & (b ^ c)), whose b ^ c is the previous round's a ^ b.
  • Scalar on every target, with no SHA-NI. An instruction path needs unsafe and core::arch, and this crate forbids unsafe. The loader is also a soft-float UEFI application that may not assume the SIMD/SHA registers are its own, which is why it already forced sha2 soft. The x86-64 callers that used SHA-NI/AVX2 are bounded under Speed and recorded in issues/x86-64-hashing-runs-scalar-where-the-cpu-has-sha-instructions.md (status: owner).
  • API: a drop-in for the Digest calls the tree makes, as inherent methods: new(), update(impl AsRef<[u8]>), finalize() -> [u8; N], digest(impl AsRef<[u8]>) -> [u8; N] and Default. Each caller drops its use sha2::Digest and its .into().
  • Callers moved:
  • ed25519-dalek keeps sha2.
    • ed25519-dalek 2.2.0 depends on sha2 0.10.9 without making it optional, and its src/verifying.rs takes sha2::Sha512 for H(R‖A‖M) inside verify_strict. So sha2 0.10.9 stays in Cargo.lock.
    • The loader keeps its sha2 … features = ["force-soft"] line, with a comment saying it exists only for that.
    • sha2 0.11.0-rc.5 belongs to russh and is untouched.
    • No ToyOS source names sha2 any more, except toyos-sha2's dev-dependency.
  • NIST's byte-oriented CAVP vectors live in tests/cavp/, outside every shipped package's directory. They are ShortMsg, LongMsg and Monte for both hashes, byte for byte as upstream, CRLF included.
    • NOTICE's section tests/cavp/ gives each file's hash and size, the upstream archive's hash, and NIST-PD.
    • The licence gate reports the section as "is not shipped", so src/licence.rs is identical to main (git diff origin/main -- src/licence.rs is empty). This follows the orchestrator's ruling that this branch does not widen the licence list.
    • The bit-oriented files are gone, with padded, bit_file and their tests. They drove the compression function under the test's own padding, which the byte files already drive. The bit Monte files differ from the byte ones only by their seed.
  • issues/the-build-runs-host-tools-outside-rust-and-qemu.md's shasum row now names toyos-sha2 as what src/release.rs hashes with.

Checks of high-risk code (the signed-image trust boundary)

  • Independent oracle 1, NIST CAVP SHAVS (toyos-sha2/src/tests.rs).
    • Every ShortMsg and LongMsg vector is checked whole, and again streamed one byte at a time.
    • Every Monte Carlo checkpoint (SHAVS §6.4) is checked.
    • Each section's [L = n] header is held against its digests' length.
  • Independent oracle 2, a differential against RustCrypto sha2 0.10.9. It is a dev-dependency only and shares no code with this crate.
    • It covers every length 0..=4096 bytes of random bytes, not a sample.
    • Each length is hashed whole, then again in 3 random splits of up to 8 cuts, empty pieces included.
    • The splits come from a seeded SplitMix64, so a red is reproducible.
  • Negative controls: six mutations of the compression red the tests. Each patch was applied checked and reverted in one script at c8aad54, with the tree left clean afterwards. Every build exited 0 and every test run exited 101. The patches, the script and the reds are in the PR comment.
    • K256[0] wrong: the SHA-256 vectors, Monte and differential red, and SHA-512 stays green.
    • K512[79] wrong (the last round): the SHA-512 vectors, Monte and differential red, and SHA-256 stays green.
    • The schedule's W(t-7) tap moved by one: all five tests red.
    • Maj's b ^ c changed to a ^ c: all five red.
    • The working variables' rotation changed to I % 4: all five red.
    • Each block started from the call's initial hash value instead of the running one: the byte vectors and the differential red, through the whole-message digests that pass many blocks in one call. Monte stays green, because its messages are at most three digests long.
  • toyos-update's existing RFC 8032 and sshsig_oracle tests (OpenSSH's ssh-keygen -Y output) pass through the new SHA-512.

Speed

  • Host CPU time at 56 MiB (the default image's ROOT size). The host is an Apple M4 Pro; the build is opt-level 2 with [profile.toyos]'s debug assertions and overflow checks; each figure is the best of 21 runs' thread CPU time. The source and the log are in the PR comment.
    • SHA-256: toyos-sha2 took 99.8–102.1 ms against sha2 force-soft's 103.3–105.3 ms, a ratio of 0.97–0.98.
    • SHA-512: 62.4–63.4 ms against 67.0–68.2 ms, a ratio of 0.92–0.93.
    • sha2 default gives the same numbers on this host, because its aarch64 hardware backend needs the asm feature.
    • Round 1's head (db2e1f3), in the same session: SHA-256 took 124.95 ms and SHA-512 80.03 ms, against this head's 99.10 ms and 61.63 ms.
  • x86-64, on the T14 (comment 6086424539): the loader at this head hashed the testcases ROOT (320,864,256 bytes) in 4,757,794,201 ticks at 2,419,200,000 Hz (1.967 s, 14.83 ticks/byte) against main's 5,343,577,520 (2.209 s, 16.65 ticks/byte): 0.89x. That loader was built by the compiler before The fork's LLVM gives a loop counter's recurrence only the wrap flags proven for it, a sysroot whose compilers lose a loop's last exit is refused, and the ScalarEvolution issue is closed #790 (merge base d6298c83e); the merge queue builds with main's compiler.
  • x86-64 codegen, read rather than timed. Built for x86_64-unknown-uefi with the same profile, this head's SHA-256 block executes about 3,300 instructions: 65 to load the block, 3 schedule passes of 341, and 4 round passes of 536 plus the loop's own. That is counted from the emitted listing. sha2 soft's fully unrolled block loop is 3,427 instructions. The T14 reading below is the timed verdict.
  • The x86-64 callers that lost SHA-NI/AVX2: bounded, not measured. These are update, pkg and swap on the T14, and the build's hashing on CI. The loss is at most their scalar hash time. The T14's loader on main measured that rate: 320,864,256 bytes in 5,343,577,520 ticks at 2,419,200,000 Hz, which is 2.21 s or 138.5 MiB/s.
    • So update loses at most 2.2 s of a 306 MiB testcases ROOT. The same loader read that ROOT off the stick in 9.31 s.
    • On the default image's 56 MiB ROOT, update loses at most 0.4 s.
    • The build's largest hash is cicache's 47,906,184 tracked bytes, at most 0.33 s at that rate.
    • SHA-NI is not added here. For a 300 MB ROOT it would save at most about 2 s of an update that also downloads and writes those bytes. It would put unsafe intrinsics into the crate every signed image is verified with, and the loader could not take that path anyway. Whether that trade is wanted is the owner's call, recorded in the issue.

Gates (head 24e6fb6, the merge)

Logs, scrubbed of home-directory and temporary paths: comment 6095789229 (round 3's, at ae2aee73c: comment 6094616150).

  • cargo test -p toyos-sha2: EXIT=0, 5 tests.
  • cargo test -p toyos-update: EXIT=0. 42 unit tests, toyos-update verifies a signed package repository and src/publish.rs writes one through it; pkg install <name> waits on an atomic directory rename on DATA #808's repository attack tests among them, repo_oracle (a repository OpenSSH's ssh-keygen -Y sign signed, accepted, and a bent one refused) and sshsig_oracle. an_archive_past_its_length_or_not_its_hash_is_refused drives Archive's streamed toyos_sha2::Sha256.
  • cargo run -- --ci host: EXIT=0, "Host: 78 step(s), all green".
    It reports the licence gate's "6 exception(s) stand, and nothing else is refused" and "NOTICE section tests/cavp/ (NIST-PD) is not shipped".
  • cargo run -- --build-only: EXIT=0; cargo run -- --build-only --arch aarch64: EXIT=0.
  • The whole guest suite, cargo test --test toyos-build: EXIT=0, "45 passed, 45 total" over 48 guests, https_fetch among them (it drives the converted hash). uptime load averages were 46.48 / 47.42 / 50.24 before and 74.92 / 65.67 / 57.65 after.

T14: boot:testcases at b9132ebb7, run by the orchestrator: both image hashes matched request.txt, both toyos-metal --fat32-check exit 0; judge cargo test --test toyos-build -- --metal --metal-readback <dir> boot:testcases EXIT=0, [metal] 249 passed, 0 failed, 2 boot(s).

No new guest test: the hash is a pure function, and the host tiers above cover it completely.

Net lines over main: 2792 insertions and 42 deletions.

  • 2190 are NIST data.
  • 225 are tests.
  • 255 are toyos-sha2/src/lib.rs.
  • 65 are NOTICE and issues.
  • The rest, about 55, are caller and manifest changes.

Coordination with #808, done in the first merge

Coordination with #810, #816, #817, #821 and #823, done in the second merge

Unsure

🤖 Generated with Claude Code

https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C

Japabu and others added 3 commits October 9, 2026 17:58
…n the loader's and update's image verification, swap, pkg and the build

The owner's ruling on the dependency audit ("Own SHA-2"): the hash the
signed-image trust boundary rests on is ours. `toyos-sha2` is SHA-256 and
SHA-512 written from FIPS 180-4 (§4.2, §5.1, §5.3, §6.2, §6.4), no_std and
forbid(unsafe_code), scalar on every target. SHA-512 is in because
`toyos-update::sig` builds the SSHSIG message over SHA-512(header).

Its API is the subset of sha2's `Digest` calls the tree makes, as inherent
methods: `new`, `update(impl AsRef<[u8]>)`, `finalize() -> [u8; N]` and
`digest(impl AsRef<[u8]>) -> [u8; N]`. Every caller drops its
`use sha2::Digest` and its `.into()`; cicache's `{:x}` of a GenericArray
becomes `release::sha256_hex`.

Callers moved: toyos-update (`sha256`, and `sig`'s SHA-512), toyos-swap,
userland/update's streamed ROOT hash, userland/pkg, and the build's
cicache, sourcegate, sysroot, image and release.

`ed25519-dalek` 2.2 still hashes with `sha2` 0.10.9 inside a verification
(its `verifying.rs` takes `sha2::Sha512` for H(R || A || M)), so `sha2`
stays in the lock and the loader keeps its `force-soft` line, recommented
as being for that alone.

Oracles: NIST's CAVP SHAVS response files, committed under
toyos-sha2/cavp/ and recorded in NOTICE (byte-oriented ShortMsg, LongMsg
and Monte for both hashes, bit-oriented ShortMsg and Monte; the
bit-oriented LongMsg files, 16.8 MB, are not), and RustCrypto's sha2 as a
dev-dependency over every length 0..=4096 in random splits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…IST-PD

Clippy's chunks_exact_to_as_chunks and manual_is_multiple_of, under
`--ci host`'s -D warnings: a block's words and the whole blocks of an
update are `as_chunks`, which leaves no `expect` on a length the type
already fixes.

The licence gate judges every file under a shipped path package's
directory as shipped, so the CAVP vectors under toyos-sha2/cavp/ are judged
by their NOTICE line, NIST-PD: NIST's notice that a work of the US
government is public domain (17 U.S.C. §105), allowed beside CC0-1.0, the
other public-domain dedication the list carries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
… a pass

The rounds moved all eight working variables every round; the scalar hash
measured 1.47x the CPU time of sha2's force-soft backend over a 56 MiB
message on the host. Each round now writes only the two it changes (d and
h, §6.2.2 step 3), and the loop takes eight rounds a pass with the names
rotated, which is the same computation: 1.19x to 1.25x.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu

Japabu commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

Negative controls, applied with git apply --check then git apply, built, cargo test -p toyos-sha2 run, and reverted with git apply -R in one script at head db2e1f3 (tree clean after: git status --porcelain empty).

patch build test reds, by name
mutation-k256-first (K256[0] 0x428a2f98 -> 0x428a2f99) EXIT=0 EXIT=101 sha256_byte_vectors shabytetestvectors/SHA256ShortMsg.rsp: Len = 0; sha256_bit_vectors shabittestvectors/SHA256ShortMsg.rsp: Len = 0; sha256_monte_carlo shabytetestvectors/SHA256Monte.rsp: COUNT = 0; differential SHA-256 of 0 bytes. All three SHA-512 tests stay green.
mutation-k512-last (K512[79] ...817 -> ...816) EXIT=0 EXIT=101 sha512_byte_vectors shabytetestvectors/SHA512ShortMsg.rsp: Len = 0; sha512_bit_vectors shabittestvectors/SHA512ShortMsg.rsp: Len = 0; sha512_monte_carlo shabytetestvectors/SHA512Monte.rsp: COUNT = 0; differential SHA-512 of 0 bytes. All three SHA-256 tests stay green.

mutation-k256-first.patch

--- a/toyos-sha2/src/lib.rs
+++ b/toyos-sha2/src/lib.rs
@@ -24,7 +24,7 @@
 /// SHA-256's round constants, §4.2.2.
 #[rustfmt::skip]
 const K256: [u32; 64] = [
-    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+    0x428a2f99, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,

mutation-k512-last.patch

--- a/toyos-sha2/src/lib.rs
+++ b/toyos-sha2/src/lib.rs
@@ -62,7 +62,7 @@
     0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
     0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
     0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
-    0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
+    0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475816,
 ];
 
 /// SHA-512's initial hash value, §5.3.5.

The script:

#!/bin/sh
# Apply one checked mutation patch, run toyos-sha2's tests, report, restore.
set -u
tree=<path>
logs=<path>
for m in mutation-k256-first mutation-k512-last; do
  cd "$tree" || exit 9
  git apply --check "$logs/$m.patch" || { echo "$m: does not apply"; exit 9; }
  git apply "$logs/$m.patch"
  cargo build -p toyos-sha2 > "$logs/$m.build.log" 2>&1; echo "$m build EXIT=$?"
  cargo test -p toyos-sha2 > "$logs/$m.test.log" 2>&1; echo "$m test EXIT=$?"
  git apply -R "$logs/$m.patch"
  git status --porcelain
done

Host benchmark source (scratch crate, [profile.release] opt-level = 2; built twice, once with --features soft = sha2/force-soft; thread CPU time, best of 21):

[package]
name = "sha2bench"
version = "0.0.0"
edition = "2024"
publish = false

[features]
soft = ["sha2/force-soft"]

[dependencies]
toyos-sha2 = { path = "<worktree>/toyos-sha2" }
sha2 = "0.10"
libc = "0.2"

[profile.release]
opt-level = 2

[workspace]
use sha2::Digest as _;
fn cpu() -> f64 {
    let mut t = libc::timespec { tv_sec: 0, tv_nsec: 0 };
    assert_eq!(unsafe { libc::clock_gettime(libc::CLOCK_THREAD_CPUTIME_ID, &mut t) }, 0);
    t.tv_sec as f64 + t.tv_nsec as f64 * 1e-9
}

fn best<const N: usize>(f: impl Fn() -> [u8; N]) -> (f64, [u8; N]) {
    let mut best = f64::MAX;
    let mut out = [0; N];
    for _ in 0..21 {
        let t = cpu();
        out = std::hint::black_box(f());
        best = best.min(cpu() - t);
    }
    (best, out)
}

fn main() {
    let size: usize = std::env::args().nth(1).expect("bytes").parse().expect("a size");
    let data: Vec<u8> = (0..size).map(|i| (i as u32).wrapping_mul(2654435761) as u8).collect();
    let mib = size as f64 / (1 << 20) as f64;
    let (a, da) = best(|| toyos_sha2::Sha256::digest(&data));
    let (b, db) = best(|| sha2::Sha256::digest(&data).into());
    assert_eq!(da, db);
    let (c, dc) = best(|| toyos_sha2::Sha512::digest(&data));
    let (d, dd) = best(|| sha2::Sha512::digest(&data).into());
    assert_eq!(dc, dd);
    let soft = if cfg!(feature = "soft") { "sha2 force-soft" } else { "sha2 default" };
    println!("{size} bytes ({mib:.1} MiB), best of 21, thread CPU time");
    println!("SHA-256 toyos-sha2 {:8.2} ms {:7.1} MiB/s | {soft} {:8.2} ms {:7.1} MiB/s | ratio {:.2}", a * 1e3, mib / a, b * 1e3, mib / b, a / b);
    println!("SHA-512 toyos-sha2 {:8.2} ms {:7.1} MiB/s | {soft} {:8.2} ms {:7.1} MiB/s | ratio {:.2}", c * 1e3, mib / c, d * 1e3, mib / d, c / d);
}

Output at db2e1f3 (Apple M4 Pro, load average 40-48 during it):

18:49  up 10 days,  6:33, 6 users, load averages: 40.80 78.48 84.39
58720256 bytes (56.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2   130.21 ms   430.1 MiB/s | sha2 default   107.52 ms   520.9 MiB/s | ratio 1.21
SHA-512 toyos-sha2    83.35 ms   671.9 MiB/s | sha2 default    68.29 ms   820.0 MiB/s | ratio 1.22
58720256 bytes (56.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2   138.69 ms   403.8 MiB/s | sha2 force-soft   108.89 ms   514.3 MiB/s | ratio 1.27
SHA-512 toyos-sha2    86.41 ms   648.1 MiB/s | sha2 force-soft    73.37 ms   763.3 MiB/s | ratio 1.18
6291456 bytes (6.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2    13.58 ms   441.7 MiB/s | sha2 force-soft    11.26 ms   532.9 MiB/s | ratio 1.21
SHA-512 toyos-sha2     8.77 ms   684.0 MiB/s | sha2 force-soft     7.29 ms   823.5 MiB/s | ratio 1.20
58720256 bytes (56.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2   130.76 ms   428.2 MiB/s | sha2 default   108.11 ms   518.0 MiB/s | ratio 1.21
SHA-512 toyos-sha2    81.93 ms   683.5 MiB/s | sha2 default    68.22 ms   820.9 MiB/s | ratio 1.20
58720256 bytes (56.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2   128.53 ms   435.7 MiB/s | sha2 force-soft   105.30 ms   531.8 MiB/s | ratio 1.22
SHA-512 toyos-sha2    81.90 ms   683.7 MiB/s | sha2 force-soft    68.24 ms   820.7 MiB/s | ratio 1.20
6291456 bytes (6.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2    13.59 ms   441.4 MiB/s | sha2 force-soft    11.27 ms   532.3 MiB/s | ratio 1.21
SHA-512 toyos-sha2     8.77 ms   684.1 MiB/s | sha2 force-soft     7.30 ms   822.0 MiB/s | ratio 1.20
18:51  up 10 days,  6:35, 6 users, load averages: 48.20 69.18 79.98

@Japabu

Japabu commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #812 at head db2e1f337, against .claude/agents/reviewer.md. This is round 1.

Net lines (git diff --shortstat origin/main...db2e1f337): 32 files, +9649/−35.

  • Production: toyos-sha2/src/lib.rs +258, plus about 50 lines of callers and manifests. That replaces a dependency on the owner's "Own SHA-2", so the growth is accepted.
  • Tests: toyos-sha2/src/tests.rs +322.
  • Data: 8974 lines of NIST .rsp.
  • NOTICE: +44.

Correctness against FIPS 180-4, read by hand at this head:

  • K256, H256, K512 and H512 match §4.2.2, §4.2.3, §5.3.3 and §5.3.5.
  • Σ/σ rotations match §4.1.2 and §4.1.3 (256: 2/13/22, 6/11/25, 7/18/>>3, 17/19/>>10; 512: 28/34/39, 14/18/41, 1/8/>>7, 19/61/>>6).
  • Ch and Maj are in their standard equivalent forms.
  • The renamed-in-place round order is right for all eight rounds of a pass.
  • The pad length (B−L−1+B−filled)%B+1 gives 1..=B bytes and ends at B−L.

The oracles (CAVP byte ShortMsg, LongMsg and Monte, plus the sha2 0.10.9 differential over every length 0..=4096 in random splits) are independent of this code, and the K256[0] and K512[79] mutations red them by name (mutate.log: build EXIT=0, test EXIT=101 for both). I found no mutation of the padding or buffering that these tests would miss.

BLOCKER

  • src/licence.rs:67 — "NIST-PD" is added to ALLOWED. That is outside the brief, and the orchestrator has ruled that this branch does not widen the licence list.
    • Fix: move the vectors out of every shipped path package's directory, so that Shipping::ships (src/licence.rs:975, under(&self.packages, …)) does not count them. For example, put them in a test-data directory that no shipped package's manifest sits above, and have tests.rs read them from there.
    • In the same diff: move the NOTICE section heading (NOTICE:417, toyos-sha2/cavp/) to the new path and leave ALLOWED byte-identical to main.
    • Evidence owed: cargo run -- --ci host green at the new head, with the licence gate's line in the log and git diff origin/main -- src/licence.rs empty.
  • PR body "Speed" — the cost is measured only where neither arm had an instruction path. On aarch64, sha2 0.10.9 takes its hardware backend only under its asm feature (sha2-0.10.9/src/sha256.rs:19). That is why "default gives the same numbers as force-soft" on the M4.
    • On x86-64, every caller except the loader used sha2's x86 backend: SHA-NI, and AVX2 for SHA-512, through cpufeatures. Those callers are update's streamed ROOT hash and pkg/swap on the T14, and the build's cicache source hashing, image.rs root_uuid and sysroot on the x86-64 CI runners.
    • The "1.2x" therefore does not describe those paths, and the x86-64 regression there is unmeasured. The body's "Unsure" says the T14 cost is not measured.
    • Measure on an x86-64 host that has SHA-NI: the same benchmark, toyos-sha2 against sha2 default, at 56 MiB. Then either record the lost instruction path in issues/ with an owner, the numbers and an exit, or show it is immaterial against what those callers hash.
  • Evidence, metal — the change is on the loader's boot path, and the T14 reading is owed (metal-stage.log: EXIT=2, staged, the machine not touched).
    • Needed: the loader's verify line and its ROOT hashed in … counter ticks at this head.
    • Also needed, for comparison: the same line from main at d6298c8 on the same machine. The loader was already scalar there (force-soft), so this pair is the honest x86-64 reading of the loader's per-boot cost.
    • The two QEMU loader lines in the body ran at different host loads and are no verdict, as the body says.

NOTE

SEND BACK

@Japabu

Japabu commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

T14 at db2e1f337, run by the orchestrator: boot:testcases, two boots (testcases 56f84f55…60fd600e, testcases-watchdog 22b7d25c…6e7913, hashes checked), each toyos-metal --fat32-check exit 0; judge EXIT=0, [metal] 249 passed, 0 failed, 2 boot(s). The loader, at the counter's stated 2419200000 Hz: Slot A: signed header … verifies under this loader's key on both; Slot A: ROOT hashed in 6418027444 counter ticks (testcases, 2.653 s) and 188011514 (watchdog, 77.7 ms). Main's comparison, the same lines from #807's boots at 0ad87a593 (base d6298c83e, the loader unchanged from main, scalar sha2 under force-soft): 5343577520 (2.209 s) and 166696118 (68.9 ms). So the loader's ROOT hash takes about 1.20x and 1.13x as long: +0.44 s on every testcases boot. One boot each, different images; no timing verdict, but the direction matches the host's 1.2x.

Japabu and others added 3 commits October 9, 2026 19:40
…and the bit-oriented ones go

The licence gate counts every file under a shipped path package's directory
as shipped, so vectors under toyos-sha2/cavp/ needed NIST-PD in ALLOWED. They
are test input only: under tests/, the build's own directory, no shipped
package holds them, NOTICE's section says NIST-PD as before, and ALLOWED is
main's again.

The bit-oriented ShortMsg and Monte files go with the test code that read
them. The crate hashes whole bytes; the bit test padded in its own helper and
drove the compression function directly, which the byte ShortMsg, LongMsg and
Monte files already drive over thousands of blocks, and the bit Monte files
differ from the byte ones only by their seed.

The host-tools issue named sha2 as what src/release.rs hashes with; it is
toyos-sha2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
…schedule computed a pass ahead, every round's indices constant, and the hash value held across a run of blocks

The loader's ROOT hash took 2.653 s on the T14 against main's 2.209 s with
sha2's soft backend. Three changes close it, measured on the host at
opt-level 2 with [profile.toyos]'s debug assertions and overflow checks, 56 MiB,
best of 21 runs' thread CPU time:

- The schedule is a sixteen-word ring, W(t) written over W(t-16) a pass at a
  time, in place of a 64- or 80-word array.
- Rounds and schedule words are written out sixteen to a pass through const
  generics, so every index into the working variables and the schedule is a
  constant; LLVM had kept the rounds a loop over memory.
- One call compresses every whole block of an update, the hash value in
  locals between them; Maj is b ^ ((a ^ b) & (b ^ c)), whose b ^ c is the
  previous round's a ^ b.

SHA-256 went from 124.95 ms to 99.10 ms and SHA-512 from 80.03 ms to 61.63 ms,
against sha2 force-soft's 103.33-105.29 ms and 66.98-68.22 ms. The two
compression functions are now one macro over their word, block, constants and
rotations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
update's ROOT hash, pkg and swap on the T14 and the build's hashing on x86-64
CI runners took sha2's x86 backend; toyos-sha2 is scalar and forbids unsafe.
The loss is at most the scalar time, which the T14's loader measured on main:
2.21 s for the testcases image's 306 MiB ROOT. Whether that is worth unsafe
intrinsics in the crate every signed image is verified with is the owner's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu Japabu changed the title ToyOS's own SHA-256 and SHA-512 replace the sha2 crate in the loader's and update's image verification, swap, pkg and the build ToyOS's own SHA-256 and SHA-512, as fast as sha2's soft backend, replace the sha2 crate in the loader's and update's image verification, swap, pkg and the build Oct 9, 2026
@Japabu

Japabu commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

Round 2 evidence for #812 at b9132eb (the code at c8aad54; b9132eb adds only the issue file). Paths are shown relative to the worktree or as <scratch>.

Host benchmark: toyos-sha2 against sha2 0.10.9, 56 MiB

Apple M4 Pro (aarch64; sha2's default there is its soft backend, its hardware one needing the asm feature). opt-level 2 with [profile.toyos]'s debug assertions and overflow checks, best of 21 runs' thread CPU time. The last two lines are the round-1 head's toyos-sha2 (db2e1f3, as a path crate old-sha2) against this head, same session.

19:40  up 10 days,  7:25, 6 users, load averages: 12.51 11.45 16.05
58720256 bytes (56.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2   102.09 ms   548.6 MiB/s | sha2 force-soft   105.29 ms   531.8 MiB/s | ratio 0.97
SHA-512 toyos-sha2    63.40 ms   883.3 MiB/s | sha2 force-soft    68.22 ms   820.9 MiB/s | ratio 0.93
58720256 bytes (56.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2   101.94 ms   549.3 MiB/s | sha2 force-soft   104.51 ms   535.8 MiB/s | ratio 0.98
SHA-512 toyos-sha2    62.99 ms   889.0 MiB/s | sha2 force-soft    68.22 ms   820.9 MiB/s | ratio 0.92
58720256 bytes (56.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2    99.77 ms   561.3 MiB/s | sha2 force-soft   103.33 ms   541.9 MiB/s | ratio 0.97
SHA-512 toyos-sha2    62.37 ms   897.9 MiB/s | sha2 force-soft    66.98 ms   836.1 MiB/s | ratio 0.93
58720256 bytes (56.0 MiB), best of 21, thread CPU time
SHA-256 toyos-sha2   100.07 ms   559.6 MiB/s | sha2 default   102.45 ms   546.6 MiB/s | ratio 0.98
SHA-512 toyos-sha2    62.06 ms   902.4 MiB/s | sha2 default    67.18 ms   833.5 MiB/s | ratio 0.92
19:41  up 10 days,  7:25, 6 users, load averages: 12.74 11.71 15.97
19:41  up 10 days,  7:25, 6 users, load averages: 12.54 11.70 15.91
SHA-256 db2e1f337   124.95 ms | this head    99.10 ms
SHA-512 db2e1f337    80.03 ms | this head    61.63 ms
Cargo.toml
[package]
name = "sha2bench"
version = "0.0.0"
edition = "2024"
publish = false

[features]
soft = ["sha2/force-soft"]

[dependencies]
toyos-sha2 = { path = "<worktree>/toyos-sha2" }
sha2 = "0.10"
libc = "0.2"
old-sha2 = { path = "old" }

# As `[profile.toyos]`, which the loader, update, swap and pkg build with.
[profile.release]
opt-level = 2
debug-assertions = true
overflow-checks = true

[workspace]
src/main.rs
use sha2::Digest as _;
fn cpu() -> f64 {
    let mut t = libc::timespec { tv_sec: 0, tv_nsec: 0 };
    assert_eq!(unsafe { libc::clock_gettime(libc::CLOCK_THREAD_CPUTIME_ID, &mut t) }, 0);
    t.tv_sec as f64 + t.tv_nsec as f64 * 1e-9
}

fn best<const N: usize>(f: impl Fn() -> [u8; N]) -> (f64, [u8; N]) {
    let mut best = f64::MAX;
    let mut out = [0; N];
    for _ in 0..21 {
        let t = cpu();
        out = std::hint::black_box(f());
        best = best.min(cpu() - t);
    }
    (best, out)
}

fn main() {
    let size: usize = std::env::args().nth(1).expect("bytes").parse().expect("a size");
    let data: Vec<u8> = (0..size).map(|i| (i as u32).wrapping_mul(2654435761) as u8).collect();
    let mib = size as f64 / (1 << 20) as f64;
    let (a, da) = best(|| toyos_sha2::Sha256::digest(&data));
    let (b, db) = best(|| sha2::Sha256::digest(&data).into());
    assert_eq!(da, db);
    let (c, dc) = best(|| toyos_sha2::Sha512::digest(&data));
    let (d, dd) = best(|| sha2::Sha512::digest(&data).into());
    assert_eq!(dc, dd);
    if std::env::args().nth(2).as_deref() == Some("old") {
        let (a, _) = best(|| old_sha2::Sha256::digest(&data));
        let (b, _) = best(|| toyos_sha2::Sha256::digest(&data));
        let (c, _) = best(|| old_sha2::Sha512::digest(&data));
        let (d, _) = best(|| toyos_sha2::Sha512::digest(&data));
        println!("SHA-256 db2e1f337 {:8.2} ms | this head {:8.2} ms", a * 1e3, b * 1e3);
        println!("SHA-512 db2e1f337 {:8.2} ms | this head {:8.2} ms", c * 1e3, d * 1e3);
        return;
    }
    let soft = if cfg!(feature = "soft") { "sha2 force-soft" } else { "sha2 default" };
    println!("{size} bytes ({mib:.1} MiB), best of 21, thread CPU time");
    println!("SHA-256 toyos-sha2 {:8.2} ms {:7.1} MiB/s | {soft} {:8.2} ms {:7.1} MiB/s | ratio {:.2}", a * 1e3, mib / a, b * 1e3, mib / b, a / b);
    println!("SHA-512 toyos-sha2 {:8.2} ms {:7.1} MiB/s | {soft} {:8.2} ms {:7.1} MiB/s | ratio {:.2}", c * 1e3, mib / c, d * 1e3, mib / d, c / d);
}

Mutations at c8aad54

Each patch applied checked, toyos-sha2 built and its tests run, the patch reverted, the tree left clean, all in one script.

head c8aad54b1
mutation-k256-first build EXIT=0
mutation-k256-first test EXIT=101
mutation-k256-first restored, porcelain: []
mutation-k512-last build EXIT=0
mutation-k512-last test EXIT=101
mutation-k512-last restored, porcelain: []
mutation-schedule-tap build EXIT=0
mutation-schedule-tap test EXIT=101
mutation-schedule-tap restored, porcelain: []
mutation-maj build EXIT=0
mutation-maj test EXIT=101
mutation-maj restored, porcelain: []
mutation-hash-across-blocks build EXIT=0
mutation-hash-across-blocks test EXIT=101
mutation-hash-across-blocks restored, porcelain: []
mutation-names-rotate build EXIT=0
mutation-names-rotate test EXIT=101
mutation-names-rotate restored, porcelain: []
mutation-k256-first: the patch and which tests red
diff --git a/toyos-sha2/src/lib.rs b/toyos-sha2/src/lib.rs
index 3e85b56fa..5c4b74ec1 100644
--- a/toyos-sha2/src/lib.rs
+++ b/toyos-sha2/src/lib.rs
@@ -24,7 +24,7 @@ mod tests;
 /// SHA-256's round constants, §4.2.2.
 #[rustfmt::skip]
 const K256: [u32; 64] = [
-    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+    0x428a2f99, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
test tests::every_length_to_4096_in_random_splits_agrees_with_sha2 ... FAILED
test tests::sha256_byte_vectors ... FAILED
test tests::sha256_monte_carlo ... FAILED
test tests::sha512_byte_vectors ... ok
test tests::sha512_monte_carlo ... ok
test result: FAILED. 2 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s
mutation-k512-last: the patch and which tests red
diff --git a/toyos-sha2/src/lib.rs b/toyos-sha2/src/lib.rs
index 3e85b56fa..f8231a48a 100644
--- a/toyos-sha2/src/lib.rs
+++ b/toyos-sha2/src/lib.rs
@@ -62,7 +62,7 @@ const K512: [u64; 80] = [
     0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
     0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
     0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
-    0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
+    0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475818,
 ];
 
 /// SHA-512's initial hash value, §5.3.5.
test tests::every_length_to_4096_in_random_splits_agrees_with_sha2 ... FAILED
test tests::sha512_byte_vectors ... FAILED
test tests::sha512_monte_carlo ... FAILED
test tests::sha256_byte_vectors ... ok
test tests::sha256_monte_carlo ... ok
test result: FAILED. 2 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s
mutation-schedule-tap: the patch and which tests red
diff --git a/toyos-sha2/src/lib.rs b/toyos-sha2/src/lib.rs
index 3e85b56fa..9b7a40f06 100644
--- a/toyos-sha2/src/lib.rs
+++ b/toyos-sha2/src/lib.rs
@@ -123,7 +123,7 @@ macro_rules! compress {
                 let s1 = w2.rotate_right(x) ^ w2.rotate_right(y) ^ (w2 >> z);
                 w[I] = w[I]
                     .wrapping_add(s0)
-                    .wrapping_add(w[(I + 9) % 16])
+                    .wrapping_add(w[(I + 8) % 16])
                     .wrapping_add(s1);
             }
 
test tests::every_length_to_4096_in_random_splits_agrees_with_sha2 ... FAILED
test tests::sha256_byte_vectors ... FAILED
test tests::sha512_byte_vectors ... FAILED
test tests::sha256_monte_carlo ... FAILED
test tests::sha512_monte_carlo ... FAILED
test result: FAILED. 0 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
mutation-maj: the patch and which tests red
diff --git a/toyos-sha2/src/lib.rs b/toyos-sha2/src/lib.rs
index 3e85b56fa..97eb746f1 100644
--- a/toyos-sha2/src/lib.rs
+++ b/toyos-sha2/src/lib.rs
@@ -107,7 +107,7 @@ macro_rules! compress {
                     .wrapping_add(e.rotate_right(x) ^ e.rotate_right(y) ^ e.rotate_right(z));
                 let [x, y, z] = $s0;
                 let t2 = (a.rotate_right(x) ^ a.rotate_right(y) ^ a.rotate_right(z))
-                    .wrapping_add(b ^ ((a ^ b) & (b ^ c)));
+                    .wrapping_add(b ^ ((a ^ b) & (a ^ c)));
                 v[at(3)] = v[at(3)].wrapping_add(t1);
                 v[at(7)] = t1.wrapping_add(t2);
             }
test tests::every_length_to_4096_in_random_splits_agrees_with_sha2 ... FAILED
test tests::sha256_byte_vectors ... FAILED
test tests::sha512_byte_vectors ... FAILED
test tests::sha256_monte_carlo ... FAILED
test tests::sha512_monte_carlo ... FAILED
test result: FAILED. 0 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
mutation-hash-across-blocks: the patch and which tests red
diff --git a/toyos-sha2/src/lib.rs b/toyos-sha2/src/lib.rs
index 3e85b56fa..e89e06dce 100644
--- a/toyos-sha2/src/lib.rs
+++ b/toyos-sha2/src/lib.rs
@@ -133,7 +133,7 @@ macro_rules! compress {
                 for (word, bytes) in w.iter_mut().zip(block.as_chunks().0) {
                     *word = <$word>::from_be_bytes(*bytes);
                 }
-                let mut v = hash;
+                let mut v = *state;
                 for (pass, k) in $k.as_chunks::<16>().0.iter().enumerate() {
                     if pass > 0 {
                         sixteen!(schedule(&mut w));
test tests::every_length_to_4096_in_random_splits_agrees_with_sha2 ... FAILED
test tests::sha256_byte_vectors ... FAILED
test tests::sha512_byte_vectors ... FAILED
test tests::sha256_monte_carlo ... ok
test tests::sha512_monte_carlo ... ok
test result: FAILED. 2 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.03s
mutation-names-rotate: the patch and which tests red
diff --git a/toyos-sha2/src/lib.rs b/toyos-sha2/src/lib.rs
index 3e85b56fa..e2b975595 100644
--- a/toyos-sha2/src/lib.rs
+++ b/toyos-sha2/src/lib.rs
@@ -96,7 +96,7 @@ macro_rules! compress {
             /// `v[(8 - I % 8) % 8]`, and it writes only its new `e` and `a`.
             #[inline(always)]
             fn round<const I: usize>(v: &mut [$word; 8], k: &[$word; 16], w: &[$word; 16]) {
-                let at = |n: usize| (n + 8 - I % 8) % 8;
+                let at = |n: usize| (n + 8 - I % 4) % 8;
                 let (a, b, c) = (v[at(0)], v[at(1)], v[at(2)]);
                 let (e, f, g) = (v[at(4)], v[at(5)], v[at(6)]);
                 let [x, y, z] = $s1;
test tests::every_length_to_4096_in_random_splits_agrees_with_sha2 ... FAILED
test tests::sha256_byte_vectors ... FAILED
test tests::sha512_byte_vectors ... FAILED
test tests::sha256_monte_carlo ... FAILED
test tests::sha512_monte_carlo ... FAILED
test result: FAILED. 0 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
mutate.sh
#!/bin/sh
# Apply one checked mutation patch, build and run toyos-sha2's tests, report, restore.
set -u
tree=<worktree>
logs=<scratch>
cd "$tree" || exit 9
echo "head $(git rev-parse --short HEAD)"
for m in mutation-k256-first mutation-k512-last mutation-schedule-tap mutation-maj mutation-hash-across-blocks mutation-names-rotate; do
  git apply --check "$logs/$m.patch" || { echo "$m: does not apply"; exit 9; }
  git apply "$logs/$m.patch"
  cargo build -p toyos-sha2 > "$logs/$m.build.log" 2>&1; echo "$m build EXIT=$?"
  cargo test -p toyos-sha2 > "$logs/$m.test.log" 2>&1; echo "$m test EXIT=$?"
  git apply -R "$logs/$m.patch"
  echo "$m restored, porcelain: [$(git status --porcelain --ignore-submodules=none)]"
done

x86-64 listing count

A staticlib crate calling toyos_sha2::Sha256::digest and sha2::Sha256::digest (force-soft), built with RUSTFLAGS=--emit=asm,link cargo build --release --target x86_64-unknown-uefi under the profile above. Instruction lines counted in each compress256: this head's block load 65, schedule pass 341 (run 3 times), round pass 536 (run 4 times); sha2 soft's per-block loop 3,427.

Cargo.toml and src/lib.rs
[package]
name = "sha2x86"
version = "0.0.0"
edition = "2024"
publish = false

[lib]
crate-type = ["staticlib"]

[dependencies]
toyos-sha2 = { path = "<worktree>/toyos-sha2" }
sha2 = { version = "0.10", default-features = false, features = ["force-soft"] }

# As `[profile.toyos]`, which the loader builds with.
[profile.release]
opt-level = 2
debug-assertions = true
overflow-checks = true
panic = "abort"

[workspace]
#![no_std]
use sha2::Digest as _;
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! { loop {} }
#[unsafe(no_mangle)]
pub extern "C" fn ours(m: &[u8], out: &mut [u8; 32]) { *out = toyos_sha2::Sha256::digest(m); }
#[unsafe(no_mangle)]
pub extern "C" fn theirs(m: &[u8], out: &mut [u8; 32]) { *out = sha2::Sha256::digest(m).into(); }

@Japabu

Japabu commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #812 at head b9132ebb7, against .claude/agents/reviewer.md. This is round 2.

Round-1 BLOCKERs

  • src/licence.rs, NIST-PD in ALLOWED: CLOSED.
    • git diff origin/main...b9132ebb7 -- src/licence.rs is empty.
    • The vectors are now in tests/cavp/, and NOTICE's section heading moved with them.
    • ci-host.log (gates.head b9132ebb7, EXIT=0, "Host: 78 step(s), all green") reads "NOTICE section tests/cavp/ (NIST-PD) is not shipped" and "6 exception(s) stand, and nothing else is refused".
    • The FAILED and SIGABRT lines in that log all sit inside [ci] control steps, each of which reached its verdict.
  • Speed: the x86-64 callers that lost SHA-NI/AVX2: CLOSED, as a recorded compromise.
    • issues/x86-64-hashing-runs-scalar-where-the-cpu-has-sha-instructions.md is kind: question / status: owner, which is legal under issues/README.md.
    • It names the callers. It bounds the loss by the scalar time main's T14 loader measured: 5,343,577,520 ticks for 320,864,256 bytes at 2,419,200,000 Hz. It says update's own time is unmeasured, and its exit is readable.
    • The bound is an upper bound only while toyos-sha2's x86-64 scalar rate is at least sha2 soft's. The metal reading below holds that.
    • The host CPU-time claim stands on bench-r2.log. The source, best of 21 runs of thread CPU time, assert_eq! between the two digests, and round 1 against this head in the same session are all in comment 6086316086. The ratios are 0.97–0.98 for SHA-256 and 0.92–0.93 for SHA-512.
  • Evidence, metal: OPEN. metal-stage.log is EXIT=2: staged, and the machine was not touched.

I re-read the c8aad54 compression against FIPS 180-4 §6.2.2 and §6.4.2.

  • In the ring schedule, w[I] holds W(t-16) going in. (I+1)%16, (I+14)%16 and (I+9)%16 are W(t-15), W(t-2) and W(t-7) at every I of a pass, before and after the wrap.
  • In round::<I>, at(n) makes round I+1's a, b, e the new a, the old a and the new e. 64 and 80 are both multiples of 16, so each pass ends aligned.
  • Maj written as b ^ ((a^b)&(b^c)) is Maj, and g ^ (e&(f^g)) is Ch.
  • The six mutations red the tests as stated (mutate.log: every build EXIT=0, every test EXIT=101, porcelain clean). I found no mutation of the schedule, the rounds, the buffering or the padding that the byte vectors, Monte and the 0..=4096 split differential would miss.

Net lines (git diff --shortstat origin/main...b9132ebb7): 29 files, +2785/−36.

  • Production: toyos-sha2/src/lib.rs +255 and about 50 lines of callers and manifests. This replaces a dependency on the owner's ruling, and is accepted.
  • Tests: +225.
  • NIST data: +2190.
  • NOTICE and issues: +65.

Round 1's NOTEs are closed: the bit vectors and padded/bit_file are deleted, and the shasum row names toyos-sha2.

BLOCKER

  • bootloader/src/slot.rs:149-150 — the T14 reading at this head is owed. The change is on the loader's boot path. The PR title claims "as fast as sha2's soft backend", and on x86-64 nothing has timed that. The x86-64 listing count (65 + 3×341 + 4×536) is a static count from a listing with no exit code or log posted, and it is not a timing. The reading must show all of the following:
    • The toyos-metal run's command, its exit code and its log, for the testcases image whose sha256 is request.txt's b792b6d7…b012d, built from b9132ebb7.
    • The loader's section and signature verification passing, and boot:testcases green on that boot.
    • The line Slot A: ROOT hashed in N counter ticks, with the ROOT's byte count from the same log.
    • N/bytes no greater than main's 5,343,577,520 / 320,864,256 ticks per byte (16.65), stated as a ratio. If the ratio is above 1.00, also a second main boot at d6298c8 on the T14. If the ratio exceeds that pair's spread, the speed claim in the title is false, the issue's "at most 2.2 s" bound understates, and the branch goes back to the compression.
    • For reference, round 1 read 6,418,027,444 ticks, a ratio of 1.20.

NOTE

SEND BACK

@Japabu

Japabu commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

T14 at b9132ebb7, run by the orchestrator (loader built by the pre-#790 compiler this branch sits on): boot:testcases, two boots, each image's sha256 checked against request.txt before its flash (testcases b792b6d7…37eb012d, testcases-watchdog d06af5d8…8d1edc), each toyos-metal --fat32-check exit 0; judge cargo test --test toyos-build -- --metal --metal-readback <dir> boot:testcases: EXIT=0, [metal] 249 passed, 0 failed, 2 boot(s). The loader, at 2419200000 Hz: Slot A: signed header … verifies under this loader's key on both; testcases: ROOT: read into memory … from LBA 212992+626688 (320,864,256 bytes) and Slot A: ROOT hashed in 4757794201 counter ticks (1.967 s, 14.83 ticks/byte) against main's 5343577520 over the same 320,864,256 bytes (2.209 s, 16.65 ticks/byte): 0.89x main; testcases-watchdog: 139726606 against main's 166696118, 0.84x. One boot each; the ratio is below 1.00, so no second main boot is owed by the review's rule.

@Japabu

Japabu commented Oct 9, 2026

Copy link
Copy Markdown
Collaborator Author

Review of #812 at head b9132ebb7 (unchanged since round 2), against .claude/agents/reviewer.md. This is round 3.

Earlier BLOCKERs

  • bootloader/src/slot.rs:149-150, the T14 reading: CLOSED. I read the orchestrator's readback, and each of round 2's conditions holds.
    • The image is the one requested. t14-sha2-r2.log reads testcases boot rc=0 sha=b792b6d71c9d4a3077db16ed146ef5e309d3203fd6bd8a62b10b3b2937eb012d. That is request.txt's sha256, and the request names wt/toyos-sha2 at b9132ebb7. The run was toyos-metal --image … --fat32-check.
    • The loader's verification passed. testcases/loader.log has Slot A: signed header bc472d6e… verifies under this loader's key and Slot A: kernel, cmdline and ROOT are the bytes the signed header names. The judge passed: t14-sha2-r2.log reads judge EXIT=0 [metal] 249 passed, 0 failed, 2 boot(s), and both verdict.txt files read passed.
    • The same log gives the ROOT hash time and the bytes it covers. ROOT: read into memory at 0x3b970000+0x13200000 is 320,864,256 bytes, and Slot A: ROOT hashed in 4757794201 counter ticks follows at the stated 2419200000 Hz. The line timestamps run from 20.068 to 22.051, which agrees.
    • Against main: 4,757,794,201 / 320,864,256 = 14.83 ticks per byte, and main's 5,343,577,520 over the same byte count is 16.65. The ratio is 0.89. It is below 1.00, so no second main boot is owed.
    • The title's speed claim and the issue's "at most 2.2 s" bound therefore stand on x86-64 too.

Main has moved to 198a9d38e. The new commits are #804, which touches src/metal.rs and tests/, and none of it is a sha2 caller. git merge-tree against this head is clean. crate::release::sha256_hex, which main's src/sdkversion.rs calls, still exists at src/release.rs:85 on this head.

Net lines (git diff --shortstat origin/main...b9132ebb7): 29 files, +2785/−36. Production is toyos-sha2/src/lib.rs at +255, plus about 50 lines of callers and manifests. Tests are +225 and NIST data +2190. All of this is unchanged since round 2 and accepted there.

NOTE

LAND

@Japabu
Japabu marked this pull request as ready for review October 9, 2026 18:03
…sha2

#808 brought toyos-update's repo.rs, which streams an archive through
sha2::Sha256; it now holds a toyos_sha2::Sha256, whose finalize is already
the [u8; 32] Digest. toyos-update's manifest keeps toyos-sha2 beside main's
toyos-wallclock and names no sha2; sha2 stays in Cargo.lock only as
ed25519-dalek's and toyos-sha2's differential dev-dependency. Cargo.lock is
main's, re-resolved.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Round 3 logs at merge head ae2aee73c (merge of origin/main 9b691ddce). Home-directory paths are written ~.

cargo test -p toyos-update (EXIT=0)

    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
   Compiling sha2 v0.10.9
   Compiling ed25519-dalek v2.2.0
   Compiling toyos-update v0.1.0 (<checkouts>/toyos-sha2/toyos-update)
    Finished `test` profile [optimized + debuginfo] target(s) in 2.62s
     Running unittests src/lib.rs (target/debug/deps/toyos_update-5d2d6fa51c550780)

running 42 tests
test floor::tests::a_runtime_variable_that_stays_is_refused ... ok
test floor::tests::a_floor_is_named_for_its_key_and_scope ... ok
test floor::tests::a_loader_deletes_the_stale_floors_of_its_scope_and_never_the_owners ... ok
test floor::tests::only_not_found_is_no_variable ... ok
test floor::tests::only_the_loaders_own_variable_is_a_floor_and_nothing_else_is_none ... ok
test policy::tests::a_boot_tries_the_marked_slot_first_and_the_other_only_if_there_is_one ... ok
test policy::tests::an_update_must_be_newer_than_what_runs ... ok
test image::tests::a_bent_header_is_refused_by_name ... ok
test image::tests::a_header_reads_back_as_it_was_written ... ok
test policy::tests::every_word_is_one_parameter_token ... ok
test image::tests::an_image_splits_into_exactly_its_sections ... ok
test policy::tests::the_floor_admits_its_own_version_and_above_and_only_rises ... ok
test record::tests::a_hang_kills_only_an_unproven_image ... ok
test record::tests::a_record_reads_back_and_anothers_is_refused ... ok
test record::tests::how_a_boot_ended_is_what_it_is_recorded_as ... ok
test record::tests::the_first_write_credits_no_image ... ok
test repo::tests::a_document_that_is_not_the_format_is_refused_by_line ... ok
test repo::tests::a_time_is_one_that_exists_and_reads_back ... ok
test repo::tests::an_archive_past_its_length_or_not_its_hash_is_refused ... ok
test repo::tests::base64_has_one_spelling ... ok
test repo::tests::a_machines_root_at_the_images_version_with_other_bytes_is_refused ... ok
test repo::tests::a_machines_newer_root_holds_though_the_mirror_withholds_it ... ok
test repo::tests::a_document_past_its_cap_is_refused_unread ... ok
test repo::tests::a_duplicated_signature_does_not_meet_a_threshold ... ok
test repo::tests::targets_not_matching_the_timestamp_are_refused ... ok
test sig::tests::the_message_is_sshsigs_signed_data ... ok
test slots::tests::a_grant_claims_only_an_idle_slot_on_the_running_disk ... ok
test slots::tests::a_table_reads_back_and_a_bent_one_is_refused ... ok
test slots::tests::moving_the_mark_is_atomic_against_a_torn_copy ... ok
test slots::tests::the_checksum_is_crc32 ... ok
test slots::tests::the_idle_slot_is_the_one_whose_root_the_kernel_does_not_hold ... ok
test repo::tests::a_repository_the_renderer_writes_is_one_the_client_accepts ... ok
test repo::tests::a_rotated_root_is_walked_and_drops_the_old_keys_floors ... ok
test sig::tests::rfc_8032_vectors_verify_and_a_flipped_bit_does_not ... ok
test repo::tests::a_root_not_signed_by_the_previous_threshold_is_refused ... ok
test repo::tests::a_signature_in_another_namespace_is_refused ... ok
test repo::tests::a_root_at_the_last_version_is_refused ... ok
test repo::tests::a_role_version_below_the_held_one_is_refused ... ok
test repo::tests::the_same_version_with_other_bytes_is_refused ... ok
test repo::tests::a_lower_sequence_or_a_reissued_one_is_refused ... ok
test repo::tests::expired_metadata_is_refused_with_both_times ... ok
test repo::tests::a_chain_past_the_walk_bound_is_refused ... ok

test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s

     Running tests/repo_oracle.rs (target/debug/deps/repo_oracle-d5eea586d4b695e0)

running 1 test
test a_repository_ssh_keygen_signed_is_accepted_and_a_bent_one_is_not ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/sshsig_oracle.rs (target/debug/deps/sshsig_oracle-08b52a2ea8eb8d0b)

running 1 test
test a_header_ssh_keygen_signed_verifies_and_a_bent_one_does_not ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests toyos_update

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo test -p toyos-sha2 (EXIT=0)

    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on package cache
    Blocking waiting for file lock on build directory
   Compiling toyos-sha2 v0.1.0 (<checkouts>/toyos-sha2/toyos-sha2)
    Finished `test` profile [optimized + debuginfo] target(s) in 11.93s
     Running unittests src/lib.rs (target/debug/deps/toyos_sha2-8fda0cdca047f679)

running 5 tests
test tests::sha256_byte_vectors ... ok
test tests::sha512_byte_vectors ... ok
test tests::sha256_monte_carlo ... ok
test tests::sha512_monte_carlo ... ok
test tests::every_length_to_4096_in_random_splits_agrees_with_sha2 ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.30s

   Doc-tests toyos_sha2

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo run -- --ci host (EXIT=0): its section headers and last line

06:10:13 === [ci] the build system
06:11:20 === [ci] the harness's own checks
06:11:45 === [ci] the workspace's host members
06:15:58 === [ci] the kernel's library
06:15:59 === [ci] the licences of what ships
06:16:03 === [ci] clippy and the bare targets
06:16:03 === [ci] clippy, warnings denied
06:16:27 === [ci] kernel-loom without loom
06:16:28 === [ci] control `wake-fence-off`
06:16:28 === [ci] control `lock-acquire-off`
06:16:28 === [ci] control `owed-fence-off`
06:16:29 === [ci] control `seqlock-writer-fence-off`
06:16:29 === [ci] control `serial-try-lock-then-some`
06:16:29 === [ci] control `reap-raise-relaxed`
06:16:29 === [ci] control `shootdown-serve-relaxed`
06:16:30 === [ci] control `shootdown-served-relaxed`
06:16:30 === [ci] control `roster-commit-relaxed`
06:16:31 === [ci] control `smp-ready-split`
06:16:31 === [ci] control `log-commit-release-off`
06:16:31 === [ci] control `shard-publish-relaxed`
06:16:31 === [ci] control `log-ring-publish-relaxed`
06:16:32 === [ci] control `log-ring-tail-relaxed`
06:16:32 === [ci] control `log-ring-loads-swapped`
06:16:32 === [ci] control `post-is-an-answer`
06:16:32 === [ci] control `poll-fire-load-store`
06:16:33 === [ci] control `sleeplock-acquire-off`
06:16:33 === [ci] control `device-irq-lossy`
06:16:33 === [ci] control `dump-report-relaxed`
06:16:34 === [ci] control `no-preempt-guard`
06:16:34 === [ci] control `doorbell-kick-relaxed`
06:16:35 === [ci] control `push-fence-relaxed`
06:16:35 === [ci] control `commit-ignores-notify`
06:16:35 === [ci] control `notify-flag-load-only`
06:16:39 === [ci] control `gate-fence-off`
06:16:39 === [ci] control `poll-fire-load-store`
06:16:39 === [ci] control `fault-posted-before-it-is-set`
06:16:39 === [ci] control `victim-retires-mid-probe`
06:16:40 === [ci] control `counting-allocator`
06:16:40 === [ci] control `mutate-spawn-skips-the-insert-recheck`
06:16:40 === [ci] control `mutate-claim-teardown-always-wins`
06:16:40 === [ci] control `mutate-kill-waits-for-its-victims`
06:16:41 === [ci] control `mutate-first-out-tears-down`
06:16:41 === [ci] control `mutate-join-collects-in-a-teardown`
06:16:41 === [ci] control `mutate-last-out-leaves-before-its-teardown`
06:16:42 === [ci] control `mutate-place-skips-the-insert-recheck`
06:16:42 === [ci] control `mutate-refused-spawn-keeps-the-count`
06:16:42 === [ci] control `mutate-landed-child-retires-nothing`
06:16:42 === [ci] control `mutate-publish-before-the-children`
06:16:42 === [ci] control `mutate-walk-in-one-hold`
06:16:43 === [ci] control `mutate-spawner-handle-after-the-landing`
06:16:43 === [ci] control `mutate-spawner-handle-before-the-childs-own`
06:16:43 === [ci] control `placement-ignores-staleness`
06:16:43 === [ci] control `mutate-session-end-forgets`
06:16:49 === [ci] control `mutate-abort-keeps-inflight`
06:16:49 === [ci] control `mutate-no-reissue-after-loss`
06:16:49 === [ci] control `publish-relaxed`
06:16:50 === [ci] control `no-clamp`
06:16:50 === [ci] control `end-keeps-inflight`
06:16:50 === [ci] userland/acpiserver
06:16:52 === [ci] userland/acpiserver/aml
06:16:53 === [ci] userland/calc
06:16:53 === [ci] userland/compositor/desktop
06:16:53 === [ci] userland/diskserver
06:16:55 === [ci] userland/fileserver
06:16:58 === [ci] userland/logkeeper
06:16:59 === [ci] userland/netstack
06:17:01 === [ci] userland/netstack/mdns
06:17:01 === [ci] userland/netstack/node
06:17:09 === [ci] userland/pkg
06:17:10 === [ci] userland/soundserver
06:17:11 === [ci] userland/soundserver/mixer
06:17:13 === [ci] userland/sshserver
06:17:14 === [ci] userland/symbolize
06:17:15 === [ci] the apps for linux
06:17:20 === [ci] the apps for macos
06:17:25 === [ci] the apps for windows
06:17:34 === [ci] the toyos SDK
06:17:38 === [ci] nothing left in $TMPDIR or /tmp
06:17:38 [ci] Host: 78 step(s), all green
EXIT=0

cargo run -- --build-only (EXIT=0): its last lines

06:20:04 Signed with this checkout's throwaway key SHA256:oHE+/kD905qIBlZwnccj27R86SMHQpWKF5MLxN9njiY at version 1791613066
06:20:05 Build finished.
Boot image: <checkouts>/toyos-sha2/target/bootable.img
EXIT=0

whole guest suite, cargo test --test toyos-build (EXIT=0)

uptime before:  8:20  up 10 days, 20:04, 6 users, load averages: 45.87 45.91 31.78
06:21:06   PASS  nested_nmi_is_loud  (3s)
06:21:17   PASS  acpi_power_button  (9s)
06:21:17   PASS  machine_shutdown  (9s)
06:21:18   PASS  machine_shutdown_short_stop  (9s)
06:21:20   PASS  acpi_supply_outlives_holder  (10s)
06:21:21   PASS  acpi_mediated_access  (46s)
06:21:21   PASS  acpi_lock_given_back_on_one_cpu  (46s)
06:21:21   PASS  bar_map_again  (9s)
06:21:22   PASS  netstack_streams  (12s)
06:21:22   PASS  netstack_socket_churn  (11s)
06:21:23   PASS  netstack_streams_e1000e  (12s)
06:21:25   PASS  screen_panic_muted  (7s)
06:21:27   PASS  libc_sockets  (45s)
06:21:29   PASS  console_image_boots  (8s)
06:21:31   PASS  screen_loader_clears  (10s)
06:21:33   PASS  screen_fatal_behind_a_painter  (13s)
06:21:35   PASS  iommu_virtio_platform  (26s)
06:21:42   PASS  nvme_disk_keeps_log_and_home  (25s)
06:21:42   PASS  screen_fatal_halt_composited  (10s)
06:22:21   PASS  virt_early_panic  (997ms)
06:22:22   PASS  virt_early_fault  (745ms)
06:22:22   PASS  virt_el2_drop  (1s)
06:22:23   PASS  virt_user_mode  (2s)
06:22:24   [virt] [ 1.958 cpu0 kernel] timer-floor: PASS span=240 floor=240 ticks: the comparator past the counter it was set from
06:22:24   PASS  virt_timer_floor  (2s)
06:22:29   PASS  virt_timer_preempts  (2s)
06:22:30   PASS  virt_unmap_touch  (52s)
06:22:30   PASS  virt_fp_isolation  (56s)
06:22:31   PASS  virt_first_entry  (58s)
06:22:31   PASS  virt_readonly_copyout  (49s)
06:22:31   PASS  virt_ring0_timer_in_syscall  (10s)
06:22:32   PASS  virt_debug_refused  (49s)
06:22:35   [virt] [12.790 cpu0 kernel] irq-storm: PASS sgis=7180565/7180565 ticks=1000: the timer fired through the flood, and every SGI sent was taken
06:22:35   PASS  virt_irq_storm  (13s)
06:22:35   PASS  virt_jobs_at_el2  (4s)
06:22:37   PASS  virt_random_differs  (5s)
06:22:38   PASS  virt_no_seed_refused  (7s)
06:22:44   PASS  virt_reboot_refused_without_psci  (2s)
06:22:44   PASS  virt_el1_smp  (9s)
06:22:44   PASS  virt_smp  (11s)
06:22:46   PASS  virt_reboot  (4s)
06:22:46   PASS  virt_mask_windows  (7s)
06:22:47   PASS  virt_fatal_halts_the_others_first  (3s)
06:22:48   PASS  virt_failed_ap_leaves_no_hole  (12s)
06:22:51   PASS  virt_off_names_the_cpus_left_on  (10s)
06:22:51   --- 46 guests, 28 of them not the shipping kernel, 3 kernel build(s): ["", "boot-actuators,test-actuators", "mask-windows"]
06:22:51 test result: ok. 43 passed, 43 total (139.8s; workers: 891s building, 692s testing)
EXIT=0
uptime after:  8:22  up 10 days, 20:07, 6 users, load averages: 34.21 41.55 32.45

git diff b9132ebb7 ae2aee73c -- bootloader toyos-sha2

(empty:        0 bytes)

@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Orchestrator's ruling on the merge head ae2aee73c: the loader's signature check is pure computation (as the review of #808 judged its sig.rs), every QEMU boot in the guest suite runs it at this head (43/43), and the hash the T14 measured (toyos-sha2, 0.89x main) is byte-identical; no new T14 boot is owed for the merge. CI at this head is read before queueing.

@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

CI at ae2aee73c, read from each job's log: host 79 steps all green; toolchain toolchain restored; guest suite 43/43 ok. Merges clean with main 9b691ddce. Queued.

@Japabu
Japabu added this pull request to the merge queue Oct 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 10, 2026
@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

CI at ae2aee73c, read from each job's log: host 79 steps all green; guest suite 43/43 ok. Merges clean with main 46632bf25. Queued.

@Japabu
Japabu added this pull request to the merge queue Oct 10, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 10, 2026
…st-side hash is toyos-sha2's

#810's https_fetch hashed the body it serves with the sha2 crate, which
this branch removes from the build crate's dependencies; it now hashes
with toyos-sha2, still a different SHA-256 from the guest's ring. Cargo.lock
is main's, regenerated by cargo over this branch's manifests. #817's
toyos-ssh hashes with ring and takes no sha2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
@Japabu

Japabu commented Oct 10, 2026

Copy link
Copy Markdown
Collaborator Author

Round 4 logs at merge head 24e6fb655 (merge of origin/main 5a3b74345). Home-directory paths are written ~, the worktree <worktree>, the per-user temporary directory $TMPDIR.

cargo test -p toyos-sha2 (EXIT=0)

    Finished `test` profile [optimized + debuginfo] target(s) in 0.22s
     Running unittests src/lib.rs (target/debug/deps/toyos_sha2-8fda0cdca047f679)

running 5 tests
test tests::sha256_byte_vectors ... ok
test tests::sha512_byte_vectors ... ok
test tests::sha256_monte_carlo ... ok
test tests::sha512_monte_carlo ... ok
test tests::every_length_to_4096_in_random_splits_agrees_with_sha2 ... ok

test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.13s

   Doc-tests toyos_sha2

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo test -p toyos-update (EXIT=0)

    Finished `test` profile [optimized + debuginfo] target(s) in 0.19s
     Running unittests src/lib.rs (target/debug/deps/toyos_update-5d2d6fa51c550780)

running 42 tests
test policy::tests::an_update_must_be_newer_than_what_runs ... ok
test record::tests::a_hang_kills_only_an_unproven_image ... ok
test policy::tests::a_boot_tries_the_marked_slot_first_and_the_other_only_if_there_is_one ... ok
test policy::tests::the_floor_admits_its_own_version_and_above_and_only_rises ... ok
test floor::tests::only_not_found_is_no_variable ... ok
test floor::tests::only_the_loaders_own_variable_is_a_floor_and_nothing_else_is_none ... ok
test floor::tests::a_runtime_variable_that_stays_is_refused ... ok
test policy::tests::every_word_is_one_parameter_token ... ok
test record::tests::a_record_reads_back_and_anothers_is_refused ... ok
test record::tests::how_a_boot_ended_is_what_it_is_recorded_as ... ok
test record::tests::the_first_write_credits_no_image ... ok
test floor::tests::a_floor_is_named_for_its_key_and_scope ... ok
test floor::tests::a_loader_deletes_the_stale_floors_of_its_scope_and_never_the_owners ... ok
test image::tests::a_header_reads_back_as_it_was_written ... ok
test image::tests::an_image_splits_into_exactly_its_sections ... ok
test image::tests::a_bent_header_is_refused_by_name ... ok
test repo::tests::a_document_that_is_not_the_format_is_refused_by_line ... ok
test repo::tests::a_document_past_its_cap_is_refused_unread ... ok
test repo::tests::a_duplicated_signature_does_not_meet_a_threshold ... ok
test repo::tests::a_machines_root_at_the_images_version_with_other_bytes_is_refused ... ok
test repo::tests::a_machines_newer_root_holds_though_the_mirror_withholds_it ... ok
test repo::tests::a_time_is_one_that_exists_and_reads_back ... ok
test repo::tests::a_repository_the_renderer_writes_is_one_the_client_accepts ... ok
test repo::tests::an_archive_past_its_length_or_not_its_hash_is_refused ... ok
test repo::tests::base64_has_one_spelling ... ok
test repo::tests::a_lower_sequence_or_a_reissued_one_is_refused ... ok
test repo::tests::targets_not_matching_the_timestamp_are_refused ... ok
test repo::tests::a_root_at_the_last_version_is_refused ... ok
test sig::tests::the_message_is_sshsigs_signed_data ... ok
test slots::tests::a_grant_claims_only_an_idle_slot_on_the_running_disk ... ok
test slots::tests::moving_the_mark_is_atomic_against_a_torn_copy ... ok
test slots::tests::a_table_reads_back_and_a_bent_one_is_refused ... ok
test slots::tests::the_checksum_is_crc32 ... ok
test slots::tests::the_idle_slot_is_the_one_whose_root_the_kernel_does_not_hold ... ok
test sig::tests::rfc_8032_vectors_verify_and_a_flipped_bit_does_not ... ok
test repo::tests::a_root_not_signed_by_the_previous_threshold_is_refused ... ok
test repo::tests::a_rotated_root_is_walked_and_drops_the_old_keys_floors ... ok
test repo::tests::the_same_version_with_other_bytes_is_refused ... ok
test repo::tests::expired_metadata_is_refused_with_both_times ... ok
test repo::tests::a_role_version_below_the_held_one_is_refused ... ok
test repo::tests::a_signature_in_another_namespace_is_refused ... ok
test repo::tests::a_chain_past_the_walk_bound_is_refused ... ok

test result: ok. 42 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s

     Running tests/repo_oracle.rs (target/debug/deps/repo_oracle-d5eea586d4b695e0)

running 1 test
test a_repository_ssh_keygen_signed_is_accepted_and_a_bent_one_is_not ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running tests/sshsig_oracle.rs (target/debug/deps/sshsig_oracle-08b52a2ea8eb8d0b)

running 1 test
test a_header_ssh_keygen_signed_verifies_and_a_bent_one_does_not ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests toyos_update

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

cargo run -- --ci host (EXIT=0): its [ci] lines

08:22:47 === [ci] the build system
08:23:54 [ci] the build system: cargo test --lib
08:23:54 === [ci] the harness's own checks
08:24:05 [ci] the harness's own checks: cargo test --test toyos-checks
08:24:05 === [ci] the workspace's host members
08:29:26 [ci] the workspace's host members: cargo test --workspace --exclude toyos-build --exclude bootloader --exclude kernel --exclude toyos --exclude acpiserver --exclude acpiserver-api --exclude toyos-aml --exclude calc --exclude compositor --exclude toyos-desktop --exclude console --exclude diskserver --exclude doom --exclude editor --exclude filepicker --exclude filepicker-api --exclude files --exclude fileserver --exclude host --exclude inspect --exclude kernelprobe --exclude logkeeper --exclude logkeeper-api --exclude metalprobe --exclude netstack --exclude toyos-mdns --exclude toyos-net-node --exclude paint --exclude pkg --exclude proctest --exclude shell --exclude snake --exclude soundserver --exclude toyos-mixer --exclude sprite --exclude sshserver --exclude supervisor --exclude swap --exclude symbolize --exclude terminal --exclude test-runner --exclude toybox --exclude toyos-font --exclude toyos-window --exclude trace --exclude update
08:29:26 === [ci] the kernel's library
08:29:26 [ci] the kernel's library: cargo test -p kernel --lib --features sched-check
08:29:26 === [ci] the licences of what ships
08:29:30 [ci] the licences of what ships: 6 exception(s) stand, and nothing else is refused
08:29:30 === [ci] clippy and the bare targets
08:29:30 [ci] clippy and the bare targets: installed
08:29:30 === [ci] clippy, warnings denied
08:32:04 [ci] clippy, warnings denied: clean
08:32:04 === [ci] kernel-loom without loom
08:32:04 [ci] kernel-loom without loom: cargo test -p kernel-loom --no-default-features --test log_zeroed_init --test log_body_words --test log_cursor
08:32:04 === [ci] control `wake-fence-off`
08:32:04 [ci] control `wake-fence-off`: 1 verdict(s) reached
08:32:04 === [ci] control `lock-acquire-off`
08:32:05 [ci] control `lock-acquire-off`: 1 verdict(s) reached
08:32:05 === [ci] control `owed-fence-off`
08:32:05 [ci] control `owed-fence-off`: 1 verdict(s) reached
08:32:05 === [ci] control `seqlock-writer-fence-off`
08:32:05 [ci] control `seqlock-writer-fence-off`: 1 verdict(s) reached
08:32:05 === [ci] control `serial-try-lock-then-some`
08:32:06 [ci] control `serial-try-lock-then-some`: 2 verdict(s) reached
08:32:06 === [ci] control `reap-raise-relaxed`
08:32:06 [ci] control `reap-raise-relaxed`: 1 verdict(s) reached
08:32:06 === [ci] control `shootdown-serve-relaxed`
08:32:07 [ci] control `shootdown-serve-relaxed`: 2 verdict(s) reached
08:32:07 === [ci] control `shootdown-served-relaxed`
08:32:07 [ci] control `shootdown-served-relaxed`: 1 verdict(s) reached
08:32:07 === [ci] control `roster-commit-relaxed`
08:32:08 [ci] control `roster-commit-relaxed`: 1 verdict(s) reached
08:32:08 === [ci] control `smp-ready-split`
08:32:08 [ci] control `smp-ready-split`: 1 verdict(s) reached
08:32:08 === [ci] control `log-commit-release-off`
08:32:08 [ci] control `log-commit-release-off`: 2 verdict(s) reached
08:32:08 === [ci] control `shard-publish-relaxed`
08:32:09 [ci] control `shard-publish-relaxed`: 1 verdict(s) reached
08:32:09 === [ci] control `log-ring-publish-relaxed`
08:32:09 [ci] control `log-ring-publish-relaxed`: 3 verdict(s) reached
08:32:09 === [ci] control `log-ring-tail-relaxed`
08:32:10 [ci] control `log-ring-tail-relaxed`: 3 verdict(s) reached
08:32:10 === [ci] control `log-ring-loads-swapped`
08:32:10 [ci] control `log-ring-loads-swapped`: 1 verdict(s) reached
08:32:10 === [ci] control `post-is-an-answer`
08:32:10 [ci] control `post-is-an-answer`: 3 verdict(s) reached
08:32:10 === [ci] control `poll-fire-load-store`
08:32:11 [ci] control `poll-fire-load-store`: 2 verdict(s) reached
08:32:11 === [ci] control `sleeplock-acquire-off`
08:32:11 [ci] control `sleeplock-acquire-off`: 2 verdict(s) reached
08:32:11 === [ci] control `device-irq-lossy`
08:32:11 [ci] control `device-irq-lossy`: 1 verdict(s) reached
08:32:11 === [ci] control `dump-report-relaxed`
08:32:12 [ci] control `dump-report-relaxed`: 1 verdict(s) reached
08:32:12 === [ci] control `no-preempt-guard`
08:32:13 [ci] control `no-preempt-guard`: 1 verdict(s) reached
08:32:13 === [ci] control `doorbell-kick-relaxed`
08:32:13 [ci] control `doorbell-kick-relaxed`: 1 verdict(s) reached
08:32:13 === [ci] control `push-fence-relaxed`
08:32:13 [ci] control `push-fence-relaxed`: 1 verdict(s) reached
08:32:13 === [ci] control `commit-ignores-notify`
08:32:14 [ci] control `commit-ignores-notify`: 2 verdict(s) reached
08:32:14 === [ci] control `notify-flag-load-only`
08:32:19 [ci] control `notify-flag-load-only`: 1 verdict(s) reached
08:32:19 === [ci] control `gate-fence-off`
08:32:19 [ci] control `gate-fence-off`: 1 verdict(s) reached
08:32:19 === [ci] control `poll-fire-load-store`
08:32:20 [ci] control `poll-fire-load-store`: 3 verdict(s) reached
08:32:20 === [ci] control `fault-posted-before-it-is-set`
08:32:20 [ci] control `fault-posted-before-it-is-set`: 3 verdict(s) reached
08:32:20 === [ci] control `victim-retires-mid-probe`
08:32:20 [ci] control `victim-retires-mid-probe`: 1 verdict(s) reached
08:32:20 === [ci] control `counting-allocator`
08:32:21 [ci] control `counting-allocator`: 2 verdict(s) reached
08:32:21 === [ci] control `mutate-spawn-skips-the-insert-recheck`
08:32:21 [ci] control `mutate-spawn-skips-the-insert-recheck`: 2 verdict(s) reached
08:32:21 === [ci] control `mutate-claim-teardown-always-wins`
08:32:21 [ci] control `mutate-claim-teardown-always-wins`: 1 verdict(s) reached
08:32:21 === [ci] control `mutate-kill-waits-for-its-victims`
08:32:22 [ci] control `mutate-kill-waits-for-its-victims`: 2 verdict(s) reached
08:32:22 === [ci] control `mutate-first-out-tears-down`
08:32:22 [ci] control `mutate-first-out-tears-down`: 1 verdict(s) reached
08:32:22 === [ci] control `mutate-join-collects-in-a-teardown`
08:32:22 [ci] control `mutate-join-collects-in-a-teardown`: 1 verdict(s) reached
08:32:22 === [ci] control `mutate-last-out-leaves-before-its-teardown`
08:32:23 [ci] control `mutate-last-out-leaves-before-its-teardown`: 2 verdict(s) reached
08:32:23 === [ci] control `mutate-place-skips-the-insert-recheck`
08:32:23 [ci] control `mutate-place-skips-the-insert-recheck`: 1 verdict(s) reached
08:32:23 === [ci] control `mutate-refused-spawn-keeps-the-count`
08:32:24 [ci] control `mutate-refused-spawn-keeps-the-count`: 1 verdict(s) reached
08:32:24 === [ci] control `mutate-landed-child-retires-nothing`
08:32:24 [ci] control `mutate-landed-child-retires-nothing`: 2 verdict(s) reached
08:32:24 === [ci] control `mutate-publish-before-the-children`
08:32:24 [ci] control `mutate-publish-before-the-children`: 1 verdict(s) reached
08:32:24 === [ci] control `mutate-walk-in-one-hold`
08:32:24 [ci] control `mutate-walk-in-one-hold`: 1 verdict(s) reached
08:32:24 === [ci] control `mutate-spawner-handle-after-the-landing`
08:32:25 [ci] control `mutate-spawner-handle-after-the-landing`: 2 verdict(s) reached
08:32:25 === [ci] control `mutate-spawner-handle-before-the-childs-own`
08:32:25 [ci] control `mutate-spawner-handle-before-the-childs-own`: 1 verdict(s) reached
08:32:25 === [ci] control `placement-ignores-staleness`
08:32:25 [ci] control `placement-ignores-staleness`: 1 verdict(s) reached
08:32:25 === [ci] control `mutate-session-end-forgets`
08:32:35 [ci] control `mutate-session-end-forgets`: 1 verdict(s) reached
08:32:35 === [ci] control `mutate-abort-keeps-inflight`
08:32:35 [ci] control `mutate-abort-keeps-inflight`: 1 verdict(s) reached
08:32:35 === [ci] control `mutate-no-reissue-after-loss`
08:32:36 [ci] control `mutate-no-reissue-after-loss`: 1 verdict(s) reached
08:32:36 === [ci] control `publish-relaxed`
08:32:36 [ci] control `publish-relaxed`: 1 verdict(s) reached
08:32:36 === [ci] control `no-clamp`
08:32:37 [ci] control `no-clamp`: 1 verdict(s) reached
08:32:37 === [ci] control `end-keeps-inflight`
08:32:37 [ci] control `end-keeps-inflight`: 1 verdict(s) reached
08:32:37 === [ci] userland/acpiserver
08:32:37 [ci] userland/acpiserver: cargo test --manifest-path userland/acpiserver/Cargo.toml
08:32:37 === [ci] userland/acpiserver/aml
08:32:39 [ci] userland/acpiserver/aml: cargo test --manifest-path userland/acpiserver/aml/Cargo.toml
08:32:39 === [ci] userland/calc
08:32:40 [ci] userland/calc: cargo test --manifest-path userland/calc/Cargo.toml
08:32:40 === [ci] userland/compositor/desktop
08:32:40 [ci] userland/compositor/desktop: cargo test --manifest-path userland/compositor/desktop/Cargo.toml
08:32:40 === [ci] userland/diskserver
08:32:40 [ci] userland/diskserver: cargo test --manifest-path userland/diskserver/Cargo.toml
08:32:40 === [ci] userland/fileserver
08:32:54 [ci] userland/fileserver: cargo test --manifest-path userland/fileserver/Cargo.toml
08:32:54 === [ci] userland/logkeeper
08:32:55 [ci] userland/logkeeper: cargo test --manifest-path userland/logkeeper/Cargo.toml
08:32:55 === [ci] userland/netstack
08:32:55 [ci] userland/netstack: cargo test --manifest-path userland/netstack/Cargo.toml
08:32:55 === [ci] userland/netstack/mdns
08:32:56 [ci] userland/netstack/mdns: cargo test --manifest-path userland/netstack/mdns/Cargo.toml
08:32:56 === [ci] userland/netstack/node
08:32:57 [ci] userland/netstack/node: cargo test --manifest-path userland/netstack/node/Cargo.toml
08:32:57 === [ci] userland/pkg
08:32:58 [ci] userland/pkg: cargo test --manifest-path userland/pkg/Cargo.toml
08:32:58 === [ci] userland/soundserver
08:32:58 [ci] userland/soundserver: cargo test --manifest-path userland/soundserver/Cargo.toml
08:32:58 === [ci] userland/soundserver/mixer
08:33:02 [ci] userland/soundserver/mixer: cargo test --manifest-path userland/soundserver/mixer/Cargo.toml
08:33:02 === [ci] userland/sshserver
08:33:04 [ci] userland/sshserver: cargo test --manifest-path userland/sshserver/Cargo.toml
08:33:04 === [ci] userland/symbolize
08:33:05 [ci] userland/symbolize: cargo test --manifest-path userland/symbolize/Cargo.toml
08:33:05 === [ci] the apps for linux
08:33:08 [ci] the apps for linux: 10 app(s) pass `cargo check --target x86_64-unknown-linux-gnu`; userland/doom, userland/proctest, userland/shell, userland/terminal, userland/toybox not attempted, as their manifests declare
08:33:08 === [ci] the apps for macos
08:33:12 [ci] the apps for macos: 10 app(s) pass `cargo build`; userland/doom, userland/proctest, userland/shell, userland/terminal, userland/toybox not attempted, as their manifests declare
08:33:12 === [ci] the apps for windows
08:33:17 [ci] the apps for windows: 10 app(s) pass `cargo check --target x86_64-pc-windows-msvc`; userland/doom, userland/proctest, userland/shell, userland/terminal, userland/toybox not attempted, as their manifests declare
08:33:17 === [ci] the toyos SDK
08:33:17 [ci] the toyos SDK: cargo test -p toyos
08:33:17 === [ci] nothing left in $TMPDIR or /tmp
08:33:17 [ci] nothing left in $TMPDIR or /tmp: every test took its scratch with it
08:33:17 [ci] Host: 78 step(s), all green

cargo run -- --build-only (EXIT=0): its last lines

08:35:01 root: symlink 'bin/stats' -> '/system/bin/toybox'
08:35:01 root: symlink 'bin/tone' -> '/system/bin/toybox'
08:35:01 Signed with this checkout's throwaway key SHA256:oHE+/kD905qIBlZwnccj27R86SMHQpWKF5MLxN9njiY at version 1791621198
08:35:02 Build finished.
Boot image: <worktree>/target/bootable.img

cargo run -- --build-only --arch aarch64 (EXIT=0): its last lines

08:37:12 root: symlink 'bin/stats' -> '/system/bin/toybox'
08:37:12 root: symlink 'bin/tone' -> '/system/bin/toybox'
08:37:12 Signed with this checkout's throwaway key SHA256:oHE+/kD905qIBlZwnccj27R86SMHQpWKF5MLxN9njiY at version 1791621303
08:37:13 Build finished.
Boot image: <worktree>/target/bootable.aarch64.img

whole guest suite, cargo test --test toyos-build (EXIT=0): its RUN, PASS and FAIL lines and summary; uptime before and after

10:37  up 10 days, 22:21, 6 users, load averages: 46.48 47.42 50.24
08:37:26   RUN   iommu_virtio_platform
08:37:26   RUN   netstack_socket_churn
08:37:26   RUN   https_fetch
08:37:26   RUN   nested_nmi_is_loud
08:37:26   RUN   machine_shutdown
08:37:26   RUN   acpi_power_button
08:37:26   RUN   acpi_mediated_access
08:37:26   RUN   acpi_supply_outlives_holder
08:37:26   RUN   acpi_lock_given_back_on_one_cpu
08:37:26   RUN   netstack_streams
08:37:26   RUN   netstack_streams_e1000e
08:37:26   RUN   libc_sockets
08:38:50   PASS  nested_nmi_is_loud  (8s)
08:38:50   RUN   machine_shutdown_short_stop
08:38:54   PASS  machine_shutdown  (13s)
08:38:54   RUN   bar_map_again
08:38:55   PASS  acpi_power_button  (14s)
08:38:55   RUN   console_image_boots
08:38:57   PASS  acpi_supply_outlives_holder  (56s)
08:38:57   RUN   nvme_disk_keeps_log_and_home
08:38:58   PASS  acpi_lock_given_back_on_one_cpu  (57s)
08:38:58   RUN   usb_keyboard_rollover
08:38:59   PASS  acpi_mediated_access  (16s)
08:38:59   RUN   screen_panic_muted
08:39:01   PASS  netstack_socket_churn  (18s)
08:39:01   RUN   screen_fatal_behind_a_painter
08:39:03   PASS  netstack_streams_e1000e  (21s)
08:39:03   RUN   screen_fatal_halt_composited
08:39:03   PASS  netstack_streams  (19s)
08:39:03   RUN   screen_loader_clears
08:39:07   PASS  https_fetch  (22s)
08:39:07   RUN   virt_early_panic
08:39:13   PASS  libc_sockets  (34s)
08:39:13   RUN   virt_early_fault
08:39:14   PASS  screen_panic_muted  (15s)
08:39:14   RUN   virt_el2_drop
08:39:20   PASS  console_image_boots  (17s)
08:39:20   RUN   virt_user_mode
08:39:20   PASS  usb_keyboard_rollover  (22s)
08:39:20   RUN   virt_timer_preempts
08:39:21   PASS  screen_fatal_behind_a_painter  (21s)
08:39:21   RUN   virt_irq_storm
08:39:26   PASS  machine_shutdown_short_stop  (22s)
08:39:26   RUN   virt_timer_floor
08:39:26   PASS  screen_loader_clears  (23s)
08:39:26   RUN   virt_fp_isolation
08:39:29   PASS  bar_map_again  (21s)
08:39:29   RUN   virt_first_entry
08:39:30   PASS  screen_fatal_halt_composited  (20s)
08:39:30   RUN   virt_unmap_touch
08:39:35   PASS  iommu_virtio_platform  (54s)
08:39:35   RUN   virt_debug_refused
08:39:55   PASS  nvme_disk_keeps_log_and_home  (58s)
08:39:55   RUN   virt_readonly_copyout
08:41:05   PASS  virt_early_fault  (2s)
08:41:05   RUN   virt_ring0_timer_in_syscall
08:41:05   PASS  virt_early_panic  (2s)
08:41:05   RUN   virt_mask_windows
08:41:08   PASS  virt_user_mode  (4s)
08:41:08   RUN   virt_smp
08:41:08   PASS  virt_el2_drop  (6s)
08:41:08   RUN   virt_el1_smp
08:41:08   [virt] [ 3.367 cpu0 kernel] timer-floor: PASS span=240 floor=240 ticks: the comparator past the counter it was set from
08:41:08   PASS  virt_timer_floor  (4s)
08:41:08   RUN   virt_failed_ap_leaves_no_hole
08:41:27   PASS  virt_timer_preempts  (4s)
08:41:27   RUN   virt_fatal_halts_the_others_first
08:41:27   PASS  virt_unmap_touch  (110s)
08:41:27   RUN   virt_reboot
08:41:28   PASS  virt_fp_isolation  (113s)
08:41:28   RUN   virt_off_names_the_cpus_left_on
08:41:29   PASS  virt_first_entry  (110s)
08:41:29   RUN   virt_reboot_refused_without_psci
08:41:31   [virt] [25.425 cpu0 kernel] irq-storm: PASS sgis=3170740/3170740 ticks=1000: the timer fired through the flood, and every SGI sent was taken
08:41:31   PASS  virt_irq_storm  (26s)
08:41:31   RUN   virt_jobs_at_el2
08:41:35   PASS  virt_readonly_copyout  (99s)
08:41:35   RUN   virt_random_differs
08:41:35   PASS  virt_debug_refused  (120s)
08:41:35   RUN   virt_no_seed_refused
08:41:35   PASS  virt_ring0_timer_in_syscall  (30s)
08:41:38   PASS  virt_reboot_refused_without_psci  (4s)
08:41:41   PASS  virt_reboot  (7s)
08:41:41   PASS  virt_jobs_at_el2  (10s)
08:41:42   PASS  virt_no_seed_refused  (8s)
08:41:43   PASS  virt_random_differs  (9s)
08:42:35   PASS  virt_failed_ap_leaves_no_hole  (16s)
08:42:36   PASS  virt_mask_windows  (34s)
08:42:36   PASS  virt_fatal_halts_the_others_first  (8s)
08:42:36   PASS  virt_el1_smp  (32s)
08:42:37   PASS  virt_smp  (32s)
08:42:41   PASS  virt_off_names_the_cpus_left_on  (17s)
08:42:41   --- 48 guests, 28 of them not the shipping kernel, 3 kernel build(s): ["", "boot-actuators,test-actuators", "mask-windows"]
08:42:41 test result: ok. 45 passed, 45 total (314.3s; workers: 2027s building, 1358s testing)
10:42  up 10 days, 22:26, 6 users, load averages: 74.92 65.67 57.65

git diff ae2aee73c 24e6fb655 -- bootloader toyos-sha2

(empty)

@Japabu
Japabu added this pull request to the merge queue Oct 10, 2026
Merged via the queue into main with commit d5bc4df Oct 10, 2026
3 checks passed
@Japabu
Japabu deleted the wt/toyos-sha2 branch October 10, 2026 10:01
Japabu added a commit that referenced this pull request Oct 10, 2026
…812), TCP window scaling (#820) and the stop's hold of the console wire (#805), into virtio-sound and the shared PCI claim

Both conflicts are two additions at one site, and both sides are kept whole:
- tests/common/qemu.rs: this branch's Profile::HeadlessVirtioGpu and main's
  Profile::HeadlessUsbSpare, each in the enum, the x86-64 arm of arch() and
  shape().
- tests/toyos.rs: RUST_SKIP takes both virtio_sound_counts and usbd_spare;
  run_machine_test takes this branch's virtio_sound_counts arm beside main's
  machine_shutdown_wire_* , usbd_drives_the_spare and usb_keyboard_rollover.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Japabu added a commit that referenced this pull request Oct 10, 2026
…h toyos-sha2

- userland/update/src/main.rs: the branch's stream_root over the block
  service's Disk (STREAM_BLOCKS of BLOCK bytes), hashed with main's
  toyos_sha2::Sha256 in place of sha2.
- tests/toyos.rs: both sides' RUST_SKIP entries, MACHINE_TESTS entries,
  dispatch arms and functions kept, the branch's first; the branch's
  update_writes_the_idle_slot_through_the_block_service keeps its own close.
- Cargo.lock: main's, regenerated by cargo against the merged manifests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Japabu added a commit that referenced this pull request Oct 10, 2026
…'s host-side hash is toyos-sha2's

main replaced the sha2 crate with toyos-sha2 (#812), so the harness's
digest of the binary it puts on ROOT is now toyos_sha2::Sha256, as the
HTTPS test's already is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Japabu added a commit that referenced this pull request Oct 10, 2026
… batch: the icons' and wallpaper's digests hash with toyos-sha2

Cargo.toml keeps both sides' entries: main's toyos-sha2 and usbd members
and toyos-sha2 dependency, and the batch's removal of `image`. `sha2` was
replaced by toyos-sha2 on main and left in place on the batch, whose
#813 and #814 added two tests hashing with it; as main meant every
SHA-256 the build takes to be toyos-sha2's, those two tests now hash
with toyos-sha2 and the root manifest drops `sha2`.

Cargo.lock is the batch's, re-resolved by `cargo metadata --offline`;
its delta from the batch's head is exactly main's delta from the merge
base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Japabu added a commit that referenced this pull request Oct 10, 2026
, #826, #835, #833, #831 and #822, into wt/toyos-netperf

No hunk conflicted. userland/netstack/src/main.rs took both sides: main's
removal of `mod device` and the branch's batched `node.receive` and its
module-doc line. The TCP window-scaling and loss-probe commits main
carries were already in the branch from #820, so their files merged to
main's text plus the branch's own delta. Both lockfiles are main's and
pass `cargo metadata --locked`. The branch's new issue still cites
`VirtioNet::poll_rx` and `toyos_i219::RX_BUDGET` as they stand on main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017cSFvbD35xJ2kGANVdm23C
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant