1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-26 12:12:02 +00:00

Hash FS start.

This commit is contained in:
Pablo Curiel 2020-04-16 06:13:11 -04:00
parent d3ad9d84b6
commit 9679eb72bb
8 changed files with 164 additions and 58 deletions

View file

@ -50,9 +50,10 @@ typedef enum {
} GameCardStorageArea; } GameCardStorageArea;
typedef struct { typedef struct {
u64 offset; ///< Relative to the start of the gamecard header. u64 offset; ///< Relative to the start of the gamecard header.
u64 size; ///< Whole partition size. u64 size; ///< Whole partition size.
u8 *header; ///< GameCardHashFileSystemHeader + GameCardHashFileSystemEntry + Name Table. u64 header_size; ///< Full header size.
u8 *header; ///< GameCardHashFileSystemHeader + GameCardHashFileSystemEntry + Name Table.
} GameCardHashFileSystemPartitionInfo; } GameCardHashFileSystemPartitionInfo;
/* Global variables. */ /* Global variables. */
@ -100,8 +101,12 @@ static void gamecardCloseStorageArea(void);
static bool gamecardGetStorageAreasSizes(void); static bool gamecardGetStorageAreasSizes(void);
static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size); static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size);
static inline GameCardHashFileSystemHeader *gamecardGetHashFileSystemPartitionHeaderByIndex(u32 idx);
static inline GameCardHashFileSystemEntry *gamecardGetHashFileSystemEntryByIndex(void *hfs_header, u32 idx);
static inline char *gamecardGetHashFileSystemEntryName(void *hfs_header, u32 name_offset);
/* Service guard used to generate thread-safe initialize + exit functions. */ /* 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. */ /* I'm using this here even though this actually isn't a real service but who cares, it gets the job done. */
NX_GENERATE_SERVICE_GUARD(gamecard); NX_GENERATE_SERVICE_GUARD(gamecard);
bool gamecardIsReady(void) bool gamecardIsReady(void)
@ -217,15 +222,52 @@ bool gamecardGetBundledFirmwareUpdateVersion(u32 *out)
return ret; return ret;
} }
bool gamecardGetHashFileSystemEntryDataOffsetByName(u32 hfs_partition_idx, const char *name, u64 *out_offset)
{
bool ret = false;
char *entry_name = NULL;
size_t name_len = 0;
GameCardHashFileSystemHeader *fs_header = NULL;
GameCardHashFileSystemEntry *fs_entry = NULL;
mtx_lock(&g_gameCardSharedDataMutex);
if (!g_gameCardInserted || !g_gameCardInfoLoaded || !name || !*name || !out_offset)
{
LOGFILE("Invalid parameters!");
goto out;
}
name_len = strlen(name);
fs_header = gamecardGetHashFileSystemPartitionHeaderByIndex(hfs_partition_idx);
if (!fs_header)
{
LOGFILE("Invalid hash FS partition index! (0x%X)", hfs_partition_idx);
goto out;
}
for(u32 i = 0; i < fs_header->entry_count; i++)
{
fs_entry = gamecardGetHashFileSystemEntryByIndex(fs_header, i);
if (!fs_entry) continue;
entry_name = gamecardGetHashFileSystemEntryName(fs_header, fs_entry->name_offset);
if (!entry_name) continue;
if (!strncasecmp(entry_name, name, name_len))
{
*out_offset = (g_gameCardHfsPartitions[hfs_partition_idx].offset + g_gameCardHfsPartitions[hfs_partition_idx].header_size + fs_entry->offset);
ret = true;
break;
}
}
out:
mtx_unlock(&g_gameCardSharedDataMutex);
return ret;
}
@ -521,11 +563,10 @@ static void gamecardLoadInfo(void)
/* Read hash FS partitions */ /* Read hash FS partitions */
for(u32 i = 0; i < fs_header->entry_count; i++) for(u32 i = 0; i < fs_header->entry_count; i++)
{ {
fs_entry = (GameCardHashFileSystemEntry*)(g_gameCardHfsRootHeader + sizeof(GameCardHashFileSystemHeader) + (i * sizeof(GameCardHashFileSystemEntry))); fs_entry = gamecardGetHashFileSystemEntryByIndex(g_gameCardHfsRootHeader, i);
if (!fs_entry || !fs_entry->size)
if (!fs_entry->size)
{ {
LOGFILE("Invalid size for hash FS partition #%u!", i); LOGFILE("Invalid hash FS partition entry!");
goto out; goto out;
} }
@ -552,11 +593,12 @@ static void gamecardLoadInfo(void)
goto out; goto out;
} }
/* Calculate the full header size for the current hash FS partition */ /* Calculate the full header size for the current hash FS partition and round it to a GAMECARD_MEDIA_UNIT_SIZE bytes boundary */
u64 partition_header_size = (sizeof(GameCardHashFileSystemHeader) + (partition_header.entry_count * sizeof(GameCardHashFileSystemEntry)) + partition_header.name_table_size); g_gameCardHfsPartitions[i].header_size = (sizeof(GameCardHashFileSystemHeader) + (partition_header.entry_count * sizeof(GameCardHashFileSystemEntry)) + partition_header.name_table_size);
g_gameCardHfsPartitions[i].header_size = ROUND_UP(g_gameCardHfsPartitions[i].header_size, GAMECARD_MEDIA_UNIT_SIZE);
/* Allocate memory for the hash FS partition header */ /* Allocate memory for the hash FS partition header */
g_gameCardHfsPartitions[i].header = calloc(partition_header_size, sizeof(u8)); g_gameCardHfsPartitions[i].header = calloc(g_gameCardHfsPartitions[i].header_size, sizeof(u8));
if (!g_gameCardHfsPartitions[i].header) if (!g_gameCardHfsPartitions[i].header)
{ {
LOGFILE("Unable to allocate memory for the hash FS partition #%u header!", i); LOGFILE("Unable to allocate memory for the hash FS partition #%u header!", i);
@ -564,7 +606,7 @@ static void gamecardLoadInfo(void)
} }
/* Finally, read the full hash FS partition header */ /* Finally, read the full hash FS partition header */
if (!gamecardReadStorageArea(g_gameCardHfsPartitions[i].header, partition_header_size, g_gameCardHfsPartitions[i].offset, false)) if (!gamecardReadStorageArea(g_gameCardHfsPartitions[i].header, g_gameCardHfsPartitions[i].header_size, g_gameCardHfsPartitions[i].offset, false))
{ {
LOGFILE("Failed to read full hash FS partition #%u header from offset 0x%lX!", i, g_gameCardHfsPartitions[i].offset); LOGFILE("Failed to read full hash FS partition #%u header from offset 0x%lX!", i, g_gameCardHfsPartitions[i].offset);
goto out; goto out;
@ -862,3 +904,25 @@ static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size)
return capacity; return capacity;
} }
static inline GameCardHashFileSystemHeader *gamecardGetHashFileSystemPartitionHeaderByIndex(u32 idx)
{
if (idx >= ((GameCardHashFileSystemHeader*)g_gameCardHfsRootHeader)->entry_count) return NULL;
return (GameCardHashFileSystemHeader*)g_gameCardHfsPartitions[idx].header;
}
static inline GameCardHashFileSystemEntry *gamecardGetHashFileSystemEntryByIndex(void *hfs_header, u32 idx)
{
if (!hfs_header || idx >= ((GameCardHashFileSystemHeader*)hfs_header)->entry_count) return NULL;
return (GameCardHashFileSystemEntry*)((u8*)hfs_header + sizeof(GameCardHashFileSystemHeader) + (idx * sizeof(GameCardHashFileSystemEntry)));
}
static inline char *gamecardGetHashFileSystemEntryName(void *hfs_header, u32 name_offset)
{
if (!hfs_header) return NULL;
GameCardHashFileSystemHeader *header = (GameCardHashFileSystemHeader*)hfs_header;
if (!header->entry_count || name_offset >= header->name_table_size) return NULL;
return ((char*)hfs_header + sizeof(GameCardHashFileSystemHeader) + (header->entry_count * sizeof(GameCardHashFileSystemEntry)) + name_offset);
}

