Skip to content

feat(slot_manager): boot attempt counter with rollback detection + fix fw_update_abort ordering - #37

Open
yash161 wants to merge 1 commit into
embeddedos-org:masterfrom
yash161:feat/boot-attempt-counter-and-fw-abort-fix
Open

feat(slot_manager): boot attempt counter with rollback detection + fix fw_update_abort ordering#37
yash161 wants to merge 1 commit into
embeddedos-org:masterfrom
yash161:feat/boot-attempt-counter-and-fw-abort-fix

Conversation

@yash161

@yash161 yash161 commented Aug 26, 2026

Copy link
Copy Markdown

Issue / Improvement

slot_manager had no way to detect a bad firmware image that boots but then crashes/hangs before the application confirms it's healthy — there was no boot-attempt counter, so a device could bootloop indefinitely on a broken image instead of rolling back to the last known-good slot.

Separately, eos_fw_update_abort() set ctx->state = EOS_FW_STATE_IDLE and then immediately called memset(ctx, 0, sizeof(*ctx)), which zeroes the whole struct after the state was set — the explicit state assignment was being clobbered by the memset. It happened to work only because EOS_FW_STATE_IDLE == 0; it was fragile if that enum ever changes.

Approach

  • Added a small boot-attempt tracking API to slot_manager:
    • eos_slot_mark_booting() — increment a per-slot attempt counter (caps at 255)
    • eos_slot_confirm() — mark the slot healthy, reset the counter, and transition VALID → CONFIRMED
    • eos_slot_needs_rollback(slot, max_attempts) — true once the counter reaches the caller-supplied threshold
    • eos_slot_get_boot_attempts() — read-only accessor for diagnostics
  • Reordered eos_fw_update_abort() to memset() first, then explicitly set state = EOS_FW_STATE_IDLE after, so the reset is correct regardless of the enum's underlying value.
  • Minor cleanup in run_all_tests.py: removed a duplicate/dead subprocess.run + sys.exit call that preceded the actual (correct) invocation lower in the same function.

Testing

  • Added test_boot_attempts_and_rollback() to tests/unit/test_slot_manager.c, covering: attempt increments, threshold detection at the boundary, reset-on-confirm, state transition to CONFIRMED, and invalid-slot handling.
  • Compiled tests/unit/test_slot_manager.c and core/slot_manager.c directly with gcc -Wall -Wextra (no CMake available in this environment) — no warnings.
  • Ran the full tests/unit/test_slot_manager.c suite: all 22 tests pass (21 pre-existing + 1 new).
  • Ran run_all_tests.py (pytest suite): all 10 tests pass.

Limitations

  • The new API doesn't persist the boot-attempt counter across power cycles by itself — callers (e.g. bootloader startup) are expected to call eos_slot_mark_booting() early in boot and eos_slot_confirm() once the running image is verified healthy, and to wire eos_slot_needs_rollback() into the existing rollback path. Persisting the counter to non-volatile storage (if not already handled elsewhere in the boot flow) is out of scope for this change.

…and fix fw_update_abort

- Feat: Add boot attempt tracking (eos_slot_mark_booting, eos_slot_confirm,
  eos_slot_needs_rollback, eos_slot_get_boot_attempts) to prevent bricking
  and bootloops after bad firmware updates
- Fix: Fix memset ordering in eos_fw_update_abort() to properly reset state
- Fix: Clean up duplicate subprocess run call and return code in run_all_tests.py
- Tests: Add test_boot_attempts_and_rollback() covering attempt increments,
  rollback threshold checks, slot confirmation, and error conditions

Signed-off-by: Yash Shah <yash@example.com>
Signed-off-by: Yash Shah <yashshah19@gnu.ac.in>
Copilot AI lite review requested due to automatic review settings August 26, 2026 03:11

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds boot-attempt tracking to the slot manager to enable rollback decisions after repeated failed boots, fixes eos_fw_update_abort() state-reset ordering, and removes dead/duplicate pytest invocation logic from the Python test runner.

Changes:

  • Introduces boot-attempt counter APIs (mark_booting, confirm, needs_rollback, get_boot_attempts) in slot_manager and exposes them in the public header.
  • Fixes eos_fw_update_abort() by performing memset() before setting ctx->state.
  • Cleans up run_all_tests.py by removing duplicate subprocess.run() + sys.exit() code.

Verification status: NOT RUN (not executed as part of this review).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/unit/test_slot_manager.c Adds a new test and local implementations for boot-attempt APIs (but currently overrides the production implementations during linking).
include/eos_slot_manager.h Exposes the new boot-attempt/rollback APIs; doc clarifications recommended for slot support and edge cases.
core/slot_manager.c Implements boot-attempt tracking and confirm transition logic for slots A/B.
core/fw_update.c Fixes abort-reset ordering by setting state after zeroing the context.
run_all_tests.py Removes dead duplicate pytest invocation and keeps a single command path.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +77 to +83
int eos_slot_mark_booting(eos_slot_t slot) {
if (slot > EOS_SLOT_RECOVERY) return EOS_ERR_INVALID;
if (slot_boot_attempts[slot] < 255) {
slot_boot_attempts[slot]++;
}
return EOS_OK;
}
Comment on lines +58 to +60
* @brief Record a boot attempt on the specified slot (increments counter).
* @param slot Slot identifier.
* @return EOS_OK on success, EOS_ERR_INVALID on error.
Comment on lines +72 to +76
* @brief Check if a slot has exceeded the maximum allowed boot attempts and needs rollback.
* @param slot Slot identifier.
* @param max_attempts Maximum allowed consecutive failed attempts (e.g., 3).
* @return true if boot attempts >= max_attempts.
*/
Comment thread core/slot_manager.c
Comment on lines 18 to 22
eos_image_header_t header;
bool header_valid;
uint8_t boot_attempts;
bool confirmed;
} slot_info_t;
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.

2 participants