UEFI

The Linaro Enterprise Group is now championing UEFI with Linaro. They are hosting a Linaro-EDK2 GIT tree that contains work in progress from various Landing Teams and from LEG.

The ARM Landing Team in Linaro is maintaining patched based on the SourceForge Tianocore GIT tree. The Landing Team manually updates, patches, builds and tests their own tree and then sends a pull request for their topics to the Linaro-EDK2 maintainers. The maintainers

Supported Platforms

The Linaro ARM Landing Team maintains a codebase that supports the following platforms:

  • ARM Versatile Express A9
  • ARM Versatile Express A5
  • ARM Versatile Express A15 TC1
  • ARM Versatile Express A15-A7 TC2

As a result of only supporting one platform type, this page is more "UEFI on Versatile Express" than a generic UEFI page.

You can also run UEFI in the ARM Fixed Virtual Platforms (aka FastModels) for AArch32 and AArch64. See the Fast Model page for instructions.

Getting UEFI from Linaro releases

The latest Linaro release contains instructions on how to update your Versatile Express firmware and install UEFI onto your board.

Linaro provides a GIT repository containing all of the motherboard files needed program a customised version of the firmware provided by ARM. The modifications configurre files for each supported platform to run a UEFI binary by default on boot. The UEFI binaries can be found in the SOFTWARE directory on the motherboard, where each platform has it's own sub-directory, eg, "TC2".

If you wish to use the UEFI binary that shipped with release you are using, the following Android and Ubuntu sections will show you how to overwrite the files supplied in the ZIP.

Configure UEFI

After installation, you need to configure UEFI to boot your Linaro image from SD card.

initrd

Android and Ubuntu images require an initrd to be configured. OpenEmbedded images do not. A feature of the latest versions of UEFI (13.11 and later) allows an initrd to be configured and the board will continue to boot if it is not found. Therefore, the same config can again be used for Android, Ubuntu and OpenEmbedded.

If the configured initrd is not present, you will now see this error message before UEFI continues to boot:

ERROR: Did not find initrd image, you may need to update your config. Attempting to continue without it.

This error is not fatal, but boot may not succeed if you are expecting an initrd to be present, eg, if you are booting Android, then you should resolve the cause of the missing initrd.

Restoring the default config

If you upgrade your UEFI binary to the latest version, the old config is still remembered over a reboot. If you wish to use the default config stored in the binary, use the UEFI Boot Manager to delete all current confis, then simply reboot to pick up the default config again.

Kernel Command Line

Note that the examples below show how to configure UEFI to boot a Linaro image using the following commandline:

console=ttyAMA0,38400n8  rootwait root=/dev/mmcblk0p2 selinux=0

The command lines for both Ubuntu and Android images has been merged to create one that works for both. For example, Android will ignore the "root=" option and Ubuntu will ignore the "selinux=0" option.

But, for easy of typing, you can use the following commandline on Android:

console=ttyAMA0,38400n8  selinux=0

And the following commandline on OpenEmbedded:

console=ttyAMA0,38400n8  rootwait root=/dev/mmcblk0p2

Note, the tiles that boot with Device Tree no longer need the "mmci.fmax" option. This is provided in the DTB file for each board.

WARNING: when you enter the commandline, be careful not to use the backspace key. It will look like it's deleted characters and allow you to enter more, but most likely, it well leave you with a corrupt commandline in your config and then your kernel won't boot

Configuring UEFI to boot Android on Juno

The default boot selection will start in   8 seconds
[1] Linux from NOR Flash
[2] Shell
[3] Boot Manager
Start: 3
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 3
[1] Linux from NOR Flash
Delete entry: 1
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 1
[1] Firmware Volume (0 MB)
[2] Firmware Volume (0 MB)
[3] NOR Flash (63 MB)
[4] VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)
[5] VenHw(02118005-9DA7-443A-92D5-781F022AEDBB)
[6] PXE on MAC Address: 00:02:F7:00:57:DD
[7] TFTP on MAC Address: 00:02:F7:00:57:DD
Select the Boot Device: 

note: the USB partitions are not found on the first attempt. At this point, you need to press ESC to abort, then continue to follow the example, as shown below:

[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 1
[1] Firmware Volume (4068 MB)
[2] Firmware Volume (4068 MB)
[3] NOR Flash (63 MB)
[4] boot (131 MB)
[5] sdcard (13585 MB)
[6] VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)
[7] VenHw(02118005-9DA7-443A-92D5-781F022AEDBB)
[8] PXE on MAC Address: 00:02:F7:00:57:DD
[9] TFTP on MAC Address: 00:02:F7:00:57:DD
Select the Boot Device: 4
File path of the EFI Application or the kernel: kernel
Has FDT support? [y/n] y
Add an initrd: [y/n] y
File path of the initrd: ramdisk.img
Arguments to pass to the binary: console=ttyAMA0,115200 earlyprintk=pl011,0x7ff80000 root=/dev/ram0 verbose debug selinux=0
Description for this new Entry: Android on USB
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 4
[1] Firmware Volume (4068 MB)
[2] Firmware Volume (4068 MB)
[3] NOR Flash (63 MB)
[4] boot (131 MB)
[5] sdcard (13585 MB)
[6] VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)
[7] VenHw(02118005-9DA7-443A-92D5-781F022AEDBB)
[8] PXE on MAC Address: 00:02:F7:00:57:DD
[9] TFTP on MAC Address: 00:02:F7:00:57:DD
Select the Boot Device: 4
File path of the FDT blob: juno.dtb
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 5
[1] Android on USB
[2] Shell
[3] Boot Manager
Start: 1
   PEI    217 ms
   DXE     48 ms
   BDS   3086 ms
Total Time = 3352 ms

[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.10.40-04499-g1866f48 (jenkins-build@ip-10-62-41-78) (gcc version 4.9.1 20140529 (prerelease) (Linaro GCC 4.9-2014.06) ) #1 SMP Tue Jun 17 02:28:46 UTC 2014
[    0.000000] CPU: AArch64 Processor [410fd030] revision 0
[    0.000000] Machine: Juno

Configuring UEFI to boot OpenEmbedded on Juno

The default boot selection will start in   8 seconds
[1] Linux from NOR Flash
[2] Shell
[3] Boot Manager
Start: 3
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 3
[1] Linux from NOR Flash
Delete entry: 1
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 1
[1] Firmware Volume (0 MB)
[2] Firmware Volume (0 MB)
[3] NOR Flash (63 MB)
[4] VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)
[5] VenHw(02118005-9DA7-443A-92D5-781F022AEDBB)
[6] PXE on MAC Address: 00:02:F7:00:57:DD
[7] TFTP on MAC Address: 00:02:F7:00:57:DD
Select the Boot Device: 

note: the USB partitions are not found on the first attempt. At this point, you need to press ESC to abort, then continue to follow the example, as shown below:

[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 1
[1] Firmware Volume (4068 MB)
[2] Firmware Volume (4068 MB)
[3] NOR Flash (63 MB)
[4] boot (67 MB)
[5] VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)
[6] VenHw(02118005-9DA7-443A-92D5-781F022AEDBB)
[7] PXE on MAC Address: 00:02:F7:00:57:DD
[8] TFTP on MAC Address: 00:02:F7:00:57:DD
Select the Boot Device: 4
File path of the EFI Application or the kernel: Image
Has FDT support? [y/n] y
Add an initrd: [y/n] n
Arguments to pass to the binary: console=ttyAMA0,115200 rootwait root=/dev/sda2
Description for this new Entry: OpenEmbedded on USB
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 4
[1] Firmware Volume (4068 MB)
[2] Firmware Volume (4068 MB)
[3] NOR Flash (63 MB)
[4] boot (67 MB)
[5] VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)
[6] VenHw(02118005-9DA7-443A-92D5-781F022AEDBB)
[7] PXE on MAC Address: 00:02:F7:00:57:DD
[8] TFTP on MAC Address: 00:02:F7:00:57:DD
Select the Boot Device: 4
File path of the FDT blob: juno\juno.dtb
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 5
[1] OpenEmbedded on USB
[2] Shell
[3] Boot Manager
Start: 1
   PEI    217 ms
   DXE     48 ms
   BDS 368934797873 ms
   BDS   3650 ms
Total Time = 368934801789 ms

[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.10.40.0-1-linaro-lt-vexpress64 (buildslave@x86-64-07) (gcc version 4.8.3 20140401 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.04 - Linaro GCC 4.8-2014.04) ) #1ubuntu1~ci+140623185422 SMP Mon Jun 23 18:55:05 UTC 2014
[    0.000000] CPU: AArch64 Processor [410fd030] revision 0
[    0.000000] Machine: Juno

Configuring UEFI for Versatile Express

Insert the MMC card before you boot the board and follow the sequence below. This sequence was created on a TC2 board. The only difference between A5, A9, TC1and TC2 is the filename used for the FDT file. For A5, use "v2p-ca5s.dtb" and for TC1 use "v2p-ca15-tc1.dtb" and for A9 use v2p-ca9.dtb

NOTE: from 14.12 onwards, the name of the kernel image is "kernel" and the initrd is "ramdisk.img". Previously they were "uImage" and "uInitrd".

