Notes on boot process, FEL/FES mode and how to dump the NAND storage and kernel. Part of the notes for Shall We Play A Game Talk
Boot Process
Most of these notes are taken almost directly from http://linux-sunxi.org/BROM with a few additional pieces of information from elsewhere on the internet or my own research
After power-up the SoC boots from an integrated 32kb ROM (aka Boot ROM or BROM).
The BROM is split into two parts:
- FEL mode (at
0xffff0000
) - eGON.BRM (at
0xffff4000
)
eGON Boot
The eGON Boot ROM performs a few tasks:
- does some co-processor setup (c15, (virtual) System Control Coprocessor).
- disables the WatchDog Timer
- setups CPU, AXI, AHB and APB0 clocks
- enables AHB Gating
- enables APB0 Gating
- sets the Stack Pointer to 32K
- then it jumps to ‘boot’ which immediately jumps to
check_uboot
check_uboot
setups up some registers, then checks the status pin (often called FEL pin, BSP pin or uboot)- if the pin is low (connected to GND) executes FEL mode at
0xffff0020
. - If the pin is high it continues trying to boot from the following media and on failure continues to the next in order.
- SD Card0 also known as MMC0
- Internal NAND flash also known as NAND
- SD Card2 also known as MMC2
- SPI connected NOR flash also known as SPI
- If all fails, FEL/USB Boot mode is executed from
0xffff0020
- if the pin is low (connected to GND) executes FEL mode at
As you can see from the above there are multiple ways to get to FEL mode and perform a recovery which means its incredibly hard to brick the NES Classic console.
FEL Mode
FEL is a low-level USB programming and recovery mode built into the Boot ROM on Allwinner SoC’s.
With the device in FEL Mode and the sunxi-fel tool you can read & write to memory as well as execute code in memory.
Because the FEL Mode code is stored in the Boot ROM it makes it very hard to brick the NES Classic console, no matter how badly you mess up the firmware image you can always go back into FEL mode and re-upload a known working image.
U-Boot
U-Boot is a first and second stage boot loader. In the NES its launched by the Boot ROM and is responsible for finding and loading the Linux Kernel and initial root filesystem.
The NES Classic uses the standard opensource U-Boot with a few tweaks by Nintendo. The source is contained in the GPL code release from Nintendo. Additional patches have been made available by madmonkey
in the hakchi
software release that fix a few issues with the original Nintendo releasd version of the software.
Dump Kernel & NAND using FEL Mode
Power on the console while holding the reset button to boot the device into FEL mode.
NB Booting the device like this into FEL mode causes it to not initialise the RAM.
Step 1 - Initialise DRAM and switch to FES Mode
Upload fes1.bin
( https://github.com/ClusterM/hakchi2/blob/stable/data/fes1.bin) - Could be built using using the Nintendo uboot source.
Upload fes1.bin
sunxi-fel write 0x2000 fes1.bin
Execute code
sunxi-fel exec 0x2000
Step 2 - Upload uboot
Upload uboot.bin
( https://github.com/ClusterM/hakchi2/blob/stable/data/uboot.bin) - Could be built using using the Nintendo uboot source.
DRAM starts at 0x40000000
uboot starts at dram + 0x7000000 = 0x47000000
Upload uboot.bin
sunxi-fel write 0x47000000 uboot.bin
Step 3 - Patch uboot bootcmd
We need to write the following command to a specific portion of the uboot binary we loaded in memory so that it’ll run this command on boot and not attempt to boot the kernel
sunxi_flash phy_read 47400000 30 20;efex_test
(needs to be \0 terminated)
To be able to do this easily from the command line, we can write the above command to the kernel_dump_bootcmd
file and then write the contents of the file (kernel_dump_bootcmd) to the offset where uboot’s bootcmd=
is in memory.
sunxi-fel write 0x470604ff kernel_dump_bootcmd
Step 4 - Execute uboot
Execute uboot
sunxi-fel exec 0x47000000
Step 5 - Dump Kernel
You need to wait a few seconds here, unsure exactly why this is required. If you attempt to dump the kernel too soon you’ll get a usb_bulk_send() ERROR -7: Operation timed out
error.
Finally dump Kernel to file
sunxi-fel read 0x47400030 0x600000 kernel.dump