Introducing ipc domains, bsd stuff

This commit is contained in:
plutoo 2017-09-15 00:18:52 +02:00
parent fb1d6f4d5c
commit 003e300e83
4 changed files with 289 additions and 17 deletions

View File

@ -46,6 +46,11 @@ typedef struct {
u32 Addr;
} IpcStaticSendDescriptor;
typedef struct {
u32 Addr;
u32 Packed;
} IpcStaticRecvDescriptor;
static inline void ipcAddSendBuffer(IpcCommand* cmd, void* buffer, size_t size, u8 flags) {
size_t off = cmd->NumSend;
cmd->Buffers[off] = buffer;
@ -103,8 +108,17 @@ static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) {
size_t i;
*buf++ = 4 | (cmd->NumStaticIn << 16) | (cmd->NumSend << 20) | (cmd->NumRecv << 24) | (cmd->NumTransfer << 28);
u32* fill_in_size_later = buf;
if (cmd->NumStaticOut > 0) {
*buf = (cmd->NumStaticOut + 2) << 10;
}
else {
*buf = 0;
}
if (cmd->SendPid || cmd->NumHandlesCopy > 0 || cmd->NumHandlesMove > 0) {
*buf++ = (sizeof_raw/4) | 0x80000000;
*buf++ |= 0x80000000;
*buf++ = (!!cmd->SendPid) | (cmd->NumHandlesCopy << 1) | (cmd->NumHandlesMove << 5);
if (cmd->SendPid)
@ -114,7 +128,7 @@ static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) {
*buf++ = cmd->Handles[i];
}
else {
*buf++ = sizeof_raw/4;
buf++;
}
for (i=0; i<cmd->NumStaticIn; i++, buf+=2) {
@ -136,14 +150,32 @@ static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) {
(((ptr >> 32) & 15) << 28) | ((ptr >> 36) << 2);
}
// todo: More
return (void*) ((((uintptr_t)buf) + 15) &~ 15);
u32 padding = ((16 - (((uintptr_t) buf) & 15)) & 15) / 4;
u32* raw = (u32*) (buf + padding);
size_t raw_size = (sizeof_raw/4) + 4;
raw_size += ((cmd->NumStaticOut*2) + 3)/4; // todo: these contain u16 lengths for StaticOuts
buf += raw_size;
*fill_in_size_later |= raw_size;
for (i=0; i<cmd->NumStaticOut; i++, buf+=2) {
IpcStaticRecvDescriptor* desc = (IpcStaticRecvDescriptor*) buf;
size_t off = cmd->NumStaticIn + i;
uintptr_t ptr = (uintptr_t) cmd->Statics[off];
desc->Addr = ptr;
desc->Packed = (ptr >> 32) | (cmd->StaticSizes[off] << 16);
}
return (void*) raw;
}
static inline Result ipcDispatch(Handle session) {
return svcSendSyncRequest(session);
}
// Response parsing
typedef struct {
bool HasPid;
u64 Pid;
@ -211,3 +243,67 @@ static inline Result ipcParseResponse(IpcCommandResponse* r) {
r->NumBuffers = num_bufs;
return 0;
}
// Domain shit
static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_out) {
u32* buf = armGetTls();
buf[0] = 5;
buf[1] = 8;
buf[4] = SFCI_MAGIC;
buf[5] = 0;
buf[6] = 0;
buf[7] = 0;
Result rc = ipcDispatch(session);
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
struct {
u64 magic;
u64 result;
u32 object_id;
} *raw = r.Raw;
rc = raw->result;
if (R_SUCCEEDED(rc)) {
*object_id_out = raw->object_id;
}
}
return rc;
}
typedef struct {
u8 Type;
u8 Pad0;
u16 Length;
u32 ObjectId;
u32 Pad1[2];
} DomainMessageHeader;
static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, size_t object_id) {
void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader));
DomainMessageHeader* hdr = (DomainMessageHeader*) raw;
hdr->Type = 1;
hdr->Length = sizeof_raw;
hdr->ObjectId = object_id;
hdr->Pad0 = hdr->Pad1[0] = hdr->Pad1[1] = 0;
return (void*)(((uintptr_t) raw) + sizeof(DomainMessageHeader));
}
static inline Result ipcParseResponseForDomain(IpcCommandResponse* r) {
Result rc = ipcParseResponse(r);
if (R_SUCCEEDED(rc)) {
r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader));
}
return rc;
}

View File

