fix(build): move boot_log into eboot_core so the core library links standalone - #39
Merged
srpatcha merged 2 commits intoAug 27, 2026
Conversation
…tandalone
core/recovery.c, core/boot_policy.c and stage0/jump_stage1.c all call
eos_boot_log_append() and friends, but boot_log.c was compiled into
eboot_stage1 — which itself links PUBLIC against eboot_core.
That circular dependency left eboot_core unable to link on its own:
- test_recovery links only eboot_core and fails to build with undefined
_eos_boot_log_append / _eos_boot_log_get_head / _eos_boot_log_read.
- ebldr_stage0 compiles stage0/jump_stage1.c, which calls
eos_boot_log_append() three times, and links `eboot_core board_${BOARD}`
without eboot_stage1. It could not link for any board.
The stage0 breakage is invisible in CI because EBLDR_BOARD defaults to "none",
so the target is only created on a cross-compile.
boot_log.c is core-layer code with no stage-1 dependencies — it includes only
eos_types.h, eos_hal.h and string.h, and implements a flash-backed circular
log. Moving it to core/ removes the cycle and makes eboot_core self-contained.
The file is moved verbatim (git records a pure rename, identical SHA-256); the
only edits are the two CMake source-list lines.
This also resolves the test_recovery failure without needing to link
eboot_stage1 into a core-level test, so tests/CMakeLists.txt is untouched.
Verified: full build succeeds where it previously exited 2, and ctest goes from
13/14 to 14/14.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Kartikey1306
requested review from
hshanmug12,
maheshmunnangi and
srpatcha
as code owners
August 26, 2026 06:23
10 tasks
srpatcha
previously approved these changes
Aug 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
eboot_corecannot link on its own.core/recovery.c,core/boot_policy.candstage0/jump_stage1.call calleos_boot_log_*(), butboot_log.cwascompiled into
eboot_stage1— which itself linksPUBLICagainsteboot_core.That circular dependency breaks two targets:
test_recoverylinks onlyeboot_coreand fails to build.ebldr_stage0compilesstage0/jump_stage1.c, which callseos_boot_log_append()three times, and linkseboot_core board_${EBLDR_BOARD}withouteboot_stage1. It cannot linkfor any board.
The fix is to put the code in the layer that uses it.
The bug
On
master:The build exits 2 and
ctestreports 13/14 withtest_recoveryNot Run.The stage0 half is the part that matters
test_recoveryis a test.ebldr_stage0is firmware. It has exactly thesame unmet dependency, and it is invisible in CI because
EBLDR_BOARDdefaultsto
"none", so the target is never created in a host build(
CMakeLists.txt:151). It would only surface on a real cross-compile.Demonstrated by linking stage0's requirement against each version of the
library:
Approach
Move
boot_log.cfromstage1/tocore/.It is core-layer code already: it includes only
eos_types.h,eos_hal.handstring.h, and implements a flash-backed circular log with no stage-1dependency of any kind. Its callers are split across core, stage0 and stage1 —
the one layer it does not belong to is stage1.
The file is moved verbatim. Git records a pure rename and the SHA-256 is
identical before and after (
b345d030…de99); the only edits are the two CMakesource-list lines.
Why not link
eboot_stage1into the testThat is what #35 does, and it does fix
test_recovery. I went the other way fortwo reasons:
eboot_corenon-self-contained, soebldr_stage0staysbroken — the test passes but the firmware target still cannot link.
layering in the test as well.
Because this fixes the root cause,
tests/CMakeLists.txtneeds no change atall, so there is no textual conflict with #35 — whichever lands first, the
other is either redundant or applies cleanly. Happy to close this in favour of
#35 if maintainers prefer the narrower fix, but the stage0 break would then want
its own issue.
Testing
test_recoverybuilds and passes. No other test changes behaviour.I specifically checked for a duplicate-symbol clash:
test_boot_loglinkseboot_coreand defines its owneos_boot_log_*stubs. It still builds andpasses, because the linker only pulls
boot_log.c.ofrom the archive to resolvean undefined symbol, and that test defines them all itself.
Two findings I am reporting rather than fixing
Both turned up while tracing this and are out of scope for a layering fix:
include/eos_boot_log.hdoes not describe the implementation. Itdeclares a different, incompatible API under the same names:
boot_log.ceos_boot_log_initint (void)void (uint32_t head)eos_boot_log_readint (entry_t *, uint32_t)int (uint32_t, entry_t *)eos_boot_log_get_headuint32_t (void)count/flush/get_latest/event_nameNothing breaks today only because no non-test source includes the header —
every caller writes its own local
externdeclaration. Anyone who doesinclude it gets
eos_boot_log_read(entries, max_count)compiled against animplementation whose first parameter is an index, i.e. a pointer
reinterpreted as
uint32_t.tests/unit/test_boot_log.ctests its own stubs. It includeseos_boot_log.h, then defines every function in that header itself, andasserts against those definitions. It exercises no line of
boot_log.c.Reconciling the header and rewriting that test against the real implementation
(it needs a simulated flash HAL, like
test_image_verify.chas) is aself-contained follow-up. I did not want to bundle a rewrite of a passing test
into a two-line build fix. Happy to open an issue or a follow-up PR.
Limitations and considerations
is added to or removed from any firmware image;
eboot_stage1still getsboot_logtransitively througheboot_core.arm-none-eabi-gcconthis machine, so
ebldr_stage0is NOT RUN — the break and the fix aredemonstrated by reproducing stage0's link requirement natively (above) rather
than by building the firmware target.
CMakeLists.txtis CRLF andCHANGELOG.mdismixed; edits were applied byte-wise so untouched lines keep their endings.
Type of Change
Changes
stage1/boot_log.c→core/boot_log.c(verbatim move).CMakeLists.txt— source listed undereboot_coreinstead ofeboot_stage1.CHANGELOG.md—Unreleasedentry.Pre-Submission Checklist