#1089611 vboot-utils: flashrom invocations incompatible with upstream flashrom

#1089611#5
Date:
2024-12-09 21:36:22 UTC
From:
To:
Hello,

The Debian build of `crossystem` displays errors related to flashrom
invocations and fails to read/write several important values (presumably
depending on the hardware). I'm attaching the `crossystem --all` output
from one of my devices.

The error is because the source code assumes "flashrom" is the
ChromiumOS fork of flashrom, and not the upstream flashrom. I can
identify three differences in the way it is called:

- `-p host` is not supported, `-p linux_mtd` works on my boards
- `--fmap` is not the default and must be added to arguments
- `-r` and `-w` need a whole rom file even with `-i $region:$file`

As a workaround I have written a flashrom wrapper that converts the
invocations I found, crossystem works if I place it in /usr/local/sbin/.
But I guess it isn't enough for all cases. There seems to be more places
where flashrom is used e.g cgpt, futility; sometimes by exact path.

Please review any flashrom invocations and replace them with
upstream-compatible ones. Or perhaps poke ChromiumOS folks to do it in
upstream vboot_reference.

(I suspect the unpackaged dependency makes this a Severity: serious.)

#1089611#10
Date:
2026-07-20 00:24:19 UTC
From:
To:
Independently hit this on real hardware; confirming the analysis in the
original report and attaching a tested patch.

On ARM Chromebooks running Debian, crossystem cannot write any vboot
NV flag.  Every write fails like this (observed on a Lenovo IdeaPad
Slim 3 Chrome 14M868, ChromeOS board "magneton", device tree
compatible google,steelix-sku393218 / mediatek,mt8186, "corsola"
family, running Debian testing):

  root@trotamar3:~# crossystem dev_boot_usb=1
  Flashrom invocation failed (exit status 1): flashrom -p host -r -i RW_NVRAM:/tmp/vb2_flashrom.MVAiey
  Failed to set parameter dev_boot_usb

The same failure affects "crossystem disable_dev_request=1" and every
other NV flag write, which breaks developer-mode workflows for Debian
on these machines.

Root cause
----------

On this platform the vboot NV data lives in the SPI flash FMAP region
RW_NVRAM.  crossystem (host/lib/crossystem.c via host/lib/flashrom.c)
executes the flashrom binary using the conventions of the ChromiumOS
flashrom fork:

 * programmer alias "-p host", which does not exist in upstream
   flashrom (the fork's cros_alias.c dispatches it to its internal
   programmer, which tries the Linux MTD interface first);

 * an implicit FMAP layout for "-i RW_NVRAM": upstream flashrom only
   honours "-i" together with an explicit layout source, e.g. --fmap.

Debian ships upstream flashrom, so the invocation fails before it
even touches the hardware.  The following manual invocation was
verified to work on the machine above (the AP SPI-NOR is exposed as
/dev/mtd0, and the region contains the expected 16-byte vb2 nvdata
ring):

  flashrom -p linux_mtd:dev=0 --fmap -r -i RW_NVRAM:/tmp/nvram.bin

This is the same root cause as reported in #1089611; the present
report adds analysis and a tested patch for the crossystem NV data
path.

Fix
---

The patch below makes the flashrom invocations in
host/lib/flashrom.c compatible with upstream flashrom:

 * translate exactly the "host" programmer alias to "linux_mtd" at
   invocation time; any other programmer string is passed through
   untouched;

 * pass --fmap whenever a region is accessed with -i.

The translation is deliberately narrow.  In this source tree the
flash-backed NV data path is only ever reached from the ARM backend
(host/arch/arm/lib/crossystem_arch.c), and only when the firmware
device tree explicitly declares nonvolatile-context-storage = "flash";
the x86 backends keep NV data in CMOS/ACPI and never call this code.
On the machines that do reach it, the AP flash is exposed as an MTD
device, which is what upstream's linux_mtd programmer drives (it
defaults to mtd0 and refuses devices that are not NOR flash).  There
is intentionally no fallback to upstream's "internal" programmer and
no runtime guessing between flash access methods: if no suitable MTD
device exists, flashrom fails cleanly instead of picking another
flash chip to write to.

The mocked flashrom argument parser in the unit test
(tests/vb2_host_flashrom_tests.c) has to learn the new --fmap
argument, since debian/rules runs the test suite during build; the
patch extends the mock (and terminates its getopt_long() option
array, which was missing the required all-zero sentinel) and asserts
that region accesses now request the FMAP layout.

With this change, crossystem NV flag reads and writes work on the
machine above with flashrom 1.6.0.  Note that writing a region
without supplying a full chip image ("-w --fmap -i REGION:file")
requires the optional -r/-w/-v filename support introduced in
upstream flashrom 1.5, so the vboot-utils dependency on flashrom
should probably become versioned, flashrom (>= 1.5~); the flashrom
version in trixie (1.4.0) still requires a full image for -w and
would only gain working reads from this patch.

Long term, the proper fix is syncing the package to a newer upstream
snapshot: current vboot_reference no longer executes the flashrom
binary at all, it uses libflashrom (host/lib/flashrom_drv.c) and
reads the FMAP from flash, so the fork-specific conventions are gone.
The patch below is a minimal interim fix for the packaged snapshot.

