Secure boot with Raspberry Pi CM4 and Nerves

So this is something I am working on for a client I will reference as REDACTED, because they are :slight_smile:

I’ve discussed it a fair bit with Frank and in the interest of sharing knowledge I will try my best to move all that I can in to the open and summarize what got us here. Hopefully we continue our exchanges unhindered and everyone benefits. Perfect world, I get great input. I have not put it in help, it is more of a project.

CM4 is not an ideal security device due to missing the ability to truly protect a secret in hardware (no, the ATECC for NervesKey has limitations here. no ARM TrustZone is on the SoC but has no secured peripherals or storage to use). More on this another time.

But one smart step is to enable secure boot, lock down the bootloader with the OTP (one-time programmable, not our usual OTP) storage part of eeprom shove a public key in there and then sign the boot.img with a boot.sig according to how raspberry pi wants it done.

This is not how fwup works.

fwup does not generate a full .img. It creates a ZIP archive with the .fw extension, signs it. The archive contains all necessary files and a compiled deterministic set of instructions for setting up partitions, copying files and all that. A .fw can be turned into a .img in a simple way.

Nerves generates a .fw. Secure boot according to CM4 methods would mean generating a Nerves firmware as a boot.img and then wrapping it up in a signature and a few additional files to make it boot.

I’ve done this manually and made it work. The question becomes, how do we tool this well in Nerves? It doesn’t really require changing the base build. I would not sign this way in dev, just prod devices.

mix firmware.sign perhaps? It could use fwup to generate a .fw with the boot.img and boot.sig inside it along with some extras. And that means deploying, updating and binary diffs should still be on the table.

I guess the “outer” .fw should own the data partition and so on and the inner .img just the firmware system. Should keep size down.

@fhunleth this a decent summary? Any further thoughts so far?

2 Likes

I’ve never tried secure boot on a CM4, so my understanding is from skimming Secure boot chain of trust and the Buildroot configuration added by this commit. Please read with a grain of salt. This could be totally wrong.

This setup looks similar at a high level to secure booting with U-Boot. One difference is that the boot.img file that contains the Linux kernel, device tree, initramfs, etc. uses FAT32 as its container format. So, instead of a ZIP or a tarball or flattened image tree (FIT) file, they chose FAT32. Cool.

The auth flow is:

  1. BootROM validates bootsys and then executes it
  2. bootsys validates bootmain and then executes it
  3. bootmain validates your boot.img and then boots the Linux kernel in it
  4. Your initramfs in boot.img needs to verify the root filesystem and then mount it.

Almost everything in Nerves is for putting together the root filesystem. That’s totally separate from the initramfs so it means that you can create it totally separately if you want. I’d use Buildroot to create it since that’s the tool I know and there’s an example Buildroot config that I linked above. It also works to create a Buildroot package that recursively calls Buildroot so you could automate this in a Nerves system build, but maybe don’t do this first step. First step for me would be to create the boot.img binary manually and download/copy it to the images directory in the Nerves system build.

In your initramfs, you’ll need to mount the root filesystem and switch_root to it. If you google around, I think you should find examples on how to do that. I’d skip the root filesystem auth at this point.

Next step is to go back to Nerves, create a nerves_system_rpi4 fork and update it to know about the boot.img file and the boot.sig file that goes with it. Modify the fwup.conf script to delete all of the normal non-root filesystem blobs that fwup writes and then add the boot.img and boot.sig. The final fwup.conf will write boot.img, boot.sig, and rootfs.squashfs. I’m skipping details, but I think that at a high level this should work and you won’t need to modify any Nerves infrastructure.

After this works, I’d implement whatever mechanism that you want to use to authenticate the root filesystem. It can be anything you want since the code to do the authentication goes in the initramfs which is totally under your control. You may be interested in dm-verity.

The extension that Nerves needs is a hook that you can run after the Nerves tooling creates the read-only SquashFS filesystem and before fwup is called to create the .fw file. The hook would turn the SquashFS filesystem into an image that can be authenticated by dm-verity or whatever you choose to use. After that, fwup would include the result in the .fw and write it to eMMC or MicroSD just like normal. Your initramfs would know that the bytes were a dm-verity’d SquashFS.

I think that it’s important to reiterate that there are multiple keys involved. There are the keys used by CM4 to authenticate the boot.img. You have to do whatever the RPi docs say you have to do for those. Then there are the keys you use to authenticate the root filesystem. You can choose any algorithm for those. You just need to put the public keys that you trust in the boot.img. Maybe you have two boot.img’s that you use - one with the dev public key and one with the prod key so the flow is the same for dev and prod. Up to you.

I hope I understand this right. Interesting project.

1 Like

I have made a boot.img from a Nerves BOOT_A and signed it. Then tried booting that using rpiboot from usboot (it doesn’t flash the emmc, just a kind of testboot). And that went fine. So for secure boot itself it is mostly about wrapping up the nerves boot image. Ideally I’d want to do the signing step via fwup so I could have the data partition outside of the boot.img or it will be massive.

The eeprom bootloader stuff I consider fairly separate for now and that is exclusively rpiboot.

I haven’t started on the full disk encryption part as much. Sounds like that will be initramfs and stuff and certainly change things further. Will dig in to what you’ve referenced.

This is the usbboot of a non-locked secure-boot with a Nerves BOOT_A partition as a boot.img with a boot.sig.

