loader: update for new-ipc

This commit is contained in:
Michael Scire 2019-10-14 21:40:05 -07:00 committed by SciresM
parent 88a86a3363
commit 2f959785e1
13 changed files with 124 additions and 84 deletions

View file

@ -16,6 +16,7 @@
#pragma once
#include <switch.h>
#include "../os/os_common_types.hpp"
#include "../ncm/ncm_types.hpp"
namespace sts::cfg {

View file

@ -20,11 +20,12 @@
#include <switch.h>
#include "../svc/svc_types.hpp"
#include "../ncm/ncm_types.hpp"
#include "../sf/sf_buffer_tags.hpp"
namespace sts::ldr {
/* General types. */
struct ProgramInfo {
struct ProgramInfo : sf::LargeData {
u8 main_thread_priority;
u8 default_cpu_id;
u16 flags;
@ -36,7 +37,7 @@ namespace sts::ldr {
u32 aci_fah_size;
u8 ac_buffer[0x3E0];
};
static_assert(sizeof(ProgramInfo) == 0x400, "ProgramInfo definition!");
static_assert(std::is_pod<ProgramInfo>::value && sizeof(ProgramInfo) == 0x400, "ProgramInfo definition!");
enum ProgramInfoFlag {
ProgramInfoFlag_SystemModule = (0 << 0),

View file

@ -15,6 +15,8 @@
*/
#pragma once
#include <switch.h>
#include "../results.hpp"
#include "../util.hpp"
namespace sts::os {

View file

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
namespace sts::sf {
/* Helper structs for serialization of buffers. */
struct LargeData{};
struct PrefersMapAliasTransferMode{};
struct PrefersPointerTransferMode{};
struct PrefersAutoSelectTransferMode{};
}

View file

@ -18,6 +18,7 @@
#include "sf_common.hpp"
#include "sf_out.hpp"
#include "cmif/sf_cmif_pointer_and_size.hpp"
#include "sf_buffer_tags.hpp"
namespace sts::sf {
@ -47,15 +48,6 @@ namespace sts::sf {
}
/* Helper structs for serialization of buffers. */
struct LargeData{};
struct PrefersMapAliasTransferMode{};
struct PrefersPointerTransferMode{};
struct PrefersAutoSelectTransferMode{};
template<typename T>
constexpr inline bool IsLargeData = std::is_base_of<sf::LargeData, T>::value;

View file

@ -32,8 +32,8 @@ namespace sts::ldr::ecs {
private:
char device_name[DeviceNameSizeMax];
public:
ExternalContentSource(const char *dn){
std::strncpy(this->device_name, dn, sizeof(this->device_name) - 1);
ExternalContentSource(const char *dn) {
std::strncpy(this->device_name, dn, sizeof(this->device_name));
this->device_name[sizeof(this->device_name) - 1] = '\0';
}

View file

@ -26,8 +26,8 @@
namespace sts::ldr {
/* Official commands. */
Result LoaderService::CreateProcess(Out<MovedHandle> proc_h, PinId id, u32 flags, CopiedHandle reslimit) {
os::ManagedHandle reslimit_holder(reslimit.GetValue());
Result LoaderService::CreateProcess(sf::OutMoveHandle proc_h, PinId id, u32 flags, sf::CopyHandle reslimit_h) {
os::ManagedHandle reslimit_holder(reslimit_h.GetValue());
ncm::TitleLocation loc;
char path[FS_MAX_PATH];
@ -41,12 +41,11 @@ namespace sts::ldr {
return ldr::CreateProcess(proc_h.GetHandlePointer(), id, loc, path, flags, reslimit_holder.Get());
}
Result LoaderService::GetProgramInfo(OutPointerWithServerSize<ProgramInfo, 0x1> out_program_info, ncm::TitleLocation loc) {
Result LoaderService::GetProgramInfo(sf::Out<ProgramInfo> out, const ncm::TitleLocation &loc) {
/* Zero output. */
ProgramInfo *out = out_program_info.pointer;
std::memset(out, 0, sizeof(*out));
std::memset(out.GetPointer(), 0, sizeof(*out.GetPointer()));
R_TRY(ldr::GetProgramInfo(out, loc));
R_TRY(ldr::GetProgramInfo(out.GetPointer(), loc));
if (loc.storage_id != static_cast<u8>(ncm::StorageId::None) && loc.title_id != out->title_id) {
char path[FS_MAX_PATH];
@ -64,7 +63,7 @@ namespace sts::ldr {
return ResultSuccess;
}
Result LoaderService::PinTitle(Out<PinId> out_id, ncm::TitleLocation loc) {
Result LoaderService::PinTitle(sf::Out<PinId> out_id, const ncm::TitleLocation &loc) {
return ldr::ro::PinTitle(out_id.GetPointer(), loc);
}
@ -72,24 +71,24 @@ namespace sts::ldr {
return ldr::ro::UnpinTitle(id);
}
Result LoaderService::SetTitleArguments(ncm::TitleId title_id, InPointer<char> args, u32 args_size) {
return args::Set(title_id, args.pointer, std::min(args.num_elements, size_t(args_size)));
Result LoaderService::SetTitleArguments(ncm::TitleId title_id, const sf::InPointerBuffer &args, u32 args_size) {
return args::Set(title_id, args.GetPointer(), std::min(args.GetSize(), size_t(args_size)));
}
Result LoaderService::ClearArguments() {
return args::Clear();
}
Result LoaderService::GetProcessModuleInfo(Out<u32> count, OutPointerWithClientSize<ModuleInfo> out, u64 process_id) {
if (out.num_elements > std::numeric_limits<s32>::max()) {
Result LoaderService::GetProcessModuleInfo(sf::Out<u32> count, const sf::OutPointerArray<ModuleInfo> &out, os::ProcessId process_id) {
if (out.GetSize() > std::numeric_limits<s32>::max()) {
return ResultLoaderInvalidSize;
}
return ldr::ro::GetProcessModuleInfo(count.GetPointer(), out.pointer, out.num_elements, process_id);
return ldr::ro::GetProcessModuleInfo(count.GetPointer(), out.GetPointer(), out.GetSize(), process_id);
}
/* Atmosphere commands. */
Result LoaderService::AtmosphereSetExternalContentSource(Out<MovedHandle> out, ncm::TitleId title_id) {
Result LoaderService::AtmosphereSetExternalContentSource(sf::OutMoveHandle out, ncm::TitleId title_id) {
return ecs::Set(out.GetHandlePointer(), title_id);
}
@ -97,7 +96,7 @@ namespace sts::ldr {
R_ASSERT(ecs::Clear(title_id));
}
void LoaderService::AtmosphereHasLaunchedTitle(Out<bool> out, ncm::TitleId title_id) {
void LoaderService::AtmosphereHasLaunchedTitle(sf::Out<bool> out, ncm::TitleId title_id) {
out.SetValue(ldr::HasLaunchedTitle(title_id));
}

View file

@ -21,25 +21,21 @@
namespace sts::ldr {
class LoaderService : public IServiceObject {
class LoaderService : public sf::IServiceObject {
protected:
/* Official commands. */
virtual Result CreateProcess(Out<MovedHandle> proc_h, PinId id, u32 flags, CopiedHandle reslimit_h);
virtual Result GetProgramInfo(OutPointerWithServerSize<ProgramInfo, 0x1> out_program_info, ncm::TitleLocation loc);
virtual Result PinTitle(Out<PinId> out_id, ncm::TitleLocation loc);
virtual Result CreateProcess(sf::OutMoveHandle proc_h, PinId id, u32 flags, sf::CopyHandle reslimit_h);
virtual Result GetProgramInfo(sf::Out<ProgramInfo> out_program_info, const ncm::TitleLocation &loc);
virtual Result PinTitle(sf::Out<PinId> out_id, const ncm::TitleLocation &loc);
virtual Result UnpinTitle(PinId id);
virtual Result SetTitleArguments(ncm::TitleId title_id, InPointer<char> args, u32 args_size);
virtual Result SetTitleArguments(ncm::TitleId title_id, const sf::InPointerBuffer &args, u32 args_size);
virtual Result ClearArguments();
virtual Result GetProcessModuleInfo(Out<u32> count, OutPointerWithClientSize<ModuleInfo> out, u64 process_id);
virtual Result GetProcessModuleInfo(sf::Out<u32> count, const sf::OutPointerArray<ModuleInfo> &out, os::ProcessId process_id);
/* Atmosphere commands. */
virtual Result AtmosphereSetExternalContentSource(Out<MovedHandle> out, ncm::TitleId title_id);
virtual Result AtmosphereSetExternalContentSource(sf::OutMoveHandle out, ncm::TitleId title_id);
virtual void AtmosphereClearExternalContentSource(ncm::TitleId title_id);
virtual void AtmosphereHasLaunchedTitle(Out<bool> out, ncm::TitleId title_id);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
/* No commands callable, as LoaderService is abstract. */
};
virtual void AtmosphereHasLaunchedTitle(sf::Out<bool> out, ncm::TitleId title_id);
};
namespace pm {
@ -56,12 +52,12 @@ namespace sts::ldr {
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(ProcessManagerInterface, CreateProcess),
MAKE_SERVICE_COMMAND_META(ProcessManagerInterface, GetProgramInfo),
MAKE_SERVICE_COMMAND_META(ProcessManagerInterface, PinTitle),
MAKE_SERVICE_COMMAND_META(ProcessManagerInterface, UnpinTitle),
MAKE_SERVICE_COMMAND_META(CreateProcess),
MAKE_SERVICE_COMMAND_META(GetProgramInfo),
MAKE_SERVICE_COMMAND_META(PinTitle),
MAKE_SERVICE_COMMAND_META(UnpinTitle),
MAKE_SERVICE_COMMAND_META(ProcessManagerInterface, AtmosphereHasLaunchedTitle),
MAKE_SERVICE_COMMAND_META(AtmosphereHasLaunchedTitle),
};
};
@ -80,11 +76,11 @@ namespace sts::ldr {
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(DebugMonitorInterface, SetTitleArguments),
MAKE_SERVICE_COMMAND_META(DebugMonitorInterface, ClearArguments),
MAKE_SERVICE_COMMAND_META(DebugMonitorInterface, GetProcessModuleInfo),
MAKE_SERVICE_COMMAND_META(SetTitleArguments),
MAKE_SERVICE_COMMAND_META(ClearArguments),
MAKE_SERVICE_COMMAND_META(GetProcessModuleInfo),
MAKE_SERVICE_COMMAND_META(DebugMonitorInterface, AtmosphereHasLaunchedTitle),
MAKE_SERVICE_COMMAND_META(AtmosphereHasLaunchedTitle),
};
};
@ -103,11 +99,11 @@ namespace sts::ldr {
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(ShellInterface, SetTitleArguments),
MAKE_SERVICE_COMMAND_META(ShellInterface, ClearArguments),
MAKE_SERVICE_COMMAND_META(SetTitleArguments),
MAKE_SERVICE_COMMAND_META(ClearArguments),
MAKE_SERVICE_COMMAND_META(ShellInterface, AtmosphereSetExternalContentSource),
MAKE_SERVICE_COMMAND_META(ShellInterface, AtmosphereClearExternalContentSource),
MAKE_SERVICE_COMMAND_META(AtmosphereSetExternalContentSource),
MAKE_SERVICE_COMMAND_META(AtmosphereClearExternalContentSource),
};
};

View file

@ -31,8 +31,9 @@ extern "C" {
extern u32 __start__;
u32 __nx_applet_type = AppletType_None;
u32 __nx_fs_num_sessions = 1;
#define INNER_HEAP_SIZE 0x30000
#define INNER_HEAP_SIZE 0x4000
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
char nx_inner_heap[INNER_HEAP_SIZE];
@ -66,8 +67,10 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
using namespace sts;
void __appInit(void) {
SetFirmwareVersionForLibnx();
hos::SetVersionForLibnx();
/* Initialize services we need. */
DoWithSmSession([&]() {
@ -87,23 +90,39 @@ void __appExit(void) {
fsExit();
}
struct LoaderServerOptions {
static constexpr size_t PointerBufferSize = 0x400;
static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0;
};
namespace {
struct ServerOptions {
static constexpr size_t PointerBufferSize = 0x400;
static constexpr size_t MaxDomains = 0;
static constexpr size_t MaxDomainObjects = 0;
};
constexpr sm::ServiceName ProcessManagerServiceName = sm::ServiceName::Encode("ldr:pm");
constexpr size_t ProcessManagerMaxSessions = 2;
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("ldr:shel");
constexpr size_t ShellMaxSessions = 3;
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ldr:dmnt");
constexpr size_t DebugMonitorMaxSessions = 3;
/* ldr:pm, ldr:shel, ldr:dmnt. */
constexpr size_t NumServers = 3;
constexpr size_t MaxSessions = ProcessManagerMaxSessions + ShellMaxSessions + DebugMonitorMaxSessions + 1;
sf::hipc::ServerManager<NumServers, ServerOptions, MaxSessions> g_server_manager;
}
int main(int argc, char **argv)
{
static auto s_server_manager = WaitableManager<LoaderServerOptions>(1);
/* Add services to manager. */
s_server_manager.AddWaitable(new ServiceServer<sts::ldr::pm::ProcessManagerInterface>("ldr:pm", 1));
s_server_manager.AddWaitable(new ServiceServer<sts::ldr::shell::ShellInterface>("ldr:shel", 3));
s_server_manager.AddWaitable(new ServiceServer<sts::ldr::dmnt::DebugMonitorInterface>("ldr:dmnt", 2));
R_ASSERT((g_server_manager.RegisterServer<ldr::pm::ProcessManagerInterface>(ProcessManagerServiceName, ProcessManagerMaxSessions)));
R_ASSERT((g_server_manager.RegisterServer<ldr::shell::ShellInterface>(ShellServiceName, ShellMaxSessions)));
R_ASSERT((g_server_manager.RegisterServer<ldr::dmnt::DebugMonitorInterface>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
/* Loop forever, servicing our services. */
s_server_manager.Process();
g_server_manager.LoopProcess();
return 0;
}

View file

@ -53,7 +53,7 @@ namespace sts::ldr {
}
/* Validate flags. */
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_700) {
if (hos::GetVersion() >= hos::Version_700) {
/* 7.0.0 added 0x10 as a valid bit to NPDM flags. */
if (npdm->flags & ~0x1F) {
return ResultLoaderInvalidMeta;
@ -182,7 +182,7 @@ namespace sts::ldr {
Meta *o_meta = &g_original_meta_cache.meta;
/* Fix pool partition. */
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
if (hos::GetVersion() >= hos::Version_500) {
meta->acid->flags = (meta->acid->flags & 0xFFFFFFC3) | (o_meta->acid->flags & 0x0000003C);
}

View file

@ -196,18 +196,18 @@ namespace sts::ldr {
constexpr size_t g_MinimumTitleVersionsCount900 = util::size(g_MinimumTitleVersions900);
Result ValidateTitleVersion(ncm::TitleId title_id, u32 version) {
if (GetRuntimeFirmwareVersion() < FirmwareVersion_810) {
if (hos::GetVersion() < hos::Version_810) {
return ResultSuccess;
} else {
#ifdef LDR_VALIDATE_PROCESS_VERSION
const MinimumTitleVersion *entries = nullptr;
size_t num_entries = 0;
switch (GetRuntimeFirmwareVersion()) {
case FirmwareVersion_810:
switch (hos::GetVersion()) {
case hos::Version_810:
entries = g_MinimumTitleVersions810;
num_entries = g_MinimumTitleVersionsCount810;
break;
case FirmwareVersion_900:
case hos::Version_900:
entries = g_MinimumTitleVersions900;
num_entries = g_MinimumTitleVersionsCount900;
break;
@ -383,7 +383,7 @@ namespace sts::ldr {
flags |= svc::CreateProcessFlag_IsApplication;
/* 7.0.0+: Set OptimizeMemoryAllocation if relevant. */
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_700) {
if (hos::GetVersion() >= hos::Version_700) {
if (meta_flags & Npdm::MetaFlag_OptimizeMemoryAllocation) {
flags |= svc::CreateProcessFlag_OptimizeMemoryAllocation;
}
@ -391,7 +391,7 @@ namespace sts::ldr {
}
/* 5.0.0+ Set Pool Partition. */
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_500) {
if (hos::GetVersion() >= hos::Version_500) {
switch (GetPoolPartition(meta)) {
case Acid::PoolPartition_Application:
if (IsApplet(meta)) {
@ -412,7 +412,7 @@ namespace sts::ldr {
default:
return ResultLoaderInvalidMeta;
}
} else if (GetRuntimeFirmwareVersion() >= FirmwareVersion_400) {
} else if (hos::GetVersion() >= hos::Version_400) {
/* On 4.0.0+, the corresponding bit was simply "UseSecureMemory". */
if (meta->acid->flags & Acid::AcidFlag_DeprecatedUseSecureMemory) {
flags |= svc::CreateProcessFlag_DeprecatedUseSecureMemory;
@ -437,7 +437,7 @@ namespace sts::ldr {
R_TRY(GetCreateProcessFlags(&out->flags, meta, flags));
/* 3.0.0+ System Resource Size. */
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_300) {
if (hos::GetVersion() >= hos::Version_300) {
/* Validate size is aligned. */
if (meta->npdm->system_resource_size & (SystemResourceSizeAlignment - 1)) {
return ResultLoaderInvalidSize;
@ -500,7 +500,7 @@ namespace sts::ldr {
/* Calculate ASLR. */
uintptr_t aslr_start = 0;
uintptr_t aslr_size = 0;
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) {
if (hos::GetVersion() >= hos::Version_200) {
switch (out_cpi->flags & svc::CreateProcessFlag_AddressSpaceMask) {
case svc::CreateProcessFlag_AddressSpace32Bit:
case svc::CreateProcessFlag_AddressSpace32BitWithoutAlias:
@ -723,10 +723,10 @@ namespace sts::ldr {
R_TRY(LoadNsosIntoProcessMemory(&info, loc.title_id, nso_headers, has_nso, arg_info));
/* Register NSOs with ro manager. */
u64 process_id;
os::ProcessId process_id = os::InvalidProcessId;
{
/* Nintendo doesn't validate this result, but we will. */
R_ASSERT(svcGetProcessId(&process_id, info.process_handle.Get()));
R_ASSERT(svcGetProcessId(&process_id.value, info.process_handle.Get()));
/* Register new process. */
ldr::ro::RegisterProcess(pin_id, process_id, loc.title_id);

View file

@ -34,7 +34,7 @@ namespace sts::ldr::ro {
struct ProcessInfo {
PinId pin_id;
u64 process_id;
os::ProcessId process_id;
ncm::TitleId title_id;
ncm::TitleLocation loc;
ModuleInfo modules[ModuleCountMax];
@ -55,7 +55,7 @@ namespace sts::ldr::ro {
return nullptr;
}
ProcessInfo *GetProcessInfo(u64 process_id) {
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) {
@ -116,7 +116,7 @@ namespace sts::ldr::ro {
return ResultSuccess;
}
Result RegisterProcess(PinId id, u64 process_id, ncm::TitleId title_id) {
Result RegisterProcess(PinId id, os::ProcessId process_id, ncm::TitleId title_id) {
ProcessInfo *info = GetProcessInfo(id);
if (info == nullptr) {
return ResultLoaderNotPinned;
@ -150,7 +150,7 @@ namespace sts::ldr::ro {
return ResultSuccess;
}
Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, u64 process_id) {
Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) {
const ProcessInfo *info = GetProcessInfo(process_id);
if (info == nullptr) {
return ResultLoaderNotPinned;

View file

@ -25,8 +25,8 @@ namespace sts::ldr::ro {
Result PinTitle(PinId *out, const ncm::TitleLocation &loc);
Result UnpinTitle(PinId id);
Result GetTitleLocation(ncm::TitleLocation *out, PinId id);
Result RegisterProcess(PinId id, u64 process_id, ncm::TitleId title_id);
Result RegisterProcess(PinId id, os::ProcessId process_id, ncm::TitleId title_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, u64 process_id);
Result GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id);
}