@ -4,6 +4,9 @@ int bsdConnect(int sockfd, void* addr, u32 addrlen);
int bsdSocket(int domain, int type, int protocol);
int bsdBind(int sockfd, void* addr, u32 addrlen);
int bsdListen(int sockfd, int backlog);
int bsdSend(int sockfd, void* buffer, size_t length, int flags);
int bsdRecv(int sockfd, void* buffer, size_t length, int flags);
int bsdWrite(int sockfd, void* buffer, size_t length);
#define BSD_AF_INET 2
#define BSD_AF_INET6 10
@ -11,6 +14,8 @@ int bsdListen(int sockfd, int backlog);
#define BSD_SOCK_STREAM 1
#define BSD_SOCK_DGRAM 2
#define BSD_MSG_RECV_ALL 0x40
struct bsd_sockaddr_in {
u8 sin_len;
u8 sin_family;

View File

@ -32,7 +32,7 @@ void heapInit(void* base, size_t size) {
void heapSetup() {
// Called by crt0.
#define HEAP_SIZE 0x20000
#define HEAP_SIZE 0x2000000
static u8 g_Heap[HEAP_SIZE];
heapInit(&g_Heap[0], HEAP_SIZE);
}

View File

@ -2,8 +2,11 @@
#include <switch.h>
static Handle g_bsdHandle = -1;
static u32 g_bsdObjectId = -1;
static int g_Errno = 0;
#define EPIPE 32
Result bsdInitialize(TransferMemory* tmem) {
Result rc = smGetService(&g_bsdHandle, "bsd:s");
@ -29,10 +32,10 @@ Result bsdInitialize(TransferMemory* tmem) {
raw->magic = SFCI_MAGIC;
raw->cmd_id = 0;
raw->unk0[0] = 0;
raw->unk0[1] = 0;
raw->unk0[2] = 0;
raw->unk0[3] = 0;
raw->unk0[0] = 0x4000;
raw->unk0[1] = 0x4000;
raw->unk0[2] = 0x4000;
raw->unk0[3] = 0x4000;
raw->unk0[4] = 0;
raw->tmem_sz = tmem->Size;
@ -48,9 +51,17 @@ Result bsdInitialize(TransferMemory* tmem) {
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
rc = ipcConvertSessionToDomain(g_bsdHandle, &g_bsdObjectId);
}
}
}
if (R_FAILED(rc)) {
g_Errno = EPIPE;
}
return rc;
}
@ -71,7 +82,7 @@ int bsdSocket(int domain, int type, int protocol) {
u32 pad[4];
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), g_bsdObjectId);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 2;
@ -84,7 +95,7 @@ int bsdSocket(int domain, int type, int protocol) {
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
ipcParseResponseForDomain(&r);
struct {
u64 magic;
@ -101,8 +112,109 @@ int bsdSocket(int domain, int type, int protocol) {
}
}
if (R_FAILED(rc)) {
g_Errno = EPIPE;
}
return fd;
}
int bsdRecv(int sockfd, void* buffer, size_t length, int flags) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, buffer, length, 0);
ipcAddRecvStatic(&c, buffer, length, 0);
struct {
u64 magic;
u64 cmd_id;
u32 sockfd;
u32 flags;
} *raw;
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), g_bsdObjectId);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 8;
raw->sockfd = sockfd;
raw->flags = flags;
Result rc = ipcDispatch(g_bsdHandle);
int ret = -1;
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponseForDomain(&r);
struct {
u64 magic;
u64 result;
u32 ret;
u32 errno;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
g_Errno = resp->errno;
ret = resp->ret;
}
}
if (R_FAILED(rc)) {
g_Errno = rc; //EPIPE;
}
return ret;
}
int bsdSend(int sockfd, void* buffer, size_t length, int flags) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, buffer, length, 0);
ipcAddSendStatic(&c, buffer, length, 0);
struct {
u64 magic;
u64 cmd_id;
u32 sockfd;
u32 flags;
} *raw;
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), g_bsdObjectId);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 10;
raw->sockfd = sockfd;
raw->flags = flags;
Result rc = ipcDispatch(g_bsdHandle);
int ret = -1;
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponseForDomain(&r);
struct {
u64 magic;
u64 result;
u32 ret;
u32 errno;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
g_Errno = resp->errno;
ret = resp->ret;
}
}
if (R_FAILED(rc)) {
g_Errno = EPIPE;
}
return ret;
}
int bsdConnect(int sockfd, void* addr, u32 addrlen) {
IpcCommand c;
@ -117,7 +229,7 @@ int bsdConnect(int sockfd, void* addr, u32 addrlen) {
u32 pad[4];
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), g_bsdObjectId);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 14;
@ -128,7 +240,7 @@ int bsdConnect(int sockfd, void* addr, u32 addrlen) {
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
ipcParseResponseForDomain(&r);
struct {
u64 magic;
@ -145,6 +257,10 @@ int bsdConnect(int sockfd, void* addr, u32 addrlen) {
}
}
if (R_FAILED(rc)) {
g_Errno = EPIPE;
}
return fd;
}
@ -160,7 +276,7 @@ int bsdBind(int sockfd, void* addr, u32 addrlen) {
u32 pad[5];
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), g_bsdObjectId);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 13;
@ -170,7 +286,7 @@ int bsdBind(int sockfd, void* addr, u32 addrlen) {
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
ipcParseResponseForDomain(&r);
struct {
u64 magic;
@ -187,6 +303,10 @@ int bsdBind(int sockfd, void* addr, u32 addrlen) {
}
}
if (R_FAILED(rc)) {
g_Errno = EPIPE;
}
return ret;
}
@ -202,7 +322,7 @@ int bsdListen(int sockfd, int backlog) {
u32 pad[4];
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), g_bsdObjectId);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 18;
@ -214,7 +334,7 @@ int bsdListen(int sockfd, int backlog) {
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponse(&r);
ipcParseResponseForDomain(&r);
struct {
u64 magic;
@ -231,5 +351,56 @@ int bsdListen(int sockfd, int backlog) {
}
}
if (R_FAILED(rc)) {
g_Errno = EPIPE;
}
return ret;
}
int bsdWrite(int sockfd, void* buffer, size_t length) {
IpcCommand c;
ipcInitialize(&c);
ipcAddSendBuffer(&c, buffer, length, 0);
ipcAddSendStatic(&c, buffer, length, 0);
struct {
u64 magic;
u64 cmd_id;
u32 sockfd;
} *raw;
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), g_bsdObjectId);
raw->magic = SFCI_MAGIC;
raw->cmd_id = 24;
raw->sockfd = sockfd;
Result rc = ipcDispatch(g_bsdHandle);
int ret = -1;
if (R_SUCCEEDED(rc)) {
IpcCommandResponse r;
ipcParseResponseForDomain(&r);
struct {
u64 magic;
u64 result;
u32 ret;
u32 errno;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
g_Errno = resp->errno;
ret = resp->ret;
}
}
if (R_FAILED(rc)) {
g_Errno = EPIPE;
}
return ret;
}