Odroid N2+ Vendor BL2 RE

Posted in Reverse Engineering on March 18, 2023 by Benjamin Mordaunt ‐ 2 min read

Odroid N2+ Vendor BL2 RE

Odroid N2+ Vendor BL2 RE

Copyright (c) 2023 Benjamin Mordaunt


Phys. OffsetSymbol


The BL2 image is a heavily customised Arm TF-A BL2 stage implementation. Primary responsibilities of this image are the initialisation of PLLs (system, DDR and fixed), DDR init and SAR ADC init, as well as the standard responsibility of loading subsequent BL3x images. Much of the platform specific information, primarily consisting of memory (DDR) timings, is located in a special image, known as the “ACS” or sometimes “timing image” located between 0xFFFAF000 and 0xFFFB0000, in the secure AHB SRAM region. This image is bundled as part of the vendor FIP and sources can often be found in the same repository as the vendor’s U-Boot (BL33).


The ACS image consists of an __acs_set which bundles a header magic, version, length and address for various child descriptors, primarily DDR, PLL timing and register information. It offers a convenient vector to e.g. enable JTAG in early BL2 without modifying BL2 itself. The ACS .text is linked at 0xFFFAF000, but for all implementations examined, there is a .word 0 at the beginning, before the __acs_set, so BL2 looks at 0xFFFAF004. Perhaps this is to stop string scanning routines running into ACS? The below table gives the magic for each descriptor type, along with a link to a further breakdown of the respective structures:

acs__The ACS set itself
ddrs_DDR settings
ddrr_DDR registers. Filled with junk on examined platforms.
pll__PLL settings
storeUnused on examined platforms
bl2r_BL2 registers. Lists registers BL2 should probe or set, often to check hardware configuration, change MUX configs, enable voltage domains and clocks. Done in order.


This function attempts to reset the SYS domain when a panic state has been entered. On entry to this function, it sleeps for 10 seconds. Then, it tries first to use the special-purpose WDT_CTRL_EE_RESET_NOW bit (26) of the CNTL register. If this doesn’t work, it enables the timer based watchdog reset mechanism by toggling reset generation through bit 18. It then enters an infinite loop of trying both methods until the system is reset. This function does not return.