diff --git a/source/gamecard.c b/source/gamecard.c index 6a51a3f..de531e8 100644 --- a/source/gamecard.c +++ b/source/gamecard.c @@ -23,17 +23,24 @@ #include "service_guard.h" #include "utils.h" +#define GAMECARD_READ_BUFFER_SIZE 0x800000 /* 8 MiB */ + #define GAMECARD_ACCESS_WAIT_TIME 3 /* Seconds */ #define GAMECARD_UPDATE_TID (u64)0x0100000000000816 -#define GAMECARD_READ_BUFFER_SIZE 0x800000 /* 8 MiB */ - #define GAMECARD_ECC_BLOCK_SIZE 0x200 #define GAMECARD_ECC_DATA_SIZE 0x24 #define GAMECARD_STORAGE_AREA_NAME(x) ((x) == GameCardStorageArea_Normal ? "normal" : ((x) == GameCardStorageArea_Secure ? "secure" : "none")) +#define GAMECARD_CAPACITY_1GiB (u64)0x40000000 +#define GAMECARD_CAPACITY_2GiB (u64)0x80000000 +#define GAMECARD_CAPACITY_4GiB (u64)0x100000000 +#define GAMECARD_CAPACITY_8GiB (u64)0x200000000 +#define GAMECARD_CAPACITY_16GiB (u64)0x400000000 +#define GAMECARD_CAPACITY_32GiB (u64)0x800000000 + /* Type definitions. */ typedef enum { @@ -67,6 +74,7 @@ static u8 *g_gameCardReadBuf = NULL; static GameCardHeader g_gameCardHeader = {0}; static u64 g_gameCardStorageNormalAreaSize = 0, g_gameCardStorageSecureAreaSize = 0; +static u64 g_gameCardCapacity = 0; static u8 *g_gameCardHfsRootHeader = NULL; /// GameCardHashFileSystemHeader + GameCardHashFileSystemEntry + Name Table. static GameCardHashFileSystemPartitionInfo *g_gameCardHfsPartitions = NULL; @@ -89,7 +97,8 @@ static bool gamecardOpenStorageArea(u8 area); static bool gamecardReadStorageArea(void *out, u64 out_size, u64 offset, bool lock); static void gamecardCloseStorageArea(void); -static bool gamecardGetSizesFromStorageAreas(void); +static bool gamecardGetStorageAreasSizes(void); +static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size); /* Service guard used to generate thread-safe initialize + exit functions. */ /* I'm using this here even though this actually isn't a service but who cares, it gets the job done. */ @@ -97,10 +106,13 @@ NX_GENERATE_SERVICE_GUARD(gamecard); bool gamecardIsReady(void) { + bool ret = false; + mtx_lock(&g_gameCardSharedDataMutex); - bool status = (g_gameCardInserted && g_gameCardInfoLoaded); + ret = (g_gameCardInserted && g_gameCardInfoLoaded); mtx_unlock(&g_gameCardSharedDataMutex); - return status; + + return ret; } bool gamecardRead(void *out, u64 out_size, u64 offset) @@ -123,7 +135,7 @@ bool gamecardGetHeader(GameCardHeader *out) return ret; } -bool gamecardGetTotalRomSize(u64 *out) +bool gamecardGetTotalSize(u64 *out) { bool ret = false; @@ -138,7 +150,7 @@ bool gamecardGetTotalRomSize(u64 *out) return ret; } -bool gamecardGetTrimmedRomSize(u64 *out) +bool gamecardGetTrimmedSize(u64 *out) { bool ret = false; @@ -153,6 +165,21 @@ bool gamecardGetTrimmedRomSize(u64 *out) return ret; } +bool gamecardGetRomCapacity(u64 *out) +{ + bool ret = false; + + mtx_lock(&g_gameCardSharedDataMutex); + if (g_gameCardInserted && g_gameCardInfoLoaded && out) + { + *out = g_gameCardCapacity; + ret = true; + } + mtx_unlock(&g_gameCardSharedDataMutex); + + return ret; +} + bool gamecardGetCertificate(FsGameCardCertificate *out) { Result rc = 0; @@ -418,7 +445,7 @@ static void gamecardLoadInfo(void) /* Retrieve gamecard storage area sizes */ /* gamecardReadStorageArea() actually checks if the storage area sizes are greater than zero, so we must first perform this step */ - if (!gamecardGetSizesFromStorageAreas()) + if (!gamecardGetStorageAreasSizes()) { LOGFILE("Failed to retrieve gamecard storage area sizes!"); goto out; @@ -438,18 +465,19 @@ static void gamecardLoadInfo(void) goto out; } + /* Get gamecard capacity */ + g_gameCardCapacity = gamecardGetCapacityFromRomSizeValue(g_gameCardHeader.rom_size); + if (!g_gameCardCapacity) + { + LOGFILE("Invalid gamecard capacity value! (0x%02X)", g_gameCardHeader.rom_size); + goto out; + } + if (utilsGetCustomFirmwareType() == UtilsCustomFirmwareType_SXOS) { /* The total size for the secure storage area is maxed out under SX OS */ /* Let's try to calculate it manually */ - u64 capacity = gamecardGetCapacityFromHeader(&g_gameCardHeader); - if (!capacity) - { - LOGFILE("Invalid gamecard capacity value! (0x%02X)", g_gameCardHeader.rom_size); - goto out; - } - - g_gameCardStorageSecureAreaSize = ((capacity - ((capacity / GAMECARD_ECC_BLOCK_SIZE) * GAMECARD_ECC_DATA_SIZE)) - g_gameCardStorageNormalAreaSize); + g_gameCardStorageSecureAreaSize = ((g_gameCardCapacity - ((g_gameCardCapacity / GAMECARD_ECC_BLOCK_SIZE) * GAMECARD_ECC_DATA_SIZE)) - g_gameCardStorageNormalAreaSize); } /* Allocate memory for the root hash FS header */ @@ -552,9 +580,12 @@ out: static void gamecardFreeInfo(void) { memset(&g_gameCardHeader, 0, sizeof(GameCardHeader)); + g_gameCardStorageNormalAreaSize = 0; g_gameCardStorageSecureAreaSize = 0; + g_gameCardCapacity = 0; + if (g_gameCardHfsRootHeader) { if (g_gameCardHfsPartitions) @@ -759,7 +790,7 @@ static void gamecardCloseStorageArea(void) g_gameCardStorageCurrentArea = GameCardStorageArea_None; } -static bool gamecardGetSizesFromStorageAreas(void) +static bool gamecardGetStorageAreasSizes(void) { if (!g_gameCardInserted) { @@ -800,3 +831,34 @@ static bool gamecardGetSizesFromStorageAreas(void) return true; } + +static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size) +{ + u64 capacity = 0; + + switch(rom_size) + { + case GameCardRomSize_1GiB: + capacity = GAMECARD_CAPACITY_1GiB; + break; + case GameCardRomSize_2GiB: + capacity = GAMECARD_CAPACITY_2GiB; + break; + case GameCardRomSize_4GiB: + capacity = GAMECARD_CAPACITY_4GiB; + break; + case GameCardRomSize_8GiB: + capacity = GAMECARD_CAPACITY_8GiB; + break; + case GameCardRomSize_16GiB: + capacity = GAMECARD_CAPACITY_16GiB; + break; + case GameCardRomSize_32GiB: + capacity = GAMECARD_CAPACITY_32GiB; + break; + default: + break; + } + + return capacity; +} diff --git a/source/gamecard.h b/source/gamecard.h index a7dd244..1b7c4ae 100644 --- a/source/gamecard.h +++ b/source/gamecard.h @@ -38,12 +38,12 @@ typedef struct { } GameCardKeyFlags; typedef enum { - GameCardRomSize_1GB = 0xFA, - GameCardRomSize_2GB = 0xF8, - GameCardRomSize_4GB = 0xF0, - GameCardRomSize_8GB = 0xE0, - GameCardRomSize_16GB = 0xE1, - GameCardRomSize_32GB = 0xE2 + GameCardRomSize_1GiB = 0xFA, + GameCardRomSize_2GiB = 0xF8, + GameCardRomSize_4GiB = 0xF0, + GameCardRomSize_8GiB = 0xE0, + GameCardRomSize_16GiB = 0xE1, + GameCardRomSize_32GiB = 0xE2 } GameCardRomSize; typedef struct { @@ -144,51 +144,15 @@ bool gamecardIsReady(void); /// Used to read data from the inserted gamecard. /// All required handles, changes between normal <-> secure storage areas and proper offset calculations are managed internally. -/// offset + out_size should never exceed the value returned by gamecardGetTotalRomSize(). +/// offset + out_size should never exceed the value returned by gamecardGetTotalSize(). bool gamecardRead(void *out, u64 out_size, u64 offset); /// Miscellaneous functions. bool gamecardGetHeader(GameCardHeader *out); -bool gamecardGetTotalRomSize(u64 *out); -bool gamecardGetTrimmedRomSize(u64 *out); +bool gamecardGetTotalSize(u64 *out); +bool gamecardGetTrimmedSize(u64 *out); +bool gamecardGetRomCapacity(u64 *out); ///< Not the same as gamecardGetTotalSize(). bool gamecardGetCertificate(FsGameCardCertificate *out); bool gamecardGetBundledFirmwareUpdateVersion(u32 *out); -static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size) -{ - u64 capacity = 0; - - switch(rom_size) - { - case GameCardRomSize_1GB: - capacity = (u64)0x40000000; - break; - case GameCardRomSize_2GB: - capacity = (u64)0x80000000; - break; - case GameCardRomSize_4GB: - capacity = (u64)0x100000000; - break; - case GameCardRomSize_8GB: - capacity = (u64)0x200000000; - break; - case GameCardRomSize_16GB: - capacity = (u64)0x400000000; - break; - case GameCardRomSize_32GB: - capacity = (u64)0x800000000; - break; - default: - break; - } - - return capacity; -} - -static inline u64 gamecardGetCapacityFromHeader(GameCardHeader *header) -{ - if (!header) return 0; - return gamecardGetCapacityFromRomSizeValue(header->rom_size); -} - #endif /* __GAMECARD_H__ */ diff --git a/source/main.c b/source/main.c index 24000c0..e9ba351 100644 --- a/source/main.c +++ b/source/main.c @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) consoleUpdate(NULL); - if (gamecardGetTotalRomSize(&total_size)) + if (gamecardGetTotalSize(&total_size)) { printf("total_size: 0x%lX\n", total_size); } else { @@ -96,7 +96,7 @@ int main(int argc, char *argv[]) consoleUpdate(NULL); - if (gamecardGetTrimmedRomSize(&trimmed_size)) + if (gamecardGetTrimmedSize(&trimmed_size)) { printf("trimmed_size: 0x%lX\n", trimmed_size); } else {