Changes

Jump to navigation Jump to search
6,114 bytes added ,  16 April
no edit summary
Line 1: Line 1: −
= Header =
+
This is the format used for storing the contents of a Nintendo Switch Gamecard.
The header is 0x200-bytes at offset 0 in the Gamecard.
      +
= Structure =
 +
{| 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 10: Line 134:  
| 0x0
 
| 0x0
 
| 0x100
 
| 0x100
| RSA-2048 PKCS #1 signature over the XCI header (data from 0x100 to 0x200)
+
| RSA-2048 PKCS #1 signature over the header (data from 0x100 to 0x200)
 
|-
 
|-
 
| 0x100
 
| 0x100
 
| 0x4
 
| 0x4
| Magicnum "HEAD"
+
| Magic ("HEAD")
 
|-
 
|-
 
| 0x104
 
| 0x104
 
| 0x4
 
| 0x4
| Write Size (size of non-secure data in Media Units which are 0x200 bytes)
+
| RomAreaStartPageAddress (in Gamecard page units, which are 0x200 bytes)
 
|-
 
|-
 
| 0x108
 
| 0x108
 
| 0x4
 
| 0x4
| 0xFFFFFFFF
+
| BackupAreaStartPageAddress (always 0xFFFFFFFF)
 
|-
 
|-
 
| 0x10C
 
| 0x10C
 
| 0x1
 
| 0x1
| ?
+
| TitleKeyDecIndex (high nibble) and KekIndex (low nibble)
 
|-
 
|-
 
| 0x10D
 
| 0x10D
 
| 0x1
 
| 0x1
| Gamecard Type (0xFA = 1GB, 0xF8 = 2GB, 0xF0 = 4GB, 0xE0 = 8GB, 0xE1 = 16GB, 0xE2 = 32GB)
+
| [[#RomSize]]
 
|-
 
|-
 
| 0x10E
 
| 0x10E
 
| 0x1
 
| 0x1
| ?
+
| CardHeaderVersion
 
|-
 
|-
 
| 0x10F
 
| 0x10F
 
| 0x1
 
| 0x1
| Gamecard Options (bit0 = AutoBoot, bit1 = HistoryErase)
+
| [[#Flags]]
 
|-
 
|-
 
| 0x110
 
| 0x110
 
| 0x8
 
| 0x8
| ?
+
| PackageId (used for challenge–response authentication)
 
|-
 
|-
 
| 0x118
 
| 0x118
| 0x8
+
| 0x4
| Gamecard Size (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
 +
| Reserved
 
|-
 
|-
 
| 0x120
 
| 0x120
 
| 0x10
 
| 0x10
| Gamecard Initial Data IV (reversed)
+
| Iv (reversed)
 
|-
 
|-
 
| 0x130
 
| 0x130
 
| 0x8
 
| 0x8
| HFS0 partition offset
+
| PartitionFsHeaderAddress
 
|-
 
|-
 
| 0x138
 
| 0x138
 
| 0x8
 
| 0x8
| HFS0 header size
+
| PartitionFsHeaderSize
 
|-
 
|-
 
| 0x140
 
| 0x140
 
| 0x20
 
| 0x20
| SHA256 hash of the HFS0 Header
+
| PartitionFsHeaderHash (SHA-256 hash of the [[#PartitionFsHeader]])
 
|-
 
|-
 
| 0x160
 
| 0x160
 
| 0x20
 
| 0x20
| SHA256 hash of the crypto header
+
| InitialDataHash (SHA-256 hash of the [[#InitialData]])
 
|-
 
|-
 
| 0x180
 
| 0x180
 
| 0x4
 
| 0x4
| 1?
+
| [[#SelSec]]
 
|-
 
|-
 
| 0x184
 
| 0x184
 
| 0x4
 
| 0x4
| 2?
+
| SelT1Key (always 2)
 
|-
 
|-
 
| 0x188
 
| 0x188
 
| 0x4
 
| 0x4
| 0?
+
| SelKey (always 0)
 
|-
 
|-
 
| 0x18C
 
| 0x18C
 
| 0x4
 
| 0x4
| Duplicate Write Size (size of non-secure data in Media Units which are 0x200 bytes)
+
| LimArea (in Gamecard page units, which are 0x200 bytes)
 
|-
 
|-
 
| 0x190
 
| 0x190
 
| 0x70
 
| 0x70
| Gamecard Initial Data (AES-128-CBC encrypted)
+
| [[#CardHeaderEncryptedData]]
 
|}
 
|}
   −
= Cert =
+
=== RomSize ===
This is for the CERT, located at Gamecard + 0x7000 (always?). This matches exactly the output from fsp-srv IDeviceOperator cmd 206 "GetGameCardDeviceCertificate".
+
[[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
 +
|}
 +
 
 +
=== Flags ===
 +
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute|GameCardAttribute]].
 +
 
 +
{| 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
 +
|-
 +
| 7
 +
| [11.0.0+] HasNewCardHeader
 +
|}
 +
 
 +
=== Flags2 ===
 +
[[Filesystem_services|FS]] retrieves this data as [[Filesystem_services#GameCardAttribute2|GameCardAttribute2]].
 +
 
 +
=== SelSec ===
 +
{| class="wikitable" border="1"
 +
|-
 +
! Value
 +
! Description
 +
|-
 +
| 1
 +
| T1
 +
|-
 +
| 2
 +
| T2
 +
|}
 +
 
 +
=== CardHeaderEncryptedData ===
 +
This region is stored encrypted (AES-128-CBC).
    +
{| class="wikitable" border="1"
 +
|-
 +
! 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 ====
 +
{| 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"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 100: Line 417:  
| 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
 +
| 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
 
| 0x4
| Magicnum "CERT"
+
| [[#NewCardHeader]] exponent
 +
|-
 +
| 0x234
 +
| 0x1CC
 +
|
 +
|}
 +
 
 +
== CertArea ==
 +
This is the Gamecard's unique certificate.
 +
 
 +
[[Filesystem_services|FS]] retrieves this data with [[Filesystem_services#GetGameCardDeviceCertificate|GetGameCardDeviceCertificate]].
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! 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
 
| 0x110
 
| 0x10
 
| 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.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#PartitionFsHeader|RootPartitionHeader]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#PartitionFsHeader|UpdatePartitionHeader]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#UpdatePartition|UpdatePartition]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [4.0.0+] [[#PartitionFsHeader|LogoPartitionHeader]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [4.0.0+] [[#LogoPartition|LogoPartition]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#PartitionFsHeader|NormalPartitionHeader]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#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"
 
|-
 
|-
| 0x12A
+
! Offset
| 0xD6
+
! Size
| Encrypted data. Some kind of key?
+
! Description
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#PartitionFsHeader|SecurePartitionHeader]]
 +
|-
 +
| Variable
 +
| Variable
 +
| [[#SecurePartition|SecurePartition]]
 
|}
 
|}
   −
The data between the CERT and the start of the HFS0 is all 0xFF.
+
=== 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".
   −
= HFS0 =
+
=== PartitionFsHeader ===
This is the FS which has magicnum "HFS0" at header+0.
+
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]].
    
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 128: Line 616:  
| 0x0
 
| 0x0
 
| 0x4
 
| 0x4
| HFS0 Magic
+
| 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 177: Line 664:  
| 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 185: Line 672:  
| 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 =
  −
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.
 

Navigation menu