Jump to: navigation, search


TOC0 Header

Name Offset Size Values Description
TOC0_NAME 0x00 8B
TOC0_MAGIC 0x08 4B
Magic value
TOC0_CHECK_SUM 0x0c 4B Checksum, same algorithm as eGON.BT0 images
TOC0_NUM_ITEMS 0x18 4B Number of following items
TOC0_LENGTH 0x1c 4B Total length of the TOC0 Image
TOC0_BOOT_MEDIA 0x20 4B Boot device, written by BROM
0x24 8B reserved
TOC0_END 0x2c 4B
End marker
TOC0_ITEMn_ID 0x30 + n * 0x20 + 0x00 4B
 0x010101 = RoT certificate
 0x010202 = TOC0 boot code
Item ID
TOC0_ITEMn_OFFSET 0x30 + n * 0x20 + 0x04 4B Item data offset
TOC0_ITEMn_LENGTH 0x30 + n * 0x20 + 0x08 4B Item data length
TOC0_ITEMn_STATUS 0x30 + n * 0x20 + 0x0c 4B
TOC0_ITEMn_TYPE 0x30 + n * 0x20 + 0x10 4B
 0x1 = certificate
 0x2 = code
Item type
TOC0_ITEMn_RUN_ADDRESS 0x30 + n * 0x20 + 0x14 4B Address to execute code at
0x30 + n * 0x20 + 0x18 4B reserved
TOC0_ITEMn_END 0x30 + n * 0x20 + 0x1c 4B
End marker

TOC0 Items

RoT certificate (ID 0x010101)

Self-signed DER encoded X.509-like certificate containing a SHA256 hash of the boot code.

If a ROTPK_HASH is programmed only certificates with that key are accepted.

The certificate has a similar structure to standard X.509 certificates, but is different in details:

  • the public key is stored in a non-standard way
  • the hash is added at the place of extensions, but not as real extension
  • the signature doesn't use a standard algorithm, misses the last 4 bytes (bug!) and is stored in a non-standard way

TODO: maybe add ASN.1 of the certificate

TOC0 boot code (ID 0x010202)

Similar to boot0, only "TOC0.GLH" magic instead of "eGON.BT0". After verifying against the SHA256 hash in the certificate, this item is copied at the run address given in the item header and executed in secure mode.

TOC0 images generation

There is a preliminary script:

Some notes:

  • You may need to replace the ".sum" method with ".reduce(:+)" to run it with modern versions of Ruby
  • You may need to change the entry point address from 0x0 to 0x10000 if you want to run it on A64/H64/H5 (the default 0x0 value is used for H3)