The default boot selection will start in  10 seconds
[1] Linaro image on SD card
[2] Shell
[3] Boot Manager
Start: 3
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 3
[1] Linaro image on SD card
Delete entry: 1
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 1
[1] Firmware Volume (201916416 MB)
[2] Firmware Volume (268697600 MB)
[3] NOR Flash (63 MB)
[4] NOR Flash (63 MB)
[5] boot (67 MB)
[6] VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)
[7] VenHw(02118005-9DA7-443A-92D5-781F022AEDBB)
[8] VenHw(1F15DA3C-37FF-4070-B471-BB4AF12A724A)
[9] VenHw(CC2CBF29-1498-4CDD-8171-F8B6B41D0909)
[10] PXE on MAC Address: 00:02:F7:00:45:86
[11] TFTP on MAC Address: 00:02:F7:00:45:86
Select the Boot Device: 5
File path of the EFI Application or the kernel: kernel
Has FDT support? [y/n] y
Add an initrd: [y/n] y
File path of the initrd: ramdisk.img
Arguments to pass to the binary: console=ttyAMA0,38400n8  rootwait root=/dev/mmcblk0p2 selinux=0
Description for this new Entry: Linaro image on SD card
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 4
[1] Firmware Volume (390532024 MB)
[2] Firmware Volume (390532024 MB)
[3] NOR Flash (63 MB)
[4] NOR Flash (63 MB)
[5] boot (67 MB)
[6] VenHw(E7223039-5836-41E1-B542-D7EC736C5E59)
[7] VenHw(02118005-9DA7-443A-92D5-781F022AEDBB)
[8] VenHw(1F15DA3C-37FF-4070-B471-BB4AF12A724A)
[9] VenHw(CC2CBF29-1498-4CDD-8171-F8B6B41D0909)
[10] PXE on MAC Address: 00:02:F7:00:45:86
[11] TFTP on MAC Address: 00:02:F7:00:45:86
Select the Boot Device: 5
File path of the FDT blob: v2p-ca15-tc2.dtb
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Update FDT path
[5] Return to main menu
Choice: 5
[1] Linaro image on SD card
[2] Shell
[3] Boot Manager
Start: 

Updating your UEFI binary

Updating your UEFI binary from the latest Android release

After creating an image by either downloading a pre-built image or by creating one using linaro-android-media-create, you can mount the image and extract the UEFI binary.

Updating your UEFI binary from the latest Ubuntu/hwpack release

After creating an image by either downloading a pre-built image or by creating one using linaro-media-create, you can mount the image and extract the UEFI binary.

Updating your UEFI binary from the release image

For example, my system mounts the boot partition of my MMC card in /media/boot. I also have my Versatile Express mass storage device mounted to /media/VEMSD. To copy the UEFI binaries to my board, I need to do the following:

$ cp /media/boot/uefi_v2p-ca5s.bin /media/VEMSD/SOFTWARE/A5/uefi.bin
$ cp /media/boot/uefi_v2p-ca9.bin /media/VEMSD/SOFTWARE/A9/uefi.bin
$ cp /media/boot/uefi_v2p-ca15-tc1.bin /media/VEMSD/SOFTWARE/TC1/uefi.bin
$ cp /media/boot/uefi_v2p-ca15-tc2.bin /media/VEMSD/SOFTWARE/TC2/uefi.bin

Linaro Snapshot builds

Linaro has snapshot builds of the latest UEFI code available here:

Where the "linaro-edk2" binaries are built from the release branch and the "linaro-edk2-release-prep" binaries are built from the code being prepared for the next release.

Linaro Release builds

Linaro also created a monthly release of UEFI. These binaries are not always the same as those found in the hardware pack or Android image.

By example, the binaries for the 14.02 release are here:

GIT Tree

You can find the GIT tree for Linaro releases and latest development code here: https://git.linaro.org/uefi/linaro-edk2.git

UEFI Tools

The ARM Landing Team has written some tools to make building UEFI simpler. You can get these here:

Add them to your path to make them easier to use.

The main tool is "uefi-build.sh". Run it without parameters to get a list of platforms that you can build. Use parameters "-b RELEASE" and/or "-b DEBUG" to over-ride the default DEBUG build target.

Output files are in the Build directory. The filename change occasionally, so using "find" to location them is often the most portable way, eg:

find Build -name *.fd

Erasing old config

If you see an ASSERT followed by a hang each time you boot UEFI, then the chances are that you have an incompatible config on your board. For example, if you move from an upstream UEFI to a Linaro UEFI, you may see this error on boot:

ASSERT /mnt/ci_build/workspace/uefi/
uefi/MdePkg/Library/
UefiDevicePathLib/
UefiDevicePathLib.c(169): Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)

There are two ways of working around this:

  1. re-install the previous version, then delete all boot devices. Install the new version again and reboot.
  2. erase the NOR flash

Erasing NOR flash

Assuming that /media/VEMSD/config.txt has AUTORUN set to FALSE, the board will power up into the ARM Boot Loader. The following log shows how I erased all of NOR flash on my board:

