Rewritten support file handling

Support files are now also accepted from CTRNAND.
This commit is contained in:
d0k3 2017-12-11 02:47:29 +01:00
parent d8521dfdb9
commit 1a63575caa
7 changed files with 124 additions and 61 deletions

View File

@ -34,10 +34,7 @@
#define STATIC_ASSERT(...) \
_Static_assert((__VA_ARGS__), #__VA_ARGS__)
// input / output paths
#define SUPPORT_PATH "0:/gm9/support"
#define SCRIPT_PATH "0:/gm9/scripts"
#define PAYLOAD_PATH "0:/gm9/payloads"
// standard output path (support file paths are in support.h)
#define OUTPUT_PATH "0:/gm9/out"
// buffer area defines (in use by godmode.c)

View File

@ -2,7 +2,7 @@
#include "aes.h"
#include "sha.h"
#include "ff.h"
#include "vram0.h"
#include "support.h"
typedef struct {
u8 slot; // keyslot, 0x00...0x39
@ -120,19 +120,7 @@ u32 LoadKeyDb(const char* path_db, AesKeyInfo* keydb, u32 bsize) {
fsize = 0;
f_close(&fp);
}
} else {
// check for hardcoded key database
u64 aeskeydb_bin_size = 0;
void* aeskeydb_bin = FindVTarFileInfo(KEYDB_NAME, &aeskeydb_bin_size);
fsize = (aeskeydb_bin_size <= bsize) ? aeskeydb_bin_size : 0;
if (fsize) memcpy(keydb, aeskeydb_bin, aeskeydb_bin_size);
// try to load aeskeydb.bin file
if (f_open(&fp, SUPPORT_PATH "/" KEYDB_NAME, FA_READ | FA_OPEN_EXISTING) == FR_OK) {
if ((f_read(&fp, keydb, bsize, &fsize) != FR_OK) || (fsize >= bsize)) fsize = 0;
f_close(&fp);
}
}
} else fsize = LoadSupportFile(KEYDB_NAME, keydb, bsize); // load key database support file
u32 nkeys = 0;
if (fsize && !(fsize % sizeof(AesKeyInfo)))
@ -173,15 +161,10 @@ u32 LoadKeyFromFile(void* key, u32 keyslot, char type, char* id)
// load legacy slot0x??Key?.bin file instead
if (!found && (type != 'I')) {
char path[64];
FIL fp;
UINT btr;
snprintf(path, 64, "%s/slot0x%02lXKey%s%s.bin", SUPPORT_PATH, keyslot,
char fname[64];
snprintf(fname, 64, "slot0x%02lXKey%s%s.bin", keyslot,
(type == 'X') ? "X" : (type == 'Y') ? "Y" : (type == 'I') ? "IV" : "", (id) ? id : "");
if (f_open(&fp, path, FA_READ | FA_OPEN_EXISTING) == FR_OK) {
found = ((f_read(&fp, key, 16, &btr) == FR_OK) && (btr == 16));
f_close(&fp);
}
found = (LoadSupportFile(fname, key, 16) == 16);
}
// key still not found (duh)
@ -254,7 +237,7 @@ u32 InitKeyDb(const char* path)
u32 CheckRecommendedKeyDb(const char* path)
{
// SHA-256 of the reommended aeskeydb.bin file
// SHA-256 of the recommended aeskeydb.bin file
// equals MD5 A5B28945A7C051D7A0CD18AF0E580D1B
const u8 recommended_sha[0x20] = {
0x40, 0x76, 0x54, 0x3D, 0xA3, 0xFF, 0x91, 0x1C, 0xE1, 0xCC, 0x4E, 0xC7, 0x2F, 0x92, 0xE4, 0xB7,

View File

@ -0,0 +1,75 @@
#include "support.h"
#include "fsutil.h" // only for file selector
#include "vram0.h"
#include "vff.h"
#define SUPPORT_FILE_PATHS "0:/gm9/support", "1:/gm9/support" // we also check the VRAM TAR first
#define SUPPORT_DIR_PATHS "V:", "0:/gm9", "1:/gm9"
bool CheckSupportFile(const char* fname)
{
// try VRAM0 first
if (FindVTarFileInfo(fname, NULL))
return true;
// try support file paths
const char* base_paths[] = { SUPPORT_FILE_PATHS };
for (u32 i = 0; i < countof(base_paths); i++) {
char path[256];
snprintf(path, 256, "%s/%s", base_paths[i], fname);
if (fvx_stat(path, NULL) == FR_OK)
return true;
}
return false;
}
size_t LoadSupportFile(const char* fname, void* buffer, size_t max_len)
{
// try VRAM0 first
u64 len64 = 0;
void* data = FindVTarFileInfo(fname, &len64);
if (data && len64 && (len64 < max_len)) {
memcpy(buffer, data, len64);
return (size_t) len64;
}
// try support file paths
const char* base_paths[] = { SUPPORT_FILE_PATHS };
for (u32 i = 0; i < countof(base_paths); i++) {
UINT len32;
char path[256];
snprintf(path, 256, "%s/%s", base_paths[i], fname);
if (fvx_qread(path, buffer, 0, max_len, &len32) == FR_OK)
return len32;
}
return 0;
}
bool GetSupportDir(char* path, const char* dname)
{
const char* base_paths[] = { SUPPORT_DIR_PATHS };
for (u32 i = 0; i < countof(base_paths); i++) {
FILINFO fno;
snprintf(path, 256, "%s/%s", base_paths[i], dname);
if ((fvx_stat(path, &fno) == FR_OK) && (fno.fattrib & AM_DIR))
return true;
}
return false;
}
bool CheckSupportDir(const char* dname)
{
char path[256];
return GetSupportDir(path, dname);
}
bool FileSelectorSupport(char* result, const char* text, const char* dname, const char* pattern, bool hide_ext, bool no_dirs)
{
char path[256];
if (!GetSupportDir(path, dname)) return false;
return FileSelector(result, text, path, pattern, hide_ext, no_dirs);
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "common.h"
// scripts / payloads dir names
#define SCRIPTS_DIR "scripts"
#define PAYLOADS_DIR "payloads"
bool CheckSupportFile(const char* fname);
size_t LoadSupportFile(const char* fname, void* buffer, size_t max_len);
bool CheckSupportDir(const char* fpath);
bool FileSelectorSupport(char* result, const char* text, const char* dname, const char* pattern, bool hide_ext, bool no_dirs);

View File

@ -1,4 +1,5 @@
#include "ncch.h"
#include "support.h"
#include "keydb.h"
#include "aes.h"
#include "sha.h"
@ -53,10 +54,6 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
static u8 lseed[16+8] = { 0 }; // seed plus title ID for easy validation
u64 titleId = ncch->programId;
u32 hash_seed = ncch->hash_seed;
UINT btr = 0;
FIL file;
char path[128];
u32 sha256sum[8];
memcpy(lseed+16, &(ncch->programId), 8);
@ -69,7 +66,11 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
// try to grab the seed from NAND database
const u32 seed_offset[2] = {SEEDSAVE_AREA_OFFSETS};
const char* nand_drv[] = {"1:", "4:"}; // SysNAND and EmuNAND
for (u32 i = 0; i < (sizeof(nand_drv)/sizeof(char*)); i++) {
for (u32 i = 0; i < countof(nand_drv); i++) {
UINT btr = 0;
FIL file;
char path[128];
// grab the key Y from movable.sed
u8 movable_keyy[16];
snprintf(path, 128, "%s/private/movable.sed", nand_drv[i]);
@ -118,11 +119,9 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
}
// not found -> try seeddb.bin
if (f_open(&file, SUPPORT_PATH "/" SEEDDB_NAME, FA_READ | FA_OPEN_EXISTING) == FR_OK) {
SeedInfo* seeddb = (SeedInfo*) (TEMP_BUFFER + (TEMP_BUFFER_SIZE/2));
f_read(&file, seeddb, TEMP_BUFFER_SIZE / 2, &btr);
f_close(&file);
if (seeddb->n_entries <= (btr - 16) / 32) { // check filesize / seeddb size
size_t len = LoadSupportFile(SEEDDB_NAME, seeddb, (TEMP_BUFFER_SIZE/2));
if (len && (seeddb->n_entries <= (len - 16) / 32)) { // check filesize / seeddb size
for (u32 s = 0; s < seeddb->n_entries; s++) {
if (titleId != seeddb->entries[s].titleId)
continue;
@ -134,7 +133,6 @@ u32 GetNcchSeed(u8* seed, NcchHeader* ncch) {
}
}
}
}
// out of options -> failed!
return 1;

View File

@ -1,4 +1,5 @@
#include "ticket.h"
#include "support.h"
#include "unittype.h"
#include "aes.h"
#include "sha.h"
@ -106,15 +107,10 @@ u32 FindTitleKey(Ticket* ticket, u8* title_id) {
// when found, add it to the ticket
for (u32 enc = 0; (enc <= 1) && !found; enc++) {
TitleKeysInfo* tikdb = (TitleKeysInfo*) (TEMP_BUFFER + (TEMP_BUFFER_SIZE/2));
const char* path = (enc) ? SUPPORT_PATH "/" TIKDB_NAME_ENC : SUPPORT_PATH "/" TIKDB_NAME_DEC;
FIL file;
UINT btr;
u32 len = LoadSupportFile((enc) ? TIKDB_NAME_ENC : TIKDB_NAME_DEC, tikdb, (TEMP_BUFFER_SIZE/2));
if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK)
continue;
f_read(&file, tikdb, TEMP_BUFFER_SIZE / 2, &btr);
f_close(&file);
if (tikdb->n_entries > (btr - 16) / 32)
if (len == 0) continue; // file not found
if (tikdb->n_entries > (len - 16) / 32)
continue; // filesize / titlekey db size mismatch
for (u32 t = 0; t < tikdb->n_entries; t++) {
TitleKeyEntry* tik = tikdb->entries + t;

View File

@ -1,4 +1,5 @@
#include "godmode.h"
#include "support.h"
#include "ui.h"
#include "hid.h"
#include "fs.h"
@ -1843,9 +1844,9 @@ u32 GodMode(int entrypoint) {
bootloader = true;
} else if (user_select == 2) {
godmode9 = true;
} else if ((user_select == 3) && (FileSelector(loadpath, "Bootloader payloads menu.\nSelect payload:", PAYLOAD_PATH, "*.firm", true, false))) {
} else if ((user_select == 3) && (FileSelectorSupport(loadpath, "Bootloader payloads menu.\nSelect payload:", PAYLOADS_DIR, "*.firm", true, false))) {
BootFirmHandler(loadpath, false, false);
} else if ((user_select == 4) && (FileSelector(loadpath, "Bootloader scripts menu.\nSelect script:", SCRIPT_PATH, "*.gm9", true, false))) {
} else if ((user_select == 4) && (FileSelectorSupport(loadpath, "Bootloader scripts menu.\nSelect script:", SCRIPTS_DIR, "*.gm9", true, false))) {
ExecuteGM9Script(loadpath);
} else if (user_select == 5) {
exit_mode = GODMODE_EXIT_POWEROFF;
@ -2228,8 +2229,8 @@ u32 GodMode(int entrypoint) {
u32 n_opt = 0;
int poweroff = ++n_opt;
int reboot = ++n_opt;
int scripts = (PathExist(SCRIPT_PATH)) ? (int) ++n_opt : -1;
int payloads = (PathExist(PAYLOAD_PATH)) ? (int) ++n_opt : -1;
int scripts = (CheckSupportDir(SCRIPTS_DIR)) ? (int) ++n_opt : -1;
int payloads = (CheckSupportDir(PAYLOADS_DIR)) ? (int) ++n_opt : -1;
int more = ++n_opt;
if (poweroff > 0) optionstr[poweroff - 1] = "Poweroff system";
if (reboot > 0) optionstr[reboot - 1] = "Reboot system";
@ -2242,12 +2243,12 @@ u32 GodMode(int entrypoint) {
(user_select != poweroff) && (user_select != reboot)) {
char loadpath[256];
if ((user_select == more) && (HomeMoreMenu(current_path) == 0)) break; // more... menu
else if ((user_select == scripts) && (FileSelector(loadpath, "HOME scripts... menu.\nSelect script:", SCRIPT_PATH, "*.gm9", true, false))) {
else if ((user_select == scripts) && (FileSelectorSupport(loadpath, "HOME scripts... menu.\nSelect script:", SCRIPTS_DIR, "*.gm9", true, false))) {
ExecuteGM9Script(loadpath);
GetDirContents(current_dir, current_path);
ClearScreenF(true, true, COLOR_STD_BG);
break;
} else if ((user_select == payloads) && (FileSelector(loadpath, "HOME payloads... menu.\nSelect payload:", PAYLOAD_PATH, "*.firm", true, false))) {
} else if ((user_select == payloads) && (FileSelectorSupport(loadpath, "HOME payloads... menu.\nSelect payload:", PAYLOADS_DIR, "*.firm", true, false))) {
BootFirmHandler(loadpath, false, false);
}
}