Wave

Reconstructing the 3DS Bootstrapping Process at the Factory

Forbidden Tempura

Table of Content


Motivation

The Nintendo 3DS was a fairly popular console. In spite of that, surprisingly little is known about how it is put together at the factory. Working with information that was uncovered during the so-called Gigaleak, I will try to recover as much information as I can about the manufacturing process up and until the point the 3DS is able to complete a normal boot sequence.

One-Time Programmable (OTP) region

Every 3DS ships with 0x100 of one-time programmable persistent memory at 0x10012000-0x10012100, containing console-unique keys and information.

This obviously has to occur before any normal firmware runs on the system because significant amounts of all data written would fail to account for console-unique information and thus the encrypted values would be all encrypted for the wrong keys.

An interesting observations: ctr.7z (SHA-256: 8b05072361254437277576d53c08b95e5f076c6b33a2871fad74eaa5561d1d38) ctr/sources/bootrom/CTR/private/build/bootrom/ctr_bootrom/ARM9/main.c has a procedure to decrypt the OTP region (which is consistently called the “fuse” or “eFuse”). If the decryption failed, there is a commented line that would call the function to detach the OTP region (i.e. making it unavailable), but the comment further explains that they need to write the “TWL eFuse” before detaching. However, this may also refer to the DSi (TWL) console ID at 0x10012100-0x10012108 and may not necessarily refer to a first-time programming.

I could not figure out where the eFuse information is written, in particular whether that is done by software running on the 3DS itself or whether that is done as part of the wafer manufacturing process. One bizarre observation here is that part of the eFuse region is used to transmit volatile data, which suggests that not everything is actually one-time programmable in that region.

What I could find is how the OTP data itself is generated. The data that is written is either pre-generated ahead of time or generated just-in-time at the factories. In paladin.7z (SHA-256: 61151df2c0489bdda6dd70297c3fed0aa7de222fa3cf6c3faeaf90e01081ca78), there is a Subversion (SVN) repository in a sub-file ctr_eFuse.zip. The build artifact is a libgenid.a library with a Makefile for “sharp”, suggesting that Nintendo provided code to generate the way they want to (and using an HSM for cryptography), while Sharp Corporation (the electronics company in Japan) ultimately integrated it with their manufacturing process. This would imply that the writing of the OTP happens at the time the system-on-chip (SoC) is manufactured.

Updater1st

ctr.7z (SHA-256: 8b05072361254437277576d53c08b95e5f076c6b33a2871fad74eaa5561d1d38) provides source code for what seems to be the initial installation program. The ctr/sources/firmware/CTR-Kernel/updater1st/ directory in particular contains UpdaterNgc, UpdaterKernel and UpdaterNgcFirm subfolders with OMakefiles. Of particular interest is the naming: “NGC” (NTR game card) is used as an abbreviation to refer to old, Nintendo DS-style cartridges. This means that Updater1st is a DS-mode image and booted from a special DS-mode cartridge. The ARM9-side boot ROM allows starting a firmware image from DS cartridges if the shell is closed and a special key combination (Start + Select + X) is held. This strongly suggests that the reason the boot ROM has this feature is to allow for initial setup of the console.

In the UpdaterKernel directory, we can see that a TCB_PROCESSES_SYS1_11 variable is appended to. This appears to be used to add to the initial processes that are baked into and launched with the ARM11 firmware kernel image:

  • UpdaterProcess
  • am (application manager)
  • i2c (I²C driver, required by the mcu process)
  • mcu (driver for the microcontroller unit, MCU, which in particular also controls at least parts of wireless LAN functionality and controls the LEDs)
  • gpio (driver for accessing general-purpose input/output ports, GPIO, which in particular also controls at least parts of wireless LAN functionality)
  • cfg (configuration management services for all ARM11 userland configuration and high-level interface for writing to the NOR/DS mode NVRAM flash)
  • spi (SPI driver, which in particular provides the low-level interface for writing to the NOR/DS mode NVRAM flash)

