mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
Stratosphere: Fill out Loader main(), fix template classes.
This commit is contained in:
parent
ee1488a1ed
commit
321286ceab
9 changed files with 136 additions and 151 deletions
|
@ -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;
|
||||||
};
|
};
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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++;
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
Loading…
Reference in a new issue