Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Division by zero in /usr/share/web/joat/webshare/ds/index.php on line 1101

Warning: Cannot modify header information - headers already sent by (output started at /usr/share/web/joat/webshare/ds/index.php:1101) in /usr/share/web/joat/webshare/ds/index.php on line 885
NDSTech Wiki : Firmware browse
Main /
Firmware

Menu

Getting Started

System Information

Misc

Firmware

The firmware is contained in a SPI data flash chip (usually 256 KB). It contains the menu and pictochat. The encrypted firmware code is decrypted by the BIOS as it gets copied to RAM. The first 64 KB of firmware on all 256 KB model DSes is write protected by SL1, although Nintendo was dumb enough to not fit a working system in 64 KB, allowing things like the DS bricker to occur. However, a FlashMe'd DS contains a recovery routine that prevents total bricking.

There are at least five revisions of the firmware, three older versions that work with passme/wifime and changed small details, and two newer versions that do not work immediately. PassMe2 is currently the only way to run code on a DS with the newer firmware. There is now a new version of FlashMe for the new-type firmware, but it still requires a PassMe2 to install.

Known versions (based on checksum at offset 0x6 in the firmware):

  • v1 (checksum 0x2C7A, Freezes on removal)
  • v2 (checksum 0xE0CE, Grayish Blue)
  • v3 (checksum 0xBFBA, Dark Green (00,15,00))
  • v4 (checksum 0xDFC7, %bgcolor=#FFFF00 color=black% (31,31,0))
  • v5 (checksum unknown, Magenta)
  • DS Lite / v6 (checksum 0xE843, %color=black bgcolor=#DE00EE% (27,0,29))
  • iQue (checksum 0xF96D, Dark Green (00,15,00))
  • Flashme (Dark Green, based on v3 firmware)

v1-v3 are the original firmware supported by old PassMe/WifiMe
v4 is the firmware of recent DSes that blocks old PassMe and current WifiMe
v5 has been spotted but not dumped yet, also blocks
v6 / ds-lite works with passme 2

To test your firmware version without using a flash cartridge or passme, you can use the color trick discovered by MaHe. This can be invoked by ejecting a game from pictochat, or by waving a magnet near the start+select buttons on a DS (to simulate hinge close). If you get yellow or magenta, you probably need a PassMe2. If you get any other colors besides those listed above, please let us know.

The firmware on the iQue DS is 512 KB and includes additional range-checking code to prevent passme. The other range-checked firmwares (v4) are still 256 KB and was first found in the Japanese red DS, although it is present in all newly released DSes (as of writing), including the pink/powder blue nintendogs bundles, the teal DS in all regions, and newer blue DSes. For more information on the spread of the new firmware (and to add your serial number), see the DS firmware tracker. It appears that newly purchased Silver DSes, DSes returned for repair, and refurbished DSes also contain the new firmware.

The user settings are also stored in the firmware.

FlashMe versioning

FlashMe v1 to v4 do not work with WFC games, as the WFC settings data overwrites part of FlashMe's extension code. The recovery routine is still intact, so an affected DS can be reflashed with a GBA cartridge.

  • 0x17C:16 = 1 for FlashMe v1..v4
  • 0x17C:16 = 2 for FlashMe v5+
    • 0x3F7FC:16 + 3 = 5 for FlashMe v5, 6 for FlashMe v6

Firmware header

FW offsetSizeDescription
0x000002Part 3 source / 8
0x000022Part 4 source / 8
0x000042CRC-16 of parts 3 and 4
0x000062CRC-16 of parts 1 and 2
0x000084"MACP" or "MACh"
0x0000C2Part 1 source info
0x0000E2Part 1 destination info
0x000102Part 2 source info
0x000122Part 2 destination info
0x000142Part 1+2 shift data
0x000162Part 5 source / 8
0x000188?? ?? ?? ??
0x0001C4?? ?? FF FF
0x000202User settings offset / 8
0x000222?? ??
0x000242?? ??
0x000262CRC16 of part 5
0x000282?? ??
0x0002A2CRC16 of remaining header
0x0002C2Size of remaining header
0x0002E2?? ??
0x000306? 00 00 00 00 00 00 ?
0x000366MAC address
0x0003C4Enabled channels (FE 3F FF FF)
0x000401RF init flag (picks modes, 00, 02 spotted)
0x000411Bits per RF init transfer
0x000421Number of RF init entries
0x000431? 01 ?
0x000442Wifi init 0x146
0x000462Wifi init 0x148
0x000482Wifi init 0x14A
0x0004A2Wifi init 0x14C
0x0004C2Wifi init 0x120
0x0004E2Wifi init 0x122
0x000502Wifi init 0x154
0x000522Wifi init 0x144
0x000542Wifi init 0x130
0x000562Wifi init 0x132
0x000582Wifi init 0x140
0x0005A2Wifi init 0x142
0x0005C2Wifi init 0x038
0x0005E2Wifi init 0x124
0x000602Wifi init 0x128
0x000622Wifi init 0x150
0x00064105Baseband init data
0x000CE36(Num Bits+7)/8*(Num Entries) of RF init data
0x000F26Channel 1 RF data
0x000F86Channel 2 RF data
0x000FE6Channel 3 RF data
0x001046Channel 4 RF data
0x0010A6Channel 5 RF data
0x001106Channel 6 RF data
0x001166Channel 7 RF data
0x0011C6Channel 8 RF data
0x001226Channel 9 RF data
0x001286Channel 10 RF data
0x0012E6Channel 11 RF data
0x001346Channel 12 RF data
0x0013A6Channel 13 RF data
0x001406Channel 14 RF data
0x0014614Channel 1..14 BB data
0x0015414? (each 0x10)
0x001621? (0x1C)
0x001631570xFF padding

Notes:

  • Part 1 (ARM 9 boot firmware)
    • Source = sourceInfo * (4 << ((shiftData>>0) & 7))
    • Destination = 0x02800000-destInfo * (4 << ((shiftData>>3) & 7))
  • Part 2 (ARM 7 boot firmware)
    • Source = sourceInfo * (4 << ((shiftData>>6) & 7))
    • Destination = (shiftData & 0x1000 ? 0x02800000 : 0x03810000) - destInfo*(4 << ((shiftData>>9) & 7))
  • Part 3 is the ARM 9 secondary firmware portion.
  • Part 4 is the ARM 7 secondary firmware portion.
  • Part 5 is language data, etc..., loaded by the ARM9.
  • In the US, you should only use channels 1 .. 13
  • CRC16 of remaining header has an initial value of 0, starting at 0x2C and continuing on to the end of the remaining header
  • size of remaining header is size including the 0x2A/0x2C fields, i.e. (0x138 means 0x2A+0x138=0x162 is the final byte, and 0x163 to 0x1FF is FF filled)

See for information on the custom firmware project.

For most purposes, you do not need to read the firmware, as the BIOS leaves the important settings in memory for you (as discussed above). However, initializing the Wireless system requires reading a number of configuration variables from the firmware. So, here is code to read it (will only operate on the ARM7):

 

#define FW_READ_ID     0x9F
#define FW_READ        0x03
#define FW_READ_STATUS 0x05

void readFirmware(uint32 address, uint32 size, uint8 * buffer) {
  uint32 index;

  // Read command
  while (SERIAL_CR & SPI_BUSY);
  SERIAL_CR = SPI_ENABLE | SPI_NOT_LAST | SPI_DEVICE_FIRMWARE;
  SERIAL_DATA = FW_READ;
  while (SERIAL_CR & SPI_BUSY);

  // Set the address
  SERIAL_DATA =  (address>>16) & 0xFF;
  while (SERIAL_CR & SPI_BUSY);
  SERIAL_DATA =  (address>>8) & 0xFF;
  while (SERIAL_CR & SPI_BUSY);
  SERIAL_DATA =  (address) & 0xFF;
  while (SERIAL_CR & SPI_BUSY);

  for (index = 0; index < size; index++) {
    SERIAL_DATA = 0;
    while (SERIAL_CR & SPI_BUSY);
    buffer[index] = SERIAL_DATA & 0xFF;
  }
  SERIAL_CR = 0;
}

// Returns a word containing information about the firmware chip:
//  byte 0: Manuf. ID (Sanyo: 0x62, ST: 0x20)
//  byte 1: Device ID (Sanyo: 0x42?, ST: 0x40)
//  byte 2: Device capacity (only on ST chips, 0x12)
//  byte 3: status register (contains two bits specifying protection size)
uint32 getFirmwareType(void) {
  uint32 result;

  // Get ID
  while (SERIAL_CR & SPI_BUSY);
  SERIAL_CR = SPI_ENABLE | SPI_NOT_LAST | SPI_DEVICE_FIRMWARE;
  SERIAL_DATA = FW_READ_ID;
  while (SERIAL_CR & SPI_BUSY);

  result = 0;
  for (int i = 0; i < 3; i++) {
    SERIAL_DATA = 0;
    while (SERIAL_CR & SPI_BUSY);
    result = (SERIAL_DATA & 0xFF) | (result<<8);
  }

  // Get status
  while (SERIAL_CR & SPI_BUSY);
  SERIAL_CR = SPI_ENABLE | SPI_NOT_LAST | SPI_DEVICE_FIRMWARE;
  SERIAL_DATA = FW_READ_STATUS;
  while (SERIAL_CR & SPI_BUSY);

  SERIAL_DATA = 0;
  while (SERIAL_CR & SPI_BUSY);
  result = ((SERIAL_DATA & 0xFF) << 24) | result;
}


This code uses the defines shown on the SPI page.

Recent Changes (All) | Edit SideBar

Page last modified on March 12, 2006, at 07:54 PM
Edit Page | Page History
Everything done on this project is for the sole purpose of writing interoperable software under Sect. 1201 (f) Reverse Engineering exception of the DMCA.
This site is not affiliated with Nintendo in any manner. Nintendo DS © 2004 Nintendo. TM and ® are trademarks of Nintendo.
Powered by PmWiki