View file

@ -155,4 +155,6 @@ bool gamecardGetRomCapacity(u64 *out); ///< Not the same as gamecardGetTotalSize
bool gamecardGetCertificate(FsGameCardCertificate *out); bool gamecardGetCertificate(FsGameCardCertificate *out);
bool gamecardGetBundledFirmwareUpdateVersion(u32 *out); bool gamecardGetBundledFirmwareUpdateVersion(u32 *out);
bool gamecardGetHashFileSystemEntryDataOffsetByName(u32 hfs_partition_idx, const char *name, u64 *out_offset);
#endif /* __GAMECARD_H__ */ #endif /* __GAMECARD_H__ */

View file

@ -29,6 +29,8 @@
#define SEGMENT_RODATA BIT(1) #define SEGMENT_RODATA BIT(1)
#define SEGMENT_DATA BIT(2) #define SEGMENT_DATA BIT(2)
/* Type definitions. */
typedef struct { typedef struct {
u64 program_id; u64 program_id;
u8 mask; u8 mask;
@ -69,6 +71,8 @@ typedef struct {
u8 key_area_keys[0x20][3][0x10]; ///< Key area encryption keys. u8 key_area_keys[0x20][3][0x10]; ///< Key area encryption keys.
} keysNcaKeyset; } keysNcaKeyset;
/* Global variables. */
static keysNcaKeyset g_ncaKeyset = {0}; static keysNcaKeyset g_ncaKeyset = {0};
static keysMemoryInfo g_fsRodataMemoryInfo = { static keysMemoryInfo g_fsRodataMemoryInfo = {
@ -130,6 +134,8 @@ static keysMemoryInfo g_fsDataMemoryInfo = {
} }
}; };
/* Function prototypes. */
static bool keysRetrieveDebugHandleFromProcessByProgramId(Handle *out, u64 program_id); static bool keysRetrieveDebugHandleFromProcessByProgramId(Handle *out, u64 program_id);
static bool keysRetrieveProcessMemory(keysMemoryLocation *location); static bool keysRetrieveProcessMemory(keysMemoryLocation *location);
static void keysFreeProcessMemory(keysMemoryLocation *location); static void keysFreeProcessMemory(keysMemoryLocation *location);

