diff --git a/code_templates/usb_gc_dumper.c b/code_templates/usb_gc_dumper.c index 694a59f..9d469da 100644 --- a/code_templates/usb_gc_dumper.c +++ b/code_templates/usb_gc_dumper.c @@ -480,6 +480,9 @@ end: utilsSetLongRunningProcessState(false); + FsGameCardIdSet id_set = {0}; + if (gamecardGetIdSet(&id_set)) LOG_DATA(&id_set, sizeof(FsGameCardIdSet), "Gamecard ID set:"); + consolePrint("press any button to continue"); utilsWaitForButtonPress(0); diff --git a/include/core/fs_ext.h b/include/core/fs_ext.h index 1911679..a512adc 100644 --- a/include/core/fs_ext.h +++ b/include/core/fs_ext.h @@ -32,18 +32,50 @@ extern "C" { /// Located at offset 0x7000 in the gamecard image. typedef struct { - u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the data. - u32 magic; ///< "CERT". + u8 signature[0x100]; ///< RSA-2048-PSS with SHA-256 signature over the rest of the data. + u32 magic; ///< "CERT". u32 version; u8 kek_index; u8 reserved[0x7]; u8 device_id[0x10]; u8 iv[0x10]; - u8 data[0xD0]; ///< Encrypted using the IV from this struct and an unknown key. + u8 data[0xD0]; ///< Encrypted using the IV from this struct and an unknown key. } FsGameCardCertificate; NXDT_ASSERT(FsGameCardCertificate, 0x200); +typedef struct { + u8 maker_code; ///< Usually 0xC2 (Macronix). + u8 memory_capacity; ///< Matches GameCardRomSize. + u8 reserved; ///< Usually 0x0A / 0x09. + u8 memory_type; ///< Usually 0x21. +} FsCardId1; + +NXDT_ASSERT(FsCardId1, 0x4); + +typedef struct { + u8 card_security_number; ///< Usually 0x02. + u8 card_type; ///< Usually 0x00. + u8 reserved[0x2]; ///< Usually filled with zeroes. +} FsCardId2; + +NXDT_ASSERT(FsCardId2, 0x4); + +typedef struct { + u8 reserved[0x4]; ///< Usually filled with zeroes. +} FsCardId3; + +NXDT_ASSERT(FsCardId3, 0x4); + +/// Returned by fsDeviceOperatorGetGameCardIdSet. +typedef struct { + FsCardId1 id1; + FsCardId2 id2; + FsCardId3 id3; +} FsGameCardIdSet; + +NXDT_ASSERT(FsGameCardIdSet, 0xC); + /// IFileSystemProxy. Result fsOpenGameCardStorage(FsStorage *out, const FsGameCardHandle *handle, u32 partition); Result fsOpenGameCardDetectionEventNotifier(FsEventNotifier *out); @@ -51,6 +83,7 @@ Result fsOpenGameCardDetectionEventNotifier(FsEventNotifier *out); /// IDeviceOperator. Result fsDeviceOperatorUpdatePartitionInfo(FsDeviceOperator *d, const FsGameCardHandle *handle, u32 *out_title_version, u64 *out_title_id); Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator *d, const FsGameCardHandle *handle, FsGameCardCertificate *out); +Result fsDeviceOperatorGetGameCardIdSet(FsDeviceOperator *d, FsGameCardIdSet *out); #ifdef __cplusplus } diff --git a/include/core/gamecard.h b/include/core/gamecard.h index 7665c3b..44ad88b 100644 --- a/include/core/gamecard.h +++ b/include/core/gamecard.h @@ -236,6 +236,10 @@ bool gamecardReadStorage(void *out, u64 read_size, u64 offset); /// This area can't be read using gamecardReadStorage(). bool gamecardGetKeyArea(GameCardKeyArea *out); +/// Fills the provided FsGameCardIdSet pointer. +/// This area can't be read using gamecardReadStorage(). +bool gamecardGetIdSet(FsGameCardIdSet *out); + /// Fills the provided GameCardHeader pointer. /// This area can also be read using gamecardReadStorage(), starting at offset 0. bool gamecardGetHeader(GameCardHeader *out); diff --git a/source/core/fs_ext.c b/source/core/fs_ext.c index 980dc01..2aa5c90 100644 --- a/source/core/fs_ext.c +++ b/source/core/fs_ext.c @@ -78,3 +78,17 @@ Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator *d, const F return rc; } + +Result fsDeviceOperatorGetGameCardIdSet(FsDeviceOperator *d, FsGameCardIdSet *out) +{ + struct { + u64 buf_size; + } in = { sizeof(FsGameCardIdSet) }; + + Result rc = serviceDispatchIn(&d->s, 208, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out, sizeof(FsGameCardIdSet) } } + ); + + return rc; +} diff --git a/source/core/gamecard.c b/source/core/gamecard.c index c29f6fd..706696d 100644 --- a/source/core/gamecard.c +++ b/source/core/gamecard.c @@ -347,6 +347,23 @@ bool gamecardGetKeyArea(GameCardKeyArea *out) return ret; } +bool gamecardGetIdSet(FsGameCardIdSet *out) +{ + bool ret = false; + + SCOPED_LOCK(&g_gameCardMutex) + { + if (!g_gameCardInterfaceInit || g_gameCardStatus != GameCardStatus_InsertedAndInfoLoaded || !out) break; + + Result rc = fsDeviceOperatorGetGameCardIdSet(&g_deviceOperator, out); + if (R_FAILED(rc)) LOG_MSG("fsDeviceOperatorGetGameCardIdSet failed! (0x%08X)", rc); + + ret = R_SUCCEEDED(rc); + } + + return ret; +} + bool gamecardGetHeader(GameCardHeader *out) { bool ret = false;