XCI

From Nintendo Switch Brew
(Redirected from Gamecard Format)
Jump to navigation Jump to search

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

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

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 MagicCode ("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 0x4 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 #CardInfo

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

SelSec

Value Description
1 T1
2 T2

CardInfo

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 Empty
0x28 0x8 UppHash (SHA-256 hash of the #UpdatePartition)
0x30 0x8 UppId (always 0x0100000000000816)
0x38 0x38 Empty

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

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 MagicCode ("CERT")
0x104 0x4 Version
0x108 0x1 KekIndex
0x109 0x7 Reserved
0x110 0x10 DeviceId
0x120 0x10 Iv
0x130 0xD0 Data (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 MagicCode ("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?).