RPi: BOOTLOADER release VERSION:f143c43a DATE: 2024/04/16 TIME: 15:37:20
BOOTMODE: 0x07 partition 0 build-ts BUILD_TIMESTAMP=1713278240 serial 2f2a72cf boardrev b03141 stc 1766378519
Boot mode: RPIBOOT (03) order f25641
secure-boot
Loading boot.img ...
boot.sig
hash: c429ef0fbeba8269bdae601bfc0ec7e1c8f8cb9b2686f9a0c1c3131c2c5fe957
ts: 1713951942
rsa2048: 2b534573150693d45aef4198647315eaef34f260afff921404263362e755fa52dd42ff0f95e6d89dea1ffde0b439f4cc6469a96d07765796e86412d5e99ee35a0e38aeeb28f9d7b23b3f9cfd230bc53730a1f082be744e849142f46cf79e785830064be68dabbbd1dbaf391146a1f59a4d5c172664af72782b0ee58181bfa4191bb25a032602b53078c4d9d210b507fef28a9a30173885cbd1d2726a7ac76cd36ad542316d47a48cff78353bc220e64483ce4e4885e4cf1be403db7119e34e9e7fb5f39fb6e0c9b9a85094383fa3ea52c94668e1a914a177f9ca7830fee0379792532294a239627a7ef3a55f588ff7b2565c275beab885a650316f3d054e6092
Verifying
RSA verify
rsa-verify pass (0x0)
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
Trying partition: 0
type: 16 lba: 0 'MSDOS5.0' '            ' clusters 38295 (1)
rsc 1 fat-sectors 151 root dir cluster 1 sectors 32 entries 512
FAT16 clusters 38295
Read config.txt bytes     1937 hnd 0x16fd
[ramdisk] pieeprom.upd not found
[ramdisk] recover4.elf not found
[ramdisk] recovery.elf not found
Read start4.elf bytes  3002536 hnd 0x14
Read fixup4.dat bytes     8399 hnd 0x3
0x00b03141 0x00000000 0x00001fff
MEM GPU: 192 ARM: 832 TOTAL: 1024
Firmware: 30f0c5e4d076da3ab4f341d88e7d505760b93ad7 Oct 17 2023 15:40:00
Starting start4.elf @ 0xfec00200 partition 0
PCI0 reset
USB-OTG disconnect
+

[    0.587228] brcm-pcie fd500000.pcie: link down
erlinit: The shell will be launched on tty 'tty1'.

erlinit: If you would like the shell to be on this tty,

erlinit: configure erlinit with '-c ttyS0'.

erlinit: The hostname is 'nerves-72cf'.

I assume the things get more interesting and that initramfs comes into the picture when I want an image with a partition scheme I can actually flash to the device. I know we spoke about this during NervesConf. I will try to follow the steps you outlined above and get it going. I expect plenty of confusion :slight_smile:

This was a bit odd:

==> nerves
==> secure_outer_rpi4
Generated secure_outer_rpi4 app
==> sec_fw

Nerves environment
  MIX_TARGET:   rpi4
  MIX_ENV:      dev

Discovered devices:
0) 0.0 GiB found at /dev/sdb
1) 7.28 GiB found at /dev/sdg
Which device do you want to burn to? 1
 99% [=================================== ] 39.80 MB in / 49.78 MB out       
fwup: Can't open file on FAT partition(boot.sig): FATFS: There is no valid FAT volume

And it does not boot:

RPi: BOOTLOADER release VERSION:e608a69d DATE: 2024/04/15 TIME: 14:12:14
BOOTMODE: 0x06 partition 0 build-ts BUILD_TIMESTAMP=1713186734 serial 2f2a72cf boardrev b03141 stc 477024
PM_RSTS: 0x00001000
part 00000000 reset_info 00000000
uSD voltage 3.3V
Initialising SDRAM 'Samsung' 16Gb x1 total-size: 16 Gbit 3200
DDR 3200 0 0 16 152

Boot mode: SD (01) order f2564
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
SD HOST: 200000000 CTL0: 0x00800f00 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
EMMC
SD retry 1 oc 0
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
OCR c0ff8080 [0]
CID: 001501003847544634520680754ad9ca
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 25000000 Hz actual: 25000000 HZ div: 8 (4) status: 0x1fff0000 delay: 4
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 50000000 Hz actual: 50000000 HZ div: 4 (2) status: 0x1fff0000 delay: 2
MBR: 0x0000003f,   38630 type: 0x0c
MBR: 0x00012e0c,  289044 type: 0x83
MBR: 0x000a0034,14614476 type: 0x83
MBR: 0x00000000,       0 type: 0x00
Trying partition: 0
type: 16 lba: 63 oem: 'MSDOS5.0' volume: '            '
rsc 1 fat-sectors 151 c-count 38295 c-size 1
root dir cluster 1 sectors 32 entries 512
FAT16 clusters 38295
Trying partition: 0
type: 16 lba: 63 oem: 'MSDOS5.0' volume: '            '
rsc 1 fat-sectors 151 c-count 38295 c-size 1
root dir cluster 1 sectors 32 entries 512
FAT16 clusters 38295
secure-boot
Loading boot.img ...
Error 6 loading boot.img
Boot mode: USB-MSD (04) order f256
PCIe timeout: 0x0000008f
USB xHC init failed
Boot mode: NVME (06) order f25
PCIe timeout: 0x0000008f
Failed to open device: 'nvme'
Retry NVME 1
PCIe timeout: 0x0000008f
Failed to open device: 'nvme'
Boot mode: BCM-USB-MSD (05) order f2
XHCI-STOP
xHC ver: 272 HCS: 01000140 0c0000f1 07ff000a HCC: 0220fe65
xHC ports 1 slots 64 intrs 1
USB2[1] 000206e1 connected
USB2[1] 00200e03 connected enabled
USB2 root HUB port 1 init
DEV [01:00] 2.00 000000:01 class 9 VID 0424 PID 2514
HUB init [01:00] 2.00 000000:01
XHCI-STOP
xHC ver: 272 HCS: 01000140 0c0000f1 07ff000a HCC: 0220fe65
USBSTS 18
USB MSD stopped. Timeout: 25 seconds

I have some other stuff to try with the flashing. But not sure what fwup is angry about…

Ah, their secure-boot-msd is not the way to flash it, probably.

