Home

Awesome

DEPRECATED - DO NOT USE

This repo isn't just resting - it's dead. Why? Because it's been upstreamed to the master TianoCore UEFI branch - https://github.com/tianocore/edk2-platforms/tree/master/Platform/RaspberryPi/RPi3

This is going to remain up only for historical purpose.

Also see https://rpi4-uefi.dev

64-bit Tiano Core UEFI for the Raspberry Pi 3

Last updated Feb 18th, 2019.

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 somewhat slid into Ard's UEFI implementation, and I would call it a day. Instead, it turned out to be a severely more frustrating experience :-).

Purpose

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, and was used to demonstrate VMware ESXi-Arm on the Pi as well.

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 ;-).

Latest Status

Features

Here is a comparison table between different available EFI firmware implementations for the RPi3.

FeatureThis ImplementationArd'sMicrosoft'sU-BootMinoca
Bitness64-bit64-bit32-bitEither32-bit
PSCI CPU_ONYesNoNoNoNo
PSCI SYSTEM_RESETYesYesNoNoNo
PSCI SYSTEM_OFFYesNoNoNoNo
DTYesYesNoYesNo
Pass-through DTYesNoN/AYesNo
NVRAMLimitedNoNoNoNo
RTCLimitedNoNoNoNo
ACPIYesNoYesNoYes
SerialYesYesYesYesYes
HDMI GOPYesNoNoYesNo
SMBIOSYesNoYesNoYes
uSDYesNoYesYesYes
uSD SdHost and ArasanYesNoYes?No
USB1LimitedNoNoYesNo
USB2/3YesNoNoYesNo
USB Mass StorageYesNoNoYesNo
USB KeyboardYesNoNoYesNo
USB Ax88772b PXE/NetworkYesNoNoYesNo
USB SMSC95xx PXE/NetworkNoNoNoYesNo
TianoYesYesYesNoNo
AArch32 Windows IoTNoNoYesNoNo
AArch64 Windows on ArmLimitedNoNoNoNo
AArch64 LinuxYesLimitedNoYesNo
AArch32 LinuxNoNoNoYesNo
AArch64 FreeBSDYesNoNoYesNo
AArch32 MinocaNoNoNoNoYes

Building

Note: If you want to use the pre-built UEFI images, you can skip this section.

  1. Clone https://github.com/tianocore/edk2.git

This is the last known good edk2 commit:

commit 66127011a544b90e800eb3619e84c2f94a354903
Author: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Date:   Wed Nov 14 11:27:24 2018 -0800

    ArmPkg/ArmGicDxe ARM: fix encoding for GICv3 interrupt acknowledge

You should rewind your edk2 tree to this commit. Here be dragons!

  1. Clone this repo.

  2. 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
  1. Use one of the provided templates for your build script. If you use a different GCC version, change accordingly, and adjust the compiler prefix to match your system - i.e. set 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.

Using

Basic

Please USE AN ADEQUATE POWER SUPPLY. Many people have had problems with poor performance (CPU underclocking itself to 600MHz) and other errors and issues (e.g. with USB) caused by an inadequate power supply. Recommended: 5V 3A. Many cheapo 2.5A power bricks can't really provide 2.5A. If you see a lightning bolt in the top right corner of the screen you have inadequate power.

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:

The first time you boot, you will be looking at the UEFI Shell. 'exit' and modify the boot order. The boot order will persist across reboots. The boot manager will only list devices available to boot from (older versions had USB Port 0, USB Port 1, etc).

ESC enters setup. F1 always boots the UEFI Shell.

FrontPage

Note: you cannot boot 32-bit OSes like Raspbian with this firmware. Aw, shucks, right?

Custom Device Tree

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.

Custom bootargs

This 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:

openSUSE Leap 42.3

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).

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:

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:

Ubuntu (18.04 Bionic Beaver)

Untested with the Pi 3 B+. You may need to get the latest device tree and follow the instructions.

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:

If you wish to use virtualization (e.g. KVM), you must configure UEFI to boot in EL2 mode. In UEFI setup screen:

FreeBSD (r326622)

Untested with the Pi 3 B+. You may need to get the latest device tree and follow the instructions.

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 is not supported, yet.

64-bit Windows on Arm

Builds 17125-17134, 17672 are known to work.

Validated with a Pi3B+ as well.

To try:

System should boot to a single cmd.exe window.

Note: there are no built-in drivers for anything.

Note: if HypDxe is configured to Boot in EL2, Windows on Arm will not boot. The remaining HypDxe configuration options are developer-oriented.

https://github.com/andreiw/RaspberryPiPkg/issues/12 for related discussion.

Also see https://www.worproject.ml/ and https://www.worproject.ml/bugtracker (not affiliated with RaspberryPiPkg).

Bugs in Implemented Functionality

HDMI

The UEFI HDMI video support relies on the VC (that's the GPU) firmware to correctly detect and configure the attached screen. Some screens are slow, and this detection may not occur fast enough. Finally, you may wish to be able to boot your Pi headless, yet be able to attach a display to it later for debugging.

To accommodate these issues, the following extra lines are recommended for your config.txt:

While the VC firmware is reponsible for setting the physical resolution, the virtual resolution the GPU framebuffer uses may be different and it scales the video appropriately. By default, the UEFI framebuffer driver makes available the following virtual resolutions:

Note that this lets you do weird stuff, like pretending to have 1080p while connected to a TV. Sometimes blurry is better than nothing...

Note: the VC framebuffer is a bit weird and will change physical locations depending on virtual resolution chosen. Some UEFI applications or OS loaders may violate the GOP spec and never refresh the framebuffer addressing after setting the mode. You can completely disable multiple virtual resolution support:

NVRAM

The Raspberry Pi has no NVRAM.

NVRAM is emulated, with the non-volatile store backed by the UEFI image itself. This means that any changes made in UEFI proper will be persisted, but changes made in HLOS will not. It would be nice to implement ATF-assisted warm reboot, to allow persisting HLOS NVRAM changes.

RTC

The Rasberry Pi has no RTC.

RtcEpochSeconds NVRAM variable is used to store the boot time This should allow you to set whatever date/time you want using the Shell date and time commands. While in UEFI or HLOS, the time will tick forward. RtcEpochSeconds is not updated on reboots.

uSD

UEFI supports both the Arasan SDHCI and the Broadcom SDHost controllers to access the uSD slot. You can use either. The other controller gets routed to the SDIO card. The choice made will impact ACPI OSes booted (e.g. Windows 10). Arasan, being an SDIO controller, is usually used with the WiFi adapter where available. SDHost cannot be used with SDIO. In UEFI setup screen:

Known issues:

USB

ACPI

More-or-less matches MS-IoT ones. Good enough to boot WinPE, but unclear how functional all of it is, given current state of WoA on RPi3. Both Arasan and SDHost SD controllers are exposed.

Missing Functionality

Licensing

All of the code is BSD licensed.

Contact

Andrey Warkentin andrey.warkentin@gmail.com

Btw, feel free to upstream, if so inclined.