ARM V2M Boot loader v1.1.2
HBI0190 build 2199
ARM V2M Firmware v3.1.1
Build Date: Aug 20 2012
Date: Thu 14 Feb 2013
Time:     11:46:39
Cmd> flash
Switching on ATXPSU...
Flash> eraseall
Erasing flash device 0
Erasing Flash
...............................................................................................................................................................................................................................................................
Erasing Flash
....
Erasing flash device 1
Erasing Flash
...............................................................................................................................................................................................................................................................
Erasing Flash
....
Flash> exit
Switching off ATXPSU...
Cmd> reboot

After reboot, the board will re-write all of the images from image.txt and boot the board normally. UEFI will detect that the config area is blank and write a default config to it. The latest versions of Linaro UEFI (since 14th Feb 2013) have a default config that will boot a Linaro SD card with UUID set to zero.

CONFIG_EFI, the EFI Shell and and EFI Stubbed kernel

Configuring UEFI to boot Shell by default

Start by deleting all boot device entries, then follow this example:

[1] Shell
[2] Boot Manager
Start: 2
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Reorder Boot Device Entries
[5] Update FDT path
[6] Set Boot Timeout
[7] Return to main menu
Choice: 1
[1] boot (131 MB)
[2] sdcard (13521 MB)
[3] Firmware Volume (0 MB)
[4] Firmware Volume (0 MB)
[5] NOR Flash (63 MB)
[6] PXE on MAC Address: 00:02:F7:00:5B:71
[7] TFTP on MAC Address: 00:02:F7:00:5B:71
Select the Boot Device: 4
File path of the EFI Application or the kernel: Shell.efi
Is your application an OS loader? [y/n] y
Arguments to pass to the EFI Application: 
Description for this new Entry: Run the UEFI Shell
[1] Add Boot Device Entry
[2] Update Boot Device Entry
[3] Remove Boot Device Entry
[4] Reorder Boot Device Entries
[5] Update FDT path
[6] Set Boot Timeout
[7] Return to main menu
Choice:7
[1] Run the UEFI shell
[2] Shell
[3] Boot Manager

Now, when you boot your board, it will run the Shell automatically.

Running an EFI Stubbed kernel from the Shell

Linaro releases up until 14.12 did NOT have an EFI stub, ie. they are built with CONFIG_EFI=n. From 15.01 onwards, Linaro intends to enable the EFI Stub (CONFIG_EFI=y) and start booting via the EFI shell with an EFI stubbed kernel.

To launch any EFI application from the EFI Shell, you simply type it's filename at the command prompt, followed by any parameters you wish to pass. Note, at present, the entire EFI Shell command seems to be sent to the application as a parameter list.

So, as an EFI Stubbed kernel is actually an EFI application, you can copy it to any boot device and just call it's filename as a command, eg, "Image". Of course, the kernel is unlikely to boot like that.

To boot Juno from NOR flash with a kernel called "Image", with a DTB called "juno" and an initrd called "ramdisk", I used this command:

Image dtb=juno initrd=ramdisk console=ttyAMA0,115200 selinux=0

To boot a Linaro Juno Android disk image, I used this command:

kernel dtb=juno.dtb initrd=ramdisk.img console=ttyAMA0,115200 selinux=0

And to boot an Juno OpenEmbedded disk image, I first removed the Image file from NOR flash, then used this command:

Image dtb=juno/juno.dtb console=ttyAMA0,115200 rootwait root=/dev/sda2

NOTE: you will probably encounter problems if you have a multiple kernels with the same filename on multiple boot devices.

For example, NOR Flash usually contains a kernel file called "Image", as does the OpenEmbedded disk image. Because UEFI simply searches the boot devices for the file, I guess it will run whichever one it finds first, which is probably not deterministic or reliable. You've been warned!

NOTE: the kernel, DTB and initrd must all live in the same place, eg, NOR flash, or the /boot partition, or wherever.

NOTE: I don't believe that the Shell scans sub-dirs, but I could be wrong.

startup.nsh

On startup, the EFI Shell will attempt to find the file "startup.nsh" on the various boot devices on the system, eg. in NOR flash, the fat32 BOOT partition on the USB stick/MMC card, etc...

If it finds this file, it will attempt to execute the EFI Shell commands within it.

If a command fails, it will move on to the next command and so on.

Therefore, it's possible to create a single startup.nsh that will attempt to boot multiple platforms/configs/OSes with a bit of crafty manipulation. It's quite error prone, however. For example, if you have "Image" as a non-EFI stubbed file in NOR flash and the script attempts to run it, the script will simply abort.

Rebooting

Older Linaro versions of UEFI, like those in some vexpress images, contain a UEFI menu option to reboot the board. However, these patches never made it upstream, so it seems impossible to remotely reboot a board that it sat runing UEFI.

However, you can use the EFI Shell's "reset" command on some boards, eg, Juno.

ARM/UEFI (last modified 2015-03-25 10:49:46)