Skip to content

Instantly share code, notes, and snippets.

Created June 19, 2016 20:37
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Building instructions for firmware image

Rebuilding the firmware image

The Pine64 firmware consists of four parts:

  • The on-chip boot ROM (BROM), which cannot be changed and does the very first steps in loading code. It is part of the A64 SoC and thus not included here.
  • A secondary program loader (SPL): Its main task is to initialize the DRAM and load the remaining firmware parts. Due to BROM limitations the SPL is limited in size to 32K. The SPL can be a part of U-Boot, but at the moment we lack free source for the DRAM initialization. The alternative is to use Allwinner's boot0, which is a closed source, but redistributable blob serving the same purpose.
  • An EL3 runtime firmware. The task of this code is to provide runtime services like PSCI. It stays resident during the whole time and can be called from an OS like Linux to enable or disable secondary cores or request other services. It also takes care of low level CPU initialization and some errata handling. We use a version of ARM Trusted Firmware, based on the official 1.0 release from ARM and ported by Allwinner to support the A64. There are a lot of patches on top of this to fix some Allwinner accidents and bring it into a sane state again.
  • An U-Boot bootloader. This provides an user interface and allows to load kernels and other data into the memory to eventually start the system. Since version 2016.07-rc1 the Pine64 board is supported by upstream U-Boot.

To rebuild the firmware image, you will need to:

Get hold of a copy of Allwinner's boot0 blob:

This is part of every "official" image so far and can be extraced like this:

$ dd if=filename.img of=boot0.bin bs=8k skip=1 count=4

Replace filename.img with the name of the image file (can be an Android image as well).

Build ARM Trusted Firmware (ATF):

Check out the latest version and compile it:

$ git clone
$ cd arm-trusted-firmware
$ export CROSS_COMPILE=aarch64-linux-gnu-
$ make PLAT=sun50iw1p1 DEBUG=1 bl31

The resulting binary is build/sun50iw1p1/debug/bl31.bin.

Build U-Boot:

Check out the latest upstream HEAD and compile it:

$ git clone git://
$ cd u-boot
$ export CROSS_COMPILE=aarch64-linux-gnu-
$ make pine64_plus_defconfig
$ make

The resulting binary is u-boot.bin.

Assemble the parts into something that both the BROM and boot0 accept.

The "boot0img" tool in this repository does the tricky parts for you:

$ cd tools
$ make boot0img
$ ./boot0img -b boot0.bin -s bl31.bin -a 0x44008 -d trampoline64:0x44000 -u u-boot.bin -e -o pine64.img
Write to an SD card:

The resulting image can now be written to sector 16 of a micro SD card:

 # dd if=pine64.img of=/dev/sdx bs=8k seek=1 skip=1

WARNING: This step overwrites parts of the SD card, so backup any data before! WARNING:

Replace /dev/sdx with the name of your SD card block device. On most ARM boards and non-USB card readers this could be /dev/mmcblk0 (with a possibly different number at the end).

Partition the SD card:

The first 20 MB are currently occupied by the firmware, so either leave this space free or create a dummy partition to protect those sectors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment