loader: refactor ro manager/improve accuracy
This commit is contained in:
@@ -48,13 +48,13 @@ namespace ams::ldr::args {
|
||||
}
|
||||
|
||||
Result Set(ncm::ProgramId program_id, const void *args, size_t args_size) {
|
||||
R_UNLESS(args_size < ArgumentSizeMax, ldr::ResultTooLongArgument());
|
||||
R_UNLESS(args_size < ArgumentSizeMax, ldr::ResultArgumentOverflow());
|
||||
|
||||
ArgumentInfo *arg_info = FindArgumentInfo(program_id);
|
||||
if (arg_info == nullptr) {
|
||||
arg_info = FindFreeArgumentInfo();
|
||||
}
|
||||
R_UNLESS(arg_info != nullptr, ldr::ResultTooManyArguments());
|
||||
R_UNLESS(arg_info != nullptr, ldr::ResultArgumentCountOverflow());
|
||||
|
||||
arg_info->program_id = program_id;
|
||||
arg_info->args_size = args_size;
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "ldr_process_creation.hpp"
|
||||
#include "ldr_launch_record.hpp"
|
||||
#include "ldr_loader_service.hpp"
|
||||
#include "ldr_ro_manager.hpp"
|
||||
|
||||
namespace ams::ldr {
|
||||
|
||||
@@ -64,7 +63,7 @@ namespace ams::ldr {
|
||||
char path[fs::EntryNameLengthMax];
|
||||
|
||||
/* Get location and override status. */
|
||||
R_TRY(ldr::ro::GetProgramLocationAndStatus(std::addressof(loc), std::addressof(override_status), id));
|
||||
R_TRY(ldr::GetProgramLocationAndOverrideStatusFromPinId(std::addressof(loc), std::addressof(override_status), id));
|
||||
|
||||
if (loc.storage_id != static_cast<u8>(ncm::StorageId::None)) {
|
||||
R_TRY(ResolveContentPath(path, loc));
|
||||
@@ -87,11 +86,11 @@ namespace ams::ldr {
|
||||
}
|
||||
|
||||
Result LoaderService::PinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc) {
|
||||
return ldr::ro::PinProgram(out_id.GetPointer(), loc, cfg::OverrideStatus{});
|
||||
return ldr::PinProgram(out_id.GetPointer(), loc, cfg::OverrideStatus{});
|
||||
}
|
||||
|
||||
Result LoaderService::UnpinProgram(PinId id) {
|
||||
return ldr::ro::UnpinProgram(id);
|
||||
return ldr::UnpinProgram(id);
|
||||
}
|
||||
|
||||
Result LoaderService::SetProgramArgumentsDeprecated(ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size) {
|
||||
@@ -107,8 +106,9 @@ namespace ams::ldr {
|
||||
}
|
||||
|
||||
Result LoaderService::GetProcessModuleInfo(sf::Out<u32> count, const sf::OutPointerArray<ModuleInfo> &out, os::ProcessId process_id) {
|
||||
R_UNLESS(out.GetSize() <= std::numeric_limits<s32>::max(), ldr::ResultInvalidSize());
|
||||
return ldr::ro::GetProcessModuleInfo(count.GetPointer(), out.GetPointer(), out.GetSize(), process_id);
|
||||
*count = 0;
|
||||
std::memset(out.GetPointer(), 0, out.GetSize() * sizeof(ldr::ModuleInfo));
|
||||
return ldr::GetProcessModuleInfo(count.GetPointer(), out.GetPointer(), out.GetSize(), process_id);
|
||||
}
|
||||
|
||||
Result LoaderService::SetEnabledProgramVerification(bool enabled) {
|
||||
@@ -138,7 +138,7 @@ namespace ams::ldr {
|
||||
}
|
||||
|
||||
Result LoaderService::AtmospherePinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status) {
|
||||
return ldr::ro::PinProgram(out_id.GetPointer(), loc, override_status);
|
||||
return ldr::PinProgram(out_id.GetPointer(), loc, override_status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ namespace ams::ldr {
|
||||
R_TRY(fs::GetFileSize(std::addressof(npdm_size), file));
|
||||
|
||||
/* Read data into cache buffer. */
|
||||
R_UNLESS(npdm_size <= static_cast<s64>(MetaCacheBufferSize), ldr::ResultTooLargeMeta());
|
||||
R_UNLESS(npdm_size <= static_cast<s64>(MetaCacheBufferSize), ldr::ResultMetaOverflow());
|
||||
R_TRY(fs::ReadFile(file, 0, cache->buffer, npdm_size));
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace ams::ldr {
|
||||
AMS_ASSUME(ofs < sizeof(module_id));
|
||||
AMS_ASSUME(str[1] != 0);
|
||||
|
||||
module_id.build_id[ofs] = (ParseNybble(str[0]) << 4) | (ParseNybble(str[1]) << 0);
|
||||
module_id.data[ofs] = (ParseNybble(str[0]) << 4) | (ParseNybble(str[1]) << 0);
|
||||
|
||||
str += 2;
|
||||
ofs++;
|
||||
@@ -112,21 +112,21 @@ namespace ams::ldr {
|
||||
}
|
||||
|
||||
/* Apply IPS patches. */
|
||||
void LocateAndApplyIpsPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size) {
|
||||
void LocateAndApplyIpsPatchesToModule(const u8 *module_id_data, uintptr_t mapped_nso, size_t mapped_size) {
|
||||
if (!EnsureSdCardMounted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ro::ModuleId module_id;
|
||||
std::memcpy(std::addressof(module_id.build_id), build_id, sizeof(module_id.build_id));
|
||||
std::memcpy(std::addressof(module_id.data), module_id_data, sizeof(module_id.data));
|
||||
ams::patcher::LocateAndApplyIpsPatchesToModule(LoaderSdMountName, NsoPatchesDirectory, NsoPatchesProtectedSize, NsoPatchesProtectedOffset, std::addressof(module_id), reinterpret_cast<u8 *>(mapped_nso), mapped_size);
|
||||
}
|
||||
|
||||
/* Apply embedded patches. */
|
||||
void ApplyEmbeddedPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size) {
|
||||
void ApplyEmbeddedPatchesToModule(const u8 *module_id_data, uintptr_t mapped_nso, size_t mapped_size) {
|
||||
/* Make module id. */
|
||||
ro::ModuleId module_id;
|
||||
std::memcpy(std::addressof(module_id.build_id), build_id, sizeof(module_id.build_id));
|
||||
std::memcpy(std::addressof(module_id.data), module_id_data, sizeof(module_id.data));
|
||||
|
||||
if (IsUsb30ForceEnabled()) {
|
||||
for (const auto &patch : Usb30ForceEnablePatches) {
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
namespace ams::ldr {
|
||||
|
||||
/* Apply IPS patches. */
|
||||
void LocateAndApplyIpsPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size);
|
||||
void LocateAndApplyIpsPatchesToModule(const u8 *module_id_data, uintptr_t mapped_nso, size_t mapped_size);
|
||||
|
||||
/* Apply embedded patches. */
|
||||
void ApplyEmbeddedPatchesToModule(const u8 *build_id, uintptr_t mapped_nso, size_t mapped_size);
|
||||
void ApplyEmbeddedPatchesToModule(const u8 *module_id_data, uintptr_t mapped_nso, size_t mapped_size);
|
||||
|
||||
}
|
||||
@@ -591,10 +591,10 @@ namespace ams::ldr {
|
||||
std::memset(reinterpret_cast<void *>(map_address + rw_end), 0, nso_header->bss_size);
|
||||
|
||||
/* Apply embedded patches. */
|
||||
ApplyEmbeddedPatchesToModule(nso_header->build_id, map_address, nso_size);
|
||||
ApplyEmbeddedPatchesToModule(nso_header->module_id, map_address, nso_size);
|
||||
|
||||
/* Apply IPS patches. */
|
||||
LocateAndApplyIpsPatchesToModule(nso_header->build_id, map_address, nso_size);
|
||||
LocateAndApplyIpsPatchesToModule(nso_header->module_id, map_address, nso_size);
|
||||
}
|
||||
|
||||
/* Set permissions. */
|
||||
@@ -683,24 +683,32 @@ namespace ams::ldr {
|
||||
ProcessInfo info;
|
||||
R_TRY(CreateProcessImpl(std::addressof(info), std::addressof(meta), nso_headers, has_nso, arg_info, flags, reslimit_h));
|
||||
|
||||
/* Ensure we close the process handle, if we fail. */
|
||||
ON_SCOPE_EXIT { os::CloseNativeHandle(info.process_handle); };
|
||||
|
||||
/* Load NSOs into process memory. */
|
||||
R_TRY(LoadNsosIntoProcessMemory(std::addressof(info), nso_headers, has_nso, arg_info));
|
||||
{
|
||||
/* Ensure we close the process handle, if we fail. */
|
||||
auto process_guard = SCOPE_GUARD { os::CloseNativeHandle(info.process_handle); };
|
||||
|
||||
/* Register NSOs with ro manager. */
|
||||
/* Load all NSOs. */
|
||||
R_TRY(LoadNsosIntoProcessMemory(std::addressof(info), nso_headers, has_nso, arg_info));
|
||||
|
||||
/* We don't need to close the process handle, since we succeeded. */
|
||||
process_guard.Cancel();
|
||||
}
|
||||
|
||||
/* Register NSOs with the RoManager. */
|
||||
{
|
||||
/* Nintendo doesn't validate this get, but we do. */
|
||||
os::ProcessId process_id = os::GetProcessId(info.process_handle);
|
||||
|
||||
/* Register new process. */
|
||||
ldr::ro::RegisterProcess(pin_id, process_id, loc.program_id);
|
||||
/* NOTE: Nintendo uses meta->aci->program_id, not loc.program_id. Should we? */
|
||||
const auto as_type = GetAddressSpaceType(std::addressof(meta));
|
||||
RoManager::GetInstance().RegisterProcess(pin_id, process_id, loc.program_id, as_type == Npdm::AddressSpaceType_64Bit || as_type == Npdm::AddressSpaceType_64BitDeprecated);
|
||||
|
||||
/* Register all NSOs. */
|
||||
for (size_t i = 0; i < Nso_Count; i++) {
|
||||
if (has_nso[i]) {
|
||||
ldr::ro::RegisterModule(pin_id, nso_headers[i].build_id, info.nso_address[i], info.nso_size[i]);
|
||||
RoManager::GetInstance().AddNso(pin_id, nso_headers[i].module_id, info.nso_address[i], info.nso_size[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -719,7 +727,6 @@ namespace ams::ldr {
|
||||
|
||||
/* Move the process handle to output. */
|
||||
*out = info.process_handle;
|
||||
info.process_handle = os::InvalidNativeHandle;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
@@ -741,4 +748,24 @@ namespace ams::ldr {
|
||||
return GetProgramInfoFromMeta(out, std::addressof(meta));
|
||||
}
|
||||
|
||||
Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status) {
|
||||
R_UNLESS(RoManager::GetInstance().Allocate(out_id, loc, override_status), ldr::ResultMaxProcess());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result UnpinProgram(PinId id) {
|
||||
R_UNLESS(RoManager::GetInstance().Free(id), ldr::ResultNotPinned());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) {
|
||||
R_UNLESS(RoManager::GetInstance().GetProcessModuleInfo(out_count, out, max_out_count, process_id), ldr::ResultNotPinned());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result GetProgramLocationAndOverrideStatusFromPinId(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id) {
|
||||
R_UNLESS(RoManager::GetInstance().GetProgramLocationAndStatus(out, out_status, pin_id), ldr::ResultNotPinned());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,4 +22,11 @@ namespace ams::ldr {
|
||||
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, u32 flags, os::NativeHandle reslimit_h);
|
||||
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc);
|
||||
|
||||
Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
|
||||
Result UnpinProgram(PinId id);
|
||||
|
||||
Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id);
|
||||
|
||||
Result GetProgramLocationAndOverrideStatusFromPinId(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,147 +16,166 @@
|
||||
#include <stratosphere.hpp>
|
||||
#include "ldr_ro_manager.hpp"
|
||||
|
||||
namespace ams::ldr::ro {
|
||||
namespace ams::ldr {
|
||||
|
||||
namespace {
|
||||
|
||||
/* Convenience definitions. */
|
||||
constexpr PinId InvalidPinId = {};
|
||||
constexpr size_t ProcessCountMax = 0x40;
|
||||
constexpr size_t ModuleCountMax = 0x20;
|
||||
|
||||
/* Types. */
|
||||
struct ModuleInfo {
|
||||
ldr::ModuleInfo info;
|
||||
bool in_use;
|
||||
};
|
||||
|
||||
struct ProcessInfo {
|
||||
PinId pin_id;
|
||||
os::ProcessId process_id;
|
||||
ncm::ProgramId program_id;
|
||||
cfg::OverrideStatus override_status;
|
||||
ncm::ProgramLocation loc;
|
||||
ModuleInfo modules[ModuleCountMax];
|
||||
bool in_use;
|
||||
};
|
||||
|
||||
/* Globals. */
|
||||
ProcessInfo g_process_infos[ProcessCountMax];
|
||||
u64 g_cur_pin_id = 1;
|
||||
|
||||
/* Helpers. */
|
||||
ProcessInfo *GetProcessInfo(PinId pin_id) {
|
||||
for (size_t i = 0; i < ProcessCountMax; i++) {
|
||||
ProcessInfo *info = g_process_infos + i;
|
||||
if (info->in_use && info->pin_id == pin_id) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ProcessInfo *GetProcessInfo(os::ProcessId process_id) {
|
||||
for (size_t i = 0; i < ProcessCountMax; i++) {
|
||||
ProcessInfo *info = g_process_infos + i;
|
||||
if (info->in_use && info->process_id == process_id) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ProcessInfo *GetFreeProcessInfo() {
|
||||
for (size_t i = 0; i < ProcessCountMax; i++) {
|
||||
ProcessInfo *info = g_process_infos + i;
|
||||
if (!info->in_use) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* RO Manager API. */
|
||||
Result PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {
|
||||
bool RoManager::Allocate(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) {
|
||||
/* Ensure that output pin id is set. */
|
||||
*out = InvalidPinId;
|
||||
ProcessInfo *info = GetFreeProcessInfo();
|
||||
R_UNLESS(info != nullptr, ldr::ResultTooManyProcesses());
|
||||
|
||||
std::memset(info, 0, sizeof(*info));
|
||||
info->pin_id = { g_cur_pin_id++ };
|
||||
info->loc = loc;
|
||||
info->override_status = status;
|
||||
info->in_use = true;
|
||||
*out = info->pin_id;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result UnpinProgram(PinId id) {
|
||||
ProcessInfo *info = GetProcessInfo(id);
|
||||
R_UNLESS(info != nullptr, ldr::ResultNotPinned());
|
||||
|
||||
info->in_use = false;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
||||
Result GetProgramLocationAndStatus(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId id) {
|
||||
ProcessInfo *info = GetProcessInfo(id);
|
||||
R_UNLESS(info != nullptr, ldr::ResultNotPinned());
|
||||
|
||||
*out = info->loc;
|
||||
*out_status = info->override_status;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result RegisterProcess(PinId id, os::ProcessId process_id, ncm::ProgramId program_id) {
|
||||
ProcessInfo *info = GetProcessInfo(id);
|
||||
R_UNLESS(info != nullptr, ldr::ResultNotPinned());
|
||||
|
||||
info->program_id = program_id;
|
||||
info->process_id = process_id;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result RegisterModule(PinId id, const u8 *build_id, uintptr_t address, size_t size) {
|
||||
ProcessInfo *info = GetProcessInfo(id);
|
||||
R_UNLESS(info != nullptr, ldr::ResultNotPinned());
|
||||
|
||||
/* Nintendo doesn't actually care about successful allocation. */
|
||||
for (size_t i = 0; i < ModuleCountMax; i++) {
|
||||
ModuleInfo *module = info->modules + i;
|
||||
if (module->in_use) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::memcpy(module->info.build_id, build_id, sizeof(module->info.build_id));
|
||||
module->info.base_address = address;
|
||||
module->info.size = size;
|
||||
module->in_use = true;
|
||||
break;
|
||||
/* Allocate a process info. */
|
||||
auto *found = this->AllocateProcessInfo();
|
||||
if (found == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
/* Setup the process info. */
|
||||
std::memset(found, 0, sizeof(*found));
|
||||
found->pin_id = { ++m_pin_id };
|
||||
found->program_location = loc;
|
||||
found->override_status = status;
|
||||
found->in_use = true;
|
||||
|
||||
/* Set the output pin id. */
|
||||
*out = found->pin_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) {
|
||||
const ProcessInfo *info = GetProcessInfo(process_id);
|
||||
R_UNLESS(info != nullptr, ldr::ResultNotPinned());
|
||||
bool RoManager::Free(PinId pin_id) {
|
||||
/* Find the process. */
|
||||
auto *found = this->FindProcessInfo(pin_id);
|
||||
if (found == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the process as not in use. */
|
||||
found->in_use = false;
|
||||
|
||||
/* Set all the process's nsos as not in use. */
|
||||
for (auto i = 0; i < NsoCount; ++i) {
|
||||
found->nso_infos[i].in_use = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RoManager::RegisterProcess(PinId pin_id, os::ProcessId process_id, ncm::ProgramId program_id, bool is_64_bit_address_space) {
|
||||
/* Find the process. */
|
||||
auto *found = this->FindProcessInfo(pin_id);
|
||||
if (found == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the process id and program id. */
|
||||
found->process_id = process_id;
|
||||
found->program_id = program_id;
|
||||
AMS_UNUSED(is_64_bit_address_space);
|
||||
}
|
||||
|
||||
bool RoManager::GetProgramLocationAndStatus(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id) {
|
||||
/* Find the process. */
|
||||
auto *found = this->FindProcessInfo(pin_id);
|
||||
if (found == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Set the output location/status. */
|
||||
*out = found->program_location;
|
||||
*out_status = found->override_status;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RoManager::AddNso(PinId pin_id, const u8 *module_id, u64 address, u64 size) {
|
||||
/* Find the process. */
|
||||
auto *found = this->FindProcessInfo(pin_id);
|
||||
if (found == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Allocate an nso. */
|
||||
auto *info = this->AllocateNsoInfo(found);
|
||||
if (info == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy the information into the nso info. */
|
||||
std::memcpy(info->module_info.module_id, module_id, sizeof(info->module_info.module_id));
|
||||
info->module_info.address = address;
|
||||
info->module_info.size = size;
|
||||
info->in_use = true;
|
||||
}
|
||||
|
||||
bool RoManager::GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) {
|
||||
/* Find the process. */
|
||||
auto *found = this->FindProcessInfo(process_id);
|
||||
if (found == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Copy allocated nso module infos. */
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < ModuleCountMax && count < max_out_count; i++) {
|
||||
const ModuleInfo *module = info->modules + i;
|
||||
if (!module->in_use) {
|
||||
for (auto i = 0; i < NsoCount && count < max_out_count; ++i) {
|
||||
/* Skip unallocated nsos. */
|
||||
if (!found->nso_infos[i].in_use) {
|
||||
continue;
|
||||
}
|
||||
|
||||
out[count++] = module->info;
|
||||
/* Copy out the module info. */
|
||||
out[count++] = found->nso_infos[i].module_info;
|
||||
}
|
||||
|
||||
*out_count = static_cast<u32>(count);
|
||||
return ResultSuccess();
|
||||
/* Set the output count. */
|
||||
*out_count = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
RoManager::ProcessInfo *RoManager::AllocateProcessInfo() {
|
||||
for (auto i = 0; i < ProcessCount; ++i) {
|
||||
if (!m_processes[i].in_use) {
|
||||
return m_processes + i;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RoManager::ProcessInfo *RoManager::FindProcessInfo(PinId pin_id) {
|
||||
for (auto i = 0; i < ProcessCount; ++i) {
|
||||
if (m_processes[i].in_use && m_processes[i].pin_id == pin_id) {
|
||||
return m_processes + i;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RoManager::ProcessInfo *RoManager::FindProcessInfo(os::ProcessId process_id) {
|
||||
for (auto i = 0; i < ProcessCount; ++i) {
|
||||
if (m_processes[i].in_use && m_processes[i].process_id == process_id) {
|
||||
return m_processes + i;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RoManager::ProcessInfo *RoManager::FindProcessInfo(ncm::ProgramId program_id) {
|
||||
for (auto i = 0; i < ProcessCount; ++i) {
|
||||
if (m_processes[i].in_use && m_processes[i].program_id == program_id) {
|
||||
return m_processes + i;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RoManager::NsoInfo *RoManager::AllocateNsoInfo(ProcessInfo *info) {
|
||||
for (auto i = 0; i < NsoCount; ++i) {
|
||||
if (!info->nso_infos[i].in_use) {
|
||||
return info->nso_infos + i;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,14 +16,50 @@
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::ldr::ro {
|
||||
namespace ams::ldr {
|
||||
|
||||
/* RO Manager API. */
|
||||
Result PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status);
|
||||
Result UnpinProgram(PinId id);
|
||||
Result GetProgramLocationAndStatus(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId id);
|
||||
Result RegisterProcess(PinId id, os::ProcessId process_id, ncm::ProgramId program_id);
|
||||
Result RegisterModule(PinId id, const u8 *build_id, uintptr_t address, size_t size);
|
||||
Result GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id);
|
||||
class RoManager {
|
||||
AMS_CONSTINIT_SINGLETON_TRAITS(RoManager);
|
||||
public:
|
||||
static constexpr PinId InvalidPinId = {};
|
||||
static constexpr int ProcessCount = 0x40;
|
||||
static constexpr int NsoCount = 0x20;
|
||||
private:
|
||||
struct NsoInfo {
|
||||
bool in_use;
|
||||
ldr::ModuleInfo module_info;
|
||||
};
|
||||
|
||||
struct ProcessInfo {
|
||||
bool in_use;
|
||||
PinId pin_id;
|
||||
os::ProcessId process_id;
|
||||
ncm::ProgramId program_id;
|
||||
cfg::OverrideStatus override_status;
|
||||
ncm::ProgramLocation program_location;
|
||||
NsoInfo nso_infos[NsoCount];
|
||||
};
|
||||
private:
|
||||
ProcessInfo m_processes[ProcessCount];
|
||||
u64 m_pin_id;
|
||||
public:
|
||||
bool Allocate(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status);
|
||||
bool Free(PinId pin_id);
|
||||
|
||||
void RegisterProcess(PinId pin_id, os::ProcessId process_id, ncm::ProgramId program_id, bool is_64_bit_address_space);
|
||||
|
||||
bool GetProgramLocationAndStatus(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id);
|
||||
|
||||
void AddNso(PinId pin_id, const u8 *module_id, u64 address, u64 size);
|
||||
|
||||
bool GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id);
|
||||
private:
|
||||
ProcessInfo *AllocateProcessInfo();
|
||||
ProcessInfo *FindProcessInfo(PinId pin_id);
|
||||
ProcessInfo *FindProcessInfo(os::ProcessId process_id);
|
||||
ProcessInfo *FindProcessInfo(ncm::ProgramId program_id);
|
||||
|
||||
NsoInfo *AllocateNsoInfo(ProcessInfo *info);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user