NAND
The iQue uses a 64MiB NAND flash, which consists of 4096 logical blocks of 16384 bytes each (made up of 32 512-byte pages). Each page also has its own "spare" area, which is detailed below.
Block Map
- 0x0 - 0x3F - SKSA area, marked in the BBFS FAT as reserved
- 0x40 - 0xFEF - data area, used for files in the BBFS
- 0xFF0 - 0xFFF - BBFS area, each block holds a copy of the BBFS along with a 'sequence number', highest sequence number is the latest BBFS.
BBFS
BBFS is the filesystem used on the iQue NAND, a very simple file-system used to store games and config data. The Wii NAND's SFFS is actually very similar to BBFS, though with many more features.
The BBFS is made up of three parts: a FAT (file-allocation table), an entry table and a footer:
FAT
The FAT is located at 0x0 in the BBFS block, made up of 4096 16-bit signed integers, one for each block in the NAND. This is used to specify if a block may be reserved, bad, available, or it might point to another block in the 'chain' (ie. file 0 points to block 0, block 0 points to block 2, block 2 points to block 15...), or signify the end of the chain.
Files make use of the FAT by simply pointing to a block in the FAT as its start block. Extracting the file is then just a matter of following the chain of pointers in the FAT, reading in each block until you reach an end-of-chain marker.
Possible FAT entries:
Value | Description |
---|---|
0 | Free/unused block |
-1 | End-of-chain marker |
-2 | Bad block |
-3 | Reserved block (used for SKSA area) |
Entry Table
File entries are stored from 0x2000 - 0x3FF4 in the BBFS block, allowing for 409 entries per BBFS.
Each entry has the format:
Offset | Length | Type | Information |
---|---|---|---|
0x0 | 0x8 | char | File name |
0x8 | 0x3 | char | File extension |
0xB | 0x1 | byte | Valid indicator (1 if file is valid) |
0xC | 0x2 | int16 | Start block # |
0xE | 0x2 | bytes | Padding? |
0x10 | 0x4 | int32 | File size |
Files may be deleted by simply having the Valid indicator set to 0, or having a block number of -1, so when reading the entry table you should make sure to read all 409 entries first and then filter out any invalid ones.
From 0x3FF4 to 0x4000 is the BBFS footer, which simply contains a BBFS signature to identify it as a BBFS block, a sequence number used for finding the latest BBFS, and a checksum for verifying the BBFS contents.
Offset | Length | Type | Information |
---|---|---|---|
0x0 | 0x4 | char | Magic (BBFS or BBFL) |
0x4 | 0x4 | int32 | Sequence number |
0x8 | 0x2 | int16 | Link block # |
0xA | 0x2 | int16 | Checksum |
The "Link block #" field seems to be used for linking two BBFS blocks together, though this hasn't been seen in any NAND dumps so far (maybe meant for NANDs larger than 4096 blocks, or containing more than 409 entries?).
Checksum is a basic adder, the fields value is made by adding each uint16 from 0x0 - 0x3FFE, and taking the result away from 0xCAD7. For verifying, 0x0 - 0x4000 is added together, and if the result is 0xCAD7 the checksum is valid.
Spare data
Each 512 page page in the NAND has a 16 byte "spare" area associated with it, which is used for bad-block markers, error-correction codes and block-pointers for the SA area.
Unfortunately the I@H USB commands for reading/writing NAND can only access the last page-spare of each block, though hardware NAND writers can access all of them. It seems that writing a "block-spare" over USB will actually copy the spare data to all the page-spares in the block (besides the ECC section), and can also recalculate ECC itself if given ECC data of all 0xFF.
Blocks in the SA area (containing SA1/SA2 tickets or data) also have 3 bytes in the spare used for pointing toward the next SA block, ie. SA1 ticket block -> SA1 data block 1 -> SA1 data block n -> SA2 ticket block, it's guessed this is for working around any bad-blocks in the SA area.
ECC is calculated using a Hamming code, as documented in the Linux kernel nand_ecc documentation, a working iQue implementation is available inside the iQueTool source code.
So far the known spare format is:
Offset | Length | Type | Information |
---|---|---|---|
0x0 | 0x3 | bytes | SA block data (1 byte, copied to all 3 bytes) |
0x3 | 0x2 | bytes | Unknown (always 0xFF?) |
0x5 | 0x1 | byte | Bad block indicator (0 if block is bad) |
0x6 | 0x2 | bytes | Unknown (always 0xFF?) |
0x8 | 0x3 | bytes | ECC data for 0x100-0x200 in the page |
0xB | 0x2 | bytes | Unknown (always 0xFF?) |
0xD | 0x3 | bytes | ECC data for 0x0-0x100 in the page |