The patch applies on top of the current debian/patches series; the
affected unit test (vb2_host_flashrom_tests) passes with it.

Regards,
Daniel

Description: make crossystem flashrom calls work with upstream flashrom
 crossystem reads and writes the vboot NV data by executing the flashrom
 binary, using conventions of the ChromiumOS flashrom fork: the "host"
 programmer alias and an implicit FMAP layout for -i REGION accesses.
 Debian ships upstream flashrom, which has no "host" programmer and
 requires --fmap (or an explicit layout) for region access, so every
 NV flag write, e.g. "crossystem dev_boot_usb=1", fails with
 "Flashrom invocation failed".
 .
 Translate exactly the "host" programmer alias to "linux_mtd" at
 invocation time; any other programmer string is passed through
 untouched.  The NV-data-in-flash path is only ever taken by the ARM
 backend (host/arch/arm/lib/crossystem_arch.c), and only when the
 firmware device tree explicitly declares nonvolatile-context-storage =
 "flash"; on those machines the AP flash is exposed as an MTD device.
 Deliberately no fallback to upstream's "internal" programmer: if no
 suitable MTD device exists, upstream flashrom fails cleanly instead of
 guessing at a flash target.  Pass --fmap whenever a region is accessed.
 Teach the mocked flashrom argument parser in the unit test about the
 new --fmap argument (and terminate its getopt_long() option array).
 .
 Verified on a Lenovo IdeaPad Slim 3 Chrome 14M868
 (google,steelix-sku393218, mediatek,mt8186) running Debian testing.
 Newer upstream vboot_reference no longer executes the flashrom binary
 but uses libflashrom (host/lib/flashrom_drv.c) and reads the FMAP from
 flash, so this patch can be dropped when the package moves to a newer
 upstream snapshot.
Author: Daniel Golle <daniel@makrotopia.org>
Bug-Debian: https://bugs.debian.org/1089611
Forwarded: no
Last-Update: 2026-07-20
---
--- a/host/lib/flashrom.c
+++ b/host/lib/flashrom.c
@@ -85,6 +85,14 @@
 	return rv;
 }

+static const char *resolve_programmer(const char *programmer)
+{
+	if (strcmp(programmer, FLASHROM_PROGRAMMER_INTERNAL_AP) != 0)
+		return programmer;
+
+	return "linux_mtd";
+}
+
 static vb2_error_t run_flashrom(const char *const argv[])
 {
 	int status = subprocess_run(argv, &subprocess_null, &subprocess_null,
@@ -121,9 +129,10 @@
 	const char *const argv[] = {
 		FLASHROM_EXEC_NAME,
 		"-p",
-		image->programmer,
+		resolve_programmer(image->programmer),
 		"-r",
-		region ? "-i" : tmpfile,
+		region ? "--fmap" : tmpfile,
+		region ? "-i" : NULL,
 		region ? region_param : NULL,
 		NULL,
 	};
@@ -152,10 +161,11 @@
 	const char *const argv[] = {
 		FLASHROM_EXEC_NAME,
 		"-p",
-		image->programmer,
+		resolve_programmer(image->programmer),
 		"--noverify-all",
 		"-w",
-		region ? "-i" : tmpfile,
+		region ? "--fmap" : tmpfile,
+		region ? "-i" : NULL,
 		region ? region_param : NULL,
 		NULL,
 	};
--- a/tests/vb2_host_flashrom_tests.c
+++ b/tests/vb2_host_flashrom_tests.c
@@ -35,6 +35,7 @@
 static const char *captured_op_filename;
 static const char *captured_region_param;
 static const char *captured_programmer;
+static int captured_fmap;
 static uint8_t *captured_rom_contents;
 static uint32_t captured_rom_size;

@@ -63,6 +64,13 @@
 			.flag = &captured_verify_int,
 			.val = FLASHROM_VERIFY_FAST,
 		},
+		{
+			.name = "fmap",
+			.has_arg = no_argument,
+			.flag = &captured_fmap,
+			.val = 1,
+		},
+		{ 0 },
 	};

 	/* Reset static variables to their defaults. */
@@ -71,6 +79,7 @@
 	captured_op_filename = NULL;
 	captured_region_param = NULL;
 	captured_programmer = NULL;
+	captured_fmap = 0;
 	captured_rom_contents = NULL;
 	captured_rom_size = 0;
 	optind = 0;
@@ -183,6 +192,7 @@
 		    "Not doing a read of the whole ROM");
 	TEST_STR_EQ(captured_region_param, "SOME_REGION:" MOCK_TMPFILE_NAME,
 		    "Reading to correct file and from correct region");
+	TEST_EQ(captured_fmap, 1, "Using FMAP layout");
 	TEST_EQ(image.size, strlen(MOCK_ROM_CONTENTS), "Contents correct size");
 	TEST_SUCC(memcmp(image.data, MOCK_ROM_CONTENTS, image.size),
 		  "Buffer has correct contents");
