Add Initial support of SMService emulation

This commit is contained in:
rkx1209 2018-04-09 18:23:01 +09:00
parent 423fa2c8b8
commit 99398de2d5
4 changed files with 119 additions and 18 deletions

51
Ipc.cpp
View file

@ -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<uint32_t*>(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<uint32_t *>(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;
}

View file

@ -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

59
Service/Sm.cpp Normal file
View file

@ -0,0 +1,59 @@
/* nsemu - LGPL - Copyright 2018 rkx1209<rkx1209dev@gmail.com> */
#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<uint64_t >(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<uint64_t>(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<uint64_t>(8));
debug_print("[TODO] IPC message to SmService::UnregisterService: ServiceName name = %s\n", name.c_str());
/* TODO: */
//resp.error_code = UnregisterService(req.GetDataPointer<ServiceName>(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;
}

View file

@ -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<typename T>
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);
};