From WiiBrew
< Hardware(Redirected from NAND Flash layout)
Jump to navigation Jump to search
See also: Hardware/NAND Interface

The Wii contains 512 MiB of NAND flash storage, which is used to store "system software", channels (including Virtual Console titles), game saves, and system settings.


The NAND is divided into 2048 byte pages combined with 64 bytes of "spare data" for the purpose of error correction and verification; page indices are used when addressing locations to the NAND Interface. Each group of 8 pages is known as a cluster (16384 bytes without spare data), which is the unit of storage used by SFFS. Each group of 64 pages (131072 bytes; 8 clusters) is known as a block, which is a single failable unit in the NAND. The NAND has a total of 4096 blocks.

Physical layout

  • Block 0 (pages 0-0x3F): boot1
    • boot1 is the second-stage bootloader; it is decrypted by boot0, which resides on a read-only mask ROM inside the Starlet coprocessor. Its primary function is to load and decrypt boot2.
    • Block 0 is guaranteed by the manufacturer to be valid, so there is no bad block map necessary.
  • Blocks 1-7 (Pages 0x40 - 0x1ff) : boot2 (two copies and blockmaps)
    • boot2 is the third-stage bootloader; it is stored in a modified WAD format, including a ticket that is encrypted with the common key and signed.
  • Block 8 / Cluster 0x40 / Page 0x200: beginning of per-console unique data
  • Clusters 0x40 - 0x7EFF: Encrypted filesystem data. Data is encrypted with a per-console AES key, and then signed with a (separate, per-console) HMAC key.
  • Clusters 0x7F00-0x7FFF: Filesystem metadata (SFFS, unencrypted). There are 16 superblocks contained therein — one every 16 clusters.

Metadata layout

The authoritative source of information about the Wii's metadata layout is Segher's zestig.c, but here is an attempt to describe that in English.

Each metadata "superblock" starts with the 4 magic bytes "SFFS" (probably short for Secure FAT FileSystem), followed by a 4-byte "generation number" and another 4-byte number (always 0x10?). When accessing the FS, IOS will choose the superblock with the generation number matching the one in SEEPROM and use it; whenever it modifies the filesystem in any way, it will increment the generation number in SEEPROM by 1, update the generation number of the superblock, and write out an entirely new superblock in the next slot (in round-robin order). This allows the history of the filesystem to be seen.

The next 0x10000 bytes (bytes 0xc:0x1000c within the superblock) are 0x8000 2-byte cluster numbers, and comprise the FAT. The FAT is followed by the FST — the tree structure containing the directory hierarchy and (plaintext!) filenames.


The FAT contains cluster chain / allocation information for the entire NAND chip, including parts of it which are not technically part of the filesystem!

The first 64 entries will always be 0xFFFC, which indicates that this cluster is "reserved". These correspond to the first 64 clusters or 8 blocks — which is where boot1 and boot2 are stored.

Special values include:

  • 0xFFFB - last cluster within a chain
  • 0xFFFC - reserved cluster
  • 0xFFFD - bad block (marked at factory) — you should always see these in groups of 8 (8 clusters per NAND block)
  • 0xFFFE - empty (unused / available) space

Otherwise, the value stored within a slot in the FAT for a given cluster points to the next cluster in the chain, similar to the FAT used in DOS. Therefore, in order to figure out what clusters belong to what file, you must use the information in the FST to find the starting cluster for each file, and then follow each cluster chain.


Each entry in the FST is 0x20 bytes. Here is a typical entry for a leaf node (regular file):

0000000: 4e41 4e44 424f 4f54 494e 464f fd00 2714  NANDBOOTINFO..'.
0000010: 0035 0000 1020 0000 1000 0001 0000 0000  .5... ..........
Start End Length Typical value Description
0x00 0x0B 0x0C "NANDBOOTINFO" Filename
0x0C 0x0C 1 0xfd File access "mode"
  • If (mode & 3) == 1, this is a regular file
  • If (mode & 3) == 2, this is a directory
  • mode >> 0x6 gives the owner permissions
  • (mode & 0x30) >> 4 gives the group permissions
  • (mode & 0xc) >> 2 gives the other permissions
0x0D 0x0D 1 0 file attributes
0x0E 0x0F 2 0x2714 "sub" -- for a file, this is the starting cluster for the file. For a directory, this points to the index into the FST of the first child of this tree node (FFFF for empty directories)
0x10 0x11 2 0x0035 "sib" -- this points to the index into the FST of the next sibling node
0x12 0x15 4 0x1020 filesize
0x16 0x19 4 0x1000 uid
0x1A 0x1B 2 0x1 gid
0x1C 0x1F 4 0 x3 (unknown, but see below)

HMAC info

The filesystem data and metadata clusters are "signed" with an HMAC to prevent tampering. The HMAC key is a 20-byte key stored in OTP, but each cluster is also seeded with a non-standard "salt". This 0x40-byte piece of data is generated in memory and then fed into the HMAC algorithm, and then the unencrypted contents of a cluster is fed through the HMAC algorithm. Two copies of the resulting 20-byte HMAC value is stored in the spare / OOB area of the cluster, in the 7th and 8th pages within that cluster.

Salt format for file data:

Start End Length Description
0x00 0x03 4 uid
0x04 0x0f 0x0b filename
0x10 0x13 0x04 index (which cluster in the chain this is; for the first cluster, this will be 0, for the second cluster, 1, etc)
0x14 0x17 0x04 fst_pos (index into FST)
0x18 0x1b 0x04 x3 (unknown field above)
0x1c 0x3f 0x24 padding (all zero)

Salt format for metadata:

Start End Length Description
0x00 0x11 0x12 padding (all zero)
0x12 0x13 2 cluster (starting cluster number of this metadata block, e.g. 0x7F00)
0x14 0x3f 0x2b padding (all zero)

Supported chips

The NAND flash driver inside boot2 and IOS supports the following chip IDs:

Hynix: ad 76 / ad f1 / ad dc  (64MB = HY27US0812(1/2)B, 128MB = HY27UF081G2A, 512MB = HY27UF084G2M or HY27UG084G2M)
Samsung: ec 76 / ec f1 / ec da / ec dc (64M K9F1208U0C /128 K9F1G08U0B/256 K9F2G08U0A/512 = K9F4G08U0A)
Toshiba: 98 76 / 98 f1 / 98 da (64/128 = TC58NVG0S3AFT05 or TC58NVG0S3ATG05 or TC58NVG0S3BFT00/256 = TC58NVG1D4BTG00 (?!))

It is not known why the IOS driver supports chips smaller than 512MB - presumably there were plans to sell lower priced models with less storage, but it turned out that 512MB wasn't much storage and smaller chips weren't much cheaper.

Useful Links @samsung