@@ -251,6 +261,7 @@
 		    "Not doing a write of the whole ROM");
 	TEST_STR_EQ(captured_region_param, "SOME_REGION:" MOCK_TMPFILE_NAME,
 		    "Writing to correct file and from correct region");
+	TEST_EQ(captured_fmap, 1, "Using FMAP layout");
 	TEST_EQ(captured_rom_size, strlen(MOCK_ROM_CONTENTS),
 		"Contents correct size");
 	TEST_SUCC(memcmp(captured_rom_contents, MOCK_ROM_CONTENTS,

#1089611#15
Date:
2026-10-15 11:47:04 UTC
From:
To:
Hello,

Bug #1089611 in vboot-utils reported by you has been fixed in the
Git repository and is awaiting an upload. You can see the commit
message below and you can check the diff of the fix at:

https://salsa.debian.org/debian/vboot-utils/-/commit/faf0c97276ad76625cea30e8738952b344eb4078

(this message was generated automatically)
-- 
Greetings

https://bugs.debian.org/1089611

#1089611#22
Date:
2026-10-15 12:20:24 UTC
From:
To:
We believe that the bug you reported is fixed in the latest version of
vboot-utils, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to 1089611@bugs.debian.org,
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Sophie Brun <sophie@kali.org> (supplier of updated vboot-utils package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing ftpmaster@ftp-master.debian.org)
Format: 1.8
Date: Thu, 15 Oct 2026 11:20:18 +0200
Source: vboot-utils
Architecture: source
Version: 0~R156-16836.B+dfsg-1
Distribution: unstable
Urgency: medium
Maintainer: Debian QA Group <packages@qa.debian.org>
Changed-By: Sophie Brun <sophie@kali.org>
Closes: 1089611 1147927
Changes:
 vboot-utils (0~R156-16836.B+dfsg-1) unstable; urgency=medium
 .
   * New upstream version 0~R156-16836.B+dfsg
   * Build with gcc instead of clang (Closes: #1147927)
   * Refresh patches
   * Remove obsolete machname in debian/rules
   * Fix usage of flashrom (Closes: #1089611): use standard flashrom not the
     Chromium fork
   * Replace build-dep pkg-config with pkgconf
   * Add missing build-dep python3
   * Do not build with libflashrom-dev: it requires the Chromium fork of
     flashrom
   * Remove tests requiring missing binaries (because the binaires contain
     non-free software)
   * Bump Standards-Version to 4.7.4
   * Re enable dh_dwz
   * Do not install libvboothost.so
   * Update debian/watch to version 5
   * Orphan the package
Checksums-Sha1:
 7bda5d69cf1dff175180c9d33dc9b87d0826420c 1735 vboot-utils_0~R156-16836.B+dfsg-1.dsc
 6b2dd4af2d7499e2d62d79599165f9ca5ece4cfe 5960220 vboot-utils_0~R156-16836.B+dfsg.orig.tar.xz
 1725de7c06feb3ff147e77dd3f3d77cb3844aea1 13972 vboot-utils_0~R156-16836.B+dfsg-1.debian.tar.xz
 82327481f1b6abb48fff99bcf68e379990f86582 8806 vboot-utils_0~R156-16836.B+dfsg-1_source.buildinfo
Checksums-Sha256:
 2baebff150f0eafe01ab20d665997259e7e46f632da60482bd25893ab39406e0 1735 vboot-utils_0~R156-16836.B+dfsg-1.dsc
 2afc6f9b8f40952e11b57aa8ff4f99ea3409b4c07f0e391d62aa6cf91f9929be 5960220 vboot-utils_0~R156-16836.B+dfsg.orig.tar.xz
 da219bea1da6b56ca73e8b8536755cb215b37e1c7c7c1d85d72e46d6d06d1247 13972 vboot-utils_0~R156-16836.B+dfsg-1.debian.tar.xz
 2fd5361d6c209d77b2872f028492ed21569c90ea8e82ae45847788bdfc2f0bd0 8806 vboot-utils_0~R156-16836.B+dfsg-1_source.buildinfo
Files:
 1a01ef2f8d69268989c4c6d44ee2a218 1735 admin optional vboot-utils_0~R156-16836.B+dfsg-1.dsc
 86ad864025208f9d437b6edbf2a624e3 5960220 admin optional vboot-utils_0~R156-16836.B+dfsg.orig.tar.xz
 308a2c7d64d357341ea249f13b56bac9 13972 admin optional vboot-utils_0~R156-16836.B+dfsg-1.debian.tar.xz
 86c2ceada46194a3b7d37cd7c75a98d9 8806 admin optional vboot-utils_0~R156-16836.B+dfsg-1_source.buildinfo
iHUEARYKAB0WIQT+vxv1zHPi+qsoK1z+ZsWMCX9qbgUCatC9tAAKCRD+ZsWMCX9q
bjSGAP9BhJLSkArHen4Ou1Pq+S/utkpvBXxSzb79DN75xs6BVgEAtEqGgcLFRrE3
PD3eTnqa733O1bAcap9FBZm6RA0FSAQ=
=v36E
-----END PGP SIGNATURE-----