For comparison: In retail firmware, these are always sm (service manager), fs (filesystem module), pxi (module for PXI, which is how the 3DS's two main ARM9 and ARM11 processes communicate), loader (loads programs) and pm (process manager). These have a cip extension, presumably meaning “CTR initial process” considering the Switch, which took heavy inspiration if not directly continued the 3DS codebase, refers to “KIP” (“kernel initial process”) files occasionally.

This selection of initial processes is obviously chosen such as to provide the minimum set that the UpdaterProcess can work. Speaking of which, the program seems to be fairly straightforward:

  1. It initializes the necessary services.
  2. It signals via LEDs that it is running.
  3. It opens a file handle to nand:/rw/sys/updater.log with a 16 KiB log buffer size.
  4. It initializes am.
  5. It reads calibration data.
  6. For each 3DS title (either on the SD card or on the intialization cart), it force-deletes the associated ticket with am, writes the log, and then installs the title with am and writes the log.
  7. It commits all changes to the am database and writes the log.
  8. It installs the Kernel9 and Kernel11 images with initial processes via am to the firm0 partition and writes the log.
  9. It writes the log that it is about to install DSi titles, then for each DSi title, it installs the title with am. Once all are imported, it writes the log.
  10. It resets the calibration data to the one previously read.
  11. It causes the cfg module to initialize the system configuration, in particular another copy of the calibration data, setting the real-time clock offsets, the LCD defaults, zeroing the known Wi-Fi access points, setting the user's name to the empty string, setting the birthday to January 1, applying various locale settings, clearing parental controls, resetting friend code information, initializing the accepted EULA version to zero, setting the “first launch” flag and clearing miscellaneous other information.
  12. It initializes the local friend code seed if on development hardware.
  13. It initializes the nand:/rw/sys/SecureInfo_A data if on development hardware.
  14. It initializes the NOR (DS mode settings) flash.

It signals state transitions by (de-)activating specific LEDs.

Power LED Wireless LED Camera LED Meaning
Off On Off Running
On Off Off Finished
On On On Error

If this initial updater runs before the shell is actually put on the system, these LEDs are likely directly connected to a system supervising the process automatically. It also writes certain values to a debug LED, further suggesting this kind of setup.

Secure sector 0x12c00

On the New 3DS exclusively, at offset 0x12c00 of the main NAND flash, there is key material. This key material is itself encrypted with console-unique key material, which were supposed to protected part of the firmware. Because the firmware is the same for all devices, the encryption keys at sector 0x12c00 are the same for all devices (with dev and prod having separate key sets).

Documents.7z (SHA-256: be3a0196a36c1449e7918483047efbde04fe02711b3df4130b090449b399e1d6) contains a file セキュリティチーム運営/プロジェクト/SNAKE/SNAKEセキュリティ改善_20140423.pdf. It notes that a New3DS-specific version of Updater1st handles encrypting the secure sector with console-unique data.

Factory firmware

Once Updater1st has finished, the system is ready to operate normally and has finished bootstrapping.

It appears that there is a multi-stage setup after installation of the initial titles since it is unclear at what point the SAFE_MODE firmware is installed. Most likely, a later stage finishes the installation thereof. The 3DS_manu.7z (SHA-256: ab674468d38340717c13a06c66f01144528874ce36e8b1dbb20b465ff6c3c777) file contains assorted files for manufacturing a New2DS, namely a set of programs for installing more programs testing the system. Interestingly, it also contains a “CPU Board Sequencer”, which is a regular DS program. A regular DS program cannot launch directly from the 3DS boot ROM and it also does not seem to actually write the OTP information.

Furthermore, many units contain traces of an old firmware, in case of very old units, parts of a pre-release firmware. In particular, they include a title called CTRAging (title ID 000400000f980000) on the NAND in no longer used sectors. Source code can be found in Documents.7z at セキュリティチーム運営/プロジェクト/コードレビュー/データ書込みソフト_セキュリティホール確認用_20140509/CTR_TRIAL.zip. It tests various system functionality.

After finishing this test, the regular firmware appears to be installed someway, presumably using a different variant of Updater1st. I cannot determine any more detail about the bootstrapping procedure in the factory from what is available to me, so I will be concluding here.

About the Author

Forbidden Tempura

I am good at being angry about video games.

Mia Rose WinterReviewer

This might also interest you

A Mystery Involving Hardware Security Modules and Value Tokens

Forbidden Tempura 10/7/2025

Context Historical context In July, 2021, the phenomenon known as the “Gigaleak” continued. The Gigaleak was a drip-feed of part of the ill-gotten data from the 2018 Nintendo data breach. On July 20, 2021, the iqcvs.tar.xz file was uploaded to the now-defunct file sharing website anonfiles.com and thereby made available to the public by The Hacker Known as 4chan. This file contains a dump of CVS repositories. The repository sw contains the BroadOn network infrastructure around the middle of the year 2006. This is shortly before the Nintendo Wii launched. The network infrastructure was initially launched alongside the iQue Player, a variant of the Nintendo 64 featuring downloadable games and some anti-piracy measures of questionable quality (non-HTTPS link) intended for the Chinese market, which was and still is notorious for being particularly prone to piracy. It was developed by a company then called BroadOn Communications Corp., a California corporation. The iQue Player u

ITInfodump

A Brief Look at the 3DS Cartridge Protocol

Forbidden Tempura 6/2/2024

About a week ago, there has been a little addition to the 3dbrew wiki page about 3DS cartridges (carts) that outlines the technical details of how the 3DS cartridge controller and a 3DS cartridge talk to each other. I would like to take this opportunity to also include the 3DS itself in the conversation to illuminate which part of which device performs which step. I will then proceed to outline where I think the corresponding design decisions originate. Finally, I will conclude with some concrete ideas for improvement. But first, we need to talk about parallel universes This protocol makes no sense unless you have a basic overview of the 3DS AES engine. The 3DS AES engine can load 128-bit AES keys in two ways: Using key-derivation from a keyX and keyY (officially called KeyId and KeySeed, respectively). Directly specifying a full AES key. The key derivation from a keyX and keyY works as follows: AES key = (((keyX ROL 2) XOR keyY) + C1) ROR 41, where ROL is left rotation on a 128-bit

ITGamesInfodump

If it has Text, it is Pain

Mia Rose Winter 5/1/2024

I've been meaning to write tests for Wave for a while. Honestly, in my 12 years of dev I never actually wrote one outside of the odd academic homework assignment, so I had no idea how to approach it. After a couple of videos and video presentations about general unit tests, TDD and stuff, I actually got intrigued, and with a bug discovered just today by a coworker in Wave I was baffled by I thought, okay, let's dissect this little Käfer. Prerequisites: What does Wave do here actually If you have not authored an article on Wave before, let me give you some background. When you want to load a specific article in the article view, there are three methods, two actively used and one historical, to find it. The first and most direct, the “permalink” if you will, is going to /article/{id}, with the UUIDv4 ID of the article. This is used for stuff like the article editor and during the draft and review process when the other method doesn't work, and maybe one day there will be a &l

ITTutorialInfodumpC#
Powered by Wave