mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-22 04:52:39 +02:00
Import ipc.h bugfixes from #44
This commit is contained in:
parent
372021e226
commit
5242771903
@ -14,11 +14,15 @@
|
|||||||
/// IPC output header magic
|
/// IPC output header magic
|
||||||
#define SFCO_MAGIC 0x4f434653
|
#define SFCO_MAGIC 0x4f434653
|
||||||
|
|
||||||
|
/// IPC invalid object ID
|
||||||
|
#define IPC_INVALID_OBJECT_ID UINT32_MAX
|
||||||
|
|
||||||
///@name IPC request building
|
///@name IPC request building
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// IPC command (request) structure.
|
/// IPC command (request) structure.
|
||||||
#define IPC_MAX_BUFFERS 8
|
#define IPC_MAX_BUFFERS 8
|
||||||
|
#define IPC_MAX_OBJECTS 8
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t NumSend; // A
|
size_t NumSend; // A
|
||||||
@ -37,7 +41,10 @@ typedef struct {
|
|||||||
bool SendPid;
|
bool SendPid;
|
||||||
size_t NumHandlesCopy;
|
size_t NumHandlesCopy;
|
||||||
size_t NumHandlesMove;
|
size_t NumHandlesMove;
|
||||||
Handle Handles[8];
|
Handle Handles[IPC_MAX_OBJECTS];
|
||||||
|
|
||||||
|
size_t NumObjectIds;
|
||||||
|
u32 ObjectIds[IPC_MAX_OBJECTS];
|
||||||
} IpcCommand;
|
} IpcCommand;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -276,11 +283,15 @@ typedef struct {
|
|||||||
u64 Pid; ///< PID included in the response (only if HasPid is true)
|
u64 Pid; ///< PID included in the response (only if HasPid is true)
|
||||||
|
|
||||||
size_t NumHandles; ///< Number of handles in the response.
|
size_t NumHandles; ///< Number of handles in the response.
|
||||||
Handle Handles[8]; ///< Handles.
|
Handle Handles[IPC_MAX_OBJECTS]; ///< Handles.
|
||||||
|
|
||||||
|
u32 ThisObjectId; ///< Object ID to call the command on (for domain messages).
|
||||||
|
size_t NumObjectIds; ///< Number of object IDs (for domain messages).
|
||||||
|
u32 ObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages).
|
||||||
|
|
||||||
size_t NumBuffers; ///< Number of buffers in the response.
|
size_t NumBuffers; ///< Number of buffers in the response.
|
||||||
void* Buffers[4]; ///< Pointers to the buffers.
|
void* Buffers[IPC_MAX_BUFFERS]; ///< Pointers to the buffers.
|
||||||
size_t BufferSizes[4]; ///< Sizes of the buffers.
|
size_t BufferSizes[IPC_MAX_BUFFERS]; ///< Sizes of the buffers.
|
||||||
|
|
||||||
void* Raw; ///< Pointer to the raw embedded data structure in the response.
|
void* Raw; ///< Pointer to the raw embedded data structure in the response.
|
||||||
size_t RawSize; ///< Size of the raw embedded data.
|
size_t RawSize; ///< Size of the raw embedded data.
|
||||||
@ -313,8 +324,8 @@ static inline Result ipcParse(IpcParsedCommand* r) {
|
|||||||
size_t num_handles = ((ctrl2 >> 1) & 15) + ((ctrl2 >> 5) & 15);
|
size_t num_handles = ((ctrl2 >> 1) & 15) + ((ctrl2 >> 5) & 15);
|
||||||
buf += num_handles;
|
buf += num_handles;
|
||||||
|
|
||||||
if (num_handles > 8)
|
if (num_handles > IPC_MAX_OBJECTS)
|
||||||
num_handles = 8;
|
num_handles = IPC_MAX_OBJECTS;
|
||||||
|
|
||||||
for (i=0; i<num_handles; i++)
|
for (i=0; i<num_handles; i++)
|
||||||
r->Handles[i] = *(buf-num_handles+i);
|
r->Handles[i] = *(buf-num_handles+i);
|
||||||
@ -328,8 +339,8 @@ static inline Result ipcParse(IpcParsedCommand* r) {
|
|||||||
size_t num_bufs = ((ctrl0 >> 20) & 15) + ((ctrl0 >> 24) & 15) + (((ctrl0 >> 28) & 15));
|
size_t num_bufs = ((ctrl0 >> 20) & 15) + ((ctrl0 >> 24) & 15) + (((ctrl0 >> 28) & 15));
|
||||||
r->Raw = (void*)(((uintptr_t)(buf + num_bufs*3) + 15) &~ 15);
|
r->Raw = (void*)(((uintptr_t)(buf + num_bufs*3) + 15) &~ 15);
|
||||||
|
|
||||||
if (num_bufs > 4)
|
if (num_bufs > IPC_MAX_BUFFERS)
|
||||||
num_bufs = 4;
|
num_bufs = IPC_MAX_BUFFERS;
|
||||||
|
|
||||||
for (i=0; i<num_bufs; i++, buf+=3) {
|
for (i=0; i<num_bufs; i++, buf+=3) {
|
||||||
IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf;
|
IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf;
|
||||||
@ -427,13 +438,22 @@ static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_ou
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds an object ID to be sent through an IPC domain command structure.
|
||||||
|
* @param cmd IPC domain command structure.
|
||||||
|
* @param object_id Object ID to send.
|
||||||
|
*/
|
||||||
|
static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id) {
|
||||||
|
cmd->ObjectIds[cmd->NumObjectIds++] = object_id;
|
||||||
|
}
|
||||||
|
|
||||||
/// IPC domain message header.
|
/// IPC domain message header.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 Type;
|
u8 Type;
|
||||||
u8 Pad0;
|
u8 NumObjectIds;
|
||||||
u16 Length;
|
u16 Length;
|
||||||
u32 ObjectId;
|
u32 ThisObjectId;
|
||||||
u32 Pad1[2];
|
u32 Pad[2];
|
||||||
} DomainMessageHeader;
|
} DomainMessageHeader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -443,16 +463,19 @@ typedef struct {
|
|||||||
* @oaram object_id Domain object ID.
|
* @oaram object_id Domain object ID.
|
||||||
* @return Pointer to the raw embedded data structure in the request, ready to be filled out.
|
* @return Pointer to the raw embedded data structure in the request, ready to be filled out.
|
||||||
*/
|
*/
|
||||||
static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, size_t object_id) {
|
static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, u32 object_id) {
|
||||||
void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader));
|
void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader));
|
||||||
DomainMessageHeader* hdr = (DomainMessageHeader*) raw;
|
DomainMessageHeader* hdr = (DomainMessageHeader*) raw;
|
||||||
|
u32 *object_ids = (u32*)(((uintptr_t) raw) + sizeof(DomainMessageHeader) + sizeof_raw);
|
||||||
|
|
||||||
hdr->Type = 1;
|
hdr->Type = 1;
|
||||||
|
hdr->NumObjectIds = (u8)cmd->NumObjectIds;
|
||||||
hdr->Length = sizeof_raw;
|
hdr->Length = sizeof_raw;
|
||||||
hdr->ObjectId = object_id;
|
hdr->ThisObjectId = object_id;
|
||||||
|
hdr->Pad[0] = hdr->Pad[1] = 0;
|
||||||
hdr->Pad0 = hdr->Pad1[0] = hdr->Pad1[1] = 0;
|
|
||||||
|
|
||||||
|
for(size_t i = 0; i < cmd->NumObjectIds; i++)
|
||||||
|
object_ids[i] = cmd->ObjectIds[i];
|
||||||
return (void*)(((uintptr_t) raw) + sizeof(DomainMessageHeader));
|
return (void*)(((uintptr_t) raw) + sizeof(DomainMessageHeader));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,12 +486,43 @@ static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw
|
|||||||
*/
|
*/
|
||||||
static inline Result ipcParseForDomain(IpcParsedCommand* r) {
|
static inline Result ipcParseForDomain(IpcParsedCommand* r) {
|
||||||
Result rc = ipcParse(r);
|
Result rc = ipcParse(r);
|
||||||
|
DomainMessageHeader* hdr;
|
||||||
|
u32 *object_ids;
|
||||||
|
if(R_FAILED(rc))
|
||||||
|
return rc;
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
hdr = (DomainMessageHeader*) r->Raw;
|
||||||
|
object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length);
|
||||||
r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader));
|
r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader));
|
||||||
}
|
|
||||||
|
r->ThisObjectId = hdr->ThisObjectId;
|
||||||
|
r->NumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds;
|
||||||
|
for(size_t i = 0; i < r->NumObjectIds; i++)
|
||||||
|
r->ObjectIds[i] = object_ids[i];
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Closes a domain object by ID.
|
||||||
|
* @param session IPC session handle.
|
||||||
|
* @param object_id ID of the object to close.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcCloseObjectById(Handle session, u32 object_id) {
|
||||||
|
IpcCommand c;
|
||||||
|
DomainMessageHeader* hdr;
|
||||||
|
|
||||||
|
ipcInitialize(&c);
|
||||||
|
hdr = (DomainMessageHeader*)ipcPrepareHeader(&c, sizeof(DomainMessageHeader));
|
||||||
|
|
||||||
|
hdr->Type = 2;
|
||||||
|
hdr->NumObjectIds = 0;
|
||||||
|
hdr->Length = 0;
|
||||||
|
hdr->ThisObjectId = object_id;
|
||||||
|
hdr->Pad[0] = hdr->Pad[1] = 0;
|
||||||
|
|
||||||
|
return ipcDispatch(session); // this command has no associated response
|
||||||
|
}
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
Loading…
Reference in New Issue
Block a user