mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-22 13:02:38 +02:00
sm: Introduce and use SmServiceName struct (with better codegen)
This commit is contained in:
parent
7103b08740
commit
d025041e3d
@ -97,6 +97,55 @@ static inline Result serviceIpcParse(Service* s, IpcParsedCommand* r, size_t siz
|
|||||||
|
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
/// Structure representing a service name (null terminated, remaining characters set to zero).
|
||||||
|
typedef struct SmServiceName {
|
||||||
|
char name[8];
|
||||||
|
} SmServiceName;
|
||||||
|
|
||||||
|
/// Converts a service name into a 64-bit integer.
|
||||||
|
NX_CONSTEXPR u64 smServiceNameToU64(SmServiceName name)
|
||||||
|
{
|
||||||
|
u64 ret = 0;
|
||||||
|
__builtin_memcpy(&ret, &name, sizeof(u64));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a 64-bit integer into a service name.
|
||||||
|
NX_CONSTEXPR SmServiceName smServiceNameFromU64(u64 name)
|
||||||
|
{
|
||||||
|
SmServiceName ret = {0};
|
||||||
|
__builtin_memcpy(&ret, &name, sizeof(SmServiceName));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether two service names are equal.
|
||||||
|
* @param[in] a First name.
|
||||||
|
* @param[in] b Second name.
|
||||||
|
* @return Comparison result.
|
||||||
|
*/
|
||||||
|
NX_CONSTEXPR bool smServiceNamesAreEqual(SmServiceName a, SmServiceName b)
|
||||||
|
{
|
||||||
|
return smServiceNameToU64(a) == smServiceNameToU64(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encodes a service name string as a \ref SmServiceName structure.
|
||||||
|
* @param[in] name Name of the service.
|
||||||
|
* @return Encoded name.
|
||||||
|
*/
|
||||||
|
NX_CONSTEXPR SmServiceName smEncodeName(const char* name)
|
||||||
|
{
|
||||||
|
SmServiceName name_encoded = {};
|
||||||
|
unsigned len = __builtin_strlen(name);
|
||||||
|
#define __COPY_CHAR(_n) \
|
||||||
|
if (len > _n) name_encoded.name[_n] = name[_n]
|
||||||
|
__COPY_CHAR(0); __COPY_CHAR(1); __COPY_CHAR(2); __COPY_CHAR(3);
|
||||||
|
__COPY_CHAR(4); __COPY_CHAR(5); __COPY_CHAR(6); __COPY_CHAR(7);
|
||||||
|
#undef __COPY_CHAR
|
||||||
|
return name_encoded;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes SM.
|
* @brief Initializes SM.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
@ -112,12 +161,12 @@ Result smInitialize(void);
|
|||||||
void smExit(void);
|
void smExit(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Requests a service from SM.
|
* @brief Requests a service from SM, allowing overrides.
|
||||||
* @param[out] service_out Service structure which will be filled in.
|
* @param[out] service_out Service structure which will be filled in.
|
||||||
* @param[in] name Name of the service to request.
|
* @param[in] name Name of the service to request.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
*/
|
*/
|
||||||
Result smGetService(Service* service_out, const char* name);
|
Result smGetServiceWrapper(Service* service_out, SmServiceName name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Requests a service from SM, as an IPC session handle directly
|
* @brief Requests a service from SM, as an IPC session handle directly
|
||||||
@ -125,14 +174,25 @@ Result smGetService(Service* service_out, const char* name);
|
|||||||
* @param[in] name Name of the service to request.
|
* @param[in] name Name of the service to request.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
*/
|
*/
|
||||||
Result smGetServiceOriginal(Handle* handle_out, u64 name);
|
Result smGetServiceOriginal(Handle* handle_out, SmServiceName name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Requests a service from SM.
|
||||||
|
* @param[out] service_out Service structure which will be filled in.
|
||||||
|
* @param[in] name Name of the service to request (as a string).
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
NX_INLINE Result smGetService(Service* service_out, const char* name)
|
||||||
|
{
|
||||||
|
return smGetServiceWrapper(service_out, smEncodeName(name));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Retrieves an overriden service in the homebrew environment.
|
* @brief Retrieves an overriden service in the homebrew environment.
|
||||||
* @param[in] name Name of the service to request (as 64-bit integer).
|
* @param[in] name Name of the service to request.
|
||||||
* @return IPC session handle.
|
* @return IPC session handle.
|
||||||
*/
|
*/
|
||||||
Handle smGetServiceOverride(u64 name);
|
Handle smGetServiceOverride(SmServiceName name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates and registers a new service within SM.
|
* @brief Creates and registers a new service within SM.
|
||||||
@ -142,14 +202,14 @@ Handle smGetServiceOverride(u64 name);
|
|||||||
* @param[in] max_sessions Maximum number of concurrent sessions that the service will accept.
|
* @param[in] max_sessions Maximum number of concurrent sessions that the service will accept.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
*/
|
*/
|
||||||
Result smRegisterService(Handle* handle_out, const char* name, bool is_light, s32 max_sessions);
|
Result smRegisterService(Handle* handle_out, SmServiceName name, bool is_light, s32 max_sessions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Unregisters a previously registered service in SM.
|
* @brief Unregisters a previously registered service in SM.
|
||||||
* @param[in] name Name of the service.
|
* @param[in] name Name of the service.
|
||||||
* @return Result code.
|
* @return Result code.
|
||||||
*/
|
*/
|
||||||
Result smUnregisterService(const char* name);
|
Result smUnregisterService(SmServiceName name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets the Service session used to communicate with SM.
|
* @brief Gets the Service session used to communicate with SM.
|
||||||
@ -157,22 +217,9 @@ Result smUnregisterService(const char* name);
|
|||||||
*/
|
*/
|
||||||
Service *smGetServiceSession(void);
|
Service *smGetServiceSession(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Encodes a service name as a 64-bit integer.
|
|
||||||
* @param[in] name Name of the service.
|
|
||||||
* @return Encoded name.
|
|
||||||
*/
|
|
||||||
NX_CONSTEXPR u64 smEncodeName(const char* name)
|
|
||||||
{
|
|
||||||
u64 name_encoded = 0;
|
|
||||||
for (unsigned i = 0; name[i] && i < 8; i ++)
|
|
||||||
name_encoded |= ((u64) name[i]) << (8*i);
|
|
||||||
return name_encoded;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Overrides a service with a custom IPC service handle.
|
* @brief Overrides a service with a custom IPC service handle.
|
||||||
* @param[in] name Name of the service (as 64-bit integer).
|
* @param[in] name Name of the service.
|
||||||
* @param[in] handle IPC session handle.
|
* @param[in] handle IPC session handle.
|
||||||
*/
|
*/
|
||||||
void smAddOverrideHandle(u64 name, Handle handle);
|
void smAddOverrideHandle(SmServiceName name, Handle handle);
|
||||||
|
@ -73,7 +73,7 @@ void envSetup(void* ctx, Handle main_thread, LoaderReturnFn saved_lr)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EntryType_OverrideService:
|
case EntryType_OverrideService:
|
||||||
smAddOverrideHandle(ent->Value[0], ent->Value[1]);
|
smAddOverrideHandle(smServiceNameFromU64(ent->Value[0]), ent->Value[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EntryType_Argv:
|
case EntryType_Argv:
|
||||||
|
@ -7,13 +7,13 @@ static Service g_smSrv;
|
|||||||
#define MAX_OVERRIDES 32
|
#define MAX_OVERRIDES 32
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
u64 name;
|
SmServiceName name;
|
||||||
Handle handle;
|
Handle handle;
|
||||||
} g_smOverrides[MAX_OVERRIDES];
|
} g_smOverrides[MAX_OVERRIDES];
|
||||||
|
|
||||||
static size_t g_smOverridesNum = 0;
|
static size_t g_smOverridesNum = 0;
|
||||||
|
|
||||||
void smAddOverrideHandle(u64 name, Handle handle) {
|
void smAddOverrideHandle(SmServiceName name, Handle handle) {
|
||||||
if (g_smOverridesNum == MAX_OVERRIDES)
|
if (g_smOverridesNum == MAX_OVERRIDES)
|
||||||
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_TooManyOverrides));
|
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_TooManyOverrides));
|
||||||
|
|
||||||
@ -25,9 +25,9 @@ void smAddOverrideHandle(u64 name, Handle handle) {
|
|||||||
g_smOverridesNum++;
|
g_smOverridesNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle smGetServiceOverride(u64 name) {
|
Handle smGetServiceOverride(SmServiceName name) {
|
||||||
for (size_t i = 0; i < g_smOverridesNum; i++)
|
for (size_t i = 0; i < g_smOverridesNum; i++)
|
||||||
if (g_smOverrides[i].name == name)
|
if (smServiceNamesAreEqual(g_smOverrides[i].name, name))
|
||||||
return g_smOverrides[i].handle;
|
return g_smOverrides[i].handle;
|
||||||
|
|
||||||
return INVALID_HANDLE;
|
return INVALID_HANDLE;
|
||||||
@ -48,12 +48,9 @@ Result _smInitialize(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handle tmp;
|
Handle tmp;
|
||||||
if (R_SUCCEEDED(rc) && smGetServiceOriginal(&tmp, smEncodeName("")) == 0x415) {
|
if (R_SUCCEEDED(rc) && smGetServiceOriginal(&tmp, (SmServiceName){}) == 0x415) {
|
||||||
const struct {
|
u64 pid_placeholder = 0;
|
||||||
u64 pid_placeholder;
|
rc = serviceDispatchIn(&g_smSrv, 0, pid_placeholder, .in_send_pid = true);
|
||||||
} in = { 0 };
|
|
||||||
|
|
||||||
rc = serviceDispatchIn(&g_smSrv, 0, in, .in_send_pid = true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -67,15 +64,14 @@ Service *smGetServiceSession(void) {
|
|||||||
return &g_smSrv;
|
return &g_smSrv;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result smGetService(Service* service_out, const char* name) {
|
Result smGetServiceWrapper(Service* service_out, SmServiceName name) {
|
||||||
u64 name_encoded = smEncodeName(name);
|
Handle handle = smGetServiceOverride(name);
|
||||||
Handle handle = smGetServiceOverride(name_encoded);
|
|
||||||
bool own_handle = false;
|
bool own_handle = false;
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
|
|
||||||
if (handle == INVALID_HANDLE) {
|
if (handle == INVALID_HANDLE) {
|
||||||
own_handle = true;
|
own_handle = true;
|
||||||
rc = smGetServiceOriginal(&handle, name_encoded);
|
rc = smGetServiceOriginal(&handle, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
@ -86,19 +82,19 @@ Result smGetService(Service* service_out, const char* name) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result smGetServiceOriginal(Handle* handle_out, u64 name) {
|
Result smGetServiceOriginal(Handle* handle_out, SmServiceName name) {
|
||||||
return serviceDispatchIn(&g_smSrv, 1, name,
|
return serviceDispatchIn(&g_smSrv, 1, name,
|
||||||
.out_handle_attrs = { SfOutHandleAttr_HipcMove },
|
.out_handle_attrs = { SfOutHandleAttr_HipcMove },
|
||||||
.out_handles = handle_out,
|
.out_handles = handle_out,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result smRegisterService(Handle* handle_out, const char* name, bool is_light, s32 max_sessions) {
|
Result smRegisterService(Handle* handle_out, SmServiceName name, bool is_light, s32 max_sessions) {
|
||||||
const struct {
|
const struct {
|
||||||
u64 service_name;
|
SmServiceName service_name;
|
||||||
u8 is_light;
|
u8 is_light;
|
||||||
s32 max_sessions;
|
s32 max_sessions;
|
||||||
} in = { smEncodeName(name), is_light!=0, max_sessions };
|
} in = { name, is_light!=0, max_sessions };
|
||||||
|
|
||||||
return serviceDispatchIn(&g_smSrv, 2, in,
|
return serviceDispatchIn(&g_smSrv, 2, in,
|
||||||
.out_handle_attrs = { SfOutHandleAttr_HipcMove },
|
.out_handle_attrs = { SfOutHandleAttr_HipcMove },
|
||||||
@ -106,7 +102,6 @@ Result smRegisterService(Handle* handle_out, const char* name, bool is_light, s3
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result smUnregisterService(const char* name) {
|
Result smUnregisterService(SmServiceName name) {
|
||||||
u64 service_name = smEncodeName(name);
|
return serviceDispatchIn(&g_smSrv, 3, name);
|
||||||
return serviceDispatchIn(&g_smSrv, 3, service_name);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user