mirror of
https://github.com/DarkMatterCore/nxdumptool.git
synced 2024-11-22 10:16:39 +00:00
Hash FS start.
This commit is contained in:
parent
d3ad9d84b6
commit
9679eb72bb
8 changed files with 164 additions and 58 deletions
|
@ -50,9 +50,10 @@ typedef enum {
|
|||
} GameCardStorageArea;
|
||||
|
||||
typedef struct {
|
||||
u64 offset; ///< Relative to the start of the gamecard header.
|
||||
u64 size; ///< Whole partition size.
|
||||
u8 *header; ///< GameCardHashFileSystemHeader + GameCardHashFileSystemEntry + Name Table.
|
||||
u64 offset; ///< Relative to the start of the gamecard header.
|
||||
u64 size; ///< Whole partition size.
|
||||
u64 header_size; ///< Full header size.
|
||||
u8 *header; ///< GameCardHashFileSystemHeader + GameCardHashFileSystemEntry + Name Table.
|
||||
} GameCardHashFileSystemPartitionInfo;
|
||||
|
||||
/* Global variables. */
|
||||
|
@ -100,8 +101,12 @@ static void gamecardCloseStorageArea(void);
|
|||
static bool gamecardGetStorageAreasSizes(void);
|
||||
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. */
|
||||
/* 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);
|
||||
|
||||
bool gamecardIsReady(void)
|
||||
|
@ -217,15 +222,52 @@ bool gamecardGetBundledFirmwareUpdateVersion(u32 *out)
|
|||
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 */
|
||||
for(u32 i = 0; i < fs_header->entry_count; i++)
|
||||
{
|
||||
fs_entry = (GameCardHashFileSystemEntry*)(g_gameCardHfsRootHeader + sizeof(GameCardHashFileSystemHeader) + (i * sizeof(GameCardHashFileSystemEntry)));
|
||||
|
||||
if (!fs_entry->size)
|
||||
fs_entry = gamecardGetHashFileSystemEntryByIndex(g_gameCardHfsRootHeader, i);
|
||||
if (!fs_entry || !fs_entry->size)
|
||||
{
|
||||
LOGFILE("Invalid size for hash FS partition #%u!", i);
|
||||
LOGFILE("Invalid hash FS partition entry!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -552,11 +593,12 @@ static void gamecardLoadInfo(void)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Calculate the full header size for the current hash FS partition */
|
||||
u64 partition_header_size = (sizeof(GameCardHashFileSystemHeader) + (partition_header.entry_count * sizeof(GameCardHashFileSystemEntry)) + partition_header.name_table_size);
|
||||
/* Calculate the full header size for the current hash FS partition and round it to a GAMECARD_MEDIA_UNIT_SIZE bytes boundary */
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
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);
|
||||
goto out;
|
||||
|
@ -862,3 +904,25 @@ static inline u64 gamecardGetCapacityFromRomSizeValue(u8 rom_size)
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -155,4 +155,6 @@ bool gamecardGetRomCapacity(u64 *out); ///< Not the same as gamecardGetTotalSize
|
|||
bool gamecardGetCertificate(FsGameCardCertificate *out);
|
||||
bool gamecardGetBundledFirmwareUpdateVersion(u32 *out);
|
||||
|
||||
bool gamecardGetHashFileSystemEntryDataOffsetByName(u32 hfs_partition_idx, const char *name, u64 *out_offset);
|
||||
|
||||
#endif /* __GAMECARD_H__ */
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define SEGMENT_RODATA BIT(1)
|
||||
#define SEGMENT_DATA BIT(2)
|
||||
|
||||
/* Type definitions. */
|
||||
|
||||
typedef struct {
|
||||
u64 program_id;
|
||||
u8 mask;
|
||||
|
@ -69,6 +71,8 @@ typedef struct {
|
|||
u8 key_area_keys[0x20][3][0x10]; ///< Key area encryption keys.
|
||||
} keysNcaKeyset;
|
||||
|
||||
/* Global variables. */
|
||||
|
||||
static keysNcaKeyset g_ncaKeyset = {0};
|
||||
|
||||
static keysMemoryInfo g_fsRodataMemoryInfo = {
|
||||
|
@ -130,6 +134,8 @@ static keysMemoryInfo g_fsDataMemoryInfo = {
|
|||
}
|
||||
};
|
||||
|
||||
/* Function prototypes. */
|
||||
|
||||
static bool keysRetrieveDebugHandleFromProcessByProgramId(Handle *out, u64 program_id);
|
||||
static bool keysRetrieveProcessMemory(keysMemoryLocation *location);
|
||||
static void keysFreeProcessMemory(keysMemoryLocation *location);
|
||||
|
|
|
@ -65,6 +65,7 @@ int main(int argc, char *argv[])
|
|||
FsGameCardCertificate cert = {0};
|
||||
u64 total_size = 0, trimmed_size = 0;
|
||||
u32 update_version = 0;
|
||||
u64 nca_offset = 0;
|
||||
|
||||
if (gamecardGetHeader(&header))
|
||||
{
|
||||
|
@ -167,6 +168,15 @@ int main(int argc, char *argv[])
|
|||
|
||||
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);
|
||||
consoleExit(NULL);
|
||||
|
||||
|
|
|
@ -265,7 +265,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
u8 storage_id; ///< NcmStorageId.
|
||||
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.
|
||||
char id_str[0x21];
|
||||
u8 hash[0x20];
|
||||
|
|
|
@ -51,13 +51,13 @@ static ServicesInfoEntry g_serviceInfo[] = {
|
|||
{ false, "ns", NULL, &nsInitialize, &nsExit },
|
||||
{ false, "csrng", NULL, &csrngInitialize, &csrngExit },
|
||||
{ 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, "pl", NULL, &plInitialize, &plExit },
|
||||
{ false, "psm", NULL, &psmInitialize, &psmExit },
|
||||
{ false, "nifm:u", NULL, &servicesNifmUserInitialize, &nifmExit },
|
||||
{ false, "clk", &servicesClkGetServiceType, NULL, NULL }, /* Placeholder for pcv / clkrst */
|
||||
{ false, "fsp-usb", &servicesFspUsbCheckAvailability, &fspusbInitialize, &fspusbExit }, /* Checks if fsp-usb is really available */
|
||||
{ false, "clk", &servicesClkGetServiceType, NULL, NULL }, /* Placeholder for pcv / clkrst */
|
||||
{ false, "fsp-usb", &servicesFspUsbCheckAvailability, &fspusbInitialize, &fspusbExit }, /* Checks if fsp-usb is really available */
|
||||
{ false, "es", NULL, &esInitialize, &esExit },
|
||||
{ false, "set:cal", NULL, &setcalInitialize, &setcalExit }
|
||||
};
|
||||
|
@ -92,7 +92,7 @@ bool servicesInitialize(void)
|
|||
rc = g_serviceInfo[i].init_func();
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -22,18 +22,23 @@
|
|||
|
||||
//#include "freetype_helper.h"
|
||||
//#include "lvgl_helper.h"
|
||||
#include "services.h"
|
||||
#include "keys.h"
|
||||
#include "gamecard.h"
|
||||
#include "services.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* Global variables. */
|
||||
|
||||
static u8 g_customFirmwareType = UtilsCustomFirmwareType_Unknown;
|
||||
|
||||
static AppletHookCookie g_systemOverclockCookie = {0};
|
||||
|
||||
static Mutex g_logfileMutex = 0;
|
||||
|
||||
/* Function prototypes. */
|
||||
|
||||
static void _utilsGetCustomFirmwareType(void);
|
||||
|
||||
static void utilsOverclockSystemAppletHook(AppletHookType hook, void *param);
|
||||
|
||||
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, ...)
|
||||
{
|
||||
mutexLock(&g_logfileMutex);
|
||||
|
@ -122,8 +111,19 @@ void utilsOverclockSystem(bool restore)
|
|||
|
||||
bool utilsInitializeResources(void)
|
||||
{
|
||||
/* Initialize all needed services */
|
||||
if (!servicesInitialize()) return false;
|
||||
/* Initialize needed services */
|
||||
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 */
|
||||
//if (!freeTypeHelperInitialize()) return false;
|
||||
|
@ -131,17 +131,20 @@ bool utilsInitializeResources(void)
|
|||
/* Initialize LVGL */
|
||||
//if (!lvglHelperInitialize()) return false;
|
||||
|
||||
/* Retrieve custom firmware type */
|
||||
_utilsGetCustomFirmwareType();
|
||||
|
||||
/* Overclock system */
|
||||
utilsOverclockSystem(false);
|
||||
|
||||
/* Setup an applet hook to change the hardware clocks after a system mode change (docked <-> undocked) */
|
||||
appletHook(&g_systemOverclockCookie, utilsOverclockSystemAppletHook, NULL);
|
||||
|
||||
/* Initialize gamecard */
|
||||
/* Initialize gamecard interface */
|
||||
Result rc = gamecardInitialize();
|
||||
if (R_FAILED(rc))
|
||||
{
|
||||
utilsConsoleErrorScreen("gamecard fail\n");
|
||||
LOGFILE("Failed to initialize gamecard interface!");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -150,7 +153,7 @@ bool utilsInitializeResources(void)
|
|||
|
||||
void utilsCloseResources(void)
|
||||
{
|
||||
/* Deinitialize gamecard */
|
||||
/* Deinitialize gamecard interface */
|
||||
gamecardExit();
|
||||
|
||||
/* Unset our overclock applet hook */
|
||||
|
@ -169,6 +172,31 @@ void utilsCloseResources(void)
|
|||
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)
|
||||
{
|
||||
(void)param;
|
||||
|
|
|
@ -36,9 +36,10 @@
|
|||
|
||||
|
||||
typedef enum {
|
||||
UtilsCustomFirmwareType_Atmosphere = 0,
|
||||
UtilsCustomFirmwareType_SXOS = 1,
|
||||
UtilsCustomFirmwareType_ReiNX = 2
|
||||
UtilsCustomFirmwareType_Unknown = 0,
|
||||
UtilsCustomFirmwareType_Atmosphere = 1,
|
||||
UtilsCustomFirmwareType_SXOS = 2,
|
||||
UtilsCustomFirmwareType_ReiNX = 3
|
||||
} UtilsCustomFirmwareType;
|
||||
|
||||
typedef struct {
|
||||
|
@ -56,8 +57,6 @@ u64 utilsHidKeysAllHeld(void);
|
|||
|
||||
void utilsWaitForButtonPress(void);
|
||||
|
||||
void utilsConsoleErrorScreen(const char *fmt, ...);
|
||||
|
||||
void utilsWriteLogMessage(const char *func_name, const char *fmt, ...);
|
||||
|
||||
void utilsOverclockSystem(bool restore);
|
||||
|
@ -65,6 +64,8 @@ void utilsOverclockSystem(bool restore);
|
|||
bool utilsInitializeResources(void);
|
||||
void utilsCloseResources(void);
|
||||
|
||||
u8 utilsGetCustomFirmwareType(void); ///< UtilsCustomFirmwareType.
|
||||
|
||||
|
||||
|
||||
static inline FsStorage *utilsGetEmmcBisSystemStorage(void)
|
||||
|
@ -72,11 +73,6 @@ static inline FsStorage *utilsGetEmmcBisSystemStorage(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline u8 utilsGetCustomFirmwareType(void)
|
||||
{
|
||||
return UtilsCustomFirmwareType_Atmosphere;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* __UTILS_H__ */
|
||||
|
|
Loading…
Reference in a new issue