Misread the fwup error. I’m doing fat_write on something that probably is not fat…

Because I misread Frank’s post. Lets compile a new one…

Sometimes, success is a kernel panic:

RPi: BOOTLOADER release VERSION:e608a69d DATE: 2024/04/15 TIME: 14:12:14
BOOTMODE: 0x06 partition 0 build-ts BUILD_TIMESTAMP=1713186734 serial 2f2a72cf boardrev b03141 stc 477024
PM_RSTS: 0x00001000
part 00000000 reset_info 00000000
uSD voltage 3.3V
Initialising SDRAM 'Samsung' 16Gb x1 total-size: 16 Gbit 3200
DDR 3200 0 0 16 152

Boot mode: SD (01) order f2564
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
SD HOST: 200000000 CTL0: 0x00800f00 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
EMMC
SD retry 1 oc 0
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
OCR c0ff8080 [0]
CID: 001501003847544634520680754ad9ca
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 25000000 Hz actual: 25000000 HZ div: 8 (4) status: 0x1fff0000 delay: 4
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 50000000 Hz actual: 50000000 HZ div: 4 (2) status: 0x1fff0000 delay: 2
MBR: 0x0000003f,   77260 type: 0x0c
MBR: 0x00012e0c,  289044 type: 0x83
MBR: 0x000a0034,14614476 type: 0x83
MBR: 0x00000000,       0 type: 0x00
Trying partition: 0
type: 32 lba: 63 oem: 'MSDOS5.0' volume: ' NO NAME    '
rsc 32 fat-sectors 604 c-count 76020 c-size 1
root dir cluster 2 sectors 0 entries 0
FAT32 clusters 76020
Trying partition: 0
type: 32 lba: 63 oem: 'MSDOS5.0' volume: ' NO NAME    '
rsc 32 fat-sectors 604 c-count 76020 c-size 1
root dir cluster 2 sectors 0 entries 0
FAT32 clusters 76020
secure-boot
Loading boot.img ...
SIG boot.sig c429ef0fbeba8269bdae601bfc0ec7e1c8f8cb9b2686f9a0c1c3131c2c5fe957 1713951942
Verifying
RSA verify
rsa-verify pass (0x0)
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
Trying partition: 0
type: 16 lba: 0 oem: 'MSDOS5.0' volume: '            '
rsc 1 fat-sectors 151 c-count 38295 c-size 1
root dir cluster 1 sectors 32 entries 512
FAT16 clusters 38295
Read config.txt bytes     1937 hnd 0x16fd
Read start4.elf bytes  3002536 hnd 0x14
Read fixup4.dat bytes     8399 hnd 0x3
0x00b03141 0x00000000 0x00001fff
MEM GPU: 192 ARM: 832 TOTAL: 1024
Firmware: 30f0c5e4d076da3ab4f341d88e7d505760b93ad7 Oct 17 2023 15:40:00
Starting start4.elf @ 0xfec00200 partition 0
+

[    0.586649] brcm-pcie fd500000.pcie: link down
[    0.881216] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2)
[    0.889796] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.1.73-v8 #1
[    0.896077] Hardware name: Raspberry Pi Compute Module 4 Rev 1.1 (DT)
[    0.902614] Call trace:
[    0.905095]  dump_backtrace.part.0+0xdc/0xf0
[    0.909451]  show_stack+0x18/0x30
[    0.912824]  dump_stack_lvl+0x64/0x80
[    0.916548]  dump_stack+0x18/0x34
[    0.919914]  panic+0x188/0x344
[    0.923015]  mount_block_root+0x220/0x240
[    0.927092]  mount_root+0x180/0x1a0
[    0.930636]  prepare_namespace+0x124/0x164
[    0.934796]  kernel_init_freeable+0x26c/0x294
[    0.939221]  kernel_init+0x28/0x130
[    0.942761]  ret_from_fork+0x10/0x20
[    0.946389] SMP: stopping secondary CPUs
[    0.950368] Kernel Offset: disabled
[    0.953901] CPU features: 0x80000,00034080,0000420b
[    0.958849] Memory Limit: none
[    0.961948] Rebooting in 10 seconds..

The boot.img for this one worked to boot via the rpiboot tool but that sidesteps all the initramfs stuff I reckon. It is the BOOT_A partition of a pretty stock rpi4 system.

Next, we init some ram in the fs.

Oh, this is the commit which made the above work: Working packaging of boot.img and boot.sig · underjord/secure_outer_rpi4@0693da1 · GitHub

1 Like

Trying to get the secure-boot-example boot.img to run before I dig into initramfs. It should be able to run and seems to be helping me in catching more goofs.

And there we go!

This was an experiment I didn’t really expect to work but had mild hopes for.

I took the standard nerves_system_rpi4. Baked a firmware image with it and did fwup -d boot.img bla-bla-bla.fw and it does produce a boot.img but it is not one that works. Probably as you aluded to Frank, it expects the FAT archive and this is something else:

RPi: BOOTLOADER release VERSION:e608a69d DATE: 2024/04/15 TIME: 14:12:14
BOOTMODE: 0x06 partition 0 build-ts BUILD_TIMESTAMP=1713186734 serial 2f2a72cf boardrev b03141 stc 477024
PM_RSTS: 0x00001000
part 00000000 reset_info 00000000
uSD voltage 3.3V
Initialising SDRAM 'Samsung' 16Gb x1 total-size: 16 Gbit 3200
DDR 3200 0 0 16 152

