1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-29 13:42:11 +00:00

Tweaked gamecard code.

Modified gamecard handle retrieval and storage area mounting. Added gamecard status codes.
This commit is contained in:
Pablo Curiel 2020-07-17 01:01:31 -04:00
parent 95d5bda83a
commit 6bee2c5d20
4 changed files with 48 additions and 48 deletions

View file

@ -129,7 +129,7 @@ static void gamecardFreeInfo(void);
static bool gamecardReadSecurityInformation(void); static bool gamecardReadSecurityInformation(void);
static bool gamecardGetHandle(void); static bool gamecardGetHandleAndStorage(u32 partition);
NX_INLINE void gamecardCloseHandle(void); NX_INLINE void gamecardCloseHandle(void);
static bool gamecardOpenStorageArea(u8 area); static bool gamecardOpenStorageArea(u8 area);
@ -262,12 +262,12 @@ UEvent *gamecardGetStatusChangeUserEvent(void)
return event; return event;
} }
bool gamecardIsReady(void) u8 gamecardGetStatus(void)
{ {
mutexLock(&g_gamecardMutex); mutexLock(&g_gamecardMutex);
bool ret = (g_gameCardInserted && g_gameCardInfoLoaded); u8 status = (g_gameCardInserted ? (g_gameCardInfoLoaded ? GameCardStatus_InsertedAndInfoLoaded : GameCardStatus_InsertedAndInfoNotLoaded) : GameCardStatus_NotInserted);
mutexUnlock(&g_gamecardMutex); mutexUnlock(&g_gamecardMutex);
return ret; return status;
} }
bool gamecardReadStorage(void *out, u64 read_size, u64 offset) bool gamecardReadStorage(void *out, u64 read_size, u64 offset)
@ -527,7 +527,7 @@ static int gamecardDetectionThreadFunc(void *arg)
Waiter exit_event_waiter = waiterForUEvent(&g_gameCardDetectionThreadExitEvent); Waiter exit_event_waiter = waiterForUEvent(&g_gameCardDetectionThreadExitEvent);
/* Retrieve initial gamecard insertion status. */ /* Retrieve initial gamecard insertion status. */
/* Load gamecard info right away if a gamecard is inserted. */ /* Load gamecard info right away if a gamecard is inserted, then signal the user mode gamecard status change event. */
g_gameCardInserted = gamecardIsInserted(); g_gameCardInserted = gamecardIsInserted();
if (g_gameCardInserted) gamecardLoadInfo(); if (g_gameCardInserted) gamecardLoadInfo();
ueventSignal(&g_gameCardStatusChangeEvent); ueventSignal(&g_gameCardStatusChangeEvent);
@ -559,6 +559,7 @@ static int gamecardDetectionThreadFunc(void *arg)
mutexUnlock(&g_gamecardMutex); mutexUnlock(&g_gamecardMutex);
/* Signal user mode gamecard status change event. */
ueventSignal(&g_gameCardStatusChangeEvent); ueventSignal(&g_gameCardStatusChangeEvent);
} }
@ -815,49 +816,51 @@ static bool gamecardReadSecurityInformation(void)
return found; return found;
} }
static bool gamecardGetHandle(void) static bool gamecardGetHandleAndStorage(u32 partition)
{ {
if (!g_gameCardInserted) if (!g_gameCardInserted || partition > 1)
{ {
LOGFILE("Gamecard not inserted!"); LOGFILE("Invalid parameters!");
return false; return false;
} }
Result rc1 = 0, rc2 = 0; Result rc1 = 0, rc2 = 0;
FsStorage tmp_storage = {0};
/* 10 tries. */ /* 10 tries. */
for(u8 i = 0; i < 10; i++) for(u8 i = 0; i < 10; i++)
{ {
/* First try to open a gamecard storage area using the current gamecard handle. */ /* 100 ms wait in case there was an error in the previous loop. */
rc1 = fsOpenGameCardStorage(&tmp_storage, &g_gameCardHandle, 0); if (R_FAILED(rc1) || R_FAILED(rc2)) svcSleepThread(100000000);
if (R_SUCCEEDED(rc1))
/* First, let's try to retrieve a gamecard handle. */
/* This can return 0x140A02 if the "nogc" patch is enabled by the running CFW. */
rc1 = fsDeviceOperatorGetGameCardHandle(&g_deviceOperator, &g_gameCardHandle);
if (R_FAILED(rc1))
{ {
fsStorageClose(&tmp_storage); LOGFILE("fsDeviceOperatorGetGameCardHandle failed on try #%u! (0x%08X).", i + 1, rc1);
break; continue;
} }
/* If the previous call failed, we may have an invalid handle, so let's close the current one and try to retrieve a new one. */ /* If the previous call succeeded, let's try to open the desired gamecard storage area. */
gamecardCloseHandle(); rc2 = fsOpenGameCardStorage(&g_gameCardStorage, &g_gameCardHandle, partition);
rc2 = fsDeviceOperatorGetGameCardHandle(&g_deviceOperator, &g_gameCardHandle); if (R_FAILED(rc2))
{
gamecardCloseHandle(); /* Close invalid gamecard handle. */
LOGFILE("fsOpenGameCardStorage failed to open %s storage area on try #%u! (0x%08X).", GAMECARD_STORAGE_AREA_NAME(partition + 1), i + 1, rc2);
continue;
}
/* If we got up to this point, both a valid gamecard handle and a valid storage area handle are guaranteed. */
break;
} }
if (R_FAILED(rc1) || R_FAILED(rc2)) return (R_SUCCEEDED(rc1) && R_SUCCEEDED(rc2));
{
/* Close leftover gamecard handle. */
gamecardCloseHandle();
if (R_FAILED(rc1)) LOGFILE("fsOpenGameCardStorage failed! (0x%08X).", rc1);
if (R_FAILED(rc2)) LOGFILE("fsDeviceOperatorGetGameCardHandle failed! (0x%08X).", rc2);
return false;
}
return true;
} }
NX_INLINE void gamecardCloseHandle(void) NX_INLINE void gamecardCloseHandle(void)
{ {
/* I need to find a way to properly close a gamecard handle... */
if (!g_gameCardHandle.value) return;
svcCloseHandle(g_gameCardHandle.value); svcCloseHandle(g_gameCardHandle.value);
g_gameCardHandle.value = 0; g_gameCardHandle.value = 0;
} }
@ -870,29 +873,20 @@ static bool gamecardOpenStorageArea(u8 area)
return false; return false;
} }
/* Return right away if a valid handle has already been retrieved and the desired gamecard storage area is currently open. */
if (g_gameCardHandle.value && serviceIsActive(&(g_gameCardStorage.s)) && g_gameCardStorageCurrentArea == area) return true; if (g_gameCardHandle.value && serviceIsActive(&(g_gameCardStorage.s)) && g_gameCardStorageCurrentArea == area) return true;
/* Close both gamecard handle and open storage area. */
gamecardCloseStorageArea(); gamecardCloseStorageArea();
Result rc = 0; /* Retrieve both a new gamecard handle and a storage area handle. */
u32 partition = (area - 1); /* Zero-based index. */ if (!gamecardGetHandleAndStorage(area - 1)) /* Zero-based index. */
/* Retrieve a new gamecard handle. */
if (!gamecardGetHandle())
{ {
LOGFILE("Failed to retrieve gamecard handle!"); LOGFILE("Failed to retrieve gamecard handle and storage area handle!");
return false;
}
/* Open storage area. */
rc = fsOpenGameCardStorage(&g_gameCardStorage, &g_gameCardHandle, partition);
if (R_FAILED(rc))
{
LOGFILE("fsOpenGameCardStorage failed to open %s storage area! (0x%08X).", GAMECARD_STORAGE_AREA_NAME(area), rc);
gamecardCloseHandle();
return false; return false;
} }
/* Update current gamecard storage area. */
g_gameCardStorageCurrentArea = area; g_gameCardStorageCurrentArea = area;
return true; return true;

