mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-23 04:12:02 +00:00
pm: update for libstratosphere refactor
This commit is contained in:
parent
9a8c70ed68
commit
887b4e0275
17 changed files with 229 additions and 526 deletions
|
@ -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,
|
||||
|
|
|
@ -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<bool> 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<bool> out);
|
||||
void SetMaintenanceBoot();
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MakeServiceCommandMeta<BootMode_Cmd_GetBootMode, &BootModeService::GetBootMode>(),
|
||||
MakeServiceCommandMeta<BootMode_Cmd_SetMaintenanceBoot, &BootModeService::SetMaintenanceBoot>(),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -20,172 +20,88 @@
|
|||
#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;
|
||||
case Dmnt_Cmd_5X_AtmosphereGetCurrentLimitInfo:
|
||||
rc = WrapIpcCommandImpl<&DebugMonitorService::get_current_limit_info>(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;
|
||||
case Dmnt_Cmd_AtmosphereGetCurrentLimitInfo:
|
||||
rc = WrapIpcCommandImpl<&DebugMonitorService::get_current_limit_info>(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;
|
||||
}
|
||||
|
||||
std::tuple<Result, u64, u64> DebugMonitorService::get_current_limit_info(u32 category, u32 resource) {
|
||||
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, 0, 0};
|
||||
return 0xF001;
|
||||
}
|
||||
|
||||
Handle limit_h = ResourceLimitUtils::GetResourceLimitHandleByCategory((ResourceLimitUtils::ResourceLimitCategory) category);
|
||||
|
||||
uint64_t current_value, limit_value;
|
||||
|
||||
Result r;
|
||||
|
||||
r = svcGetResourceLimitCurrentValue(¤t_value, limit_h, (LimitableResource) resource);
|
||||
if(R_FAILED(r)) {
|
||||
return {r, 0, 0};
|
||||
rc = svcGetResourceLimitCurrentValue(cur_val.GetPointer(), limit_h, (LimitableResource) resource);
|
||||
if(R_FAILED(rc)) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
r = svcGetResourceLimitLimitValue(&limit_value, limit_h, (LimitableResource) resource);
|
||||
if(R_FAILED(r)) {
|
||||
return {r, 0, 0};
|
||||
rc = svcGetResourceLimitLimitValue(lim_val.GetPointer(), limit_h, (LimitableResource) resource);
|
||||
if(R_FAILED(rc)) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return {0, current_value, limit_value};
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <stratosphere/iserviceobject.hpp>
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
#include "pm_registration.hpp"
|
||||
|
||||
|
@ -28,12 +28,7 @@ enum DmntCmd {
|
|||
Dmnt_Cmd_EnableDebugForTitleId = 4,
|
||||
Dmnt_Cmd_GetApplicationProcessId = 5,
|
||||
Dmnt_Cmd_EnableDebugForApplication = 6,
|
||||
|
||||
Dmnt_Cmd_AtmosphereGetProcessHandle = 65000,
|
||||
Dmnt_Cmd_AtmosphereGetCurrentLimitInfo = 65001,
|
||||
};
|
||||
|
||||
enum DmntCmd_5X {
|
||||
|
||||
Dmnt_Cmd_5X_GetDebugProcessIds = 0,
|
||||
Dmnt_Cmd_5X_LaunchDebugProcess = 1,
|
||||
Dmnt_Cmd_5X_GetTitleProcessId = 2,
|
||||
|
@ -43,31 +38,49 @@ enum DmntCmd_5X {
|
|||
|
||||
Dmnt_Cmd_6X_DisableDebug = 6,
|
||||
|
||||
Dmnt_Cmd_5X_AtmosphereGetProcessHandle = 65000,
|
||||
Dmnt_Cmd_5X_AtmosphereGetCurrentLimitInfo = 65001,
|
||||
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);
|
||||
std::tuple<Result, u64, u64> get_current_limit_info(u32 category, u32 resource);
|
||||
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>(),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "pm_process_track.hpp"
|
||||
#include "pm_registration.hpp"
|
||||
#include "pm_debug_monitor.hpp"
|
||||
#include "smm_ams.h"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
@ -150,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)) {
|
||||
|
@ -181,6 +179,7 @@ HANDLE_PROCESS_LAUNCH_END:
|
|||
if (R_SUCCEEDED(rc)) {
|
||||
*out_pid = new_process.pid;
|
||||
}
|
||||
|
||||
g_sema_finish_launch.Signal();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -253,7 +252,7 @@ Result Registration::HandleSignaledProcess(std::shared_ptr<Registration::Process
|
|||
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_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,7 +411,7 @@ 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) {
|
||||
|
@ -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);
|
||||
|
|
|
@ -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, u64 launch_flags, Registration::TidSid tid_sid) {
|
||||
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, u64 launch_flags, Registration::TidSid tid_sid);
|
||||
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>(),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <switch/arm/atomics.h>
|
||||
#include "smm_ams.h"
|
||||
|
||||
static Service g_smManagerAmsSrv;
|
||||
static u64 g_smManagerAmsRefcnt;
|
||||
|
||||
Result smManagerAmsInitialize(void) {
|
||||
atomicIncrement64(&g_smManagerAmsRefcnt);
|
||||
|
||||
if (serviceIsActive(&g_smManagerAmsSrv))
|
||||
return 0;
|
||||
|
||||
return smGetService(&g_smManagerAmsSrv, "sm:m");
|
||||
}
|
||||
|
||||
void smManagerAmsExit(void) {
|
||||
if (atomicDecrement64(&g_smManagerAmsRefcnt) == 0)
|
||||
serviceClose(&g_smManagerAmsSrv);
|
||||
}
|
||||
|
||||
Result smManagerAmsEndInitialDefers(void) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = serviceIpcPrepareHeader(&g_smManagerAmsSrv, &c, sizeof(*raw));
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 65000;
|
||||
|
||||
|
||||
Result rc = serviceIpcDispatch(&g_smManagerAmsSrv);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&g_smManagerAmsSrv, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/**
|
||||
* @file smm_ams.h
|
||||
* @brief Service manager (sm:m) IPC wrapper for Atmosphere extensions.
|
||||
* @author SciresM
|
||||
* @copyright libnx Authors
|
||||
*/
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
Result smManagerAmsInitialize(void);
|
||||
void smManagerAmsExit(void);
|
||||
|
||||
Result smManagerAmsEndInitialDefers(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Reference in a new issue