Dump Amlogic S905D3 BootROM from Khadas VIM3L board

Posted on Tue 09 February 2021 in Article

This post describes how to dump bootROM from Amlogic S905D3 SoC using Khadas VIM3L board. Since this board doesn't use Secure Boot, we can execute custom code in Secure World (a.k.a TrustZone) without exploiting any vulnerability. In addition, the board exposes an UART connector, which is convenient for communicating with baremetal code running on target.

Collect bootroms


Khadas VIM3L

The following resources were abused to complete this project :

  • VIM3L board : SBC based on Amlogic S905D3 System-On-Chip.
  • USB to TTL Converter : to enable communication between host and target using UART port.
  • S905D3 SoC datasheet : Khadas published a datasheet for S905D3. It contains a memory map, including the bootROM address.
  • khadas-uboot : U-Boot code released by Khadas contains a signing tool to package a bootloader image.
  • khadas-utils : Khadas released a tool to communicate with the bootROM via USB.


In order to dump the bootROM, we need to execute custom code in Secure World.

On most firmwares provided by Khadas, U-Boot shell is accessible via UART port. However, U-Boot runs in Non-Secure World (a.k.a. Normal World) and therefore isn't helpful.

Instead, we need to execute our code earlier in the boot chain. Since Secure Boot is disabled on this board, we could modify the BL2 bootloader stored in flash memory. However, there's a more convienent solution : the bootROM implements a feature to load BL2 bootloader via the USB Type-C port. This in-RAM solution has the advantage of not altering the flash memory.

Finally, we also take advantage of the UART port to transfer data to our host.


The code to dump the bootROM is straightforward : each byte is read then sent to UART port.

The datasheet published by Khadas indicates that bootROM memory is at address [0xFFFF0000-0xFFFFFFFF] (region named a53_rom). To send data to UART port, we reuse open-source code from U-Boot.

Early tests revealed an issue : UART data transfers would stop inconsistently before completion, and the board would then reset. This issue was caused by a watchdog timeout. U-Boot source repository contains the code to reset the watchdog, which solves that issue.


The code is built using GNU C cross-compiler for the arm64 architecture (packages gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu on Debian) :

$ aarch64-linux-gnu-gcc -O3 -nostdlib -Wl,--build-id=none -o S905D3_dump_bootrom.elf S905D3_dump_bootrom.c
$ aarch64-linux-gnu-objcopy -O binary -j .text S905D3_dump_bootrom.elf S905D3_dump_bootrom.bin

Then, the binary is packaged as regular BL2 image for this target using the aml_encrypt_g12a tool from khadas-uboot repository:

$ ./khadas-uboot/fip/g12a/aml_encrypt_g12a --bl2sig --input ./S905D3_dump_bootrom.bin --output ./S905D3_dump_bootrom.img


Khadas documentation explains how to connect UART port on VIM3L board. On host side, we use minicom software to communicate with this port :

$ sudo minicom -D /dev/ttyUSB0

Then, we boot the board in USB Upgrade mode (a.k.a. TST mode or USB Download mode) as explained in Khadas documentation. In minicom console, we can see :


This string ending with USB:0; means the board has started in USB Upgrade mode.

On the host side, we see a new USB device :

[10504.840173] usb 1-4.3.1: new high-speed USB device number 16 using xhci_hcd
[10504.979469] usb 1-4.3.1: New USB device found, idVendor=1b8e, idProduct=c003, bcdDevice= 0.20
[10504.979495] usb 1-4.3.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[10504.979514] usb 1-4.3.1: Product: GX-CHIP
[10504.979525] usb 1-4.3.1: Manufacturer: Amlogic

In minicom, we use the capture feature (CTRL-A L) to save data sent by our program into a file minicom.cap.


Our code is uploaded and run on the board using the update tool from khadas-utils repository.

$ ./khadas-utils/aml-flash-tool/tools/linux-x86/update write ./S905D3_dump_bootrom.img 0xfffa0000
Transfer Complete! total size is 65536 Bytes

$ ./khadas-utils/aml-flash-tool/tools/linux-x86/update run 0xfffa0000
[update]Run at Addr fffa0000

In minicom console, we received the bootROM dump sent by our code :


Since the dump is encoded in hexadecimal representation, the last step is to convert it back to binary :

$ cat minicom.cap | xxd -r -p > VIM3L.bootrom.bin

$ sha1sum VIM3L.bootrom.bin
5de02d2958d4d7214b28521239ec9b63fe9a2dbe  VIM3L.bootrom.bin

$ wc -c VIM3L.bootrom.bin
65536   VIM3L.bootrom.bin

$ strings -13 VIM3L.bootrom.bin
auth failed, reboot...
gcc version 4.8
FAILkey error
FAILkey len error
FAILmissing var
FAILmissing var!
FAILUnkonw chipinfo id
FAILVariable not implemented
FAILdata invalid size
FAILdata too large
FAILkey_len error
FAILunknow command
New World Cup

The strings in the bootROM dump reveal that Fastboot protocol is implemented (different protocol than the one we just used to upload our code).