The experimental branch contains two scripts (egon2toc.rb and toc2egon.rb, based on Jemk's library). They can be used to convert SPL binaries back and forth between these two formats. Usage example:

   git clone -b toc0
   cd sunxi-tools
   ruby egon2toc.rb bin/uart0-helloworld-sdboot.sunxi bin/uart0-helloworld-sdboot.toc0
   ruby toc2egon.rb bin/uart0-helloworld-sdboot.toc0 roundtrip-conversion-output.sunxi
   cmp -b bin/uart0-helloworld-sdboot.sunxi roundtrip-conversion-output.sunxi

The resulting file bin/uart0-helloworld-sdboot.toc0 can be written to an SD card or to SPI NOR flash and successfully booted on Allwinner H3/A64/H64 devices with secure mode bit burned in the eFUSE.

Doing conversion of the u-boot-sunxi-with-spl.bin files (not just SPL alone) back and forth between eGON and TOC0 formats requires a minor patch for U-Boot.

TOC0 vs. eGON.BT0

Feature Allwinner A64/H64/H5
Boot time TBD TBD (but worse than eGON)
SPL size limit 32 KiB (SRAM A1) more than 100 KiB (SRAM A1 + SRAM C)
SPL load address Loaded into SRAM A1 and executed there. This address is may be different on different SoC types, but the same position independent code can run on multiple SoC types (see uart0-helloworld-sdboot example) The load & execute address is specified in the TOC0 item header and it should be set as SRAM A1 address of the SoC (or at least land into a valid SRAM address range). This is a little bit problematic, because it becomes difficult to boot the same image, for example, on H3 and A64 (but maybe we can load the SPL into SRAM A2 to overcome this?).
Can boot from Works with SD card, eMMC, SPI. NAND is untested. Booting from eMMC boot partitions is untested too Works with SD card, eMMC. SPI, NAND and eMMC boot partitions are still untested.
Boot source detection A 8-bit boot media type identifier is written by the BROM at the offset 0x28 in SRAM A1 A 8-bit boot media type identifier is written by the BROM at the offset 0x20 in SRAM A1
Secure peripherals Access to SID and the other secure-only resources is allowed from both secure and non-secure mode, SPC settings are ignored. Investigation for a possible fix or workaround is underway. Work correctly, SPC settings are respected.

Note: some peripherals are switchable but the others are secure-only (such as SID). It means that secure boot is not a superset and the eGON-style non-secure boot configuration can't be replicated at the moment. This may cause inconveniences for the Linux kernel (reading SID is a perfect example) and some assistance from the firmware will be required.

The currently used eGON.BT0 images can be wrapped into TOC0 containers with just a little bit of adaptation. As discussed in the irc log, a small extra stub code added to the TOC0 container can ensure that the eGON.BT0 image lands at the start of SRAM A1 and also the boot media identifier can be patched there at the expected offset 0x28. This way the differences between eGON.BT0 and TOC0 can be fully hidden and we can continue using eGON.BT0 as a single unified format for the SPL on Allwinner devices (the 32K size restriction can be lifted though).

The task of converting from eGON.BT0 to TOC0 can be delegated to a smart flasher tool. For example, sunxi-fel can check whether the secure boot bit is set in LCJS and automatically do conversion into the TOC0 format when flashing SPI NOR. As an additional safety measure, it's also best if the tool can verify that the device is not locked down to only accept some particular key.

U-Boot build may produce images in both formats, but a smart flasher tool can interchangeably use either of them if the conversion is straightforward (this way a possible user error is eliminated).

This all is very similar in principle to what we have already done with FEL USB boot support (eliminate a special extra U-Boot build configuration and just use a single unified image for both SD card boot and FEL USB boot):

U-Boot build generates a single unified "payload". And sunxi-tools provides a suitable "delivery" method :-)


Check if it is actually possible to configure secure peripherals after booting via eGON.BT0. Are there any other differences?

Tried to dump and compare HW registers with/without TOC0:

There was a hope to maybe find some magic bit, which will allow restricting access to peripherals in non-secure mode.

This is a trivial quick and dirty test program, which can verify if such restrictions actually work as expected:

Running it on Jide Remix Mini (secure bit is set in eFUSE) via "sunxi-fel spl" after "sunxi-fel smc":

Checking the current mode ... secure.
Switching to non-secure ... done.
Checking peripherals security ... SRAM A2 is not accessible (this is GOOD).

Hello from Allwinner A64!
Returning back to FEL.

Running on Pine64 (secure bit is not set in eFUSE) via "sunxi-fel spl":

Checking the current mode ... secure.
Switching to non-secure ... done.
Checking peripherals security ... SRAM A2 is accessible (this is BAD).

Hello from Allwinner A64!
Returning back to FEL.

None of the attempts to toggle various bits in various HW registers helped so far on Pine64, restricting access to SRAM A2 does not work.

Note: the test program does not work correctly on Jide Remix Mini when booting from SD card (deadlocks when trying to switch to non-secure, most likely the default settings are not the same as in FEL mode):

Checking the current mode ... secure.
Switching to non-secure ... 

Implement and test FEL boot for TOC0 bootloaders.

We can in principle boot TOC0 images via sunxi-fel even on boards without the secure bit set in eFUSE (and can boot oversized TOC0 images too). This just needs to be implemented.

Personal tools