diff --git a/nx/include/switch/ipc.h b/nx/include/switch/ipc.h index 9e54273c..254bbd83 100644 --- a/nx/include/switch/ipc.h +++ b/nx/include/switch/ipc.h @@ -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; iNumStaticIn; 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; iNumStaticOut; 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; +} diff --git a/nx/include/switch/services/bsd.h b/nx/include/switch/services/bsd.h index 7130b8a4..8c2b2975 100644 --- a/nx/include/switch/services/bsd.h +++ b/nx/include/switch/services/bsd.h @@ -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; diff --git a/nx/source/heap/heap.c b/nx/source/heap/heap.c index 9409cc33..bce5d693 100644 --- a/nx/source/heap/heap.c +++ b/nx/source/heap/heap.c @@ -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); } diff --git a/nx/source/services/bsd.c b/nx/source/services/bsd.c index c48bc10e..147c3379 100644 --- a/nx/source/services/bsd.c +++ b/nx/source/services/bsd.c @@ -2,8 +2,11 @@ #include 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; }