evidence · 10.3 KiB

boot-boundary-host-2026-10-03.md

Committed at docs/evidence/mainline-system-trial/boot-boundary-host-2026-10-03.md. This is what grounds the requirements that cite it.

Open raw source

Optional mainline boot-boundary markers — host proof

2026-10-03 UTC. Branch mainline-boot-boundary-trace, base 6e4a82f9f965fb4125edb819efbe3a53136d381b, worktree /home/jadams/tmp/k230-mainline-boot-boundary.

This is host source/API/object/evaluation evidence. Complete kernel build, artifact inspection, marker output, ordinary init/root/login, automatic return and deliberate glass touch are UNVERIFIED. Task 5b.5 remains open. No board, UART, cross-kernel build or protected card operation was performed.

Scope and source

The optional kernelMainlineBootTrace applies only nix/patches/mainline/k230-boot-trace.patch to the already assembled DRM, restart and five-clock SD1 source. Derivation inspection confirms its input is /nix/store/l0j3rf11mr65wl5x88a9zzma45ciz687-linux-mainline-k230-drm-src; upstream pin remains 72d3fcf802c45d00b300f25b848a93c3a2bd7c7e. Unpatched init/main.c SHA-256 is e020a85da2661817a61a4d15dff0e482ecdd687f0f77d24b2bd74987a6851414.

The new k230-mainline-boot-trace system and kernelMainlineBootTraceTrialBootFiles reuse the ordinary DRM trial builder. They remove exactly console=tty0 and append k230.boot_trace=1, preserving console=ttyS0,115200n8, the existing root/logging controls and matching sole system init. No earlycon, keep_bootcon, clock bypass, observer unit or debug shell is added. Existing kernel/system/console/observer outputs and controllers are unchanged. The ordinary trial controller supplies its existing qualified fsck/root-growth/registration controls; these are not production acceptance.

The marker helper and counter/enable flag have regular lifetimes. Only the boot option parser is __init. include/linux/console.h:606–607 declares the emergency API (disabled-PRINTK stubs at 670–671). Each enabled call enters nbcon emergency state, emits one public pr_info, then exits. No blocking operation is inside that interval. kernel/printk/nbcon.c:1709–1758 documents the emergency behavior; it can change flushing and scheduling. A marker can itself block or fail to become visible. This is instrumentation, not a fix or an autonomous hang-recovery mechanism.

There are 20 fixed sites, ten enter/exit pairs: basic setup, initcalls, initramfs wait, root-console open, init accessibility, namespace preparation, integrity keys, async synchronization, initmem/readonly cleanup and init exec. Namespace markers appear only on the original failed-init-access branch; init exec can repeat on original fallback paths. At most 32 records are emitted, with K230_BOOT_TRACE_V1 seq=N step=<fixed label>. The original kernel operations, branches and exec return values remain in order.

An enter-only observation identifies the last visible boundary, not a stack or a root cause. A pair completed only proves that bracketed call returned. Even init-exec-exit does not prove userspace readiness. Work before the first basic-setup marker is not covered. The KUnit call sits between basic-setup-exit and initramfs-wait-enter; the prepared configuration used for the object check has # CONFIG_KUNIT is not set. Recheck the actual built configuration before interpreting that gap. No raw bootargs, pointers, private log contents or counter dumps are emitted.

Narrow commands and results

The real patched object was built using a private copy of already prepared headers/configuration from /home/jadams/tmp/k230-mainline-restart/.scratch/mainline-restart-object/run.CuXzA8/build. The original prepared tree was not changed. The source was the restored exact l0j3… tree; a scratch external Kbuild directory contained the patched main.c and obj-y += main.o (no MODULE define).

make -C /nix/store/l0j3rf11mr65wl5x88a9zzma45ciz687-linux-mainline-k230-drm-src \
  O=/home/jadams/tmp/k230-boot-trace-object/build \
  M=/home/jadams/tmp/k230-boot-trace-object/module ARCH=riscv \
  CROSS_COMPILE=/nix/store/4j2mwxqjvnyr6da0925sp0bm4jaj5r5i-riscv64-unknown-linux-gnu-gcc-wrapper-15.3.0/bin/riscv64-unknown-linux-gnu- \
  W=1 main.o

