diff --git a/src/libnx/wrapper/ipc.nim b/src/libnx/wrapper/ipc.nim index 7f1a276..b52c860 100644 --- a/src/libnx/wrapper/ipc.nim +++ b/src/libnx/wrapper/ipc.nim @@ -47,6 +47,24 @@ type IpcCommandType_Close = 2, IpcCommandType_LegacyControl = 3, IpcCommandType_Request = 4, IpcCommandType_Control = 5, IpcCommandType_RequestWithContext = 6, IpcCommandType_ControlWithContext = 7 + DomainMessageType* {.size: sizeof(cint).} = enum + DomainMessageType_Invalid = 0, DomainMessageType_SendMessage = 1, + DomainMessageType_Close = 2 + + + + + +## / IPC domain message header. + +type + DomainMessageHeader* {.importc: "DomainMessageHeader", header: headeripc, bycopy.} = object + Type* {.importc: "Type".}: uint8 + NumObjectIds* {.importc: "NumObjectIds".}: uint8 + Length* {.importc: "Length".}: uint16 + ThisObjectId* {.importc: "ThisObjectId".}: uint32 + Pad* {.importc: "Pad".}: array[2, uint32] + IpcCommand* {.importc: "IpcCommand", header: headeripc, bycopy.} = object NumSend* {.importc: "NumSend".}: csize ## A NumRecv* {.importc: "NumRecv".}: csize ## B @@ -67,9 +85,6 @@ type ObjectIds* {.importc: "ObjectIds".}: array[IPC_MAX_OBJECTS, uint32] - - - ## * ## @brief Initializes an IPC command structure. ## @param cmd IPC command structure. @@ -236,6 +251,9 @@ type NumHandles* {.importc: "NumHandles".}: csize ## /< Number of handles copied. Handles* {.importc: "Handles".}: array[IPC_MAX_OBJECTS, Handle] ## /< Handles. WasHandleCopied* {.importc: "WasHandleCopied".}: array[IPC_MAX_OBJECTS, bool] ## /< true if the handle was moved, false if it was copied. + IsDomainMessage* {.importc: "IsDomainMessage".}: bool ## /< true if the the message is a Domain message. + MessageType* {.importc: "MessageType".}: DomainMessageType ## /< Type of the domain message. + MessageLength* {.importc: "MessageLength".}: uint32 ## /< Size of rawdata (for domain messages). ThisObjectId* {.importc: "ThisObjectId".}: uint32 ## /< Object ID to call the command on (for domain messages). NumObjectIds* {.importc: "NumObjectIds".}: csize ## /< Number of object IDs (for domain messages). ObjectIds* {.importc: "ObjectIds".}: array[IPC_MAX_OBJECTS, uint32] ## /< Object IDs (for domain messages). @@ -300,17 +318,6 @@ proc ipcConvertSessionToDomain*(session: Handle; object_id_out: ptr uint32): Res proc ipcSendObjectId*(cmd: ptr IpcCommand; object_id: uint32) {.inline, cdecl, importc: "ipcSendObjectId", header: headeripc.} -## / IPC domain message header. - -type - DomainMessageHeader* {.importc: "DomainMessageHeader", header: headeripc, bycopy.} = object - Type* {.importc: "Type".}: uint8 - NumObjectIds* {.importc: "NumObjectIds".}: uint8 - Length* {.importc: "Length".}: uint16 - ThisObjectId* {.importc: "ThisObjectId".}: uint32 - Pad* {.importc: "Pad".}: array[2, uint32] - - ## * ## @brief Prepares the header of an IPC command structure (domain version). ## @param cmd IPC command structure. diff --git a/src/libnx/wrapper/ns.nim b/src/libnx/wrapper/ns.nim index 3a8aa2f..b9705da 100644 --- a/src/libnx/wrapper/ns.nim +++ b/src/libnx/wrapper/ns.nim @@ -26,4 +26,11 @@ proc nsvmExit*() {.cdecl, importc: "nsvmExit", header: headerns.} proc nsvmNeedsUpdateVulnerability*(`out`: ptr bool): Result {.cdecl, importc: "nsvmNeedsUpdateVulnerability", header: headerns.} proc nsvmGetSafeSystemVersion*(`out`: ptr uint16): Result {.cdecl, - importc: "nsvmGetSafeSystemVersion", header: headerns.} \ No newline at end of file + importc: "nsvmGetSafeSystemVersion", header: headerns.} +proc nsdevInitialize*(): Result {.cdecl, importc: "nsdevInitialize", + header: headerns.} +proc nsdevExit*() {.cdecl, importc: "nsdevExit", header: headerns.} +proc nsdevTerminateProcess*(pid: uint64): Result {.cdecl, + importc: "nsdevTerminateProcess", header: headerns.} +proc nsdevTerminateProgram*(tid: uint64): Result {.cdecl, + importc: "nsdevTerminateProgram", header: headerns.} \ No newline at end of file diff --git a/src/libnx/wrapper/nx/include/switch/kernel/ipc.h b/src/libnx/wrapper/nx/include/switch/kernel/ipc.h index ce99815..49d28f3 100644 --- a/src/libnx/wrapper/nx/include/switch/kernel/ipc.h +++ b/src/libnx/wrapper/nx/include/switch/kernel/ipc.h @@ -45,9 +45,24 @@ typedef enum { IpcCommandType_Request = 4, IpcCommandType_Control = 5, IpcCommandType_RequestWithContext = 6, - IpcCommandType_ControlWithContext = 7 + IpcCommandType_ControlWithContext = 7, } IpcCommandType; +typedef enum { + DomainMessageType_Invalid = 0, + DomainMessageType_SendMessage = 1, + DomainMessageType_Close = 2, +} DomainMessageType; + +/// IPC domain message header. +typedef struct { + u8 Type; + u8 NumObjectIds; + u16 Length; + u32 ThisObjectId; + u32 Pad[2]; +} DomainMessageHeader; + typedef struct { size_t NumSend; // A size_t NumRecv; // B @@ -348,6 +363,9 @@ typedef struct { Handle Handles[IPC_MAX_OBJECTS]; ///< Handles. bool WasHandleCopied[IPC_MAX_OBJECTS]; ///< true if the handle was moved, false if it was copied. + bool IsDomainMessage; ///< true if the the message is a Domain message. + DomainMessageType MessageType; ///< Type of the domain message. + u32 MessageLength; ///< Size of rawdata (for domain messages). 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). @@ -366,7 +384,7 @@ typedef struct { size_t NumStaticsOut; ///< Number of output statics available in the response. void* Raw; ///< Pointer to the raw embedded data structure in the response. - void* RawWithoutPadding; ///< Pointer to the raw embedded data structure, without padding. + void* RawWithoutPadding; ///< Pointer to the raw embedded data structure, without padding. size_t RawSize; ///< Size of the raw embedded data. } IpcParsedCommand; @@ -380,6 +398,8 @@ static inline Result ipcParse(IpcParsedCommand* r) { u32 ctrl0 = *buf++; u32 ctrl1 = *buf++; size_t i; + + r->IsDomainMessage = false; r->CommandType = (IpcCommandType) (ctrl0 & 0xffff); r->HasPid = false; @@ -570,15 +590,6 @@ static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id) { cmd->ObjectIds[cmd->NumObjectIds++] = object_id; } -/// IPC domain message header. -typedef struct { - u8 Type; - u8 NumObjectIds; - u16 Length; - u32 ThisObjectId; - u32 Pad[2]; -} DomainMessageHeader; - /** * @brief Prepares the header of an IPC command structure (domain version). * @param cmd IPC command structure. @@ -591,7 +602,7 @@ static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw DomainMessageHeader* hdr = (DomainMessageHeader*) raw; u32 *object_ids = (u32*)(((uintptr_t) raw) + sizeof(DomainMessageHeader) + sizeof_raw); - hdr->Type = 1; + hdr->Type = DomainMessageType_SendMessage; hdr->NumObjectIds = (u8)cmd->NumObjectIds; hdr->Length = sizeof_raw; hdr->ThisObjectId = object_id; @@ -609,7 +620,7 @@ static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw */ static inline Result ipcParseForDomain(IpcParsedCommand* r) { Result rc = ipcParse(r); - DomainMessageHeader* hdr; + DomainMessageHeader *hdr; u32 *object_ids; if(R_FAILED(rc)) return rc; @@ -618,8 +629,20 @@ static inline Result ipcParseForDomain(IpcParsedCommand* r) { object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length); r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader)); + r->IsDomainMessage = true; + r->MessageType = (DomainMessageType)(hdr->Type); + switch (r->MessageType) { + case DomainMessageType_SendMessage: + case DomainMessageType_Close: + break; + default: + return MAKERESULT(Module_Libnx, LibnxError_DomainMessageUnknownType); + } r->ThisObjectId = hdr->ThisObjectId; r->NumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds; + if ((uintptr_t)object_ids + sizeof(u32) * r->NumObjectIds - (uintptr_t)armGetTls() >= 0x100) { + return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds); + } for(size_t i = 0; i < r->NumObjectIds; i++) r->ObjectIds[i] = object_ids[i]; diff --git a/src/libnx/wrapper/nx/include/switch/kernel/svc.h b/src/libnx/wrapper/nx/include/switch/kernel/svc.h index 0ae591c..e5d0c4b 100644 --- a/src/libnx/wrapper/nx/include/switch/kernel/svc.h +++ b/src/libnx/wrapper/nx/include/switch/kernel/svc.h @@ -131,6 +131,15 @@ typedef enum { ProcessState_DebugSuspended=7, ///