Stratosphere: Fill out Loader main(), fix template classes.

This commit is contained in:
Michael Scire 2018-04-18 12:10:45 -06:00
parent ee1488a1ed
commit 321286ceab
9 changed files with 136 additions and 151 deletions

View file

@ -3,5 +3,6 @@
class IServiceObject { class IServiceObject {
public: public:
virtual ~IServiceObject() { }
virtual Result dispatch(IpcParsedCommand *r, u32 *cmd_buf, u32 cmd_id, u32 *in_rawdata, u32 in_rawdata_size, u32 *out_rawdata, u32 *out_raw_data_count) = 0; virtual Result dispatch(IpcParsedCommand *r, u32 *cmd_buf, u32 cmd_id, u32 *in_rawdata, u32 in_rawdata_size, u32 *out_rawdata, u32 *out_raw_data_count) = 0;
}; };

View file

@ -6,7 +6,8 @@ class IWaitable {
u64 wait_priority = 0; u64 wait_priority = 0;
IWaitable *parent_waitable; IWaitable *parent_waitable;
public: public:
virtual ~IWaitable(); virtual ~IWaitable() { }
virtual unsigned int get_num_waitables() = 0; virtual unsigned int get_num_waitables() = 0;
virtual void get_waitables(IWaitable **dst) = 0; virtual void get_waitables(IWaitable **dst) = 0;
virtual void delete_child(IWaitable *child) = 0; virtual void delete_child(IWaitable *child) = 0;

View file

@ -9,7 +9,7 @@ Result DebugMonitorService::dispatch(IpcParsedCommand *r, u32 *cmd_buf, u32 cmd_
/* TODO: Prepare SFCO. */ /* TODO: Prepare SFCO. */
switch ((DebugMonitorServiceCmd)cmd_id) { switch ((DebugMonitorServiceCmd)cmd_id) {
case Cmd_AddTitleToLaunchQueue: case Dmnt_Cmd_AddTitleToLaunchQueue:
/* Validate arguments. */ /* Validate arguments. */
if (in_rawdata_size < 0x10 || r->HasPid || r->NumHandles != 0 || r->NumBuffers != 0 || r->NumStatics != 1) { if (in_rawdata_size < 0x10 || r->HasPid || r->NumHandles != 0 || r->NumBuffers != 0 || r->NumStatics != 1) {
break; break;
@ -20,7 +20,7 @@ Result DebugMonitorService::dispatch(IpcParsedCommand *r, u32 *cmd_buf, u32 cmd_
*out_raw_data_count = 0; *out_raw_data_count = 0;
break; break;
case Cmd_ClearLaunchQueue: case Dmnt_Cmd_ClearLaunchQueue:
if (r->HasPid || r->NumHandles != 0 || r->NumBuffers != 0 || r->NumStatics != 0) { if (r->HasPid || r->NumHandles != 0 || r->NumBuffers != 0 || r->NumStatics != 0) {
break; break;
} }
@ -29,7 +29,7 @@ Result DebugMonitorService::dispatch(IpcParsedCommand *r, u32 *cmd_buf, u32 cmd_
*out_raw_data_count = 0; *out_raw_data_count = 0;
break; break;
case Cmd_GetNsoInfo: case Dmnt_Cmd_GetNsoInfo:
if (in_rawdata_size < 0x8 || r->HasPid || r->NumHandles != 0 || r->NumBuffers != 0 || r->NumStatics != 1) { if (in_rawdata_size < 0x8 || r->HasPid || r->NumHandles != 0 || r->NumBuffers != 0 || r->NumStatics != 1) {
break; break;
} }

View file

@ -4,9 +4,9 @@
#include "iserviceobject.hpp" #include "iserviceobject.hpp"
enum DebugMonitorServiceCmd { enum DebugMonitorServiceCmd {
Cmd_AddTitleToLaunchQueue = 0, Dmnt_Cmd_AddTitleToLaunchQueue = 0,
Cmd_ClearLaunchQueue = 1, Dmnt_Cmd_ClearLaunchQueue = 1,
Cmd_GetNsoInfo = 2 Dmnt_Cmd_GetNsoInfo = 2
}; };
class DebugMonitorService : IServiceObject { class DebugMonitorService : IServiceObject {

View file

@ -5,6 +5,11 @@
#include <switch.h> #include <switch.h>
#include "waitablemanager.hpp"
#include "serviceserver.hpp"
#include "ldr_debug_monitor.hpp"
#include "ldr_shell.hpp"
extern u32 __start__; extern u32 __start__;
u32 __nx_applet_type = AppletType_None; u32 __nx_applet_type = AppletType_None;
@ -28,6 +33,18 @@ void __libnx_initheap(void)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
/* TODO: What's a good timeout value to use here? */
WaitableManager *server_manager = new WaitableManager(U64_MAX);
/* Add services to manager. */
server_manager->add_waitable(new ServiceServer<ShellService>("ldr:shel", 3));
server_manager->add_waitable(new ServiceServer<DebugMonitorService>("ldr:dmnt", 2));
/* Loop forever, servicing our services. */
server_manager->process();
/* Cleanup. */
delete server_manager;
return 0; return 0;
} }

View file

@ -1,99 +0,0 @@
#include <switch.h>
#include "serviceserver.hpp"
template <typename T>
ServiceServer<T>::ServiceServer(const char *service_name, unsigned int max_s) : max_sessions(max_s) {
if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) {
/* TODO: Panic. */
}
this->sessions = new ServiceSession<T> *[this->max_sessions];
for (unsigned int i = 0; i < this->max_sessions; i++) {
this->sessions[i] = NULL;
}
this->num_sessions = 0;
}
template <typename T>
ServiceServer<T>::~ServiceServer() {
for (unsigned int i = 0; i < this->max_sessions; i++) {
if (this->sessions[i]) {
delete this->sessions[i];
}
delete this->sessions;
}
if (port_handle) {
svcCloseHandle(port_handle);
}
}
/* IWaitable functions. */
template <typename T>
unsigned int ServiceServer<T>::get_num_waitables() {
unsigned int n = 1;
for (unsigned int i = 0; i < this->max_sessions; i++) {
if (this->sessions[i]) {
n += this->sessions[i]->get_num_waitables();
}
}
return n;
}
template <typename T>
void ServiceServer<T>::get_waitables(IWaitable **dst) {
dst[0] = this;
unsigned int n = 0;
for (unsigned int i = 0; i < this->max_sessions; i++) {
if (this->sessions[i]) {
this->sessions[i]->get_waitables(&dst[1 + n]);
n += this->sessions[i]->get_num_waitables();
}
}
}
template <typename T>
void ServiceSession<T>::delete_child(IWaitable *child) {
unsigned int i;
for (i = 0; i < this->max_sessions; i++) {
if (this->sessions[i] == child) {
break;
}
}
if (i == this->max_sessions) {
/* TODO: Panic, because this isn't our child. */
} else {
delete this->sessions[i];
this->sessions[i] = NULL;
this->num_sessions--;
}
}
template <typename T>
Handle ServiceServer<T>::get_handle() {
return this->port_handle;
}
template <typename T>
Result ServiceServer<T>::handle_signaled() {
/* If this server's port was signaled, accept a new session. */
Handle session_h;
svcAcceptSession(&session_h, this->port_handle);
if (this->num_sessions >= this->max_sessions) {
svcCloseHandle(session_h);
return 0x10601;
}
unsigned int i;
for (i = 0; i < this->max_sessions; i++) {
if (this->sessions[i] = NULL) {
break;
}
}
this->sessions[i] = new ServiceSession<T>(this, session_h, 0);
this->num_sessions++;
}

View file

@ -10,7 +10,7 @@ template <typename T>
class ServiceSession; class ServiceSession;
template <typename T> template <typename T>
class ServiceServer : IWaitable { class ServiceServer : public IWaitable {
static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject");
Handle port_handle; Handle port_handle;
@ -19,13 +19,93 @@ class ServiceServer : IWaitable {
ServiceSession<T> **sessions; ServiceSession<T> **sessions;
public: public:
ServiceServer(const char *service_name, unsigned int max_s); ServiceServer(const char *service_name, unsigned int max_s) {
virtual ~ServiceServer(); if (R_FAILED(smRegisterService(&this->port_handle, service_name, false, this->max_sessions))) {
/* TODO: Panic. */
}
this->sessions = new ServiceSession<T> *[this->max_sessions];
for (unsigned int i = 0; i < this->max_sessions; i++) {
this->sessions[i] = NULL;
}
this->num_sessions = 0;
}
virtual ~ServiceServer() {
for (unsigned int i = 0; i < this->max_sessions; i++) {
if (this->sessions[i]) {
delete this->sessions[i];
}
delete this->sessions;
}
if (port_handle) {
svcCloseHandle(port_handle);
}
}
/* IWaitable */ /* IWaitable */
virtual unsigned int get_num_waitables(); virtual unsigned int get_num_waitables() {
virtual void get_waitables(IWaitable **dst); unsigned int n = 1;
virtual void delete_child(IWaitable *child); for (unsigned int i = 0; i < this->max_sessions; i++) {
virtual Handle get_handle(); if (this->sessions[i]) {
virtual Result handle_signaled(); n += this->sessions[i]->get_num_waitables();
}
}
return n;
}
virtual void get_waitables(IWaitable **dst) {
dst[0] = this;
unsigned int n = 0;
for (unsigned int i = 0; i < this->max_sessions; i++) {
if (this->sessions[i]) {
this->sessions[i]->get_waitables(&dst[1 + n]);
n += this->sessions[i]->get_num_waitables();
}
}
}
virtual void delete_child(IWaitable *child) {
unsigned int i;
for (i = 0; i < this->max_sessions; i++) {
if (this->sessions[i] == child) {
break;
}
}
if (i == this->max_sessions) {
/* TODO: Panic, because this isn't our child. */
} else {
delete this->sessions[i];
this->sessions[i] = NULL;
this->num_sessions--;
}
}
virtual Handle get_handle() {
return this->port_handle;
}
virtual Result handle_signaled() {
/* If this server's port was signaled, accept a new session. */
Handle session_h;
svcAcceptSession(&session_h, this->port_handle);
if (this->num_sessions >= this->max_sessions) {
svcCloseHandle(session_h);
return 0x10601;
}
unsigned int i;
for (i = 0; i < this->max_sessions; i++) {
if (this->sessions[i] == NULL) {
break;
}
}
this->sessions[i] = new ServiceSession<T>(this, session_h, 0);
this->num_sessions++;
return 0;
}
}; };

View file

@ -1,30 +0,0 @@
#include <switch.h>
#include "servicesession.hpp"
/* IWaitable functions. */
template <typename T>
unsigned int ServiceSession<T>::get_num_waitables() {
return 1;
}
template <typename T>
void ServiceSession<T>::get_waitables(IWaitable **dst) {
dst[0] = this;
}
template <typename T>
void ServiceSession<T>::delete_child(IWaitable *child) {
/* TODO: Panic, because we can never have any children. */
}
template <typename T>
Handle ServiceSession<T>::get_handle() {
return this->server_handle;
}
template <typename T>
Result ServiceSession<T>::handle_signaled() {
/* TODO */
return 0;
}

View file

@ -10,7 +10,7 @@ template <typename T>
class ServiceServer; class ServiceServer;
template <typename T> template <typename T>
class ServiceSession : IWaitable { class ServiceSession : public IWaitable {
static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject"); static_assert(std::is_base_of<IServiceObject, T>::value, "Service Objects must derive from IServiceObject");
T *service_object; T *service_object;
@ -18,7 +18,7 @@ class ServiceSession : IWaitable {
Handle server_handle; Handle server_handle;
Handle client_handle; Handle client_handle;
public: public:
ServiceSession(ServiceServer<T> *s, Handle s_h, Handle c_h) : server(s), server_handle(s_h), client_handle(c_h) { ServiceSession<T>(ServiceServer<T> *s, Handle s_h, Handle c_h) : server(s), server_handle(s_h), client_handle(c_h) {
this->service_object = new T(); this->service_object = new T();
} }
@ -37,9 +37,24 @@ class ServiceSession : IWaitable {
Handle get_client_handle() { return this->client_handle; } Handle get_client_handle() { return this->client_handle; }
/* IWaitable */ /* IWaitable */
virtual unsigned int get_num_waitables(); virtual unsigned int get_num_waitables() {
virtual void get_waitables(IWaitable **dst); return 1;
virtual void delete_child(IWaitable *child); }
virtual Handle get_handle();
virtual Result handle_signaled(); virtual void get_waitables(IWaitable **dst) {
dst[0] = this;
}
virtual void delete_child(IWaitable *child) {
/* TODO: Panic, because we can never have any children. */
}
virtual Handle get_handle() {
return this->server_handle;
}
virtual Result handle_signaled() {
/* TODO */
return 0;
}
}; };