Boot mode: SD (01) order f2564
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
SD HOST: 200000000 CTL0: 0x00800f00 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
EMMC
SD retry 1 oc 0
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
OCR c0ff8080 [0]
CID: 001501003847544634520680754ad9ca
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 25000000 Hz actual: 25000000 HZ div: 8 (4) status: 0x1fff0000 delay: 4
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 50000000 Hz actual: 50000000 HZ div: 4 (2) status: 0x1fff0000 delay: 2
MBR: 0x0000003f,  716800 type: 0x0c
MBR: 0x00168000,  289044 type: 0x83
MBR: 0x001f5228,13217240 type: 0x83
MBR: 0x00000000,       0 type: 0x00
Trying partition: 0
type: 32 lba: 63 oem: 'MSDOS5.0' volume: ' NO NAME    '
rsc 32 fat-sectors 5601 c-count 705566 c-size 1
root dir cluster 2 sectors 0 entries 0
FAT32 clusters 705566
Trying partition: 0
type: 32 lba: 63 oem: 'MSDOS5.0' volume: ' NO NAME    '
rsc 32 fat-sectors 5601 c-count 705566 c-size 1
root dir cluster 2 sectors 0 entries 0
FAT32 clusters 705566
secure-boot
Loading boot.img ...
SIG boot.sig 4c5a9740190c57241651194413b3db7fd5c64acff948563bcea02a1c23fac22a 1716540259
Error 1 loading boot.img
Boot mode: USB-MSD (04) order f256
PCIe timeout: 0x0000008f
USB xHC init failed
Boot mode: NVME (06) order f25
PCIe timeout: 0x0000008f
Failed to open device: 'nvme'
Retry NVME 1
PCIe timeout: 0x0000008f
Failed to open device: 'nvme'
Boot mode: BCM-USB-MSD (05) order f2
XHCI-STOP
xHC ver: 272 HCS: 01000140 0c0000f1 07ff000a HCC: 0220fe65
xHC ports 1 slots 64 intrs 1
XHCI-STOP
xHC ver: 272 HCS: 01000140 0c0000f1 07ff000a HCC: 0220fe65
USBSTS 0
USB MSD stopped. Timeout: 25 seconds
Boot mode: NETWORK (02) order f
GENET: RESET_PHY 1
CTL 1140 PHY ID 600d 84a2
MII_CONTROL 1140
MII APD 0021 SCTL3 0021 IDDQ 0000

NETWORK: 2c:cf:67:0a:8a:f7 wait for link TFTP: 0.0.0.0

Now people should at least be able to find it by the error code.

Next approach is a Nerves System that essentially build as usual but uses the scripts and config from raspberry pi buildroot as a post-build.sh and generates a boot.img in the process. This would still produce a .fw which I guess would still be fine for development.

If I get it working (setting it up is a bit tedious) then I would be able to build my system by essentially building two Nerves systems.

Inner: The first one for my actual firmware and application, which produces the boot.img and a .fw. This would have the

Outer: And the next one that packages the boot.img and boot.sig for secure boot and produces a .fw for the eMMC/SD card.

@fhunleth does this make sense?

Since the boot.img is also signed we won’t ever be able to change data inside it without also updating the boot.sig. So upgrade should hit the “outer” one.

Every time I read the original response I understand a bit more. The amount of “I have to try or I don’t understand” is ridiculous today.

1 Like

Trying to unfurl all this without deep insight into linux booting is “fun”.

  • The bootloader, managed with usbboot and rpiboot. This determines whether secure-boot is ON.
  • The partition table, on the SD card/eMMC:
    • Boot A - Initial boot partition, a FAT32 filesystem containing stuff required to boot.
      • config.txt a Raspberry Pi special saying how this boot should happen, after the bootloader. Should have boot_ramdisk=1 apparently which is not really in the docs. This makes it boot boot.img.
      • boot.img a Raspberry Pi special, this is a file that if doing secure-boot will be loaded as a ramdisk and the linux inside it will be started.
        • (more to come)
      • boot.sig signature for the boot.img to ensure it matches with the expected public key stored in the bootloader EEPROM.
    • Boot B - Secondary boot partition if an update has shipped.
      • same as Boot A, essentially.
    • Root A - Root partition. This is our Nerves Linux system where all the fun happens and where we want to be. This starts the BEAM and all that.

Alright. I have a system baking a proper boot.img for me:

RPi: BOOTLOADER release VERSION:e608a69d DATE: 2024/04/15 TIME: 14:12:14
BOOTMODE: 0x06 partition 0 build-ts BUILD_TIMESTAMP=1713186734 serial 2f2a72cf boardrev b03141 stc 477024
PM_RSTS: 0x00001000
part 00000000 reset_info 00000000
uSD voltage 3.3V
Initialising SDRAM 'Samsung' 16Gb x1 total-size: 16 Gbit 3200
DDR 3200 0 0 16 152

Boot mode: SD (01) order f2564
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
SD HOST: 200000000 CTL0: 0x00800f00 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
EMMC
SD retry 1 oc 0
SD HOST: 200000000 CTL0: 0x00800000 BUS: 400000 Hz actual: 390625 HZ div: 512 (256) status: 0x1fff0000 delay: 276
OCR c0ff8080 [0]
CID: 001501003847544634520680754ad9ca
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 25000000 Hz actual: 25000000 HZ div: 8 (4) status: 0x1fff0000 delay: 4
SD HOST: 200000000 CTL0: 0x00800f04 BUS: 50000000 Hz actual: 50000000 HZ div: 4 (2) status: 0x1fff0000 delay: 2
MBR: 0x0000003f,  716800 type: 0x0c
MBR: 0x00168000,  289044 type: 0x83
MBR: 0x001f5228,13217240 type: 0x83
MBR: 0x00000000,       0 type: 0x00
Trying partition: 0
type: 32 lba: 63 oem: 'MSDOS5.0' volume: ' NO NAME    '
rsc 32 fat-sectors 5601 c-count 705566 c-size 1
root dir cluster 2 sectors 0 entries 0
FAT32 clusters 705566
Trying partition: 0
type: 32 lba: 63 oem: 'MSDOS5.0' volume: ' NO NAME    '
rsc 32 fat-sectors 5601 c-count 705566 c-size 1
root dir cluster 2 sectors 0 entries 0
FAT32 clusters 705566
secure-boot
Loading boot.img ...
SIG boot.sig 9fc705ba873900c4bfc28bea92baf04ad2825519908a477406eef014478a72bd 1711932785
Verifying
RSA verify
rsa-verify pass (0x0)
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
MBR: 0x00000000,       0 type: 0x00
Trying partition: 0
type: 16 lba: 0 oem: 'mkfs.fat' volume: '  V       ^ '
rsc 4 fat-sectors 64 c-count 16343 c-size 4
root dir cluster 1 sectors 32 entries 512
FAT16 clusters 16343
Read config.txt bytes     2108 hnd 0x54
Read start4x.elf bytes  3002536 hnd 0x5c
Read fixup4x.dat bytes     8399 hnd 0x57
0x00b03141 0x00000000 0x00001fff
MEM GPU: 192 ARM: 832 TOTAL: 1024
Firmware: 30f0c5e4d076da3ab4f341d88e7d505760b93ad7 Oct 17 2023 15:40:00
Starting start4x.elf @ 0xfec00200 partition 0
+

