USB factory-flash bundle
pv-flash-bundle (recipes-bsp/pv-flash/pv-flash-bundle.bb) is meta-pantavisor's
preferred way to flash devices that program their on-board storage over USB
instead of via a plain .wic write — NXP i.MX boards through NXP's UUU tool, and
Rockchip boards through rkdeveloptool. It bundles the image payload, the host
flashing tool as a portable binary, a boot/recovery loader, and generated flash
scripts into a single pv-flash-bundle-${MACHINE}.tar.gz, so flashing needs
nothing beyond a USB cable and the extracted archive.
Every currently supported board in Getting Started that flash-over-USB uses this recipe:
- Toradex — Verdin iMX8MM and Colibri iMX6ULL; see Flashing Toradex Modules for the end-user procedure.
- Variscite — DART-MX8M-MINI and VAR-SOM-MX8M-NANO; see Flashing via NXP uuu for the end-user procedure.
- NXP i.MX8QXP MEK — Board Guide; also covered by Flashing via NXP uuu.
- Rockchip — Orange Pi 5B (RK3588S); see Flashing Rockchip devices for the end-user procedure.
This page covers how the recipe itself is built and how to wire up a new machine.
Design
The recipe has no compile step — do_configure and do_compile are
noexec. All the work happens in a single do_deploy task that copies
pre-built artifacts into a bundle directory, expands two .in script
templates, and tars the result.
Everything machine-specific is expressed as PV_FLASH_* variables, set per
machine in kas/machines/<machine>.yaml (local_conf_header) or in the
release build-config (kas/build-configs/release/<machine>-scarthgap.yaml).
The recipe itself never mentions a machine name — adding a new board is a
matter of setting variables and dropping in templates, not editing the .bb.
| Variable | Role | Default |
|---|---|---|
PV_FLASH_IMAGE | Image recipe whose rootfs goes into the bundle | pantavisor-starter |
PV_FLASH_TOOL | Host flashing tool bundled and driven by flash.sh: uuu (NXP SDP/fastboot) or rkdeveloptool (Rockchip Maskrom) | uuu (set to rkdeveloptool for orangepi-5b) |
PV_FLASH_RK_LOADER | rkdeveloptool only: glob for the Rockchip USB loader (DDR init + miniloader/usbplug) in the main build's DEPLOY_DIR_IMAGE; installed into the bundle as loader.bin and passed to rkdeveloptool db | (none, set for orangepi-5b) |
PV_FLASH_RECOVERY_MC | Multiconfig that builds the recovery U-Boot | (none) |
PV_FLASH_RECOVERY_RECIPE | Recipe to build in that multiconfig (e.g. u-boot-toradex) | (none) |
PV_FLASH_RECOVERY_IMAGE | Filename of the recovery U-Boot in the recovery MC's deploy dir | (none) |
PV_FLASH_BOOT_IMAGE | Glob for a boot binary sourced directly from the main build's DEPLOY_DIR_IMAGE — for machines whose production bootloader already self-enters SDP/fastboot download mode | (none, set for imx8mm-var-dart/imx8mn-var-som/imx8qxp-b0-mek) |
PV_FLASH_NAND_UBOOT | Production NAND U-Boot filename (NAND machines only) | (none, set for colibri-imx6ull) |
PV_FLASH_UBIFS | UBIFS rootfs filename (NAND machines only) | (none, set for colibri-imx6ull) |
PV_FLASH_UUU_SCRIPT_IN | file://uuu.auto.in template SRC_URI entry | (none) |
PV_FLASH_FLASH_SCRIPT_IN | file://flash.sh.in template SRC_URI entry | (none) |
PV_FLASH_README_IN | file://README.md.in template SRC_URI entry — an optional README.md shipped inside the bundle (host prerequisites, OS constraints) | (none, set for orangepi-5b) |
Leaving PV_FLASH_UBIFS/PV_FLASH_NAND_UBOOT empty (the eMMC default) makes
do_deploy bundle whichever compressed WIC image the main build produced —
.wic.zst and/or .wic.gz (+ .wic.bmap if present) — instead of a raw
UBIFS image.
do_deploy steps
- Rootfs artifact — installs
${PV_FLASH_IMAGE}-${MACHINE}.rootfs.ubifsifPV_FLASH_UBIFSis set, otherwise whichever of.wic.zst/.wic.gzis present inDEPLOY_DIR_IMAGE(+.wic.bmap); both are installed if both exist, and the uncompressed.wicis used as a fallback when the main build produced no compressed variant. - Recovery U-Boot — installs
PV_FLASH_RECOVERY_IMAGEfromRECOVERY_DEPLOY_DIR_IMAGE(tmp-${DISTRO_CODENAME}-${PV_FLASH_RECOVERY_MC}/deploy/images/${MACHINE}), pulled in viado_deploy[mcdepends]onmc::${PV_FLASH_RECOVERY_MC}:${PV_FLASH_RECOVERY_RECIPE}:do_deploy— only added if that multiconfig is actually listed inBBMULTICONFIG. - NAND U-Boot — installs
PV_FLASH_NAND_UBOOTfrom the same recovery deploy dir, if set. - Boot image from the main build — if
PV_FLASH_BOOT_IMAGEis set, globs it out of${DEPLOY_DIR_IMAGE}(the machine's own build, not a recovery MC) and installs it into the bundle as the fixed nameimx-boot.bin. Nomcdependsneeded here: the boot binary is guaranteed present already, since${PV_FLASH_IMAGE}:do_image_complete(indo_deploy[depends]) transitively requires the WKS's bootloader partition to be built first. - Flashing tool — for
PV_FLASH_TOOL = "uuu"(default), copiesuuufromuuu-native:do_populate_sysroot; forPV_FLASH_TOOL = "rkdeveloptool", copiesrkdeveloptoolfromrkdeveloptool-native:do_populate_sysrootand globsPV_FLASH_RK_LOADERout of${DEPLOY_DIR_IMAGE}into the bundle as the fixed nameloader.bin(do_deploy[depends]onvirtual/bootloader:do_deployguarantees the loader is present). Either way,patchelf --set-interpreter /lib64/ld-linux-x86-64.so.2 --set-rpath ""is run on the copied binary so it runs on an arbitrary x86-64 Linux host regardless of its build sysroot. Therkdeveloptoolbuild linkslibusb-1.0dynamically, so the flashing host must have that library installed. - Script generation —
sed-expands@WIC@ @WIC_GZ@ @WIC_ZST@ @UBIFS@ @UBOOT_NAND@ @RECOVERY_IMAGE@inuuu.auto.inandflash.sh.in(staged viaFILESEXTRAPATHS:prependfromfiles/${MACHINE}/) intouuu.autoandflash.shin the bundle.imx-boot.bin(step 4) andloader.bin(step 5) are referenced as literal filenames in those templates instead, since their bundle names are fixed by the recipe rather than expanded from a variable. IfPV_FLASH_README_INis set,README.md.inis expanded the same way intoREADME.mdin the bundle. Everyflash.sh.inresolves the tool at run time —$UUU/$RKDEVELOPTOOLif set, else the bundled./uuu/./rkdeveloptool, else the tool onPATH— and prefixessudoonly when not already root, so a bundle can also be driven from a container or host that ships its own tool (see Flashing via NXP uuu and Flashing Rockchip devices). - Package — tars the bundle directory as
${PN}-${MACHINE}.tar.gzand symlinks${PN}-${MACHINE}-latest.tar.gz.
Per-machine templates
Machine-specific flashing logic lives entirely in files/<machine>/uuu.auto.in
(UUU machines) and files/<machine>/flash.sh.in — the recipe code is identical
for every machine.
- verdin-imx8mm (eMMC): SDP boot of the recovery U-Boot (SPL then full
image, VID/PID
0x1b67:0x4fff), jump to fastboot (0x1b67:0x4000), thenFB: flash -raw2sparse all @WIC@writes the disk image directly to eMMC.flash.sh.indecompresses@WIC_GZ@to@WIC@first, since UUU's-raw2sparsepath does not accept gzip input. - colibri-imx6ull (NAND): single-stage SDP boot (no SPL), fastboot mode,
then the recovery U-Boot is written raw to the
u-boot1/u-boot2NAND offsets (bypassing the productionroMTD flag), theu-boot-envpartition is erased so a stale environment can't override the new build'sbootcmd, and finally theubipartition is erased, abootUBI volume created, and the UBIFS rootfs written into it. - imx8mm-var-dart / imx8mn-var-som (eMMC, Variscite): SDP boot of the
production
imx-boot.bin(no recovery build — see below), SPL then full U-Boot viaSDPV: write -skipspl+jump, thenFB: flash -raw2sparse all @WIC@. NoCFG:VID/PID overrides: unlike Toradex, Variscite doesn't rebrand the fastboot USB IDs away from NXP's defaults, souuuauto-detects the device. Mirrors NXP mfgtools' built-inemmc_allscript, minus itsbootloader/mmc partconfsteps — Variscite's WKS (wic/imx-imx-boot-singlepart.wks.in) already embedsimx-bootas a raw-offset region inside the.wicitself, so flashing the whole.wicalready writes the bootloader; there's no separate eMMC boot-partition switch to make.flash.sh.indecompresses@WIC_ZST@(viazstd) to@WIC@if present, falling back to@WIC_GZ@(viazcat) otherwise — whichever compressionIMAGE_FSTYPESactually produced for the main build. - imx8qxp-b0-mek (eMMC, NXP eval board): a single
SDPS: boot -scantermcommand instead ofSDP:/SDPV:— i.MX8QXP/8QM silicon's ROM supports "stream" SDP mode, where the SCU loads the whole boot container (SCFW + ATF + OP-TEE + U-Boot) in one transfer with no separate SPL-jump step to script. Then the sameFB: flash -raw2sparse all @WIC@as the other eMMC machines.mmc dev 0targets eMMC on this board:usdhc1(mmc-hs400-1_8v— an eMMC-only speed mode) probes beforeusdhc2(sd-uhs-sdr104— SD card), and no/aliasesoverride reorders them, sousdhc1gets U-Boot device index 0. - orangepi-5b (eMMC, Rockchip RK3588S —
PV_FLASH_TOOL = "rkdeveloptool"): nouuu.auto.in.flash.sh.inwaits for a device in USB Maskrom mode (rkdeveloptool ld | grep -i maskrom), sends the loader to SoC SRAM (rkdeveloptool db loader.bin), streams the whole disk image to eMMC (rkdeveloptool wl 0 @WIC@— sector 0, so the GPT, idbloader, U-Boot and rootfs are all written), thenrkdeveloptool rdreboots.loader.binis the JeffyCNu-boot-rockchip.bbloader.bin(the Rockchip Miniloader, which also provides theusbplugthat handleswl).flash.sh.indecompresses@WIC_ZST@/@WIC_GZ@to@WIC@first if the main build compressed it.
Why Variscite and the MEK don't need a recovery multiconfig
Toradex needs PV_FLASH_RECOVERY_MC because recipes-bsp/u-boot/u-boot%.bbappend
force-overrides CONFIG_BOOTCOMMAND="run distro_bootcmd" on every U-Boot
build in the layer, and Toradex's SDP→fastboot entry is driven by that same
bootcmd. Variscite's u-boot-variscite and the MEK's u-boot-imx recipes
get the same override, but their fastboot entry doesn't depend on it: both
uboot-imx forks' SPL (board/variscite/imx8mm_var_dart/spl.c,
configs/imx8qxp_mek_defconfig) build with CONFIG_SPL_USB_SDP_SUPPORT=y,
so the ROM/SPL-level SDP-to-fastboot handoff happens before bootcmd is
ever evaluated — confirmed by Variscite's own var-uuu-installer recipe (in
meta-variscite-bsp-imx), which bundles the same production build's
imx-boot/.wic/.bmap with no separate recovery step. PV_FLASH_BOOT_IMAGE
exists for exactly this case: pull the boot binary straight from the main
build instead of standing up a second multiconfig.
See Flashing Toradex Modules, Flashing via NXP uuu, and Flashing Rockchip devices for the full step-by-step sequences and hardware-specific notes (NAND geometry, udev rules, boot-mode switches, Maskrom entry, etc).
Build wiring
Release KAS configs list pv-flash-bundle as a build target alongside the
image. Toradex machines also list the recovery multiconfig target; Variscite
machines don't need one:
# verdin-imx8mm-scarthgap.yaml / colibri-imx6ull-scarthgap.yaml
target:
- pantavisor-starter
- mc:tezi-recovery:u-boot-toradex
- pv-flash-bundle
# imx8mm-var-dart-scarthgap.yaml / imx8mn-var-som-scarthgap.yaml /
# imx8qxp-b0-mek-scarthgap.yaml / rockchip-orangepi-5b-scarthgap.yaml
target:
- pantavisor-starter
- pv-flash-bundle
Every machine's config chain ends in the same build-base-starter.yaml (which
sets target: [pantavisor-starter]). The extra targets are declared per machine
as extra_targets in .github/machines.json and appended to the target: list
by .github/scripts/makemachines:
"extra_targets": ["pv-flash-bundle"] // Variscite, NXP MEK, Rockchip
"extra_targets": ["mc:tezi-recovery:u-boot-toradex", "pv-flash-bundle"] // Toradex
This can't live in kas/machines/<machine>.yaml: kas replaces target with
the value from the last file in the chain, and the machine yaml is first — so
makemachines does the append after kas dump.
kas build kas/build-configs/release/verdin-imx8mm-scarthgap.yaml
Artifacts land at
build/tmp-${codename}/deploy/images/${machine}/pv-flash-bundle-${machine}.tar.gz.
Adding a new machine
- Add
recipes-bsp/pv-flash/files/<machine>/flash.sh.in(and, for UUU machines,uuu.auto.in). - Set
PV_FLASH_FLASH_SCRIPT_IN:<machine>(andPV_FLASH_UUU_SCRIPT_IN:<machine>for UUU) tofile://flash.sh.in/file://uuu.auto.ininpv-flash-bundle.bb. - Pick the flashing tool and the loader source:
- NXP i.MX, needs a stripped recovery build (like Toradex): keep
PV_FLASH_TOOL = "uuu"; setPV_FLASH_RECOVERY_MC/PV_FLASH_RECOVERY_RECIPE/PV_FLASH_RECOVERY_IMAGEin the machine'skas/machines/<machine>.yaml, and add the recovery multiconfig target to the release build-config. - NXP i.MX, production bootloader already self-enters SDP/fastboot (like
Variscite — check the SoC vendor SPL for
CONFIG_SPL_USB_SDP_SUPPORT, or a vendor single-build uuu installer recipe): keepPV_FLASH_TOOL = "uuu"; setPV_FLASH_BOOT_IMAGE:<machine>(a glob) directly inpv-flash-bundle.bb. - Rockchip (like
orangepi-5b): setPV_FLASH_TOOL:<machine> = "rkdeveloptool"andPV_FLASH_RK_LOADER:<machine>to the glob for a Maskrom-capable USB loader in the main build'sDEPLOY_DIR_IMAGE(the JeffyCN BSP deploysloader.bin; a mainline-U-Boot BSP has none prebuilt and needs one merged from rkbin withboot_mergerfirst).
- NXP i.MX, needs a stripped recovery build (like Toradex): keep
- For NAND machines, also set
PV_FLASH_NAND_UBOOT/PV_FLASH_UBIFS. - In the machine's
.github/machines.jsonentry set"extra_targets": ["pv-flash-bundle"](add"mc:tezi-recovery:u-boot-toradex"first for the recovery-multiconfig case),"build_target": ""and"output": "pv-flash-bundle-<machine>.tar.gz", then run.github/scripts/makemachinesand.github/scripts/makeworkflows.
No changes to pv-flash-bundle.bb's do_deploy logic are needed unless the
new machine requires a genuinely new flash topology beyond eMMC-wic,
eMMC-boot-image, NAND-UBIFS, or Rockchip Maskrom.
Related
- Flashing Toradex Modules — end-user flashing procedure, prerequisites, and troubleshooting
- Starter Image —
pantavisor-starter, the defaultPV_FLASH_IMAGE - Build System — KAS multiconfig mechanics behind
PV_FLASH_RECOVERY_MC