View file

@ -177,6 +177,12 @@ typedef struct {
GameCardHeaderEncryptedArea encrypted_area; GameCardHeaderEncryptedArea encrypted_area;
} GameCardHeader; } GameCardHeader;
typedef enum {
GameCardStatus_NotInserted = 0,
GameCardStatus_InsertedAndInfoNotLoaded = 1, ///< Most likely related to the "nogc" patch being enabled. Means nothing at all can be done with the inserted gamecard.
GameCardStatus_InsertedAndInfoLoaded = 2
} GameCardStatus;
typedef enum { typedef enum {
GameCardHashFileSystemPartitionType_Root = 0, GameCardHashFileSystemPartitionType_Root = 0,
GameCardHashFileSystemPartitionType_Update = 1, GameCardHashFileSystemPartitionType_Update = 1,
@ -198,9 +204,8 @@ void gamecardExit(void);
/// If the gamecard interface hasn't been initialized, this returns NULL. /// If the gamecard interface hasn't been initialized, this returns NULL.
UEvent *gamecardGetStatusChangeUserEvent(void); UEvent *gamecardGetStatusChangeUserEvent(void);
/// Used to check if a gamecard has been inserted and if info could be loaded from it (e.g. physical storage access is possible). /// Returns the current GameCardStatus value.
/// If this call returns false, it pretty much means nothing can be done with the inserted gamecard. u8 gamecardGetStatus(void);
bool gamecardIsReady(void);
/// Used to read data from the inserted gamecard. /// Used to read data from the inserted gamecard.
/// All required handles, changes between normal <-> secure storage areas and proper offset calculations are managed internally. /// All required handles, changes between normal <-> secure storage areas and proper offset calculations are managed internally.

View file

@ -29,6 +29,8 @@
#include "usb.h" #include "usb.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#define LOGFILE_PATH "./nxdumptool.log"
/* Global variables. */ /* Global variables. */
static bool g_resourcesInitialized = false; static bool g_resourcesInitialized = false;

View file

@ -38,7 +38,6 @@
#include <switch.h> #include <switch.h>
#define APP_BASE_PATH "sdmc:/switch/nxdumptool/" #define APP_BASE_PATH "sdmc:/switch/nxdumptool/"
#define LOGFILE_PATH APP_BASE_PATH "nxdumptool.log"
#define MEMBER_SIZE(type, member) sizeof(((type*)NULL)->member) #define MEMBER_SIZE(type, member) sizeof(((type*)NULL)->member)