new-ipc: implement deferral. sm now works.

This commit is contained in:
Michael Scire 2019-10-11 02:15:14 -07:00 committed by SciresM
parent f4dcd1db9b
commit c8ed190e5c
13 changed files with 193 additions and 157 deletions

View file

@ -127,6 +127,10 @@ namespace sts::sf::hipc {
os::Mutex waitlist_mutex; os::Mutex waitlist_mutex;
os::WaitableManager waitlist; os::WaitableManager waitlist;
os::Mutex deferred_session_mutex;
using DeferredSessionList = typename util::IntrusiveListMemberTraits<&ServerSession::deferred_list_node>::ListType;
DeferredSessionList deferred_session_list;
private: private:
virtual void RegisterSessionToWaitList(ServerSession *session) override final; virtual void RegisterSessionToWaitList(ServerSession *session) override final;
void RegisterToWaitList(os::WaitableHolder *holder); void RegisterToWaitList(os::WaitableHolder *holder);
@ -138,6 +142,8 @@ namespace sts::sf::hipc {
Result ProcessForMitmServer(os::WaitableHolder *holder); Result ProcessForMitmServer(os::WaitableHolder *holder);
Result ProcessForSession(os::WaitableHolder *holder); Result ProcessForSession(os::WaitableHolder *holder);
void ProcessDeferredSessions();
template<typename ServiceImpl, auto MakeShared = std::make_shared<ServiceImpl>> template<typename ServiceImpl, auto MakeShared = std::make_shared<ServiceImpl>>
void RegisterServerImpl(Handle port_handle, sm::ServiceName service_name, bool managed, cmif::ServiceObjectHolder &&static_holder) { void RegisterServerImpl(Handle port_handle, sm::ServiceName service_name, bool managed, cmif::ServiceObjectHolder &&static_holder) {
/* Allocate server memory. */ /* Allocate server memory. */

View file

@ -32,6 +32,7 @@ namespace sts::sf::hipc {
NON_COPYABLE(ServerSession); NON_COPYABLE(ServerSession);
NON_MOVEABLE(ServerSession); NON_MOVEABLE(ServerSession);
private: private:
util::IntrusiveListNode deferred_list_node;
cmif::ServiceObjectHolder srv_obj_holder; cmif::ServiceObjectHolder srv_obj_holder;
cmif::PointerAndSize pointer_buffer; cmif::PointerAndSize pointer_buffer;
cmif::PointerAndSize saved_message; cmif::PointerAndSize saved_message;

View file

@ -936,10 +936,15 @@ namespace sts::sf::impl {
if constexpr (Info.arg_type == ArgumentType::InData) { if constexpr (Info.arg_type == ArgumentType::InData) {
/* New in rawdata. */ /* New in rawdata. */
constexpr size_t Offset = CommandMeta::InDataOffsets[Info.in_raw_data_index]; constexpr size_t Offset = CommandMeta::InDataOffsets[Info.in_raw_data_index];
return *reinterpret_cast<const T *>(in_raw_data.GetAddress() + Offset); if constexpr (!std::is_same<T, bool>::value) {
return *reinterpret_cast<const T *>(in_raw_data.GetAddress() + Offset);
} else {
/* Special case bools. */
return *reinterpret_cast<const u8 *>(in_raw_data.GetAddress() + Offset) & 1;
}
} else if constexpr (Info.arg_type == ArgumentType::OutData) { } else if constexpr (Info.arg_type == ArgumentType::OutData) {
/* New out rawdata. */ /* New out rawdata. */
constexpr size_t Offset = CommandMeta::InDataOffsets[Info.in_raw_data_index]; constexpr size_t Offset = CommandMeta::InDataOffsets[Info.out_raw_data_index];
return T(out_raw_holder.template GetAddress<Offset, T::TypeSize>()); return T(out_raw_holder.template GetAddress<Offset, T::TypeSize>());
} else if constexpr (Info.arg_type == ArgumentType::InHandle) { } else if constexpr (Info.arg_type == ArgumentType::InHandle) {
/* New InHandle. */ /* New InHandle. */

View file

@ -127,6 +127,27 @@ namespace sts::sf::hipc {
return this->ProcessRequest(session, tls_message); return this->ProcessRequest(session, tls_message);
} }
void ServerManagerBase::ProcessDeferredSessions() {
/* Iterate over the list of deferred sessions, and see if we can't do anything. */
std::scoped_lock lk(this->deferred_session_mutex);
auto it = this->deferred_session_list.begin();
while (it != this->deferred_session_list.end()) {
ServerSession *session = static_cast<ServerSession *>(&*it);
R_TRY_CATCH(this->ProcessForSession(session)) {
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) {
/* Session is still deferred, so let's continue. */
it++;
continue;
}
/* TODO: N has a result that undefers without success. */
} R_END_TRY_CATCH_WITH_ASSERT;
/* We succeeded! Remove from deferred list. */
it = this->deferred_session_list.erase(it);
}
}
Result ServerManagerBase::Process(os::WaitableHolder *holder) { Result ServerManagerBase::Process(os::WaitableHolder *holder) {
switch (static_cast<UserDataTag>(holder->GetUserData())) { switch (static_cast<UserDataTag>(holder->GetUserData())) {
case UserDataTag::Server: case UserDataTag::Server:
@ -136,8 +157,19 @@ namespace sts::sf::hipc {
return this->ProcessForMitmServer(holder); return this->ProcessForMitmServer(holder);
break; break;
case UserDataTag::Session: case UserDataTag::Session:
/* TODO: Process deferred. */ /* Try to process for session. */
return this->ProcessForSession(holder); R_TRY_CATCH(this->ProcessForSession(holder)) {
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) {
/* The session was deferred, so push it onto the deferred session list. */
std::scoped_lock lk(this->deferred_session_mutex);
this->deferred_session_list.push_back(*static_cast<ServerSession *>(holder));
return ResultSuccess;
}
} R_END_TRY_CATCH;
/* We successfully invoked a command...so let's see if anything can be undeferred. */
this->ProcessDeferredSessions();
return ResultSuccess;
break; break;
STS_UNREACHABLE_DEFAULT_CASE(); STS_UNREACHABLE_DEFAULT_CASE();
} }

View file

@ -34,7 +34,7 @@ namespace sts::sm::impl {
/* Types. */ /* Types. */
struct ProcessInfo { struct ProcessInfo {
u64 pid; os::ProcessId pid;
ncm::TitleId tid; ncm::TitleId tid;
size_t access_control_size; size_t access_control_size;
u8 access_control[AccessControlSizeMax]; u8 access_control[AccessControlSizeMax];
@ -44,7 +44,7 @@ namespace sts::sm::impl {
} }
void Free() { void Free() {
this->pid = InvalidProcessId; this->pid = os::InvalidProcessId;
this->tid = ncm::TitleId::Invalid; this->tid = ncm::TitleId::Invalid;
this->access_control_size = 0; this->access_control_size = 0;
std::memset(this->access_control, 0, sizeof(this->access_control)); std::memset(this->access_control, 0, sizeof(this->access_control));
@ -52,11 +52,11 @@ namespace sts::sm::impl {
}; };
/* Forward declaration, for use in ServiceInfo. */ /* Forward declaration, for use in ServiceInfo. */
ncm::TitleId GetTitleIdForMitm(u64 pid); ncm::TitleId GetTitleIdForMitm(os::ProcessId pid);
struct ServiceInfo { struct ServiceInfo {
ServiceName name; ServiceName name;
u64 owner_pid; os::ProcessId owner_pid;
os::ManagedHandle port_h; os::ManagedHandle port_h;
/* Debug. */ /* Debug. */
@ -64,13 +64,13 @@ namespace sts::sm::impl {
bool is_light; bool is_light;
/* Mitm Extension. */ /* Mitm Extension. */
u64 mitm_pid; os::ProcessId mitm_pid;
os::ManagedHandle mitm_port_h; os::ManagedHandle mitm_port_h;
os::ManagedHandle mitm_query_h; os::ManagedHandle mitm_query_h;
/* Acknowledgement members. */ /* Acknowledgement members. */
bool mitm_waiting_ack; bool mitm_waiting_ack;
u64 mitm_waiting_ack_pid; os::ProcessId mitm_waiting_ack_pid;
os::ManagedHandle mitm_fwd_sess_h; os::ManagedHandle mitm_fwd_sess_h;
ServiceInfo() { ServiceInfo() {
@ -86,12 +86,12 @@ namespace sts::sm::impl {
/* Reset all other members. */ /* Reset all other members. */
this->name = InvalidServiceName; this->name = InvalidServiceName;
this->owner_pid = InvalidProcessId; this->owner_pid = os::InvalidProcessId;
this->max_sessions = 0; this->max_sessions = 0;
this->is_light = false; this->is_light = false;
this->mitm_pid = InvalidProcessId; this->mitm_pid = os::InvalidProcessId;
this->mitm_waiting_ack = false; this->mitm_waiting_ack = false;
this->mitm_waiting_ack_pid = InvalidProcessId; this->mitm_waiting_ack_pid = os::InvalidProcessId;
} }
void FreeMitm() { void FreeMitm() {
@ -100,16 +100,16 @@ namespace sts::sm::impl {
this->mitm_query_h.Clear(); this->mitm_query_h.Clear();
/* Reset mitm members. */ /* Reset mitm members. */
this->mitm_pid = InvalidProcessId; this->mitm_pid = os::InvalidProcessId;
} }
void AcknowledgeMitmSession(u64 *out_pid, ncm::TitleId *out_tid, Handle *out_hnd) { void AcknowledgeMitmSession(os::ProcessId *out_pid, ncm::TitleId *out_tid, Handle *out_hnd) {
/* Copy to output. */ /* Copy to output. */
*out_pid = this->mitm_waiting_ack_pid; *out_pid = this->mitm_waiting_ack_pid;
*out_tid = GetTitleIdForMitm(this->mitm_waiting_ack_pid); *out_tid = GetTitleIdForMitm(this->mitm_waiting_ack_pid);
*out_hnd = this->mitm_fwd_sess_h.Move(); *out_hnd = this->mitm_fwd_sess_h.Move();
this->mitm_waiting_ack = false; this->mitm_waiting_ack = false;
this->mitm_waiting_ack_pid = InvalidProcessId; this->mitm_waiting_ack_pid = os::InvalidProcessId;
} }
}; };
@ -159,8 +159,8 @@ namespace sts::sm::impl {
class InitialProcessIdLimits { class InitialProcessIdLimits {
private: private:
u64 min; os::ProcessId min;
u64 max; os::ProcessId max;
public: public:
InitialProcessIdLimits() { InitialProcessIdLimits() {
/* Retrieve process limits. */ /* Retrieve process limits. */
@ -170,8 +170,8 @@ namespace sts::sm::impl {
STS_ASSERT(this->min <= this->max); STS_ASSERT(this->min <= this->max);
} }
bool IsInitialProcess(u64 pid) const { bool IsInitialProcess(os::ProcessId pid) const {
STS_ASSERT(pid != InvalidProcessId); STS_ASSERT(pid != os::InvalidProcessId);
return this->min <= pid && pid <= this->max; return this->min <= pid && pid <= this->max;
} }
}; };
@ -184,7 +184,7 @@ namespace sts::sm::impl {
bool g_ended_initial_defers; bool g_ended_initial_defers;
/* Helper functions for interacting with processes/services. */ /* Helper functions for interacting with processes/services. */
ProcessInfo *GetProcessInfo(u64 pid) { ProcessInfo *GetProcessInfo(os::ProcessId pid) {
for (size_t i = 0; i < ProcessCountMax; i++) { for (size_t i = 0; i < ProcessCountMax; i++) {
if (g_process_list[i].pid == pid) { if (g_process_list[i].pid == pid) {
return &g_process_list[i]; return &g_process_list[i];
@ -194,19 +194,19 @@ namespace sts::sm::impl {
} }
ProcessInfo *GetFreeProcessInfo() { ProcessInfo *GetFreeProcessInfo() {
return GetProcessInfo(InvalidProcessId); return GetProcessInfo(os::InvalidProcessId);
} }
bool HasProcessInfo(u64 pid) { bool HasProcessInfo(os::ProcessId pid) {
return GetProcessInfo(pid) != nullptr; return GetProcessInfo(pid) != nullptr;
} }
bool IsInitialProcess(u64 pid) { bool IsInitialProcess(os::ProcessId pid) {
return g_initial_process_id_limits.IsInitialProcess(pid); return g_initial_process_id_limits.IsInitialProcess(pid);
} }
bool IsValidProcessId(u64 pid) { constexpr inline bool IsValidProcessId(os::ProcessId pid) {
return pid != InvalidProcessId; return pid != os::InvalidProcessId;
} }
ServiceInfo *GetServiceInfo(ServiceName service_name) { ServiceInfo *GetServiceInfo(ServiceName service_name) {
@ -231,7 +231,7 @@ namespace sts::sm::impl {
return service_info != nullptr && IsValidProcessId(service_info->mitm_pid); return service_info != nullptr && IsValidProcessId(service_info->mitm_pid);
} }
ncm::TitleId GetTitleIdForMitm(u64 pid) { ncm::TitleId GetTitleIdForMitm(os::ProcessId pid) {
/* Anything that can request a mitm session must have a process info. */ /* Anything that can request a mitm session must have a process info. */
const auto process_info = GetProcessInfo(pid); const auto process_info = GetProcessInfo(pid);
STS_ASSERT(process_info != nullptr); STS_ASSERT(process_info != nullptr);
@ -352,37 +352,16 @@ namespace sts::sm::impl {
return service == ServiceName::Encode("fsp-srv"); return service == ServiceName::Encode("fsp-srv");
} }
Result GetMitmServiceHandleImpl(Handle *out, ServiceInfo *service_info, u64 pid, ncm::TitleId title_id) { Result GetMitmServiceHandleImpl(Handle *out, ServiceInfo *service_info, os::ProcessId process_id, ncm::TitleId title_id) {
/* Send command to query if we should mitm. */ /* Send command to query if we should mitm. */
{
IpcCommand c;
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 pid;
ncm::TitleId tid;
} *info = ((decltype(info))ipcPrepareHeader(&c, sizeof(*info)));
info->magic = SFCI_MAGIC;
info->cmd_id = 65000;
info->pid = pid;
info->tid = title_id;
R_TRY(ipcDispatch(service_info->mitm_query_h.Get()));
}
/* Parse response to see if we should mitm. */
bool should_mitm; bool should_mitm;
{ {
IpcParsedCommand r; Service srv { .session = service_info->mitm_query_h.Get() };
ipcParse(&r); const struct {
struct { os::ProcessId process_id;
u64 magic; ncm::TitleId title_id;
u64 result; } in = { process_id, title_id };
bool should_mitm; R_TRY(serviceDispatchInOut(&srv, 65000, in, should_mitm));
} *resp = ((decltype(resp))r.Raw);
R_TRY(resp->result);
should_mitm = resp->should_mitm;
} }
/* If we shouldn't mitm, give normal session. */ /* If we shouldn't mitm, give normal session. */
@ -399,13 +378,13 @@ namespace sts::sm::impl {
*out = hnd.Move(); *out = hnd.Move();
} }
service_info->mitm_waiting_ack_pid = pid; service_info->mitm_waiting_ack_pid = process_id;
service_info->mitm_waiting_ack = true; service_info->mitm_waiting_ack = true;
return ResultSuccess; return ResultSuccess;
} }
Result GetServiceHandleImpl(Handle *out, ServiceInfo *service_info, u64 pid) { Result GetServiceHandleImpl(Handle *out, ServiceInfo *service_info, os::ProcessId pid) {
/* Clear handle output. */ /* Clear handle output. */
*out = INVALID_HANDLE; *out = INVALID_HANDLE;
@ -424,7 +403,7 @@ namespace sts::sm::impl {
return svcConnectToPort(out, service_info->port_h.Get()); return svcConnectToPort(out, service_info->port_h.Get());
} }
Result RegisterServiceImpl(Handle *out, u64 pid, ServiceName service, size_t max_sessions, bool is_light) { Result RegisterServiceImpl(Handle *out, os::ProcessId pid, ServiceName service, size_t max_sessions, bool is_light) {
/* Validate service name. */ /* Validate service name. */
R_TRY(ValidateServiceName(service)); R_TRY(ValidateServiceName(service));
@ -461,7 +440,7 @@ namespace sts::sm::impl {
} }
/* Process management. */ /* Process management. */
Result RegisterProcess(u64 pid, ncm::TitleId tid, const void *acid_sac, size_t acid_sac_size, const void *aci_sac, size_t aci_sac_size) { Result RegisterProcess(os::ProcessId pid, ncm::TitleId tid, const void *acid_sac, size_t acid_sac_size, const void *aci_sac, size_t aci_sac_size) {
/* Check that access control will fit in the ServiceInfo. */ /* Check that access control will fit in the ServiceInfo. */
if (aci_sac_size > AccessControlSizeMax) { if (aci_sac_size > AccessControlSizeMax) {
return ResultSmTooLargeAccessControl; return ResultSmTooLargeAccessControl;
@ -487,7 +466,7 @@ namespace sts::sm::impl {
return ResultSuccess; return ResultSuccess;
} }
Result UnregisterProcess(u64 pid) { Result UnregisterProcess(os::ProcessId pid) {
/* Find the process. */ /* Find the process. */
ProcessInfo *proc = GetProcessInfo(pid); ProcessInfo *proc = GetProcessInfo(pid);
if (proc == nullptr) { if (proc == nullptr) {
@ -518,7 +497,7 @@ namespace sts::sm::impl {
return ResultSuccess; return ResultSuccess;
} }
Result GetServiceHandle(Handle *out, u64 pid, ServiceName service) { Result GetServiceHandle(Handle *out, os::ProcessId pid, ServiceName service) {
/* Validate service name. */ /* Validate service name. */
R_TRY(ValidateServiceName(service)); R_TRY(ValidateServiceName(service));
@ -527,7 +506,7 @@ namespace sts::sm::impl {
/* This would return true, and homebrew would *wait forever* trying to get a handle to a service */ /* This would return true, and homebrew would *wait forever* trying to get a handle to a service */
/* that will never register. Thus, in the interest of not breaking every single piece of homebrew */ /* that will never register. Thus, in the interest of not breaking every single piece of homebrew */
/* we will provide a little first class help. */ /* we will provide a little first class help. */
if (GetRuntimeFirmwareVersion() >= FirmwareVersion_800 && service == ServiceName::Encode("apm:p")) { if (hos::GetVersion() >= hos::Version_800 && service == ServiceName::Encode("apm:p")) {
return ResultSmNotAllowed; return ResultSmNotAllowed;
} }
@ -558,7 +537,7 @@ namespace sts::sm::impl {
return ResultSuccess; return ResultSuccess;
} }
Result RegisterService(Handle *out, u64 pid, ServiceName service, size_t max_sessions, bool is_light) { Result RegisterService(Handle *out, os::ProcessId pid, ServiceName service, size_t max_sessions, bool is_light) {
/* Validate service name. */ /* Validate service name. */
R_TRY(ValidateServiceName(service)); R_TRY(ValidateServiceName(service));
@ -580,13 +559,10 @@ namespace sts::sm::impl {
} }
Result RegisterServiceForSelf(Handle *out, ServiceName service, size_t max_sessions) { Result RegisterServiceForSelf(Handle *out, ServiceName service, size_t max_sessions) {
u64 self_pid; return RegisterServiceImpl(out, os::GetCurrentProcessId(), service, max_sessions, false);
R_TRY(svcGetProcessId(&self_pid, CUR_PROCESS_HANDLE));
return RegisterServiceImpl(out, self_pid, service, max_sessions, false);
} }
Result UnregisterService(u64 pid, ServiceName service) { Result UnregisterService(os::ProcessId pid, ServiceName service) {
/* Validate service name. */ /* Validate service name. */
R_TRY(ValidateServiceName(service)); R_TRY(ValidateServiceName(service));
@ -634,7 +610,7 @@ namespace sts::sm::impl {
return ResultSuccess; return ResultSuccess;
} }
Result InstallMitm(Handle *out, Handle *out_query, u64 pid, ServiceName service) { Result InstallMitm(Handle *out, Handle *out_query, os::ProcessId pid, ServiceName service) {
/* Validate service name. */ /* Validate service name. */
R_TRY(ValidateServiceName(service)); R_TRY(ValidateServiceName(service));
@ -685,7 +661,7 @@ namespace sts::sm::impl {
return ResultSuccess; return ResultSuccess;
} }
Result UninstallMitm(u64 pid, ServiceName service) { Result UninstallMitm(os::ProcessId pid, ServiceName service) {
/* Validate service name. */ /* Validate service name. */
R_TRY(ValidateServiceName(service)); R_TRY(ValidateServiceName(service));
@ -713,7 +689,7 @@ namespace sts::sm::impl {
return ResultSuccess; return ResultSuccess;
} }
Result DeclareFutureMitm(u64 pid, ServiceName service) { Result DeclareFutureMitm(os::ProcessId pid, ServiceName service) {
/* Validate service name. */ /* Validate service name. */
R_TRY(ValidateServiceName(service)); R_TRY(ValidateServiceName(service));
@ -737,7 +713,7 @@ namespace sts::sm::impl {
return ResultSuccess; return ResultSuccess;
} }
Result AcknowledgeMitmSession(u64 *out_pid, ncm::TitleId *out_tid, Handle *out_hnd, u64 pid, ServiceName service) { Result AcknowledgeMitmSession(os::ProcessId *out_pid, ncm::TitleId *out_tid, Handle *out_hnd, os::ProcessId pid, ServiceName service) {
/* Validate service name. */ /* Validate service name. */
R_TRY(ValidateServiceName(service)); R_TRY(ValidateServiceName(service));

View file

@ -22,24 +22,24 @@
namespace sts::sm::impl { namespace sts::sm::impl {
/* Process management. */ /* Process management. */
Result RegisterProcess(u64 pid, ncm::TitleId tid, const void *acid_sac, size_t acid_sac_size, const void *aci_sac, size_t aci_sac_size); Result RegisterProcess(os::ProcessId pid, ncm::TitleId tid, const void *acid_sac, size_t acid_sac_size, const void *aci_sac, size_t aci_sac_size);
Result UnregisterProcess(u64 pid); Result UnregisterProcess(os::ProcessId pid);
/* Service management. */ /* Service management. */
Result HasService(bool *out, ServiceName service); Result HasService(bool *out, ServiceName service);
Result WaitService(ServiceName service); Result WaitService(ServiceName service);
Result GetServiceHandle(Handle *out, u64 pid, ServiceName service); Result GetServiceHandle(Handle *out, os::ProcessId pid, ServiceName service);
Result RegisterService(Handle *out, u64 pid, ServiceName service, size_t max_sessions, bool is_light); Result RegisterService(Handle *out, os::ProcessId pid, ServiceName service, size_t max_sessions, bool is_light);
Result RegisterServiceForSelf(Handle *out, ServiceName service, size_t max_sessions); Result RegisterServiceForSelf(Handle *out, ServiceName service, size_t max_sessions);
Result UnregisterService(u64 pid, ServiceName service); Result UnregisterService(os::ProcessId pid, ServiceName service);
/* Mitm extensions. */ /* Mitm extensions. */
Result HasMitm(bool *out, ServiceName service); Result HasMitm(bool *out, ServiceName service);
Result WaitMitm(ServiceName service); Result WaitMitm(ServiceName service);
Result InstallMitm(Handle *out, Handle *out_query, u64 pid, ServiceName service); Result InstallMitm(Handle *out, Handle *out_query, os::ProcessId pid, ServiceName service);
Result UninstallMitm(u64 pid, ServiceName service); Result UninstallMitm(os::ProcessId pid, ServiceName service);
Result DeclareFutureMitm(u64 pid, ServiceName service); Result DeclareFutureMitm(os::ProcessId pid, ServiceName service);
Result AcknowledgeMitmSession(u64 *out_pid, ncm::TitleId *out_tid, Handle *out_hnd, u64 pid, ServiceName service); Result AcknowledgeMitmSession(os::ProcessId *out_pid, ncm::TitleId *out_tid, Handle *out_hnd, os::ProcessId pid, ServiceName service);
/* Dmnt record extensions. */ /* Dmnt record extensions. */
Result GetServiceRecord(ServiceRecord *out, ServiceName service); Result GetServiceRecord(ServiceRecord *out, ServiceName service);

View file

@ -22,15 +22,15 @@
namespace sts::sm { namespace sts::sm {
Result DmntService::AtmosphereGetRecord(Out<ServiceRecord> record, ServiceName service) { Result DmntService::AtmosphereGetRecord(sf::Out<ServiceRecord> record, ServiceName service) {
return impl::GetServiceRecord(record.GetPointer(), service); return impl::GetServiceRecord(record.GetPointer(), service);
} }
void DmntService::AtmosphereListRecords(OutBuffer<ServiceRecord> records, Out<u64> out_count, u64 offset) { void DmntService::AtmosphereListRecords(const sf::OutArray<ServiceRecord> &records, sf::Out<u64> out_count, u64 offset) {
R_ASSERT(impl::ListServiceRecords(records.buffer, out_count.GetPointer(), offset, records.num_elements)); R_ASSERT(impl::ListServiceRecords(records.GetPointer(), out_count.GetPointer(), offset, records.GetSize()));
} }
void DmntService::AtmosphereGetRecordSize(Out<u64> record_size) { void DmntService::AtmosphereGetRecordSize(sf::Out<u64> record_size) {
record_size.SetValue(sizeof(ServiceRecord)); record_size.SetValue(sizeof(ServiceRecord));
} }

View file

@ -22,7 +22,7 @@
namespace sts::sm { namespace sts::sm {
/* Service definition. */ /* Service definition. */
class DmntService final : public IServiceObject { class DmntService final : public sf::IServiceObject {
protected: protected:
/* Command IDs. */ /* Command IDs. */
enum class CommandId { enum class CommandId {
@ -32,14 +32,14 @@ namespace sts::sm {
}; };
private: private:
/* Actual commands. */ /* Actual commands. */
virtual Result AtmosphereGetRecord(Out<ServiceRecord> record, ServiceName service); virtual Result AtmosphereGetRecord(sf::Out<ServiceRecord> record, ServiceName service);
virtual void AtmosphereListRecords(OutBuffer<ServiceRecord> records, Out<u64> out_count, u64 offset); virtual void AtmosphereListRecords(const sf::OutArray<ServiceRecord> &records, sf::Out<u64> out_count, u64 offset);
virtual void AtmosphereGetRecordSize(Out<u64> record_size); virtual void AtmosphereGetRecordSize(sf::Out<u64> record_size);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(DmntService, AtmosphereGetRecord), MAKE_SERVICE_COMMAND_META(AtmosphereGetRecord),
MAKE_SERVICE_COMMAND_META(DmntService, AtmosphereListRecords), MAKE_SERVICE_COMMAND_META(AtmosphereListRecords),
MAKE_SERVICE_COMMAND_META(DmntService, AtmosphereGetRecordSize), MAKE_SERVICE_COMMAND_META(AtmosphereGetRecordSize),
}; };
}; };

View file

@ -33,7 +33,7 @@ extern "C" {
u32 __nx_applet_type = AppletType_None; u32 __nx_applet_type = AppletType_None;
#define INNER_HEAP_SIZE 0x20000 #define INNER_HEAP_SIZE 0x4000
size_t nx_inner_heap_size = INNER_HEAP_SIZE; size_t nx_inner_heap_size = INNER_HEAP_SIZE;
char nx_inner_heap[INNER_HEAP_SIZE]; char nx_inner_heap[INNER_HEAP_SIZE];
@ -68,7 +68,7 @@ void __libnx_initheap(void) {
} }
void __appInit(void) { void __appInit(void) {
SetFirmwareVersionForLibnx(); sts::hos::SetVersionForLibnx();
/* We must do no service setup here, because we are sm. */ /* We must do no service setup here, because we are sm. */
} }
@ -79,29 +79,45 @@ void __appExit(void) {
using namespace sts; using namespace sts;
namespace {
/* sm:m, sm:, sm:dmnt. */
constexpr size_t NumServers = 3;
sf::hipc::ServerManager<NumServers> g_server_manager;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
/* Create service waitable manager. */ /* NOTE: These handles are manually managed, but we don't save references to them to close on exit. */
static auto s_server_manager = WaitableManager(1); /* This is fine, because if SM crashes we have much bigger issues. */
/* Create sm:, (and thus allow things to register to it). */ /* Create sm:, (and thus allow things to register to it). */
s_server_manager.AddWaitable(new ManagedPortServer<sm::UserService>("sm:", 0x40)); {
Handle sm_h;
R_ASSERT(svcManageNamedPort(&sm_h, "sm:", 0x40));
g_server_manager.RegisterServer<sm::UserService>(sm_h);
}
/* Create sm:m manually. */ /* Create sm:m manually. */
Handle smm_h; {
R_ASSERT(sm::impl::RegisterServiceForSelf(&smm_h, sm::ServiceName::Encode("sm:m"), 1)); Handle smm_h;
s_server_manager.AddWaitable(new ExistingPortServer<sm::ManagerService>(smm_h, 1)); R_ASSERT(sm::impl::RegisterServiceForSelf(&smm_h, sm::ServiceName::Encode("sm:m"), 1));
g_server_manager.RegisterServer<sm::ManagerService>(smm_h);
}
/*===== ATMOSPHERE EXTENSION =====*/ /*===== ATMOSPHERE EXTENSION =====*/
/* Create sm:dmnt manually. */ /* Create sm:dmnt manually. */
Handle smdmnt_h; {
R_ASSERT(sm::impl::RegisterServiceForSelf(&smdmnt_h, sm::ServiceName::Encode("sm:dmnt"), 1)); Handle smdmnt_h;
s_server_manager.AddWaitable(new ExistingPortServer<sm::DmntService>(smm_h, 1));; R_ASSERT(sm::impl::RegisterServiceForSelf(&smdmnt_h, sm::ServiceName::Encode("sm:dmnt"), 1));
g_server_manager.RegisterServer<sm::DmntService>(smdmnt_h);
}
/*================================*/ /*================================*/
/* Loop forever, servicing our services. */ /* Loop forever, servicing our services. */
s_server_manager.Process(); g_server_manager.LoopProcess();
/* Cleanup. */ /* Cleanup. */
return 0; return 0;

View file

@ -22,25 +22,25 @@
namespace sts::sm { namespace sts::sm {
Result ManagerService::RegisterProcess(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci_sac) { Result ManagerService::RegisterProcess(os::ProcessId process_id, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac) {
return impl::RegisterProcess(pid, ncm::TitleId::Invalid, acid_sac.buffer, acid_sac.num_elements, aci_sac.buffer, aci_sac.num_elements); return impl::RegisterProcess(process_id, ncm::TitleId::Invalid, acid_sac.GetPointer(), acid_sac.GetSize(), aci_sac.GetPointer(), aci_sac.GetSize());
} }
Result ManagerService::UnregisterProcess(u64 pid) { Result ManagerService::UnregisterProcess(os::ProcessId process_id) {
return impl::UnregisterProcess(pid); return impl::UnregisterProcess(process_id);
} }
void ManagerService::AtmosphereEndInitDefers() { void ManagerService::AtmosphereEndInitDefers() {
R_ASSERT(impl::EndInitialDefers()); R_ASSERT(impl::EndInitialDefers());
} }
void ManagerService::AtmosphereHasMitm(Out<bool> out, ServiceName service) { void ManagerService::AtmosphereHasMitm(sf::Out<bool> out, ServiceName service) {
R_ASSERT(impl::HasMitm(out.GetPointer(), service)); R_ASSERT(impl::HasMitm(out.GetPointer(), service));
} }
Result ManagerService::AtmosphereRegisterProcess(u64 pid, ncm::TitleId tid, InBuffer<u8> acid_sac, InBuffer<u8> aci_sac) { Result ManagerService::AtmosphereRegisterProcess(os::ProcessId process_id, ncm::TitleId title_id, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac) {
/* This takes in a title id, unlike RegisterProcess. */ /* This takes in a title id, unlike RegisterProcess. */
return impl::RegisterProcess(pid, tid, acid_sac.buffer, acid_sac.num_elements, aci_sac.buffer, aci_sac.num_elements); return impl::RegisterProcess(process_id, title_id, acid_sac.GetPointer(), acid_sac.GetSize(), aci_sac.GetPointer(), aci_sac.GetSize());
} }
} }

View file

@ -23,7 +23,7 @@
namespace sts::sm { namespace sts::sm {
/* Service definition. */ /* Service definition. */
class ManagerService final : public IServiceObject { class ManagerService final : public sf::IServiceObject {
protected: protected:
/* Command IDs. */ /* Command IDs. */
enum class CommandId { enum class CommandId {
@ -36,19 +36,19 @@ namespace sts::sm {
}; };
private: private:
/* Actual commands. */ /* Actual commands. */
virtual Result RegisterProcess(u64 pid, InBuffer<u8> acid_sac, InBuffer<u8> aci_sac); virtual Result RegisterProcess(os::ProcessId process_id, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac);
virtual Result UnregisterProcess(u64 pid); virtual Result UnregisterProcess(os::ProcessId process_id);
virtual void AtmosphereEndInitDefers(); virtual void AtmosphereEndInitDefers();
virtual void AtmosphereHasMitm(Out<bool> out, ServiceName service); virtual void AtmosphereHasMitm(sf::Out<bool> out, ServiceName service);
virtual Result AtmosphereRegisterProcess(u64 pid, ncm::TitleId tid, InBuffer<u8> acid_sac, InBuffer<u8> aci_sac); virtual Result AtmosphereRegisterProcess(os::ProcessId process_id, ncm::TitleId title_id, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(ManagerService, RegisterProcess), MAKE_SERVICE_COMMAND_META(RegisterProcess),
MAKE_SERVICE_COMMAND_META(ManagerService, UnregisterProcess), MAKE_SERVICE_COMMAND_META(UnregisterProcess),
MAKE_SERVICE_COMMAND_META(ManagerService, AtmosphereEndInitDefers), MAKE_SERVICE_COMMAND_META(AtmosphereEndInitDefers),
MAKE_SERVICE_COMMAND_META(ManagerService, AtmosphereHasMitm), MAKE_SERVICE_COMMAND_META(AtmosphereHasMitm),
MAKE_SERVICE_COMMAND_META(ManagerService, AtmosphereRegisterProcess), MAKE_SERVICE_COMMAND_META(AtmosphereRegisterProcess),
}; };
}; };

View file

@ -22,8 +22,8 @@
namespace sts::sm { namespace sts::sm {
Result UserService::Initialize(PidDescriptor pid) { Result UserService::Initialize(const sf::ClientProcessId &client_process_id) {
this->pid = pid.pid; this->process_id = client_process_id.GetValue();
this->has_initialized = true; this->has_initialized = true;
return ResultSuccess; return ResultSuccess;
} }
@ -35,37 +35,37 @@ namespace sts::sm {
return ResultSuccess; return ResultSuccess;
} }
Result UserService::GetService(Out<MovedHandle> out_h, ServiceName service) { Result UserService::GetService(sf::OutMoveHandle out_h, ServiceName service) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::GetServiceHandle(out_h.GetHandlePointer(), this->pid, service); return impl::GetServiceHandle(out_h.GetHandlePointer(), this->process_id, service);
} }
Result UserService::RegisterService(Out<MovedHandle> out_h, ServiceName service, u32 max_sessions, bool is_light) { Result UserService::RegisterService(sf::OutMoveHandle out_h, ServiceName service, u32 max_sessions, bool is_light) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::RegisterService(out_h.GetHandlePointer(), this->pid, service, max_sessions, is_light); return impl::RegisterService(out_h.GetHandlePointer(), this->process_id, service, max_sessions, is_light);
} }
Result UserService::UnregisterService(ServiceName service) { Result UserService::UnregisterService(ServiceName service) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::UnregisterService(this->pid, service); return impl::UnregisterService(this->process_id, service);
} }
Result UserService::AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, ServiceName service) { Result UserService::AtmosphereInstallMitm(sf::OutMoveHandle srv_h, sf::OutMoveHandle qry_h, ServiceName service) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::InstallMitm(srv_h.GetHandlePointer(), qry_h.GetHandlePointer(), this->pid, service); return impl::InstallMitm(srv_h.GetHandlePointer(), qry_h.GetHandlePointer(), this->process_id, service);
} }
Result UserService::AtmosphereUninstallMitm(ServiceName service) { Result UserService::AtmosphereUninstallMitm(ServiceName service) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::UninstallMitm(this->pid, service); return impl::UninstallMitm(this->process_id, service);
} }
Result UserService::AtmosphereAcknowledgeMitmSession(Out<u64> client_pid, Out<ncm::TitleId> client_tid, Out<MovedHandle> fwd_h, ServiceName service) { Result UserService::AtmosphereAcknowledgeMitmSession(sf::Out<os::ProcessId> client_pid, sf::Out<ncm::TitleId> client_tid, sf::OutMoveHandle fwd_h, ServiceName service) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::AcknowledgeMitmSession(client_pid.GetPointer(), client_tid.GetPointer(), fwd_h.GetHandlePointer(), this->pid, service); return impl::AcknowledgeMitmSession(client_pid.GetPointer(), client_tid.GetPointer(), fwd_h.GetHandlePointer(), this->process_id, service);
} }
Result UserService::AtmosphereHasMitm(Out<bool> out, ServiceName service) { Result UserService::AtmosphereHasMitm(sf::Out<bool> out, ServiceName service) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::HasMitm(out.GetPointer(), service); return impl::HasMitm(out.GetPointer(), service);
} }
@ -77,11 +77,11 @@ namespace sts::sm {
Result UserService::AtmosphereDeclareFutureMitm(ServiceName service) { Result UserService::AtmosphereDeclareFutureMitm(ServiceName service) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::DeclareFutureMitm(this->pid, service); return impl::DeclareFutureMitm(this->process_id, service);
} }
Result UserService::AtmosphereHasService(Out<bool> out, ServiceName service) { Result UserService::AtmosphereHasService(sf::Out<bool> out, ServiceName service) {
R_TRY(this->EnsureInitialized()); R_TRY(this->EnsureInitialized());
return impl::HasService(out.GetPointer(), service); return impl::HasService(out.GetPointer(), service);
} }

View file

@ -23,7 +23,7 @@
namespace sts::sm { namespace sts::sm {
/* Service definition. */ /* Service definition. */
class UserService final : public IServiceObject { class UserService final : public sf::IServiceObject {
protected: protected:
/* Command IDs. */ /* Command IDs. */
enum class CommandId { enum class CommandId {
@ -44,43 +44,43 @@ namespace sts::sm {
AtmosphereWaitService = 65101, AtmosphereWaitService = 65101,
}; };
private: private:
u64 pid = InvalidProcessId; os::ProcessId process_id = os::InvalidProcessId;
bool has_initialized = false; bool has_initialized = false;
private: private:
Result EnsureInitialized(); Result EnsureInitialized();
public: public:
/* Official commands. */ /* Official commands. */
virtual Result Initialize(PidDescriptor pid); virtual Result Initialize(const sf::ClientProcessId &client_process_id);
virtual Result GetService(Out<MovedHandle> out_h, ServiceName service); virtual Result GetService(sf::OutMoveHandle out_h, ServiceName service);
virtual Result RegisterService(Out<MovedHandle> out_h, ServiceName service, u32 max_sessions, bool is_light); virtual Result RegisterService(sf::OutMoveHandle out_h, ServiceName service, u32 max_sessions, bool is_light);
virtual Result UnregisterService(ServiceName service); virtual Result UnregisterService(ServiceName service);
/* Atmosphere commands. */ /* Atmosphere commands. */
virtual Result AtmosphereInstallMitm(Out<MovedHandle> srv_h, Out<MovedHandle> qry_h, ServiceName service); virtual Result AtmosphereInstallMitm(sf::OutMoveHandle srv_h, sf::OutMoveHandle qry_h, ServiceName service);
virtual Result AtmosphereUninstallMitm(ServiceName service); virtual Result AtmosphereUninstallMitm(ServiceName service);
virtual Result AtmosphereAcknowledgeMitmSession(Out<u64> client_pid, Out<ncm::TitleId> client_tid, Out<MovedHandle> fwd_h, ServiceName service); virtual Result AtmosphereAcknowledgeMitmSession(sf::Out<os::ProcessId> client_pid, sf::Out<ncm::TitleId> client_tid, sf::OutMoveHandle fwd_h, ServiceName service);
virtual Result AtmosphereHasMitm(Out<bool> out, ServiceName service); virtual Result AtmosphereHasMitm(sf::Out<bool> out, ServiceName service);
virtual Result AtmosphereWaitMitm(ServiceName service); virtual Result AtmosphereWaitMitm(ServiceName service);
virtual Result AtmosphereDeclareFutureMitm(ServiceName service); virtual Result AtmosphereDeclareFutureMitm(ServiceName service);
virtual Result AtmosphereHasService(Out<bool> out, ServiceName service); virtual Result AtmosphereHasService(sf::Out<bool> out, ServiceName service);
virtual Result AtmosphereWaitService(ServiceName service); virtual Result AtmosphereWaitService(ServiceName service);
public: public:
DEFINE_SERVICE_DISPATCH_TABLE { DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(UserService, Initialize), MAKE_SERVICE_COMMAND_META(Initialize),
MAKE_SERVICE_COMMAND_META(UserService, GetService), MAKE_SERVICE_COMMAND_META(GetService),
MAKE_SERVICE_COMMAND_META(UserService, RegisterService), MAKE_SERVICE_COMMAND_META(RegisterService),
MAKE_SERVICE_COMMAND_META(UserService, UnregisterService), MAKE_SERVICE_COMMAND_META(UnregisterService),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereInstallMitm), MAKE_SERVICE_COMMAND_META(AtmosphereInstallMitm),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereUninstallMitm), MAKE_SERVICE_COMMAND_META(AtmosphereUninstallMitm),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereAcknowledgeMitmSession), MAKE_SERVICE_COMMAND_META(AtmosphereAcknowledgeMitmSession),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereHasMitm), MAKE_SERVICE_COMMAND_META(AtmosphereHasMitm),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereWaitMitm), MAKE_SERVICE_COMMAND_META(AtmosphereWaitMitm),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereDeclareFutureMitm), MAKE_SERVICE_COMMAND_META(AtmosphereDeclareFutureMitm),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereHasService), MAKE_SERVICE_COMMAND_META(AtmosphereHasService),
MAKE_SERVICE_COMMAND_META(UserService, AtmosphereWaitService), MAKE_SERVICE_COMMAND_META(AtmosphereWaitService),
}; };
}; };