Merge branch 'master' into npdmfixup

This commit is contained in:
SciresM
2018-10-31 18:02:07 +09:00
committed by GitHub
235 changed files with 6301 additions and 9851 deletions

View File

@@ -21,7 +21,7 @@ TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src
DEFINES := -DDISABLE_IPC

View File

@@ -1,7 +1,7 @@
{
"name": "ProcessMana",
"title_id": "0x0100000000000003",
"main_thread_stack_size": "0x00001000",
"main_thread_stack_size": "0x00002000",
"main_thread_priority": 49,
"default_cpu_id": 3,
"process_category": 1,
@@ -13,64 +13,64 @@
{
"type": "syscalls",
"value": {
"svcSetHeapSize": "0x01",
"svcSetMemoryPermission": "0x02",
"svcSetMemoryAttribute": "0x03",
"svcMapMemory": "0x04",
"svcUnmapMemory": "0x05",
"svcQueryMemory": "0x06",
"svcExitProcess": "0x07",
"svcCreateThread": "0x08",
"svcStartThread": "0x09",
"svcExitThread": "0x0a",
"svcSleepThread": "0x0b",
"svcGetThreadPriority": "0x0c",
"svcSetThreadPriority": "0x0d",
"svcGetThreadCoreMask": "0x0e",
"svcSetThreadCoreMask": "0x0f",
"svcGetCurrentProcessorNumber": "0x10",
"svcSignalEvent": "0x11",
"svcClearEvent": "0x12",
"svcMapSharedMemory": "0x13",
"svcUnmapSharedMemory": "0x14",
"svcCreateTransferMemory": "0x15",
"svcCloseHandle": "0x16",
"svcResetSignal": "0x17",
"svcWaitSynchronization": "0x18",
"svcCancelSynchronization": "0x19",
"svcArbitrateLock": "0x1a",
"svcArbitrateUnlock": "0x1b",
"svcWaitProcessWideKeyAtomic": "0x1c",
"svcSignalProcessWideKey": "0x1d",
"svcGetSystemTick": "0x1e",
"svcConnectToNamedPort": "0x1f",
"svcSendSyncRequestLight": "0x20",
"svcSendSyncRequest": "0x21",
"svcSendSyncRequestWithUserBuffer": "0x22",
"svcSendAsyncRequestWithUserBuffer": "0x23",
"svcGetProcessId": "0x24",
"svcGetThreadId": "0x25",
"svcBreak": "0x26",
"svcOutputDebugString": "0x27",
"svcReturnFromException": "0x28",
"svcGetInfo": "0x29",
"svcGetResourceLimitLimitValue": "0x30",
"svcGetResourceLimitCurrentValue": "0x31",
"svcWaitForAddress": "0x34",
"svcSignalToAddress": "0x35",
"svcCreateSession": "0x40",
"svcAcceptSession": "0x41",
"svcReplyAndReceiveLight": "0x42",
"svcReplyAndReceive": "0x43",
"svcReplyAndReceiveWithUserBuffer": "0x44",
"svcCreateEvent": "0x45",
"svcStartProcess": "0x7a",
"svcTerminateProcess": "0x7b",
"svcGetProcessInfo": "0x7c",
"svcCreateResourceLimit": "0x7d",
"svcSetResourceLimitLimitValue": "0x7e",
"svcSetUnsafeLimit": "0x4a",
"svcGetSystemInfo": "0x6f"
"svcSetHeapSize": "0x01",
"svcSetMemoryPermission": "0x02",
"svcSetMemoryAttribute": "0x03",
"svcMapMemory": "0x04",
"svcUnmapMemory": "0x05",
"svcQueryMemory": "0x06",
"svcExitProcess": "0x07",
"svcCreateThread": "0x08",
"svcStartThread": "0x09",
"svcExitThread": "0x0a",
"svcSleepThread": "0x0b",
"svcGetThreadPriority": "0x0c",
"svcSetThreadPriority": "0x0d",
"svcGetThreadCoreMask": "0x0e",
"svcSetThreadCoreMask": "0x0f",
"svcGetCurrentProcessorNumber": "0x10",
"svcSignalEvent": "0x11",
"svcClearEvent": "0x12",
"svcMapSharedMemory": "0x13",
"svcUnmapSharedMemory": "0x14",
"svcCreateTransferMemory": "0x15",
"svcCloseHandle": "0x16",
"svcResetSignal": "0x17",
"svcWaitSynchronization": "0x18",
"svcCancelSynchronization": "0x19",
"svcArbitrateLock": "0x1a",
"svcArbitrateUnlock": "0x1b",
"svcWaitProcessWideKeyAtomic": "0x1c",
"svcSignalProcessWideKey": "0x1d",
"svcGetSystemTick": "0x1e",
"svcConnectToNamedPort": "0x1f",
"svcSendSyncRequestLight": "0x20",
"svcSendSyncRequest": "0x21",
"svcSendSyncRequestWithUserBuffer": "0x22",
"svcSendAsyncRequestWithUserBuffer": "0x23",
"svcGetProcessId": "0x24",
"svcGetThreadId": "0x25",
"svcBreak": "0x26",
"svcOutputDebugString": "0x27",
"svcReturnFromException": "0x28",
"svcGetInfo": "0x29",
"svcGetResourceLimitLimitValue": "0x30",
"svcGetResourceLimitCurrentValue": "0x31",
"svcWaitForAddress": "0x34",
"svcSignalToAddress": "0x35",
"svcCreateSession": "0x40",
"svcAcceptSession": "0x41",
"svcReplyAndReceiveLight": "0x42",
"svcReplyAndReceive": "0x43",
"svcReplyAndReceiveWithUserBuffer": "0x44",
"svcCreateEvent": "0x45",
"svcSetUnsafeLimit": "0x4a",
"svcStartProcess": "0x7a",
"svcTerminateProcess": "0x7b",
"svcGetProcessInfo": "0x7c",
"svcCreateResourceLimit": "0x7d",
"svcSetResourceLimitLimitValue": "0x7e",
"svcGetSystemInfo": "0x6f"
}
}
]

View File

@@ -173,7 +173,7 @@ void EmbeddedBoot2::Main() {
}
closedir(titles_dir);
}
/* We no longer need the SD card. */
fsdevUnmountAll();
}

View File

@@ -20,33 +20,10 @@
static bool g_is_maintenance_boot = false;
Result BootModeService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
switch ((BootModeCmd)cmd_id) {
case BootMode_Cmd_GetBootMode:
rc = WrapIpcCommandImpl<&BootModeService::get_boot_mode>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case BootMode_Cmd_SetMaintenanceBoot:
rc = WrapIpcCommandImpl<&BootModeService::set_maintenance_boot>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
return rc;
void BootModeService::GetBootMode(Out<u32> out) {
out.SetValue(g_is_maintenance_boot);
}
Result BootModeService::handle_deferred() {
/* This service is never deferrable. */
return 0;
}
std::tuple<Result, bool> BootModeService::get_boot_mode() {
return {0, g_is_maintenance_boot};
}
std::tuple<Result> BootModeService::set_maintenance_boot() {
void BootModeService::SetMaintenanceBoot() {
g_is_maintenance_boot = true;
return {0};
}

View File

@@ -16,24 +16,21 @@
#pragma once
#include <switch.h>
#include <stratosphere/iserviceobject.hpp>
#include <stratosphere.hpp>
enum BootModeCmd {
BootMode_Cmd_GetBootMode = 0,
BootMode_Cmd_SetMaintenanceBoot = 1
};
class BootModeService final : public IServiceObject {
public:
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
Result handle_deferred() override;
BootModeService *clone() override {
return new BootModeService(*this);
}
class BootModeService final : public IServiceObject {
private:
/* Actual commands. */
std::tuple<Result, bool> get_boot_mode();
std::tuple<Result> set_maintenance_boot();
void GetBootMode(Out<u32> out);
void SetMaintenanceBoot();
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<BootMode_Cmd_GetBootMode, &BootModeService::GetBootMode>(),
MakeServiceCommandMeta<BootMode_Cmd_SetMaintenanceBoot, &BootModeService::SetMaintenanceBoot>(),
};
};

View File

@@ -17,144 +17,91 @@
#include <switch.h>
#include <stratosphere.hpp>
#include "pm_registration.hpp"
#include "pm_resource_limits.hpp"
#include "pm_debug_monitor.hpp"
Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
if (kernelAbove500()) {
switch ((DmntCmd_5X)cmd_id) {
case Dmnt_Cmd_5X_GetDebugProcessIds:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_debug_process_ids>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_LaunchDebugProcess:
rc = WrapIpcCommandImpl<&DebugMonitorService::launch_debug_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_GetTitleProcessId:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_title_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_EnableDebugForTitleId:
rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_tid>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_GetApplicationProcessId:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_5X_EnableDebugForApplication:
rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_application>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_6X_DisableDebug:
if (kernelAbove600()) {
rc = WrapIpcCommandImpl<&DebugMonitorService::disable_debug>(this, r, out_c, pointer_buffer, pointer_buffer_size);
}
break;
case Dmnt_Cmd_5X_AtmosphereGetProcessHandle:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_process_handle>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
} else {
switch ((DmntCmd)cmd_id) {
case Dmnt_Cmd_GetUnknownStub:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_unknown_stub>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_GetDebugProcessIds:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_debug_process_ids>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_LaunchDebugProcess:
rc = WrapIpcCommandImpl<&DebugMonitorService::launch_debug_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_GetTitleProcessId:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_title_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_EnableDebugForTitleId:
rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_tid>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_GetApplicationProcessId:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_EnableDebugForApplication:
rc = WrapIpcCommandImpl<&DebugMonitorService::enable_debug_for_application>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Dmnt_Cmd_AtmosphereGetProcessHandle:
rc = WrapIpcCommandImpl<&DebugMonitorService::get_process_handle>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
Result DebugMonitorService::GetUnknownStub(Out<u32> count, OutBuffer<u8> out_buf, u64 in_unk) {
/* This command seems stubbed. */
if (out_buf.num_elements >> 31) {
return 0xC0F;
}
return rc;
count.SetValue(0);
return 0x0;
}
Result DebugMonitorService::handle_deferred() {
/* This service is never deferrable. */
return 0;
}
std::tuple<Result, u32> DebugMonitorService::get_unknown_stub(u64 unknown, OutBuffer<u8> out_unknown) {
/* This command seem stubbed on retail. */
if (out_unknown.num_elements >> 31) {
return {0xC0F, 0};
}
return {0x0, 0};
}
std::tuple<Result, u32> DebugMonitorService::get_debug_process_ids(OutBuffer<u64> out_pids) {
u32 num_out = 0;
Result rc;
Result DebugMonitorService::GetDebugProcessIds(Out<u32> count, OutBuffer<u64> out_pids) {
if (out_pids.num_elements >> 31) {
return {0xC0F, 0};
return 0xC0F;
}
rc = Registration::GetDebugProcessIds(out_pids.buffer, out_pids.num_elements, &num_out);
return {rc, num_out};
return Registration::GetDebugProcessIds(out_pids.buffer, out_pids.num_elements, count.GetPointer());
}
std::tuple<Result> DebugMonitorService::launch_debug_process(u64 pid) {
return {Registration::LaunchDebugProcess(pid)};
Result DebugMonitorService::LaunchDebugProcess(u64 pid) {
return Registration::LaunchDebugProcess(pid);
}
std::tuple<Result, u64> DebugMonitorService::get_title_process_id(u64 tid) {
Result DebugMonitorService::GetTitleProcessId(Out<u64> pid, u64 tid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
std::shared_ptr<Registration::Process> proc = Registration::GetProcessByTitleId(tid);
if (proc != nullptr) {
return {0, proc->pid};
} else {
return {0x20F, 0};
pid.SetValue(proc->pid);
return 0;
}
return 0x20F;
}
std::tuple<Result, CopiedHandle> DebugMonitorService::enable_debug_for_tid(u64 tid) {
Handle h = 0;
Result rc = Registration::EnableDebugForTitleId(tid, &h);
return {rc, h};
Result DebugMonitorService::EnableDebugForTitleId(Out<CopiedHandle> event, u64 tid) {
return Registration::EnableDebugForTitleId(tid, event.GetHandlePointer());
}
std::tuple<Result, u64> DebugMonitorService::get_application_process_id() {
Result DebugMonitorService::GetApplicationProcessId(Out<u64> pid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
std::shared_ptr<Registration::Process> app_proc;
if (Registration::HasApplicationProcess(&app_proc)) {
return {0, app_proc->pid};
pid.SetValue(app_proc->pid);
return 0x0;
}
return {0x20F, 0};
return 0x20F;
}
std::tuple<Result, CopiedHandle> DebugMonitorService::enable_debug_for_application() {
Handle h = 0;
Result rc = Registration::EnableDebugForApplication(&h);
return {rc, h};
Result DebugMonitorService::EnableDebugForApplication(Out<CopiedHandle> event) {
return Registration::EnableDebugForApplication(event.GetHandlePointer());
}
std::tuple<Result> DebugMonitorService::disable_debug(u32 which) {
return {Registration::DisableDebug(which)};
Result DebugMonitorService::DisableDebug(u32 which) {
return Registration::DisableDebug(which);
}
std::tuple<Result, CopiedHandle> DebugMonitorService::get_process_handle(u64 pid) {
std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid);
if(proc == NULL) {
return {0x20F, 0};
Result DebugMonitorService::AtmosphereGetProcessHandle(Out<CopiedHandle> proc_hand, u64 pid) {
auto proc = Registration::GetProcess(pid);
if(proc != nullptr) {
proc_hand.SetValue(proc->handle);
return 0;
}
return {0, proc->handle};
return 0x20F;
}
Result DebugMonitorService::AtmosphereGetCurrentLimitInfo(Out<u64> cur_val, Out<u64> lim_val, u32 category, u32 resource) {
Result rc;
if(category > ResourceLimitUtils::ResourceLimitCategory::ResourceLimitCategory_Applet) {
return 0xF001;
}
Handle limit_h = ResourceLimitUtils::GetResourceLimitHandleByCategory((ResourceLimitUtils::ResourceLimitCategory) category);
rc = svcGetResourceLimitCurrentValue(cur_val.GetPointer(), limit_h, (LimitableResource) resource);
if(R_FAILED(rc)) {
return rc;
}
rc = svcGetResourceLimitLimitValue(lim_val.GetPointer(), limit_h, (LimitableResource) resource);
if(R_FAILED(rc)) {
return rc;
}
return 0;
}

View File

@@ -16,7 +16,7 @@
#pragma once
#include <switch.h>
#include <stratosphere/iserviceobject.hpp>
#include <stratosphere.hpp>
#include "pm_registration.hpp"
@@ -28,11 +28,7 @@ enum DmntCmd {
Dmnt_Cmd_EnableDebugForTitleId = 4,
Dmnt_Cmd_GetApplicationProcessId = 5,
Dmnt_Cmd_EnableDebugForApplication = 6,
Dmnt_Cmd_AtmosphereGetProcessHandle = 65000
};
enum DmntCmd_5X {
Dmnt_Cmd_5X_GetDebugProcessIds = 0,
Dmnt_Cmd_5X_LaunchDebugProcess = 1,
Dmnt_Cmd_5X_GetTitleProcessId = 2,
@@ -42,29 +38,49 @@ enum DmntCmd_5X {
Dmnt_Cmd_6X_DisableDebug = 6,
Dmnt_Cmd_5X_AtmosphereGetProcessHandle = 65000
Dmnt_Cmd_AtmosphereGetProcessHandle = 65000,
Dmnt_Cmd_AtmosphereGetCurrentLimitInfo = 65001,
};
class DebugMonitorService final : public IServiceObject {
public:
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
Result handle_deferred() override;
DebugMonitorService *clone() override {
return new DebugMonitorService(*this);
}
private:
/* Actual commands. */
std::tuple<Result, u32> get_unknown_stub(u64 unknown, OutBuffer<u8> out_unknown);
std::tuple<Result, u32> get_debug_process_ids(OutBuffer<u64> out_processes);
std::tuple<Result> launch_debug_process(u64 pid);
std::tuple<Result, u64> get_title_process_id(u64 tid);
std::tuple<Result, CopiedHandle> enable_debug_for_tid(u64 tid);
std::tuple<Result, u64> get_application_process_id();
std::tuple<Result, CopiedHandle> enable_debug_for_application();
std::tuple<Result> disable_debug(u32 which);
Result GetUnknownStub(Out<u32> count, OutBuffer<u8> out_buf, u64 in_unk);
Result GetDebugProcessIds(Out<u32> count, OutBuffer<u64> out_pids);
Result LaunchDebugProcess(u64 pid);
Result GetTitleProcessId(Out<u64> pid, u64 tid);
Result EnableDebugForTitleId(Out<CopiedHandle> event, u64 tid);
Result GetApplicationProcessId(Out<u64> pid);
Result EnableDebugForApplication(Out<CopiedHandle> event);
Result DisableDebug(u32 which);
/* Atmosphere commands. */
std::tuple<Result, CopiedHandle> get_process_handle(u64 pid);
Result AtmosphereGetProcessHandle(Out<CopiedHandle> proc_hand, u64 pid);
Result AtmosphereGetCurrentLimitInfo(Out<u64> cur_val, Out<u64> lim_val, u32 category, u32 resource);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
/* 1.0.0-4.1.0 */
MakeServiceCommandMeta<Dmnt_Cmd_GetUnknownStub, &DebugMonitorService::GetUnknownStub, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Dmnt_Cmd_GetDebugProcessIds, &DebugMonitorService::GetDebugProcessIds, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Dmnt_Cmd_LaunchDebugProcess, &DebugMonitorService::LaunchDebugProcess, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Dmnt_Cmd_GetTitleProcessId, &DebugMonitorService::GetTitleProcessId, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Dmnt_Cmd_EnableDebugForTitleId, &DebugMonitorService::EnableDebugForTitleId, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Dmnt_Cmd_GetApplicationProcessId, &DebugMonitorService::GetApplicationProcessId, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Dmnt_Cmd_EnableDebugForApplication, &DebugMonitorService::EnableDebugForApplication, FirmwareVersion_Min, FirmwareVersion_400>(),
/* 5.0.0-* */
MakeServiceCommandMeta<Dmnt_Cmd_5X_GetDebugProcessIds, &DebugMonitorService::GetDebugProcessIds, FirmwareVersion_500>(),
MakeServiceCommandMeta<Dmnt_Cmd_5X_LaunchDebugProcess, &DebugMonitorService::LaunchDebugProcess, FirmwareVersion_500>(),
MakeServiceCommandMeta<Dmnt_Cmd_5X_GetTitleProcessId, &DebugMonitorService::GetTitleProcessId, FirmwareVersion_500>(),
MakeServiceCommandMeta<Dmnt_Cmd_5X_EnableDebugForTitleId, &DebugMonitorService::EnableDebugForTitleId, FirmwareVersion_500>(),
MakeServiceCommandMeta<Dmnt_Cmd_5X_GetApplicationProcessId, &DebugMonitorService::GetApplicationProcessId, FirmwareVersion_500>(),
MakeServiceCommandMeta<Dmnt_Cmd_5X_EnableDebugForApplication, &DebugMonitorService::EnableDebugForApplication, FirmwareVersion_500>(),
/* 6.0.0-* */
MakeServiceCommandMeta<Dmnt_Cmd_6X_DisableDebug, &DebugMonitorService::DisableDebug, FirmwareVersion_600>(),
/* Atmosphere extensions. */
MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetProcessHandle, &DebugMonitorService::AtmosphereGetProcessHandle>(),
MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetCurrentLimitInfo, &DebugMonitorService::AtmosphereGetCurrentLimitInfo>(),
};
};

View File

@@ -18,32 +18,13 @@
#include "pm_registration.hpp"
#include "pm_info.hpp"
Result InformationService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
switch ((InformationCmd)cmd_id) {
case Information_Cmd_GetTitleId:
rc = WrapIpcCommandImpl<&InformationService::get_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
return rc;
}
Result InformationService::handle_deferred() {
/* This service is never deferrable. */
return 0;
}
std::tuple<Result, u64> InformationService::get_title_id(u64 pid) {
Result InformationService::GetTitleId(Out<u64> tid, u64 pid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid);
if (proc != NULL) {
return {0x0, proc->tid_sid.title_id};
} else {
return {0x20F, 0x0};
tid.SetValue(proc->tid_sid.title_id);
return 0;
}
return 0x20F;
}

View File

@@ -17,22 +17,17 @@
#pragma once
#include <switch.h>
#include <stratosphere.hpp>
#include <stratosphere/iserviceobject.hpp>
enum InformationCmd {
Information_Cmd_GetTitleId = 0,
};
class InformationService final : public IServiceObject {
public:
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
Result handle_deferred() override;
InformationService *clone() override {
return new InformationService(*this);
}
private:
/* Actual commands. */
std::tuple<Result, u64> get_title_id(u64 pid);
Result GetTitleId(Out<u64> tid, u64 pid);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MakeServiceCommandMeta<Information_Cmd_GetTitleId, &InformationService::GetTitleId>(),
};
};

View File

@@ -56,6 +56,20 @@ void __libnx_initheap(void) {
fake_heap_end = (char*)addr + size;
}
void RegisterPrivilegedProcessesWithFs() {
/* Ensures that all privileged processes are registered with full FS permissions. */
constexpr u64 PRIVILEGED_PROCESS_MIN = 0;
constexpr u64 PRIVILEGED_PROCESS_MAX = 0x4F;
const u32 PRIVILEGED_FAH[0x1C/sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
const u32 PRIVILEGED_FAC[0x2C/sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
for (u64 pid = PRIVILEGED_PROCESS_MIN; pid <= PRIVILEGED_PROCESS_MAX; pid++) {
fsprUnregisterProgram(pid);
fsprRegisterProgram(pid, pid, FsStorageId_NandSystem, PRIVILEGED_FAH, sizeof(PRIVILEGED_FAH), PRIVILEGED_FAC, sizeof(PRIVILEGED_FAC));
}
}
void __appInit(void) {
Result rc;
@@ -64,27 +78,33 @@ void __appInit(void) {
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_SM));
}
rc = fsInitialize();
if (R_FAILED(rc)) {
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS));
}
rc = lrInitialize();
rc = fsprInitialize();
if (R_FAILED(rc)) {
fatalSimple(0xCAFE << 4 | 1);
}
rc = fsprInitialize();
if (R_FAILED(rc)) {
/* This works around a bug with process permissions on < 4.0.0. */
RegisterPrivilegedProcessesWithFs();
rc = smManagerAmsInitialize();
if (R_SUCCEEDED(rc)) {
smManagerAmsEndInitialDefers();
smManagerAmsExit();
} else {
fatalSimple(0xCAFE << 4 | 2);
}
rc = ldrPmInitialize();
rc = smManagerInitialize();
if (R_FAILED(rc)) {
fatalSimple(0xCAFE << 4 | 3);
}
rc = lrInitialize();
if (R_FAILED(rc)) {
fatalSimple(0xCAFE << 4 | 4);
}
rc = smManagerInitialize();
rc = ldrPmInitialize();
if (R_FAILED(rc)) {
fatalSimple(0xCAFE << 4 | 5);
}
@@ -94,12 +114,12 @@ void __appInit(void) {
fatalSimple(0xCAFE << 4 | 6);
}
/* Check for exosphere API compatibility. */
u64 exosphere_cfg;
if (R_FAILED(splGetConfig((SplConfigItem)65000, &exosphere_cfg))) {
fatalSimple(0xCAFE << 4 | 0xFF);
/* TODO: Does PM need to know about target firmware/master key revision? If so, extract from exosphere_cfg. */
rc = fsInitialize();
if (R_FAILED(rc)) {
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_InitFail_FS));
}
CheckAtmosphereVersion();
}
void __appExit(void) {
@@ -129,16 +149,16 @@ int main(int argc, char **argv)
}
/* TODO: What's a good timeout value to use here? */
WaitableManager *server_manager = new WaitableManager(U64_MAX);
auto server_manager = new WaitableManager(1);
/* TODO: Create services. */
server_manager->add_waitable(new ServiceServer<ShellService>("pm:shell", 3));
server_manager->add_waitable(new ServiceServer<DebugMonitorService>("pm:dmnt", 2));
server_manager->add_waitable(new ServiceServer<BootModeService>("pm:bm", 5));
server_manager->add_waitable(new ServiceServer<InformationService>("pm:info", 1));
server_manager->AddWaitable(new ServiceServer<ShellService>("pm:shell", 3));
server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("pm:dmnt", 2));
server_manager->AddWaitable(new ServiceServer<BootModeService>("pm:bm", 5));
server_manager->AddWaitable(new ServiceServer<InformationService>("pm:info", 1));
/* Loop forever, servicing our services. */
server_manager->process();
server_manager->Process();
/* Cleanup. */
delete server_manager;

View File

@@ -21,12 +21,11 @@
void ProcessTracking::MainLoop(void *arg) {
/* Make a new waitable manager. */
MultiThreadedWaitableManager *process_waiter = new MultiThreadedWaitableManager(1, U64_MAX);
process_waiter->add_waitable(Registration::GetProcessLaunchStartEvent());
Registration::SetProcessListManager(process_waiter);
auto process_waiter = new WaitableManager(1);
process_waiter->AddWaitable(Registration::GetProcessLaunchStartEvent());
/* Service processes. */
process_waiter->process();
process_waiter->Process();
delete process_waiter;
svcExitThread();

View File

@@ -28,41 +28,28 @@ class ProcessWaiter final : public IWaitable {
/* ... */
}
std::shared_ptr<Registration::Process> get_process() {
std::shared_ptr<Registration::Process> GetProcess() {
return this->process;
}
/* IWaitable */
Handle get_handle() override {
Handle GetHandle() override {
return this->process->handle;
}
void handle_deferred() override {
/* TODO: Panic, because we can never be deferred. */
}
Result handle_signaled(u64 timeout) override {
return Registration::HandleSignaledProcess(this->get_process());
Result HandleSignaled(u64 timeout) override {
return Registration::HandleSignaledProcess(this->GetProcess());
}
};
class ProcessList final {
private:
HosRecursiveMutex mutex;
WaitableManager *manager;
public:
std::vector<std::shared_ptr<Registration::Process>> processes;
auto get_unique_lock() {
auto GetUniqueLock() {
return std::unique_lock{this->mutex};
}
void set_manager(WaitableManager *manager) {
this->manager = manager;
}
WaitableManager *get_manager() {
return this->manager;
}
};

View File

@@ -25,7 +25,7 @@
static ProcessList g_process_list;
static ProcessList g_dead_process_list;
static SystemEvent *g_process_launch_start_event = NULL;
static IEvent *g_process_launch_start_event = nullptr;
static HosSemaphore g_sema_finish_launch;
static HosMutex g_process_launch_mutex;
@@ -34,29 +34,27 @@ static Registration::ProcessLaunchState g_process_launch_state;
static std::atomic_bool g_debug_next_application(false);
static std::atomic<u64> g_debug_on_launch_tid(0);
static SystemEvent *g_process_event = NULL;
static SystemEvent *g_debug_title_event = NULL;
static SystemEvent *g_debug_application_event = NULL;
static IEvent *g_process_event = nullptr;
static IEvent *g_debug_title_event = nullptr;
static IEvent *g_debug_application_event = nullptr;
std::unique_lock<HosRecursiveMutex> Registration::GetProcessListUniqueLock() {
return g_process_list.get_unique_lock();
}
void Registration::SetProcessListManager(WaitableManager *m) {
g_process_list.set_manager(m);
return g_process_list.GetUniqueLock();
}
void Registration::InitializeSystemResources() {
g_process_event = new SystemEvent(NULL, &IEvent::PanicCallback);
g_debug_title_event = new SystemEvent(NULL, &IEvent::PanicCallback);
g_debug_application_event = new SystemEvent(NULL, &IEvent::PanicCallback);
g_process_launch_start_event = new SystemEvent(NULL, &Registration::ProcessLaunchStartCallback);
g_process_event = CreateWriteOnlySystemEvent();
g_debug_title_event = CreateWriteOnlySystemEvent();
g_debug_application_event = CreateWriteOnlySystemEvent();
/* Auto-clear non-system event. */
g_process_launch_start_event = CreateSystemEvent(&Registration::ProcessLaunchStartCallback);
ResourceLimitUtils::InitializeLimits();
}
Result Registration::ProcessLaunchStartCallback(void *arg, Handle *handles, size_t num_handles, u64 timeout) {
svcClearEvent(handles[0]);
Result Registration::ProcessLaunchStartCallback(u64 timeout) {
g_process_launch_start_event->Clear();
Registration::HandleProcessLaunch();
return 0;
}
@@ -138,11 +136,11 @@ void Registration::HandleProcessLaunch() {
/* Signal, if relevant. */
if (new_process.tid_sid.title_id == g_debug_on_launch_tid.load()) {
g_debug_title_event->signal_event();
g_debug_title_event->Signal();
g_debug_on_launch_tid = 0;
rc = 0;
} else if ((new_process.flags & PROCESSFLAGS_APPLICATION) && g_debug_next_application.load()) {
g_debug_application_event->signal_event();
g_debug_application_event->Signal();
g_debug_next_application = false;
rc = 0;
} else if (LAUNCHFLAGS_STARTSUSPENDED(launch_flags)) {
@@ -151,7 +149,7 @@ void Registration::HandleProcessLaunch() {
rc = svcStartProcess(new_process.handle, program_info.main_thread_priority, program_info.default_cpu_id, program_info.main_thread_stack_size);
if (R_SUCCEEDED(rc)) {
SetProcessState(new_process.pid, ProcessState_DebugDetached);
SetProcessState(new_process.pid, ProcessState_Running);
}
}
@@ -181,6 +179,7 @@ HANDLE_PROCESS_LAUNCH_END:
if (R_SUCCEEDED(rc)) {
*out_pid = new_process.pid;
}
g_sema_finish_launch.Signal();
}
@@ -195,7 +194,7 @@ Result Registration::LaunchDebugProcess(u64 pid) {
return 0x20F;
}
if (proc->state >= ProcessState_DebugDetached) {
if (proc->state >= ProcessState_Running) {
return 0x40F;
}
@@ -205,7 +204,7 @@ Result Registration::LaunchDebugProcess(u64 pid) {
}
if (R_SUCCEEDED((rc = svcStartProcess(proc->handle, program_info.main_thread_priority, program_info.default_cpu_id, program_info.main_thread_stack_size)))) {
proc->state = ProcessState_DebugDetached;
proc->state = ProcessState_Running;
}
return rc;
@@ -220,9 +219,9 @@ Result Registration::LaunchProcess(u64 title_id, FsStorageId storage_id, u64 lau
g_process_launch_state.out_pid = out_pid;
/* Start a launch, and wait for it to exit. */
g_process_launch_start_event->signal_event();
g_process_launch_start_event->Signal();
g_sema_finish_launch.Wait();
return g_process_launch_state.result;
}
@@ -246,14 +245,14 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process
}
switch (process->state) {
case ProcessState_Created:
case ProcessState_DebugAttached:
case ProcessState_CreatedAttached:
case ProcessState_Exiting:
break;
case ProcessState_DebugDetached:
case ProcessState_Running:
if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) {
process->flags &= ~(PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED);
process->flags |= PROCESSFLAGS_DEBUGEVENTPENDING;
g_process_event->signal_event();
g_process_event->Signal();
}
if (kernelAbove200() && process->flags & PROCESSFLAGS_NOTIFYDEBUGSPECIAL) {
process->flags &= ~(PROCESSFLAGS_NOTIFYDEBUGSPECIAL | PROCESSFLAGS_DEBUGDETACHED);
@@ -262,18 +261,18 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process
break;
case ProcessState_Crashed:
process->flags |= (PROCESSFLAGS_CRASHED | PROCESSFLAGS_CRASH_DEBUG);
g_process_event->signal_event();
g_process_event->Signal();
break;
case ProcessState_Running:
case ProcessState_RunningAttached:
if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) {
process->flags &= ~(PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED);
process->flags |= PROCESSFLAGS_DEBUGEVENTPENDING;
g_process_event->signal_event();
g_process_event->Signal();
}
break;
case ProcessState_Exited:
if (process->flags & PROCESSFLAGS_NOTIFYWHENEXITED && !kernelAbove500()) {
g_process_event->signal_event();
g_process_event->Signal();
} else {
FinalizeExitedProcess(process);
}
@@ -281,7 +280,7 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process
case ProcessState_DebugSuspended:
if (process->flags & PROCESSFLAGS_NOTIFYDEBUGEVENTS) {
process->flags |= (PROCESSFLAGS_DEBUGEVENTPENDING | PROCESSFLAGS_DEBUGSUSPENDED);
g_process_event->signal_event();
g_process_event->Signal();
}
break;
}
@@ -310,7 +309,7 @@ void Registration::FinalizeExitedProcess(std::shared_ptr<Registration::Process>
/* Insert into dead process list, if relevant. */
if (signal_debug_process_5x) {
auto lk = g_dead_process_list.get_unique_lock();
auto lk = g_dead_process_list.GetUniqueLock();
g_dead_process_list.processes.push_back(process);
}
@@ -319,14 +318,14 @@ void Registration::FinalizeExitedProcess(std::shared_ptr<Registration::Process>
auto_lock.unlock();
if (signal_debug_process_5x) {
g_process_event->signal_event();
g_process_event->Signal();
}
}
void Registration::AddProcessToList(std::shared_ptr<Registration::Process> process) {
auto auto_lock = GetProcessListUniqueLock();
g_process_list.processes.push_back(process);
g_process_list.get_manager()->add_waitable(new ProcessWaiter(process));
g_process_launch_start_event->GetManager()->AddWaitable(new ProcessWaiter(process));
}
void Registration::RemoveProcessFromList(u64 pid) {
@@ -412,14 +411,14 @@ Result Registration::GetDebugProcessIds(u64 *out_pids, u32 max_out, u32 *num_out
}
Handle Registration::GetProcessEventHandle() {
return g_process_event->get_handle();
return g_process_event->GetHandle();
}
void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) {
auto auto_lock = GetProcessListUniqueLock();
for (auto &p : g_process_list.processes) {
if (kernelAbove200() && p->state >= ProcessState_DebugDetached && p->flags & PROCESSFLAGS_DEBUGDETACHED) {
if (kernelAbove200() && p->state >= ProcessState_Running && p->flags & PROCESSFLAGS_DEBUGDETACHED) {
p->flags &= ~PROCESSFLAGS_DEBUGDETACHED;
*out_pid = p->pid;
*out_type = kernelAbove500() ? PROCESSEVENTTYPE_500_DEBUGDETACHED : PROCESSEVENTTYPE_DEBUGDETACHED;
@@ -451,7 +450,7 @@ void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) {
}
if (kernelAbove500()) {
auto_lock.unlock();
auto dead_process_list_lock = g_dead_process_list.get_unique_lock();
auto dead_process_list_lock = g_dead_process_list.GetUniqueLock();
if (g_dead_process_list.processes.size()) {
std::shared_ptr<Registration::Process> process = g_dead_process_list.processes[0];
g_dead_process_list.processes.erase(g_dead_process_list.processes.begin());
@@ -471,13 +470,13 @@ Result Registration::EnableDebugForTitleId(u64 tid, Handle *out) {
g_debug_on_launch_tid = old;
return 0x80F;
}
*out = g_debug_title_event->get_handle();
*out = g_debug_title_event->GetHandle();
return 0x0;
}
Result Registration::EnableDebugForApplication(Handle *out) {
g_debug_next_application = true;
*out = g_debug_application_event->get_handle();
*out = g_debug_application_event->GetHandle();
return 0;
}

View File

@@ -172,8 +172,7 @@ class Registration {
static void InitializeSystemResources();
static IWaitable *GetProcessLaunchStartEvent();
static std::unique_lock<HosRecursiveMutex> GetProcessListUniqueLock();
static void SetProcessListManager(WaitableManager *m);
static Result ProcessLaunchStartCallback(void *arg, Handle *handles, size_t num_handles, u64 timeout);
static Result ProcessLaunchStartCallback(u64 timeout);
static Result HandleSignaledProcess(std::shared_ptr<Process> process);
static void FinalizeExitedProcess(std::shared_ptr<Process> process);

View File

@@ -182,7 +182,12 @@ void ResourceLimitUtils::InitializeLimits() {
/* Atmosphere: Allocate extra memory (24 MiB) to SYSTEM away from Applet. */
for (unsigned int i = 0; i < 6; i++) {
g_memory_resource_limits[i][0] += ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES;
g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES;
/* On < 4.0.0, taking from application instead of applet fixes a rare hang on boot. */
if (kernelAbove400()) {
g_memory_resource_limits[i][2] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES;
} else {
g_memory_resource_limits[i][1] -= ATMOSPHERE_EXTRA_SYSTEM_MEMORY_FOR_SYSMODULES;
}
}
/* Set resource limits. */
@@ -224,6 +229,10 @@ Handle ResourceLimitUtils::GetResourceLimitHandle(u16 application_type) {
}
}
Handle ResourceLimitUtils::GetResourceLimitHandleByCategory(ResourceLimitCategory category) {
return g_resource_limit_handles[category];
}
Result ResourceLimitUtils::BoostSystemMemoryResourceLimit(u64 boost_size) {
Result rc = 0;
if (boost_size > g_memory_resource_limits[g_memory_limit_type][ResourceLimitCategory_Application]) {

View File

@@ -28,5 +28,6 @@ class ResourceLimitUtils {
static void InitializeLimits();
static void EnsureApplicationResourcesAvailable();
static Handle GetResourceLimitHandle(u16 application_type);
static Handle GetResourceLimitHandleByCategory(ResourceLimitCategory category);
static Result BoostSystemMemoryResourceLimit(u64 boost_size);
};

View File

@@ -23,170 +23,84 @@
static bool g_has_boot_finished = false;
Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601;
if (kernelAbove500()) {
switch ((ShellCmd_5X)cmd_id) {
case Shell_Cmd_5X_LaunchProcess:
rc = WrapIpcCommandImpl<&ShellService::launch_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_5X_TerminateProcessId:
rc = WrapIpcCommandImpl<&ShellService::terminate_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_5X_TerminateTitleId:
rc = WrapIpcCommandImpl<&ShellService::terminate_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_5X_GetProcessWaitEvent:
rc = WrapIpcCommandImpl<&ShellService::get_process_wait_event>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_5X_GetProcessEventType:
rc = WrapIpcCommandImpl<&ShellService::get_process_event_type>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_5X_NotifyBootFinished:
rc = WrapIpcCommandImpl<&ShellService::notify_boot_finished>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_5X_GetApplicationProcessId:
rc = WrapIpcCommandImpl<&ShellService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_5X_BoostSystemMemoryResourceLimit:
rc = WrapIpcCommandImpl<&ShellService::boost_system_memory_resource_limit>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
} else {
switch ((ShellCmd)cmd_id) {
case Shell_Cmd_LaunchProcess:
rc = WrapIpcCommandImpl<&ShellService::launch_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_TerminateProcessId:
rc = WrapIpcCommandImpl<&ShellService::terminate_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_TerminateTitleId:
rc = WrapIpcCommandImpl<&ShellService::terminate_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_GetProcessWaitEvent:
rc = WrapIpcCommandImpl<&ShellService::get_process_wait_event>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_GetProcessEventType:
rc = WrapIpcCommandImpl<&ShellService::get_process_event_type>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_FinalizeExitedProcess:
rc = WrapIpcCommandImpl<&ShellService::finalize_exited_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_ClearProcessNotificationFlag:
rc = WrapIpcCommandImpl<&ShellService::clear_process_notification_flag>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_NotifyBootFinished:
rc = WrapIpcCommandImpl<&ShellService::notify_boot_finished>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_GetApplicationProcessId:
rc = WrapIpcCommandImpl<&ShellService::get_application_process_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
case Shell_Cmd_BoostSystemMemoryResourceLimit:
rc = WrapIpcCommandImpl<&ShellService::boost_system_memory_resource_limit>(this, r, out_c, pointer_buffer, pointer_buffer_size);
break;
default:
break;
}
}
return rc;
Result ShellService::LaunchProcess(Out<u64> pid, Registration::TidSid tid_sid, u32 launch_flags) {
return Registration::LaunchProcessByTidSid(tid_sid, launch_flags, pid.GetPointer());
}
Result ShellService::handle_deferred() {
/* This service is never deferrable. */
return 0;
}
std::tuple<Result, u64> ShellService::launch_process(u64 launch_flags, Registration::TidSid tid_sid) {
u64 pid = 0;
Result rc = Registration::LaunchProcessByTidSid(tid_sid, launch_flags, &pid);
return {rc, pid};
}
std::tuple<Result> ShellService::terminate_process_id(u64 pid) {
Result ShellService::TerminateProcessId(u64 pid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid);
auto proc = Registration::GetProcess(pid);
if (proc != nullptr) {
return svcTerminateProcess(proc->handle);
} else {
return 0x20F;
}
}
Result ShellService::TerminateTitleId(u64 tid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
auto proc = Registration::GetProcessByTitleId(tid);
if (proc != NULL) {
return {svcTerminateProcess(proc->handle)};
return svcTerminateProcess(proc->handle);
} else {
return {0x20F};
return 0x20F;
}
}
std::tuple<Result> ShellService::terminate_title_id(u64 tid) {
void ShellService::GetProcessWaitEvent(Out<CopiedHandle> event) {
event.SetValue(Registration::GetProcessEventHandle());
}
void ShellService::GetProcessEventType(Out<u64> type, Out<u64> pid) {
Registration::GetProcessEventType(pid.GetPointer(), type.GetPointer());
}
Result ShellService::FinalizeExitedProcess(u64 pid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
std::shared_ptr<Registration::Process> proc = Registration::GetProcessByTitleId(tid);
if (proc != NULL) {
return {svcTerminateProcess(proc->handle)};
} else {
return {0x20F};
}
}
std::tuple<Result, CopiedHandle> ShellService::get_process_wait_event() {
return {0x0, Registration::GetProcessEventHandle()};
}
std::tuple<Result, u64, u64> ShellService::get_process_event_type() {
u64 type, pid;
Registration::GetProcessEventType(&pid, &type);
return {0x0, type, pid};
}
std::tuple<Result> ShellService::finalize_exited_process(u64 pid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid);
auto proc = Registration::GetProcess(pid);
if (proc == NULL) {
return {0x20F};
return 0x20F;
} else if (proc->state != ProcessState_Exited) {
return {0x60F};
return 0x60F;
} else {
Registration::FinalizeExitedProcess(proc);
return {0x0};
return 0x0;
}
}
std::tuple<Result> ShellService::clear_process_notification_flag(u64 pid) {
Result ShellService::ClearProcessNotificationFlag(u64 pid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
std::shared_ptr<Registration::Process> proc = Registration::GetProcess(pid);
auto proc = Registration::GetProcess(pid);
if (proc != NULL) {
proc->flags &= ~PROCESSFLAGS_CRASHED;
return {0x0};
return 0x0;
} else {
return {0x20F};
return 0x20F;
}
}
std::tuple<Result> ShellService::notify_boot_finished() {
void ShellService::NotifyBootFinished() {
if (!g_has_boot_finished) {
g_has_boot_finished = true;
EmbeddedBoot2::Main();
}
return {0};
}
std::tuple<Result, u64> ShellService::get_application_process_id() {
Result ShellService::GetApplicationProcessId(Out<u64> pid) {
auto auto_lock = Registration::GetProcessListUniqueLock();
std::shared_ptr<Registration::Process> app_proc;
if (Registration::HasApplicationProcess(&app_proc)) {
return {0, app_proc->pid};
pid.SetValue(app_proc->pid);
return 0;
}
return {0x20F, 0};
return 0x20F;
}
std::tuple<Result> ShellService::boost_system_memory_resource_limit(u64 sysmem_size) {
if (!kernelAbove400()) {
return {0xF601};
}
/* TODO */
return {ResourceLimitUtils::BoostSystemMemoryResourceLimit(sysmem_size)};
Result ShellService::BoostSystemMemoryResourceLimit(u64 sysmem_size) {
return ResourceLimitUtils::BoostSystemMemoryResourceLimit(sysmem_size);
}

View File

@@ -16,7 +16,7 @@
#pragma once
#include <switch.h>
#include <stratosphere/iserviceobject.hpp>
#include <stratosphere.hpp>
#include "pm_registration.hpp"
@@ -46,26 +46,43 @@ enum ShellCmd_5X {
Shell_Cmd_5X_BoostSystemMemoryResourceLimit = 7
};
class ShellService final : public IServiceObject {
public:
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
Result handle_deferred() override;
ShellService *clone() override {
return new ShellService(*this);
}
class ShellService final : public IServiceObject {
private:
/* Actual commands. */
std::tuple<Result, u64> launch_process(u64 launch_flags, Registration::TidSid tid_sid);
std::tuple<Result> terminate_process_id(u64 pid);
std::tuple<Result> terminate_title_id(u64 tid);
std::tuple<Result, CopiedHandle> get_process_wait_event();
std::tuple<Result, u64, u64> get_process_event_type();
std::tuple<Result> finalize_exited_process(u64 pid);
std::tuple<Result> clear_process_notification_flag(u64 pid);
std::tuple<Result> notify_boot_finished();
std::tuple<Result, u64> get_application_process_id();
std::tuple<Result> boost_system_memory_resource_limit(u64 sysmem_size);
Result LaunchProcess(Out<u64> pid, Registration::TidSid tid_sid, u32 launch_flags);
Result TerminateProcessId(u64 pid);
Result TerminateTitleId(u64 tid);
void GetProcessWaitEvent(Out<CopiedHandle> event);
void GetProcessEventType(Out<u64> type, Out<u64> pid);
Result FinalizeExitedProcess(u64 pid);
Result ClearProcessNotificationFlag(u64 pid);
void NotifyBootFinished();
Result GetApplicationProcessId(Out<u64> pid);
Result BoostSystemMemoryResourceLimit(u64 sysmem_size);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
/* 1.0.0-4.0.0 */
MakeServiceCommandMeta<Shell_Cmd_LaunchProcess, &ShellService::LaunchProcess, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Shell_Cmd_TerminateProcessId, &ShellService::TerminateProcessId, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Shell_Cmd_TerminateTitleId, &ShellService::TerminateTitleId, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Shell_Cmd_GetProcessWaitEvent, &ShellService::GetProcessWaitEvent, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Shell_Cmd_GetProcessEventType, &ShellService::GetProcessEventType, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Shell_Cmd_FinalizeExitedProcess, &ShellService::FinalizeExitedProcess, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Shell_Cmd_ClearProcessNotificationFlag, &ShellService::ClearProcessNotificationFlag, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Shell_Cmd_NotifyBootFinished, &ShellService::NotifyBootFinished, FirmwareVersion_Min, FirmwareVersion_400>(),
MakeServiceCommandMeta<Shell_Cmd_GetApplicationProcessId, &ShellService::GetApplicationProcessId, FirmwareVersion_Min, FirmwareVersion_400>(),
/* 4.0.0-4.0.0 */
MakeServiceCommandMeta<Shell_Cmd_BoostSystemMemoryResourceLimit, &ShellService::BoostSystemMemoryResourceLimit, FirmwareVersion_400, FirmwareVersion_400>(),
/* 5.0.0-* */
MakeServiceCommandMeta<Shell_Cmd_5X_LaunchProcess, &ShellService::LaunchProcess, FirmwareVersion_500>(),
MakeServiceCommandMeta<Shell_Cmd_5X_TerminateProcessId, &ShellService::TerminateProcessId, FirmwareVersion_500>(),
MakeServiceCommandMeta<Shell_Cmd_5X_TerminateTitleId, &ShellService::TerminateTitleId, FirmwareVersion_500>(),
MakeServiceCommandMeta<Shell_Cmd_5X_GetProcessWaitEvent, &ShellService::GetProcessWaitEvent, FirmwareVersion_500>(),
MakeServiceCommandMeta<Shell_Cmd_5X_GetProcessEventType, &ShellService::GetProcessEventType, FirmwareVersion_500>(),
MakeServiceCommandMeta<Shell_Cmd_5X_NotifyBootFinished, &ShellService::NotifyBootFinished, FirmwareVersion_500>(),
MakeServiceCommandMeta<Shell_Cmd_5X_GetApplicationProcessId, &ShellService::GetApplicationProcessId, FirmwareVersion_500>(),
MakeServiceCommandMeta<Shell_Cmd_5X_BoostSystemMemoryResourceLimit, &ShellService::BoostSystemMemoryResourceLimit, FirmwareVersion_500>(),
};
};