View file

@ -65,6 +65,7 @@ int main(int argc, char *argv[])
FsGameCardCertificate cert = {0}; FsGameCardCertificate cert = {0};
u64 total_size = 0, trimmed_size = 0; u64 total_size = 0, trimmed_size = 0;
u32 update_version = 0; u32 update_version = 0;
u64 nca_offset = 0;
if (gamecardGetHeader(&header)) if (gamecardGetHeader(&header))
{ {
@ -167,6 +168,15 @@ int main(int argc, char *argv[])
consoleUpdate(NULL); consoleUpdate(NULL);
if (gamecardGetHashFileSystemEntryDataOffsetByName(2, "7e86768383cfabb30f1b58d2373fed07.nca", &nca_offset)) // Should match 0x1657F5E00
{
printf("nca_offset: 0x%lX\n", nca_offset);
} else {
printf("nca_offset failed\n");
}
consoleUpdate(NULL);
SLEEP(3); SLEEP(3);
consoleExit(NULL); consoleExit(NULL);

View file

@ -265,7 +265,7 @@ typedef struct {
typedef struct { typedef struct {
u8 storage_id; ///< NcmStorageId. u8 storage_id; ///< NcmStorageId.
NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data. NcmContentStorage *ncm_storage; ///< Pointer to a NcmContentStorage instance. Used to read NCA data.
u64 gc_secure_area_base_offset; ///< Used to read NCA data from a gamecard using a FsStorage instance when storage_id == NcmStorageId_GameCard. u64 gamecard_offset; ///< Used to read NCA data from a gamecard using a FsStorage instance when storage_id == NcmStorageId_GameCard.
NcmContentId id; ///< Also used to read NCA data. NcmContentId id; ///< Also used to read NCA data.
char id_str[0x21]; char id_str[0x21];
u8 hash[0x20]; u8 hash[0x20];

View file

@ -51,13 +51,13 @@ static ServicesInfoEntry g_serviceInfo[] = {
{ false, "ns", NULL, &nsInitialize, &nsExit }, { false, "ns", NULL, &nsInitialize, &nsExit },
{ false, "csrng", NULL, &csrngInitialize, &csrngExit }, { false, "csrng", NULL, &csrngInitialize, &csrngExit },
{ false, "spl", NULL, &splInitialize, &splExit }, { false, "spl", NULL, &splInitialize, &splExit },
{ false, "spl:mig", &servicesSplCryptoCheckAvailability, &splCryptoInitialize, &splCryptoExit }, /* Checks if spl:mig is really available (e.g. avoid calling splInitialize twice) */ { false, "spl:mig", &servicesSplCryptoCheckAvailability, &splCryptoInitialize, &splCryptoExit }, /* Checks if spl:mig is really available (e.g. avoid calling splInitialize twice) */
{ false, "pm:dmnt", NULL, &pmdmntInitialize, &pmdmntExit }, { false, "pm:dmnt", NULL, &pmdmntInitialize, &pmdmntExit },
{ false, "pl", NULL, &plInitialize, &plExit }, { false, "pl", NULL, &plInitialize, &plExit },
{ false, "psm", NULL, &psmInitialize, &psmExit }, { false, "psm", NULL, &psmInitialize, &psmExit },
{ false, "nifm:u", NULL, &servicesNifmUserInitialize, &nifmExit }, { false, "nifm:u", NULL, &servicesNifmUserInitialize, &nifmExit },
{ false, "clk", &servicesClkGetServiceType, NULL, NULL }, /* Placeholder for pcv / clkrst */ { false, "clk", &servicesClkGetServiceType, NULL, NULL }, /* Placeholder for pcv / clkrst */
{ false, "fsp-usb", &servicesFspUsbCheckAvailability, &fspusbInitialize, &fspusbExit }, /* Checks if fsp-usb is really available */ { false, "fsp-usb", &servicesFspUsbCheckAvailability, &fspusbInitialize, &fspusbExit }, /* Checks if fsp-usb is really available */
{ false, "es", NULL, &esInitialize, &esExit }, { false, "es", NULL, &esInitialize, &esExit },
{ false, "set:cal", NULL, &setcalInitialize, &setcalExit } { false, "set:cal", NULL, &setcalInitialize, &setcalExit }
}; };
@ -92,7 +92,7 @@ bool servicesInitialize(void)
rc = g_serviceInfo[i].init_func(); rc = g_serviceInfo[i].init_func();
if (R_FAILED(rc)) if (R_FAILED(rc))
{ {
utilsConsoleErrorScreen("%s: failed to initialize %s service! (0x%08X)", __func__, g_serviceInfo[i].name, rc); LOGFILE("Failed to initialize %s service! (0x%08X)", g_serviceInfo[i].name, rc);
ret = false; ret = false;
break; break;
} }

View file

@ -22,18 +22,23 @@
//#include "freetype_helper.h" //#include "freetype_helper.h"
//#include "lvgl_helper.h" //#include "lvgl_helper.h"
#include "services.h" #include "keys.h"
#include "gamecard.h" #include "gamecard.h"
#include "services.h"
#include "utils.h" #include "utils.h"
/* Global variables. */ /* Global variables. */
static u8 g_customFirmwareType = UtilsCustomFirmwareType_Unknown;
static AppletHookCookie g_systemOverclockCookie = {0}; static AppletHookCookie g_systemOverclockCookie = {0};
static Mutex g_logfileMutex = 0; static Mutex g_logfileMutex = 0;
/* Function prototypes. */ /* Function prototypes. */
static void _utilsGetCustomFirmwareType(void);
static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param); static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param);
u64 utilsHidKeysAllDown(void) u64 utilsHidKeysAllDown(void)
@ -71,22 +76,6 @@ void utilsWaitForButtonPress(void)
} }
} }
void utilsConsoleErrorScreen(const char *fmt, ...)
{
consoleInit(NULL);
va_list va;
va_start(va, fmt);
vprintf(fmt, va);
va_end(va);
printf("\nPress any button to exit.\n");
consoleUpdate(NULL);
utilsWaitForButtonPress();
consoleExit(NULL);
}
void utilsWriteLogMessage(const char *func_name, const char *fmt, ...) void utilsWriteLogMessage(const char *func_name, const char *fmt, ...)
{ {
mutexLock(&g_logfileMutex); mutexLock(&g_logfileMutex);
@ -122,8 +111,19 @@ void utilsOverclockSystem(bool restore)
bool utilsInitializeResources(void) bool utilsInitializeResources(void)
{ {
/* Initialize all needed services */ /* Initialize needed services */
if (!servicesInitialize()) return false; if (!servicesInitialize())
{
LOGFILE("Failed to initialize needed services!");
return false;
}
/* Load NCA keyset */
if (!keysLoadNcaKeyset())
{
LOGFILE("Failed to load NCA keyset!");
return false;
}
/* Initialize FreeType */ /* Initialize FreeType */
//if (!freeTypeHelperInitialize()) return false; //if (!freeTypeHelperInitialize()) return false;
@ -131,17 +131,20 @@ bool utilsInitializeResources(void)
/* Initialize LVGL */ /* Initialize LVGL */
//if (!lvglHelperInitialize()) return false; //if (!lvglHelperInitialize()) return false;
/* Retrieve custom firmware type */
_utilsGetCustomFirmwareType();
/* Overclock system */ /* Overclock system */
utilsOverclockSystem(false); utilsOverclockSystem(false);
/* Setup an applet hook to change the hardware clocks after a system mode change (docked <-> undocked) */ /* Setup an applet hook to change the hardware clocks after a system mode change (docked <-> undocked) */
appletHook(&g_systemOverclockCookie, utilsOverclockSystemAppletHook, NULL); appletHook(&g_systemOverclockCookie, utilsOverclockSystemAppletHook, NULL);
/* Initialize gamecard */ /* Initialize gamecard interface */
Result rc = gamecardInitialize(); Result rc = gamecardInitialize();
if (R_FAILED(rc)) if (R_FAILED(rc))
{ {
utilsConsoleErrorScreen("gamecard fail\n"); LOGFILE("Failed to initialize gamecard interface!");
return false; return false;
} }
@ -150,7 +153,7 @@ bool utilsInitializeResources(void)
void utilsCloseResources(void) void utilsCloseResources(void)
{ {
/* Deinitialize gamecard */ /* Deinitialize gamecard interface */
gamecardExit(); gamecardExit();
/* Unset our overclock applet hook */ /* Unset our overclock applet hook */
@ -169,6 +172,31 @@ void utilsCloseResources(void)
servicesClose(); servicesClose();
} }
u8 utilsGetCustomFirmwareType(void)
{
return g_customFirmwareType;
}
static void _utilsGetCustomFirmwareType(void)
{
bool tx_srv = servicesCheckRunningServiceByName("tx");
bool rnx_srv = servicesCheckRunningServiceByName("rnx");
if (!tx_srv && !rnx_srv)
{
/* Atmosphere */
g_customFirmwareType = UtilsCustomFirmwareType_Atmosphere;
} else
if (tx_srv && !rnx_srv)
{
/* SX OS */
g_customFirmwareType = UtilsCustomFirmwareType_SXOS;
} else {
/* ReiNX */
g_customFirmwareType = UtilsCustomFirmwareType_ReiNX;
}
}
static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param) static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param)
{ {
(void)param; (void)param;

View file

@ -36,9 +36,10 @@
typedef enum { typedef enum {
UtilsCustomFirmwareType_Atmosphere = 0, UtilsCustomFirmwareType_Unknown = 0,
UtilsCustomFirmwareType_SXOS = 1, UtilsCustomFirmwareType_Atmosphere = 1,
UtilsCustomFirmwareType_ReiNX = 2 UtilsCustomFirmwareType_SXOS = 2,
UtilsCustomFirmwareType_ReiNX = 3
} UtilsCustomFirmwareType; } UtilsCustomFirmwareType;
typedef struct { typedef struct {
@ -56,8 +57,6 @@ u64 utilsHidKeysAllHeld(void);
void utilsWaitForButtonPress(void); void utilsWaitForButtonPress(void);
void utilsConsoleErrorScreen(const char *fmt, ...);
void utilsWriteLogMessage(const char *func_name, const char *fmt, ...); void utilsWriteLogMessage(const char *func_name, const char *fmt, ...);
void utilsOverclockSystem(bool restore); void utilsOverclockSystem(bool restore);
@ -65,6 +64,8 @@ void utilsOverclockSystem(bool restore);
bool utilsInitializeResources(void); bool utilsInitializeResources(void);
void utilsCloseResources(void); void utilsCloseResources(void);
u8 utilsGetCustomFirmwareType(void); ///< UtilsCustomFirmwareType.
static inline FsStorage *utilsGetEmmcBisSystemStorage(void) static inline FsStorage *utilsGetEmmcBisSystemStorage(void)
@ -72,11 +73,6 @@ static inline FsStorage *utilsGetEmmcBisSystemStorage(void)
return NULL; return NULL;
} }
static inline u8 utilsGetCustomFirmwareType(void)
{
return UtilsCustomFirmwareType_Atmosphere;
}
#endif /* __UTILS_H__ */ #endif /* __UTILS_H__ */