mirror of
https://github.com/switchbrew/libnx.git
synced 2025-08-05 16:09:24 +02:00
Introducing ipc domains, bsd stuff
This commit is contained in:
parent
fb1d6f4d5c
commit
003e300e83
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user