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
This commit is contained in:
fincs 2019-09-19 03:50:06 +02:00
parent 0a3592d4dd
commit 6ad0042147
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
16 changed files with 1234 additions and 369 deletions

View File

@ -36,9 +36,13 @@ extern "C" {
#include "switch/kernel/detect.h" #include "switch/kernel/detect.h"
#include "switch/kernel/random.h" #include "switch/kernel/random.h"
#include "switch/kernel/jit.h" #include "switch/kernel/jit.h"
#include "switch/kernel/ipc.h" #include "switch/kernel/ipc.h" // Deprecated
#include "switch/kernel/barrier.h" #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/sm.h"
#include "switch/services/smm.h" #include "switch/services/smm.h"
#include "switch/services/fs.h" #include "switch/services/fs.h"

View File

@ -10,7 +10,7 @@ typedef struct {
bool initialized : 1; bool initialized : 1;
bool has_transact_auto : 1; bool has_transact_auto : 1;
s32 id; s32 id;
size_t ipc_buffer_size; size_t dummy;
Service* relay; Service* relay;
} Binder; } Binder;

View File

@ -9,71 +9,11 @@
#include "../types.h" #include "../types.h"
#include "../kernel/svc.h" #include "../kernel/svc.h"
#include "../kernel/ipc.h" #include "../kernel/ipc.h"
#include "../sf/service.h"
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #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. * @brief Closes a domain object by ID.
* @param[in] s Service object, necessarily a domain or domain subservice. * @param[in] s Service object, necessarily a domain or domain subservice.
@ -82,7 +22,7 @@ static inline u32 serviceGetObjectId(Service* s) {
*/ */
DEPRECATED DEPRECATED
static inline Result serviceCloseObjectById(Service* s, u32 object_id) { 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 DEPRECATED
static inline Result serviceIpcDispatch(Service* s) { static inline Result serviceIpcDispatch(Service* s) {
return ipcDispatch(s->handle); return ipcDispatch(s->session);
}
/**
* @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;
} }
/** /**
@ -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. * @brief Prepares the header of an IPC command structure for a service.
* @param s Service to prepare message header for * @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. * @brief Initializes SM.
* @return Result code. * @return Result code.
@ -308,5 +176,3 @@ u64 smEncodeName(const char* name);
* @param[in] handle IPC session handle. * @param[in] handle IPC session handle.
*/ */
void smAddOverrideHandle(u64 name, Handle handle); void smAddOverrideHandle(u64 name, Handle handle);
#pragma GCC diagnostic pop

View File

@ -96,7 +96,6 @@ typedef struct {
typedef struct { typedef struct {
Service s; Service s;
Event eventXfer; ///< [2.0.0+] Signaled when PostBufferAsync finishes. Event eventXfer; ///< [2.0.0+] Signaled when PostBufferAsync finishes.
size_t ptrbufsize; ///< [3.0.0+] IPC pointer buffer size.
struct usb_endpoint_descriptor desc; struct usb_endpoint_descriptor desc;
} UsbHsClientEpSession; } UsbHsClientEpSession;

362
nx/include/switch/sf/cmif.h Normal file
View File

@ -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;
}

363
nx/include/switch/sf/hipc.h Normal file
View File

@ -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;
}

View File

@ -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__ })

View File

