diff --git a/Ipc.cpp b/Ipc.cpp index ea786bf..144e860 100644 --- a/Ipc.cpp +++ b/Ipc.cpp @@ -76,18 +76,6 @@ void IpcMessage::SetErrorCode(uint32_t error_code) { } } -uint32_t SmService::Dispatch(IpcMessage *req, IpcMessage *resp) { - -} -uint32_t SmService::GetService(std::string name, IpcService *service) { - if (IPC::services.find(name) == IPC::services.end()) { - ns_print("Unknown service name %s\n", name.c_str()); - return 0xC15; //error code - } - *service = IPC::services[name]; - return 0; -} - namespace IPC { static uint32_t handle_id; @@ -126,13 +114,48 @@ uint32_t ProcMessage(IpcService *handler, uint8_t buf[]) { switch(req.type) { case 2: //Close + resp.GenBuf(0, 0, 0); + resp.SetErrorCode(0); + ret = 0x25a0b; break; case 4: //Normal ret = handler->Dispatch(&req, &resp); break; case 5: //Control - break; - + switch(req.cmd_id) { + case 0: // ConvertSessionToDomain + debug_print("IPC: ConvertSessionToDomain\n"); + resp.GenBuf(0, 0, 4); + is_domainobj = true; + *resp.GetDataPointer(8) = handler->handle; + resp.SetErrorCode(0); + break; + case 2: // DuplicateSession + debug_print("DuplicateSession\n"); + is_domainobj = false; + resp.GenBuf(1, 0, 0); + resp.SetMove(0, NewHandle(handler)); + resp.SetErrorCode(0); + ret = 0; + break; + case 3: // QueryPointerBufferSize + debug_print("QueryPointerBufferSize\n"); + resp.GenBuf(0, 0, 4); + *resp.GetDataPointer(8) = 0x500; + resp.SetErrorCode(0); + ret = 0; + break; + case 4: // DuplicateSession + debug_print("DuplicateSessionEx\n"); + is_domainobj = false; + resp.GenBuf(1, 0, 0); + resp.SetMove(0, NewHandle(handler)); + resp.SetErrorCode(0); + ret = 0; + break; + default: + ns_abort("Unknown cmdId to control %u\n", req.cmd_id); + } } return 0; } diff --git a/Makefile b/Makefile index 7072938..8f83b46 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CXX := g++ -SRC_FILES := $(wildcard *.cpp ARMv8/*.cpp) +SRC_FILES := $(wildcard *.cpp ARMv8/*.cpp Service/*.cpp) OBJ_FILES := $(SRC_FILES:.cpp=.o) CXX_FLAGS := -std=gnu++1z -Iinclude LD_FLAGS := -llz4 -lpthread diff --git a/Service/Sm.cpp b/Service/Sm.cpp new file mode 100644 index 0000000..67da461 --- /dev/null +++ b/Service/Sm.cpp @@ -0,0 +1,59 @@ +/* nsemu - LGPL - Copyright 2018 rkx1209 */ +#include "Nsemu.hpp" +uint32_t SmService::Initialize() { + return 0; +} + +uint32_t SmService::Dispatch(IpcMessage *req, IpcMessage *resp) { + switch(req->cmd_id) { + case 0: { + resp->GenBuf(0, 0, 0); + debug_print("IPC message to SmService::Dispatch\n"); + resp->error_code = Initialize(); + return 0; + } + case 1: { + resp->GenBuf(1, 0, 0); + IpcService service; + std::string name = ARMv8::ReadString(req->GetDataPointer(8)); + debug_print("IPC message to SmService::GetService: ServiceName name = %s\n", name.c_str()); + resp->error_code = GetService(name, &service); + if(!resp->error_code) + resp->SetMove(0, IPC::NewHandle(&service)); + return 0; + } + case 2: { + resp->GenBuf(1, 0, 0); + IpcService service; + std::string name = ARMv8::ReadString(req->GetDataPointer(8)); + debug_print("[TODO] IPC message to SmService::RegisterService: ServiceName name = %s\n", name.c_str()); + /* TODO: Currently hombrew applications with libtransistor doesn't use RegisterService message. */ + resp->error_code = RegisterService(name, &service); + if(!resp->error_code) + resp->SetMove(0, IPC::NewHandle(&service)); + return 0; + } + case 3: { + resp->GenBuf(0, 0, 0); + std::string name = ARMv8::ReadString(req->GetDataPointer(8)); + debug_print("[TODO] IPC message to SmService::UnregisterService: ServiceName name = %s\n", name.c_str()); + /* TODO: */ + //resp.error_code = UnregisterService(req.GetDataPointer(8)); + return 0; + } + default: + ns_abort("Unknown message cmdId %u to interface SmService", req->cmd_id); + } +} +uint32_t SmService::GetService(std::string name, IpcService *service) { + if (IPC::services.find(name) == IPC::services.end()) { + ns_print("Unknown service name %s\n", name.c_str()); + return 0xC15; //error code + } + *service = IPC::services[name]; + return 0; +} + +uint32_t SmService::RegisterService(std::string name, IpcService *service) { + return 0; +} diff --git a/include/Ipc.hpp b/include/Ipc.hpp index 8955921..4388f73 100644 --- a/include/Ipc.hpp +++ b/include/Ipc.hpp @@ -3,7 +3,7 @@ class IpcMessage { public: - IpcMessage() {} + IpcMessage() : raw_ptr(nullptr) {} IpcMessage(uint8_t *buf, bool is_domainobj) : raw_ptr(buf), is_domainobj(is_domainobj) {} /* IPC command structure */ unsigned int type; @@ -22,12 +22,28 @@ public: return *((T *) (raw_ptr + payload_off + 8 + offset)); } template - T getDataPointer(uint offset) { + T GetDataPointer(uint offset) { return (T) (raw_ptr + payload_off + 8 + offset); } void GenBuf(unsigned int _move_cnt, unsigned int _copy_cnt, unsigned int _data_bytes); void SetErrorCode(uint32_t error_code); void ParseMessage(); + void SetMove(int offset, uint32_t handler) { + if (!raw_ptr) { + return; + } + if(is_domainobj) + raw_ptr[(payload_off >> 2) + 4 + offset] = handler; + else + raw_ptr[3 + copy_cnt + offset] = handler; + } + void SetCopy(int offset, uint32_t handler) { + if (!raw_ptr) { + return; + } + uint32_t *buf = (uint32_t *) raw_ptr; + buf[3 + offset] = handler; + } private: unsigned int copy_off, move_off, desc_off, raw_off, payload_off, realdata_off; uint8_t *raw_ptr; @@ -36,14 +52,17 @@ private: class IpcService { public: - IpcService() {} + IpcService() : handle(0xf000){} virtual uint32_t Dispatch(IpcMessage *req, IpcMessage *resp) { return 0; } + int handle; }; class SmService : public IpcService { public: SmService() { } + uint32_t Initialize(); uint32_t GetService(std::string name, IpcService *service); + uint32_t RegisterService(std::string name, IpcService *service); uint32_t Dispatch(IpcMessage *req, IpcMessage *resp); };