MESS:00:00:08.785692:0: brfs: File read: /mfs/sd/config.txt
MESS:00:00:08.789221:0: brfs: File read: 2108 bytes
MESS:00:00:08.813278:0: HDMI0:EDID error reading EDID block 0 attempt 0
MESS:00:00:08.817781:0: HDMI0:EDID giving up on reading EDID block 0
MESS:00:00:08.834476:0: HDMI1:EDID error reading EDID block 0 attempt 0
MESS:00:00:08.838984:0: HDMI1:EDID giving up on reading EDID block 0
MESS:00:00:08.844344:0: brfs: File read: /mfs/sd/config.txt
MESS:00:00:08.850376:0: gpioman: gpioman_get_pin_num: pin DISPLAY_SDA not defined
MESS:00:00:08.856563:0: gpioman: gpioman_get_pin_num: pin LEDS_PWR_OK not defined
MESS:00:00:09.027896:0: gpioman: gpioman_get_pin_num: pin FLASH_0_ENABLE not defined
MESS:00:00:09.032537:0: gpioman: gpioman_get_pin_num: pin FLASH_0_INDICATOR not defined
MESS:00:00:09.040277:0: gpioman: gpioman_get_pin_num: pin FLASH_0_ENABLE not defined
MESS:00:00:09.047727:0: gpioman: gpioman_get_pin_num: pin FLASH_0_INDICATOR not defined
MESS:00:00:09.353735:0: gpioman: gpioman_get_pin_num: pin LEDS_PWR_OK not defined
MESS:00:00:09.359382:0: *** Restart logging
MESS:00:00:09.362024:0: brfs: File read: 2108 bytes
MESS:00:00:09.371775:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 0
MESS:00:00:09.376801:0: hdmi: HDMI0:EDID giving up on reading EDID block 0
MESS:00:00:09.387424:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 0
MESS:00:00:09.392453:0: hdmi: HDMI0:EDID giving up on reading EDID block 0
MESS:00:00:09.398052:0: hdmi: HDMI:hdmi_get_state is deprecated, use hdmi_get_display_state instead
MESS:00:00:09.411842:0: hdmi: HDMI1:EDID error reading EDID block 0 attempt 0
MESS:00:00:09.416873:0: hdmi: HDMI1:EDID giving up on reading EDID block 0
MESS:00:00:09.427494:0: hdmi: HDMI1:EDID error reading EDID block 0 attempt 0
MESS:00:00:09.432519:0: hdmi: HDMI1:EDID giving up on reading EDID block 0
MESS:00:00:09.438116:0: hdmi: HDMI:hdmi_get_state is deprecated, use hdmi_get_display_state instead
MESS:00:00:09.446881:0: HDMI0: hdmi_pixel_encoding: 300000000
MESS:00:00:09.452354:0: HDMI1: hdmi_pixel_encoding: 300000000
MESS:00:00:09.660020:0: brfs: File read: /mfs/sd/rootfs.cpio.zst
MESS:00:00:09.662920:0: Loaded 'rootfs.cpio.zst' to 0x0 size 0x13d2e14
MESS:00:00:09.685269:0: initramfs loaded to 0x2dc2d000 (size 0x13d2e14)
MESS:00:00:09.688791:0: gpioman: gpioman_get_pin_num: pin CAMERA_0_I2C_PORT not defined
MESS:00:00:09.700760:0: dtb_file 'bcm2711-rpi-cm4.dtb'
MESS:00:00:09.702789:0: brfs: File read: 20786708 bytes
MESS:00:00:09.708249:0: brfs: File read: /mfs/sd/bcm2711-rpi-cm4.dtb
MESS:00:00:09.713812:0: Loaded 'bcm2711-rpi-cm4.dtb' to 0x100 size 0xd84f
MESS:00:00:09.733962:0: brfs: File read: 55375 bytes
MESS:00:00:09.737926:0: brfs: File read: /mfs/sd/overlays/overlay_map.dtb
MESS:00:00:09.769259:0: brfs: File read: 4775 bytes
MESS:00:00:09.771135:0: brfs: File read: /mfs/sd/config.txt
MESS:00:00:09.776665:0: dtparam: i2c_arm=on
MESS:00:00:09.788988:0: dtparam: spi=on
MESS:00:00:09.797928:0: dtparam: audio=on
MESS:00:00:09.803852:0: brfs: File read: 2108 bytes
MESS:00:00:09.807024:0: brfs: File read: /mfs/sd/overlays/vc4-kms-v3d-pi4.dtbo
MESS:00:00:09.875247:0: Loaded overlay 'vc4-kms-v3d'
MESS:00:00:10.029190:0: brfs: File read: 3913 bytes
MESS:00:00:10.033338:0: brfs: File read: /mfs/sd/overlays/dwc2.dtbo
MESS:00:00:10.043147:0: Loaded overlay 'dwc2'
MESS:00:00:10.055240:0: brfs: File read: 801 bytes
MESS:00:00:10.057627:0: brfs: File read: /mfs/sd/overlays/ramoops-pi4.dtbo
MESS:00:00:10.067378:0: Loaded overlay 'ramoops'
MESS:00:00:10.076351:0: brfs: File read: 741 bytes
MESS:00:00:10.080395:0: brfs: File read: /mfs/sd/overlays/dwc2.dtbo
MESS:00:00:10.090240:0: Loaded overlay 'dwc2'
MESS:00:00:10.091483:0: dtparam: dr_mode=host
MESS:00:00:10.113801:0: brfs: File read: 801 bytes
MESS:00:00:10.115571:0: brfs: File read: /mfs/sd/cmdline.txt
MESS:00:00:10.121006:0: Read command line from file 'cmdline.txt':
MESS:00:00:10.126762:0: 'rootwait console=tty0 console=serial0,115200 root=/dev/ram0'
MESS:00:00:10.245118:0: brfs: File read: 550 bytes
MESS:00:00:10.289923:0: brfs: File read: /mfs/sd/zImage
MESS:00:00:10.292039:0: Loaded 'zImage' to 0x80000 size 0x5236d4
MESS:00:00:11.021463:0: Kernel relocated to 0x200000
MESS:00:00:11.023318:0: Device tree loaded to 0x2dc1f200 (size 0xdd73)
MESS:00:00:11.031502:0: uart: Set PL011 baud rate to 103448.300000 Hz
MESS:00:00:11.038642:0: uart: Baud rate change done...
MESS:00:00:11.040665:0:[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd083]
[    0.000000] Linux version 6.1.73-v8 (buildroot@buildroot) (aarch64-nerves-linux-gnu-gcc (crosstool-NG UNKNOWN) 13.2.0, GNU ld (crosstool-NG UNKNOWN) 2.40) #1 SMP PREEMPT Mon Apr  1 00:53:05 UTC 2024
[    0.000000] random: crng init done
[    0.000000] Machine model: Raspberry Pi Compute Module 4 Rev 1.1
[    0.000000] Reserved memory: created CMA memory pool at 0x000000000dc00000, size 512 MiB
[    0.000000] OF: reserved mem: initialized node linux,cma, compatible id shared-dma-pool
[    0.000000] Zone ranges:
[    0.000000]   DMA      [mem 0x0000000000000000-0x000000003fffffff]
[    0.000000]   DMA32    [mem 0x0000000040000000-0x000000007fffffff]
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000000000-0x0000000033ffffff]
[    0.000000]   node   0: [mem 0x0000000040000000-0x000000007fffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x000000007fffffff]
[    0.000000] On node 0, zone DMA32: 16384 pages in unavailable ranges
[    0.000000] percpu: Embedded 25 pages/cpu s64680 r8192 d29528 u102400
[    0.000000] Detected PIPT I-cache on CPU0
[    0.000000] CPU features: detected: Spectre-v2
[    0.000000] CPU features: detected: Spectre-v4
[    0.000000] CPU features: detected: Spectre-BHB
[    0.000000] CPU features: detected: ARM errata 1165522, 1319367, or 1530923
[    0.000000] alternatives: applying boot alternatives
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 467712
[    0.000000] Kernel command line: coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=1 snd_bcm2835.enable_hdmi=0  smsc95xx.macaddr=2C:CF:67:0A:8A:F7 vc_mem.mem_base=0x3ec00000 vc_mem.mem_size=0x40000000  rootwait console=tty0 console=ttyS0,115200 root=/dev/ram0
[    0.000000] Dentry cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
[    0.000000] Inode-cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
[    0.000000] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[    0.000000] software IO TLB: area num 4.
[    0.000000] software IO TLB: mapped [mem 0x0000000030000000-0x0000000034000000] (64MB)
[    0.000000] Memory: 1237600K/1900544K available (7872K kernel code, 1270K rwdata, 2036K rodata, 1728K init, 597K bss, 138656K reserved, 524288K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
[    0.000000] trace event string verifier disabled
[    0.000000] rcu: Preemptible hierarchical RCU implementation.
[    0.000000] rcu: 	RCU event tracing is enabled.
[    0.000000] 	Trampoline variant of Tasks RCU enabled.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] Root IRQ handler: gic_handle_irq
[    0.000000] GIC: Using split EOI/Deactivate mode
[    0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
[    0.000000] arch_timer: cp15 timer(s) running at 54.00MHz (phys).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0xc743ce346, max_idle_ns: 440795203123 ns
[    0.000001] sched_clock: 56 bits at 54MHz, resolution 18ns, wraps every 4398046511102ns
[    0.000209] Console: colour dummy device 80x25
[    0.000570] printk: console [tty0] enabled
[    0.000621] Calibrating delay loop (skipped), value calculated using timer frequency.. 108.00 BogoMIPS (lpj=216000)
[    0.000650] pid_max: default: 32768 minimum: 301
[    0.000867] Mount-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
[    0.000910] Mountpoint-cache hash table entries: 4096 (order: 3, 32768 bytes, linear)
[    0.001719] cgroup: Disabling memory control group subsystem
[    0.002690] cblist_init_generic: Setting adjustable number of callback queues.
[    0.002715] cblist_init_generic: Setting shift to 2 and lim to 1.
[    0.002932] rcu: Hierarchical SRCU implementation.
[    0.002948] rcu: 	Max phase no-delay instances is 1000.
[    0.003944] smp: Bringing up secondary CPUs ...
[    0.004447] Detected PIPT I-cache on CPU1
[    0.004587] CPU1: Booted secondary processor 0x0000000001 [0x410fd083]
[    0.005129] Detected PIPT I-cache on CPU2
[    0.005247] CPU2: Booted secondary processor 0x0000000002 [0x410fd083]
[    0.005749] Detected PIPT I-cache on CPU3
[    0.005873] CPU3: Booted secondary processor 0x0000000003 [0x410fd083]
[    0.005954] smp: Brought up 1 node, 4 CPUs
[    0.006023] SMP: Total of 4 processors activated.
[    0.006037] CPU features: detected: 32-bit EL0 Support
[    0.006051] CPU features: detected: CRC32 instructions
[    0.006135] CPU: All CPU(s) started at EL2
[    0.006148] alternatives: applying system-wide alternatives
[    0.007241] devtmpfs: initialized
[    0.016077] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
[    0.016139] futex hash table entries: 1024 (order: 4, 65536 bytes, linear)
[    0.028664] pinctrl core: initialized pinctrl subsystem
[    0.029514] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.031063] DMA: preallocated 1024 KiB GFP_KERNEL pool for atomic allocations
[    0.031319] DMA: preallocated 1024 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
[    0.031748] DMA: preallocated 1024 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    0.032194] thermal_sys: Registered thermal governor 'step_wise'
[    0.032239] cpuidle: using governor menu
[    0.032392] ASID allocator initialised with 65536 entries
[    0.032471] Serial: AMBA PL011 UART driver
[    0.032877] pstore: Registered ramoops as persistent store backend
[    0.032895] ramoops: using 0x10000@0xb000000, ecc: 0
[    0.040253] bcm2835-mbox fe00b880.mailbox: mailbox enabled
[    0.052102] raspberrypi-firmware soc:firmware: Attached to firmware from 2023-10-17T15:40:00, variant start_x
[    0.056111] raspberrypi-firmware soc:firmware: Firmware hash is 30f0c5e4d076da3ab4f341d88e7d505760b93ad7
[    0.090443] bcm2835-dma fe007000.dma: DMA legacy API manager, dmachans=0x1
[    0.093081] SCSI subsystem initialized
[    0.093244] usbcore: registered new interface driver usbfs
[    0.093296] usbcore: registered new interface driver hub
[    0.093370] usbcore: registered new device driver usb
[    0.093542] usb_phy_generic phy: supply vcc not found, using dummy regulator
[    0.093788] pps_core: LinuxPPS API ver. 1 registered
[    0.093805] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.093833] PTP clock support registered
[    0.094699] vgaarb: loaded
[    0.095024] clocksource: Switched to clocksource arch_sys_counter
[    0.101953] NET: Registered PF_INET protocol family
[    0.102247] IP idents hash table entries: 32768 (order: 6, 262144 bytes, linear)
[    0.104665] tcp_listen_portaddr_hash hash table entries: 1024 (order: 2, 16384 bytes, linear)
[    0.104717] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.104789] TCP established hash table entries: 16384 (order: 5, 131072 bytes, linear)
[    0.104915] TCP bind hash table entries: 16384 (order: 7, 524288 bytes, linear)
[    0.105434] TCP: Hash tables configured (established 16384 bind 16384)
[    0.105596] UDP hash table entries: 1024 (order: 3, 32768 bytes, linear)
[    0.105643] UDP-Lite hash table entries: 1024 (order: 3, 32768 bytes, linear)
[    0.105804] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.105849] PCI: CLS 0 bytes, default 64
[    0.106262] Trying to unpack rootfs image as initramfs...
[    0.123814] Initialise system trusted keyrings
[    0.124102] workingset: timestamp_bits=46 max_order=19 bucket_order=0
[    0.129713] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.131147] Key type asymmetric registered
[    0.131185] Asymmetric key parser 'x509' registered
[    0.131262] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 248)
[    0.131852] irq_brcmstb_l2: registered L2 intc (/soc/interrupt-controller@7ef00100, parent irq: 23)
[    0.136663] gpio-507 (ant1): hogged as output/high
[    0.138011] gpio-511 (ant2): hogged as output/low
[    0.138948] brcm-pcie fd500000.pcie: host bridge /scb/pcie@7d500000 ranges:
[    0.138985] brcm-pcie fd500000.pcie:   No bus range found for /scb/pcie@7d500000, using [bus 00-ff]
[    0.139077] brcm-pcie fd500000.pcie:      MEM 0x0600000000..0x063fffffff -> 0x00c0000000
[    0.139124] brcm-pcie fd500000.pcie:   IB MEM 0x0000000000..0x007fffffff -> 0x0400000000
[    0.139633] brcm-pcie fd500000.pcie: setting SCB_ACCESS_EN, READ_UR_MODE, MAX_BURST_SIZE
[    0.139908] brcm-pcie fd500000.pcie: PCI host bridge to bus 0000:00
[    0.139933] pci_bus 0000:00: root bus resource [bus 00-ff]
[    0.139955] pci_bus 0000:00: root bus resource [mem 0x600000000-0x63fffffff] (bus address [0xc0000000-0xffffffff])
[    0.140010] pci 0000:00:00.0: [14e4:2711] type 01 class 0x060400
[    0.140103] pci 0000:00:00.0: PME# supported from D0 D3hot
[    0.143850] pci 0000:00:00.0: bridge configuration invalid ([bus 00-00]), reconfiguring
[    0.144064] pci_bus 0000:01: supply vpcie3v3 not found, using dummy regulator
[    0.144163] pci_bus 0000:01: supply vpcie3v3aux not found, using dummy regulator
[    0.144196] pci_bus 0000:01: supply vpcie12v not found, using dummy regulator
[    0.571073] brcm-pcie fd500000.pcie: link down
[    0.571379] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
[    0.571421] pci 0000:00:00.0: PCI bridge to [bus 01]
[    0.571499] pci_bus 0000:01: busn_res: [bus 01] is released
[    0.571946] pci_bus 0000:00: busn_res: [bus 00-ff] is released
[    0.577255] Serial: 8250/16550 driver, 1 ports, IRQ sharing enabled
[    0.578674] iproc-rng200 fe104000.rng: hwrng registered
[    0.578869] vc-mem: phys_addr:0x00000000 mem_base=0x3ec00000 mem_size:0x40000000(1024 MiB)
[    0.586497] brd: module loaded
[    0.590324] loop: module loaded
[    0.590864] Loading iSCSI transport class v2.0-870.
[    0.593292] bcmgenet fd580000.ethernet: GENET 5.0 EPHY: 0x0000
[    1.340163] Freeing initrd memory: 20296K
[    1.407097] unimac-mdio unimac-mdio.-19: Broadcom UniMAC MDIO bus
[    1.408193] dwc_otg: version 3.00a 10-AUG-2012 (platform bus)
[    1.408520] usbcore: registered new interface driver usb-storage
[    1.408650] UDC core: g_ether: couldn't find an available UDC
[    1.408671] i2c_dev: i2c /dev entries driver
[    1.409375] brcmstb-i2c fef04500.i2c:  @97500hz registered in polling mode
[    1.409735] brcmstb-i2c fef09500.i2c:  @97500hz registered in polling mode
[    1.411307] sdhci: Secure Digital Host Controller Interface driver
[    1.411330] sdhci: Copyright(c) Pierre Ossman
[    1.411552] sdhci-pltfm: SDHCI platform and OF driver helper
[    1.413756] ledtrig-cpu: registered to indicate activity on CPUs
[    1.413892] hid: raw HID events driver (C) Jiri Kosina
[    1.414031] usbcore: registered new interface driver usbhid
[    1.414047] usbhid: USB HID core driver
[    1.414195] bcm2835_vchiq fe00b840.mailbox: there is not valid maps for state default
[    1.419091] NET: Registered PF_INET6 protocol family
[    1.420122] Segment Routing with IPv6
[    1.420162] In-situ OAM (IOAM) with IPv6
[    1.420244] NET: Registered PF_PACKET protocol family
[    1.420578] Loading compiled-in X.509 certificates
[    1.421013] pstore: Using crash dump compression: deflate
[    1.423712] uart-pl011 fe201000.serial: there is not valid maps for state default
[    1.424022] uart-pl011 fe201000.serial: cts_event_workaround enabled
[    1.424121] fe201000.serial: ttyAMA1 at MMIO 0xfe201000 (irq = 30, base_baud = 0) is a PL011 rev2
[    1.430011] bcm2835-aux-uart fe215040.serial: there is not valid maps for state default
[    1.430405] printk: console [ttyS0] disabled
[    1.430480] fe215040.serial: ttyS0 at MMIO 0xfe215040 (irq = 31, base_baud = 62500000) is a 16550
[    2.506866] printk: console [ttyS0] enabled
[    2.511442] bcm2835-wdt bcm2835-wdt: Broadcom BCM2835 watchdog timer
[    2.518007] bcm2835-power bcm2835-power: Broadcom BCM2835 power domains driver
[    2.526641] mmc-bcm2835 fe300000.mmcnr: mmc_debug:0 mmc_debug2:0
[    2.532775] mmc-bcm2835 fe300000.mmcnr: DMA channel allocated
[    2.563940] of_cfs_init
[    2.566440] of_cfs_init: OK
[    2.607675] mmc0: SDHCI controller on fe340000.mmc [fe340000.mmc] using ADMA
[    2.615948] Freeing unused kernel memory: 1728K
[    2.620649] Run /init as init process
[    2.624512] Failed to execute /init (error -13)
[    2.629131] Run /sbin/init as init process
erlinit: Cannot remount /dev
erlinit: Cannot create /dev/pts
erlinit: Cannot create /dev/shm
erlinit: error setting controlling terminal: /dev/tty1
erlinit: Cannot mount /dev/mmcblk0p1 at /boot: No such file or directory
erlinit: Cannot mount /dev/mmcblk0p3 at /root: No such file or directory
erlinit: No release found in /srv/erlang.


