Loader: Button override + first-class HBL support

This commit is contained in:
Michael Scire 2018-09-19 16:21:46 -07:00
parent d8391078c8
commit 6afbcd12d9
11 changed files with 692 additions and 35 deletions

View file

@ -19,8 +19,10 @@
#include <cstdio>
#include "ldr_npdm.hpp"
#include "ldr_registration.hpp"
#include "ldr_content_management.hpp"
static NpdmUtils::NpdmCache g_npdm_cache = {0};
static NpdmUtils::NpdmCache g_original_npdm_cache = {0};
static char g_npdm_path[FS_MAX_PATH] = {0};
Result NpdmUtils::LoadNpdmFromCache(u64 tid, NpdmInfo *out) {
@ -31,6 +33,12 @@ Result NpdmUtils::LoadNpdmFromCache(u64 tid, NpdmInfo *out) {
return 0;
}
FILE *NpdmUtils::OpenNpdmFromHBL() {
std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0);
snprintf(g_npdm_path, FS_MAX_PATH, "hbl:/main.npdm");
return fopen(g_npdm_path, "rb");
}
FILE *NpdmUtils::OpenNpdmFromExeFS() {
std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0);
snprintf(g_npdm_path, FS_MAX_PATH, "code:/main.npdm");
@ -45,20 +53,23 @@ FILE *NpdmUtils::OpenNpdmFromSdCard(u64 title_id) {
FILE *NpdmUtils::OpenNpdm(u64 title_id) {
FILE *f_out = OpenNpdmFromSdCard(title_id);
if (f_out != NULL) {
return f_out;
if (ContentManagement::ShouldOverrideContents()) {
if (ContentManagement::ShouldReplaceWithHBL(title_id)) {
return OpenNpdmFromHBL();
}
FILE *f_out = OpenNpdmFromSdCard(title_id);
if (f_out != NULL) {
return f_out;
}
}
return OpenNpdmFromExeFS();
}
Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
Result NpdmUtils::LoadNpdmInternal(FILE *f_npdm, NpdmUtils::NpdmCache *cache) {
Result rc;
g_npdm_cache.info = (const NpdmUtils::NpdmInfo){0};
FILE *f_npdm = OpenNpdm(tid);
cache->info = (const NpdmUtils::NpdmInfo){0};
rc = 0x202;
if (f_npdm == NULL) {
/* For generic "Couldn't open the file" error, just say the file doesn't exist. */
@ -70,7 +81,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
fseek(f_npdm, 0, SEEK_SET);
rc = 0x609;
if ((npdm_size > sizeof(g_npdm_cache.buffer)) || (fread(g_npdm_cache.buffer, 1, npdm_size, f_npdm) != npdm_size)) {
if ((npdm_size > sizeof(cache->buffer)) || (fread(cache->buffer, 1, npdm_size, f_npdm) != npdm_size)) {
fclose(f_npdm);
return rc;
}
@ -83,8 +94,8 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
}
/* For ease of access... */
g_npdm_cache.info.header = (NpdmUtils::NpdmHeader *)(g_npdm_cache.buffer);
NpdmInfo *info = &g_npdm_cache.info;
cache->info.header = (NpdmUtils::NpdmHeader *)(cache->buffer);
NpdmInfo *info = &cache->info;
if (info->header->magic != MAGIC_META) {
return rc;
@ -98,7 +109,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
return rc;
}
info->aci0 = (NpdmAci0 *)(g_npdm_cache.buffer + info->header->aci0_offset);
info->aci0 = (NpdmAci0 *)(cache->buffer + info->header->aci0_offset);
if (info->aci0->magic != MAGIC_ACI0) {
return rc;
@ -126,7 +137,7 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
return rc;
}
info->acid = (NpdmAcid *)(g_npdm_cache.buffer + info->header->acid_offset);
info->acid = (NpdmAcid *)(cache->buffer + info->header->acid_offset);
if (info->acid->magic != MAGIC_ACID) {
return rc;
@ -152,7 +163,48 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
info->acid_kac = (void *)((uintptr_t)info->acid + info->acid->kac_offset);
rc = 0;
return rc;
}
Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
Result rc;
rc = LoadNpdmInternal(OpenNpdm(tid), &g_npdm_cache);
if (R_FAILED(rc)) {
return rc;
}
NpdmInfo *info = &g_npdm_cache.info;
/* Override the ACID/ACI0 title ID, in order to facilitate HBL takeover of any title. */
info->acid->title_id_range_min = tid;
info->acid->title_id_range_max = tid;
info->aci0->title_id = tid;
if (ContentManagement::ShouldOverrideContents() && ContentManagement::ShouldReplaceWithHBL(tid)
&& R_SUCCEEDED(LoadNpdmInternal(OpenNpdmFromExeFS(), &g_original_npdm_cache))) {
NpdmInfo *original_info = &g_original_npdm_cache.info;
/* Fix pool partition. */
if (kernelAbove500()) {
info->acid->flags = (info->acid->flags & 0xFFFFFFF9) | (original_info->acid->flags & 0x00000006);
}
/* Fix application type. */
const u32 original_application_type = GetApplicationType((u32 *)original_info->aci0_kac, original_info->aci0->kac_size/sizeof(u32)) & 7;
u32 *caps = (u32 *)info->aci0_kac;
for (unsigned int i = 0; i < info->aci0->kac_size/sizeof(u32); i++) {
if ((caps[i] & 0x3FFF) == 0x1FFF) {
caps[i] = (caps[i] & 0xFFFE3FFF) | (original_application_type << 14);
}
}
caps = (u32 *)info->acid_kac;
for (unsigned int i = 0; i < info->acid->kac_size/sizeof(u32); i++) {
if ((caps[i] & 0x3FFF) == 0x1FFF) {
caps[i] = (caps[i] & 0xFFFE3FFF) | (original_application_type << 14);
}
}
}
/* We validated! */
info->title_id = tid;
*out = *info;