diff --git a/stratosphere/fs_mitm/source/fsmitm_main.cpp b/stratosphere/fs_mitm/source/fsmitm_main.cpp index fcc8653b9..4f714f177 100644 --- a/stratosphere/fs_mitm/source/fsmitm_main.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_main.cpp @@ -10,6 +10,7 @@ #include "mitm_server.hpp" #include "fsmitm_service.hpp" +#include "fsmitm_worker.hpp" extern "C" { extern u32 __start__; @@ -85,8 +86,15 @@ void __appExit(void) { int main(int argc, char **argv) { + Thread worker_thread = {0}; consoleDebugInit(debugDevice_SVC); + if (R_FAILED(threadCreate(&worker_thread, &FsMitmWorker::Main, NULL, 0x8000, 45, 0))) { + /* TODO: Panic. */ + } + if (R_FAILED(threadStart(&worker_thread))) { + /* TODO: Panic. */ + } /* TODO: What's a good timeout value to use here? */ WaitableManager *server_manager = new WaitableManager(U64_MAX); diff --git a/stratosphere/fs_mitm/source/fsmitm_service.cpp b/stratosphere/fs_mitm/source/fsmitm_service.cpp index b01d8ddf3..2f23765ef 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.cpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.cpp @@ -3,6 +3,13 @@ Result FsMitMService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result rc = 0xF601; + switch (cmd_id) { + case FspSrv_Cmd_SetCurrentProcess: + if (!this->has_initialized && r.HasPid) { + this->process_id = r.Pid; + } + break; + } return rc; } @@ -13,7 +20,17 @@ Result FsMitMService::postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cm } *resp = (decltype(resp))r.Raw; Result rc = (Result)resp->result; - /* TODO: Hook here, if needed. */ + switch (cmd_id) { + case FspSrv_Cmd_SetCurrentProcess: + if (R_SUCCEEDED(rc)) { + this->has_initialized = true; + if (R_FAILED(pminfoInitialize()) || R_FAILED(pminfoGetTitleId(&this->title_id, this->process_id))) { + fatalSimple(0xCAFE << 8 | 0xFD); + } + pminfoExit(); + } + break; + } return rc; } diff --git a/stratosphere/fs_mitm/source/fsmitm_service.hpp b/stratosphere/fs_mitm/source/fsmitm_service.hpp index 3ddd8c981..e8ea369b9 100644 --- a/stratosphere/fs_mitm/source/fsmitm_service.hpp +++ b/stratosphere/fs_mitm/source/fsmitm_service.hpp @@ -3,7 +3,15 @@ #include #include "imitmserviceobject.hpp" -class FsMitMService : public IMitMServiceObject { +enum FspSrvCmd { + FspSrv_Cmd_SetCurrentProcess = 1, +}; + +class FsMitMService : public IMitMServiceObject { + private: + bool has_initialized; + u64 process_id; + u64 title_id; public: virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); virtual Result postprocess(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); diff --git a/stratosphere/fs_mitm/source/fsmitm_worker.cpp b/stratosphere/fs_mitm/source/fsmitm_worker.cpp new file mode 100644 index 000000000..0dd4cdb2a --- /dev/null +++ b/stratosphere/fs_mitm/source/fsmitm_worker.cpp @@ -0,0 +1,37 @@ +#include +#include +#include "fsmitm_worker.hpp" + +static SystemEvent *g_new_waitable_event = NULL; +static ChildWaitableHolder *g_child_holder = NULL; + +static HosMutex g_new_waitable_mutex; +static IWaitable *g_new_waitable = NULL; + +Result FsMitmWorker::AddWaitableInternal(Handle *handles, size_t num_handles, u64 timeout) { + svcClearEvent(handles[0]); + g_child_holder->add_child(g_new_waitable); + return 0; +} + +void FsMitmWorker::AddWaitable(IWaitable *waitable) { + g_new_waitable_mutex.Lock(); + g_new_waitable = waitable; + g_new_waitable_event->signal_event(); + g_new_waitable_mutex.Unlock(); +} + +void FsMitmWorker::Main(void *arg) { + /* Initialize waitable event. */ + g_new_waitable_event = new SystemEvent(&FsMitmWorker::AddWaitableInternal); + g_child_holder = new ChildWaitableHolder(); + + /* Make a new waitable manager. */ + WaitableManager *worker_waiter = new WaitableManager(U64_MAX); + worker_waiter->add_waitable(g_new_waitable_event); + + /* Service processes. */ + worker_waiter->process(); + + delete worker_waiter; +} diff --git a/stratosphere/fs_mitm/source/fsmitm_worker.hpp b/stratosphere/fs_mitm/source/fsmitm_worker.hpp new file mode 100644 index 000000000..4f7a48d6f --- /dev/null +++ b/stratosphere/fs_mitm/source/fsmitm_worker.hpp @@ -0,0 +1,11 @@ +#pragma once +#include +#include + +class FsMitmWorker { + private: + static Result AddWaitableInternal(Handle *handles, size_t num_handles, u64 timeout); + public: + static void Main(void *arg); + static void AddWaitable(IWaitable *waitable); +}; \ No newline at end of file diff --git a/stratosphere/libstratosphere/include/stratosphere.hpp b/stratosphere/libstratosphere/include/stratosphere.hpp index 0b6274400..67b73b833 100644 --- a/stratosphere/libstratosphere/include/stratosphere.hpp +++ b/stratosphere/libstratosphere/include/stratosphere.hpp @@ -7,6 +7,7 @@ #include "stratosphere/serviceserver.hpp" #include "stratosphere/managedportserver.hpp" #include "stratosphere/existingportserver.hpp" +#include "stratosphere/childholder.hpp" #include "stratosphere/ievent.hpp" #include "stratosphere/systemevent.hpp" diff --git a/stratosphere/libstratosphere/include/stratosphere/childholder.hpp b/stratosphere/libstratosphere/include/stratosphere/childholder.hpp new file mode 100644 index 000000000..428ccef69 --- /dev/null +++ b/stratosphere/libstratosphere/include/stratosphere/childholder.hpp @@ -0,0 +1,76 @@ +#pragma once +#include +#include + +#include "iwaitable.hpp" + +class ChildWaitableHolder : public IWaitable { + protected: + std::vector children; + + public: + /* Implicit constructor. */ + + void add_child(IWaitable *child) { + this->children.push_back(child); + } + + virtual ~ChildWaitableHolder() { + for (unsigned int i = 0; i < this->children.size(); i++) { + delete this->children[i]; + } + this->children.clear(); + } + + /* IWaitable */ + virtual unsigned int get_num_waitables() { + unsigned int n = 0; + for (unsigned int i = 0; i < this->children.size(); i++) { + if (this->children[i]) { + n += this->children[i]->get_num_waitables(); + } + } + return n; + } + + virtual void get_waitables(IWaitable **dst) { + unsigned int n = 0; + for (unsigned int i = 0; i < this->children.size(); i++) { + if (this->children[i]) { + this->children[i]->get_waitables(&dst[n]); + n += this->children[i]->get_num_waitables(); + } + } + } + + virtual void delete_child(IWaitable *child) { + unsigned int i; + for (i = 0; i < this->children.size(); i++) { + if (this->children[i] == child) { + break; + } + } + + if (i == this->children.size()) { + /* TODO: Panic, because this isn't our child. */ + } else { + delete this->children[i]; + this->children.erase(this->children.begin() + i); + } + } + + virtual Handle get_handle() { + /* We don't have a handle. */ + return 0; + } + + + virtual void handle_deferred() { + /* TODO: Panic, because we can never defer a server. */ + } + + virtual Result handle_signaled(u64 timeout) { + /* TODO: Panic, because we can never be signalled. */ + return 0; + } +}; \ No newline at end of file