FATAL ERROR:


erlinit: Erlang installation not found. Check that /usr/lib/erlang exists


CANNOT CONTINUE.
[    2.675423] mmc0: new DDR MMC card at address 0001
[    2.680872] mmcblk0: mmc0:0001 8GTF4R 7.28 GiB 
[    2.687535]  mmcblk0: p1 p2 p3
[    2.690846] mmcblk0: mmc0:0001 8GTF4R 7.28 GiB
[    2.695641] mmcblk0boot0: mmc0:0001 8GTF4R 4.00 MiB 
[    2.701120] mmcblk0boot1: mmc0:0001 8GTF4R 4.00 MiB 
[    2.706364] mmcblk0rpmb: mmc0:0001 8GTF4R 512 KiB, chardev (246:0)
[    3.691420] reboot: Restarting system

So my process is:

  • In secure_boot_rpi4 repo, clear out .nerves and _build, then run mix compile. The post-createfs.sh references a ../usbboot/private.pem. Change as needed.
  • Copy the generated build.img and build.sig to ../secure_outer_rpi4/images/.
  • In secure_outer_rpi4 repo, clear out .nerves, images and _build, then run mix compile.
  • In your project using the secure_outer_rpi4 system as your Nerves system: mix firmware
  • Put the CM4 IO board into flashy mody using the jumper.
  • I ran ./rpiboot -d mass-storage-gadget64 (which I have signed previously) to get it to be a mass storage device.
  • mix burn and burn it to device.

So now to mount that root filesystem and switch_root into it.

The iteration speed is painful. I have a Ryzen 5950X but the compile times are still kind of brutal compared to my sheltered life of web dev. I have built so many kernels. I know I could trim down both systems in some ways but I’m not certain enough about where. So suffer I shall.

Onward!

2 Likes