Last updated Oct 1st, 2018.
This is a port of 64-bit Tiano Core UEFI firmware for the Pi 3/3B+ platforms, based on Ard Bisheuvel's 64-bit and Microsoft's 32-bit implementations.
Initially, this was supposed to be an easy walk in the park, where the Microsoft drivers just sorta slid into Ard's UEFI implementation, and I would call it a day. Instead, it turned out to be a severely more frustrating experience :-).
This is meant as a generally useful 64-bit ATF + UEFI implementation for the Pi 3/3B+, good enough for most kinds of UEFI development and good enough for running real operating systems. It has been validated to install and boot Linux (SUSE, Ubuntu), NetBSD and FreeBSD, and there is experimental (64-bit) Windows on Arm support as well. It wound up being the early development platform for NetBSD's 64-bit Arm UEFI bootloader.
It's mostly EBBR compliant, favoring user experience over pedantic compliance where those two are in conflict. With enough HypDxe grease it may even, some day, pass for an SBSA + SBBR system ;-).
Here is a comparison table between different available EFI firmware implementations for the RPi3.
| Feature | This Implementation | Ard's | Microsoft's | U-Boot | Minoca |
|---|---|---|---|---|---|
| Bitness | 64-bit | 64-bit | 32-bit | Either | 32-bit |
| PSCI CPU_ON | Yes | No | No | No | No |
| PSCI SYSTEM_RESET | Yes | Yes | No | No | No |
| PSCI SYSTEM_OFF | Yes | No | No | No | No |
| DT | Yes | Yes | No | Yes | No |
| Pass-through DT | Yes | No | N/A | Yes | No |
| NVRAM | Limited | No | No | No | No |
| RTC | Limited | No | No | No | No |
| ACPI | Yes | No | Yes | No | Yes |
| Serial | Yes | Yes | Yes | Yes | Yes |
| HDMI GOP | Yes | No | No | Yes | No |
| SMBIOS | Yes | No | Yes | No | Yes |
| uSD | Yes | No | Yes | Yes | Yes |
| uSD SdHost and Arasan | Yes | No | Yes | ? | No |
| USB1 | Limited | No | No | Yes | No |
| USB2/3 | Yes | No | No | Yes | No |
| USB Mass Storage | Yes | No | No | Yes | No |
| USB Keyboard | Yes | No | No | Yes | No |
| USB Ax88772b PXE/Network | Yes | No | No | Yes | No |
| USB SMSC95xx PXE/Network | No | No | No | Yes | No |
| Tiano | Yes | Yes | Yes | No | No |
| AArch32 Windows IoT | No | No | Yes | No | No |
| AArch64 Windows on Arm | Limited | No | No | No | No |
| AArch64 Linux | Yes | Limited | No | Yes | No |
| AArch32 Linux | No | No | No | Yes | No |
| AArch64 FreeBSD | Yes | No | No | Yes | No |
| AArch32 Minoca | No | No | No | No | Yes |
Note: If you want to use the pre-built UEFI images, you can skip this section.
https://github.com/tianocore/edk2.gitThis is the last known good edk2 commit:
commit 989f7a2cf0e27123fda5ca538b15832e115e0f4e
Author: cinnamon shia <cinnamon.shia@hpe.com>
Date: Fri May 11 23:21:12 2018 +0800
You should rewind your edk2 tree to this commit. Here be dragons!
Clone this repo.
Apply the various patches against the edk2 tree. Yes, it sucks to have to do this, but this is a clearer way forward than forking every single Tiano driver that has a bug in it, or worse - carrying around an entire private fork of edk2. You're welcome to upstream these patches!
To avoid issues, apply using --ignore-whitespace. E.g.:
$ git am --ignore-whitespace ../RaspberryPiPkg/edk2Patches/*.patch
GCC49_AARCH64_PREFIX if you're passing -t GCC49 to build.If you want to build your own ATF, instead of using the checked-in binaries, follow
the additional directions under Binary/atf/readme.md.
UEFI boot media can be a uSD card or USB mass storage, if you've enabled USB booting previously in the OTP (i.e. via program_usb_boot_mode=1).
UEFI boot media must be MBR partitioned and FAT32 formatted.
As a starting point, take one of the latest RELEASE prebuilt image directories and copy contents to empty boot media. If you've built your own UEFI from source (e.g. $WORKSPACE/Build/RaspberryPiPkg-AARCH64/RELEASE_GCC5/FV/RPI_EFI.fd) you can simply now copy over and overwrite RPI_EFI.fd.
Note: You may not have a kernel.img (or kernelX.img, where X is a digit) in the root catalogue of the boot media. It will not boot.
The most basic config.txt contents are:
arm_control=0x200
enable_uart=1
armstub=RPI_EFI.fd
disable_commandline_tags=1
This will boot UEFI and expose an RPi3 device tree that is compatible with openSUSE Leap 42.2/42.3, although it was found to work with Ubuntu 18.04 (Bionic Beaver) as well.
Of course use the debug variant (e.g. $WORKSPACE/Build/RaspberryPiPkg-AARCH64/DEBUG_GCC5/FV/RPI_EFI.fd) if necessary, but it will boot a lot slower due to the verbose spew.
HDMI and the mini-UART serial port can be used for output devices. Output is mirrored. USB keyboards and the mini-UART serial port can be used as input.
USB keyboard support has been validated with a few keyboards: - Logitech K750 (wireless) - Dell SK-8125 keyboard (with built-in hub) - Microsoft Natural Ergonomic Keyboard 4000 - An Apple keyboard (chicklet, USB2 hub)
The boot order is hardcoded to first be the USB ports and then the uSD card. If there are no bootable media, you should be looking at the UEFI Shell. ESC enters setup. F1 always boots the UEFI Shell.

Note: you cannot boot 32-bit OSes like Raspbian with this firmware. Aw, shucks, right?
Most likely, if you boot an OS other than openSUSE Leap 42.3, you will need to pass your own distro- and kernel- specific device tree. This will need to be extracted from the distributed media or from a running system (e.g that was booted via U-Boot).
This involves a few changes to the above config.txt:
...
disable_commandline_tags=2
device_tree_address=0x8000
device_tree_end=0x10000
device_tree=my_fdt.dtb
Note: the address range must be [0x8000:0x10000). dtoverlay and dtparam parameters are also supported.
bootargsThis firmware will honor the command line passed by the GPU via cmdline.txt.
Note, that the ultimate contents of /chosen/bootargs are a combination of several pieces:
- Original /chosen/bootargs if using the internal DTB. Seems to be completely discarded by GPU when booting with a custom device tree.
- GPU-passed hardware configuration. This one is always present.
- Additional boot options passed via cmdline.txt.
Untested with the Pi 3 B+. You may need to get the latest device tree and follow the instructions.
Download the Leap 42.3 RPi image first, from http://download.opensuse.org/ports/aarch64/distribution/leap/42.3/appliances/ (e.g. openSUSE-Leap42.3-ARM-XFCE-raspberrypi3.aarch64-2017.07.26-Build1.1 was good).
dd image to media.EFI partition, delete everything but the EFI folder.Login is root/linux. There is also a login available on the serial port.
Note: if your media is USB, after first boot you must follow these steps, or you will have an unbootable system after first reboot:
- Edit the file /etc/dracut.conf.d/raspberrypi_modules.conf to include as its first line:
add_drivers+=" bcm2835-sdhost bcm2835_dma sdhci_bcm2835 dwc2 usbnet uas usb_storage usbcore usb_common "
- mkinitrd
You may choose to remove enable_uart=1 from config.txt to get your RPi3 to run
at full speed.
If you wish to use virtualization (e.g. KVM), you must configure UEFI to boot in EL2 mode. In UEFI setup screen:
- go to Device Manager
- go to Raspberry Pi Configuration
- go to HypDxe Configuration
- configure System Boot Mode as Boot in EL2
- after saving, Pi will reset itself.
Untested with the Pi 3 B+. You may need to get the latest device tree and follow the instructions.
http://ports.ubuntu.com/ubuntu-ports/dists/bionic/main/installer-arm64/current/images/netboot/mini.iso and write out to a USB stick.There is a device tree blob under http://ports.ubuntu.com/ubuntu-ports/dists/bionic/main/installer-arm64/current/images/device-tree/bcm2837-rpi-3-b.dtb, which you will need to use to if you want Wi-Fi and Bluetooth, but otherwise things seem to work just fine with
the bundled openSUSE Leap 42.2 device tree.
Note: don't use DEBUG builds of ATF (e.g. DEBUG builds of UEFI) with Ubuntu, as the latter
disables the mini-UART port, which the ATF relies on for logging. If you want to use a DEBUG
build of UEFI, you must use a release version of ATF. Follow the directions under Binary/atf/readme.md.
For Wi-Fi and BT there are a few more steps, as certain firmware files appear to be missing from the installation:
- cd /lib/firmware/brcm/
- wget https://raw.githubusercontent.com/RPi-Distro/firmware-nonfree/master/brcm/brcmfmac43430-sdio.txt
- wget https://github.com/OpenELEC/misc-firmware/raw/master/firmware/brcm/BCM43430A1.hcd
- apt-get install wireless-regdb
If you wish to use virtualization (e.g. KVM), you must configure UEFI to boot in EL2 mode. In UEFI setup screen:
- go to Device Manager
- go to Raspberry Pi Configuration
- go to HypDxe Configuration
- configure System Boot Mode as Boot in EL2
- after saving, Pi will reset itself.
Untested with the Pi 3 B+. You may need to get the latest device tree and follow the instructions.
http://ftp.freebsd.org/pub/FreeBSD/snapshots/ISO-IMAGES/12.0/FreeBSD-12.0-CURRENT-arm64-aarch64-RPI3-20171206-r326622.img.xzdd to media.MSDOSBOOT partition, except:EFIoverlaysbcm2710-rpi-3-b.dtbbcm2710-rpi-3-b.dtb and overlays to the UEFI boot media.Now replace config.txt in the UEFI boot media with:
arm_control=0x200
armstub=RPI_EFI.fd
enable_uart=1
disable_commandline_tags=2
dtoverlay=mmc
dtparam=audio=on,i2c_arm=on,spi=on
device_tree_address=0x8000
device_tree_end=0x10000
device_tree=bcm2710-rpi-3-b.dtb
For a different (newer) release, you will need to look at the original config.txt.
This should boot to login prompt on HDMI with USB HID as the input. Login is root/root.
Note: you must remove dtoverlay=pi3-disable-bt, if present, from config.txt, as both ATF and UEFI rely on the mini-UART being initialized.
PL011 serial console in FreeBSD
$ claude mcp add RaspberryPiPkg \
-- python -m otcore.mcp_server <graph>