mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-29 04:50:17 +00:00
loader: refactor for R_TRY
This commit is contained in:
parent
ee40dcd76f
commit
f9bf8923b1
24 changed files with 437 additions and 579 deletions
|
@ -67,7 +67,6 @@ static std::map<u64, ContentManagement::ExternalContentSource> g_external_conten
|
|||
|
||||
Result ContentManagement::MountCode(u64 tid, FsStorageId sid) {
|
||||
char path[FS_MAX_PATH] = {0};
|
||||
Result rc;
|
||||
|
||||
/* We defer SD card mounting, so if relevant ensure it is mounted. */
|
||||
if (!g_has_initialized_fs_dev) {
|
||||
|
@ -82,9 +81,7 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) {
|
|||
return ResultSuccess;
|
||||
}
|
||||
|
||||
if (R_FAILED(rc = ResolveContentPath(path, tid, sid))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(ResolveContentPath(path, tid, sid));
|
||||
|
||||
/* Fix up path. */
|
||||
for (unsigned int i = 0; i < FS_MAX_PATH && path[i] != '\x00'; i++) {
|
||||
|
@ -95,20 +92,17 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) {
|
|||
|
||||
/* Always re-initialize fsp-ldr, in case it's closed */
|
||||
DoWithSmSession([&]() {
|
||||
rc = fsldrInitialize();
|
||||
});
|
||||
if (R_FAILED(rc)) {
|
||||
return rc;
|
||||
if (R_FAILED(fsldrInitialize())) {
|
||||
std::abort();
|
||||
}
|
||||
});
|
||||
ON_SCOPE_EXIT { fsldrExit(); };
|
||||
|
||||
if (R_FAILED(rc = fsldrOpenCodeFileSystem(tid, path, &g_CodeFileSystem))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(fsldrOpenCodeFileSystem(tid, path, &g_CodeFileSystem));
|
||||
|
||||
fsdevMountDevice("code", g_CodeFileSystem);
|
||||
TryMountHblNspOnSd();
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result ContentManagement::UnmountCode() {
|
||||
|
@ -139,14 +133,12 @@ void ContentManagement::TryMountHblNspOnSd() {
|
|||
Result ContentManagement::MountCodeNspOnSd(u64 tid) {
|
||||
char path[FS_MAX_PATH+1] = {0};
|
||||
snprintf(path, FS_MAX_PATH, "@Sdcard:/atmosphere/titles/%016lx/exefs.nsp", tid);
|
||||
Result rc = fsOpenFileSystemWithId(&g_CodeFileSystem, 0, FsFileSystemType_ApplicationPackage, path);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
R_TRY(fsOpenFileSystemWithId(&g_CodeFileSystem, 0, FsFileSystemType_ApplicationPackage, path));
|
||||
fsdevMountDevice("code", g_CodeFileSystem);
|
||||
TryMountHblNspOnSd();
|
||||
}
|
||||
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result ContentManagement::MountCodeForTidSid(Registration::TidSid *tid_sid) {
|
||||
|
@ -154,39 +146,29 @@ Result ContentManagement::MountCodeForTidSid(Registration::TidSid *tid_sid) {
|
|||
}
|
||||
|
||||
Result ContentManagement::ResolveContentPath(char *out_path, u64 tid, FsStorageId sid) {
|
||||
Result rc;
|
||||
LrRegisteredLocationResolver reg;
|
||||
LrLocationResolver lr;
|
||||
char path[FS_MAX_PATH] = {0};
|
||||
|
||||
/* Try to get the path from the registered resolver. */
|
||||
if (R_FAILED(rc = lrOpenRegisteredLocationResolver(®))) {
|
||||
return rc;
|
||||
}
|
||||
LrRegisteredLocationResolver reg;
|
||||
R_TRY(lrOpenRegisteredLocationResolver(®));
|
||||
ON_SCOPE_EXIT { serviceClose(®.s); };
|
||||
|
||||
R_TRY_CATCH(lrRegLrResolveProgramPath(®, tid, path)) {
|
||||
R_CATCH(ResultLrProgramNotFound) {
|
||||
/* Program wasn't found via registered resolver, fall back to the normal resolver. */
|
||||
LrLocationResolver lr;
|
||||
R_TRY(lrOpenLocationResolver(sid, &lr));
|
||||
ON_SCOPE_EXIT { serviceClose(&lr.s); };
|
||||
|
||||
R_TRY(lrLrResolveProgramPath(&lr, tid, path));
|
||||
|
||||
if (R_SUCCEEDED(rc = lrRegLrResolveProgramPath(®, tid, path))) {
|
||||
strncpy(out_path, path, FS_MAX_PATH);
|
||||
} else if (rc != ResultLrProgramNotFound) {
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
serviceClose(®.s);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* If getting the path from the registered resolver fails, fall back to the normal resolver. */
|
||||
if (R_FAILED(rc = lrOpenLocationResolver(sid, &lr))) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc = lrLrResolveProgramPath(&lr, tid, path))) {
|
||||
strncpy(out_path, path, FS_MAX_PATH);
|
||||
}
|
||||
|
||||
serviceClose(&lr.s);
|
||||
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result ContentManagement::ResolveContentPathForTidSid(char *out_path, Registration::TidSid *tid_sid) {
|
||||
|
@ -194,18 +176,11 @@ Result ContentManagement::ResolveContentPathForTidSid(char *out_path, Registrati
|
|||
}
|
||||
|
||||
Result ContentManagement::RedirectContentPath(const char *path, u64 tid, FsStorageId sid) {
|
||||
Result rc;
|
||||
LrLocationResolver lr;
|
||||
R_TRY(lrOpenLocationResolver(sid, &lr));
|
||||
ON_SCOPE_EXIT { serviceClose(&lr.s); };
|
||||
|
||||
if (R_FAILED(rc = lrOpenLocationResolver(sid, &lr))) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = lrLrRedirectProgramPath(&lr, tid, path);
|
||||
|
||||
serviceClose(&lr.s);
|
||||
|
||||
return rc;
|
||||
return lrLrRedirectProgramPath(&lr, tid, path);
|
||||
}
|
||||
|
||||
Result ContentManagement::RedirectContentPathForTidSid(const char *path, Registration::TidSid *tid_sid) {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "ldr_map.hpp"
|
||||
|
||||
Result MapUtils::LocateSpaceForMap(u64 *out, u64 out_size) {
|
||||
if ((GetRuntimeFirmwareVersion() >= FirmwareVersion_200)) {
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) {
|
||||
return LocateSpaceForMapModern(out, out_size);
|
||||
} else {
|
||||
return LocateSpaceForMapDeprecated(out, out_size);
|
||||
|
@ -32,31 +32,27 @@ Result MapUtils::LocateSpaceForMapModern(u64 *out, u64 out_size) {
|
|||
AddressSpaceInfo address_space = {};
|
||||
u32 page_info = 0;
|
||||
u64 cur_base = 0, cur_end = 0;
|
||||
Result rc;
|
||||
|
||||
if (R_FAILED((rc = GetAddressSpaceInfo(&address_space, CUR_PROCESS_HANDLE)))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(GetAddressSpaceInfo(&address_space, CUR_PROCESS_HANDLE));
|
||||
|
||||
cur_base = address_space.addspace_base;
|
||||
|
||||
rc = ResultKernelOutOfMemory;
|
||||
cur_end = cur_base + out_size;
|
||||
if (cur_end <= cur_base) {
|
||||
return rc;
|
||||
return ResultKernelOutOfMemory;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (address_space.heap_size && (address_space.heap_base <= cur_end - 1 && cur_base <= address_space.heap_end - 1)) {
|
||||
/* If we overlap the heap region, go to the end of the heap region. */
|
||||
if (cur_base == address_space.heap_end) {
|
||||
return rc;
|
||||
return ResultKernelOutOfMemory;
|
||||
}
|
||||
cur_base = address_space.heap_end;
|
||||
} else if (address_space.map_size && (address_space.map_base <= cur_end - 1 && cur_base <= address_space.map_end - 1)) {
|
||||
/* If we overlap the map region, go to the end of the map region. */
|
||||
if (cur_base == address_space.map_end) {
|
||||
return rc;
|
||||
return ResultKernelOutOfMemory;
|
||||
}
|
||||
cur_base = address_space.map_end;
|
||||
} else {
|
||||
|
@ -68,75 +64,50 @@ Result MapUtils::LocateSpaceForMapModern(u64 *out, u64 out_size) {
|
|||
return ResultSuccess;
|
||||
}
|
||||
if (mem_info.addr + mem_info.size <= cur_base) {
|
||||
return rc;
|
||||
return ResultKernelOutOfMemory;
|
||||
}
|
||||
cur_base = mem_info.addr + mem_info.size;
|
||||
if (cur_base >= address_space.addspace_end) {
|
||||
return rc;
|
||||
return ResultKernelOutOfMemory;
|
||||
}
|
||||
}
|
||||
cur_end = cur_base + out_size;
|
||||
if (cur_base + out_size <= cur_base) {
|
||||
return rc;
|
||||
return ResultKernelOutOfMemory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Result MapUtils::LocateSpaceForMapDeprecated(u64 *out, u64 out_size) {
|
||||
MemoryInfo mem_info = {};
|
||||
u32 page_info = 0;
|
||||
Result rc;
|
||||
|
||||
u64 cur_base = 0x8000000ULL;
|
||||
if (R_FAILED((rc = svcQueryMemory(&mem_info, &page_info, cur_base)))) {
|
||||
return rc;
|
||||
}
|
||||
do {
|
||||
R_TRY(svcQueryMemory(&mem_info, &page_info, cur_base));
|
||||
|
||||
rc = ResultKernelOutOfMemory;
|
||||
while (true) {
|
||||
if (mem_info.type == 0x10) {
|
||||
return rc;
|
||||
}
|
||||
if (mem_info.type == 0 && mem_info.addr - cur_base + mem_info.size >= out_size) {
|
||||
*out = cur_base;
|
||||
return ResultSuccess;
|
||||
}
|
||||
u64 mem_end = mem_info.addr + mem_info.size;
|
||||
if (mem_end < cur_base) {
|
||||
return rc;
|
||||
}
|
||||
if (mem_end >> 31) {
|
||||
break;
|
||||
|
||||
const u64 mem_end = mem_info.addr + mem_info.size;
|
||||
if (mem_info.type == 0x10 || mem_end < cur_base || (mem_end >> 31)) {
|
||||
return ResultKernelOutOfMemory;
|
||||
}
|
||||
|
||||
cur_base = mem_end;
|
||||
if (R_FAILED((rc = svcQueryMemory(&mem_info, &page_info, cur_base)))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
Result MapUtils::GetAddressSpaceInfo(AddressSpaceInfo *out, Handle process_h) {
|
||||
Result rc;
|
||||
if (R_FAILED((rc = svcGetInfo(&out->heap_base, 4, process_h, 0)))) {
|
||||
return rc;
|
||||
}
|
||||
if (R_FAILED((rc = svcGetInfo(&out->heap_size, 5, process_h, 0)))) {
|
||||
return rc;
|
||||
}
|
||||
if (R_FAILED((rc = svcGetInfo(&out->map_base, 2, process_h, 0)))) {
|
||||
return rc;
|
||||
}
|
||||
if (R_FAILED((rc = svcGetInfo(&out->map_size, 3, process_h, 0)))) {
|
||||
return rc;
|
||||
}
|
||||
if (R_FAILED((rc = svcGetInfo(&out->addspace_base, 12, process_h, 0)))) {
|
||||
return rc;
|
||||
}
|
||||
if (R_FAILED((rc = svcGetInfo(&out->addspace_size, 13, process_h, 0)))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(svcGetInfo(&out->heap_base, 4, process_h, 0));
|
||||
R_TRY(svcGetInfo(&out->heap_size, 5, process_h, 0));
|
||||
R_TRY(svcGetInfo(&out->map_base, 2, process_h, 0));
|
||||
R_TRY(svcGetInfo(&out->map_size, 3, process_h, 0));
|
||||
R_TRY(svcGetInfo(&out->addspace_base, 12, process_h, 0));
|
||||
R_TRY(svcGetInfo(&out->addspace_size, 13, process_h, 0));
|
||||
|
||||
out->heap_end = out->heap_base + out->heap_size;
|
||||
out->map_end = out->map_base + out->map_size;
|
||||
out->addspace_end = out->addspace_base + out->addspace_size;
|
||||
|
|
|
@ -53,17 +53,16 @@ class AutoCloseMap {
|
|||
}
|
||||
|
||||
Result Open(Handle process_h, u64 address, u64 size) {
|
||||
Result rc;
|
||||
u64 try_address;
|
||||
if (R_FAILED(rc = MapUtils::LocateSpaceForMap(&try_address, size))) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (R_FAILED((rc = svcMapProcessMemory((void *)try_address, process_h, address, size)))) {
|
||||
return rc;
|
||||
}
|
||||
/* Find an address to map at. */
|
||||
R_TRY(MapUtils::LocateSpaceForMap(&try_address, size));
|
||||
|
||||
this->mapped_address = (void *)try_address;
|
||||
/* Actually map at address. */
|
||||
void *try_map_address = reinterpret_cast<void *>(try_address);
|
||||
R_TRY(svcMapProcessMemory(try_map_address, process_h, address, size));
|
||||
|
||||
this->mapped_address = try_map_address;
|
||||
this->process_handle = process_h;
|
||||
this->base_address = address;
|
||||
this->size = size;
|
||||
|
|
|
@ -82,31 +82,26 @@ FILE *NpdmUtils::OpenNpdm(u64 title_id) {
|
|||
}
|
||||
|
||||
Result NpdmUtils::LoadNpdmInternal(FILE *f_npdm, NpdmUtils::NpdmCache *cache) {
|
||||
Result rc;
|
||||
|
||||
cache->info = {};
|
||||
|
||||
rc = ResultFsPathNotFound;
|
||||
if (f_npdm == NULL) {
|
||||
/* For generic "Couldn't open the file" error, just say the file doesn't exist. */
|
||||
return rc;
|
||||
return ResultFsPathNotFound;
|
||||
}
|
||||
|
||||
fseek(f_npdm, 0, SEEK_END);
|
||||
size_t npdm_size = ftell(f_npdm);
|
||||
fseek(f_npdm, 0, SEEK_SET);
|
||||
|
||||
rc = ResultLoaderTooLargeMeta;
|
||||
if ((npdm_size > sizeof(cache->buffer)) || (fread(cache->buffer, 1, npdm_size, f_npdm) != npdm_size)) {
|
||||
fclose(f_npdm);
|
||||
return rc;
|
||||
return ResultLoaderTooLargeMeta;
|
||||
}
|
||||
|
||||
fclose(f_npdm);
|
||||
|
||||
rc = ResultLoaderInvalidMeta;
|
||||
if (npdm_size < sizeof(NpdmUtils::NpdmHeader)) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
/* For ease of access... */
|
||||
|
@ -114,90 +109,84 @@ Result NpdmUtils::LoadNpdmInternal(FILE *f_npdm, NpdmUtils::NpdmCache *cache) {
|
|||
NpdmInfo *info = &cache->info;
|
||||
|
||||
if (info->header->magic != MAGIC_META) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
/* 7.0.0 added 0x10 as a valid bit to NPDM flags. */
|
||||
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_700) {
|
||||
if (info->header->mmu_flags > 0x1F) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
} else {
|
||||
if (info->header->mmu_flags > 0xF) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->header->aci0_offset < sizeof(NpdmUtils::NpdmHeader) || info->header->aci0_size < sizeof(NpdmUtils::NpdmAci0) || info->header->aci0_offset + info->header->aci0_size > npdm_size) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
info->aci0 = (NpdmAci0 *)(cache->buffer + info->header->aci0_offset);
|
||||
|
||||
if (info->aci0->magic != MAGIC_ACI0) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
if (info->aci0->fah_size > info->header->aci0_size || info->aci0->fah_offset < sizeof(NpdmUtils::NpdmAci0) || info->aci0->fah_offset + info->aci0->fah_size > info->header->aci0_size) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
info->aci0_fah = (void *)((uintptr_t)info->aci0 + info->aci0->fah_offset);
|
||||
|
||||
if (info->aci0->sac_size > info->header->aci0_size || info->aci0->sac_offset < sizeof(NpdmUtils::NpdmAci0) || info->aci0->sac_offset + info->aci0->sac_size > info->header->aci0_size) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
info->aci0_sac = (void *)((uintptr_t)info->aci0 + info->aci0->sac_offset);
|
||||
|
||||
if (info->aci0->kac_size > info->header->aci0_size || info->aci0->kac_offset < sizeof(NpdmUtils::NpdmAci0) || info->aci0->kac_offset + info->aci0->kac_size > info->header->aci0_size) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
info->aci0_kac = (void *)((uintptr_t)info->aci0 + info->aci0->kac_offset);
|
||||
|
||||
if (info->header->acid_offset < sizeof(NpdmUtils::NpdmHeader) || info->header->acid_size < sizeof(NpdmUtils::NpdmAcid) || info->header->acid_offset + info->header->acid_size > npdm_size) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
info->acid = (NpdmAcid *)(cache->buffer + info->header->acid_offset);
|
||||
|
||||
if (info->acid->magic != MAGIC_ACID) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
/* TODO: Check if retail flag is set if not development hardware. */
|
||||
|
||||
if (info->acid->fac_size > info->header->acid_size || info->acid->fac_offset < sizeof(NpdmUtils::NpdmAcid) || info->acid->fac_offset + info->acid->fac_size > info->header->acid_size) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
info->acid_fac = (void *)((uintptr_t)info->acid + info->acid->fac_offset);
|
||||
|
||||
if (info->acid->sac_size > info->header->acid_size || info->acid->sac_offset < sizeof(NpdmUtils::NpdmAcid) || info->acid->sac_offset + info->acid->sac_size > info->header->acid_size) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
info->acid_sac = (void *)((uintptr_t)info->acid + info->acid->sac_offset);
|
||||
|
||||
if (info->acid->kac_size > info->header->acid_size || info->acid->kac_offset < sizeof(NpdmUtils::NpdmAcid) || info->acid->kac_offset + info->acid->kac_size > info->header->acid_size) {
|
||||
return rc;
|
||||
return ResultLoaderInvalidMeta;
|
||||
}
|
||||
|
||||
info->acid_kac = (void *)((uintptr_t)info->acid + info->acid->kac_offset);
|
||||
|
||||
rc = ResultSuccess;
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
||||
Result rc;
|
||||
|
||||
rc = LoadNpdmInternal(OpenNpdm(tid), &g_npdm_cache);
|
||||
|
||||
if (R_FAILED(rc)) {
|
||||
return rc;
|
||||
}
|
||||
/* Load and validate the NPDM. */
|
||||
R_TRY(LoadNpdmInternal(OpenNpdm(tid), &g_npdm_cache));
|
||||
|
||||
NpdmInfo *info = &g_npdm_cache.info;
|
||||
/* Override the ACID/ACI0 title ID, in order to facilitate HBL takeover of any title. */
|
||||
|
@ -230,13 +219,11 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) {
|
|||
/* We validated! */
|
||||
info->title_id = tid;
|
||||
*out = *info;
|
||||
rc = ResultSuccess;
|
||||
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size_t num_restrict_caps, u32 *&cur_cap, size_t &caps_remaining) {
|
||||
Result rc = ResultSuccess;
|
||||
Result NpdmUtils::ValidateCapabilityAgainstRestrictions(const u32 *restrict_caps, size_t num_restrict_caps, const u32 *&cur_cap, size_t &caps_remaining) {
|
||||
u32 desc = *cur_cap++;
|
||||
caps_remaining--;
|
||||
unsigned int low_bits = 0;
|
||||
|
@ -248,7 +235,6 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
u32 r_desc = 0;
|
||||
switch (low_bits) {
|
||||
case 3: /* Kernel flags. */
|
||||
rc = ResultLoaderInvalidCapabilityKernelFlags;
|
||||
for (size_t i = 0; i < num_restrict_caps; i++) {
|
||||
if ((restrict_caps[i] & 0xF) == 0x7) {
|
||||
r_desc = restrict_caps[i] >> 4;
|
||||
|
@ -285,13 +271,11 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
break;
|
||||
}
|
||||
/* Valid! */
|
||||
rc = ResultSuccess;
|
||||
break;
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityKernelFlags;
|
||||
case 4: /* Syscall mask. */
|
||||
rc = ResultLoaderInvalidCapabilitySyscallMask;
|
||||
for (size_t i = 0; i < num_restrict_caps; i++) {
|
||||
if ((restrict_caps[i] & 0x1F) == 0xF) {
|
||||
r_desc = restrict_caps[i] >> 5;
|
||||
|
@ -306,32 +290,31 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
break;
|
||||
}
|
||||
/* Valid! */
|
||||
rc = ResultSuccess;
|
||||
break;
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6: /* Map IO/Normal. */ {
|
||||
rc = ResultLoaderInvalidCapabilityMapRange;
|
||||
return ResultLoaderInvalidCapabilitySyscallMask;
|
||||
case 6: /* Map IO/Normal. */
|
||||
{
|
||||
if (caps_remaining == 0) {
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityMapRange;
|
||||
}
|
||||
u32 next_cap = *cur_cap++;
|
||||
caps_remaining--;
|
||||
if ((next_cap & 0x7F) != 0x3F) {
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityMapRange;
|
||||
}
|
||||
u32 next_desc = next_cap >> 7;
|
||||
u32 base_addr = desc & 0xFFFFFF;
|
||||
u32 base_size = next_desc & 0xFFFFFF;
|
||||
/* Size check the mapping. */
|
||||
if (base_size >> 20) {
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityMapRange;
|
||||
}
|
||||
u32 base_end = base_addr + base_size;
|
||||
/* Validate it's possible to validate this mapping. */
|
||||
if (num_restrict_caps < 2) {
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityMapRange;
|
||||
}
|
||||
for (size_t i = 0; i < num_restrict_caps - 1; i++) {
|
||||
if ((restrict_caps[i] & 0x7F) == 0x3F) {
|
||||
|
@ -360,14 +343,12 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
continue;
|
||||
}
|
||||
/* Valid! */
|
||||
rc = ResultSuccess;
|
||||
break;
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityMapRange;
|
||||
case 7: /* Map Normal Page. */
|
||||
rc = ResultLoaderInvalidCapabilityMapPage;
|
||||
for (size_t i = 0; i < num_restrict_caps; i++) {
|
||||
if ((restrict_caps[i] & 0xFF) == 0x7F) {
|
||||
r_desc = restrict_caps[i] >> 8;
|
||||
|
@ -375,13 +356,11 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
continue;
|
||||
}
|
||||
/* Valid! */
|
||||
rc = ResultSuccess;
|
||||
break;
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityMapPage;
|
||||
case 11: /* IRQ Pair. */
|
||||
rc = ResultSuccess;
|
||||
for (unsigned int irq_i = 0; irq_i < 2; irq_i++) {
|
||||
u32 irq = desc & 0x3FF;
|
||||
desc >>= 10;
|
||||
|
@ -398,14 +377,12 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
}
|
||||
}
|
||||
if (!found) {
|
||||
rc = ResultLoaderInvalidCapabilityInterruptPair;
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityInterruptPair;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
return ResultSuccess;
|
||||
case 13: /* App Type. */
|
||||
rc = ResultLoaderInvalidCapabilityApplicationType;
|
||||
if (num_restrict_caps) {
|
||||
for (size_t i = 0; i < num_restrict_caps; i++) {
|
||||
if ((restrict_caps[i] & 0x3FFF) == 0x1FFF) {
|
||||
|
@ -418,11 +395,10 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
}
|
||||
if (desc == r_desc) {
|
||||
/* Valid! */
|
||||
rc = ResultSuccess;
|
||||
return ResultSuccess;
|
||||
}
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityApplicationType;
|
||||
case 14: /* Kernel Release Version. */
|
||||
rc = ResultLoaderInvalidCapabilityKernelVersion;
|
||||
if (num_restrict_caps) {
|
||||
for (size_t i = 0; i < num_restrict_caps; i++) {
|
||||
if ((restrict_caps[i] & 0x7FFF) == 0x3FFF) {
|
||||
|
@ -435,11 +411,10 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
}
|
||||
if (desc == r_desc) {
|
||||
/* Valid! */
|
||||
rc = ResultSuccess;
|
||||
return ResultSuccess;
|
||||
}
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityKernelVersion;
|
||||
case 15: /* Handle Table Size. */
|
||||
rc = ResultLoaderInvalidCapabilityHandleTable;
|
||||
for (size_t i = 0; i < num_restrict_caps; i++) {
|
||||
if ((restrict_caps[i] & 0xFFFF) == 0x7FFF) {
|
||||
r_desc = restrict_caps[i] >> 16;
|
||||
|
@ -449,13 +424,11 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
break;
|
||||
}
|
||||
/* Valid! */
|
||||
rc = ResultSuccess;
|
||||
break;
|
||||
return ResultSuccess;
|
||||
}
|
||||
}
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityHandleTable;
|
||||
case 16: /* Debug Flags. */
|
||||
rc = ResultLoaderInvalidCapabilityDebugFlags;
|
||||
if (num_restrict_caps) {
|
||||
for (size_t i = 0; i < num_restrict_caps; i++) {
|
||||
if ((restrict_caps[i] & 0x1FFFF) == 0xFFFF) {
|
||||
|
@ -468,33 +441,29 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size
|
|||
}
|
||||
if ((desc & ~r_desc) == 0) {
|
||||
/* Valid! */
|
||||
rc = ResultSuccess;
|
||||
return ResultSuccess;
|
||||
}
|
||||
break;
|
||||
return ResultLoaderInvalidCapabilityDebugFlags;
|
||||
case 32: /* Empty Descriptor. */
|
||||
rc = ResultSuccess;
|
||||
break;
|
||||
return ResultSuccess;
|
||||
default: /* Unrecognized Descriptor. */
|
||||
rc = ResultLoaderUnknownCapability;
|
||||
break;
|
||||
return ResultLoaderUnknownCapability;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result NpdmUtils::ValidateCapabilities(u32 *acid_caps, size_t num_acid_caps, u32 *aci0_caps, size_t num_aci0_caps) {
|
||||
Result rc = ResultSuccess;
|
||||
Result NpdmUtils::ValidateCapabilities(const u32 *acid_caps, size_t num_acid_caps, const u32 *aci0_caps, size_t num_aci0_caps) {
|
||||
const u32 *cur_cap = aci0_caps;
|
||||
size_t remaining = num_aci0_caps;
|
||||
u32 *cur_cap = aci0_caps;
|
||||
|
||||
while (remaining) {
|
||||
if (R_FAILED((rc = ValidateCapabilityAgainstRestrictions(acid_caps, num_acid_caps, cur_cap, remaining)))) {
|
||||
break;
|
||||
}
|
||||
/* Validate, update capabilities. cur_cap and remaining passed by reference. */
|
||||
R_TRY(ValidateCapabilityAgainstRestrictions(acid_caps, num_acid_caps, cur_cap, remaining));
|
||||
}
|
||||
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
u32 NpdmUtils::GetApplicationType(u32 *caps, size_t num_caps) {
|
||||
u32 NpdmUtils::GetApplicationType(const u32 *caps, size_t num_caps) {
|
||||
u32 application_type = 0;
|
||||
for (unsigned int i = 0; i < num_caps; i++) {
|
||||
if ((caps[i] & 0x3FFF) == 0x1FFF) {
|
||||
|
@ -514,7 +483,7 @@ u32 NpdmUtils::GetApplicationType(u32 *caps, size_t num_caps) {
|
|||
}
|
||||
|
||||
/* Like GetApplicationType, except this returns the raw kac descriptor value. */
|
||||
u32 NpdmUtils::GetApplicationTypeRaw(u32 *caps, size_t num_caps) {
|
||||
u32 NpdmUtils::GetApplicationTypeRaw(const u32 *caps, size_t num_caps) {
|
||||
u32 application_type = 0;
|
||||
for (unsigned int i = 0; i < num_caps; i++) {
|
||||
if ((caps[i] & 0x3FFF) == 0x1FFF) {
|
||||
|
|
|
@ -96,11 +96,11 @@ class NpdmUtils {
|
|||
static_assert(sizeof(NpdmAcid) == 0x240, "Incorrectly defined NpdmAcid!");
|
||||
static_assert(sizeof(NpdmAci0) == 0x40, "Incorrectly defined NpdmAci0!");
|
||||
|
||||
static u32 GetApplicationType(u32 *caps, size_t num_caps);
|
||||
static u32 GetApplicationTypeRaw(u32 *caps, size_t num_caps);
|
||||
static u32 GetApplicationType(const u32 *caps, size_t num_caps);
|
||||
static u32 GetApplicationTypeRaw(const u32 *caps, size_t num_caps);
|
||||
|
||||
static Result ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size_t num_restrict_caps, u32 *&cur_cap, size_t &caps_remaining);
|
||||
static Result ValidateCapabilities(u32 *acid_caps, size_t num_acid_caps, u32 *aci0_caps, size_t num_aci0_caps);
|
||||
static Result ValidateCapabilityAgainstRestrictions(const u32 *restrict_caps, size_t num_restrict_caps, const u32 *&cur_cap, size_t &caps_remaining);
|
||||
static Result ValidateCapabilities(const u32 *acid_caps, size_t num_acid_caps, const u32 *aci0_caps, size_t num_aci0_caps);
|
||||
|
||||
static FILE *OpenNpdmFromECS(ContentManagement::ExternalContentSource *ecs);
|
||||
static FILE *OpenNpdmFromHBL();
|
||||
|
|
|
@ -283,31 +283,28 @@ Result NsoUtils::LoadNsoSegment(u64 title_id, unsigned int index, unsigned int s
|
|||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, u8 *args, u32 args_size) {
|
||||
Result rc = ResultLoaderInvalidNso;
|
||||
Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, const u8 *args, u32 args_size) {
|
||||
for (unsigned int i = 0; i < NSO_NUM_MAX; i++) {
|
||||
if (g_nso_present[i]) {
|
||||
AutoCloseMap nso_map;
|
||||
if (R_FAILED((rc = nso_map.Open(process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(nso_map.Open(process_h, extents->nso_addresses[i], extents->nso_sizes[i]));
|
||||
|
||||
u8 *map_base = (u8 *)nso_map.GetMappedAddress();
|
||||
|
||||
/* Load NSO segments from file. */
|
||||
{
|
||||
FILE *f_nso = OpenNso(i, title_id);
|
||||
if (f_nso == NULL) {
|
||||
/* TODO: Is there a better error to return here? */
|
||||
return ResultLoaderInvalidNso;
|
||||
}
|
||||
ON_SCOPE_EXIT { fclose(f_nso); };
|
||||
|
||||
for (unsigned int seg = 0; seg < 3; seg++) {
|
||||
if (R_FAILED((rc = LoadNsoSegment(title_id, i, seg, f_nso, map_base, map_base + extents->nso_sizes[i])))) {
|
||||
fclose(f_nso);
|
||||
return rc;
|
||||
R_TRY(LoadNsoSegment(title_id, i, seg, f_nso, map_base, map_base + extents->nso_sizes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f_nso);
|
||||
f_nso = NULL;
|
||||
/* Zero out memory before .text. */
|
||||
u64 text_base = 0, text_start = g_nso_headers[i].segments[0].dst_offset;
|
||||
std::fill(map_base + text_base, map_base + text_start, 0);
|
||||
|
@ -334,19 +331,15 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo
|
|||
size += 0xFFF;
|
||||
size &= ~0xFFFULL;
|
||||
const static unsigned int segment_perms[3] = {5, 1, 3};
|
||||
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, extents->nso_addresses[i] + g_nso_headers[i].segments[seg].dst_offset, size, segment_perms[seg])))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(svcSetProcessMemoryPermission(process_h, extents->nso_addresses[i] + g_nso_headers[i].segments[seg].dst_offset, size, segment_perms[seg]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Map in arguments. */
|
||||
if (args != NULL && args_size) {
|
||||
if (args != nullptr && args_size) {
|
||||
AutoCloseMap args_map;
|
||||
if (R_FAILED((rc = args_map.Open(process_h, extents->args_address, extents->args_size)))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(args_map.Open(process_h, extents->args_address, extents->args_size));
|
||||
|
||||
NsoArgument *arg_map_base = (NsoArgument *)args_map.GetMappedAddress();
|
||||
|
||||
|
@ -357,10 +350,8 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo
|
|||
|
||||
args_map.Close();
|
||||
|
||||
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, extents->args_address, extents->args_size, 3)))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(svcSetProcessMemoryPermission(process_h, extents->args_address, extents->args_size, 3));
|
||||
}
|
||||
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
|
|
@ -112,5 +112,5 @@ class NsoUtils {
|
|||
static Result CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLoadExtents *extents);
|
||||
|
||||
static Result LoadNsoSegment(u64 title_id, unsigned int index, unsigned int segment, FILE *f_nso, u8 *map_base, u8 *map_end);
|
||||
static Result LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, u8 *args, u32 args_size);
|
||||
static Result LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, const u8 *args, u32 args_size);
|
||||
};
|
|
@ -117,69 +117,57 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc
|
|||
Registration::Process *target_process;
|
||||
Handle process_h = 0;
|
||||
u64 process_id = 0;
|
||||
bool mounted_code = false;
|
||||
Result rc;
|
||||
|
||||
/* Get the process from the registration queue. */
|
||||
target_process = Registration::GetProcess(index);
|
||||
if (target_process == NULL) {
|
||||
if (target_process == nullptr) {
|
||||
return ResultLoaderProcessNotRegistered;
|
||||
}
|
||||
|
||||
/* Mount the title's exefs. */
|
||||
bool mounted_code = false;
|
||||
if (target_process->tid_sid.storage_id != FsStorageId_None) {
|
||||
rc = ContentManagement::MountCodeForTidSid(&target_process->tid_sid);
|
||||
if (R_FAILED(rc)) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(ContentManagement::MountCodeForTidSid(&target_process->tid_sid));
|
||||
mounted_code = true;
|
||||
} else {
|
||||
if (R_SUCCEEDED(ContentManagement::MountCodeNspOnSd(target_process->tid_sid.title_id))) {
|
||||
mounted_code = true;
|
||||
}
|
||||
}
|
||||
ON_SCOPE_EXIT {
|
||||
if (mounted_code) {
|
||||
if (R_FAILED(ContentManagement::UnmountCode()) && target_process->tid_sid.storage_id != FsStorageId_None) {
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Load the process's NPDM. */
|
||||
rc = NpdmUtils::LoadNpdmFromCache(target_process->tid_sid.title_id, &npdm_info);
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
R_TRY(NpdmUtils::LoadNpdmFromCache(target_process->tid_sid.title_id, &npdm_info));
|
||||
|
||||
/* Validate the title we're loading is what we expect. */
|
||||
if (npdm_info.aci0->title_id < npdm_info.acid->title_id_range_min || npdm_info.aci0->title_id > npdm_info.acid->title_id_range_max) {
|
||||
rc = ResultLoaderInvalidProgramId;
|
||||
goto CREATE_PROCESS_END;
|
||||
return ResultLoaderInvalidProgramId;
|
||||
}
|
||||
|
||||
/* Validate that the ACI0 Kernel Capabilities are valid and restricted by the ACID Kernel Capabilities. */
|
||||
rc = NpdmUtils::ValidateCapabilities((u32 *)npdm_info.acid_kac, npdm_info.acid->kac_size/sizeof(u32), (u32 *)npdm_info.aci0_kac, npdm_info.aci0->kac_size/sizeof(u32));
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
const u32 *acid_caps = reinterpret_cast<u32 *>(npdm_info.acid_kac);
|
||||
const u32 *aci0_caps = reinterpret_cast<u32 *>(npdm_info.aci0_kac);
|
||||
const size_t num_acid_caps = npdm_info.acid->kac_size / sizeof(*acid_caps);
|
||||
const size_t num_aci0_caps = npdm_info.aci0->kac_size / sizeof(*aci0_caps);
|
||||
R_TRY(NpdmUtils::ValidateCapabilities(acid_caps, num_acid_caps, aci0_caps, num_aci0_caps));
|
||||
|
||||
/* Read in all NSO headers, see what NSOs are present. */
|
||||
rc = NsoUtils::LoadNsoHeaders(npdm_info.aci0->title_id);
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
R_TRY(NsoUtils::LoadNsoHeaders(npdm_info.aci0->title_id));
|
||||
|
||||
/* Validate that the set of NSOs to be loaded is correct. */
|
||||
rc = NsoUtils::ValidateNsoLoadSet();
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
R_TRY(NsoUtils::ValidateNsoLoadSet());
|
||||
|
||||
/* Initialize the ProcessInfo. */
|
||||
rc = ProcessCreation::InitializeProcessInfo(&npdm_info, reslimit_h, arg_flags, &process_info);
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
R_TRY(ProcessCreation::InitializeProcessInfo(&npdm_info, reslimit_h, arg_flags, &process_info));
|
||||
|
||||
/* Figure out where NSOs will be mapped, and how much space they (and arguments) will take up. */
|
||||
rc = NsoUtils::CalculateNsoLoadExtents(process_info.process_flags, launch_item != NULL ? launch_item->arg_size : 0, &nso_extents);
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
R_TRY(NsoUtils::CalculateNsoLoadExtents(process_info.process_flags, launch_item != nullptr ? launch_item->arg_size : 0, &nso_extents));
|
||||
|
||||
/* Set Address Space information in ProcessInfo. */
|
||||
process_info.code_addr = nso_extents.base_address;
|
||||
|
@ -187,20 +175,22 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc
|
|||
process_info.code_num_pages >>= 12;
|
||||
|
||||
/* Call svcCreateProcess(). */
|
||||
rc = svcCreateProcess(&process_h, &process_info, (u32 *)npdm_info.aci0_kac, npdm_info.aci0->kac_size/sizeof(u32));
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
R_TRY(svcCreateProcess(&process_h, &process_info, (u32 *)npdm_info.aci0_kac, npdm_info.aci0->kac_size/sizeof(u32)));
|
||||
auto proc_handle_guard = SCOPE_GUARD {
|
||||
svcCloseHandle(process_h);
|
||||
};
|
||||
|
||||
|
||||
/* Load all NSOs into Process memory, and set permissions accordingly. */
|
||||
if (launch_item != NULL) {
|
||||
rc = NsoUtils::LoadNsosIntoProcessMemory(process_h, npdm_info.aci0->title_id, &nso_extents, (u8 *)launch_item->args, launch_item->arg_size);
|
||||
} else {
|
||||
rc = NsoUtils::LoadNsosIntoProcessMemory(process_h, npdm_info.aci0->title_id, &nso_extents, NULL, 0);
|
||||
{
|
||||
const u8 *launch_args = nullptr;
|
||||
size_t launch_args_size = 0;
|
||||
if (launch_item != nullptr) {
|
||||
launch_args = reinterpret_cast<const u8 *>(launch_item->args);
|
||||
launch_args_size = launch_item->arg_size;
|
||||
}
|
||||
if (R_FAILED(rc)) {
|
||||
goto CREATE_PROCESS_END;
|
||||
|
||||
R_TRY(NsoUtils::LoadNsosIntoProcessMemory(process_h, npdm_info.aci0->title_id, &nso_extents, launch_args, launch_args_size));
|
||||
}
|
||||
|
||||
/* Update the list of registered processes with the new process. */
|
||||
|
@ -221,8 +211,6 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc
|
|||
/* Send the pid/tid pair to anyone interested in man-in-the-middle-attacking it. */
|
||||
Registration::AssociatePidTidForMitM(index);
|
||||
|
||||
rc = ResultSuccess;
|
||||
|
||||
/* If HBL, override HTML document path. */
|
||||
if (ContentManagement::ShouldOverrideContentsWithHBL(target_process->tid_sid.title_id)) {
|
||||
ContentManagement::RedirectHtmlDocumentPathForHbl(target_process->tid_sid.title_id, target_process->tid_sid.storage_id);
|
||||
|
@ -231,20 +219,10 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc
|
|||
/* ECS is a one-shot operation, but we don't clear on failure. */
|
||||
ContentManagement::ClearExternalContentSource(target_process->tid_sid.title_id);
|
||||
|
||||
/* Cancel the process handle guard. */
|
||||
proc_handle_guard.Cancel();
|
||||
|
||||
CREATE_PROCESS_END:
|
||||
if (mounted_code) {
|
||||
if (R_SUCCEEDED(rc) && target_process->tid_sid.storage_id != FsStorageId_None) {
|
||||
rc = ContentManagement::UnmountCode();
|
||||
} else {
|
||||
ContentManagement::UnmountCode();
|
||||
}
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
/* Write process handle to output. */
|
||||
*out_process_h = process_h;
|
||||
} else {
|
||||
svcCloseHandle(process_h);
|
||||
}
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "ldr_npdm.hpp"
|
||||
|
||||
Result ProcessManagerService::CreateProcess(Out<MovedHandle> proc_h, u64 index, u32 flags, CopiedHandle reslimit_h) {
|
||||
Result rc;
|
||||
Registration::TidSid tid_sid;
|
||||
LaunchQueue::LaunchItem *launch_item;
|
||||
char nca_path[FS_MAX_PATH] = {0};
|
||||
|
@ -33,57 +32,34 @@ Result ProcessManagerService::CreateProcess(Out<MovedHandle> proc_h, u64 index,
|
|||
svcCloseHandle(reslimit_h.handle);
|
||||
};
|
||||
|
||||
rc = Registration::GetRegisteredTidSid(index, &tid_sid);
|
||||
if (R_FAILED(rc)) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(Registration::GetRegisteredTidSid(index, &tid_sid));
|
||||
|
||||
if (tid_sid.storage_id != FsStorageId_None) {
|
||||
rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid);
|
||||
if (R_FAILED(rc)) {
|
||||
return rc;
|
||||
R_TRY(ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
launch_item = LaunchQueue::GetItem(tid_sid.title_id);
|
||||
R_TRY(ProcessCreation::CreateProcess(proc_h.GetHandlePointer(), index, nca_path, launch_item, flags, reslimit_h.handle));
|
||||
|
||||
rc = ProcessCreation::CreateProcess(proc_h.GetHandlePointer(), index, nca_path, launch_item, flags, reslimit_h.handle);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
ContentManagement::SetCreatedTitle(tid_sid.title_id);
|
||||
}
|
||||
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result ProcessManagerService::GetProgramInfo(OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info, Registration::TidSid tid_sid) {
|
||||
Result rc;
|
||||
char nca_path[FS_MAX_PATH] = {0};
|
||||
|
||||
/* Zero output. */
|
||||
std::fill(out_program_info.pointer, out_program_info.pointer + out_program_info.num_elements, ProcessManagerService::ProgramInfo{});
|
||||
|
||||
rc = PopulateProgramInfoBuffer(out_program_info.pointer, &tid_sid);
|
||||
|
||||
if (R_FAILED(rc)) {
|
||||
return {rc};
|
||||
}
|
||||
R_TRY(PopulateProgramInfoBuffer(out_program_info.pointer, &tid_sid));
|
||||
|
||||
if (tid_sid.storage_id != FsStorageId_None && tid_sid.title_id != out_program_info.pointer->title_id) {
|
||||
rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid);
|
||||
if (R_FAILED(rc)) {
|
||||
return {rc};
|
||||
R_TRY(ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid));
|
||||
R_TRY(ContentManagement::RedirectContentPath(nca_path, out_program_info.pointer->title_id, tid_sid.storage_id));
|
||||
R_TRY(LaunchQueue::AddCopy(tid_sid.title_id, out_program_info.pointer->title_id));
|
||||
}
|
||||
|
||||
rc = ContentManagement::RedirectContentPath(nca_path, out_program_info.pointer->title_id, tid_sid.storage_id);
|
||||
if (R_FAILED(rc)) {
|
||||
return {rc};
|
||||
}
|
||||
|
||||
rc = LaunchQueue::AddCopy(tid_sid.title_id, out_program_info.pointer->title_id);
|
||||
}
|
||||
|
||||
return {rc};
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
Result ProcessManagerService::RegisterTitle(Out<u64> index, Registration::TidSid tid_sid) {
|
||||
|
@ -97,30 +73,25 @@ Result ProcessManagerService::UnregisterTitle(u64 index) {
|
|||
|
||||
Result ProcessManagerService::PopulateProgramInfoBuffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid) {
|
||||
NpdmUtils::NpdmInfo info;
|
||||
Result rc;
|
||||
bool mounted_code = false;
|
||||
|
||||
/* Mount code, load NPDM. */
|
||||
{
|
||||
bool mounted_code = false;
|
||||
if (tid_sid->storage_id != FsStorageId_None) {
|
||||
rc = ContentManagement::MountCodeForTidSid(tid_sid);
|
||||
if (R_FAILED(rc)) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(ContentManagement::MountCodeForTidSid(tid_sid));
|
||||
mounted_code = true;
|
||||
} else if (R_SUCCEEDED(ContentManagement::MountCodeNspOnSd(tid_sid->title_id))) {
|
||||
mounted_code = true;
|
||||
}
|
||||
|
||||
rc = NpdmUtils::LoadNpdm(tid_sid->title_id, &info);
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
if (mounted_code) {
|
||||
ContentManagement::UnmountCode();
|
||||
}
|
||||
};
|
||||
|
||||
if (R_FAILED(rc)) {
|
||||
return rc;
|
||||
R_TRY(NpdmUtils::LoadNpdm(tid_sid->title_id, &info));
|
||||
}
|
||||
|
||||
|
||||
out->main_thread_priority = info.header->main_thread_prio;
|
||||
out->default_cpu_id = info.header->default_cpuid;
|
||||
out->main_thread_stack_size = info.header->main_stack_size;
|
||||
|
@ -131,34 +102,41 @@ Result ProcessManagerService::PopulateProgramInfoBuffer(ProcessManagerService::P
|
|||
out->aci0_fah_size = info.aci0->fah_size;
|
||||
|
||||
size_t offset = 0;
|
||||
rc = ResultLoaderInternalError;
|
||||
if (offset + info.acid->sac_size < sizeof(out->ac_buffer)) {
|
||||
|
||||
/* Copy ACID Service Access Control. */
|
||||
if (offset + info.acid->sac_size >= sizeof(out->ac_buffer)) {
|
||||
return ResultLoaderInternalError;
|
||||
}
|
||||
out->acid_sac_size = info.acid->sac_size;
|
||||
std::memcpy(out->ac_buffer + offset, info.acid_sac, out->acid_sac_size);
|
||||
offset += out->acid_sac_size;
|
||||
if (offset + info.aci0->sac_size < sizeof(out->ac_buffer)) {
|
||||
|
||||
/* Copy ACI0 Service Access Control. */
|
||||
if (offset + info.aci0->sac_size >= sizeof(out->ac_buffer)) {
|
||||
return ResultLoaderInternalError;
|
||||
}
|
||||
out->aci0_sac_size = info.aci0->sac_size;
|
||||
std::memcpy(out->ac_buffer + offset, info.aci0_sac, out->aci0_sac_size);
|
||||
offset += out->aci0_sac_size;
|
||||
if (offset + info.acid->fac_size < sizeof(out->ac_buffer)) {
|
||||
|
||||
/* Copy ACID Filesystem Access Control. */
|
||||
if (offset + info.acid->fac_size >= sizeof(out->ac_buffer)) {
|
||||
return ResultLoaderInternalError;
|
||||
}
|
||||
out->acid_fac_size = info.acid->fac_size;
|
||||
std::memcpy(out->ac_buffer + offset, info.acid_fac, out->acid_fac_size);
|
||||
offset += out->acid_fac_size;
|
||||
if (offset + info.aci0->fah_size < sizeof(out->ac_buffer)) {
|
||||
|
||||
/* Copy ACI0 Filesystem Access Header. */
|
||||
if (offset + info.aci0->fah_size >= sizeof(out->ac_buffer)) {
|
||||
return ResultLoaderInternalError;
|
||||
}
|
||||
out->aci0_fah_size = info.aci0->fah_size;
|
||||
std::memcpy(out->ac_buffer + offset, info.aci0_fah, out->aci0_fah_size);
|
||||
offset += out->aci0_fah_size;
|
||||
rc = ResultSuccess;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse application type. */
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
out->application_type = NpdmUtils::GetApplicationType((u32 *)info.acid_kac, info.acid->kac_size / sizeof(u32));
|
||||
}
|
||||
out->application_type = NpdmUtils::GetApplicationType(reinterpret_cast<const u32 *>(info.acid_kac), info.acid->kac_size / sizeof(u32));
|
||||
|
||||
|
||||
return rc;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
|
|
@ -34,10 +34,7 @@ Result ShellService::SetExternalContentSource(Out<MovedHandle> out, u64 tid) {
|
|||
Handle server_h;
|
||||
Handle client_h;
|
||||
|
||||
Result rc;
|
||||
if (R_FAILED(rc = svcCreateSession(&server_h, &client_h, 0, 0))) {
|
||||
return rc;
|
||||
}
|
||||
R_TRY(svcCreateSession(&server_h, &client_h, 0, 0));
|
||||
|
||||
Service service;
|
||||
serviceCreate(&service, client_h);
|
||||
|
|
Loading…
Reference in a new issue