Merge branch 'master' into npdmfixup
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -173,7 +173,7 @@ void EmbeddedBoot2::Main() {
|
||||
}
|
||||
closedir(titles_dir);
|
||||
}
|
||||
|
||||
|
||||
/* We no longer need the SD card. */
|
||||
fsdevUnmountAll();
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
|
||||
@@ -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>(),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>(),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>(),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>(),
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user