Skip to content

Give SigmaStar and Ingenic the layout their bootloader has - #131

Merged
openipc-ai merged 2 commits into
masterfrom
sigmastar-nor-layout
Aug 29, 2026
Merged

Give SigmaStar and Ingenic the layout their bootloader has#131
openipc-ai merged 2 commits into
masterfrom
sigmastar-nor-layout

Conversation

@widgetii

Copy link
Copy Markdown
Member

Found while installing OpenIPC on a 16MB SSC377QE camera and then checking the page against what actually went on the flash.

The image a 16MB SigmaStar chip is offered cannot boot

FlashLayout::EIGHT_MEG_LAYOUT_VENDORS = %w[SigmaStar Ingenic] was removed in #78, on the grounds that those vendors' bootloaders define mtdpartsnor16m and the uknor16m/urnor16m pair the same as the HiSilicon and Goke ones. u-boot-msc313e, u-boot-t20 and u-boot-t40 do define them — and no released binary is built from any of them.

OpenIPC/firmware/.github/workflows/uboot.yml is what builds the bootloaders this site links. It clones openipc/u-boot-sigmastar and openipc/u-boot-ingenic and runs their build.sh; the SigmaStar one's spinor loop is literally ssc377 ssc377d ssc377de ssc377qe ssc378de ssc378qe against include/configs/infinity6c.h, which includes configs/sstar-common.h. That header is the whole environment every SSC3xx NOR camera boots with:

kernaddr=0x50000   kernsize=0x200000
rootaddr=0x250000  rootsize=0x500000   rootmtd=5120k
uknor / urnor / ubnor
CONFIG_BOOTARGS "... mtdparts=NOR_FLASH:256k(boot),64k(env),2048k(kernel),${rootmtd}(rootfs),-(rootfs_data) ..."

A repo-wide grep for uknor8m|uknor16m|urnor8m|urnor16m|setnor8m|setnor16m|mtdpartsnor returns nothing in either repo; u-boot-ingenic's isvp_common.h has the same unsuffixed uknor/urnor.

One mtdparts string, a 2048k kernel inside it, and only ${rootmtd} varying — so the rootfs starts at 0x250000 at every chip size. Handing these two NOR[16] puts it at 0x350000. Probed on the images the site serves today for ssc377qe (flash_size=16&fw_release=lite), by range request:

offset layout=8 layout=16
0x40000 (env) ff ff ff ff
0x50000 27051956 uImage 27051956 uImage
0x250000 68737173 "hsqs" ff ff ff ff
0x350000 rootfs body 68737173 "hsqs"

The env region is blank because the full-image flash erases it, so the camera comes up on the compiled-in bootargs, looks for the rootfs at 0x250000, finds erased flash and panics on root mount. Since #130 the 16MB layout is what a 16MB chip selects by default, so that is what a SigmaStar visitor gets by pressing the button. The 8MB-layout image of the same page is correct and boots.

None of the macros the expert section names exist

run setnor16m, run uknor16m; run urnor16m and the printenv hint under them name variables no SigmaStar or Ingenic camera has. U-Boot answers ## Error: "uknor16m" not defined and flashes nothing, with no failure the reader can see. This one predates #78 — the expert section has emitted suffixed macros for these vendors since it existed.

What this does

The pin was right for these two; its stated reason was not. This replaces it with the fact itself:

  • FlashLayout gets a second table for bootloaders with one mtdparts string. 16MB there means rootmtd=10240k at the same 0x250000, not a rootfs 1MB further up; the kernel partition stays 2048k because the bootargs say so.
  • The macro suffix is Camera#bootloader_macro_suffix rather than the layout name, so these cameras are told run uknor; run urnor and the hint names uknor, urnor with no set… they could not find in their own printenv.
  • The step that puts the bootloader on the layout is Camera#layout_commands: a macro where there is one, and the setenv that macro would have done where there is not — setenv rootmtd 10240k; setenv rootsize 0xA00000, saveenv, reset. Empty where the layout is already the bootloader's default, and the heading above it is skipped rather than printed over a command that does nothing.
  • @flash_type_command is gone. It was read in four places in the view, so the offsets and the commands could disagree.

Keeping both layouts is deliberate: an Ultimate rootfs is 7832KB on ssc338q, 7252KB on ssc30kq and 6772KB on t31, against the 5120KB rootmtd defaults to, so a flat pin to the 8MB numbers would take Ultimate off eleven SoCs that publish it. rootmtd is a plain variable, stored unexpanded and expanded at boot by cmdnor, so raising it is all that is needed and nothing has to move.

