Changes

Jump to navigation Jump to search
3,432 bytes added ,  22:27, 25 December 2019
m
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.
25

edits

Navigation menu