sm: Introduce and use SmServiceName struct (with better codegen)

This commit is contained in:
fincs 2019-10-22 20:10:52 +02:00
parent 7103b08740
commit d025041e3d
No known key found for this signature in database
GPG Key ID: 62C7609ADA219C60
3 changed files with 86 additions and 44 deletions

View File

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

View File

@ -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:

View File

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