What I have and have not verified

Verified on hardware and against the served artifacts:

  • the SSC377QE bootloader environment above, and that a kernel at 0x50000 plus a squashfs at 0x250000 boots (an IM50Q01, 16MB NOR, imx335, now running OpenIPC 2.6.08.29);
  • that mtdparts=nor0: — the vendor spelling — is ignored by the OpenIPC kernel, which names the device NOR_FLASH, and that the mismatch is exactly this root-mount panic;
  • the offsets in the two generated images, by range request.

Not verified on hardware: the rootmtd=10240k variant. It follows from sstar-common.h and from ${rootmtd} being expanded at boot, but nobody has flashed an Ultimate image to a SigmaStar camera this way. Worth a bench run before this leaves draft — I have the hardware for the Lite half, not for an Ultimate one.

The alternative fix is upstream rather than here: add mtdpartsnor8m/mtdpartsnor16m and the uknor*/urnor*/setnor* sets to u-boot-sigmastar and u-boot-ingenic so they match u-boot-hi3516ev200/include/configs/hi-common.h, and then the page's current behaviour becomes correct as written. That is a better end state and a much longer path; this change makes the page describe the bootloaders that exist today.

`FlashLayout::EIGHT_MEG_LAYOUT_VENDORS = %w[SigmaStar Ingenic]` was removed in
#78 on the grounds that their bootloaders define mtdpartsnor16m and the
uknor16m/urnor16m pair "down to the byte", the same as the HiSilicon and Goke
ones. The repositories that carry those definitions -- u-boot-msc313e,
u-boot-t20, u-boot-t40 -- are real, and no released binary is built from any of
them, so no camera runs them.

OpenIPC/firmware's .github/workflows/uboot.yml is what builds the bootloaders
this site links. It clones openipc/u-boot-sigmastar and openipc/u-boot-ingenic
and runs their build.sh; the SigmaStar one's spinor loop is `ssc377 ssc377d
ssc377de ssc377qe ssc378de ssc378qe` against include/configs/infinity6c.h,
which includes configs/sstar-common.h. That header is the whole environment
every SSC3xx NOR camera boots with:

    kernaddr=0x50000   kernsize=0x200000
    rootaddr=0x250000  rootsize=0x500000   rootmtd=5120k
    uknor / urnor / ubnor
    CONFIG_BOOTARGS "... mtdparts=NOR_FLASH:256k(boot),64k(env),2048k(kernel),
                         ${rootmtd}(rootfs),-(rootfs_data) ..."

A repo-wide grep for uknor8m|uknor16m|urnor8m|urnor16m|setnor8m|setnor16m|
mtdpartsnor returns nothing in either repo. u-boot-ingenic's isvp_common.h
carries the same unsuffixed uknor/urnor.

**The 16MB image cannot boot.** One mtdparts string, a 2048k kernel inside it,
and only ${rootmtd} varying: the rootfs starts at 0x250000 at every chip size.
Handing these two NOR[16] put it at 0x350000. The image openipc.org serves for
ssc377qe today has "hsqs" at 0x350000 and 0xff at 0x250000, and its env region
at 0x40000 is blank -- a full-image flash erases the env, so the camera comes up
on the compiled-in bootargs, looks for the rootfs at 0x250000, finds erased
flash and panics on root mount. The 8MB-layout image of the same page has it at
0x250000 and boots. Since #130 the 16MB layout is what a 16MB chip selects by
default, so this is what a SigmaStar visitor gets by pressing the button.

**None of the macros exist.** `run setnor16m`, `run uknor16m; run urnor16m` and
the printenv hint under them name variables no SigmaStar or Ingenic camera has.
U-Boot answers `## Error: "uknor16m" not defined` and flashes nothing, with no
failure the reader can see. This predates #78 -- the expert section has emitted
suffixed macros for these vendors since it existed.

So the pin was right for these two, even though its own comment gave a wrong
reason for it. What replaces it is the same fact stated properly: they have one
mtdparts, so 16MB means rootmtd=10240k at the same offset rather than a rootfs
1MB further up, and their macros are `uknor`/`urnor` with nothing after them.

That keeps Ultimate reachable, which a flat pin to the 8MB numbers would not:
its rootfs is 7832KB on ssc338q, 7252KB on ssc30kq and 6772KB on t31 against the
5120KB rootmtd defaults to. rootmtd is a plain variable, saved unexpanded and
expanded at boot by `cmdnor`, so the step that a macro does elsewhere is a
setenv here:

    setenv rootmtd 10240k; setenv rootsize 0xA00000
    saveenv
    reset

