mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
98 lines
2.5 KiB
C
98 lines
2.5 KiB
C
#define SFCI_MAGIC 0x49434653
|
|
|
|
typedef struct {
|
|
size_t NumSend; // A
|
|
size_t NumRecv; // B
|
|
size_t NumStaticSend; // X
|
|
size_t NumStaticRecv; // C
|
|
void* Buffers[8];
|
|
size_t Sizes[8];
|
|
u8 Flags[8];
|
|
|
|
bool SendPid;
|
|
size_t NumHandlesCopy;
|
|
size_t NumHandlesMove;
|
|
Handle Handles[8];
|
|
} IpcCommand;
|
|
|
|
static inline void ipcInitialize(IpcCommand* cmd) {
|
|
cmd->NumSend = 0;
|
|
cmd->NumRecv = 0;
|
|
cmd->NumStaticSend = 0;
|
|
cmd->NumStaticRecv = 0;
|
|
|
|
cmd->SendPid = false;
|
|
cmd->NumHandlesCopy = 0;
|
|
cmd->NumHandlesMove = 0;
|
|
}
|
|
|
|
typedef struct { // todo: Make sure sizeof isn't 16 bytes!
|
|
u32 Size;
|
|
u32 Addr;
|
|
u32 Packed;
|
|
} IpcBufferDescriptor;
|
|
|
|
typedef struct {
|
|
u32 Packed;
|
|
u32 Addr;
|
|
} IpcStaticSendDescriptor;
|
|
|
|
static inline void ipcAddSendBuffer(IpcCommand* cmd, void* buffer, size_t size, u8 flags) {
|
|
size_t off = cmd->NumSend;
|
|
cmd->Buffers[off] = buffer;
|
|
cmd->Sizes[off] = size;
|
|
cmd->Flags[off] = flags;
|
|
cmd->NumSend++;
|
|
}
|
|
|
|
static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, u8 flags) {
|
|
size_t off = cmd->NumSend + cmd->NumRecv;
|
|
cmd->Buffers[off] = buffer;
|
|
cmd->Sizes[off] = size;
|
|
cmd->Flags[off] = flags;
|
|
cmd->NumRecv++;
|
|
}
|
|
|
|
static inline void ipcSendPid(IpcCommand* cmd) {
|
|
cmd->SendPid = true;
|
|
}
|
|
|
|
static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h) {
|
|
cmd->Handles[cmd->NumHandlesCopy++] = h;
|
|
}
|
|
|
|
static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h) {
|
|
cmd->Handles[cmd->NumHandlesCopy + cmd->NumHandlesMove++] = h;
|
|
}
|
|
|
|
static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) {
|
|
u32* buf = armGetTls();
|
|
*buf++ = 4 | (cmd->NumSend << 20) | (cmd->NumRecv << 24);
|
|
|
|
if (cmd->SendPid || cmd->NumHandlesCopy > 0 || cmd->NumHandlesMove > 0) {
|
|
*buf++ = (sizeof_raw/4) | 0x80000000;
|
|
*buf++ = (!!cmd->SendPid) | (cmd->NumHandlesCopy << 1) | (cmd->NumHandlesMove << 1);
|
|
}
|
|
else {
|
|
*buf++ = sizeof_raw/4;
|
|
}
|
|
|
|
size_t i;
|
|
for (i=0; i<(cmd->NumSend + cmd->NumRecv); i++, buf+=3) {
|
|
IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf;
|
|
desc->Size = cmd->Sizes[i];
|
|
|
|
uintptr_t ptr = (uintptr_t) cmd->Buffers[i];
|
|
desc->Addr = ptr;
|
|
desc->Packed =
|
|
(((ptr) >> 36) << 28) | (((ptr >> 32) & 15) << 28) | cmd->Flags[i];
|
|
}
|
|
|
|
// todo: More
|
|
return (void*) ((((uintptr_t)buf) + 15) &~ 15);
|
|
}
|
|
|
|
static inline Result ipcDispatch(Handle session) {
|
|
return svcSendSyncRequest(session);
|
|
}
|