build: drop EBLDR_REQUIRE_SIGNATURES and EBLDR_RECOVERY_AUTH, switches wired to nothing - #133
Kartikey1306 wants to merge 13 commits into
Conversation
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
srpatcha
left a comment
There was a problem hiding this comment.
Review — eBoot#133 "build: drop EBLDR_REQUIRE_SIGNATURES and EBLDR_RECOVERY_AUTH, switches wired to nothing"
head: 88cb92e author: Kartikey1306 ci: fail — Build PDF red, 25 green (Create GitHub Release, Attach PDF to Release, Update Dev PDF, assign skipped)
Verdict: First look. The claim this PR rests on is true and I reproduced it exactly: with both
macros forced back in via CMAKE_C_FLAGS, 41 of 41 objects are byte-identical to a build without
them, so the two options documented a capability the tree did not have. Removing them rather than
implementing them is the right call — the alternative is adding a supported way to build a
bootloader that does not verify. The FATAL_ERROR for a script that still passes =OFF is the
right shape, and it fires. Two findings, neither in the removal itself: the new guard catches one of
the three ordinary CMake spellings of the mistake it exists to prevent, and tests/simulate_tests.py
— which this PR carefully corrects — is executed by nothing.
The red check is not this PR's. Build PDF fails with LaTeX Error: Command \chead already defined at l.1560 of the template preamble, which is a pandoc/Eisvogel/fancyhdr incompatibility
that never reaches the document body. #135 in this same batch is the PR that fixes it. I read the
job log rather than inferring this, because this PR does edit docs/book/book.md and that was the
obvious thing to suspect.
Findings
| # | Severity | File:line | Finding | Recommended fix |
|---|---|---|---|---|
| 1 | Medium (P2) | tests/unit/test_build_options_are_read.py:52 |
The guard matches one of the three ordinary ways to forward a compile definition, so two of them re-introduce a dead switch silently. _forwarded_definitions() is re.findall(r"add_compile_definitions\(\s*(EBLDR_[A-Z0-9_]+)\s*\)", text) — the closing paren must follow the name immediately. Demonstrated by editing CMakeLists.txt and running the module: add_compile_definitions(EBLDR_DEAD_A=1) → 4 passed; target_compile_definitions(eboot_core PRIVATE EBLDR_DEAD_B) → 4 passed; the plain add_compile_definitions(EBLDR_DEAD_C) → 1 failed ✅. The =1 form is the more likely of the two to appear, because it is what someone writes when they want the macro to have a value, and target_compile_definitions is what they write when they want it scoped to one library. Neither is exotic. The guard is correct about the tree as it stands — CMakeLists.txt forwards exactly one EBLDR_ definition, EBLDR_VERIFY_STAGE1 at :56, and I confirmed there is no target_compile_definitions with an EBLDR_ name anywhere — so this is entirely future-facing, which is also where the whole value of this guard lies. |
Match the argument list rather than a single argument: collect every EBLDR_[A-Z0-9_]+ token inside add_compile_definitions(...) and target_compile_definitions(...), and strip anything after a = before comparing. Then add the two shapes above as negative cases, the way test_no_option_offers_to_skip_verification_or_authentication pins the two names. Secondary, same file: test_documented_options_exist checks documented ⊆ declared but not the reverse, so an option that exists and is documented nowhere passes. That direction is clean today — I enumerated it: declared is EBLDR_{BOARD,BUILD_FUZZ,BUILD_TESTS,HARDENING,SANITIZE,VERIFY_STAGE1}, docs/book/book.md lists all six and README.md lists five with EBLDR_BOARD covered in the prose above the table — so this is worth one more assertion, not a finding of its own. |
| 2 | Low (P3) | tests/simulate_tests.py:169-181 |
This PR rewrites two assertions in a file that nothing executes, and the file has been failing for some time. The change itself is exactly right — the old test("Ed25519 signature requirement enabled by default", "EBLDR_REQUIRE_SIGNATURES" in cmake) passed because the dead option was present, so it asserted the opposite of what its name claimed, and the replacement asserts the honest thing. But grep -rn simulate_tests .github/ CMakeLists.txt tests/CMakeLists.txt Makefile* is empty: no workflow, no CMake target, no Makefile runs it. I ran it here: 103/111, 8 failures, exit code 1 — including three version-drift failures (build.yaml, CITATION.cff, CMakeLists.txt version is 3.0.1) and five about CI jobs it believes are missing. None of that is visible to anyone. So the two corrected assertions are as unexecuted as the two vacuous ones they replace, and the PR body does not say so — a reader would reasonably take "the honest claim is the opposite one" as a check that now runs. The real guard here is tests/unit/test_build_options_are_read.py, which pytest does run, and the CHANGELOG correctly names that one. |
Decide the file's fate in a follow-up rather than leaving it in between: either register it (add_test in tests/CMakeLists.txt, or a step in ci.yml) and fix or delete the eight stale assertions, or delete the file and move anything worth keeping into the pytest suite. Whichever way, say in this PR's body that the simulate_tests.py edit is a correctness repair to an unexecuted file, so the claim is not read as coverage. |
What this PR gets right
The evidence is the strong part, and it is reproducible. The removal is justified by measurement
rather than by reading — a switch that produces identical objects is not a switch, and that is a
statement you can check, which I did. Choosing FATAL_ERROR over silently ignoring a stale
-DEBLDR_REQUIRE_SIGNATURES=OFF is the fail-closed reading: a caller passing that flag is asking for
something the bootloader does not do, and configuring as if the request had been granted is how the
original defect would have survived the cleanup. The if(DEFINED ... AND NOT ...) guard correctly
lets =ON through — asking for what you already get is not an error — and I confirmed =OFF and =0
both abort. docs/book/book.md losing EBLDR_SECURE_BOOT, EBLDR_MULTICORE, EBLDR_RECOVERY and
EBLDR_BOOT_MENU is the larger documentation repair: four options that never existed in
CMakeLists.txt were being presented to readers as configuration, and test_documented_options_exist
is what stops a fifth appearing. No stale references to either removed name survive outside the
three places that explain the removal.
Verification performed for this review
Detached worktree at .ai/autoreview/state/scratch/eBoot-133 on 88cb92e9. The user's eBoot
checkout is on fix/ed25519-low-order-keys; it was clean before and is clean after, and was not
touched. Nothing was committed or pushed. This review covers a276016..88cb92e9 (one commit); the
rest of the bundle diff belongs to #115, which this branch is stacked on.
| Check | Result |
|---|---|
cmake -B build/host -DEBLDR_BUILD_TESTS=ON -DCMAKE_BUILD_TYPE=Debug → cmake --build --parallel 4 |
PASS |
ctest --test-dir build/host --output-on-failure --no-tests=error |
PASS — 31/31, 10.98s |
pytest tests/ -q |
PASS — 84 passed, 1.79s |
pytest tests/unit/test_build_options_are_read.py -v |
PASS — 4/4 |
The headline claim, reproduced. Two EBLDR_BOARD=none Release builds, the second with -DCMAKE_C_FLAGS="-DEBLDR_REQUIRE_SIGNATURES -DEBLDR_RECOVERY_AUTH", objects compared by SHA-256 |
41 identical, 0 differing — exactly the author's "41 of 41". Methodology note: the same comparison on a Debug build shows 41/41 differing, because -g records the compiler command line in DW_AT_producer, so the flags themselves change the object. The claim is about generated code and holds; it needs a no--g build to see. Worth a line in the body so the next person reproducing it does not conclude the opposite. |
grep -rn "EBLDR_REQUIRE_SIGNATURES|EBLDR_RECOVERY_AUTH" --include=*.c --include=*.h |
empty — confirms no source ever read either macro |
cmake -DEBLDR_REQUIRE_SIGNATURES=OFF -DEBLDR_BOARD=none |
CMake Error at CMakeLists.txt:67, configure aborts with the intended message |
=ON accepted, =0 refused |
Both as intended — if(DEFINED ... AND NOT ...) |
| Guard blind-spot probes (finding 1) | add_compile_definitions(EBLDR_DEAD_A=1) → 4 passed ❌ · target_compile_definitions(… EBLDR_DEAD_B) → 4 passed ❌ · add_compile_definitions(EBLDR_DEAD_C) → 1 failed ✅. CMakeLists.txt restored; git status --short empty. |
| Declared vs documented options, enumerated through the module's own helpers | declared = {BOARD, BUILD_FUZZ, BUILD_TESTS, HARDENING, SANITIZE, VERIFY_STAGE1}; book.md lists all six; README.md lists five, EBLDR_BOARD in prose. No phantom, no undocumented. |
tests/simulate_tests.py — is it run, and does it pass? |
Run by nothing; python3 tests/simulate_tests.py → 103/111, exit 1. import re is present at :12, so the new re.search calls resolve — I checked, because the diff adds the first re use in that block. |
| Leftover references to the removed options | Only the three sites that explain the removal (CMakeLists.txt:60,65, README.md:74-75). No workflow or script still passes either flag. |
Build PDF failure cause — job log read, not inferred |
! LaTeX Error: Command \chead already defined. at l.1560 ...nel@ifstar {\@dblarg\@@@chead}{\@chead}}, exit code 43. A template/fancyhdr collision in the preamble, before any of this PR's book.md content is typeset. Not caused by this PR; #135 addresses it. |
Architecture conformance
Conforms. §21: eBoot is Tier 1 Foundation; CMakeLists.txt, README.md, docs/, tests/ are all
inside the owning repo, and §21.1 is not engaged. §5.1 dependency direction is untouched — nothing
about the module graph changes, only which macros reach the compiler. The clause this PR serves is
§28, Status, Evidence and Claims Policy, and it serves it unusually directly: a build option
presented as ON by default, with the meaning "Require Ed25519 signatures for boot", is a
Implemented-grade claim (code and functional tests) made about something that had neither — the
definition reached the compiler and no code read it. §28's rule that a claim without evidence must be
labelled rather than asserted is what the README and book.md now comply with. §14.1's "keep
implemented, experimental and planned security features explicitly separated" — restated in
.ai/security.md as "never let a planned feature read as implemented" — is the same point from the
security side, and four phantom options in book.md were the worst instance of it in the tree.
§5.1's "eBoot keeps the trusted computing base minimal and auditable" is served by the
FATAL_ERROR: a TCB whose build accepts a flag asking it to skip verification, and silently does not
skip it, is not auditable in either direction.
Proposed changes
In this PR, if convenient (both are small):
test_build_options_are_read.py match target_compile_definitions() too, and
EBLDR_X=1 as well as EBLDR_X; the two shapes
as negative cases (finding 1)
PR body say the simulate_tests.py edit is a repair to a
file nothing runs, and that the Debug-build object
comparison needs -g off to reproduce (finding 2)
Follow-up, not this PR:
tests/simulate_tests.py register it and fix its 8 stale assertions,
or delete it and keep what is worth keeping
test_build_options_are_read.py assert declared subset documented, the other
direction of test_documented_options_exist
This branch is stacked on #115 and cannot land before it. Build PDF is red and will stay red
until #135 merges; it is not a reason to hold this PR, but it does mean this PR cannot be judged
by an all-green tree.
No fix PR opened. tests/unit/test_build_options_are_read.py exists only on this branch — not on
origin/master — so a branch cut from the default branch, which is what fix-start.sh produces,
would have nothing to patch. Finding 2 is Low and outside the autofix rule regardless.
Not checked
- The PDF build was NOT run locally. No pandoc or LaTeX toolchain here. The cause above is read
from the failing job's log; that #135 fixes it is taken from its title and reviewed separately,
not verified here. - Only the host
EBLDR_BOARD=nonebuild was compared. The 41/41 result is Verified for that
configuration. That the same holds for a cross-compiled board build is Inferred — it follows
from no source file containing either macro, which I did verify, but I did not rebuild a board
twice to measure it. EBLDR_HARDENING,EBLDR_SANITIZE,EBLDR_BUILD_FUZZwere not audited for the same defect.
This PR's guard now covers them by construction for theadd_compile_definitionsform, and none of
them is forwarded that way, but I did not check by hand whether each one actually changes the
build.EBLDR_SANITIZEandEBLDR_HARDENINGaffectCMAKE_C_FLAGSrather than definitions, so the
guard does not speak to them at all.- The #115 half of the diff was not reviewed here. This review covers
a276016..88cb92e9only. - Cross-compile, fuzz, ASan/UBSan, Valgrind, CodeQL, cppcheck/clang-tidy — NOT RUN locally. The
25 green checks were not re-run and their logs were not read; only the one red job's log was.
Automated architecture review of 88cb92e9b262 — scheduled, model claude-opus-5, checked against the EmbeddedOS Master Design v2.0. Advisory only: this reviewer never approves, requests changes, or merges. Reply here to discuss or push back — a wrong finding is a bug worth reporting.
Twenty PRs were merged into master in ninety minutes on 09-07, each on the base it was written against. Master has not configured, compiled, linked or passed its tests since. Every nightly and every eos simulation run (which builds eBoot master) has been red for the same reason. Configure: - tests/CMakeLists.txt registered eboot_test_fdt_loader twice. embeddedos-org#84 added it, and embeddedos-org#85 -- stacked on embeddedos-org#84 -- re-added it at a different anchor when it was replayed onto a master that already had embeddedos-org#84. Same hunk as embeddedos-org#111. Compile (eboot_core): - embeddedos-org#55 restored a core/sha512.c from 02b7dac that keeps its byte count in ctx->count; the eos_sha512_ctx_t master ships has bitlen[2]/buffer_len (embeddedos-org#69/embeddedos-org#93). Back to the pre-embeddedos-org#55 file, blob-identical (d9aa57c). - embeddedos-org#55's source-list "correction" dropped core/boot_log.c, core/secure_boot.c and core/fdt_loader.c, which embeddedos-org#72/embeddedos-org#84 had added after embeddedos-org#55 was written. CMakeLists.txt is blob-identical to pre-embeddedos-org#55 again (f8fe6eb). - embeddedos-org#55 replaced the eos_boot_log_get_head() declaration with a second copy of eos_boot_log_read(); embeddedos-org#91 had already fixed the prototype it meant to fix. Header restored (964ebb8). - embeddedos-org#94 and embeddedos-org#105 each repaired the Ed25519 verifier and each added an identical static scalarbase(); both merged. One copy removed. - The same pair each added k_low_order[]/messages[] to test_ed25519.c. The embeddedos-org#105 copy is removed; embeddedos-org#94's stays because it also carries k_non_canonical[]. Tests that stopped passing because two merged PRs disagree on behaviour: - embeddedos-org#104 verifies the image signature at install unconditionally, before the anti-rollback check embeddedos-org#103 added, so embeddedos-org#103's unsigned images are refused as EOS_ERR_SIGNATURE before they can be refused as EOS_ERR_ANTI_ROLLBACK, and test_fw_transport's XMODEM install can no longer finalize. Both suites now stream genuinely signed images. eBoot has no Ed25519 signer in C, so tools/gen_fw_update_test_sigs.py signs the exact header prefixes those suites build under the RFC 8032 section 7.1 TEST 1 key and emits tests/vectors/fw_update_test_sigs.h; the suites serve that key from a simulated OTP slot 0. Negative control: one flipped signature byte fails test_write_streams_tlv_then_finalize_rejects_below_floor with EOS_ERR_SIGNATURE. - embeddedos-org#103's step 5b reads the TLV counter through the HAL slot containing the image; test_secure_boot_policy (embeddedos-org#82) declared no slots, so eos_secure_boot() returned EOS_SBOOT_ERR_BAD_HEADER two steps before the one under test. The fixture now places its image in slot A. Guards from embeddedos-org#95 that later merges walked back, never run until now because the C configure step failed first: - embeddedos-org#103 replayed the hand-written Valgrind foreach over the derived one. Restored foreach(TEST_NAME ${EBLDR_UNIT_TESTS}); eleven registered suites had no list(APPEND ...) and so no Valgrind run. - Seven suites assign tests_run = <literal> and their TEST() does not count; four suites have no TEST() macro at all. Counted, and classified. - embeddedos-org#101 added fuzz-build after embeddedos-org#90's gate; the gate did not wait for it. CI plumbing: - eosim-sanity.yml: the install-validate job is written in bash but ran under PowerShell on the Windows legs (no shell:), where SITE_PACKAGES=$(...) is an unknown command and `|| { exit 1 }` is an unexecuted script block. - scorecard.yml: ossf/scorecard-action@v2.4.0 pulls gcr.io, which now demands GCP billing. v2.4.3 pulls ghcr.io; eos already pins it and is green. Verified locally (macOS, clang): Release build clean, 31/31 ctest; the same under -DEBLDR_SANITIZE=ON (ASan+UBSan); 78/78 pytest. Not fixed here, reported separately: core/keystore.c's compiled-in default_dev_key is described as the RFC 8032 TEST 1 public key but differs from byte 21 on and is not a point on the curve, so nothing can verify against it on any board without OTP. With embeddedos-org#104 that makes firmware update refuse every image on such boards.
… -1.0.0 as an option test_out_of_range_version_is_rejected[-1.0.0] passed locally (Python 3.14) and failed in CI (ubuntu-22.04, Python 3.10) with argparse's own "expected one argument": the older negative-number matcher does not accept -1.0.0, so the token was read as an unknown option and imgpack.py's range check -- the thing under test -- never ran. The joined form is unambiguous on every interpreter and the test now reaches the tool's message.
tests/vectors/fw_update_test_sigs.h is the output of tools/gen_fw_update_test_sigs.py, committed because eBoot has no Ed25519 signer in C. Nothing checked that the two agree: a generator edit without a regeneration leaves test_fw_update and test_fw_transport verifying against stale signatures, failing with EOS_ERR_SIGNATURE and nothing to say why. tests/unit/test_fw_update_test_sigs.py runs the generator with the test's own interpreter and compares its stdout to the committed header byte for byte, so a line-ending change counts too. It follows the same dependency rule as test_eos_sign_payload_offset.py: with EOS_REQUIRE_SIGNING_TESTS set (the CI workflow sets it before the pytest step) a missing cryptography module fails the job instead of skipping. Negative control: one flipped hex byte in the header fails the test with a unified diff naming the line. build_image() and build_container() now carry a comment naming the coupling: the signed prefix is assembled both there and in the generator, and changing any field in it means changing the generator's copy and regenerating the header.
…epair embeddedos-org#103 and embeddedos-org#104 were both merged and disagree on whether the anti-rollback counter or the signature is checked first in eos_fw_update_finalize(). The master design orders boot as verify image, then version policy (section 8.1), but its update flow (section 15) never places the anti-rollback check, so the order the install path uses existed only in a PR body. ADR-020 records it: the signature over the signed header prefix is verified first, the TLV counter is read only after the prefix that binds it is authenticated, and an image that fails verification is refused as EOS_ERR_SIGNATURE without its counter being consulted. docs/adr/README.md is added in the shape of the eos repository's index; 020 avoids reusing 001 through 019. CHANGELOG.md gains the Unreleased entries for the repair: the configure, compile and link breakage after the 09-07 batch merge, the settled check ordering with the suites streaming signed images, the re-derived Valgrind list, fuzz-build in the CI gate, counted tests_run, the EoSim Windows legs running under bash, and the Scorecard action on its ghcr.io-hosted release.
The changelog said eleven suites had no Valgrind run. Eleven were missing from EBLDR_UNIT_TESTS, but four of those were named in the hand-written foreach and did run; seven had no run at all. Say which. ADR-020: its design-document citation now says where it comes from (the architecture review of embeddedos-org#115), and the sentence about the two PRs' bases is replaced with what the history shows -- embeddedos-org#103's commits predate embeddedos-org#104's merge, and embeddedos-org#104 was written without embeddedos-org#103's check in place.
The regeneration test's failure path -- the unified diff under the regenerate command -- ran only when the header was stale, so a green run never executed it and the coverage report said so. The report is now a helper the match asserts with, and a second test drives the helper with two byte strings that differ in one byte and checks the command and both sides of the changed line appear.
…itself No run of "Build & Release Book PDF" in this repository's history has succeeded: every run since the step was added (ef0dc50, 2026-04-25) is a failure, and every one whose log is still readable dies with ! LaTeX Error: Command \chead already defined. (exit 43) The workflow installs pandoc 3.6.1 from the release .deb and Eisvogel 2.4.0, which predates pandoc 3.6. The 3.x line merges pandoc's default template through 3.6.1 and later (its CHANGELOG names each merge) and states pandoc 3 compatibility. The LaTeX-level cause of the clash is not established here; the run on this change is what shows whether the pair works. Three changes to the one step and its trigger: Eisvogel 2.4.0 -> 3.5.1, as EISVOGEL_VERSION next to PANDOC_VERSION. The 3.x tarball extracts into Eisvogel-<v>/ rather than flat, so the copy names the directory -- a bare version bump would have failed at the cp. Ran the new step verbatim against the real release: template installed, 29,929 bytes; the old cp against the 3.x layout fails as predicted. No more `tar xzf ... 2>/dev/null || true`. That was fail-open on the exact step that breaks: a missing or reshaped tarball failed silently and the diagnostic landed on the cp after it. The workflow is added to its own paths: filter, for push and pull_request. It fired only on docs/book/**, so a workflow-only change could not get the run that proves it -- including this one. Verified: parsed structure asserted, not parse success -- both paths lists, push.tags ['v*'], branches, release types, workflow_dispatch and the job list are unchanged apart from the two added path entries; the template step contains no '|| true'. NOT RUN here: the PDF itself (no xelatex on this host). The evidence is this PR's own run of the job, cited in the PR once it exists -- and only if build-pdf ran rather than being skipped on has_book. Closes embeddedos-org#134
…ships
The first run of this change got past the template clash -- no more
"\chead already defined" -- and failed on the next thing:
! LaTeX Error: File `sourcesans.sty' not found. (exit 43)
Eisvogel 3.5.0 migrated its default font from the `sourcesanspro` package
to `sourcesans` (its CHANGELOG, 2026-06-28), and ubuntu-22.04's TeX Live
2021 has no sourcesans.sty. 3.4.0 is the last release on sourcesanspro,
which texlive-fonts-extra ships (checked against the package's file list),
and it already carries pandoc's default template merged through 3.9.
Install step re-run verbatim against the 3.4.0 release: template installed.
The PDF is still NOT RUN here; the PR's next run is the evidence.
The second run of this PR, on Eisvogel 3.4.0, failed exactly as master
does -- "Command \chead already defined" -- which means the first run's
apparent progress was an illusion: on 3.5.1 LaTeX died earlier, on a
missing font at line ~672 of the template, before it ever reached the
header setup at ~890. The clash was never in the Eisvogel version.
It is in this workflow. The pandoc step injected, through header-includes,
\usepackage{fancyhdr} \pagestyle{fancy} \fancyhead[L]{...} ...
and Eisvogel builds its own header and footer with KOMA's scrlayer-scrpage,
which defines \chead. The template places $header-includes$ (line 541)
before its header block (~890), so fancyhdr defined \chead first and
scrlayer-scrpage's \newcommand failed. Two header packages, one command.
Both arrived in ef0dc50 (2026-04-25), which is why no run of this job has
ever succeeded, on any pandoc or Eisvogel version.
The header and footer now go through the template's own variables --
header-left=\leftmark, header-right=<version>, footer-center=<press line>,
footer-right left at the template's default page number -- and the
fancyhdr block is gone. The rest of header-includes (float, booktabs,
longtable, caption, graphicx) is unchanged. Eisvogel stays at 3.4.0 for
the fonts (3.5.x needs sourcesans.sty, absent from TeX Live 2021).
Asserted on the parsed workflow: no fancyhdr/fancyhead/pagestyle{fancy}/
*rulewidth on any non-comment line of the step; the four variables and
the remaining header-includes packages present; no comment or blank line
inside the backslash-continued pandoc command (a first draft put the
explanation inside it, where '#' would have swallowed the continuation);
trigger paths, tags and EISVOGEL_VERSION unchanged.
Still NOT RUN here: the PDF. Third run is the evidence.
Run 3 got through the preamble and died on content:
! Misplaced alignment tab character &.
<argument> Srikanth Patchava & EmbeddedOS Contributors
The pandoc step passed -V "author=Srikanth Patchava & EmbeddedOS
Contributors". A -V value is inserted into the LaTeX verbatim, so the '&'
reached xelatex as an alignment tab. book.md's front matter already
declares the same author, and metadata goes through pandoc's writer, which
escapes it. The override is removed; the metadata is the one source.
Earlier runs never reached this line -- they died in the preamble first,
on \chead and on the font -- which is the same lesson as before: the first
error hides every later one.
Asserted on the parsed step: no -V author; every remaining literal -V value
is free of unescaped LaTeX specials (& % # _ ^ ~); header-includes is
exempt by design and values expanded at run time (title, version, date)
come from metadata or `date`, which carry none.
Still NOT RUN here. Fourth run is the evidence.
b5213df to
25794f4
Compare
|
Both taken. Restacked onto #115's Finding 1 (Medium) — the guard saw one of three shapes. Reproduced your three probes first, same result ( Negative control: old one-shape collector, new tests kept → 5 of 11 fail. Finding 2 (Low) — On the red Build PDF: pre-existing since 2026-04-25, as the body already said; the toolchain fix is #135 and this should land after it. (One correction visible in the history: the first push of this commit said |
The comment said the missing sourcesans.sty was ubuntu-22.04's TeX Live 2021. The job runs on ubuntu-latest, which the green run at 358009e shows is ubuntu-24.04 (noble). The fact that matters -- the runner's texlive-fonts-extra has no sourcesans.sty, so Eisvogel 3.5.x cannot be used -- is unchanged and is what run 1 proved; the distro and TeX Live version I attached to it were assumed, not read from the log.
…s wired to nothing CMakeLists.txt offered both as options (default ON), forwarded each as a compile definition, and the README listed both under "Security options". No source file tests either macro: a configure with one of them OFF produces byte-for-byte the same objects as ON (41 of 41 non-test object files identical with the two definitions forced back in through CMAKE_C_FLAGS). Signature verification and recovery authentication are unconditional, and a switch that documents otherwise is a capability the tree does not have, presented as configuration. Remove the two options and their add_compile_definitions. A configure that still passes either as OFF now stops with a message saying there is no such build, instead of silently producing the verifying one. The README says the two are not options. docs/book/book.md's option table listed EBLDR_SECURE_BOOT, EBLDR_MULTICORE, EBLDR_RECOVERY and EBLDR_BOOT_MENU, none of which has ever existed in CMakeLists.txt; it now lists the real ones. tests/unit/test_build_options_are_read.py pins both rules: every EBLDR_ name CMakeLists.txt forwards as a compile definition is referenced by a preprocessor line in some C or header file, and every EBLDR_ name a documentation table presents as an option is declared. Against the base tree it fails on exactly the two dead options and the four phantom book entries. tests/simulate_tests.py, which nothing runs, asserted the option names were present in CMakeLists.txt; it now asserts the honest opposite, and its failure set is unchanged (9 before, 9 after, all unrelated).
…warded Finding 1 from the review of 88cb92e. _forwarded_definitions() matched add_compile_definitions(EBLDR_X) with the closing paren required to follow the name, so of the three ordinary ways to forward a compile definition it saw one. The reviewer showed the other two carrying a name nothing reads straight past it: add_compile_definitions(EBLDR_DEAD_A=1) -> 4 passed target_compile_definitions(eboot_core PRIVATE EBLDR_DEAD_B) -> 4 passed add_compile_definitions(EBLDR_DEAD_C) -> 1 failed The =1 form is what someone writes when they want the macro to have a value; target_compile_definitions is what they write when they want it scoped to one library. Neither is exotic, and this guard exists only for the future -- the tree forwards exactly one EBLDR_ name today and it is read. The collector now takes the whole argument list of add_ or target_compile_definitions(...), every EBLDR_ token in it, with anything after = stripped. Five shapes are pinned as collected, including a multi-line call and a mixed list, and a second test appends each shape to the real CMakeLists.txt text with a dead name and requires the guard to fail on it -- which is exactly how a dead switch would come back. All three of the reviewer's probes now fail the guard. The secondary note is taken too: test_documented_options_exist checked documented <= declared; the reverse direction is now asserted as well, with EBLDR_BOARD exempted because the README covers it in prose above the table rather than in it. Clean today, as the reviewer enumerated. Negative control: with the old one-shape collector restored and the new tests kept, 5 of 11 fail. At this head (restacked onto embeddedos-org#115's e152d8e, itself on master 682d005): pytest tests/ 93 passed, ctest 31/31.
25794f4 to
f9fa26c
Compare
|
Restacked onto #135 at |
Fixes #132
Stacked on #135 (→ #115); review
abf0522..f9fa26cfor this change alone -- two commits, six files. Merge order #115 → #135 → this: #135 is the Eisvogel toolchain fix forBuild PDF, which this PR triggers by touchingdocs/book/and which has been red on every run since 2026-04-25; stacking on it is what turns that check green here rather than leaving it as a declared-prerequisite red. (Restacked frome152d8e..25794f4once #135's fix was proven green atabf0522; before that froma276016..88cb92e.) Merge #115 first. Independent of the other stacks on #115 (#116/#122, #123, #127/#131, #129): its CHANGELOG line goes at the end of### Fixed, where none of them writes.On the red
Build & Release Book PDFcheck: this PR is the first one tonight to touchdocs/book/, so it is the first to trigger that workflow, and the workflow has never succeeded in this repository -- every run since 2026-04-25 fails, including the lastmasterpush run (84bbef0, 2026-09-08), on the same! LaTeX Error: Command \chead already defined.(pandoc 3.6.1 + Eisvogel 2.4.0). Not caused by the table edit here; the toolchain fix is #135 (issue #134), and this PR's PDF check goes green once that lands. The gate checks (CI — eBoot,eBoot Build & Test,CodeQL,Linked issue policy,Simulation Sanity Test) are green on this head.The defect
CMakeLists.txtofferedEBLDR_REQUIRE_SIGNATURESandEBLDR_RECOVERY_AUTHas options (defaultON), forwarded each as a compile definition, and the README listed both under "Security options" as the switches that require Ed25519 signatures and recovery authentication. No source file tests either macro:Measured rather than inferred: the same tree configured with
-DCMAKE_C_FLAGS="-DEBLDR_REQUIRE_SIGNATURES -DEBLDR_RECOVERY_AUTH"and without produces byte-identical output for 41 of 41 non-test object files (to reproduce, build without-g— debug info embeds the command line, so a Debug configuration differs in every object for a reason that has nothing to do with the options) (cmpoverCMakeFiles/**/*.c.o; the.aarchives differ only in their timestamp fields).OFFbuilt the verifying bootloader too -- fail-closed by accident, but a documented switch that changes nothing is a capability the tree does not have, presented as configuration.docs/book/book.md§24.1 went further and listedEBLDR_SECURE_BOOT,EBLDR_MULTICORE,EBLDR_RECOVERYandEBLDR_BOOT_MENU, none of which has ever existed inCMakeLists.txt.The fix
CMakeLists.txt: the twooption()s and theiradd_compile_definitionsare removed. A configure that still passes either asOFFstops withFATAL_ERROR("there is no build that skips signature verification or recovery authentication ... drop the flag") instead of silently producing the verifying firmware. PassingONis inert and gets CMake's usual unused-variable warning.README.md: the two rows are gone; a paragraph states that verification and recovery authentication are not options, and why the rows were there.docs/book/book.md: the table lists the options that exist (EBLDR_BOARD,EBLDR_BUILD_TESTS,EBLDR_VERIFY_STAGE1,EBLDR_HARDENING,EBLDR_SANITIZE,EBLDR_BUILD_FUZZ) and names the four phantoms it used to carry.tests/unit/test_build_options_are_read.py(new, runs under the existingpytest tests/step inci.yml): everyEBLDR_name thatCMakeLists.txtforwards withadd_compile_definitionsmust be referenced by a preprocessor line in some.c/.hundercore hal include stage0 stage1 boards tests; everyEBLDR_name in a README or book option table must be declared byCMakeLists.txt; and neither removed option may be redeclared.tests/simulate_tests.py: a correctness repair to a file nothing executes — not coverage. Its two checks asserted the option names appeared inCMakeLists.txt, which held because the switches did nothing, so each asserted the opposite of what its name claimed. They now assert the honest opposite, and they are exactly as unexecuted as before: no workflow, CMake target or Makefile runs this file (grep -rn simulate_tests .github/ CMakeLists.txt tests/CMakeLists.txtis empty), and run by hand it fails 8 unrelated stale checks. The guard that pytest actually runs istests/unit/test_build_options_are_read.py, which the CHANGELOG names. The file's fate — register-and-repair, or delete — is a follow-up, not this PR. That script is run by no workflow and fails 9 unrelated checks on the base (3.0.1version pins, CI job names); the failure set is unchanged, 9 before and 9 after.Not done:
EBLDR_VERIFY_STAGE1is a real switch (stage0/jump_stage1.c:65) and stays one; whether a Release build of a real board should be allowed to turn it off is a policy question for #122's gate, not this PR.Verification
cmake -S . -B build -DEBLDR_BUILD_TESTS=ON→cmake --build→ctestcmake ... -DEBLDR_REQUIRE_SIGNATURES=OFF/-DEBLDR_RECOVERY_AUTH=0cmake ... -DEBLDR_REQUIRE_SIGNATURES=ONpytest tests -qCMakeLists.txt,README.mdanddocs/book/book.mdrestored, new guard run['EBLDR_RECOVERY_AUTH', 'EBLDR_REQUIRE_SIGNATURES']; phantom book options['EBLDR_BOOT_MENU', 'EBLDR_MULTICORE', 'EBLDR_RECOVERY', 'EBLDR_SECURE_BOOT']; the removed options still declaredCMakeLists.txtstays CRLF (464→471 CR bytes),CHANGELOG.md135→136; README, book, and the Python files stay LF