mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +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
|
||||
|
||||
/// 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.
|
||||
* @return Result code.
|
||||
@ -112,12 +161,12 @@ Result smInitialize(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[in] name Name of the service to request.
|
||||
* @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
|
||||
@ -125,14 +174,25 @@ Result smGetService(Service* service_out, const char* name);
|
||||
* @param[in] name Name of the service to request.
|
||||
* @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.
|
||||
* @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.
|
||||
*/
|
||||
Handle smGetServiceOverride(u64 name);
|
||||
Handle smGetServiceOverride(SmServiceName name);
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @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.
|
||||
* @param[in] name Name of the service.
|
||||
* @return Result code.
|
||||
*/
|
||||
Result smUnregisterService(const char* name);
|
||||
Result smUnregisterService(SmServiceName name);
|
||||
|
||||
/**
|
||||
* @brief Gets the Service session used to communicate with SM.
|
||||
@ -157,22 +217,9 @@ Result smUnregisterService(const char* name);
|
||||
*/
|
||||
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.
|
||||
* @param[in] name Name of the service (as 64-bit integer).
|
||||
* @param[in] name Name of the service.
|
||||
* @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;
|
||||
|
||||
case EntryType_OverrideService:
|
||||
smAddOverrideHandle(ent->Value[0], ent->Value[1]);
|
||||
smAddOverrideHandle(smServiceNameFromU64(ent->Value[0]), ent->Value[1]);
|
||||
break;
|
||||
|
||||
case EntryType_Argv:
|
||||
|
@ -7,13 +7,13 @@ static Service g_smSrv;
|
||||
#define MAX_OVERRIDES 32
|
||||
|
||||
static struct {
|
||||
u64 name;
|
||||
SmServiceName name;
|
||||
Handle handle;
|
||||
} g_smOverrides[MAX_OVERRIDES];
|
||||
|
||||
static size_t g_smOverridesNum = 0;
|
||||
|
||||
void smAddOverrideHandle(u64 name, Handle handle) {
|
||||
void smAddOverrideHandle(SmServiceName name, Handle handle) {
|
||||
if (g_smOverridesNum == MAX_OVERRIDES)
|
||||
fatalSimple(MAKERESULT(Module_Libnx, LibnxError_TooManyOverrides));
|
||||
|
||||
@ -25,9 +25,9 @@ void smAddOverrideHandle(u64 name, Handle handle) {
|
||||
g_smOverridesNum++;
|
||||
}
|
||||
|
||||
Handle smGetServiceOverride(u64 name) {
|
||||
Handle smGetServiceOverride(SmServiceName name) {
|
||||
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 INVALID_HANDLE;
|
||||
@ -48,12 +48,9 @@ Result _smInitialize(void) {
|
||||
}
|
||||
|
||||
Handle tmp;
|
||||
if (R_SUCCEEDED(rc) && smGetServiceOriginal(&tmp, smEncodeName("")) == 0x415) {
|
||||
const struct {
|
||||
u64 pid_placeholder;
|
||||
} in = { 0 };
|
||||
|
||||
rc = serviceDispatchIn(&g_smSrv, 0, in, .in_send_pid = true);
|
||||
if (R_SUCCEEDED(rc) && smGetServiceOriginal(&tmp, (SmServiceName){}) == 0x415) {
|
||||
u64 pid_placeholder = 0;
|
||||
rc = serviceDispatchIn(&g_smSrv, 0, pid_placeholder, .in_send_pid = true);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -67,15 +64,14 @@ Service *smGetServiceSession(void) {
|
||||
return &g_smSrv;
|
||||
}
|
||||
|
||||
Result smGetService(Service* service_out, const char* name) {
|
||||
u64 name_encoded = smEncodeName(name);
|
||||
Handle handle = smGetServiceOverride(name_encoded);
|
||||
Result smGetServiceWrapper(Service* service_out, SmServiceName name) {
|
||||
Handle handle = smGetServiceOverride(name);
|
||||
bool own_handle = false;
|
||||
Result rc = 0;
|
||||
|
||||
if (handle == INVALID_HANDLE) {
|
||||
own_handle = true;
|
||||
rc = smGetServiceOriginal(&handle, name_encoded);
|
||||
rc = smGetServiceOriginal(&handle, name);
|
||||
}
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
@ -86,19 +82,19 @@ Result smGetService(Service* service_out, const char* name) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result smGetServiceOriginal(Handle* handle_out, u64 name) {
|
||||
Result smGetServiceOriginal(Handle* handle_out, SmServiceName name) {
|
||||
return serviceDispatchIn(&g_smSrv, 1, name,
|
||||
.out_handle_attrs = { SfOutHandleAttr_HipcMove },
|
||||
.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 {
|
||||
u64 service_name;
|
||||
SmServiceName service_name;
|
||||
u8 is_light;
|
||||
s32 max_sessions;
|
||||
} in = { smEncodeName(name), is_light!=0, max_sessions };
|
||||
} in = { name, is_light!=0, max_sessions };
|
||||
|
||||
return serviceDispatchIn(&g_smSrv, 2, in,
|
||||
.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) {
|
||||
u64 service_name = smEncodeName(name);
|
||||
return serviceDispatchIn(&g_smSrv, 3, service_name);
|
||||
Result smUnregisterService(SmServiceName name) {
|
||||
return serviceDispatchIn(&g_smSrv, 3, name);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user