mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
Loader: Implement ldr:ro->LoadNRR(). NOTE: No sigchecks, at the moment.
This commit is contained in:
parent
789afe7929
commit
8524f284fd
6 changed files with 143 additions and 25 deletions
|
@ -1,8 +1,6 @@
|
|||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#include "ldr_registration.hpp"
|
||||
|
||||
class MapUtils {
|
||||
public:
|
||||
struct AddressSpaceInfo {
|
||||
|
@ -69,4 +67,64 @@ class AutoCloseMap {
|
|||
this->mapped_address = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct MappedCodeMemory {
|
||||
Handle process_handle;
|
||||
u64 base_address;
|
||||
u64 size;
|
||||
u64 code_memory_address;
|
||||
void *mapped_address;
|
||||
|
||||
bool IsActive() {
|
||||
return this->mapped_address != NULL;
|
||||
}
|
||||
|
||||
/* Utility functions. */
|
||||
Result Open(Handle process_h, bool is_64_bit_address_space, u64 address, u64 size) {
|
||||
Result rc;
|
||||
u64 try_address;
|
||||
if (this->IsActive()) {
|
||||
return 0x19009;
|
||||
}
|
||||
|
||||
this->process_handle = process_h;
|
||||
this->base_address = address;
|
||||
this->size = size;
|
||||
|
||||
if (R_FAILED((rc = MapUtils::MapCodeMemoryForProcess(process_h, is_64_bit_address_space, address, size, &this->code_memory_address)))) {
|
||||
goto CODE_MEMORY_OPEN_END;
|
||||
}
|
||||
|
||||
if (R_FAILED(rc = MapUtils::LocateSpaceForMap(&try_address, size))) {
|
||||
goto CODE_MEMORY_OPEN_END;
|
||||
}
|
||||
|
||||
if (R_FAILED((rc = svcMapProcessMemory((void *)try_address, process_h, try_address, size)))) {
|
||||
goto CODE_MEMORY_OPEN_END;
|
||||
}
|
||||
|
||||
this->mapped_address = (void *)try_address;
|
||||
|
||||
CODE_MEMORY_OPEN_END:
|
||||
if (R_FAILED(rc)) {
|
||||
if (this->code_memory_address && R_FAILED(svcUnmapProcessCodeMemory(this->process_handle, this->code_memory_address, this->base_address, this->size))) {
|
||||
/* TODO: panic(). */
|
||||
}
|
||||
*this = (const MappedCodeMemory){0};
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void Close() {
|
||||
if (this->IsActive()) {
|
||||
if (R_FAILED(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size))) {
|
||||
/* TODO: panic(). */
|
||||
}
|
||||
if (R_FAILED(svcUnmapProcessCodeMemory(this->process_handle, this->code_memory_address, this->base_address, this->size))) {
|
||||
/* TODO: panic(). */
|
||||
}
|
||||
*this = (const MappedCodeMemory){0};
|
||||
}
|
||||
}
|
||||
};
|
28
stratosphere/loader/source/ldr_nro.cpp
Normal file
28
stratosphere/loader/source/ldr_nro.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <switch.h>
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <picosha2.hpp>
|
||||
#include "ldr_nro.hpp"
|
||||
#include "ldr_map.hpp"
|
||||
#include "ldr_random.hpp"
|
||||
|
||||
Result NroUtils::ValidateNrrHeader(NrrHeader *header, u64 size, u64 title_id_min) {
|
||||
if (header->magic != MAGIC_NRR0) {
|
||||
return 0x6A09;
|
||||
}
|
||||
if (header->nrr_size != size) {
|
||||
return 0xA409;
|
||||
}
|
||||
|
||||
/* TODO: Check NRR signature. */
|
||||
if (false) {
|
||||
return 0x6C09;
|
||||
}
|
||||
|
||||
if (header->title_id_min != title_id_min) {
|
||||
return 0x6A09;
|
||||
}
|
||||
|
||||
return 0x0;
|
||||
}
|
33
stratosphere/loader/source/ldr_nro.hpp
Normal file
33
stratosphere/loader/source/ldr_nro.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <cstdio>
|
||||
|
||||
#define MAGIC_NRO0 0x304F524E
|
||||
#define MAGIC_NRR0 0x3052524E
|
||||
|
||||
class NroUtils {
|
||||
public:
|
||||
struct NrrHeader {
|
||||
u32 magic;
|
||||
u32 _0x4;
|
||||
u32 _0x8;
|
||||
u32 _0xC;
|
||||
u64 title_id_mask;
|
||||
u64 title_id_pattern;
|
||||
u64 _0x20;
|
||||
u64 _0x28;
|
||||
u8 modulus[0x100];
|
||||
u8 fixed_key_signature[0x100];
|
||||
u8 nrr_signature[0x100];
|
||||
u64 title_id_min;
|
||||
u32 nrr_size;
|
||||
u32 _0x33C;
|
||||
u32 hash_offset;
|
||||
u32 num_hashes;
|
||||
u64 _0x348;
|
||||
};
|
||||
|
||||
|
||||
static_assert(sizeof(NrrHeader) == 0x350, "Incorrectly defined NrrHeader!");
|
||||
static Result ValidateNrrHeader(NrrHeader *header, u64 size, u64 title_id_min);
|
||||
};
|
|
@ -104,7 +104,7 @@ void Registration::AddNsoInfo(u64 index, u64 base_address, u64 size, const unsig
|
|||
}
|
||||
|
||||
|
||||
Result Registration::AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_memory_address, u64 loader_address) {
|
||||
Result Registration::AddNrrInfo(u64 index, MappedCodeMemory *nrr_info) {
|
||||
Registration::Process *target_process = GetProcess(index);
|
||||
if (target_process == NULL) {
|
||||
/* TODO: panic() */
|
||||
|
@ -112,11 +112,8 @@ Result Registration::AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_
|
|||
}
|
||||
|
||||
for (unsigned int i = 0; i < NSO_INFO_MAX; i++) {
|
||||
if (!target_process->nrr_infos[i].in_use) {
|
||||
target_process->nrr_infos[i].info.base_address = base_address;
|
||||
target_process->nrr_infos[i].info.size = size;
|
||||
target_process->nrr_infos[i].info.code_memory_address = code_memory_address;
|
||||
target_process->nrr_infos[i].info.loader_address = loader_address;
|
||||
if (!target_process->nrr_infos[i].IsActive()) {
|
||||
target_process->nrr_infos[i] = *nrr_info;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#include "ldr_map.hpp"
|
||||
|
||||
#define REGISTRATION_LIST_MAX (0x40)
|
||||
|
||||
#define NSO_INFO_MAX (0x20)
|
||||
|
@ -19,18 +21,6 @@ class Registration {
|
|||
NsoInfo info;
|
||||
};
|
||||
|
||||
struct NrrInfo {
|
||||
u64 base_address;
|
||||
u64 size;
|
||||
u64 code_memory_address;
|
||||
u64 loader_address;
|
||||
};
|
||||
|
||||
struct NrrInfoHolder {
|
||||
bool in_use;
|
||||
NrrInfo info;
|
||||
};
|
||||
|
||||
struct TidSid {
|
||||
u64 title_id;
|
||||
FsStorageId storage_id;
|
||||
|
@ -44,7 +34,7 @@ class Registration {
|
|||
u64 title_id_min;
|
||||
Registration::TidSid tid_sid;
|
||||
Registration::NsoInfoHolder nso_infos[NSO_INFO_MAX];
|
||||
Registration::NrrInfoHolder nrr_infos[NRR_INFO_MAX];
|
||||
MappedCodeMemory nrr_infos[NRR_INFO_MAX];
|
||||
void *owner_ro_service;
|
||||
};
|
||||
|
||||
|
@ -61,6 +51,6 @@ class Registration {
|
|||
static bool UnregisterIndex(u64 index);
|
||||
static void SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace);
|
||||
static void AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id);
|
||||
static Result AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_memory_address, u64 loader_address);
|
||||
static Result AddNrrInfo(u64 index, MappedCodeMemory *nrr_info);
|
||||
static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written);
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "ldr_ro_service.hpp"
|
||||
#include "ldr_registration.hpp"
|
||||
#include "ldr_map.hpp"
|
||||
#include "ldr_nro.hpp"
|
||||
|
||||
Result RelocatableObjectsService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||
Result rc = 0xF601;
|
||||
|
@ -44,7 +45,8 @@ std::tuple<Result> RelocatableObjectsService::unload_nro(PidDescriptor pid_desc,
|
|||
|
||||
std::tuple<Result> RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) {
|
||||
Result rc;
|
||||
Registration::Process *target_proc;
|
||||
Registration::Process *target_proc = NULL;
|
||||
MappedCodeMemory nrr_info = {0};
|
||||
if (!this->has_initialized || this->process_id != pid_desc.pid) {
|
||||
rc = 0xAE09;
|
||||
goto LOAD_NRR_END;
|
||||
|
@ -65,11 +67,21 @@ std::tuple<Result> RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u
|
|||
}
|
||||
target_proc->owner_ro_service = this;
|
||||
|
||||
if (R_FAILED((rc = nrr_info.Open(this->process_handle, target_proc->is_64_bit_addspace, nrr_address, nrr_size)))) {
|
||||
goto LOAD_NRR_END;
|
||||
}
|
||||
|
||||
/* TODO: Implement remainder of fucntion */
|
||||
rc = 0xDED09;
|
||||
rc = NroUtils::ValidateNrrHeader((NroUtils::NrrHeader *)nrr_info.mapped_address, nrr_size, target_proc->title_id_min);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
Registration::AddNrrInfo(target_proc->index, &nrr_info);
|
||||
}
|
||||
|
||||
LOAD_NRR_END:
|
||||
if (R_FAILED(rc)) {
|
||||
if (nrr_info.IsActive()) {
|
||||
nrr_info.Close();
|
||||
}
|
||||
}
|
||||
return std::make_tuple(rc);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue