On AVH, two types of firmware images are supported:
A zip file containing multiple images such as a disk image, kernel or binary firmware etc
A raw binary file, ELF executable or kernel loaded into RAM
The Coreimg Zip Package
The format of the coreimg zip package looks like this:
Required files
Info.plist
(meta information)If what you are booting is Linux
kernel
(a Linux kernel in the Image format)devicetree
(the device tree for Linux in binary .dtb format)
Or if it's a raw firmware (e.g. used by Cortex-M machines)
firmware
(Binary, ELF executable file, ZIP archive with load instructions)
Storage
Most devices have flash specific files that are required. See the relevant storage files page for that specific device.
What does the Info.plist
look like?
An Info.plist
file containing the version, type, build, unique identifier, device identifier, and optionally boot arguments. This can also be a JSON file with the same format.
Example
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Type</key>
<string>iot</string>
<key>UniqueIdentifier</key>
<string>WifiBasics</string>
<key>DeviceIdentifier</key>
<string>stm32u5-b-u585i-iot02a</string>
<key>Version</key>
<string>WifiBasics</string>
<key>Build</key>
<string>WB</string>
</dict>
</plist>
Bootargs
The default bootargs
are provided by the model, but can be overriden via the Info.plist
or Info.json
file. The "normal" key is used for every regular boot. The "restore" key, if present, is used for a "firstboot" prior to the device being declared ready. It is expected that the device will reboot itself to indicate that this phase is complete. It is used, for example, on the Raspberry Pi to expand the root fs
as shown below:
<key>bootargs</key>
<dict>
<key>normal</key>
<string>earlycon=uart8250,mmio32,0xfe215040 console=ttyS0,115200n8 rw rootwait root=/dev/mmcblk0p2 coherent_pool=1M 8250.nr_uarts=1 cma=64M</string>
<key>restore</key>
<string>earlycon=uart8250,mmio32,0xfe215040 console=ttyS0,115200n8 console=tty0 rw rootwait root=/dev/mmcblk0p2 coherent_pool=1M 8250.nr_uarts=1 cma=64M init=/usr/lib/raspi-config/init_resize.sh</string>
</dict>
Raw Firmware
There are three supported formats for executable firmware:
ELF executable: 32-bit ELF program files (fully linked, no relocation required) typically produced by IoT vendor tools: recommended - they contain all information needed to load the program, even if it has multiple memory ranges;
binary: loaded at a predefined location in memory (typically start of Flash for devices with built-in executable Flash, otherwise start of RAM);
ZIP archive: an archive containing a few binary files, and a file called
LOAD.TXT
that instructs the firmware loader to distribute them to different load locations in memory; aLOAD.TXT
file could look like this:
load:0x00000000 name:bl2.bin
load:0x01000000 name:tfm_s_ns_signed.bin
This LOAD.TXT
file would cause file bl2.bin
in the same ZIP archive to be loaded at address 0x00000000
, and tfm_s_ns_signed.bin
at 0x01000000
. This format is required when all that's available is binary files, and there's more than one of them.
Sample Firmware Packaging Script for Raspberry Pi
#!/bin/bash
set -e
[ -d pi ] || mkdir pi
cd pi
# Grab the raspberry pi firmware
[ -f 2022-01-28-raspios-bullseye-arm64.zip ] || wget https://downloads.raspberrypi.org/raspios_arm64/images/raspios_arm64-2022-01-28/2022-01-28-raspios-bullseye-arm64.zip
rm -rf {nand,devicetree,kernel,Info.plist,boot,rootfs}
unzip 2022-01-28-raspios-bullseye-arm64.zip
mv 2022-01-28-raspios-bullseye-arm64.img nand
# Mount the firmware image and extract the kernel and device tree
LO="$(losetup -f)"
mkdir boot
losetup -P "${LO}" nand
mount "${LO}p1" boot
# Enable ssh
touch boot/ssh
cp boot/bcm2711-rpi-4-b.dtb devicetree
zcat boot/kernel8.img > kernel
umount boot
rm -rf boot
mkdir rootfs
mount "${LO}p2" rootfs
# Don't run dhcpcd on docker interfaces
echo 'denyinterfaces veth*' >> rootfs/etc/dhcpcd.conf
umount rootfs
rm -rf rootfs
losetup -d "${LO}"
# create the Info plist that describes the model image
cat << EOF > Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Type</key>
<string>iot</string>
<key>UniqueIdentifier</key>
<string>Raspberry Pi OS Desktop</string>
<key>DeviceIdentifier</key>
<string>rpi4b</string>
<key>Version</key>
<string>11.2.0</string>
<key>Build</key>
<string>desktop</string>
</dict>
</plist>
EOF
# zip image and its ready for use
zip -r ../rpi4b-11.2-desktop.zip Info.plist nand devicetree kernel ramdisk.img