@ -51,12 +51,6 @@ Result binderInitSession(Binder* b, Service* relay)
b->initialized = true; b->initialized = true;
rc = ipcQueryPointerBufferSize(b->relay->handle, &b->ipc_buffer_size);
if (R_FAILED(rc)) {
binderClose(b);
return rc;
}
// Use TransactParcelAuto when available. // Use TransactParcelAuto when available.
if (hosversionAtLeast(3,0,0)) if (hosversionAtLeast(3,0,0))
b->has_transact_auto = true; b->has_transact_auto = true;
@ -148,8 +142,8 @@ static Result _binderTransactParcelAuto(
u32 flags; u32 flags;
} PACKED *raw; } PACKED *raw;
ipcAddSendSmart(&c, b->ipc_buffer_size, parcel_data, parcel_data_size, 0); ipcAddSendSmart(&c, b->relay->pointer_buffer_size, parcel_data, parcel_data_size, 0);
ipcAddRecvSmart(&c, b->ipc_buffer_size, parcel_reply, parcel_reply_size, 0); ipcAddRecvSmart(&c, b->relay->pointer_buffer_size, parcel_reply, parcel_reply_size, 0);
raw = _binderIpcPrepareHeader(b, &c, sizeof(*raw)); raw = _binderIpcPrepareHeader(b, &c, sizeof(*raw));
raw->magic = SFCI_MAGIC; raw->magic = SFCI_MAGIC;

View File

@ -50,9 +50,6 @@ static Service g_appletIAudioController;
static Service g_appletIDisplayController; static Service g_appletIDisplayController;
static Service g_appletIDebugFunctions; static Service g_appletIDebugFunctions;
static size_t g_appletIAppletCommonFunctions_ptrbufsize;
static size_t g_appletISelfController_ptrbufsize;
static Event g_appletMessageEvent; static Event g_appletMessageEvent;
static u64 g_appletResourceUserId = 0; static u64 g_appletResourceUserId = 0;
@ -192,7 +189,6 @@ Result appletInitialize(void)
if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) { if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) {
if (__nx_applet_type == AppletType_SystemApplet || __nx_applet_type == AppletType_LibraryApplet || __nx_applet_type == AppletType_OverlayApplet) { 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); 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)) if (R_SUCCEEDED(rc))
rc = _appletGetSession(&g_appletProxySession, &g_appletIDebugFunctions, 1000); rc = _appletGetSession(&g_appletProxySession, &g_appletIDebugFunctions, 1000);
if (R_SUCCEEDED(rc))
rc = ipcQueryPointerBufferSize(g_appletISelfController.handle, &g_appletISelfController_ptrbufsize);
Result rc2 = _appletGetAccumulatedSuspendedTickChangedEvent(&g_appletSuspendedTickEvent); Result rc2 = _appletGetAccumulatedSuspendedTickChangedEvent(&g_appletSuspendedTickEvent);
if (R_SUCCEEDED(rc2)) { if (R_SUCCEEDED(rc2)) {
g_appletInitTickBase = armGetSystemTick(); g_appletInitTickBase = armGetSystemTick();
@ -2090,7 +2083,7 @@ Result appletSetApplicationAlbumUserData(const void* buffer, size_t size) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_appletISelfController_ptrbufsize, buffer, size, 0); ipcAddSendSmart(&c, g_appletISelfController.pointer_buffer_size, buffer, size, 0);
struct { struct {
u64 magic; 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) { static Result _appletStorageRW(AppletStorage *s, s64 offset, void* buffer, size_t size, bool rw) {
Result rc=0; Result rc=0;
size_t ipcbufsize=0;
Service tmp_srv;//IStorageAccessor Service tmp_srv;//IStorageAccessor
if (!serviceIsActive(&s->s)) 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 rc = _appletGetSession(&s->s, &tmp_srv, 0);//Open
if (R_FAILED(rc)) return rc; if (R_FAILED(rc)) return rc;
rc = ipcQueryPointerBufferSize(tmp_srv.handle, &ipcbufsize); if (R_SUCCEEDED(rc)) rc = _appletStorageAccessorRW(&tmp_srv, tmp_srv.pointer_buffer_size, offset, buffer, size, rw);
if (R_SUCCEEDED(rc)) rc = _appletStorageAccessorRW(&tmp_srv, ipcbufsize, offset, buffer, size, rw);
serviceClose(&tmp_srv); serviceClose(&tmp_srv);
return rc; return rc;
@ -5442,7 +5432,7 @@ Result appletReadThemeStorage(void* buffer, size_t size, u64 offset, size_t *tra
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddRecvSmart(&c, g_appletIAppletCommonFunctions_ptrbufsize, buffer, size, 0); ipcAddRecvSmart(&c, g_appletIAppletCommonFunctions.pointer_buffer_size, buffer, size, 0);
struct { struct {
u64 magic; u64 magic;
@ -5484,7 +5474,7 @@ Result appletWriteThemeStorage(const void* buffer, size_t size, u64 offset) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_appletIAppletCommonFunctions_ptrbufsize, buffer, size, 0); ipcAddSendSmart(&c, g_appletIAppletCommonFunctions.pointer_buffer_size, buffer, size, 0);
struct { struct {
u64 magic; u64 magic;

View File

@ -11,7 +11,6 @@
static Service g_auddevIAudioDevice; static Service g_auddevIAudioDevice;
static u64 g_auddevRefCnt; static u64 g_auddevRefCnt;
static size_t g_auddevIpcBufferSize;
static Result _auddevGetAudioDeviceService(Service* srv, Service* out_srv, u64 aruid); static Result _auddevGetAudioDeviceService(Service* srv, Service* out_srv, u64 aruid);
@ -32,8 +31,6 @@ Result auddevInitialize(void) {
rc = _auddevGetAudioDeviceService(&audrenMgrSrv, &g_auddevIAudioDevice, aruid); rc = _auddevGetAudioDeviceService(&audrenMgrSrv, &g_auddevIAudioDevice, aruid);
serviceClose(&audrenMgrSrv); serviceClose(&audrenMgrSrv);
if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_auddevIAudioDevice.handle, &g_auddevIpcBufferSize);
} }
if (R_FAILED(rc)) auddevExit(); if (R_FAILED(rc)) auddevExit();
@ -102,7 +99,7 @@ Result auddevListAudioDeviceName(AudioDeviceName *DeviceNames, s32 max_names, s3
} *raw; } *raw;
if (!new_cmd) ipcAddRecvBuffer(&c, DeviceNames, sizeof(AudioDeviceName) * max_names, BufferType_Normal); 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)); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw));
@ -144,7 +141,7 @@ Result auddevSetAudioDeviceOutputVolume(const AudioDeviceName *DeviceName, float
} *raw; } *raw;
if (!new_cmd) ipcAddSendBuffer(&c, DeviceName, sizeof(AudioDeviceName), BufferType_Normal); 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)); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw));
@ -183,7 +180,7 @@ Result auddevGetAudioDeviceOutputVolume(const AudioDeviceName *DeviceName, float
} *raw; } *raw;
if (!new_cmd) ipcAddSendBuffer(&c, DeviceName, sizeof(AudioDeviceName), BufferType_Normal); 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)); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw));

