ro: update for new sf semantics

This commit is contained in:
Michael Scire
2021-01-17 22:03:26 -08:00
parent bc9da91362
commit fb6a4e28a5
23 changed files with 192 additions and 119 deletions

View File

@@ -20,18 +20,49 @@ namespace ams::ldr {
namespace {
/* Global cache. */
std::set<u64> g_launched_programs;
static constexpr size_t MaxBootPrograms = 0x50;
constinit std::array<ncm::ProgramId, MaxBootPrograms> g_launched_boot_programs = [] {
std::array<ncm::ProgramId, MaxBootPrograms> arr = {};
for (size_t i = 0; i < MaxBootPrograms; ++i) {
arr[i] = ncm::InvalidProgramId;
}
return arr;
}();
constinit bool g_boot_programs_done = false;
bool HasLaunchedBootProgramImpl(ncm::ProgramId program_id) {
for (const auto &launched : g_launched_boot_programs) {
if (launched == program_id) {
return true;
}
}
return false;
}
void SetLaunchedBootProgramImpl(ncm::ProgramId program_id) {
for (size_t i = 0; i < MaxBootPrograms; ++i) {
if (g_launched_boot_programs[i] == ncm::InvalidProgramId) {
g_launched_boot_programs[i] = program_id;
}
}
AMS_ABORT("Too many boot programs");
}
}
/* Launch Record API. */
bool HasLaunchedProgram(ncm::ProgramId program_id) {
return g_launched_programs.find(program_id.value) != g_launched_programs.end();
bool HasLaunchedBootProgram(ncm::ProgramId program_id) {
return HasLaunchedBootProgramImpl(program_id);
}
void SetLaunchedProgram(ncm::ProgramId program_id) {
g_launched_programs.insert(program_id.value);
void SetLaunchedBootProgram(ncm::ProgramId program_id) {
if (!g_boot_programs_done) {
SetLaunchedBootProgramImpl(program_id);
if (program_id == ncm::SystemAppletId::Qlaunch) {
g_boot_programs_done = true;
}
}
}
}
@@ -40,8 +71,8 @@ namespace ams::ldr {
/* This is necessary to prevent circular dependencies. */
namespace ams::pm::info {
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
*out = ldr::HasLaunchedProgram(program_id);
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id) {
*out = ldr::HasLaunchedBootProgram(program_id);
return ResultSuccess();
}

View File

@@ -19,7 +19,7 @@
namespace ams::ldr {
/* Launch Record API. */
bool HasLaunchedProgram(ncm::ProgramId program_id);
void SetLaunchedProgram(ncm::ProgramId program_id);
bool HasLaunchedBootProgram(ncm::ProgramId program_id);
void SetLaunchedBootProgram(ncm::ProgramId program_id);
}

View File

@@ -115,8 +115,8 @@ namespace ams::ldr {
fssystem::DestroyExternalCode(program_id);
}
void LoaderService::AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
out.SetValue(ldr::HasLaunchedProgram(program_id));
void LoaderService::AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
out.SetValue(ldr::HasLaunchedBootProgram(program_id));
}
Result LoaderService::AtmosphereGetProgramInfo(sf::Out<ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc) {

View File

@@ -34,7 +34,7 @@ namespace ams::ldr {
/* Atmosphere commands. */
Result AtmosphereRegisterExternalCode(sf::OutMoveHandle out, ncm::ProgramId program_id);
void AtmosphereUnregisterExternalCode(ncm::ProgramId program_id);
void AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id);
void AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id);
Result AtmosphereGetProgramInfo(sf::Out<ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc);
Result AtmospherePinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
};

View File

@@ -22,8 +22,8 @@ namespace ams::pm {
/* Overrides for libstratosphere pm::info commands. */
namespace info {
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
return ldr::pm::HasLaunchedProgram(out, program_id);
Result HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id) {
return ldr::pm::HasLaunchedBootProgram(out, program_id);
}
}
@@ -38,8 +38,8 @@ namespace ams::pm {
return impl::GetProcessId(out.GetPointer(), program_id);
}
Result InformationService::AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
return pm::info::HasLaunchedProgram(out.GetPointer(), program_id);
Result InformationService::AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id) {
return pm::info::HasLaunchedBootProgram(out.GetPointer(), program_id);
}
Result InformationService::AtmosphereGetProcessInfo(sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id) {

View File

@@ -25,7 +25,7 @@ namespace ams::pm {
/* Atmosphere extension commands. */
Result AtmosphereGetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id);
Result AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id);
Result AtmosphereHasLaunchedBootProgram(sf::Out<bool> out, ncm::ProgramId program_id);
Result AtmosphereGetProcessInfo(sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id);
};
static_assert(pm::impl::IsIInformationInterface<InformationService>);

View File

