1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-08 11:51:48 +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;
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);
}

View file

@ -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__ */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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__ */