View File

@ -24,7 +24,6 @@ __thread Result g_bsdResult;
__thread int g_bsdErrno; __thread int g_bsdErrno;
static Service g_bsdSrv; static Service g_bsdSrv;
static size_t g_bsdSrvIpcBufferSize;
static Service g_bsdMonitor; static Service g_bsdMonitor;
static u64 g_bsdClientPid = -1; 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; 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 { struct {
u64 magic; u64 magic;
@ -247,9 +246,6 @@ Result bsdInitialize(const BsdInitConfig *config) {
} }
if(R_FAILED(rc)) goto error; 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); rc = smGetService(&g_bsdMonitor, bsd_srv);
if(R_FAILED(rc)) goto error; if(R_FAILED(rc)) goto error;
@ -270,7 +266,6 @@ error:
} }
void bsdExit(void) { void bsdExit(void) {
g_bsdSrvIpcBufferSize = 0;
g_bsdClientPid = 0; g_bsdClientPid = 0;
serviceClose(&g_bsdMonitor); serviceClose(&g_bsdMonitor);
serviceClose(&g_bsdSrv); serviceClose(&g_bsdSrv);
@ -294,7 +289,7 @@ int bsdOpen(const char *pathname, int flags) {
ipcInitialize(&c); ipcInitialize(&c);
size_t pathlen = strlen(pathname) + 1; size_t pathlen = strlen(pathname) + 1;
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, pathname, pathlen, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, pathname, pathlen, 0);
struct { struct {
u64 magic; u64 magic;
@ -315,15 +310,15 @@ int bsdSelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, st
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, 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, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, 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, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3);
struct { struct {
@ -349,8 +344,8 @@ int bsdPoll(struct pollfd *fds, nfds_t nfds, int timeout) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&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_bsdSrvIpcBufferSize, fds, nfds * sizeof(struct pollfd), 0); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, fds, nfds * sizeof(struct pollfd), 0);
struct { struct {
u64 magic; u64 magic;
@ -375,10 +370,10 @@ int bsdSysctl(const int *name, unsigned int namelen, void *oldp, size_t *oldlenp
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, name, 4 * namelen, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, name, 4 * namelen, 0);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, newp, newlen, 1); 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 { struct {
u64 magic; 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) { ssize_t bsdRecv(int sockfd, void *buf, size_t len, int flags) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0);
struct { struct {
u64 magic; u64 magic;
@ -430,8 +425,8 @@ ssize_t bsdRecvFrom(int sockfd, void *buf, size_t len, int flags, struct sockadd
ipcInitialize(&c); ipcInitialize(&c);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, src_addr, inaddrlen, 1); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, src_addr, inaddrlen, 1);
struct { struct {
u64 magic; 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) { ssize_t bsdSend(int sockfd, const void* buf, size_t len, int flags) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0);
struct { struct {
u64 magic; 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) { ssize_t bsdSendTo(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, dest_addr, addrlen, 1); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, dest_addr, addrlen, 1);
struct { struct {
u64 magic; 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) { int bsdBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, addr, addrlen, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, addr, addrlen, 0);
struct { struct {
u64 magic; 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) { int bsdConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, addr, addrlen, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, addr, addrlen, 0);
struct { struct {
u64 magic; 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; 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 { struct {
u64 magic; u64 magic;
@ -645,15 +640,15 @@ int bsdIoctl(int fd, int request, void *data) {
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in1, in1sz, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in1, in1sz, 0);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in2, in2sz, 1); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in2, in2sz, 1);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in3, in3sz, 2); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in3, in3sz, 2);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in4, in4sz, 3); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in4, in4sz, 3);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out1, out1sz, 0); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out1, out1sz, 0);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out2, out2sz, 1); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out2, out2sz, 1);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out3, out3sz, 2); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out3, out3sz, 2);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out4, out4sz, 3); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out4, out4sz, 3);
struct { struct {
u64 magic; u64 magic;
@ -711,7 +706,7 @@ int bsdSetSockOpt(int sockfd, int level, int optname, const void *optval, sockle
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, optval, optlen, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, optval, optlen, 0);
struct { struct {
u64 magic; u64 magic;
@ -775,7 +770,7 @@ int bsdShutdownAllSockets(int how) {
ssize_t bsdWrite(int fd, const void *buf, size_t count) { ssize_t bsdWrite(int fd, const void *buf, size_t count) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, count, 0); ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, count, 0);
struct { struct {
u64 magic; 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) { ssize_t bsdRead(int fd, void *buf, size_t count) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, count, 0); ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, count, 0);
struct { struct {
u64 magic; u64 magic;

View File

@ -11,7 +11,6 @@
static Service g_hiddbgSrv; static Service g_hiddbgSrv;
static u64 g_hiddbgRefCnt; static u64 g_hiddbgRefCnt;
static size_t g_hiddbgPtrbufsize;
static bool g_hiddbgHdlsInitialized; static bool g_hiddbgHdlsInitialized;
static TransferMemory g_hiddbgHdlsTmem; static TransferMemory g_hiddbgHdlsTmem;
@ -49,8 +48,6 @@ Result hiddbgInitialize(void) {
Result rc = smGetService(&g_hiddbgSrv, "hid:dbg"); Result rc = smGetService(&g_hiddbgSrv, "hid:dbg");
if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_hiddbgSrv.handle, &g_hiddbgPtrbufsize);
if (R_FAILED(rc)) hiddbgExit(); if (R_FAILED(rc)) hiddbgExit();
return rc; return rc;
@ -463,7 +460,7 @@ Result hiddbgGetAbstractedPadsState(u64 *AbstractedPadHandles, HiddbgAbstractedP
} *raw; } *raw;
ipcAddRecvStatic(&c, AbstractedPadHandles, sizeof(u64)*count, 0); 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)); raw = serviceIpcPrepareHeader(&g_hiddbgSrv, &c, sizeof(*raw));

View File

@ -6,7 +6,6 @@
#include "services/sm.h" #include "services/sm.h"
static Service g_i2cSrv; static Service g_i2cSrv;
static size_t g_i2cSrvPtrBufSize;
static u64 g_refCnt; static u64 g_refCnt;
Result i2cInitialize(void) { Result i2cInitialize(void) {
@ -19,8 +18,6 @@ Result i2cInitialize(void) {
rc = smGetService(&g_i2cSrv, "i2c"); rc = smGetService(&g_i2cSrv, "i2c");
if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_i2cSrv.handle, &g_i2cSrvPtrBufSize);
if (R_FAILED(rc)) i2cExit(); if (R_FAILED(rc)) i2cExit();
return rc; return rc;
@ -28,7 +25,6 @@ Result i2cInitialize(void) {
void i2cExit(void) { void i2cExit(void) {
if (atomicDecrement64(&g_refCnt) == 0) { if (atomicDecrement64(&g_refCnt) == 0) {
g_i2cSrvPtrBufSize = 0;
serviceClose(&g_i2cSrv); 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) { Result i2csessionSendAuto(I2cSession *s, const void *buf, size_t size, I2cTransactionOption option) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendSmart(&c, g_i2cSrvPtrBufSize, buf, size, 0); ipcAddSendSmart(&c, s->s.pointer_buffer_size, buf, size, 0);
struct { struct {
u64 magic; 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) { Result i2csessionReceiveAuto(I2cSession *s, void *buf, size_t size, I2cTransactionOption option) {
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddRecvSmart(&c, g_i2cSrvPtrBufSize, buf, size, 0); ipcAddRecvSmart(&c, s->s.pointer_buffer_size, buf, size, 0);
struct { struct {
u64 magic; u64 magic;
@ -149,7 +145,7 @@ Result i2csessionExecuteCommandList(I2cSession *s, void *dst, size_t dst_size, c
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
ipcAddSendStatic(&c, cmd_list, cmd_list_size, 0); 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 { struct {
u64 magic; u64 magic;

View File

@ -51,8 +51,7 @@ Result nvInitialize(void)
} }
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
g_nvIpcBufferSize = 0; g_nvIpcBufferSize = g_nvSrv.pointer_buffer_size;
rc = ipcQueryPointerBufferSize(g_nvSrv.handle, &g_nvIpcBufferSize);
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = tmemCreate(&g_nvTransfermem, __nx_nv_transfermem_size, Perm_None); 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 // Clone the session handle - the cloned session is used to execute certain commands in parallel
Handle nv_clone = INVALID_HANDLE; Handle nv_clone = INVALID_HANDLE;
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
rc = ipcCloneSession(g_nvSrv.handle, 1, &nv_clone); rc = ipcCloneSession(g_nvSrv.session, 1, &nv_clone);
if (R_SUCCEEDED(rc)) if (R_SUCCEEDED(rc))
serviceCreate(&g_nvSrvClone, nv_clone); serviceCreate(&g_nvSrvClone, nv_clone);

View File

@ -68,37 +68,11 @@ Result smInitialize(void)
Handle tmp; Handle tmp;
if (R_SUCCEEDED(rc) && smGetServiceOriginal(&tmp, smEncodeName("")) == 0x415) { if (R_SUCCEEDED(rc) && smGetServiceOriginal(&tmp, smEncodeName("")) == 0x415) {
IpcCommand c; const struct {
ipcInitialize(&c); u64 pid_placeholder;
ipcSendPid(&c); } in = { 0 };
struct { rc = serviceDispatchIn(&g_smSrv, 0, in, .in_send_pid = true);
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;
}
} }
if (R_FAILED(rc)) if (R_FAILED(rc))
@ -140,141 +114,55 @@ Result smGetService(Service* service_out, const char* name)
{ {
u64 name_encoded = smEncodeName(name); u64 name_encoded = smEncodeName(name);
Handle handle = smGetServiceOverride(name_encoded); Handle handle = smGetServiceOverride(name_encoded);
Result rc;
if (handle != INVALID_HANDLE) if (handle != INVALID_HANDLE)
{ {
service_out->type = ServiceType_Override; serviceCreate(service_out, handle);
service_out->handle = handle; service_out->own_handle = 0;
rc = 0; return 0;
} }
else
{
rc = smGetServiceOriginal(&handle, name_encoded);
if (R_SUCCEEDED(rc)) Result rc = smGetServiceOriginal(&handle, name_encoded);
{ if (R_SUCCEEDED(rc))
service_out->type = ServiceType_Normal; serviceCreate(service_out, handle);
service_out->handle = handle;
}
}
return rc; return rc;
} }
Result smGetServiceOriginal(Handle* handle_out, u64 name) Result smGetServiceOriginal(Handle* handle_out, u64 name)
{ {
IpcCommand c; const struct {
ipcInitialize(&c);
struct {
u64 magic;
u64 cmd_id;
u64 service_name; u64 service_name;
u64 reserved[2]; } in = { name };
} *raw;
raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); return serviceDispatchIn(&g_smSrv, 1, in,
.out_handle_attrs = { SfOutHandleAttr_HipcMove },
raw->magic = SFCI_MAGIC; .out_handles = handle_out,
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;
} }
Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions) { Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions)
IpcCommand c; {
ipcInitialize(&c); const struct {
struct {
u64 magic;
u64 cmd_id;
u64 service_name; u64 service_name;
u32 is_light; u32 is_light;
u32 max_sessions; u32 max_sessions;
} *raw; } in = { smEncodeName(name), !!is_light, max_sessions };
raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); return serviceDispatchIn(&g_smSrv, 2, in,
.out_handle_attrs = { SfOutHandleAttr_HipcMove },
raw->magic = SFCI_MAGIC; .out_handles = handle_out,
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;
} }
Result smUnregisterService(const char* name) { Result smUnregisterService(const char* name)
{
IpcCommand c; IpcCommand c;
ipcInitialize(&c); ipcInitialize(&c);
struct { const struct {
u64 magic;
u64 cmd_id;
u64 service_name; u64 service_name;
u64 reserved; } in = { smEncodeName(name) };
} *raw;
raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); return serviceDispatchIn(&g_smSrv, 3, in);
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;
} }

View File

@ -725,8 +725,6 @@ Result usbHsIfOpenUsbEp(UsbHsClientIfSession* s, UsbHsClientEpSession* ep, u16 m
if (R_SUCCEEDED(rc)) rc = _usbHsGetEvent(&ep->s, &ep->eventXfer, 2); 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)) { if (R_FAILED(rc)) {
serviceClose(&ep->s); serviceClose(&ep->s);
eventClose(&ep->eventXfer); eventClose(&ep->eventXfer);
@ -854,7 +852,7 @@ static Result _usbHsEpGetXferReport(UsbHsClientEpSession* s, UsbHsXferReport* re
ipcAddRecvBuffer(&c, reports, sizeof(UsbHsXferReport) * max_reports, BufferType_Normal); ipcAddRecvBuffer(&c, reports, sizeof(UsbHsXferReport) * max_reports, BufferType_Normal);
} }
else { 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)); raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));