Flashprog 1.5 support wp revert if no interactive shell have flash verify compressed internal flashing archive#2076
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the firmware flashing stack to support flashprog v1.5 and adds a rollback/confirmation workflow to improve recoverability after firmware writes, including optional SPI write-protection status checks and new GUI configuration toggles.
Changes:
- Bump
flashprogto v1.5 (new commit + hash). - Add automatic rollback backups +
pending_rollbackmarker handling, with boot-time confirmation/auto-restore logic. - Refactor flash image preparation/verification to support
.zippackages and Talos-2.tgzhandling, and extend GUI menus/options for rollback and flash behaviors.
Reviewed changes
Copilot reviewed 4 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| modules/flashprog | Updates flashprog version/hash to v1.5. |
| initrd/init | Adds boot-time rollback checks and a manual rollback keypath. |
| initrd/etc/functions | Adds shared helpers for image prep + rollback confirmation logic. |
| initrd/bin/flash.sh | Adds backup/marker creation, .zip handling, WP status checks, and new CLI flags. |
| initrd/bin/flash-gui.sh | Adds GUI rollback option and reuses new image prep logic. |
| initrd/bin/config-gui.sh | Adds GUI menu to configure verification/backup/auto-rollback + WP status display. |
| initrd/bin/gui-init | Runs rollback confirmation logic after mounting /boot. |
| initrd/bin/oem-factory-reset | Switches to flash.sh --no-backup for internal reflashes. |
| initrd/bin/gpg-gui.sh | Switches to flash.sh --no-backup for internal reflashes. |
| CONTRIBUTING.md | Documents DCO sign-off requirement and cleans formatting. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
|
@i-c-o-n: internal programmer not supported on metteorlake etc to check wp status through "wp list" on 1.5? |
… from flash-gui These helpers were local to flash-gui.sh; moving them to etc/functions makes them available to flash.sh and any future callers without duplication. prepare_flash_image() centralises all package preparation logic: - .zip: extract, normalise sha256sum.txt paths, verify integrity, locate ROM - .tgz (talos-2): extract, verify, read current flash, assemble pnor image - .rom: copy to staging dir, compute SHA256 for display flash-gui.sh drops its local single_glob() and inline UPDATE_PLAIN_EXT logic, delegating to the new functions. Error messages now include PREPARED_ROM_ERROR for better diagnostics. Incidental: fix == to = for POSIX sh compatibility. flash.sh replaces its inline talos-2 tgz block with a case dispatch through prepare_flash_image(), and gains zip support as a side-effect. The -r read path is separated from the write path at the top level for clarity. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Argument parsing replaces the old positional if/elif chain with a proper while/case loop, making flags order-independent and extensible. New flag: --bypass-verify skips flashprog post-write verification. Persistent override: CONFIG_FLASH_NO_VERIFY=y sets it at config level. CLI always wins over config. New functions: - flash_status() / flash_status_ok(): thin INFO() wrappers for progress lines - check_spi_wp(): queries --wp-status before any write; warns if protection is active but does not abort (some programmers cannot disable it in software) Logging upgrades throughout flash_rom(): - TRACE_FUNC at entry - INFO (via flash_status) for read/write progress - DEBUG for CLEAN/NOVERIFY decision points and config override application - NOTE for active deviations (--bypass-verify) - Quoted variable expansions for correctness Usage text expanded to document all flags and supported image formats. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Before each write, flash.sh saves the current firmware to
/boot/<brand>/backup_<board>_<timestamp>.rom. After a successful write
it writes a pending_rollback marker at /boot/<brand>/pending_rollback
containing the backup path, so init can detect the post-flash boot and
auto-rollback if the new firmware fails to reach the user prompt.
New flags:
--save-backup Force backup even if CONFIG_FLASH_SAVE_BACKUP=n
--no-backup Hard-suppress backup and marker; used by rollback
itself and trusted internal callers to prevent
infinite reflash loops
Persistent overrides (CLI always wins):
CONFIG_FLASH_SAVE_BACKUP=n disables backup by default
Backup failure is non-fatal: a warning is printed and the write
proceeds without a backup. /boot must be mounted for backup to
succeed; if not mounted a warning is printed and the write continues.
Backup integrity is provided by /boot attestation (print_tree +
kexec.sig) once the user re-signs /boot after confirming the new
firmware works. No separate GPG signature of the backup is required.
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
… boot check_pending_rollback() is added to etc/functions so both init and gui-init can call it without duplication. Behaviour: if /boot/<brand>/pending_rollback exists and points to a valid backup file, a 30-second text-mode countdown is displayed (using only echo/read so it works even with a broken framebuffer). A beep alerts the user. The countdown message tells the user to hold the power button 10 seconds to cancel. On timeout or non-interactive stdin (CI/headless), the backup is reflashed via flash.sh -c --no-backup --bypass-verify to restore the previous firmware and reboot. Pressing Enter within 30 seconds cancels the rollback and clears the marker. CONFIG_FLASH_AUTO_ROLLBACK=n clears the marker and skips the countdown. The local check_pending_rollback() definition is removed from gui-init; it now calls the shared function from etc/functions. The call is placed after detect_boot_device/mount_boot so /boot is mounted. In init, check_pending_rollback is called just before exec cttyhack, with /boot mounted transiently via CONFIG_BOOT_DEV if not already mounted. This ensures rollback fires before the GUI starts, even if the display is broken. A new 'b' key option is added to init's early keyboard handler (alongside 'r' and 'o') for manual emergency rollback: mounts /boot, calls check_pending_rollback, then continues normal boot if no marker is found or if the user presses Enter to confirm. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
A new 'r' option in the Firmware Management Menu allows the user to manually rollback to the most recent firmware backup saved in /boot/<brand>/. The backup is located via the pending_rollback marker if present, otherwise the most recent backup_*.rom file is used. Before flashing, the /boot kexec.sig is verified using the standard codebase pattern: sha256sum $(find /boot/kexec*.txt) | gpgv /boot/kexec.sig - kexec.sig covers all /boot files including the backup ROM once the user re-signs /boot after confirming new firmware works. If kexec.sig is missing or invalid a large whiptail_error warning is shown; the user may still override and proceed. If verified, a standard confirmation dialog is shown before flashing with flash.sh -c --no-backup --bypass-verify. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
A new 'F' entry in the Configuration menu opens a Flash Write Options
submenu with three toggles and a diagnostic:
v - Enable/disable post-write verification (CONFIG_FLASH_NO_VERIFY)
b - Enable/disable rollback backup before each write
(CONFIG_FLASH_SAVE_BACKUP; backup is on by default)
r - Enable/disable automatic rollback countdown on failed boot
detection (CONFIG_FLASH_AUTO_ROLLBACK; on by default)
w - Show current SPI write protection status (live flashprog query)
All toggles update /etc/config.user immediately via set_user_config and
take effect on the next flash.sh call. They persist across reboots when
the configuration is saved. The menu re-sources /tmp/config on each
loop iteration so the displayed Enable/Disable label stays accurate.
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…ash calls
These callers write only CBFS-level changes (GPG keys, user config,
OEM setup image) rather than user-selected firmware updates. Saving a
rollback backup before these writes is incorrect: the backup would
contain the same firmware the caller is about to re-flash with minor
CBFS modifications, and the pending_rollback marker would spuriously
trigger the auto-rollback countdown on the next boot.
Add --no-backup to suppress both the backup read and the
pending_rollback marker for:
gpg-gui.sh gpg_flash_rom() - GPG key reflash
oem-factory-reset OEM setup image reflash
config-gui.sh save-config reflash (3 call sites: save user
config, factory reset, disable restricted boot)
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
All commits require both a GPG signature and a DCO sign-off (git commit --signoff), certifying the contributor wrote the code and has the right to submit it under the project licence. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…ammer internal --wp-status' Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Required by initrd/tests/wp/wp-debug to read the PCH SPI BAR base address via 'setpci -s 00:1f.5 0x10.L', which is used to identify the HSFS register location and report FLOCKDN state. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Prevent path traversal via a tampered rollback marker file:
- Read only the first line of the marker (blocks multi-line injection)
- Resolve the path with readlink -f before using it
- Validate the resolved path matches /boot/<brand>/backup_*.rom
pattern; clear the marker and continue boot if it does not
- Use the resolved, validated path for the actual reflash
Also correct the comment in init for the manual rollback path ('b'):
the fallback-to-most-recent-backup behaviour described in the old
comment was never implemented; check_pending_rollback() returns
silently when no marker is present, so boot just continues.
Signed-off-by: Thierry Laurion <insurgo@riseup.net>
…grammer Enables all 'flashprog wp' subcommands on PCH100+ chipsets (Meteor Lake etc.) where flash is exposed via hardware sequencing (hwseq/opaque master) and the chip's STATUS register is not directly addressable. Patches 0100, 0300, 0400 and the ich_hwseq_read_status / ich_hwseq_write_status functions in 0200 are backported from upstream flashrom (https://github.com/flashrom/flashrom), where this infrastructure was contributed by the Dasharo/3mdeb team (SergiiDmytruk, Pokisiekk, macpijan, krystian-hebel and others). See: https://review.coreboot.org/c/flashrom/+/68179 linuxboot#1741 The PRR-based WP functions in 0200 (ich_hwseq_wp_read_cfg, ich_hwseq_wp_write_cfg, ich_hwseq_wp_get_ranges) are original heads work and are not present in upstream flashrom or Dasharo's fork. Protection is enforced only when FLOCKDN is set at lock_chip/kexec time. coreboot pre-programs PRR0 with WP=1 as preparation, but ich9_set_pr() clears those bits when FLOCKDN=0, so protection is not actually enforced during heads execution. wp status correctly reports 'disabled' in this state and 'hardware' only when FLOCKDN=1 with active PRR WP bits. Four patches applied in order to flashprog 1.5: 0100 - include/programmer.h: add read_register, write_register, wp_read_cfg, wp_write_cfg, wp_get_ranges callbacks to struct opaque_master so programmers can provide WP operations directly. [backport] 0200 - ichspi.c: ich_hwseq_read_status / ich_hwseq_write_status for STATUS register access via hwseq cycle types 8/7 [backport]; plus ich_hwseq_wp_read_cfg (FLOCKDN-aware PRR read), ich_hwseq_wp_write_cfg (PRR encode + WP bit), ich_hwseq_wp_get_ranges (power-of-2 top fractions). All hooks wired into opaque_master_ich_hwseq. [original] 0300 - writeprotect.c, include/writeprotect.h: dispatch register reads/writes through opaque master callbacks on BUS_PROG chips. Add and export wp_operations_available(). [backport] 0400 - libflashprog.c: try programmer-level WP override before chip-level and generic SPI paths. Previously all WP calls returned CHIP_UNSUPPORTED for opaque chips. [backport] Tested on novacustom-v560tu (Intel Meteor Lake, PCH100+): Before lock_chip (FLOCKDN=0): wp status=disabled; PASS=8 FAIL=0 SKIP=0 After lock_chip (FLOCKDN=1): wp status=hardware; PASS=6 FAIL=0 SKIP=2 Signed-off-by: Thierry Laurion <insurgo@riseup.net>
flashprog wp subcommands (status, list, enable, disable, range) do not accept --ifd, -i <region>, or --image <region> layout flags. Boards like novacustom-v560tu/v540tu include these in CONFIG_FLASH_OPTIONS, causing 'unrecognized option' errors from check_spi_wp() and the config-gui WP status check. Strip --ifd, --image <region>, and -i <region> alongside --progress when building wp_opts in both flash.sh and config-gui.sh. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
wp-debug: collects flashprog wp status/list/verbose output, HSFS/FLOCKDN state via setpci, /proc/mtd, and dmesg SPI lines into a single report. Run and attach when filing flash write protection issues. wp-test: functional test suite for the opaque/hwseq WP path on Intel PCH100+ hardware. Tests 1-6 validate read paths (wp status, wp list, FLOCKDN detection, mode accuracy). Tests 7-8 exercise write paths (wp disable, wp range + wp enable) and are skipped when FLOCKDN=1 prevents PRR modification. Both scripts strip --ifd, --image <region>, and -i <region> from CONFIG_FLASH_OPTIONS before passing to flashprog wp subcommands, which do not accept layout flags. Expected results: Before lock_chip (FLOCKDN=0): PASS=8 FAIL=0 SKIP=0 After lock_chip (FLOCKDN=1): PASS=6 FAIL=0 SKIP=2 Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Documents the 'flashprog wp' subcommands for heads-supported Intel PCH hardware: wp status, wp list, wp disable, wp range + wp enable. Explains the FLOCKDN/lock_chip lifecycle and PCH100+ PRR mechanics. Includes real hardware output from novacustom-v560tu before and after lock_chip, and documents the wp-test and wp-debug scripts with expected results. Credits the Dasharo/3mdeb team for the upstream flashrom WP infrastructure that these patches backport. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
46aa161 to
9dd69c8
Compare
|
@i-c-o-n this is PoC but seems to work with internal programmer (opaque) on pch100 (tested v540tu/v560tu Novacustom laptops with Dasharo fork) with patches added on top of flashprog 1.5. See here are debug and tests output from this PR. wp-debug_before-lock_chip.log |
Update status from 'WP still unused' to reflect that flashprog wp subcommands now work on PCH100+ (Meteor Lake) via PRR-based protection. Note FLOCKDN-aware behaviour, Dasharo/3mdeb attribution, test results, and pointer to doc/flashprog-wp.md. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
On ICH9/pre-PCH100 platforms (e.g. ThinkPad X230, Intel QM77/Ivy Bridge), Protected Range Registers may be write-locked by their own WP bit independently of FLOCKDN. Registering PRR-based wp_read_cfg/wp_write_cfg/wp_get_ranges callbacks on those platforms caused `wp enable` to write an invalid PRR value (0xffff0000 from an unsigned underflow in limit_4k) which the hardware rejects, failing Test 8 of the WP functional test suite. Fix by splitting opaque_master_ich_hwseq into two structs: - opaque_master_ich_hwseq: STATUS register read/write only (Dasharo approach), registered for ICH9/pre-PCH100. WP goes through wp_operations_available() which uses the ich_hwseq_read/write_status callbacks for register access. - opaque_master_ich_hwseq_pch100: adds PRR-based wp_read_cfg/wp_write_cfg/ wp_get_ranges callbacks, registered only for PCH100+ (Meteor Lake and later). This matches the architecture of the Dasharo flashrom fork, which provides ich_hwseq_read/write_status in opaque_master_ich_hwseq but defers WP to the generic SPI STATUS register path via wp_operations_available. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
Dasharo's flashrom fork defines HSFC_FCYCLE_MASK(n), HSFC_CYCLE_WR_STATUS, and HSFC_CYCLE_RD_STATUS constants for the hardware sequencer STATUS register read/write cycle types (7 and 8). Flashprog 1.5 lacks these. Add the same constants to the patch and use them in ich_hwseq_read_status and ich_hwseq_write_status, replacing the inline magic numbers (0x8 and 0x7) with named constants that match Dasharo's naming exactly. This makes the STATUS cycle types self-documenting and the code easier to compare against upstream. Signed-off-by: Thierry Laurion <insurgo@riseup.net>
|
More fixes will come. This is poc code to test flashkeeper iterations an is definitely not ready for production. EDIT:
|
|
So there are two things here:
Both solutions have many pitfalls. I suggest to focus on one, and given that the chip's block protection is more complex, hence more error prone, I'd make it 1. Patches for flashprog are best discussed on review.sourcearcade.org About PRx:
The problems with flash block-protection settings over
|
Automated firmware backup and rollback
Before each flash write,
flash.shsaves the current firmware to/boot/<brand>/backup_<board>_<timestamp>.romand drops apending_rollbackmarker pointing to it. On the next boot,check_pending_rollback()fires a 30-second countdown; on timeout thebackup is automatically reflashed and the system reboots. Pressing
Enter cancels.
flash-gui: new Rollback menu entry for manual rollback withkexec.sigintegrity check.config-gui: new Flash Write Options submenu exposing--bypass-verifyand--no-backupflags.--no-backupadded to trusted internal callers (gpg-gui,oem-factory-reset, rollback itself) to prevent infinite reflash loops.--bypass-verify/CONFIG_FLASH_NO_VERIFY=yskips post-writeverification.
validation).
flash.shCLI rewritten: argument parsing,check_spi_wp()pre-flashWP query, logging via
INFO/DEBUG/NOTE.update_plain_ext,single_glob,prepare_flash_image) promoted fromflash-guitoetc/functions.SPI Write Protection — PCH100+ (Meteor Lake)
flashprog wpsubcommands (status,list,disable,range,enable) are now functional on PCH100+ chipsets where flash is accessedvia hardware sequencing (opaque/hwseq programmer).
setpci(required bywp-debug).contributed by the Dasharo/3mdeb team.
See review.coreboot.org/c/flashrom/+/68179
and heads#1741.
ich_hwseq_wp_read_cfg— reports
disabledbeforelock_chip(FLOCKDN=0) andhardwareafter (FLOCKDN=1, PRRs frozen).
--ifd,-i,--image) stripped fromCONFIG_FLASH_OPTIONSbefore passing towpsubcommands.initrd/tests/wp/wp-test) and debug collector(
initrd/tests/wp/wp-debug) added.doc/flashprog-wp.md;WP_NOTES.mdupdated.CONTRIBUTING.md: note DCO sign-off requirement.Tested on novacustom-v560tu (Intel Meteor Lake):
lock_chip(FLOCKDN=0)lock_chip(FLOCKDN=1)Test plan
/boot/<brand>/backup_*.romandpending_rollbackmarker createdrollback succeeds
config-guiFlash Write Options submenu and flags persist--no-backupsuppresses backup on OEM factory reset andgpg-guitrusted flash pathsinitrd/tests/wp/wp-test—expect PASS=8 FAIL=0 SKIP=0 before
lock_chip, PASS=6 FAIL=0SKIP=2 after
initrd/tests/wp/wp-debug; confirm FLOCKDN state and PRRoutput match hardware