FIRM
Overview
This is the file format for the 3DS' Firmware, it contains four 'sections' of ARM code (ARM9 and ARM11). The firmware sections are not encrypted in the FIRM format.
A structural example of a FIRM file (created using the specs in ctrtool) can be found here (Note it does not contain any ARM code, it's just a structural example)
The ARM9 section contains the ARM9 kernel and the ARM9 process. The ARM11 section(s) contains the ARM11 kernel, and the ARM11 process(es). For NATIVE_FIRM/SAFE_MODE_FIRM these ARM11 processes are sm, fs, pm, loader, and pxi. Normally the 4th section is not used. The code loaded from FIRM is constantly running on the system until another FIRM is launched.
FIRM Header
OFFSET | SIZE | DESCRIPTION |
---|---|---|
0x000 | 4 | Magic 'FIRM' |
0x004 | 4 | Reserved1 |
0x008 | 4 | ARM11 Entrypoint |
0x00C | 4 | ARM9 Entrypoint |
0x010 | 0x030 | Reserved2 |
0x040 | 0x0C0 (0x030*4) | Firmware Section Headers |
0x100 | 0x100 | RSA-2048 signature of the FIRM header, using SHA-256. |
Firmware Section Headers
OFFSET | SIZE | DESCRIPTION |
---|---|---|
0x000 | 4 | Offset |
0x004 | 4 | Address |
0x008 | 4 | Size |
0x00C | 4 | Firmware Type ('0'=ARM9/'1'=ARM11) |
0x010 | 0x020 | SHA-256 Hash of Firmware Section |
NATIVE_FIRM and SAFE_MODE_FIRM
NATIVE_FIRM is the FIRM which is installed to the NAND firm partitions, which is loaded by bootrom. SAFE_MODE_FIRM and NATIVE_FIRM for the initial versions are exactly the same, except for the system core version fields. SAFE_MODE is used for running the System Updater.
TWL_FIRM and AGB_FIRM
TWL_FIRM handles DS(i) backwards compatibility, while AGB_FIRM handles running GBA VC titles. The ARM9 FIRM section for TWL_FIRM and AGB_FIRM are exactly the same(for TWL_FIRM and AGB_FIRM versions which were updated with the same system-update).
TWL_FIRM
The 3DS-mode ARM9 core seems to switch into DSi-mode(for running DSi-mode ARM9 code) by writing to a PDN register(this changes the memory layout to DSi-mode / etc, therefore this register poke *must* be executed from ITCM). This is the final 3DS-mode register poke before the ARM9 switches into DSi-mode. It's unknown how exactly DS(i)-mode ARM7 code is run. Trying to read from the exception-vector region(address 0x0) under this DSi-mode ARM7 seems to only return 0x0 data. Also note that this DSi-mode ARM7 runs code(stored in TWL_FIRM) which pokes some DSi-mode registers that on the DSi were used for disabling access to the DSi bootROMs, however these registers do not affect the 3DS DSi-mode ARM9/ARM7 "bootrom" region(exceptionvector region + 0x8000) at all.