Line 1: |
Line 1: |
− | =Header= | + | Known internally as "XCI" (NX Card Image), this is the format used for storing the contents of a Nintendo Switch Gamecard. |
− | The header is 0x200-bytes, at Gamecard+0.
| + | |
| + | = Gamecard Header = |
| + | This header is 0x200 bytes and is located at offset 0 in the Gamecard. |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 10: |
Line 12: |
| | 0x0 | | | 0x0 |
| | 0x100 | | | 0x100 |
− | | RSA-2048 PKCS #1 signature over the data from 0x100 - 0x200. | + | | RSA-2048 PKCS #1 signature over the header (data from 0x100 to 0x200) |
| |- | | |- |
| | 0x100 | | | 0x100 |
Line 18: |
Line 20: |
| | 0x104 | | | 0x104 |
| | 0x4 | | | 0x4 |
− | | Offset of Secure partition (Size of non-secure data?), in Media Units (0x200 bytes for switch gamecarts) | + | | Secure Area Start Address (in Media Units which are 0x200 bytes) |
| |- | | |- |
| | 0x108 | | | 0x108 |
| | 0x4 | | | 0x4 |
− | | 0xFFFFFFFF | + | | Backup Area Start Address (always 0xFFFFFFFF) |
| |- | | |- |
| | 0x10C | | | 0x10C |
| | 0x1 | | | 0x1 |
− | | ? | + | | TitleKeyDec Index (high nibble) and KEK Index (low nibble) |
| |- | | |- |
| | 0x10D | | | 0x10D |
| | 0x1 | | | 0x1 |
− | | Cartridge Size. 0xF8 = 2 GB, 0xF0 = 4 GB, 0xE0 = 8 GB, 0xE1 = 16 GB | + | | [[#Gamecard Size|Gamecard Size]] |
| |- | | |- |
| | 0x10E | | | 0x10E |
| | 0x1 | | | 0x1 |
− | | ? | + | | Gamecard Header Version |
| |- | | |- |
| | 0x10F | | | 0x10F |
| | 0x1 | | | 0x1 |
− | | ? | + | | [[#Gamecard Flags|Gamecard Flags]] |
| |- | | |- |
| | 0x110 | | | 0x110 |
| | 0x8 | | | 0x8 |
− | | ? | + | | Package ID (used for challenge–response authentication) |
| |- | | |- |
| | 0x118 | | | 0x118 |
| | 0x8 | | | 0x8 |
− | | Size of the Gamecart, in Media Units | + | | Valid Data End Address (in Media Units which are 0x200 bytes) |
| |- | | |- |
| | 0x120 | | | 0x120 |
| | 0x10 | | | 0x10 |
− | | ? | + | | Gamecard Info IV (reversed) |
| |- | | |- |
| | 0x130 | | | 0x130 |
| | 0x8 | | | 0x8 |
− | | Offset of HFS0 FS partition | + | | HFS0 partition offset |
| |- | | |- |
| | 0x138 | | | 0x138 |
− | | 8 | + | | 0x8 |
− | | HFS0 Header size | + | | HFS0 header size |
| |- | | |- |
| | 0x140 | | | 0x140 |
| | 0x20 | | | 0x20 |
− | | SHA256 hash of the HFS0 Header | + | | SHA-256 hash of the [[#HFS0 Header|HFS0 Header]] |
| |- | | |- |
| | 0x160 | | | 0x160 |
| | 0x20 | | | 0x20 |
− | | SHA256 hash of the crypto header | + | | SHA-256 hash of the [[#Initial Data|Initial Data]] |
| |- | | |- |
| | 0x180 | | | 0x180 |
| | 0x4 | | | 0x4 |
− | | 1? | + | | Security Mode (0x01 = T1, 0x02 = T2) |
| |- | | |- |
| | 0x184 | | | 0x184 |
| | 0x4 | | | 0x4 |
− | | 2? | + | | T1 Key Index (always 2) |
| |- | | |- |
| | 0x188 | | | 0x188 |
| | 0x4 | | | 0x4 |
− | | 0? | + | | Key Index (always 0) |
| |- | | |- |
| | 0x18C | | | 0x18C |
| | 0x4 | | | 0x4 |
− | | Offset of Secure partition (Size of non-secure data?), in Media Units, again. | + | | Normal Area End Address (in Media Units which are 0x200 bytes) |
| |- | | |- |
| | 0x190 | | | 0x190 |
| | 0x70 | | | 0x70 |
− | | Encrypted data/hashes of some kind | + | | [[#Gamecard Info|Gamecard Info]] (AES-128-CBC encrypted) |
| + | |} |
| + | |
| + | == Gamecard Size == |
| + | [[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardSize|GameCardSize]]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Value |
| + | ! Description |
| + | |- |
| + | | 0xFA |
| + | | 1GB |
| + | |- |
| + | | 0xF8 |
| + | | 2GB |
| + | |- |
| + | | 0xF0 |
| + | | 4GB |
| + | |- |
| + | | 0xE0 |
| + | | 8GB |
| + | |- |
| + | | 0xE1 |
| + | | 16GB |
| + | |- |
| + | | 0xE2 |
| + | | 32GB |
| |} | | |} |
| | | |
| + | == Gamecard Flags == |
| + | [[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute|GameCardAttribute]]. |
| | | |
− | = Cert = | + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0 |
| + | | AutoBoot |
| + | |- |
| + | | 1 |
| + | | HistoryErase |
| + | |- |
| + | | 2 |
| + | | [4.0.0+] RepairTool |
| + | |- |
| + | | 3 |
| + | | [9.0.0+] DifferentRegionCupToTerraDevice |
| + | |- |
| + | | 4 |
| + | | [9.0.0+] DifferentRegionCupToGlobalDevice |
| + | |} |
| | | |
− | This is for the CERT, located at Gamecard + 0x7000 (always?). This matches exactly the output from fsp-srv IDeviceOperator cmd 206 "GetGameCardDeviceCertificate".
| + | == Gamecard Info == |
| + | When decrypted, this 0x70 byte region is as follows: |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x8 |
| + | | Firmware Version (0x00 = Development, 0x01 = Retail, [4.0.0+] 0x02 = Retail) |
| + | |- |
| + | | 0x8 |
| + | | 0x4 |
| + | | Access Control (0x00A10011 = 25MHz access, 0x00A10010 = 50MHz access) |
| + | |- |
| + | | 0xC |
| + | | 0x4 |
| + | | Read Time Wait1 (always 0x1388) |
| + | |- |
| + | | 0x10 |
| + | | 0x4 |
| + | | Read Time Wait2 (always 0) |
| + | |- |
| + | | 0x14 |
| + | | 0x4 |
| + | | Write Time Wait1 (always 0) |
| + | |- |
| + | | 0x18 |
| + | | 0x4 |
| + | | Write Time Wait2 (always 0) |
| + | |- |
| + | | 0x1C |
| + | | 0x4 |
| + | | Firmware Mode |
| + | |- |
| + | | 0x20 |
| + | | 0x4 |
| + | | CUP Version |
| + | |- |
| + | | 0x24 |
| + | | 0x1 |
| + | | [9.0.0+] Compatibility Type (0x00 = Normal, 0x01 = Terra) |
| + | |- |
| + | | 0x25 |
| + | | 0x3 |
| + | | Empty |
| + | |- |
| + | | 0x28 |
| + | | 0x8 |
| + | | Update Partition Hash |
| + | |- |
| + | | 0x30 |
| + | | 0x8 |
| + | | CUP ID (always 0x0100000000000816, which is the title-listing data archive's title ID) |
| + | |- |
| + | | 0x38 |
| + | | 0x38 |
| + | | Empty |
| + | |} |
| + | |
| + | = Gamecard Certificate = |
| + | This is the Gamecard's unique certificate and is located at offset 0x7000. |
| + | |
| + | [[Filesystem_services|FS]] retrieves this data with [[Filesystem_services#GetGameCardDeviceCertificate|GetGameCardDeviceCertificate]]. |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 102: |
Line 217: |
| | 0x0 | | | 0x0 |
| | 0x100 | | | 0x100 |
− | | RSA-2048 PKCS #1 signature over the data from 0x100 - 0x200. | + | | RSA-2048 PKCS #1 signature over the data from 0x100 to 0x200 |
| |- | | |- |
| | 0x100 | | | 0x100 |
| | 0x4 | | | 0x4 |
| | Magicnum "CERT" | | | Magicnum "CERT" |
| + | |- |
| + | | 0x104 |
| + | | 0x4 |
| + | | Empty |
| + | |- |
| + | | 0x108 |
| + | | 0x1 |
| + | | KEK Index |
| + | |- |
| + | | 0x109 |
| + | | 0x7 |
| + | | Empty |
| |- | | |- |
| | 0x110 | | | 0x110 |
| | 0x10 | | | 0x10 |
− | | ? | + | | Device ID |
| |- | | |- |
− | | 0x12A | + | | 0x120 |
− | | 0xD6 | + | | 0x10 |
− | | Encrypted data. Some kind of key? | + | | Unknown |
| + | |- |
| + | | 0x130 |
| + | | 0xD0 |
| + | | Encrypted data |
| |} | | |} |
| | | |
− | The data between the CERT and the start of the HFS0 is all 0xFF. | + | The data between the Gamecard Certificate and the start of the HFS0 region is all 0xFF, except for one BOTW cart that has been found, inwhich it is 0x00. |
| + | |
| + | = Initial Data = |
| + | This data is used for challenge–response authentication when changing to the Gamecard's secure mode. |
| + | |
| + | [[Filesystem_services|FS]] calculates a SHA-256 hash over the whole 0x200 bytes and compares it with the hash stored at offset 0x160 in the [[#Gamecard Header|Gamecard Header]]. |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 |
| + | | 0x8 |
| + | | Package ID from [[#Gamecard Header|Gamecard Header]] at offset 0x110 |
| + | |- |
| + | | 0x8 |
| + | | 0x8 |
| + | | Empty |
| + | |- |
| + | | 0x10 |
| + | | 0x10 |
| + | | Challenge–response authentication data |
| + | |- |
| + | | 0x20 |
| + | | 0x10 |
| + | | Challenge–response authentication MAC |
| + | |- |
| + | | 0x30 |
| + | | 0xC |
| + | | Challenge–response authentication Nonce |
| + | |- |
| + | | 0x3C |
| + | | 0x1C4 |
| + | | Reserved (must be empty) |
| + | |} |
| | | |
| = HFS0 = | | = HFS0 = |
− | This is the FS which has magicnum "HFS0" at header+0. | + | This is the Gamecard file system which starts with magicnum "HFS0". |
| + | |
| + | == Header == |
| + | The "SHA-256 File System" or "HFS0" starts at offset 0xF000 in the Gamecard. The first 0x200 bytes act as a global header and represent the root partition which points to the other partitions ("normal", "logo", "update" and "secure). |
| + | |
| + | A hash for this header is stored at offset 0x140 in the [[#Gamecard Header|Gamecard Header]]. |
| + | |
| + | == File System == |
| + | The actual file system is as follows (also valid for the root partition): |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 130: |
Line 305: |
| | 0x0 | | | 0x0 |
| | 0x4 | | | 0x4 |
− | | HFS0 Magic | + | | Magicnum "HFS0" |
| |- | | |- |
| | 0x4 | | | 0x4 |
Line 179: |
Line 354: |
| | 0x14 | | | 0x14 |
| | 0x4 | | | 0x4 |
− | | Size of Hashed region of file (for HFS0s, this is the size of the pre-filedata portion, for NCAs this is usually 0x200). | + | | Size of Hashed region of file (for HFS0s, this is the size of the pre-filedata portion, for NCAs this is usually 0x200) |
| |- | | |- |
| | 0x18 | | | 0x18 |
Line 187: |
Line 362: |
| | 0x20 | | | 0x20 |
| | 0x20 | | | 0x20 |
− | | SHA256 hash of the first (size of hashed region) bytes of filedata. | + | | SHA-256 hash of the first (size of hashed region) bytes of filedata |
| |} | | |} |
| | | |
| The string table is 00-padded to align the start of raw filedata with a sector/media unit boundary (usually?). | | The string table is 00-padded to align the start of raw filedata with a sector/media unit boundary (usually?). |
| | | |
− | =Typical Cartridge Layout= | + | = Cartridge Layout = |
− | Observed gamecarts contain three partitions: "update", "normal", and "secure". | + | Observed gamecards contain three partitions: "update", "normal", and "secure". |
| | | |
| The update partition (Gamecard partition 0 for fsp-srv cmd 31) contains .cnmt.nca + .nca files for the entire system update required to play the game. Launch day carts contain a full copy of 1.0 ncas, newer carts contain newer sysupdate NCAs etc. | | The update partition (Gamecard partition 0 for fsp-srv cmd 31) contains .cnmt.nca + .nca files for the entire system update required to play the game. Launch day carts contain a full copy of 1.0 ncas, newer carts contain newer sysupdate NCAs etc. |
Line 201: |
Line 376: |
| The secure partition contains an identical copy of the .cnmt.nca and game icondata nca, as well as all other ncas required for the game. | | The secure partition contains an identical copy of the .cnmt.nca and game icondata nca, as well as all other ncas required for the game. |
| | | |
− | The entire rest of the gamecard after the secure partition ends is all FF padding. | + | The entire rest of the Gamecard after the secure partition ends is all FF padding. |
| + | |
| + | [4.0.0+] The "normal" partition is now empty and a new partition "logo" was added. |