Difference between revisions of "XCI"

From Nintendo Switch Brew
Jump to navigation Jump to search
(Tencent card)
 
(15 intermediate revisions by 4 users not shown)
Line 1: Line 1:
Known internally as "XCI" (NX Card Image), this is the format used for storing the contents of a Nintendo Switch Gamecard.  
+
This is the format used for storing the contents of a Nintendo Switch Gamecard.
  
= Gamecard Header =
+
= Structure =
This header is 0x200 bytes and is located at offset 0 in the Gamecard.
+
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x1000
 +
| [[#CardKeyArea]]
 +
|-
 +
| 0x1000
 +
| 0x200
 +
| [[#CardHeader]]
 +
|-
 +
| 0x1200
 +
| 0x200
 +
| [11.0.0+] [[#NewCardHeader]]
 +
|-
 +
| 0x1400
 +
| 0x400
 +
| [11.0.0+] [[#NewCardHeaderCertArea]]
 +
|-
 +
| 0x1800
 +
| 0x6800
 +
| 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
 +
| Reserved
 +
|-
 +
| 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 138:
 
| 0x100
 
| 0x100
 
| 0x4
 
| 0x4
| Magicnum "HEAD"
+
| Magic ("HEAD")
 
|-
 
|-
 
| 0x104
 
| 0x104
 
| 0x4
 
| 0x4
| Secure Area Start Address (in Media Units which are 0x200 bytes)
+
| RomAreaStartPageAddress (in Gamecard page units, which are 0x200 bytes)
 
|-
 
|-
 
| 0x108
 
| 0x108
 
| 0x4
 
| 0x4
| Backup Area Start Address (always 0xFFFFFFFF)
+
| BackupAreaStartPageAddress (always 0xFFFFFFFF)
 
|-
 
|-
 
| 0x10C
 
| 0x10C
 
| 0x1
 
| 0x1
| TitleKeyDec Index (high nibble) and KEK Index (low nibble)
+
| TitleKeyDecIndex (high nibble) and KekIndex (low nibble)
 
|-
 
|-
 
| 0x10D
 
| 0x10D
 
| 0x1
 
| 0x1
| [[#Gamecard Size|Gamecard Size]]
+
| [[#RomSize]]
 
|-
 
|-
 
| 0x10E
 
| 0x10E
 
| 0x1
 
| 0x1
| Gamecard Header Version
+
| CardHeaderVersion
 
|-
 
|-
 
| 0x10F
 
| 0x10F
 
| 0x1
 
| 0x1
| [[#Gamecard Flags|Gamecard Flags]]
+
| [[#Flags]]
 
|-
 
|-
 
| 0x110
 
| 0x110
 
| 0x8
 
| 0x8
| Package ID (used for challenge–response authentication)
+
| PackageId (used for challenge–response authentication)
 
|-
 
|-
 
| 0x118
 
| 0x118
| 0x8
+
| 0x4
| Valid Data End Address (in Media Units which are 0x200 bytes)
+
| ValidDataEndAddress (in Gamecard page units, which are 0x200 bytes)
 +
|-
 +
| 0x11C
 +
| 0x1
 +
| Reserved
 +
|-
 +
| 0x11D
 +
| 0x1
 +
| [18.0.0+] [[#Flags2]] ([1.0.0-17.0.1] Reserved)
 +
|-
 +
| 0x11E
 +
| 0x2
 +
| [19.0.0+] [[#ApplicationIdListEntryCount]] ([1.0.0-18.1.0] Reserved)
 
|-
 
|-
 
| 0x120
 
| 0x120
 
| 0x10
 
| 0x10
| Gamecard Info IV (reversed)
+
| Iv (reversed)
 
|-
 
|-
 
| 0x130
 
| 0x130
 
| 0x8
 
| 0x8
| HFS0 partition offset
+
| PartitionFsHeaderAddress
 
|-
 
|-
 
| 0x138
 
| 0x138
 
| 0x8
 
| 0x8
| HFS0 header size
+
| PartitionFsHeaderSize
 
|-
 
|-
 
| 0x140
 
| 0x140
 
| 0x20
 
| 0x20
| SHA-256 hash of the [[#HFS0 Header|HFS0 Header]]
+
| PartitionFsHeaderHash (SHA-256 hash of the [[#PartitionFsHeader]])
 
|-
 
|-
 
| 0x160
 
| 0x160
 
| 0x20
 
| 0x20
| SHA-256 hash of the [[#Initial Data|Initial Data]]
+
| InitialDataHash (SHA-256 hash of the [[#InitialData]])
 
|-
 
|-
 
| 0x180
 
| 0x180
 
| 0x4
 
| 0x4
| Security Mode (0x01 = T1, 0x02 = T2)
+
| [[#SelSec]]
 
|-
 
|-
 
| 0x184
 
| 0x184
 
| 0x4
 
| 0x4
| T1 Key Index (always 2)
+
| SelT1Key (always 2)
 
|-
 
|-
 
| 0x188
 
| 0x188
 
| 0x4
 
| 0x4
| Key Index (always 0)
+
| SelKey (always 0)
 
|-
 
|-
 
| 0x18C
 
| 0x18C
 
| 0x4
 
| 0x4
| Normal Area End Address (in Media Units which are 0x200 bytes)
+
| LimArea (in Gamecard page units, which are 0x200 bytes)
 
|-
 
|-
 
| 0x190
 
| 0x190
 
| 0x70
 
| 0x70
| [[#Gamecard Info|Gamecard Info]] (AES-128-CBC encrypted)
+
| [[#CardHeaderEncryptedData]]
 
|}
 
|}
  
== Gamecard Size ==
+
=== 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 252:
 
|}
 
|}
  
== Gamecard Flags ==
+
=== Flags ===
 
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute|GameCardAttribute]].
 
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute|GameCardAttribute]].
  
Line 140: Line 274:
 
| 4
 
| 4
 
| [9.0.0+] DifferentRegionCupToGlobalDevice
 
| [9.0.0+] DifferentRegionCupToGlobalDevice
 +
|-
 +
| 7
 +
| [11.0.0+] HasNewCardHeader
 
|}
 
|}
  
== Gamecard Info ==
+
=== Flags2 ===
When decrypted, this 0x70 byte region is as follows:
+
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute2|GameCardAttribute2]].
 +
 
 +
=== ApplicationIdListEntryCount ===
 +
This is the number of entries in the ApplicationIdList located right before ValidDataEndAddress.
 +
 
 +
=== SelSec ===
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value
 +
! Description
 +
|-
 +
| 1
 +
| T1
 +
|-
 +
| 2
 +
| T2
 +
|}
 +
 
 +
=== CardHeaderEncryptedData ===
 +
This region is stored encrypted (AES-128-CBC).
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 153: Line 309:
 
| 0x0
 
| 0x0
 
| 0x8
 
| 0x8
| Firmware Version (0x00 = Development, 0x01 = Retail, [4.0.0+] 0x02 = Retail)
+
| [[#FwVersion]]
 
|-
 
|-
 
| 0x8
 
| 0x8
 
| 0x4
 
| 0x4
| Access Control (0x00A10011 = 25MHz access, 0x00A10010 = 50MHz access)
+
| [[#AccCtrl1]]
 
|-
 
|-
 
| 0xC
 
| 0xC
 
| 0x4
 
| 0x4
| Read Time Wait1 (always 0x1388)
+
| Wait1TimeRead (always 0x1388)
 
|-
 
|-
 
| 0x10
 
| 0x10
 
| 0x4
 
| 0x4
| Read Time Wait2 (always 0)
+
| Wait2TimeRead (always 0)
 
|-
 
|-
 
| 0x14
 
| 0x14
 
| 0x4
 
| 0x4
| Write Time Wait1 (always 0)
+
| Wait1TimeWrite (always 0)
 
|-
 
|-
 
| 0x18
 
| 0x18
 
| 0x4
 
| 0x4
| Write Time Wait2 (always 0)
+
| Wait2TimeWrite (always 0)
 
|-
 
|-
 
| 0x1C
 
| 0x1C
 
| 0x4
 
| 0x4
| Firmware Mode
+
| FwMode (the current SdkAddonVersion)
 
|-
 
|-
 
| 0x20
 
| 0x20
 
| 0x4
 
| 0x4
| CUP Version
+
| UppVersion
 
|-
 
|-
 
| 0x24
 
| 0x24
 
| 0x1
 
| 0x1
| [9.0.0+] Compatibility Type (0x00 = Normal, 0x01 = Terra)
+
| [9.0.0+] [[#CompatibilityType]]
 
|-
 
|-
 
| 0x25
 
| 0x25
 
| 0x3
 
| 0x3
| Empty
+
| Reserved
 
|-
 
|-
 
| 0x28
 
| 0x28
 
| 0x8
 
| 0x8
| Update Partition Hash
+
| UppHash (SHA-256 hash of the [[#UpdatePartition]])
 
|-
 
|-
 
| 0x30
 
| 0x30
 
| 0x8
 
| 0x8
| CUP ID (always 0x0100000000000816, which is the title-listing data archive's title ID)
+
| UppId (always 0x0100000000000816)
 
|-
 
|-
 
| 0x38
 
| 0x38
 
| 0x38
 
| 0x38
| Empty
+
| Reserved
 
|}
 
|}
  
= Gamecard Certificate =
+
==== FwVersion ====
This is the Gamecard's unique certificate and is located at offset 0x7000.
+
{| class="wikitable" border="1"
 +
|-
 +
! Value
 +
! Description
 +
|-
 +
| 0
 +
| Development
 +
|-
 +
| 1
 +
| Retail
 +
|-
 +
| 2
 +
| [4.0.0+] Retail
 +
|-
 +
| 3
 +
| [11.0.0+] Development
 +
|-
 +
| 4
 +
| [11.0.0+] Retail
 +
|-
 +
| 5
 +
| [12.0.0+] Retail
 +
|}
 +
 
 +
==== AccCtrl1 ====
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value
 +
! Description
 +
|-
 +
| 0x00A10011
 +
| 25MHz
 +
|-
 +
| 0x00A10010
 +
| 50MHz
 +
|}
 +
 
 +
==== CompatibilityType ====
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value
 +
! Description
 +
|-
 +
| 0
 +
| Normal
 +
|-
 +
| 1
 +
| Terra
 +
|}
 +
 
 +
== NewCardHeader ==
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x100
 +
| RSA-2048 PKCS #1 signature over the data from 0x100 to 0x200
 +
|-
 +
| 0x100
 +
| 0x90
 +
|
 +
|-
 +
| 0x190
 +
| 0x70
 +
| [[#NewCardHeaderEncryptedData]]
 +
|}
 +
 
 +
=== NewCardHeaderEncryptedData ===
 +
This region is stored encrypted (AES-128-CBC).
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x40
 +
|
 +
|-
 +
| 0x40
 +
| 0x20
 +
| SHA-256 hash of the [[#CardHeader]]
 +
|-
 +
| 0x60
 +
| 0x10
 +
| Reserved
 +
|}
 +
 
 +
== NewCardHeaderCertArea ==
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x100
 +
| RSA-2048 PKCS #1 signature over the data from 0x100 to 0x300
 +
|-
 +
| 0x100
 +
| 0x30
 +
|
 +
|-
 +
| 0x130
 +
| 0x100
 +
| [[#NewCardHeader]] modulus
 +
|-
 +
| 0x230
 +
| 0x4
 +
| [[#NewCardHeader]] exponent
 +
|-
 +
| 0x234
 +
| 0x1CC
 +
|
 +
|}
 +
 
 +
== CertArea ==
 +
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 498:
 
| 0x100
 
| 0x100
 
| 0x4
 
| 0x4
| Magicnum "CERT"
+
| Magic ("CERT")
 
|-
 
|-
 
| 0x104
 
| 0x104
 
| 0x4
 
| 0x4
| Empty
+
| Version
 
|-
 
|-
 
| 0x108
 
| 0x108
 
| 0x1
 
| 0x1
| KEK Index
+
| KekIndex
 
|-
 
|-
 
| 0x109
 
| 0x109
 
| 0x7
 
| 0x7
| Empty
+
| Reserved
 
|-
 
|-
 
| 0x110
 
| 0x110
 
| 0x10
 
| 0x10
| Device ID
+
| T1CardDeviceId
 
|-
 
|-
 
| 0x120
 
| 0x120
 
| 0x10
 
| 0x10
| Unknown
+
| Iv
 
|-
 
|-
 
| 0x130
 
| 0x130
| 0xD0
+
| 0x10
| Encrypted data
+
| HwKey (encrypted)
 +
|-
 +
| 0x140
 +
| 0xC0
 +
| Reserved (encrypted)
 +
|-
 +
| 0x200
 +
| 0x7E00
 +
| Reserved
 
|}
 
|}
  
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.
+
== NormalArea ==
 
+
This region contains all non-secure partitions of the Gamecard file system.
= 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"
 
{| class="wikitable" border="1"
Line 261: Line 542:
 
! Description
 
! Description
 
|-
 
|-
| 0x0
+
| Variable
| 0x8
+
| Variable
| Package ID from [[#Gamecard Header|Gamecard Header]] at offset 0x110
+
| [[#PartitionFsHeader|RootPartitionHeader]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#PartitionFsHeader|UpdatePartitionHeader]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#UpdatePartition|UpdatePartition]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [4.0.0+] [[#PartitionFsHeader|LogoPartitionHeader]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [4.0.0+] [[#LogoPartition|LogoPartition]]
 
|-
 
|-
| 0x8
+
| Variable
| 0x8
+
| Variable
| Empty
+
| [[#PartitionFsHeader|NormalPartitionHeader]]
 
|-
 
|-
| 0x10
+
| Variable
| 0x10
+
| Variable
| Challenge–response authentication data
+
| [[#NormalPartition|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"
 
|-
 
|-
| 0x20
+
! Offset
| 0x10
+
! Size
| Challenge–response authentication MAC
+
! Description
 
|-
 
|-
| 0x30
+
| Variable
| 0xC
+
| Variable
| Challenge–response authentication Nonce
+
| [[#PartitionFsHeader|SecurePartitionHeader]]
 
|-
 
|-
| 0x3C
+
| Variable
| 0x1C4
+
| Variable
| Reserved (must be empty)
+
| [[#SecurePartition|SecurePartition]]
 
|}
 
|}
  
= HFS0 =
+
=== 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".
  
== Header ==
+
=== PartitionFsHeader ===
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).
+
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 [[#Gamecard Header|Gamecard Header]].
+
A hash for this header is stored at offset 0x140 in the [[#CardHeader]].
 
 
== File System ==
 
The actual file system is as follows (also valid for the root partition):
 
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 305: Line 619:
 
| 0x0
 
| 0x0
 
| 0x4
 
| 0x4
| Magicnum "HFS0"
+
| Magic ("HFS0")
 
|-
 
|-
 
| 0x4
 
| 0x4
 
| 0x4
 
| 0x4
| Number of files
+
| FileCount
 
|-
 
|-
 
| 0x8
 
| 0x8
 
| 0x4
 
| 0x4
| Size of the string table
+
| StringTableSize
 
|-
 
|-
 
| 0xC
 
| 0xC
 
| 0x4
 
| 0x4
| Zero/Reserved
+
| Reserved
 
|-
 
|-
 
| 0x10
 
| 0x10
 
| X
 
| X
| File Entry Table
+
| [[#FileEntryTable]]
 
|-
 
|-
 
| 0x10 + X
 
| 0x10 + X
 
| Y
 
| Y
| String Table
+
| StringTable
 
|-
 
|-
 
| 0x10 + X + Y
 
| 0x10 + X + Y
 
| Z
 
| Z
| Raw File Data
+
| RawFileData
 
|}
 
|}
  
Where File Entry Table consists of Number of Files FileEntries:
+
==== FileEntryTable ====
 
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 366: Line 679:
  
 
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?).
 
= Cartridge Layout =
 
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 normal 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.
 
 
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.
 
 
[4.0.0+] The "normal" partition is now empty and a new partition "logo" was added.
 
[CHINA -TENCENT] On tencent cartridge for China, A partition "boot" got added with exact same content than "logo".
 

Latest revision as of 22:03, 9 October 2024

This is the format used for storing the contents of a Nintendo Switch Gamecard.

Structure

Offset Size Description
0x0 0x1000 #CardKeyArea
0x1000 0x200 #CardHeader
0x1200 0x200 [11.0.0+] #NewCardHeader
0x1400 0x400 [11.0.0+] #NewCardHeaderCertArea
0x1800 0x6800 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.

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.

FS calculates a SHA-256 hash over the whole 0x200 bytes and compares it with the hash stored at offset 0x160 in the #CardHeader.

Offset Size Description
0x0 0x8 Package ID from #CardHeader at offset 0x110
0x8 0x8 Reserved
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.

Offset Size Description
0x0 0x8 TitleKey1
0x8 0x8 TitleKey2
0x10 0xCF0 Reserved

CardHeader

Offset Size Description
0x0 0x100 RSA-2048 PKCS #1 signature over the header (data from 0x100 to 0x200)
0x100 0x4 Magic ("HEAD")
0x104 0x4 RomAreaStartPageAddress (in Gamecard page units, which are 0x200 bytes)
0x108 0x4 BackupAreaStartPageAddress (always 0xFFFFFFFF)
0x10C 0x1 TitleKeyDecIndex (high nibble) and KekIndex (low nibble)
0x10D 0x1 #RomSize
0x10E 0x1 CardHeaderVersion
0x10F 0x1 #Flags
0x110 0x8 PackageId (used for challenge–response authentication)
0x118 0x4 ValidDataEndAddress (in Gamecard page units, which are 0x200 bytes)
0x11C 0x1 Reserved
0x11D 0x1 [18.0.0+] #Flags2 ([1.0.0-17.0.1] Reserved)
0x11E 0x2 [19.0.0+] #ApplicationIdListEntryCount ([1.0.0-18.1.0] Reserved)
0x120 0x10 Iv (reversed)
0x130 0x8 PartitionFsHeaderAddress
0x138 0x8 PartitionFsHeaderSize
0x140 0x20 PartitionFsHeaderHash (SHA-256 hash of the #PartitionFsHeader)
0x160 0x20 InitialDataHash (SHA-256 hash of the #InitialData)
0x180 0x4 #SelSec
0x184 0x4 SelT1Key (always 2)
0x188 0x4 SelKey (always 0)
0x18C 0x4 LimArea (in Gamecard page units, which are 0x200 bytes)
0x190 0x70 #CardHeaderEncryptedData

RomSize

FS retrieves this data as GameCardSize.

Value Description
0xFA 1GB
0xF8 2GB
0xF0 4GB
0xE0 8GB
0xE1 16GB
0xE2 32GB

Flags

FS retrieves this data as GameCardAttribute.

Bits Description
0 AutoBoot
1 HistoryErase
2 [4.0.0+] RepairTool
3 [9.0.0+] DifferentRegionCupToTerraDevice
4 [9.0.0+] DifferentRegionCupToGlobalDevice
7 [11.0.0+] HasNewCardHeader

Flags2

FS retrieves this data as GameCardAttribute2.

ApplicationIdListEntryCount

This is the number of entries in the ApplicationIdList located right before ValidDataEndAddress.

SelSec

Value Description
1 T1
2 T2

CardHeaderEncryptedData

This region is stored encrypted (AES-128-CBC).

Offset Size Description
0x0 0x8 #FwVersion
0x8 0x4 #AccCtrl1
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
0x25 0x3 Reserved
0x28 0x8 UppHash (SHA-256 hash of the #UpdatePartition)
0x30 0x8 UppId (always 0x0100000000000816)
0x38 0x38 Reserved

FwVersion

Value Description
0 Development
1 Retail
2 [4.0.0+] Retail
3 [11.0.0+] Development
4 [11.0.0+] Retail
5 [12.0.0+] Retail

AccCtrl1

Value Description
0x00A10011 25MHz
0x00A10010 50MHz

CompatibilityType

Value Description
0 Normal
1 Terra

NewCardHeader

Offset Size Description
0x0 0x100 RSA-2048 PKCS #1 signature over the data from 0x100 to 0x200
0x100 0x90
0x190 0x70 #NewCardHeaderEncryptedData

NewCardHeaderEncryptedData

This region is stored encrypted (AES-128-CBC).

Offset Size Description
0x0 0x40
0x40 0x20 SHA-256 hash of the #CardHeader
0x60 0x10 Reserved

NewCardHeaderCertArea

Offset Size Description
0x0 0x100 RSA-2048 PKCS #1 signature over the data from 0x100 to 0x300
0x100 0x30
0x130 0x100 #NewCardHeader modulus
0x230 0x4 #NewCardHeader exponent
0x234 0x1CC

CertArea

This is the Gamecard's unique certificate.

FS retrieves this data with GetGameCardDeviceCertificate.

Offset Size Description
0x0 0x100 RSA-2048 PKCS #1 signature over the data from 0x100 to 0x200
0x100 0x4 Magic ("CERT")
0x104 0x4 Version
0x108 0x1 KekIndex
0x109 0x7 Reserved
0x110 0x10 T1CardDeviceId
0x120 0x10 Iv
0x130 0x10 HwKey (encrypted)
0x140 0xC0 Reserved (encrypted)
0x200 0x7E00 Reserved

NormalArea

This region contains all non-secure partitions of the Gamecard file system.

Offset Size Description
Variable Variable RootPartitionHeader
Variable Variable UpdatePartitionHeader
Variable Variable UpdatePartition
Variable Variable [4.0.0+] LogoPartitionHeader
Variable Variable [4.0.0+] LogoPartition
Variable Variable 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.

Offset Size Description
Variable Variable 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".

PartitionFsHeader

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 #CardHeader.

Offset Size Description
0x0 0x4 Magic ("HFS0")
0x4 0x4 FileCount
0x8 0x4 StringTableSize
0xC 0x4 Reserved
0x10 X #FileEntryTable
0x10 + X Y StringTable
0x10 + X + Y Z RawFileData

FileEntryTable

Offset Size Description
0x0 0x8 Offset of file in Data
0x8 0x8 Size of file in Data
0x10 0x4 Offset of filename in String Table
0x14 0x4 Size of Hashed region of file (for HFS0s, this is the size of the pre-filedata portion, for NCAs this is usually 0x200)
0x18 8 Zero/Reserved
0x20 0x20 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?).