BROM

A10/A20
The A10/A20 has several ways to boot. It has an integrated non-replaceable 32 KiB ROM chip (Boot ROM or BROM) which could be considered the primary program-loader. On startup, the SoC starts to fetch the first instruction from address 0xffff0000, which is where the BROM is located at.

The BROM is actually split up into two parts. FEL mode and eGON.BRM. FEL mode is at the start, at 0xffff0000 followed by eGON.BRM at 0xffff4000.

At 0xffff0000 is the reset vector which jumps to 0xffff0028. There it loads 0xffff4000 into the program counter to be executed next.

eGON Boot
The eGON Boot Rom has a few tasks.
 * 1) does some co-processor setup (c15, (virtual) System Control Coprocessor).
 * 2) next the  WatchDog Timer is being disabled
 * 3) CPU, AXI, AHB and APB0 clocks get setup
 * 4) setup the AHB Gating
 * 5) APB0 Gating is then done
 * 6) before calling 'boot' it puts on the Stack Pointer.
 * 7) 'boot' immediately jumps to check_uboot
 * 8) check_uboot setups up some registers, then checks the status pin (often called FEL pin, BSP pin or uboot) and if the pin is low (connected to GND) executes FEL mode at 0xffff0020.
 * 9)  If the pin is high it continues trying to boot from the following media and on failure continues to the next in order.
 * 10) SD Card0 also known as MMC0
 * 11) Internal NAND flash also known as NAND
 * 12) SD Card2 also known as MMC2
 * 13) SPI connected NOR flash also known as SPI
 * 14) If all fails, FEL/USB Boot mode is executed from 0xffff0020

So as can be seen, a lot would need to go wrong or 'fail' before entering FEL mode. Especially if there is a valid header in the NAND flash. Obviously this can be abused, by corrupting the header and thus forcing failure. If no other boot options are available, then FEL mode should be the final result. As a bypass mechanism, the A10 has the so called Boot Select Pin (BSP). This pin is normally internally pulled up by a 50KΩ resistor. If the pin is pulled low to GND, the A10 will try to boot into FEL mode. Otherwise the above boot-order will be tried.

Source code for boot0 and boot1
The source code for boot0 and boot1 for the A20 chip is included in an SDK from Olimex: A20-SDK.torrent

As of March 2015 Allwinner has also published bootloader code on GitHub.

A31
Instead of falling through boot options, the A31 boots slightly differently. One fel pin, which is the same as A10/A20. Two boot select pins, boot sel0 and boot sel1, which decide where to boot. The fel key priority is higher than the boot select key. The boot-flow process is explained briefly below.

boot-> check fel key pressed (yes)-> check if sd0 bootable(no) -->go to fel mode \                                  \                          \                              (yes)\__ boot from sd0 \                            \                                       _____[00] boot from nand flash (go to fel mode if failed) (no) \                                     /_____[01] boot from sd2 (go to fel mode if failed) \                                  /                               \___check boot sel[0:1]---[10] boot from emmc2 (go to fel mode if failed) \                                                                  \______[11] boot from spi (go to fel mode if failed) by hipboi

U-Boot SPL limitations
In order to be recognized by the BROM, the SPL needs to written to a certain location on the SD card (see SD Card Layout) and have a special header with a correct checksum. Such special header can be added to a binary file using the Mksunxiboot tool. The size of the SPL must be a multiple of 8 KiB in NAND and a multiple of 512 bytes on the SD card (see the "sunxi/nand: change BLOCK_SIZE in mksunxiboot to match NAND block size" commit in U-Boot).

Early SoC variants (A10 and A20) used to have a somewhat artificial 24 KiB restriction of the SPL size. Then A13 tried to increase this limit to almost 32 KiB. And finally all recent SoC variants (A31 / H3 / A64) have 32 KiB size limit for the SPL. The 32 KiB limit is still artificial. For example, A64 has 192 KiB of contiguous SRAM space, starting at 0x10000.

It is possible to increase the practical size limit to some extent by making use of runtime decompression (via LZO or UCL). As an additional bonus, compression should eliminate repeatable patterns, which are supposedly bad for MLC NAND and maybe (?) help the NAND hardware randomizer to some extent. And while we are at it, the runtime decompressor code could also take care of applying relocations, allowing to use the same unified SPL binary even on devices with different SPL load addresses.

Other booting methods

 * How to boot the A10 over the network