People on the internet like complaining about the Raspberry Pi's boot process. The default boot screen isn't great, all the diagnostics available to the user is a colourful gradient that eventually disappears when things are working properly.
Using UEFI firmware can make your RPI3 function more like a "real
computer", and makes it easy to boot from external disks and configure
things like CPU clock speed. Only the firmware needs to reside on the SD card,
the OS can be elsewhere. The GENERIC NetBSD kernel resides in the standard
location of /netbsd
on the root filesystem, just like on x86. It updates
like a real computer too!
Ignore this section if you just want some instructions that work.
I ran into one problem when booting NetBSD. It turns out the Raspberry Pi ACPI implementation is strangely non-standard, not using the usual ARM interrupt controllers, and the NetBSD/aarch64 UEFI bootloader will prefer booting via ACPI if it detects ACPI. This resulted in a system that wouldn't boot, even when EDK2 was set to devicetree-only mode (apparently, due to a firmware bug). This is not a problem on the Raspberry Pi 4, where booting via UEFI is the standard way to boot NetBSD.
I filed an issue concerning the firmware's insistence on exposing ACPI tables.
For now, I'm working around this by building a EFI bootloader with skrll's patch that allows disabling ACPI.
You can download a patched bootloader, or build it yourself by following the instructions at the bottom.
Hopefully, this will become entirely unnecessary. On the bright side, ARM ACPI implementations being weird and quirky shows we are finally getting the x86 experience.
Extract the firmware. In the future, it'll become our FAT32 boot partition.
$ mkdir rpi3-firmware && cd rpi3-firmware
$ unzip ../RPi3_UEFI_Firmware_v1.32.zip
The bootloader needs to be copied to the appropriate subdirectory of the extracted firmware archive:
$ mkdir -p EFI/BOOT
$ cp ../bootaa64.efi EFI/BOOT/bootaa64.efi
Create a boot.cfg
file for NetBSD's bootloader:
menu=Boot normally:acpi off;rndseed /var/db/entropy-file;boot
menu=Boot single user:acpi off;rndseed /var/db/entropy-file;boot -s
menu=Drop to boot prompt:prompt
default=1
timeout=5
Now, write the operating system image to your SD card:
$ cd ..
$ gunzip arm64mbr.img.gz
# dd if=arm64mbr.img of=/dev/rld0d bs=1m conv=sync progress=1
Note your operating system's dd
command and device names may vary from NetBSD's.
Be careful.
arm64mbr.img
already contains a FAT32 boot partition for the firmware, and
a FFS partition for NetBSD. On first boot NetBSD will resize the FFS
partition to fill your SD card.
Once the OS image is written, we replace the contents of its boot partition with our files extracted from the archive, but keeping the NetBSD device trees:
# mount /dev/ld0e /mnt
# mv /mnt/dtb/broadcom/bcm2837-rpi-* /tmp
# rm -r /mnt/*
# cp -r rpi3-firmware/* /mnt
# mv /tmp/bcm2837-rpi-* /mnt
# umount /mnt
Remove the SD card, plug it into your Pi. The colourful gradient will appear for a couple of seconds before dropping you into a nice UEFI boot screen. It now boots like a real computer!
Note: you can also just download my patched binary above.
Checkout the NetBSD sources and build an aarch64 toolchain:
$ cvs -q -d anoncvs@anoncvs.netbsd.org:/cvsroot co -P src
$ cd src
$ ./build.sh -U -j2 -m evbarm64 tools
Apply the patch:
$ curl -L https://github.com/skrll/src/commit/401f9d238f149a01ad94b00fa8475cda29dfa302.patch | patch -p1
Then build the bootloader:
$ cd sys/stand/efiboot/bootaa64
$ ../../../../obj/tooldir.NetBSD-9.99.78-amd64/bin/nbmake MACHINE=evbarm MACHINE_ARCH=aarch64
The filename of tooldir will vary depending on your operating system. On NetBSD
you can usually substitute for just make
.
There will now be a bootaa64.efi
binary in the current directory.
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017,
2018, 2019, 2020, 2021 The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
NetBSD 9.99.78 (GENERIC64) #0: Fri Jan 22 00:44:55 UTC 2021
mkrepro@mkrepro.NetBSD.org:/usr/src/sys/arch/evbarm/compile/GENERIC64
total memory = 919 MB
avail memory = 890 MB
entropy: ready
timecounter: Timecounters tick every 10.000 msec
Kernelized RAIDframe activated
armfdt0 (root)
armfdt0: using EFI runtime services for RTC
simplebus0 at armfdt0: Raspberry Pi 3 Model B Plus Rev 1.3
simplebus1 at simplebus0
simplebus2 at simplebus0
cpus0 at simplebus0
psci0 at simplebus0: PSCI 1.1
simplebus3 at simplebus0
cpu0 at cpus0: Arm Cortex-A53 r0p4 (v8-A), id 0x0
cpu0: IC enabled, DC enabled, EL0/EL1 stack Alignment check enabled
cpu0: Cache Writeback Granule 16B, Exclusives Reservation Granule 16B
cpu0: Dcache line 64, Icache line 64, DIC=0, IDC=0, LoUU=1, LoC=2, LoUIS=1
cpu0: L1 32KB/64B*256L*2W VIPT Instruction cache
cpu0: L1 32KB/64B*128L*4W PIPT Data cache
cpu0: L2 512KB/64B*512L*16W PIPT Unified cache
cpu0: revID=0x80, PMCv3, 4k table, 64k table, 16bit ASID
cpu0: auxID=0x10000, FP, CRC32, NEON, rounding, NaN propagation, denormals, 32x64bitRegs, Fused Multiply-Add
cpu1 at cpus0: Arm Cortex-A53 r0p4 (v8-A), id 0x1
cpu2 at cpus0: Arm Cortex-A53 r0p4 (v8-A), id 0x2
cpu3 at cpus0: Arm Cortex-A53 r0p4 (v8-A), id 0x3
bcmicu0 at simplebus1
fclock0 at simplebus2: 19200000 Hz fixed clock (osc)
syscon0 at simplebus1autoconfiguration error: : couldn't get registers
bcmcprman0 at simplebus1: BCM283x Clock Controller
bcmaux0 at simplebus1
fclock1 at simplebus2: 480000000 Hz fixed clock (otg)
bcmicu1 at simplebus1: Multiprocessor
gtmr0 at simplebus0: Generic Timer
gtmr0: interrupting on local_intc irq 3
armgtmr0 at gtmr0: Generic Timer (19200 kHz, virtual)
timecounter: Timecounter "armgtmr0" frequency 19200000 Hz quality 500
bcmgpio0 at simplebus1: GPIO controller 2835
bcmgpio0: pins 0..31 interrupting on icu irq 49
bcmgpio0: pins 32..54 interrupting on icu irq 50
gpio0 at bcmgpio0: 54 pins
plcom0 at simplebus1: ARM PL011 UART
plcom0: txfifo disabled
plcom0: interrupting on icu irq 57
com0 at simplebus1: BCM AUX UART, 1-byte FIFO
com0: console
com0: interrupting on icu irq 29
fregulator0 at simplebus0: 3v3
fregulator1 at simplebus0: 5v0
/soc/thermal@7e212000 at simplebus1 not configured
bcmdmac0 at simplebus1: DMA0 DMA2 DMA4 DMA5 DMA6 DMA7 DMA8 DMA9 DMA10 DMA11
/soc/power at simplebus1 not configured
/phy at simplebus0 not configured
bcmmbox0 at simplebus1: VC mailbox
bcmmbox0: interrupting on icu irq 65
vcmbox0 at bcmmbox0
vchiq0 at simplebus1: BCM2835 VCHIQ
bcmpmwdog0 at simplebus1: Power management, Reset and Watchdog controller
bcmrng0 at simplebus1: RNG
bcmsdhost0 at simplebus1: SD HOST controller
bcmsdhost0: interrupting on icu irq 56
sdhc0 at simplebus1: SDHC controller
sdhc0: interrupting on icu irq 62
gpioleds0 at simplebus0: led0
dwctwo0 at simplebus1: USB controller
dwctwo0: interrupting on icu irq 9
/soc/fb at simplebus1 not configured
/soc/vcsm at simplebus1 not configured
armpmu0 at simplebus0: Performance Monitor Unit
/soc/gpiomem at simplebus1 not configured
genfb0 at simplebus3no data for est. mode 640x480x67
: Simple Framebuffer (1920x1080 32-bpp @ 0x3e402000)
genfb0: framebuffer at 0x3e402000, size 1920x1080, depth 32, stride 7680
wsdisplay0 at genfb0 kbdmux 1: console (default, vt100 emulation)
wsmux1: connecting to wsdisplay0
wsdisplay0: screen 1-3 added (default, vt100 emulation)
timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
cpu2: IC enabled, DC enabled, EL0/EL1 stack Alignment check enabled
cpu2: Cache Writeback Granule 16B, Exclusives Reservation Granule 16B
cpu2: Dcache line 64, Icache line 64, DIC=0, IDC=0, LoUU=1, LoC=2, LoUIS=1
cpu2: L1 32KB/64B*256L*2W VIPT Instruction cache
cpu2: L1 32KB/64B*128L*4W PIPT Data cache
cpu2: L2 512KB/64B*512L*16W PIPT Unified cache
cpu2: revID=0x80, PMCv3, 4k table, 64k table, 16bit ASID
cpu2: auxID=0x10000, FP, CRC32, NEON, rounding, NaN propagation, denormals, 32x64bitRegs, Fused Multiply-Add
cpu1: IC enabled, DC enabled, EL0/EL1 stack Alignment check enabled
cpu1: Cache Writeback Granule 16B, Exclusives Reservation Granule 16B
cpu1: Dcache line 64, Icache line 64, DIC=0, IDC=0, LoUU=1, LoC=2, LoUIS=1
cpu1: L1 32KB/64B*256L*2W VIPT Instruction cache
cpu1: L1 32KB/64B*128L*4W PIPT Data cache
cpu1: L2 512KB/64B*512L*16W PIPT Unified cache
cpu1: revID=0x80, PMCv3, 4k table, 64k table, 16bit ASID
cpu1: auxID=0x10000, FP, CRC32, NEON, rounding, NaN propagation, denormals, 32x64bitRegs, Fused Multiply-Add
cpu3: IC enabled, DC enabled, EL0/EL1 stack Alignment check enabled
cpu3: Cache Writeback Granule 16B, Exclusives Reservation Granule 16B
cpu3: Dcache line 64, Icache line 64, DIC=0, IDC=0, LoUU=1, LoC=2, LoUIS=1
cpu3: L1 32KB/64B*256L*2W VIPT Instruction cache
cpu3: L1 32KB/64B*128L*4W PIPT Data cache
cpu3: L2 512KB/64B*512L*16W PIPT Unified cache
cpu3: revID=0x80, PMCv3, 4k table, 64k table, 16bit ASID
cpu3: auxID=0x10000, FP, CRC32, NEON, rounding, NaN propagation, denormals, 32x64bitRegs, Fused Multiply-Add
sdmmc0 at bcmsdhost0
sdhc0: SDHC 3.0, rev 153, platform DMA, 200000 kHz, HS 3.3V, re-tuning mode 1, 1024 byte blocks
sdmmc1 at sdhc0 slot 0
dwctwo0: Core Release: 2.80a (snpsid=4f54280a)
usb0 at dwctwo0: USB revision 2.0
armpmu0: interrupting on local_intc irq 9
uhub0 at usb0: NetBSD (0x0000) DWC2 root hub (0x0000), class 9/0, rev 2.00/1.00, addr 1
uhub0: 1 port with 1 removable, self powered
IPsec: Initialized Security Association Processing.
aes: ARM NEON vpaes
chacha: ARM NEON ChaCha
adiantum: self-test passed
aes_ccm: self-test passed
blake2s: self-test passed
sdmmc0: direct I/O error 5, r=6 p=0xffffc00042bb1e3c write
sdmmc0: SD card status: 4-bit, C10, U1, A1
ld0 at sdmmc0: <0x03:0x5344:SC64G:0x80:0x109426e6:0x12a>
ld0: 60906 MB, 7764 cyl, 255 head, 63 sec, 512 bytes/sect x 124735488 sectors
ld0: 4-bit width, High-Speed/SDR25, 50.000 MHz
sdmmc1: 4-bit width, 50.000 MHz
sdmmc1: SDIO function
bwfm0 at sdmmc1 function 1
(manufacturer 0x2d0, product 0xa9a6) at sdmmc1 function 2 not configured
(manufacturer 0x2d0, product 0xa9a6, standard function interface code 0x2) at sdmmc1 function 3 not configured
uhub1 at uhub0 port 1: vendor 0424 (0x0424) product 2514 (0x2514), class 9/0, rev 2.00/b.b3, addr 2
uhub1: multiple transaction translators
uhub1: 4 ports with 3 removable, self powered
uhub2 at uhub1 port 1: vendor 0424 (0x0424) product 2514 (0x2514), class 9/0, rev 2.00/b.b3, addr 3
uhub2: multiple transaction translators
uhub2: 3 ports with 2 removable, self powered
uhidev0 at uhub1 port 3 configuration 1 interface 0
uhidev0: vendor 04d9 (0x04d9) USB-HID Keyboard (0x0112), rev 1.10/1.12, addr 4, iclass 3/1
ukbd0 at uhidev0: 8 Variable keys, 6 Array codes
wskbd0 at ukbd0: console keyboard, using wsdisplay0
uhidev1 at uhub1 port 3 configuration 1 interface 1
uhidev1: vendor 04d9 (0x04d9) USB-HID Keyboard (0x0112), rev 1.10/1.12, addr 4, iclass 3/0
uhidev1: 2 report ids
uhid0 at uhidev1 reportid 1: input=1, output=0, feature=0
uhid1 at uhidev1 reportid 2: input=4, output=0, feature=0
uhidev2 at uhub1 port 3 configuration 1 interface 2
uhidev2: vendor 04d9 (0x04d9) USB-HID Keyboard (0x0112), rev 1.10/1.12, addr 4, iclass 3/0
uhid2 at uhidev2: input=64, output=64, feature=0
uhub0: autoconfiguration error: illegal enable change, port 1
mue0 at uhub2 port 1
mue0: vendor 0424 (0x0424) product 7800 (0x7800), rev 2.10/3.00, addr 5
mue0: LAN7800 id 0x7800 rev 0x2
ukphy0 at mue0 phy 1: OUI 0x00800f, model 0x0013, rev. 2
ukphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, 1000baseT, 1000baseT-FDX, auto
mue0: Ethernet address b8:27:eb:09:23:d3
cgd: self-test aes-xts-256
cgd: self-test aes-xts-512
cgd: self-test aes-cbc-128
cgd: self-test aes-cbc-256
cgd: self-test 3des-cbc-192
cgd: self-test blowfish-cbc-448
cgd: self-test aes-cbc-128 (encblkno8)
cgd: self-tests passed
WARNING: 2 errors while detecting hardware; check system log.
boot device: ld0
unknown device major 0xffffffffffffffff
root device (default ld0a):
dump device (default ld0b):
file system (default generic):
root on ld0a dumps on ld0b
root file system type: ffs
kern.module.path=/stand/evbarm/9.99.78/modules
WARNING: clock lost 15 days
vchiq0: interrupting on icu irq 66
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
vchiq: vchiq_init_state: slot_zero = 0xffffc000430e0000, is_master = 0
vchiq: local ver 8 (min 3), remote ver 8.
vcaudio0 at vchiq0: auds
bwfm0: Firmware file default: brcmfmac43455-sdio.bin
bwfm0: Firmware file model-spec: brcmfmac43455-sdio.raspberrypi,3-model-b-plus.bin
audio0 at vcaudio0: playback, capture, half duplex, independent
audio0: slinear_le:16 -> slinear_le:16 2ch 48000Hz, blk 7680 bytes (40ms) for playback
audio0: slinear_le:16 2ch 48000Hz, blk 7680 bytes (40ms) for recording
spkr0 at audio0: PC Speaker (synthesized)
wsbell at spkr0 not configured
bwfm0: Found Firmware file: brcmfmac43455-sdio.bin
bwfm0: NVRAM file default: brcmfmac43455-sdio.txt
bwfm0: NVRAM file model-spec: brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt
bwfm0: Found NVRAM file: brcmfmac43455-sdio.raspberrypi,3-model-b-plus.txt
bwfm0: CHIPACTIVE
bwfm0: wl0: Mar 1 2015 07:29:38 version 7.45.18 (r538002) FWID 01-6a2c8ad4
bwfm0: address b8:27:eb:5c:76:86
init path (default /sbin/init):
init: trying /sbin/init
wsdisplay0: screen 4 added (default, vt100 emulation)