and where the layout is already the bootloader's own, that step is dropped
rather than rendered as a `run setnor8m` under a heading calling it required.

@flash_type_command is gone with it. It was the layout name, which is the macro
suffix only for the bootloaders that name their macros after the layout, and the
view read it in four places -- so the offsets and the commands could disagree.
Camera answers both now, off the same suffix.
The test that pinned every vendor to 0x350000 was written when every vendor
had the same answer. It still checks the thing it was for -- that the image and
the page cannot describe different layouts -- but reads the offset each
bootloader is actually on.

A model of its own per vendor with it: the cache filename carries the model and
not the vendor, so one model built under three vendors has the second and third
read back the first's image. Nothing in production can hit that, a model
belongs to one vendor, but a test that did would pass on a stale file.
@openipc-ai
openipc-ai marked this pull request as ready for review August 29, 2026 17:44
@openipc-ai
openipc-ai merged commit a64f7b5 into master Aug 29, 2026
2 checks passed
@openipc-ai
openipc-ai deleted the sigmastar-nor-layout branch August 29, 2026 17:45
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Align SigmaStar and Ingenic NOR layouts with shipped bootloaders

🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Generate bootable 16MB SigmaStar and Ingenic images using their fixed rootfs offset.
• Emit unsuffixed U-Boot macros and explicit rootmtd changes those bootloaders support.
• Add model, image, and controller coverage for vendor-specific layouts and commands.
Diagram

graph TD
  A["SoC Controller"] --> B["Camera Policy"] --> C["Flash Layout"] --> D["Firmware Generator"] --> G["Flash Image"] --> H["Camera Bootloader"]
  B --> E["Install Helper"] --> F["Install View"] --> H
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Standardize upstream bootloader macros
  • ➕ Makes SigmaStar and Ingenic environments match existing size-suffixed installation behavior.
  • ➕ Removes vendor-specific command handling from the website over time.
  • ➖ Requires coordinated changes, builds, releases, and deployment across two bootloader repositories.
  • ➖ Does not repair instructions or images for bootloaders already deployed on cameras.
2. Model bootloader capabilities per SoC
  • ➕ Avoids inferring bootloader behavior from vendor names.
  • ➕ Supports future vendor models that ship different bootloader environments.
  • ➖ Adds schema or configuration maintenance for every affected SoC.
  • ➖ Creates more opportunities for metadata to drift from released bootloader binaries.

Recommendation: Use the PR's vendor-aware compatibility layer now because it makes generated images and instructions match the released bootloaders already in use. Pursue upstream macro standardization as the preferred long-term state; if bootloader behavior later diverges within a vendor, replace the vendor table with explicit per-SoC capability metadata.

Files changed (9) +382 / -108

Bug fix (6) +178 / -64
socs_controller.rbRemove duplicated layout-derived macro state +8/-10

Remove duplicated layout-derived macro state

• Stops assigning '@flash_type_command' and delegates bootloader macro selection to the camera model. This prevents command names from drifting from the finalized flash layout and vendor behavior.

app/controllers/cameras/socs_controller.rb

installation_helper.rbGenerate commands from camera bootloader policy +19/-10

Generate commands from camera bootloader policy

• Derives Linux flashing macros, variable hints, and environment preparation commands directly from 'Camera'. Unsuffixed NOR environments no longer receive nonexistent size-specific or 'setnor*' macros.

app/helpers/installation_helper.rb

camera.rbModel vendor-specific bootloader layouts and commands +62/-1

Model vendor-specific bootloader layouts and commands

• Adds fixed-mtdparts detection, actual macro suffixes, default-layout checks, and layout transition commands. Vendor context now selects flash geometry while preserving standard NOR and NAND behavior.

app/models/camera.rb

firmware.rbGenerate images with vendor-aware NOR geometry +5/-2

Generate images with vendor-aware NOR geometry

• Passes the SoC vendor into layout selection so generated SigmaStar and Ingenic images place rootfs at the bootloader's fixed '0x250000' offset.

app/models/firmware.rb

flash_layout.rbAdd fixed-mtdparts NOR layout table +60/-21

Add fixed-mtdparts NOR layout table

• Introduces SigmaStar and Ingenic geometry with a fixed 2MB kernel and '0x250000' rootfs offset for both layout sizes. The 16MB entry expands rootfs capacity and moves only the overlay boundary.

app/models/flash_layout.rb

update.html.erbRender only supported bootloader instructions +24/-20

Render only supported bootloader instructions

