XCI: Difference between revisions
No edit summary |
|||
Line 1: | Line 1: | ||
This is the format used for storing the contents of a Nintendo Switch Gamecard. | |||
= Gamecard | = Structure = | ||
This | {| class="wikitable" border="1" | ||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x1000 | |||
| [[#CardKeyArea]] | |||
|- | |||
| 0x1000 | |||
| 0x200 | |||
| [[#CardHeader]] | |||
|- | |||
| 0x1200 | |||
| 0x6E00 | |||
| ReservedArea | |||
|- | |||
| 0x8000 | |||
| 0x8000 | |||
| [[#CertArea]] | |||
|- | |||
| 0x10000 | |||
| Variable | |||
| [[#NormalArea]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#RomArea]] | |||
|- | |||
| Invalid | |||
| Invalid | |||
| BackupArea | |||
|} | |||
== CardKeyArea == | |||
This region cannot be read directly once written to the Gamecard. Therefore, it is hidden away during read/write operations on the raw Gamecard data. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x200 | |||
| [[#InitialData]] | |||
|- | |||
| 0x200 | |||
| 0xD00 | |||
| [[#TitleKeyArea]] | |||
|- | |||
| 0xF00 | |||
| 0x100 | |||
| Reserved | |||
|} | |||
=== InitialData === | |||
This region 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 [[#CardHeader]]. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| Package ID from [[#CardHeader]] 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) | |||
|} | |||
=== TitleKeyArea === | |||
This region is stored encrypted and contains the title keys used by the [[#InitialData]]. | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| TitleKey1 | |||
|- | |||
| 0x8 | |||
| 0x8 | |||
| TitleKey2 | |||
|- | |||
| 0x10 | |||
| 0xCF0 | |||
| Reserved | |||
|} | |||
== CardHeader == | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 16: | Line 130: | ||
| 0x100 | | 0x100 | ||
| 0x4 | | 0x4 | ||
| | | MagicCode ("HEAD") | ||
|- | |- | ||
| 0x104 | | 0x104 | ||
| 0x4 | | 0x4 | ||
| | | RomAreaStartPageAddress (in Gamecard page units, which are 0x200 bytes) | ||
|- | |- | ||
| 0x108 | | 0x108 | ||
| 0x4 | | 0x4 | ||
| | | BackupAreaStartPageAddress (always 0xFFFFFFFF) | ||
|- | |- | ||
| 0x10C | | 0x10C | ||
| 0x1 | | 0x1 | ||
| | | TitleKeyDecIndex (high nibble) and KekIndex (low nibble) | ||
|- | |- | ||
| 0x10D | | 0x10D | ||
| 0x1 | | 0x1 | ||
| [[# | | [[#RomSize]] | ||
|- | |- | ||
| 0x10E | | 0x10E | ||
| 0x1 | | 0x1 | ||
| | | CardHeaderVersion | ||
|- | |- | ||
| 0x10F | | 0x10F | ||
| 0x1 | | 0x1 | ||
| [[# | | [[#Flags]] | ||
|- | |- | ||
| 0x110 | | 0x110 | ||
| 0x8 | | 0x8 | ||
| | | PackageId (used for challenge–response authentication) | ||
|- | |- | ||
| 0x118 | | 0x118 | ||
| 0x8 | | 0x8 | ||
| | | ValidDataEndAddress (in Gamecard page units, which are 0x200 bytes) | ||
|- | |- | ||
| 0x120 | | 0x120 | ||
| 0x10 | | 0x10 | ||
| | | Iv (reversed) | ||
|- | |- | ||
| 0x130 | | 0x130 | ||
| 0x8 | | 0x8 | ||
| | | PartitionFsHeaderAddress | ||
|- | |- | ||
| 0x138 | | 0x138 | ||
| 0x8 | | 0x8 | ||
| | | PartitionFsHeaderSize | ||
|- | |- | ||
| 0x140 | | 0x140 | ||
| 0x20 | | 0x20 | ||
| SHA-256 hash of the [[# | | PartitionFsHeaderHash (SHA-256 hash of the [[#PartitionFsHeader]]) | ||
|- | |- | ||
| 0x160 | | 0x160 | ||
| 0x20 | | 0x20 | ||
| SHA-256 hash of the [[# | | InitialDataHash (SHA-256 hash of the [[#InitialData]]) | ||
|- | |- | ||
| 0x180 | | 0x180 | ||
| 0x4 | | 0x4 | ||
| | | SelSec (0x01 = T1, 0x02 = T2) | ||
|- | |- | ||
| 0x184 | | 0x184 | ||
| 0x4 | | 0x4 | ||
| | | SelT1Key (always 2) | ||
|- | |- | ||
| 0x188 | | 0x188 | ||
| 0x4 | | 0x4 | ||
| | | SelKey (always 0) | ||
|- | |- | ||
| 0x18C | | 0x18C | ||
| 0x4 | | 0x4 | ||
| | | LimArea (in Gamecard page units, which are 0x200 bytes) | ||
|- | |- | ||
| 0x190 | | 0x190 | ||
| 0x70 | | 0x70 | ||
| [[# | | [[#CardInfo]] ( encrypted) | ||
|} | |||
=== CardInfo === | |||
This region is stored encrypted (AES-128-CBC). | |||
{| class="wikitable" border="1" | |||
|- | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x8 | |||
| FwVersion (0x00 = Development, 0x01 = Retail, [4.0.0+] 0x02 = Retail, [11.0.0+] 0x04 = Retail) | |||
|- | |||
| 0x8 | |||
| 0x4 | |||
| AccCtrl1 (0x00A10011 = 25MHz access, 0x00A10010 = 50MHz access) | |||
|- | |||
| 0xC | |||
| 0x4 | |||
| Wait1TimeRead (always 0x1388) | |||
|- | |||
| 0x10 | |||
| 0x4 | |||
| Wait2TimeRead (always 0) | |||
|- | |||
| 0x14 | |||
| 0x4 | |||
| Wait1TimeWrite (always 0) | |||
|- | |||
| 0x18 | |||
| 0x4 | |||
| Wait2TimeWrite (always 0) | |||
|- | |||
| 0x1C | |||
| 0x4 | |||
| FwMode (the current SdkAddonVersion) | |||
|- | |||
| 0x20 | |||
| 0x4 | |||
| UppVersion | |||
|- | |||
| 0x24 | |||
| 0x1 | |||
| [9.0.0+] CompatibilityType (0x00 = Normal, 0x01 = Terra) | |||
|- | |||
| 0x25 | |||
| 0x3 | |||
| Empty | |||
|- | |||
| 0x28 | |||
| 0x8 | |||
| UppHash (SHA-256 hash of the [[#UpdatePartition]]) | |||
|- | |||
| 0x30 | |||
| 0x8 | |||
| UppId (always 0x0100000000000816) | |||
|- | |||
| 0x38 | |||
| 0x38 | |||
| Empty | |||
|} | |} | ||
== | === RomSize === | ||
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardSize|GameCardSize]]. | [[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardSize|GameCardSize]]. | ||
Line 118: | Line 294: | ||
|} | |} | ||
== | === Flags === | ||
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute|GameCardAttribute]]. | [[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute|GameCardAttribute]]. | ||
Line 142: | Line 318: | ||
|} | |} | ||
== | == CertArea == | ||
This is the Gamecard's unique certificate. | |||
This is the Gamecard's unique certificate | |||
[[Filesystem_services|FS]] retrieves this data with [[Filesystem_services#GetGameCardDeviceCertificate|GetGameCardDeviceCertificate]]. | [[Filesystem_services|FS]] retrieves this data with [[Filesystem_services#GetGameCardDeviceCertificate|GetGameCardDeviceCertificate]]. | ||
Line 221: | Line 335: | ||
| 0x100 | | 0x100 | ||
| 0x4 | | 0x4 | ||
| | | MagicCode ("CERT") | ||
|- | |- | ||
| 0x104 | | 0x104 | ||
| 0x4 | | 0x4 | ||
| | | Version | ||
|- | |- | ||
| 0x108 | | 0x108 | ||
| 0x1 | | 0x1 | ||
| | | KekIndex | ||
|- | |- | ||
| 0x109 | | 0x109 | ||
| 0x7 | | 0x7 | ||
| | | Reserved | ||
|- | |- | ||
| 0x110 | | 0x110 | ||
| 0x10 | | 0x10 | ||
| | | DeviceId | ||
|- | |- | ||
| 0x120 | | 0x120 | ||
| 0x10 | | 0x10 | ||
| | | Iv | ||
|- | |- | ||
| 0x130 | | 0x130 | ||
| 0xD0 | | 0xD0 | ||
| | | Data (encrypted) | ||
|- | |||
| 0x200 | |||
| 0x7E00 | |||
| Reserved | |||
|} | |} | ||
== NormalArea == | |||
This region contains all non-secure partitions of the Gamecard file system. | |||
= | |||
This | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 261: | Line 375: | ||
! Description | ! Description | ||
|- | |- | ||
| | | Variable | ||
| | | Variable | ||
| | | [[#PartitionFsHeader|RootPartitionHeader]] | ||
|- | |||
| Variable | |||
| Variable | |||
| [[#PartitionFsHeader|UpdatePartitionHeader]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [[#UpdatePartition]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [4.0.0+] [[#PartitionFsHeader|LogoPartitionHeader]] | |||
|- | |||
| Variable | |||
| Variable | |||
| [4.0.0+] [[#LogoPartition]] | |||
|- | |- | ||
| | | Variable | ||
| | | Variable | ||
| | | [[#PartitionFsHeader|NormalPartitionHeader]] | ||
|- | |- | ||
| | | Variable | ||
| | | Variable | ||
| | | [[#NormalPartition]] | ||
|} | |||
=== UpdatePartition === | |||
This partition 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. | |||
=== NormalPartition === | |||
This partition contains the .cnmt.nca and the game icondata nca. This is presumably for future compatibility so that if a future update changes the cryptographic protocol for the secure partition. Game icon data can still be shown in the home menu on old firmwares. | |||
[4.0.0+] This partition is now empty. | |||
=== LogoPartition === | |||
[4.0.0+] This partition now contains the contents of the [[#NormalPartition]]. | |||
== RomArea == | |||
This region contains all secure partitions of the Gamecard file system. | |||
{| class="wikitable" border="1" | |||
|- | |- | ||
! Offset | |||
! Size | |||
! Description | |||
|- | |- | ||
| | | Variable | ||
| | | Variable | ||
| | | [[#PartitionFsHeader|SecurePartitionHeader]] | ||
|- | |- | ||
| | | Variable | ||
| | | Variable | ||
| | | [[#SecurePartition]] | ||
|} | |} | ||
= | === SecurePartition === | ||
This partition contains an identical copy of the .cnmt.nca and game icondata nca, as well as all other ncas required for the game. | |||
== PartitionFs == | |||
This is the Gamecard file system which starts with magicnum "HFS0". | This is the Gamecard file system which starts with magicnum "HFS0". | ||
== | === PartitionFsHeader === | ||
The "SHA-256 File System" or "HFS0" starts at offset | The "SHA-256 File System" or "HFS0" starts at offset 0x10000 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 [[# | A hash for this header is stored at offset 0x140 in the [[#CardHeader]]. | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 305: | Line 452: | ||
| 0x0 | | 0x0 | ||
| 0x4 | | 0x4 | ||
| | | MagicCode ("HFS0") | ||
|- | |- | ||
| 0x4 | | 0x4 | ||
| 0x4 | | 0x4 | ||
| | | FileCount | ||
|- | |- | ||
| 0x8 | | 0x8 | ||
| 0x4 | | 0x4 | ||
| | | StringTableSize | ||
|- | |- | ||
| 0xC | | 0xC | ||
| 0x4 | | 0x4 | ||
| | | Reserved | ||
|- | |- | ||
| 0x10 | | 0x10 | ||
| X | | X | ||
| | | [[#FileEntryTable]] | ||
|- | |- | ||
| 0x10 + X | | 0x10 + X | ||
| Y | | Y | ||
| | | StringTable | ||
|- | |- | ||
| 0x10 + X + Y | | 0x10 + X + Y | ||
| Z | | Z | ||
| | | RawFileData | ||
|} | |} | ||
==== FileEntryTable ==== | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
Line 366: | Line 512: | ||
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?). | ||