Passed, ELF64 little-endian RISC-V relocatable object. readelf -sW/-SW places k230_boot_trace_mark in .text.unlikely, both state variables in .sbss, and only k230_boot_trace_setup in .init.text. Both emergency APIs remain resolved-at-link references. No full kernel link or execution occurred. Initial LLVM=1 attempt failed because the cached GCC configuration supplied Clang-unsupported -fmin-function-alignment=8 and -fconserve-stack; the matching GCC 15.3 check above then passed. Prepared config SHA-256: 40fee52e7dc0d13cc9cd98c51925da55f99c0a4a85c74b390715c264d88cf758. Patched C: ce95e6b40b1cbdebff28f4f3434afb87a51e207cf4e7928588b820904e16520d. Object: 028eba4643b06e3a972e928a7ee732591191824035f086babfe969bf990cf45e. This checks this translation unit against prepared headers, not the final Nix kernel configuration/link.

Offline nix eval --offline --no-write-lock-file --json --impure evaluated .packages.x86_64-linux and the optional system. It confirmed uname 7.3.0-rc5, selected system kernel equals the optional kernel, and params:

consoleblank=0 console=ttyS0,115200n8 root=fstab loglevel=4
lsm=landlock,yama,bpf loglevel=7 k230.boot_trace=1

Evaluated derivations (not built outputs):

The same offline expression compared drvPaths with builtins.getFlake "git+file:///home/jadams/tmp/k230-mainline-boot-boundary?rev=6e4a82f9f965fb4125edb819efbe3a53136d381b". All nine existing package identities are equal: kernel, kernelMainline, kernelMainlineDrm, kernelMainlineDrmTrialBootFiles, kernelMainlineUartObserverBootFiles, toplevel, toplevel-mainline-console, toplevel-mainline-drm-trial, toplevel-mainline-uart-observer. Evaluation invoked no source realization or kernel build.

Reproducible evaluation commands (run from this worktree; no build):

nix eval --offline --no-write-lock-file --json --impure --expr '
  let f = builtins.getFlake (toString /home/jadams/tmp/k230-mainline-boot-boundary);
      p = f.packages.x86_64-linux;
      c = f.nixosConfigurations.k230-mainline-boot-trace.config;
  in assert p.kernelMainlineBootTrace.drvPath == c.boot.kernelPackages.kernel.drvPath; {
    kernel = p.kernelMainlineBootTrace.drvPath;
    source = p.kernelMainlineBootTrace.src.drvPath;
    system = c.system.build.toplevel.drvPath;
    bundle = p.kernelMainlineBootTraceTrialBootFiles.drvPath;
    params = c.boot.kernelParams;
    uname = c.boot.kernelPackages.kernel.version;
  }'
nix eval --offline --no-write-lock-file --json --impure --expr '
  let old = builtins.getFlake "git+file:///home/jadams/tmp/k230-mainline-boot-boundary?rev=6e4a82f9f965fb4125edb819efbe3a53136d381b";
      new = builtins.getFlake (toString /home/jadams/tmp/k230-mainline-boot-boundary);
      names = [ "kernel" "kernelMainline" "kernelMainlineDrm"
        "kernelMainlineDrmTrialBootFiles" "kernelMainlineUartObserverBootFiles"
        "toplevel" "toplevel-mainline-console" "toplevel-mainline-drm-trial"
        "toplevel-mainline-uart-observer" ];
      paths = f: builtins.listToAttrs (map (name: {
        inherit name; value = f.packages.x86_64-linux.${name}.drvPath;
      }) names);
  in assert paths old == paths new; { before = paths old; after = paths new; }'
nix derivation show /nix/store/cj04yq9adb0647rla5gxa142pcp9v602-linux-mainline-k230-boot-trace-src.drv

The last command exposes the final patch derivation’s env.src for the exact DRM source input check. The evaluated new config path is /nix/store/c55hagx8ss9vkpgfzpc24k2jb8qnqg8q-linux-config-riscv64-unknown-linux-gnu-7.3.0-rc5; it has not been realized by this work, so the final built KUnit/configuration check remains with the build owner.

Remaining operator gate

After review, the build-slot owner must build nix build .#kernelMainlineBootTraceTrialBootFiles --no-link --print-out-paths, inspect the exact resulting bundle with tools/mainline-drm-trial-inspect.py, verify matching Image/system/initrd/DT bootargs and configuration, and create its exact controller manifest/protected normal report. Physical use remains operator-only, with a reserved board/UART and protected staging/preflight.

The existing ordinary controller command is:

python3 tools/mainline-drm-system-trial.py begin --bundle <exact-built-bundle> \
  --manifest <private-exact-manifest> --normal-report <private-normal-report> \
  --state <private-state> --log <private-uart-log> --result <private-result>

Keep the original 180-second readiness bound and fail-closed candidate/root checks. No prompt/receipt means no further input or guessed reboot. Preserve raw private output, report the last complete marker and any unknown boundary; operator reset recovery may still be required. If readiness returns, root and real glass touch still need their existing independent checks and protected normal postflight. No task is completed by this host increment.