1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-12-27 19:06:01 +00:00

gamecard: support ID set dumping.

This commit is contained in:
Pablo Curiel 2022-02-03 02:13:20 +01:00
parent 9cc1d64694
commit 4929330e32
5 changed files with 74 additions and 3 deletions

View file

@ -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);

View file

@ -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
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;