Skip to content

install: the split NOR image is a uImage + squashfs - #155

Merged
widgetii merged 2 commits into
masterfrom
install/split-uimage
Oct 18, 2026
Merged

widgetii merged 2 commits into
masterfrom
install/split-uimage

Conversation

@widgetii

Copy link
Copy Markdown
Member

OpenIPC moves the split NOR layout's firmware.bin from a FIT to the legacy
uImage followed by the squashfs at the next 64 KiB block, and the kernel
now finds the layout's partitions and root in its own device tree,
whatever the bootloader passes. Any U-Boot that bootm's a uImage at
0x50000 boots it, the factory XM U-Boot included, which has no FIT.

  • split_image_end() reads the uImage header (data size at bytes 12..15)
    instead of a FIT's totalsize; the shape checks are otherwise the same.
  • The warning on a plan without the uboot stage goes: the U-Boot already
    on the flash boots the image whichever it is.
  • README and the firmware table say uImage.

Tests: the split fixture is a uImage; a FIT now fails the shape check.

Matches OpenIPC/linux#97, OpenIPC/firmware#2623 and OpenIPC/u-boot#20 (all merged). The format was verified on hardware with sysupgrade and in QEMU; defib install of the uImage split image itself has not been run on a camera.

OpenIPC moves the split NOR layout's firmware.bin from a FIT to the legacy
uImage followed by the squashfs at the next 64 KiB block, and the kernel
now finds the layout's partitions and root in its own device tree,
whatever the bootloader passes. Any U-Boot that bootm's a uImage at
0x50000 boots it, the factory XM U-Boot included, which has no FIT.

- split_image_end() reads the uImage header (data size at bytes 12..15)
  instead of a FIT's totalsize; the shape checks are otherwise the same.
- The warning on a plan without the uboot stage goes: the U-Boot already
  on the flash boots the image whichever it is.
- README and the firmware table say uImage.

Tests: the split fixture is a uImage; a FIT now fails the shape check.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Support uImage-based split NOR firmware

🐞 Bug fix 🕐 20-40 Minutes

Grey Divider

AI Description

• Recognize uImage plus squashfs split NOR packages instead of the former FIT format.
• Remove the OpenIPC U-Boot warning because compatible bootloaders can boot the new image.
• Update documentation and tests to reflect the new package format.
Diagram

graph TD
  A["Split archive"] --> B["Bundle loader"] --> C{"Valid uImage?"}
  C -->|yes| D["Rootfs stage"] --> E["NOR flash"] --> F["U-Boot bootm"] --> G["DT partitions"]
  C -->|no| H["Reject package"]
Loading
High-Level Assessment

Use the uImage header to locate the squashfs while retaining the existing shape checks. Supporting FIT alongside uImage would add complexity for a format the split NOR package no longer ships.

Files changed (5) +37 / -38

Bug fix (2) +18 / -22
firmware.pyValidate uImage-based split firmware +16/-14

Validate uImage-based split firmware

• Reads the uImage data size from its header to locate the next 64 KiB squashfs block, replacing FIT totalsize parsing. Retains squashfs size and trailing-data checks.

src/defib/install/firmware.py

orchestrator.pyRemove obsolete split bootloader warning +2/-8

Remove obsolete split bootloader warning

• Drops the warning when a split install omits the U-Boot stage. Changes human-readable install and kernel-stage messages from FIT to uImage.

src/defib/install/orchestrator.py

Tests (1) +10 / -8
test_install_nor_split.pyExercise uImage split package validation +10/-8

Exercise uImage split package validation

• Rebuilds the split fixture with a uImage header and data size. Checks that a FIT is rejected while existing shape and install tests use the new format.

tests/test_install_nor_split.py

Documentation (2) +9 / -8
README.mdDocument the uImage split NOR layout +5/-4

Document the uImage split NOR layout

• Replaces the FIT description with uImage plus squashfs. Clarifies that the kernel uses its own device tree and that a compatible U-Boot need not be replaced.

README.md

firmware.pyClarify split NOR firmware compatibility +4/-4

Clarify split NOR firmware compatibility

• Updates the supported-SoC comments to describe the uImage package, device-tree partition discovery, and bootloader requirements.

src/defib/firmware.py

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Empty kernels pass the install check ✓ Resolved
Description
split_image_end() rounds the 64-byte uImage header to the next erase block even when the header
declares a data size of zero, so a squashfs at that block passes validation. When such an archive is
supplied, load_firmware_bundle() accepts it and the rootfs stage flashes an image with no kernel
payload.
Code

src/defib/install/firmware.py[R51-53]

+    kernel = UIMAGE_HEADER + int.from_bytes(image[12:16], "big")
+    squash = (kernel + ERASE_BLOCK - 1) // ERASE_BLOCK * ERASE_BLOCK
+    if squash + 48 > len(image) or image[squash:squash + 4] != SQUASHFS_MAGIC:
Evidence
The new calculation places squashfs at 0x10000 for a zero data-size field, while the subsequent
checks require only squashfs magic and a nonzero squashfs length. The package loader uses this check
to accept split images, and the rootfs stage then flashes the accepted bytes.

src/defib/install/firmware.py[49-62]
src/defib/install/firmware.py[120-138]
src/defib/install/orchestrator.py[1565-1570]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A split image with a zero uImage data-size field can pass the shape check if squashfs starts at the first erase-block boundary, despite containing no kernel payload.
## Fix Focus Areas
- src/defib/install/firmware.py[49-54]
- tests/test_install_nor_split.py[166-174]
## Recommended Fix
Read the uImage data size into a separate value and reject zero before adding the header length and calculating the squashfs offset. Add a shape-check test with a zero-size uImage header and squashfs at the first erase-block boundary.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can move or hide resolved findings to focus on what still needs action

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/defib/install/firmware.py Outdated
A uImage header declaring zero data bytes rounds up to the first 64 KiB
block, so a squashfs there passed the shape check and the install would
have flashed an image with no kernel.
@widgetii
widgetii merged commit 1ba3100 into master Oct 18, 2026
13 checks passed
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