NAND

From iQueBrew
Jump to: navigation, search

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 - 0x40 - SKSA area, marked in the BBFS FAT as reserved
  • 0x40 - 0xFF0 - data area, used for files in the BBFS
  • 0xFF0 - 0x1000 - 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.

Footer

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