@@ -18,7 +18,7 @@
namespace ams::ro {
class DebugMonitorService final {
class DebugMonitorService {
public:
Result GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<LoaderModuleInfo> &out_infos, os::ProcessId process_id);
};

View File

@@ -23,7 +23,7 @@ extern "C" {
u32 __nx_applet_type = AppletType_None;
u32 __nx_fs_num_sessions = 1;
#define INNER_HEAP_SIZE 0x4000
#define INNER_HEAP_SIZE 0x0
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
char nx_inner_heap[INNER_HEAP_SIZE];
@@ -46,6 +46,88 @@ namespace ams {
using namespace ams;
namespace ams::ro {
namespace {
/* ldr:ro, ro:dmnt, ro:1. */
enum PortIndex {
PortIndex_DebugMonitor,
PortIndex_User,
PortIndex_JitPlugin,
PortIndex_Count,
};
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ro:dmnt");
constexpr size_t DebugMonitorMaxSessions = 2;
/* NOTE: Official code passes 32 for ldr:ro max sessions. We will pass 2, because that's the actual limit. */
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("ldr:ro");
constexpr size_t UserMaxSessions = 2;
constexpr sm::ServiceName JitPluginServiceName = sm::ServiceName::Encode("ro:1");
constexpr size_t JitPluginMaxSessions = 2;
static constexpr size_t MaxSessions = DebugMonitorMaxSessions + UserMaxSessions + JitPluginMaxSessions;
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
private:
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override;
};
using Allocator = sf::ExpHeapAllocator;
using ObjectFactory = sf::ObjectFactory<sf::ExpHeapAllocator::Policy>;
alignas(0x40) constinit u8 g_server_allocator_buffer[4_KB];
lmem::HeapHandle g_server_heap_handle;
Allocator g_server_allocator;
ServerManager g_server_manager;
ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
switch (port_index) {
case PortIndex_DebugMonitor:
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IDebugMonitorInterface, ro::DebugMonitorService>(std::addressof(g_server_allocator)));
case PortIndex_User:
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IRoInterface, ro::RoService>(std::addressof(g_server_allocator), ro::NrrKind_User));
case PortIndex_JitPlugin:
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IRoInterface, ro::RoService>(std::addressof(g_server_allocator), ro::NrrKind_JitPlugin));
AMS_UNREACHABLE_DEFAULT_CASE();
}
}
void *Allocate(size_t size) {
return lmem::AllocateFromExpHeap(g_server_heap_handle, size);
}
void Deallocate(void *p, size_t size) {
return lmem::FreeToExpHeap(g_server_heap_handle, p);
}
void InitializeHeap() {
/* Setup server allocator. */
g_server_heap_handle = lmem::CreateExpHeap(g_server_allocator_buffer, sizeof(g_server_allocator_buffer), lmem::CreateOption_None);
}
void LoopServer() {
/* Create services. */
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_DebugMonitor, DebugMonitorServiceName, DebugMonitorMaxSessions));
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_User, UserServiceName, UserMaxSessions));
if (hos::GetVersion() >= hos::Version_7_0_0) {
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_JitPlugin, JitPluginServiceName, JitPluginMaxSessions));
}
/* Loop forever, servicing our services. */
ro::g_server_manager.LoopProcess();
}
}
}
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
size_t size = nx_inner_heap_size;
@@ -56,11 +138,15 @@ void __libnx_initheap(void) {
fake_heap_start = (char*)addr;
fake_heap_end = (char*)addr + size;
ams::ro::InitializeHeap();
}
void __appInit(void) {
hos::InitializeForStratosphere();
fs::SetAllocator(ro::Allocate, ro::Deallocate);
sm::DoWithSession([&]() {
R_ABORT_UNLESS(setsysInitialize());
R_ABORT_UNLESS(fsInitialize());
@@ -86,21 +172,15 @@ void __appExit(void) {
namespace {
/* ldr:ro, ro:dmnt, ro:1. */
/* TODO: Consider max sessions enforcement? */
constexpr size_t NumServers = 3;
sf::hipc::ServerManager<NumServers> g_server_manager;
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ro:dmnt");
constexpr size_t DebugMonitorMaxSessions = 2;
}
/* NOTE: Official code passes 32 for ldr:ro max sessions. We will pass 2, because that's the actual limit. */
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("ldr:ro");
constexpr size_t UserMaxSessions = 2;
constexpr sm::ServiceName JitPluginServiceName = sm::ServiceName::Encode("ro:1");
constexpr size_t JitPluginMaxSessions = 2;
void *operator new(size_t size) {
AMS_ABORT("operator new(size_t) was called");
}
void operator delete(void *p) {
AMS_ABORT("operator delete(void *) was called");
}
int main(int argc, char **argv)
@@ -109,6 +189,12 @@ int main(int argc, char **argv)
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ro, Main));
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ro, Main));
/* Attach the server allocator. */
ro::g_server_allocator.Attach(ro::g_server_heap_handle);
/* Disable auto-abort in fs operations. */
fs::SetEnabledAutoAbort(false);
/* Initialize Debug config. */
{
ON_SCOPE_EXIT { spl::Finalize(); };
@@ -117,16 +203,8 @@ int main(int argc, char **argv)
ro::SetDevelopmentFunctionEnabled(spl::IsDevelopmentFunctionEnabled());
}
/* Create services. */
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IDebugMonitorInterface, ro::DebugMonitorService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IRoInterface, ro::RoUserService>(UserServiceName, UserMaxSessions)));
if (hos::GetVersion() >= hos::Version_7_0_0) {
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IRoInterface, ro::RoJitPluginService>(JitPluginServiceName, JitPluginMaxSessions)));
}
/* Loop forever, servicing our services. */
g_server_manager.LoopProcess();
/* Run the ro server. */
ro::LoopServer();
/* Cleanup */
return 0;

View File

@@ -42,14 +42,4 @@ namespace ams::ro {
};
static_assert(ro::impl::IsIRoInterface<RoService>);
class RoUserService final : public RoService {
public:
RoUserService() : RoService(NrrKind_User) { /* ... */ }
};
class RoJitPluginService final : public RoService {
public:
RoJitPluginService() : RoService(NrrKind_JitPlugin) { /* ... */ }
};
}