From 6ad0042147ec110e97a33911e93c003fc77b7d7e Mon Sep 17 00:00:00 2001 From: fincs Date: Thu, 19 Sep 2019 03:50:06 +0200 Subject: [PATCH] Introduce new IPC interface wrapper code, see details: - Service object moved away from sm.h and into its own file (sf/service.h) - Service object completely redesigned, but a (mostly) backwards compatible API was kept - New low level HIPC request/response code - New CMIF client-oriented code - New service IPC dispatch functions - Pointer buffer size automatically retrieved for all sessions - Removed previous manual pointer buffer size query code - SM rewritten with new IPC code - All other services are still pending IPC rewrite --- nx/include/switch.h | 6 +- nx/include/switch/display/binder.h | 2 +- nx/include/switch/services/sm.h | 144 +--------- nx/include/switch/services/usbhs.h | 1 - nx/include/switch/sf/cmif.h | 362 +++++++++++++++++++++++++ nx/include/switch/sf/hipc.h | 363 +++++++++++++++++++++++++ nx/include/switch/sf/service.h | 417 +++++++++++++++++++++++++++++ nx/source/display/binder.c | 10 +- nx/source/services/applet.c | 18 +- nx/source/services/auddev.c | 9 +- nx/source/services/bsd.c | 75 +++--- nx/source/services/hiddbg.c | 5 +- nx/source/services/i2c.c | 12 +- nx/source/services/nv.c | 5 +- nx/source/services/sm.c | 170 ++---------- nx/source/services/usbhs.c | 4 +- 16 files changed, 1234 insertions(+), 369 deletions(-) create mode 100644 nx/include/switch/sf/cmif.h create mode 100644 nx/include/switch/sf/hipc.h create mode 100644 nx/include/switch/sf/service.h diff --git a/nx/include/switch.h b/nx/include/switch.h index 15429807..8b7e87dc 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -36,9 +36,13 @@ extern "C" { #include "switch/kernel/detect.h" #include "switch/kernel/random.h" #include "switch/kernel/jit.h" -#include "switch/kernel/ipc.h" +#include "switch/kernel/ipc.h" // Deprecated #include "switch/kernel/barrier.h" +#include "switch/sf/hipc.h" +#include "switch/sf/cmif.h" +#include "switch/sf/service.h" + #include "switch/services/sm.h" #include "switch/services/smm.h" #include "switch/services/fs.h" diff --git a/nx/include/switch/display/binder.h b/nx/include/switch/display/binder.h index aa8cefc7..d61abe3c 100644 --- a/nx/include/switch/display/binder.h +++ b/nx/include/switch/display/binder.h @@ -10,7 +10,7 @@ typedef struct { bool initialized : 1; bool has_transact_auto : 1; s32 id; - size_t ipc_buffer_size; + size_t dummy; Service* relay; } Binder; diff --git a/nx/include/switch/services/sm.h b/nx/include/switch/services/sm.h index b2cb0816..a9ad7445 100644 --- a/nx/include/switch/services/sm.h +++ b/nx/include/switch/services/sm.h @@ -9,71 +9,11 @@ #include "../types.h" #include "../kernel/svc.h" #include "../kernel/ipc.h" +#include "../sf/service.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -/// Service type. -typedef enum { - ServiceType_Uninitialized, ///< Uninitialized service. - ServiceType_Normal, ///< Normal service. - ServiceType_Domain, ///< Domain. - ServiceType_DomainSubservice, ///< Domain subservice; - ServiceType_Override, ///< Service overriden in the homebrew environment. -} ServiceType; - -/// Service object structure. -typedef struct { - Handle handle; - u32 object_id; - ServiceType type; -} Service; - -/** - * @brief Returns whether a service is overriden in the homebrew environment. - * @param[in] s Service object. - * @return true if overriden. - */ -static inline bool serviceIsOverride(Service* s) { - return s->type == ServiceType_Override; -} - -/** - * @brief Returns whether a service has been initialized. - * @param[in] s Service object. - * @return true if initialized. - */ -static inline bool serviceIsActive(Service* s) { - return s->type != ServiceType_Uninitialized; -} - -/** - * @brief Returns whether a service is a domain. - * @param[in] s Service object. - * @return true if a domain. - */ -static inline bool serviceIsDomain(Service* s) { - return s->type == ServiceType_Domain; -} - -/** - * @brief Returns whether a service is a domain subservice. - * @param[in] s Service object. - * @return true if a domain subservice. - */ -static inline bool serviceIsDomainSubservice(Service* s) { - return s->type == ServiceType_DomainSubservice; -} - -/** - * @brief For a domain/domain subservice, return the associated object ID. - * @param[in] s Service object, necessarily a domain or domain subservice. - * @return The object ID. - */ -static inline u32 serviceGetObjectId(Service* s) { - return s->object_id; -} - /** * @brief Closes a domain object by ID. * @param[in] s Service object, necessarily a domain or domain subservice. @@ -82,7 +22,7 @@ static inline u32 serviceGetObjectId(Service* s) { */ DEPRECATED static inline Result serviceCloseObjectById(Service* s, u32 object_id) { - return ipcCloseObjectById(s->handle, object_id); + return ipcCloseObjectById(s->session, object_id); } /** @@ -92,30 +32,7 @@ static inline Result serviceCloseObjectById(Service* s, u32 object_id) { */ DEPRECATED static inline Result serviceIpcDispatch(Service* s) { - return ipcDispatch(s->handle); -} - -/** - * @brief Creates a service object from an IPC session handle. - * @param[out] s Service object. - * @param[in] h IPC session handle. - */ -static inline void serviceCreate(Service* s, Handle h) { - s->handle = h; - s->type = ServiceType_Normal; - s->object_id = IPC_INVALID_OBJECT_ID; -} - -/** - * @brief Creates a domain subservice object from a parent service. - * @param[out] s Service object. - * @param[in] parent Parent service, necessarily a domain or domain subservice. - * @param[in] object_id Object ID for this subservice. - */ -static inline void serviceCreateDomainSubservice(Service* s, Service* parent, u32 object_id) { - s->handle = parent->handle; - s->type = ServiceType_DomainSubservice; - s->object_id = object_id; + return ipcDispatch(s->session); } /** @@ -146,57 +63,6 @@ static inline void serviceSendObject(Service* s, IpcCommand* cmd) { } } -/** - * @brief Converts a regular service to a domain. - * @param[in] s Service object. - * @return Result code. - */ -static inline Result serviceConvertToDomain(Service* s) { - Result rc = 0; - if (serviceIsOverride(s)) { - rc = ipcCloneSession(s->handle, 1, &s->handle); - if (R_FAILED(rc)) { - return rc; - } - s->type = ServiceType_Normal; - } - rc = ipcConvertSessionToDomain(s->handle, &s->object_id); - if (R_SUCCEEDED(rc)) { - s->type = ServiceType_Domain; - } - return rc; -} - -/** - * @brief Closes a service. - * @param[in] s Service object. - */ -static inline void serviceClose(Service* s) { - switch (s->type) { - - case ServiceType_Normal: - case ServiceType_Domain: - ipcCloseSession(s->handle); - svcCloseHandle(s->handle); - break; - - case ServiceType_DomainSubservice: - serviceCloseObjectById(s, s->object_id); - break; - - case ServiceType_Override: - // Don't close because we don't own the overridden handle. - break; - - case ServiceType_Uninitialized: - break; - } - - s->type = ServiceType_Uninitialized; -} - - - /** * @brief Prepares the header of an IPC command structure for a service. * @param s Service to prepare message header for @@ -229,6 +95,8 @@ static inline Result serviceIpcParse(Service* s, IpcParsedCommand* r, size_t siz } } +#pragma GCC diagnostic pop + /** * @brief Initializes SM. * @return Result code. @@ -308,5 +176,3 @@ u64 smEncodeName(const char* name); * @param[in] handle IPC session handle. */ void smAddOverrideHandle(u64 name, Handle handle); - -#pragma GCC diagnostic pop diff --git a/nx/include/switch/services/usbhs.h b/nx/include/switch/services/usbhs.h index b6937767..22ae0114 100644 --- a/nx/include/switch/services/usbhs.h +++ b/nx/include/switch/services/usbhs.h @@ -96,7 +96,6 @@ typedef struct { typedef struct { Service s; Event eventXfer; ///< [2.0.0+] Signaled when PostBufferAsync finishes. - size_t ptrbufsize; ///< [3.0.0+] IPC pointer buffer size. struct usb_endpoint_descriptor desc; } UsbHsClientEpSession; diff --git a/nx/include/switch/sf/cmif.h b/nx/include/switch/sf/cmif.h new file mode 100644 index 00000000..69df4719 --- /dev/null +++ b/nx/include/switch/sf/cmif.h @@ -0,0 +1,362 @@ +/** + * @file cmif.h + * @brief Common Message Interface Framework protocol + * @author fincs + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "hipc.h" + +#define CMIF_IN_HEADER_MAGIC 0x49434653 // "SFCI" +#define CMIF_OUT_HEADER_MAGIC 0x4F434653 // "SFCO" + +typedef enum CmifCommandType { + CmifCommandType_Invalid = 0, + CmifCommandType_LegacyRequest = 1, + CmifCommandType_Close = 2, + CmifCommandType_LegacyControl = 3, + CmifCommandType_Request = 4, + CmifCommandType_Control = 5, + CmifCommandType_RequestWithContext = 6, + CmifCommandType_ControlWithContext = 7, +} CmifCommandType; + +typedef enum CmifDomainRequestType { + CmifDomainRequestType_Invalid = 0, + CmifDomainRequestType_SendMessage = 1, + CmifDomainRequestType_Close = 2, +} CmifDomainRequestType; + +typedef struct CmifInHeader { + u32 magic; + u32 version; + u32 command_id; + u32 token; +} CmifInHeader; + +typedef struct CmifOutHeader { + u32 magic; + u32 version; + Result result; + u32 token; +} CmifOutHeader; + +typedef struct CmifDomainInHeader { + u8 type; + u8 num_in_objects; + u16 data_size; + u32 object_id; + u32 padding; + u32 token; +} CmifDomainInHeader; + +typedef struct CmifDomainOutHeader { + u32 num_out_objects; + u32 padding[3]; +} CmifDomainOutHeader; + +typedef struct CmifRequestFormat { + u32 object_id; + u32 request_id; + u32 context; + u32 data_size; + u32 server_pointer_size; + u32 num_in_auto_buffers; + u32 num_out_auto_buffers; + u32 num_in_buffers; + u32 num_out_buffers; + u32 num_inout_buffers; + u32 num_in_pointers; + u32 num_out_pointers; + u32 num_out_fixed_pointers; + u32 num_objects; + u32 num_handles; + u32 send_pid; +} CmifRequestFormat; + +typedef struct CmifRequest { + HipcRequest hipc; + void* data; + u16* out_pointer_sizes; + u32* objects; + u32 server_pointer_size; + u32 cur_in_ptr_id; +} CmifRequest; + +typedef struct CmifResponse { + void* data; + u32* objects; + Handle* copy_handles; + Handle* move_handles; +} CmifResponse; + +NX_CONSTEXPR void* cmifGetAlignedDataStart(u32* data_words, void* base) +{ + intptr_t data_start = ((u8*)data_words - (u8*)base + 15) &~ 15; + return (u8*)base + data_start; +} + +NX_CONSTEXPR CmifRequest cmifMakeRequest(void* base, CmifRequestFormat fmt) +{ + // First of all, we need to figure out what size we need. + u32 actual_size = 16; + if (fmt.object_id) + actual_size += sizeof(CmifDomainInHeader) + fmt.num_objects*sizeof(u32); + actual_size += sizeof(CmifInHeader) + fmt.data_size; + actual_size = (actual_size + 1) &~ 1; // hword-align + u32 out_pointer_size_table_offset = actual_size; + u32 out_pointer_size_table_size = fmt.num_out_auto_buffers + fmt.num_out_pointers; + actual_size += sizeof(u16)*out_pointer_size_table_size; + u32 num_data_words = (actual_size + 3) / 4; + + CmifRequest req = {}; + req.hipc = hipcMakeRequestInline(base, + .type = CmifCommandType_Request, + .num_send_statics = fmt.num_in_auto_buffers + fmt.num_in_pointers, + .num_send_buffers = fmt.num_in_auto_buffers + fmt.num_in_buffers, + .num_recv_buffers = fmt.num_out_auto_buffers + fmt.num_out_buffers, + .num_exch_buffers = fmt.num_inout_buffers, + .num_data_words = num_data_words, + .num_recv_statics = out_pointer_size_table_size + fmt.num_out_fixed_pointers, + .send_pid = fmt.send_pid, + .num_copy_handles = fmt.num_handles, + .num_move_handles = 0, + ); + + CmifInHeader* hdr = NULL; + void* start = cmifGetAlignedDataStart(req.hipc.data_words, base); + if (fmt.object_id) { + CmifDomainInHeader* domain_hdr = (CmifDomainInHeader*)start; + u32 payload_size = sizeof(CmifInHeader) + fmt.data_size; + *domain_hdr = (CmifDomainInHeader){ + .type = CmifDomainRequestType_SendMessage, + .num_in_objects = fmt.num_objects, + .data_size = (u16)payload_size, + .object_id = fmt.object_id, + .padding = 0, + .token = 0, + }; + hdr = (CmifInHeader*)(domain_hdr+1); + req.objects = (u32*)((u8*)hdr + payload_size); + } else + hdr = (CmifInHeader*)start; + + *hdr = (CmifInHeader){ + .magic = CMIF_IN_HEADER_MAGIC, + .version = 0, + .command_id = fmt.request_id, + .token = 0, + }; + + req.data = hdr+1; + req.out_pointer_sizes = (u16*)((u8*)req.hipc.data_words + out_pointer_size_table_offset); + req.server_pointer_size = fmt.server_pointer_size; + + return req; +} + +NX_CONSTEXPR void* cmifMakeControlRequest(void* base, u32 request_id, u32 size) +{ + u32 actual_size = 16 + sizeof(CmifInHeader) + size; + HipcRequest hipc = hipcMakeRequestInline(base, + .type = CmifCommandType_Control, + .num_data_words = (actual_size + 3) / 4, + ); + CmifInHeader* hdr = (CmifInHeader*)cmifGetAlignedDataStart(hipc.data_words, base); + *hdr = (CmifInHeader){ + .magic = CMIF_IN_HEADER_MAGIC, + .version = 0, + .command_id = request_id, + .token = 0, + }; + return hdr+1; +} + +NX_CONSTEXPR void cmifMakeCloseRequest(void* base, u32 object_id) +{ + if (object_id) { + HipcRequest hipc = hipcMakeRequestInline(base, + .type = CmifCommandType_Request, + .num_data_words = (16 + sizeof(CmifDomainInHeader)) / 4, + ); + CmifDomainInHeader* domain_hdr = (CmifDomainInHeader*)cmifGetAlignedDataStart(hipc.data_words, base); + *domain_hdr = (CmifDomainInHeader){ + .type = CmifDomainRequestType_Close, + .object_id = object_id, + }; + } else { + hipcMakeRequestInline(base, + .type = CmifCommandType_Close, + ); + } +} + +NX_CONSTEXPR void cmifRequestInBuffer(CmifRequest* req, const void* buffer, size_t size, HipcBufferMode mode) +{ + *req->hipc.send_buffers++ = hipcMakeBuffer(buffer, size, mode); +} + +NX_CONSTEXPR void cmifRequestOutBuffer(CmifRequest* req, void* buffer, size_t size, HipcBufferMode mode) +{ + *req->hipc.recv_buffers++ = hipcMakeBuffer(buffer, size, mode); +} + +NX_CONSTEXPR void cmifRequestInOutBuffer(CmifRequest* req, void* buffer, size_t size, HipcBufferMode mode) +{ + *req->hipc.exch_buffers++ = hipcMakeBuffer(buffer, size, mode); +} + +NX_CONSTEXPR void cmifRequestInPointer(CmifRequest* req, const void* buffer, size_t size) +{ + *req->hipc.send_statics++ = hipcMakeSendStatic(buffer, size, req->cur_in_ptr_id++); + req->server_pointer_size -= size; +} + +NX_CONSTEXPR void cmifRequestOutFixedPointer(CmifRequest* req, void* buffer, size_t size) +{ + *req->hipc.recv_list++ = hipcMakeRecvStatic(buffer, size); + req->server_pointer_size -= size; +} + +NX_CONSTEXPR void cmifRequestOutPointer(CmifRequest* req, void* buffer, size_t size) +{ + cmifRequestOutFixedPointer(req, buffer, size); + *req->out_pointer_sizes++ = size; +} + +NX_CONSTEXPR void cmifRequestInAutoBuffer(CmifRequest* req, const void* buffer, size_t size) +{ + if (req->server_pointer_size && size <= req->server_pointer_size) { + cmifRequestInPointer(req, buffer, size); + cmifRequestInBuffer(req, NULL, 0, HipcBufferMode_Normal); + } else { + cmifRequestInPointer(req, NULL, 0); + cmifRequestInBuffer(req, buffer, size, HipcBufferMode_Normal); + } +} + +NX_CONSTEXPR void cmifRequestOutAutoBuffer(CmifRequest* req, void* buffer, size_t size) +{ + if (req->server_pointer_size && size <= req->server_pointer_size) { + cmifRequestOutPointer(req, buffer, size); + cmifRequestOutBuffer(req, NULL, 0, HipcBufferMode_Normal); + } else { + cmifRequestOutPointer(req, NULL, 0); + cmifRequestOutBuffer(req, buffer, size, HipcBufferMode_Normal); + } +} + +NX_CONSTEXPR void cmifRequestObject(CmifRequest* req, u32 object_id) +{ + *req->objects++ = object_id; +} + +NX_CONSTEXPR void cmifRequestHandle(CmifRequest* req, Handle handle) +{ + *req->hipc.copy_handles++ = handle; +} + +NX_CONSTEXPR Result cmifParseResponse(CmifResponse* res, void* base, bool is_domain, u32 size) +{ + HipcResponse hipc = hipcParseResponse(base); + void* start = cmifGetAlignedDataStart(hipc.data_words, base); + + CmifOutHeader* hdr = NULL; + u32* objects = NULL; + if (is_domain) + { + CmifDomainOutHeader* domain_hdr = (CmifDomainOutHeader*)start; + hdr = (CmifOutHeader*)(domain_hdr+1); + objects = (u32*)((u8*)hdr + sizeof(CmifOutHeader) + size); + } + else + hdr = (CmifOutHeader*)start; + + if (hdr->magic != CMIF_OUT_HEADER_MAGIC) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); // todo: proper result code + if (R_FAILED(hdr->result)) + return hdr->result; + + *res = (CmifResponse){ + .data = hdr+1, + .objects = objects, + .copy_handles = hipc.copy_handles, + .move_handles = hipc.move_handles, + }; + + return 0; +} + +NX_CONSTEXPR u32 cmifResponseGetObject(CmifResponse* res) +{ + return *res->objects++; +} + +NX_CONSTEXPR Handle cmifResponseGetCopyHandle(CmifResponse* res) +{ + return *res->copy_handles++; +} + +NX_CONSTEXPR Handle cmifResponseGetMoveHandle(CmifResponse* res) +{ + return *res->move_handles++; +} + +NX_INLINE Result cmifConvertCurrentObjectToDomain(Handle h, u32* out_object_id) +{ + cmifMakeControlRequest(armGetTls(), 0, 0); + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) + { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, sizeof(u32)); + if (R_SUCCEEDED(rc) && out_object_id) + *out_object_id = *(u32*)resp.data; + } + return rc; +} + +NX_INLINE Result cmifCopyFromCurrentDomain(Handle h, u32 object_id, Handle* out_h) +{ + void* raw = cmifMakeControlRequest(armGetTls(), 1, sizeof(u32)); + *(u32*)raw = object_id; + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) + { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, 0); + if (R_SUCCEEDED(rc) && out_h) + *out_h = resp.move_handles[0]; + } + return rc; +} + +NX_INLINE Result cmifQueryPointerBufferSize(Handle h, u16* out_size) +{ + cmifMakeControlRequest(armGetTls(), 3, 0); + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) + { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, sizeof(u16)); + if (R_SUCCEEDED(rc) && out_size) + *out_size = *(u16*)resp.data; + } + return rc; +} + +NX_INLINE Result cmifCloneCurrentObjectEx(Handle h, u32 unk, Handle* out_h) +{ + void* raw = cmifMakeControlRequest(armGetTls(), 4, sizeof(u32)); + *(u32*)raw = unk; + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) + { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, 0); + if (R_SUCCEEDED(rc) && out_h) + *out_h = resp.move_handles[0]; + } + return rc; +} diff --git a/nx/include/switch/sf/hipc.h b/nx/include/switch/sf/hipc.h new file mode 100644 index 00000000..e3836007 --- /dev/null +++ b/nx/include/switch/sf/hipc.h @@ -0,0 +1,363 @@ +/** + * @file hipc.h + * @brief Horizon Inter-Process Communication protocol + * @author fincs + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "../result.h" +#include "../arm/tls.h" +#include "../kernel/svc.h" + +#define HIPC_AUTO_RECV_STATIC UINT8_MAX +#define HIPC_RESPONSE_NO_PID UINT32_MAX + +typedef struct HipcMetadata { + u32 type; + u32 num_send_statics; + u32 num_send_buffers; + u32 num_recv_buffers; + u32 num_exch_buffers; + u32 num_data_words; + u32 num_recv_statics; // also accepts HIPC_AUTO_RECV_STATIC + u32 send_pid; + u32 num_copy_handles; + u32 num_move_handles; +} HipcMetadata; + +typedef struct HipcHeader { + u32 type : 16; + u32 num_send_statics : 4; + u32 num_send_buffers : 4; + u32 num_recv_buffers : 4; + u32 num_exch_buffers : 4; + u32 num_data_words : 10; + u32 recv_static_mode : 4; + u32 padding : 6; + u32 recv_list_offset : 11; // Unused. + u32 has_special_header : 1; +} HipcHeader; + +typedef struct HipcSpecialHeader { + u32 send_pid : 1; + u32 num_copy_handles : 4; + u32 num_move_handles : 4; + u32 padding : 23; +} HipcSpecialHeader; + +typedef struct HipcStaticDescriptor { + u32 index : 6; + u32 address_high : 6; + u32 address_mid : 4; + u32 size : 16; + u32 address_low; +} HipcStaticDescriptor; + +typedef struct HipcBufferDescriptor { + u32 size_low; + u32 address_low; + u32 mode : 2; + u32 address_high : 22; + u32 size_high : 4; + u32 address_mid : 4; +} HipcBufferDescriptor; + +typedef struct HipcRecvListEntry { + u32 address_low; + u32 address_high : 16; + u32 size : 16; +} HipcRecvListEntry; + +typedef struct HipcRequest { + HipcStaticDescriptor* send_statics; + HipcBufferDescriptor* send_buffers; + HipcBufferDescriptor* recv_buffers; + HipcBufferDescriptor* exch_buffers; + u32* data_words; + HipcRecvListEntry* recv_list; + Handle* copy_handles; + Handle* move_handles; +} HipcRequest; + +typedef struct HipcParsedRequest { + HipcMetadata meta; + HipcRequest data; + u64 pid; +} HipcParsedRequest; + +typedef struct HipcResponse { + u64 pid; + u32 num_statics; + u32 num_data_words; + u32 num_copy_handles; + u32 num_move_handles; + HipcStaticDescriptor* statics; + u32* data_words; + Handle* copy_handles; + Handle* move_handles; +} HipcResponse; + +typedef enum HipcBufferMode { + HipcBufferMode_Normal = 0, + HipcBufferMode_NonSecure = 1, + HipcBufferMode_Invalid = 2, + HipcBufferMode_NonDevice = 3, +} HipcBufferMode; + +NX_CONSTEXPR HipcStaticDescriptor hipcMakeSendStatic(const void* buffer, size_t size, u8 index) +{ + return (HipcStaticDescriptor){ + .index = index, + .address_high = (u32)((uintptr_t)buffer >> 36), + .address_mid = (u32)((uintptr_t)buffer >> 32), + .size = (u32)size, + .address_low = (u32)(uintptr_t)buffer, + }; +} + +NX_CONSTEXPR HipcBufferDescriptor hipcMakeBuffer(const void* buffer, size_t size, HipcBufferMode mode) +{ + return (HipcBufferDescriptor){ + .size_low = (u32)size, + .address_low = (u32)(uintptr_t)buffer, + .mode = mode, + .address_high = (u32)((uintptr_t)buffer >> 36), + .size_high = (u32)(size >> 32), + .address_mid = (u32)((uintptr_t)buffer >> 32), + }; +} + +NX_CONSTEXPR HipcRecvListEntry hipcMakeRecvStatic(void* buffer, size_t size) +{ + return (HipcRecvListEntry){ + .address_low = (u32)((uintptr_t)buffer), + .address_high = (u32)((uintptr_t)buffer >> 32), + .size = (u32)size, + }; +} + +NX_CONSTEXPR void* hipcGetStaticAddress(const HipcStaticDescriptor* desc) +{ + return (void*)(desc->address_low | ((uintptr_t)desc->address_mid << 32) | ((uintptr_t)desc->address_high << 36)); +} + +NX_CONSTEXPR size_t hipcGetStaticSize(const HipcStaticDescriptor* desc) +{ + return desc->size; +} + +NX_CONSTEXPR void* hipcGetBufferAddress(const HipcBufferDescriptor* desc) +{ + return (void*)(desc->address_low | ((uintptr_t)desc->address_mid << 32) | ((uintptr_t)desc->address_high << 36)); +} + +NX_CONSTEXPR size_t hipcGetBufferSize(const HipcBufferDescriptor* desc) +{ + return desc->size_low | ((size_t)desc->size_high << 32); +} + +NX_CONSTEXPR HipcRequest hipcCalcRequestLayout(HipcMetadata meta, void* base) +{ + // Copy handles + Handle* copy_handles = NULL; + if (meta.num_copy_handles) { + copy_handles = (Handle*)base; + base = copy_handles + meta.num_copy_handles; + } + + // Move handles + Handle* move_handles = NULL; + if (meta.num_move_handles) { + move_handles = (Handle*)base; + base = move_handles + meta.num_move_handles; + } + + // Send statics + HipcStaticDescriptor* send_statics = NULL; + if (meta.num_send_statics) { + send_statics = (HipcStaticDescriptor*)base; + base = send_statics + meta.num_send_statics; + } + + // Send buffers + HipcBufferDescriptor* send_buffers = NULL; + if (meta.num_send_buffers) { + send_buffers = (HipcBufferDescriptor*)base; + base = send_buffers + meta.num_send_buffers; + } + + // Recv buffers + HipcBufferDescriptor* recv_buffers = NULL; + if (meta.num_recv_buffers) { + recv_buffers = (HipcBufferDescriptor*)base; + base = recv_buffers + meta.num_recv_buffers; + } + + // Exch buffers + HipcBufferDescriptor* exch_buffers = NULL; + if (meta.num_exch_buffers) { + exch_buffers = (HipcBufferDescriptor*)base; + base = exch_buffers + meta.num_exch_buffers; + } + + // Data words + u32* data_words = NULL; + if (meta.num_data_words) { + data_words = (u32*)base; + base = data_words + meta.num_data_words; + } + + // Recv list + HipcRecvListEntry* recv_list = NULL; + if (meta.num_recv_statics) + recv_list = (HipcRecvListEntry*)base; + + return (HipcRequest){ + .send_statics = send_statics, + .send_buffers = send_buffers, + .recv_buffers = recv_buffers, + .exch_buffers = exch_buffers, + .data_words = data_words, + .recv_list = recv_list, + .copy_handles = copy_handles, + .move_handles = move_handles, + }; +} + +NX_CONSTEXPR HipcRequest hipcMakeRequest(void* base, HipcMetadata meta) +{ + // Write message header + bool has_special_header = meta.send_pid || meta.num_copy_handles || meta.num_move_handles; + HipcHeader* hdr = (HipcHeader*)base; + base = hdr+1; + *hdr = (HipcHeader){ + .type = meta.type, + .num_send_statics = meta.num_send_statics, + .num_send_buffers = meta.num_send_buffers, + .num_recv_buffers = meta.num_recv_buffers, + .num_exch_buffers = meta.num_exch_buffers, + .num_data_words = meta.num_data_words, + .recv_static_mode = meta.num_recv_statics ? (meta.num_recv_statics != HIPC_AUTO_RECV_STATIC ? 2u + meta.num_recv_statics : 2u) : 0u, + .padding = 0, + .recv_list_offset = 0, + .has_special_header = has_special_header, + }; + + // Write special header + if (has_special_header) { + HipcSpecialHeader* sphdr = (HipcSpecialHeader*)base; + base = sphdr+1; + *sphdr = (HipcSpecialHeader){ + .send_pid = meta.send_pid, + .num_copy_handles = meta.num_copy_handles, + .num_move_handles = meta.num_move_handles, + }; + if (meta.send_pid) + base = (u8*)base + sizeof(u64); + } + + // Calculate layout + return hipcCalcRequestLayout(meta, base); +} + +#define hipcMakeRequestInline(_base,...) hipcMakeRequest((_base),(HipcMetadata){ __VA_ARGS__ }) + +NX_CONSTEXPR HipcParsedRequest hipcParseRequest(void* base) +{ + // Parse message header + HipcHeader hdr = {}; + __builtin_memcpy(&hdr, base, sizeof(hdr)); + base = (u8*)base + sizeof(hdr); + u32 num_recv_statics = 0; + u64 pid = 0; + + // Parse recv static mode + if (hdr.recv_static_mode) { + if (hdr.recv_static_mode == 2u) + num_recv_statics = HIPC_AUTO_RECV_STATIC; + else if (hdr.recv_static_mode > 2u) + num_recv_statics = hdr.recv_static_mode - 2u; + } + + // Parse special header + HipcSpecialHeader sphdr = {}; + if (hdr.has_special_header) { + __builtin_memcpy(&sphdr, base, sizeof(sphdr)); + base = (u8*)base + sizeof(sphdr); + + // Read PID descriptor + if (sphdr.send_pid) { + pid = *(u64*)base; + base = (u8*)base + sizeof(u64); + } + } + + const HipcMetadata meta = { + .type = hdr.type, + .num_send_statics = hdr.num_send_statics, + .num_send_buffers = hdr.num_send_buffers, + .num_recv_buffers = hdr.num_recv_buffers, + .num_exch_buffers = hdr.num_exch_buffers, + .num_data_words = hdr.num_data_words, + .num_recv_statics = num_recv_statics, + .send_pid = sphdr.send_pid, + .num_copy_handles = sphdr.num_copy_handles, + .num_move_handles = sphdr.num_move_handles, + }; + + return (HipcParsedRequest){ + .meta = meta, + .data = hipcCalcRequestLayout(meta, base), + .pid = pid, + }; +} + +NX_CONSTEXPR HipcResponse hipcParseResponse(void* base) +{ + // Parse header + HipcHeader hdr = {}; + __builtin_memcpy(&hdr, base, sizeof(hdr)); + base = (u8*)base + sizeof(hdr); + + // Initialize response + HipcResponse response = {}; + response.num_statics = hdr.num_send_statics; + response.num_data_words = hdr.num_data_words; + response.pid = HIPC_RESPONSE_NO_PID; + + // Parse special header + if (hdr.has_special_header) + { + HipcSpecialHeader sphdr = {}; + __builtin_memcpy(&sphdr, base, sizeof(sphdr)); + base = (u8*)base + sizeof(sphdr); + + // Update response + response.num_copy_handles = sphdr.num_copy_handles; + response.num_move_handles = sphdr.num_move_handles; + + // Parse PID descriptor + if (sphdr.send_pid) { + response.pid = *(u64*)base; + base = (u8*)base + sizeof(u64); + } + } + + // Copy handles + response.copy_handles = (Handle*)base; + base = response.copy_handles + response.num_copy_handles; + + // Move handles + response.move_handles = (Handle*)base; + base = response.move_handles + response.num_move_handles; + + // Send statics + response.statics = (HipcStaticDescriptor*)base; + base = response.statics + response.num_statics; + + // Data words + response.data_words = (u32*)base; + + return response; +} diff --git a/nx/include/switch/sf/service.h b/nx/include/switch/sf/service.h new file mode 100644 index 00000000..f8cfc359 --- /dev/null +++ b/nx/include/switch/sf/service.h @@ -0,0 +1,417 @@ +/** + * @file service.h + * @brief Service wrapper object + * @author fincs + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "hipc.h" +#include "cmif.h" + +/// Service object structure +typedef struct Service +{ + Handle session; + u32 own_handle; + u32 object_id; + u16 pointer_buffer_size; +} Service; + +enum +{ + SfBufferAttr_In = BIT(0), + SfBufferAttr_Out = BIT(1), + SfBufferAttr_HipcMapAlias = BIT(2), + SfBufferAttr_HipcPointer = BIT(3), + SfBufferAttr_FixedSize = BIT(4), + SfBufferAttr_HipcAutoSelect = BIT(5), + SfBufferAttr_HipcMapTransferAllowsNonSecure = BIT(6), + SfBufferAttr_HipcMapTransferAllowsNonDevice = BIT(7), +}; + +typedef struct SfBufferAttrs { + u32 attr0; + u32 attr1; + u32 attr2; + u32 attr3; + u32 attr4; + u32 attr5; + u32 attr6; + u32 attr7; +} SfBufferAttrs; + +typedef struct SfBuffer +{ + const void* ptr; + size_t size; +} SfBuffer; + +typedef enum SfOutHandleAttr { + SfOutHandleAttr_None = 0, + SfOutHandleAttr_HipcCopy = 1, + SfOutHandleAttr_HipcMove = 2, +} SfOutHandleAttr; + +typedef struct SfOutHandleAttrs +{ + SfOutHandleAttr attr0; + SfOutHandleAttr attr1; + SfOutHandleAttr attr2; + SfOutHandleAttr attr3; + SfOutHandleAttr attr4; + SfOutHandleAttr attr5; + SfOutHandleAttr attr6; + SfOutHandleAttr attr7; +} SfOutHandleAttrs; + +typedef struct SfDispatchParams +{ + Handle target_session; + + SfBufferAttrs buffer_attrs; + SfBuffer buffers[8]; + + bool in_send_pid; + + u32 in_num_objects; + const Service* in_objects[8]; + + u32 in_num_handles; + Handle in_handles[8]; + + u32 out_num_objects; + Service* out_objects; + + SfOutHandleAttrs out_handle_attrs; + Handle* out_handles; +} SfDispatchParams; + +/** + * @brief Returns whether a service has been initialized. + * @param[in] s Service object. + * @return true if initialized. + */ +NX_CONSTEXPR bool serviceIsActive(Service* s) { + return s->session != INVALID_HANDLE; +} + +/** + * @brief Returns whether a service is overriden in the homebrew environment. + * @param[in] s Service object. + * @return true if overriden. + */ +NX_CONSTEXPR bool serviceIsOverride(Service* s) { + return serviceIsActive(s) && !s->own_handle && !s->object_id; +} + +/** + * @brief Returns whether a service is a domain. + * @param[in] s Service object. + * @return true if a domain. + */ +NX_CONSTEXPR bool serviceIsDomain(Service* s) { + return serviceIsActive(s) && s->own_handle && s->object_id; +} + +/** + * @brief Returns whether a service is a domain subservice. + * @param[in] s Service object. + * @return true if a domain subservice. + */ +NX_CONSTEXPR bool serviceIsDomainSubservice(Service* s) { + return serviceIsActive(s) && !s->own_handle && s->object_id; +} + +/** + * @brief For a domain/domain subservice, return the associated object ID. + * @param[in] s Service object, necessarily a domain or domain subservice. + * @return The object ID. + */ +NX_CONSTEXPR u32 serviceGetObjectId(Service* s) { + return s->object_id; +} + +/** + * @brief Creates a service object from an IPC session handle. + * @param[out] s Service object. + * @param[in] h IPC session handle. + */ +NX_INLINE void serviceCreate(Service* s, Handle h) +{ + s->session = h; + s->own_handle = 1; + s->object_id = 0; + s->pointer_buffer_size = 0; + cmifQueryPointerBufferSize(h, &s->pointer_buffer_size); +} + +/** + * @brief Creates a domain subservice object from a parent service. + * @param[out] s Service object. + * @param[in] parent Parent service, necessarily a domain or domain subservice. + * @param[in] object_id Object ID for this subservice. + */ +NX_CONSTEXPR void serviceCreateDomainSubservice(Service* s, Service* parent, u32 object_id) +{ + s->session = parent->session; + s->own_handle = 0; + s->object_id = object_id; + s->pointer_buffer_size = parent->pointer_buffer_size; +} + +/** + * @brief Closes a service. + * @param[in] s Service object. + */ +NX_INLINE void serviceClose(Service* s) +{ + if (s->own_handle || s->object_id) { + cmifMakeCloseRequest(armGetTls(), s->own_handle ? 0 : s->object_id); + svcSendSyncRequest(s->session); + if (s->own_handle) + svcCloseHandle(s->session); + } + *s = (Service){}; +} + +/** + * @brief Clones a service. + * @param[in] s Service object. + * @param[out] out_s Output service object. + */ +NX_INLINE Result serviceClone(Service* s, Service* out_s) +{ + out_s->session = 0; + out_s->own_handle = 1; + out_s->object_id = s->object_id; + out_s->pointer_buffer_size = s->pointer_buffer_size; + return cmifCloneCurrentObjectEx(s->session, 0, &out_s->session); +} + +/** + * @brief Converts a regular service to a domain. + * @param[in] s Service object. + * @return Result code. + */ +NX_INLINE Result serviceConvertToDomain(Service* s) +{ + if (s->object_id) + return 0; // Nothing to do + + if (!s->own_handle) + { + // For overridden services, create a clone first. + Result rc = cmifCloneCurrentObjectEx(s->session, 0, &s->session); + if (R_FAILED(rc)) + return rc; + s->own_handle = 1; + } + + return cmifConvertCurrentObjectToDomain(s->session, &s->object_id); +} + +NX_CONSTEXPR void _serviceRequestFormatProcessBuffer(CmifRequestFormat* fmt, u32 attr) +{ + if (!attr) return; + const bool is_in = (attr & SfBufferAttr_In) != 0; + const bool is_out = (attr & SfBufferAttr_Out) != 0; + + if (attr & SfBufferAttr_HipcAutoSelect) { + if (is_in) + fmt->num_in_auto_buffers ++; + if (is_out) + fmt->num_out_auto_buffers ++; + } else if (attr & SfBufferAttr_HipcPointer) { + if (is_in) + fmt->num_in_pointers ++; + if (is_out) { + if (attr & SfBufferAttr_FixedSize) + fmt->num_out_fixed_pointers ++; + else + fmt->num_out_pointers ++; + } + } else if (attr & SfBufferAttr_HipcMapAlias) { + if (is_in && is_out) + fmt->num_inout_buffers ++; + else if (is_in) + fmt->num_in_buffers ++; + else if (is_out) + fmt->num_out_buffers ++; + } +} + +NX_CONSTEXPR void _serviceRequestProcessBuffer(CmifRequest* req, const SfBuffer* buf, u32 attr) +{ + if (!attr) return; + const bool is_in = (attr & SfBufferAttr_In); + const bool is_out = (attr & SfBufferAttr_Out); + + if (attr & SfBufferAttr_HipcAutoSelect) { + if (is_in) + cmifRequestInAutoBuffer(req, buf->ptr, buf->size); + if (is_out) + cmifRequestOutAutoBuffer(req, (void*)buf->ptr, buf->size); + } else if (attr & SfBufferAttr_HipcPointer) { + if (is_in) + cmifRequestInPointer(req, buf->ptr, buf->size); + if (is_out) { + if (attr & SfBufferAttr_FixedSize) + cmifRequestOutFixedPointer(req, (void*)buf->ptr, buf->size); + else + cmifRequestOutPointer(req, (void*)buf->ptr, buf->size); + } + } else if (attr & SfBufferAttr_HipcMapAlias) { + HipcBufferMode mode = HipcBufferMode_Normal; + if (attr & SfBufferAttr_HipcMapTransferAllowsNonSecure) + mode = HipcBufferMode_NonSecure; + if (attr & SfBufferAttr_HipcMapTransferAllowsNonDevice) + mode = HipcBufferMode_NonDevice; + + if (is_in && is_out) + cmifRequestInOutBuffer(req, (void*)buf->ptr, buf->size, mode); + else if (is_in) + cmifRequestInBuffer(req, buf->ptr, buf->size, mode); + else if (is_out) + cmifRequestOutBuffer(req, (void*)buf->ptr, buf->size, mode); + } +} + +NX_INLINE void* serviceMakeRequest( + Service* s, u32 request_id, u32 data_size, bool send_pid, + const SfBufferAttrs buffer_attrs, const SfBuffer* buffers, + u32 num_objects, const Service* const* objects, + u32 num_handles, const Handle* handles +) { + CmifRequestFormat fmt = {}; + fmt.object_id = s->object_id; + fmt.request_id = request_id; + fmt.data_size = data_size; + fmt.server_pointer_size = s->pointer_buffer_size; + fmt.num_objects = num_objects; + fmt.num_handles = num_handles; + fmt.send_pid = send_pid; + + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr0); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr1); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr2); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr3); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr4); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr5); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr6); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr7); + + CmifRequest req = cmifMakeRequest(armGetTls(), fmt); + + if (s->object_id) // TODO: Check behavior of input objects in non-domain sessions + for (u32 i = 0; i < num_objects; i ++) + cmifRequestObject(&req, objects[i]->object_id); + + for (u32 i = 0; i < num_handles; i ++) + cmifRequestHandle(&req, handles[i]); + + _serviceRequestProcessBuffer(&req, &buffers[0], buffer_attrs.attr0); + _serviceRequestProcessBuffer(&req, &buffers[1], buffer_attrs.attr1); + _serviceRequestProcessBuffer(&req, &buffers[2], buffer_attrs.attr2); + _serviceRequestProcessBuffer(&req, &buffers[3], buffer_attrs.attr3); + _serviceRequestProcessBuffer(&req, &buffers[4], buffer_attrs.attr4); + _serviceRequestProcessBuffer(&req, &buffers[5], buffer_attrs.attr5); + _serviceRequestProcessBuffer(&req, &buffers[6], buffer_attrs.attr6); + _serviceRequestProcessBuffer(&req, &buffers[7], buffer_attrs.attr7); + + return req.data; +} + +NX_CONSTEXPR void _serviceResponseGetHandle(CmifResponse* res, SfOutHandleAttr type, Handle* out) +{ + switch (type) + { + default: + case SfOutHandleAttr_None: + break; + case SfOutHandleAttr_HipcCopy: + *out = cmifResponseGetCopyHandle(res); + break; + case SfOutHandleAttr_HipcMove: + *out = cmifResponseGetMoveHandle(res); + break; + } +} + +NX_INLINE Result serviceParseResponse( + Service* s, u32 out_size, void** out_data, + u32 num_out_objects, Service* out_objects, + const SfOutHandleAttrs out_handle_attrs, Handle* out_handles +) { + CmifResponse res = {}; + bool is_domain = s->object_id != 0; + Result rc = cmifParseResponse(&res, armGetTls(), is_domain, out_size); + if (R_FAILED(rc)) + return rc; + + if (out_size) + *out_data = res.data; + + for (u32 i = 0; i < num_out_objects; i ++) + { + if (is_domain) + serviceCreateDomainSubservice(&out_objects[i], s, cmifResponseGetObject(&res)); + else // Output objects are marshalled as move handles at the beginning of the list. + serviceCreate(&out_objects[i], cmifResponseGetMoveHandle(&res)); + } + + _serviceResponseGetHandle(&res, out_handle_attrs.attr0, &out_handles[0]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr1, &out_handles[1]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr2, &out_handles[2]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr3, &out_handles[3]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr4, &out_handles[4]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr5, &out_handles[5]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr6, &out_handles[6]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr7, &out_handles[7]); + + return 0; +} + +NX_INLINE Result serviceDispatchImpl( + Service* s, u32 request_id, + const void* in_data, u32 in_data_size, + void* out_data, u32 out_data_size, + SfDispatchParams disp +) +{ + void* in = serviceMakeRequest(s, request_id, + in_data_size, disp.in_send_pid, + disp.buffer_attrs, disp.buffers, + disp.in_num_objects, disp.in_objects, + disp.in_num_handles, disp.in_handles); + + if (in_data_size) + __builtin_memcpy(in, in_data, in_data_size); + + Result rc = svcSendSyncRequest(disp.target_session == INVALID_HANDLE ? s->session : disp.target_session); + if (R_SUCCEEDED(rc)) + { + void* out = NULL; + rc = serviceParseResponse(s, + out_data_size, &out, + disp.out_num_objects, disp.out_objects, + disp.out_handle_attrs, disp.out_handles); + + if (R_SUCCEEDED(rc) && out_data_size) + __builtin_memcpy(out_data, out, out_data_size); + } + + return rc; +} + +#define serviceDispatch(_s,_rid,...) \ + serviceDispatchImpl((_s),(_rid),NULL,0,NULL,0,(SfDispatchParams){ __VA_ARGS__ }) + +#define serviceDispatchIn(_s,_rid,_in,...) \ + serviceDispatchImpl((_s),(_rid),&(_in),sizeof(_in),NULL,0,(SfDispatchParams){ __VA_ARGS__ }) + +#define serviceDispatchOut(_s,_rid,_out,...) \ + serviceDispatchImpl((_s),(_rid),NULL,0,&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) + +#define serviceDispatchInOut(_s,_rid,_in,_out,...) \ + serviceDispatchImpl((_s),(_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) diff --git a/nx/source/display/binder.c b/nx/source/display/binder.c index f757dde8..3d0ad528 100644 --- a/nx/source/display/binder.c +++ b/nx/source/display/binder.c @@ -51,12 +51,6 @@ Result binderInitSession(Binder* b, Service* relay) b->initialized = true; - rc = ipcQueryPointerBufferSize(b->relay->handle, &b->ipc_buffer_size); - if (R_FAILED(rc)) { - binderClose(b); - return rc; - } - // Use TransactParcelAuto when available. if (hosversionAtLeast(3,0,0)) b->has_transact_auto = true; @@ -148,8 +142,8 @@ static Result _binderTransactParcelAuto( u32 flags; } PACKED *raw; - ipcAddSendSmart(&c, b->ipc_buffer_size, parcel_data, parcel_data_size, 0); - ipcAddRecvSmart(&c, b->ipc_buffer_size, parcel_reply, parcel_reply_size, 0); + ipcAddSendSmart(&c, b->relay->pointer_buffer_size, parcel_data, parcel_data_size, 0); + ipcAddRecvSmart(&c, b->relay->pointer_buffer_size, parcel_reply, parcel_reply_size, 0); raw = _binderIpcPrepareHeader(b, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index 2f74fa44..ce2fe5cf 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -50,9 +50,6 @@ static Service g_appletIAudioController; static Service g_appletIDisplayController; static Service g_appletIDebugFunctions; -static size_t g_appletIAppletCommonFunctions_ptrbufsize; -static size_t g_appletISelfController_ptrbufsize; - static Event g_appletMessageEvent; static u64 g_appletResourceUserId = 0; @@ -192,7 +189,6 @@ Result appletInitialize(void) if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) { if (__nx_applet_type == AppletType_SystemApplet || __nx_applet_type == AppletType_LibraryApplet || __nx_applet_type == AppletType_OverlayApplet) { rc = _appletGetSession(&g_appletProxySession, &g_appletIAppletCommonFunctions, __nx_applet_type == AppletType_SystemApplet ? 23 : 21); - if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_appletIAppletCommonFunctions.handle, &g_appletIAppletCommonFunctions_ptrbufsize); } } @@ -243,9 +239,6 @@ Result appletInitialize(void) if (R_SUCCEEDED(rc)) rc = _appletGetSession(&g_appletProxySession, &g_appletIDebugFunctions, 1000); - if (R_SUCCEEDED(rc)) - rc = ipcQueryPointerBufferSize(g_appletISelfController.handle, &g_appletISelfController_ptrbufsize); - Result rc2 = _appletGetAccumulatedSuspendedTickChangedEvent(&g_appletSuspendedTickEvent); if (R_SUCCEEDED(rc2)) { g_appletInitTickBase = armGetSystemTick(); @@ -2090,7 +2083,7 @@ Result appletSetApplicationAlbumUserData(const void* buffer, size_t size) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_appletISelfController_ptrbufsize, buffer, size, 0); + ipcAddSendSmart(&c, g_appletISelfController.pointer_buffer_size, buffer, size, 0); struct { u64 magic; @@ -3240,7 +3233,6 @@ Result appletStorageGetSize(AppletStorage *s, s64 *size) { static Result _appletStorageRW(AppletStorage *s, s64 offset, void* buffer, size_t size, bool rw) { Result rc=0; - size_t ipcbufsize=0; Service tmp_srv;//IStorageAccessor if (!serviceIsActive(&s->s)) @@ -3249,9 +3241,7 @@ static Result _appletStorageRW(AppletStorage *s, s64 offset, void* buffer, size_ rc = _appletGetSession(&s->s, &tmp_srv, 0);//Open if (R_FAILED(rc)) return rc; - rc = ipcQueryPointerBufferSize(tmp_srv.handle, &ipcbufsize); - - if (R_SUCCEEDED(rc)) rc = _appletStorageAccessorRW(&tmp_srv, ipcbufsize, offset, buffer, size, rw); + if (R_SUCCEEDED(rc)) rc = _appletStorageAccessorRW(&tmp_srv, tmp_srv.pointer_buffer_size, offset, buffer, size, rw); serviceClose(&tmp_srv); return rc; @@ -5442,7 +5432,7 @@ Result appletReadThemeStorage(void* buffer, size_t size, u64 offset, size_t *tra IpcCommand c; ipcInitialize(&c); - ipcAddRecvSmart(&c, g_appletIAppletCommonFunctions_ptrbufsize, buffer, size, 0); + ipcAddRecvSmart(&c, g_appletIAppletCommonFunctions.pointer_buffer_size, buffer, size, 0); struct { u64 magic; @@ -5484,7 +5474,7 @@ Result appletWriteThemeStorage(const void* buffer, size_t size, u64 offset) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_appletIAppletCommonFunctions_ptrbufsize, buffer, size, 0); + ipcAddSendSmart(&c, g_appletIAppletCommonFunctions.pointer_buffer_size, buffer, size, 0); struct { u64 magic; diff --git a/nx/source/services/auddev.c b/nx/source/services/auddev.c index 38a448ae..6e075abf 100644 --- a/nx/source/services/auddev.c +++ b/nx/source/services/auddev.c @@ -11,7 +11,6 @@ static Service g_auddevIAudioDevice; static u64 g_auddevRefCnt; -static size_t g_auddevIpcBufferSize; static Result _auddevGetAudioDeviceService(Service* srv, Service* out_srv, u64 aruid); @@ -32,8 +31,6 @@ Result auddevInitialize(void) { rc = _auddevGetAudioDeviceService(&audrenMgrSrv, &g_auddevIAudioDevice, aruid); serviceClose(&audrenMgrSrv); - - if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_auddevIAudioDevice.handle, &g_auddevIpcBufferSize); } if (R_FAILED(rc)) auddevExit(); @@ -102,7 +99,7 @@ Result auddevListAudioDeviceName(AudioDeviceName *DeviceNames, s32 max_names, s3 } *raw; if (!new_cmd) ipcAddRecvBuffer(&c, DeviceNames, sizeof(AudioDeviceName) * max_names, BufferType_Normal); - if (new_cmd) ipcAddRecvSmart(&c, g_auddevIpcBufferSize, DeviceNames, sizeof(AudioDeviceName) * max_names, 0); + if (new_cmd) ipcAddRecvSmart(&c, g_auddevIAudioDevice.pointer_buffer_size, DeviceNames, sizeof(AudioDeviceName) * max_names, 0); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw)); @@ -144,7 +141,7 @@ Result auddevSetAudioDeviceOutputVolume(const AudioDeviceName *DeviceName, float } *raw; if (!new_cmd) ipcAddSendBuffer(&c, DeviceName, sizeof(AudioDeviceName), BufferType_Normal); - if (new_cmd) ipcAddSendSmart(&c, g_auddevIpcBufferSize, DeviceName, sizeof(AudioDeviceName), 0); + if (new_cmd) ipcAddSendSmart(&c, g_auddevIAudioDevice.pointer_buffer_size, DeviceName, sizeof(AudioDeviceName), 0); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw)); @@ -183,7 +180,7 @@ Result auddevGetAudioDeviceOutputVolume(const AudioDeviceName *DeviceName, float } *raw; if (!new_cmd) ipcAddSendBuffer(&c, DeviceName, sizeof(AudioDeviceName), BufferType_Normal); - if (new_cmd) ipcAddSendSmart(&c, g_auddevIpcBufferSize, DeviceName, sizeof(AudioDeviceName), 0); + if (new_cmd) ipcAddSendSmart(&c, g_auddevIAudioDevice.pointer_buffer_size, DeviceName, sizeof(AudioDeviceName), 0); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw)); diff --git a/nx/source/services/bsd.c b/nx/source/services/bsd.c index 62ac7f3c..5a6d3253 100644 --- a/nx/source/services/bsd.c +++ b/nx/source/services/bsd.c @@ -24,7 +24,6 @@ __thread Result g_bsdResult; __thread int g_bsdErrno; static Service g_bsdSrv; -static size_t g_bsdSrvIpcBufferSize; static Service g_bsdMonitor; static u64 g_bsdClientPid = -1; @@ -189,7 +188,7 @@ static int _bsdNameGetterCommand(u32 cmd_id, int sockfd, struct sockaddr *addr, socklen_t maxaddrlen = addrlen == NULL ? 0 : *addrlen; - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, addr, maxaddrlen, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, addr, maxaddrlen, 0); struct { u64 magic; @@ -247,9 +246,6 @@ Result bsdInitialize(const BsdInitConfig *config) { } if(R_FAILED(rc)) goto error; - rc = ipcQueryPointerBufferSize(g_bsdSrv.handle, &g_bsdSrvIpcBufferSize); - if(R_FAILED(rc)) goto error; - rc = smGetService(&g_bsdMonitor, bsd_srv); if(R_FAILED(rc)) goto error; @@ -270,7 +266,6 @@ error: } void bsdExit(void) { - g_bsdSrvIpcBufferSize = 0; g_bsdClientPid = 0; serviceClose(&g_bsdMonitor); serviceClose(&g_bsdSrv); @@ -294,7 +289,7 @@ int bsdOpen(const char *pathname, int flags) { ipcInitialize(&c); size_t pathlen = strlen(pathname) + 1; - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, pathname, pathlen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, pathname, pathlen, 0); struct { u64 magic; @@ -315,15 +310,15 @@ int bsdSelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, st IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3); struct { @@ -349,8 +344,8 @@ int bsdPoll(struct pollfd *fds, nfds_t nfds, int timeout) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, fds, nfds * sizeof(struct pollfd), 0); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, fds, nfds * sizeof(struct pollfd), 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, fds, nfds * sizeof(struct pollfd), 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, fds, nfds * sizeof(struct pollfd), 0); struct { u64 magic; @@ -375,10 +370,10 @@ int bsdSysctl(const int *name, unsigned int namelen, void *oldp, size_t *oldlenp ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, name, 4 * namelen, 0); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, newp, newlen, 1); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, name, 4 * namelen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, newp, newlen, 1); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, oldp, inlen, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, oldp, inlen, 0); struct { u64 magic; @@ -405,7 +400,7 @@ int bsdSysctl(const int *name, unsigned int namelen, void *oldp, size_t *oldlenp ssize_t bsdRecv(int sockfd, void *buf, size_t len, int flags) { IpcCommand c; ipcInitialize(&c); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0); struct { u64 magic; @@ -430,8 +425,8 @@ ssize_t bsdRecvFrom(int sockfd, void *buf, size_t len, int flags, struct sockadd ipcInitialize(&c); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, src_addr, inaddrlen, 1); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, src_addr, inaddrlen, 1); struct { u64 magic; @@ -453,7 +448,7 @@ ssize_t bsdRecvFrom(int sockfd, void *buf, size_t len, int flags, struct sockadd ssize_t bsdSend(int sockfd, const void* buf, size_t len, int flags) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0); struct { u64 magic; @@ -475,8 +470,8 @@ ssize_t bsdSend(int sockfd, const void* buf, size_t len, int flags) { ssize_t bsdSendTo(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, dest_addr, addrlen, 1); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, dest_addr, addrlen, 1); struct { u64 magic; @@ -502,7 +497,7 @@ int bsdAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int bsdBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, addr, addrlen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, addr, addrlen, 0); struct { u64 magic; @@ -522,7 +517,7 @@ int bsdBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { int bsdConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, addr, addrlen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, addr, addrlen, 0); struct { u64 magic; @@ -553,7 +548,7 @@ int bsdGetSockOpt(int sockfd, int level, int optname, void *optval, socklen_t *o socklen_t inoptlen = optlen == NULL ? 0 : *optlen; - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, optval, inoptlen, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, optval, inoptlen, 0); struct { u64 magic; @@ -645,15 +640,15 @@ int bsdIoctl(int fd, int request, void *data) { ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in1, in1sz, 0); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in2, in2sz, 1); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in3, in3sz, 2); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in4, in4sz, 3); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in1, in1sz, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in2, in2sz, 1); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in3, in3sz, 2); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in4, in4sz, 3); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out1, out1sz, 0); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out2, out2sz, 1); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out3, out3sz, 2); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out4, out4sz, 3); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out1, out1sz, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out2, out2sz, 1); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out3, out3sz, 2); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out4, out4sz, 3); struct { u64 magic; @@ -711,7 +706,7 @@ int bsdSetSockOpt(int sockfd, int level, int optname, const void *optval, sockle IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, optval, optlen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, optval, optlen, 0); struct { u64 magic; @@ -775,7 +770,7 @@ int bsdShutdownAllSockets(int how) { ssize_t bsdWrite(int fd, const void *buf, size_t count) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, count, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, count, 0); struct { u64 magic; @@ -795,7 +790,7 @@ ssize_t bsdWrite(int fd, const void *buf, size_t count) { ssize_t bsdRead(int fd, void *buf, size_t count) { IpcCommand c; ipcInitialize(&c); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, count, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, count, 0); struct { u64 magic; diff --git a/nx/source/services/hiddbg.c b/nx/source/services/hiddbg.c index c57162cb..7d2a84bd 100644 --- a/nx/source/services/hiddbg.c +++ b/nx/source/services/hiddbg.c @@ -11,7 +11,6 @@ static Service g_hiddbgSrv; static u64 g_hiddbgRefCnt; -static size_t g_hiddbgPtrbufsize; static bool g_hiddbgHdlsInitialized; static TransferMemory g_hiddbgHdlsTmem; @@ -49,8 +48,6 @@ Result hiddbgInitialize(void) { Result rc = smGetService(&g_hiddbgSrv, "hid:dbg"); - if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_hiddbgSrv.handle, &g_hiddbgPtrbufsize); - if (R_FAILED(rc)) hiddbgExit(); return rc; @@ -463,7 +460,7 @@ Result hiddbgGetAbstractedPadsState(u64 *AbstractedPadHandles, HiddbgAbstractedP } *raw; ipcAddRecvStatic(&c, AbstractedPadHandles, sizeof(u64)*count, 0); - ipcAddRecvSmart(&c, g_hiddbgPtrbufsize, states, sizeof(HiddbgAbstractedPadState)*count, 0); + ipcAddRecvSmart(&c, g_hiddbgSrv.pointer_buffer_size, states, sizeof(HiddbgAbstractedPadState)*count, 0); raw = serviceIpcPrepareHeader(&g_hiddbgSrv, &c, sizeof(*raw)); diff --git a/nx/source/services/i2c.c b/nx/source/services/i2c.c index 75dae96d..3f667f4b 100644 --- a/nx/source/services/i2c.c +++ b/nx/source/services/i2c.c @@ -6,20 +6,17 @@ #include "services/sm.h" static Service g_i2cSrv; -static size_t g_i2cSrvPtrBufSize; static u64 g_refCnt; Result i2cInitialize(void) { Result rc = 0; - + atomicIncrement64(&g_refCnt); if (serviceIsActive(&g_i2cSrv)) return 0; rc = smGetService(&g_i2cSrv, "i2c"); - - if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_i2cSrv.handle, &g_i2cSrvPtrBufSize); if (R_FAILED(rc)) i2cExit(); @@ -28,7 +25,6 @@ Result i2cInitialize(void) { void i2cExit(void) { if (atomicDecrement64(&g_refCnt) == 0) { - g_i2cSrvPtrBufSize = 0; serviceClose(&g_i2cSrv); } } @@ -78,7 +74,7 @@ Result i2cOpenSession(I2cSession *out, I2cDevice dev) { Result i2csessionSendAuto(I2cSession *s, const void *buf, size_t size, I2cTransactionOption option) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_i2cSrvPtrBufSize, buf, size, 0); + ipcAddSendSmart(&c, s->s.pointer_buffer_size, buf, size, 0); struct { u64 magic; @@ -113,7 +109,7 @@ Result i2csessionSendAuto(I2cSession *s, const void *buf, size_t size, I2cTransa Result i2csessionReceiveAuto(I2cSession *s, void *buf, size_t size, I2cTransactionOption option) { IpcCommand c; ipcInitialize(&c); - ipcAddRecvSmart(&c, g_i2cSrvPtrBufSize, buf, size, 0); + ipcAddRecvSmart(&c, s->s.pointer_buffer_size, buf, size, 0); struct { u64 magic; @@ -149,7 +145,7 @@ Result i2csessionExecuteCommandList(I2cSession *s, void *dst, size_t dst_size, c IpcCommand c; ipcInitialize(&c); ipcAddSendStatic(&c, cmd_list, cmd_list_size, 0); - ipcAddRecvSmart(&c, g_i2cSrvPtrBufSize, dst, dst_size, 0); + ipcAddRecvSmart(&c, s->s.pointer_buffer_size, dst, dst_size, 0); struct { u64 magic; diff --git a/nx/source/services/nv.c b/nx/source/services/nv.c index fcf5cd09..319f6be9 100644 --- a/nx/source/services/nv.c +++ b/nx/source/services/nv.c @@ -51,8 +51,7 @@ Result nvInitialize(void) } if (R_SUCCEEDED(rc)) { - g_nvIpcBufferSize = 0; - rc = ipcQueryPointerBufferSize(g_nvSrv.handle, &g_nvIpcBufferSize); + g_nvIpcBufferSize = g_nvSrv.pointer_buffer_size; if (R_SUCCEEDED(rc)) rc = tmemCreate(&g_nvTransfermem, __nx_nv_transfermem_size, Perm_None); @@ -63,7 +62,7 @@ Result nvInitialize(void) // Clone the session handle - the cloned session is used to execute certain commands in parallel Handle nv_clone = INVALID_HANDLE; if (R_SUCCEEDED(rc)) - rc = ipcCloneSession(g_nvSrv.handle, 1, &nv_clone); + rc = ipcCloneSession(g_nvSrv.session, 1, &nv_clone); if (R_SUCCEEDED(rc)) serviceCreate(&g_nvSrvClone, nv_clone); diff --git a/nx/source/services/sm.c b/nx/source/services/sm.c index 445b1658..3954ede0 100644 --- a/nx/source/services/sm.c +++ b/nx/source/services/sm.c @@ -68,37 +68,11 @@ Result smInitialize(void) Handle tmp; if (R_SUCCEEDED(rc) && smGetServiceOriginal(&tmp, smEncodeName("")) == 0x415) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); + const struct { + u64 pid_placeholder; + } in = { 0 }; - struct { - u64 magic; - u64 cmd_id; - u64 zero; - u64 reserved[2]; - } *raw; - - raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->zero = 0; - - rc = serviceIpcDispatch(&g_smSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - serviceIpcParse(&g_smSrv, &r, sizeof(*resp)); - - resp = r.Raw; - rc = resp->result; - } + rc = serviceDispatchIn(&g_smSrv, 0, in, .in_send_pid = true); } if (R_FAILED(rc)) @@ -140,141 +114,55 @@ Result smGetService(Service* service_out, const char* name) { u64 name_encoded = smEncodeName(name); Handle handle = smGetServiceOverride(name_encoded); - Result rc; if (handle != INVALID_HANDLE) { - service_out->type = ServiceType_Override; - service_out->handle = handle; - rc = 0; + serviceCreate(service_out, handle); + service_out->own_handle = 0; + return 0; } - else - { - rc = smGetServiceOriginal(&handle, name_encoded); - if (R_SUCCEEDED(rc)) - { - service_out->type = ServiceType_Normal; - service_out->handle = handle; - } - } + Result rc = smGetServiceOriginal(&handle, name_encoded); + if (R_SUCCEEDED(rc)) + serviceCreate(service_out, handle); return rc; } Result smGetServiceOriginal(Handle* handle_out, u64 name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u64 service_name; - u64 reserved[2]; - } *raw; + } in = { name }; - raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->service_name = name; - - Result rc = serviceIpcDispatch(&g_smSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - serviceIpcParse(&g_smSrv, &r, sizeof(*resp)); - - resp = r.Raw; - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - } - } - - return rc; + return serviceDispatchIn(&g_smSrv, 1, in, + .out_handle_attrs = { SfOutHandleAttr_HipcMove }, + .out_handles = handle_out, + ); } -Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; +Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions) +{ + const struct { u64 service_name; u32 is_light; u32 max_sessions; - } *raw; + } in = { smEncodeName(name), !!is_light, max_sessions }; - raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - raw->service_name = smEncodeName(name); - raw->is_light = !!is_light; - raw->max_sessions = max_sessions; - - Result rc = serviceIpcDispatch(&g_smSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - serviceIpcParse(&g_smSrv, &r, sizeof(*resp)); - - resp = r.Raw; - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - } - } - - return rc; + return serviceDispatchIn(&g_smSrv, 2, in, + .out_handle_attrs = { SfOutHandleAttr_HipcMove }, + .out_handles = handle_out, + ); } -Result smUnregisterService(const char* name) { +Result smUnregisterService(const char* name) +{ IpcCommand c; ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; + const struct { u64 service_name; - u64 reserved; - } *raw; + } in = { smEncodeName(name) }; - raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->service_name = smEncodeName(name); - - Result rc = serviceIpcDispatch(&g_smSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - serviceIpcParse(&g_smSrv, &r, sizeof(*resp)); - - resp = r.Raw; - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_smSrv, 3, in); } diff --git a/nx/source/services/usbhs.c b/nx/source/services/usbhs.c index 09630586..650ee5df 100644 --- a/nx/source/services/usbhs.c +++ b/nx/source/services/usbhs.c @@ -725,8 +725,6 @@ Result usbHsIfOpenUsbEp(UsbHsClientIfSession* s, UsbHsClientEpSession* ep, u16 m if (R_SUCCEEDED(rc)) rc = _usbHsGetEvent(&ep->s, &ep->eventXfer, 2); } - if (hosversionAtLeast(3,0,0) && R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(ep->s.handle, &ep->ptrbufsize); - if (R_FAILED(rc)) { serviceClose(&ep->s); eventClose(&ep->eventXfer); @@ -854,7 +852,7 @@ static Result _usbHsEpGetXferReport(UsbHsClientEpSession* s, UsbHsXferReport* re ipcAddRecvBuffer(&c, reports, sizeof(UsbHsXferReport) * max_reports, BufferType_Normal); } else { - ipcAddRecvSmart(&c, s->ptrbufsize, reports, sizeof(UsbHsXferReport) * max_reports, 0); + ipcAddRecvSmart(&c, s->s.pointer_buffer_size, reports, sizeof(UsbHsXferReport) * max_reports, 0); } raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));