• Uses camera-derived commands throughout the full-image and expert flows. It suppresses environment-remapping sections when the bootloader already uses the requested default layout.

app/views/cameras/socs/update.html.erb

Tests (3) +204 / -44
socs_controller_test.rbCover fixed-offset installation guidance +64/-31

Cover fixed-offset installation guidance

• Verifies SigmaStar and Ingenic pages retain the '0x250000' rootfs geometry, use unsuffixed macros, set 'rootmtd' for 16MB, and emit no remapping command for the default layout.

test/controllers/socs_controller_test.rb

camera_test.rbTest bootloader-aware camera policy +90/-0

Test bootloader-aware camera policy

• Covers vendor-specific offsets, macro variables, explicit environment commands, standard NOR compatibility, NAND isolation, and fallback behavior without a SoC.

test/models/camera_test.rb

firmware_test.rbVerify vendor-compatible binary image placement +50/-13

Verify vendor-compatible binary image placement

• Asserts generated 16MB SigmaStar and Ingenic images place rootfs at '0x250000' while standard vendors retain '0x350000'. It also prevents test cache collisions by using distinct models per vendor.

test/models/firmware_test.rb

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

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Stale images survive layout change 🐞 Bug ≡ Correctness
Description
The new vendor-specific layout is only applied when an image is assembled, while natural 16MB images
retain their old cache filename; a fresh, same-size pre-PR SigmaStar/Ingenic image therefore
bypasses assembly and is served with its rootfs still at 0x350000. This leaves the primary boot
failure unfixed until the source archive becomes newer or the age-based cache purge removes the
artifact.
Code

app/models/firmware.rb[456]

+    @nor_layout ||= FlashLayout.nor(@layout, @soc.vendor.name)
Evidence
Natural layouts omit a layout suffix from the cache filename, and freshness accepts any readable
image of the expected chip size that is newer than its inputs. The changed vendor-aware lookup only
affects fresh assembly, while the download action serves the cached path after generate returns; the
normal purge is based solely on age.

app/models/firmware.rb[60-88]
app/models/firmware.rb[136-183]
app/models/firmware.rb[197-212]
app/models/firmware.rb[448-456]
app/models/flash_layout.rb[76-82]
app/controllers/cameras/socs_controller.rb[160-174]
deploy/purge-firmware-cache.sh[60-68]

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

## Issue description
The PR changes the assembled layout of natural 16MB SigmaStar and Ingenic NOR images, but those images keep the same cache filename. Existing same-size cached images pass the freshness checks and can continue to be served with the old, unbootable rootfs offset.

## Issue Context
Firmware cache validity currently depends on file existence, permissions, size, and source mtimes; it does not include a layout implementation version or inspect partition offsets. Ensure deployment or cache-key behavior forces all affected pre-change images to be rebuilt, while preserving safe concurrent generation.

## Fix Focus Areas
- app/models/firmware.rb[74-92]
- app/models/firmware.rb[136-183]
- app/models/firmware.rb[197-212]
- app/models/firmware.rb[448-456]
- test/models/firmware_test.rb[601-614]
- deploy/purge-firmware-cache.sh[50-68]

ⓘ 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 group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread app/models/firmware.rb
# bootloader cannot boot.
def nor_layout
@nor_layout ||= FlashLayout.nor(@layout)
@nor_layout ||= FlashLayout.nor(@layout, @soc.vendor.name)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Stale images survive layout change 🐞 Bug ≡ Correctness

The new vendor-specific layout is only applied when an image is assembled, while natural 16MB images
retain their old cache filename; a fresh, same-size pre-PR SigmaStar/Ingenic image therefore
bypasses assembly and is served with its rootfs still at 0x350000. This leaves the primary boot
failure unfixed until the source archive becomes newer or the age-based cache purge removes the
artifact.
Agent Prompt
## Issue description
The PR changes the assembled layout of natural 16MB SigmaStar and Ingenic NOR images, but those images keep the same cache filename. Existing same-size cached images pass the freshness checks and can continue to be served with the old, unbootable rootfs offset.

## Issue Context
Firmware cache validity currently depends on file existence, permissions, size, and source mtimes; it does not include a layout implementation version or inspect partition offsets. Ensure deployment or cache-key behavior forces all affected pre-change images to be rebuilt, while preserving safe concurrent generation.

## Fix Focus Areas
- app/models/firmware.rb[74-92]
- app/models/firmware.rb[136-183]
- app/models/firmware.rb[197-212]
- app/models/firmware.rb[448-456]
- test/models/firmware_test.rb[601-614]
- deploy/purge-firmware-cache.sh[50-68]

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

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