diff --git a/nx/include/switch.h b/nx/include/switch.h index 2dbcc022..c2a40424 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -123,6 +123,7 @@ extern "C" { #include "switch/services/lp2p.h" #include "switch/services/news.h" #include "switch/services/ins.h" +#include "switch/services/ectx.h" #include "switch/display/binder.h" #include "switch/display/parcel.h" diff --git a/nx/include/switch/services/ectx.h b/nx/include/switch/services/ectx.h new file mode 100644 index 00000000..0a691e8f --- /dev/null +++ b/nx/include/switch/services/ectx.h @@ -0,0 +1,32 @@ +/** + * @file ectx.h + * @brief [11.0.0+] Error Context services IPC wrapper. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../kernel/event.h" +#include "../sf/service.h" + +/// Initialize ectx:r. +Result ectxrInitialize(void); + +/// Exit ectx:r. +void ectxrExit(void); + +/// Gets the Service object for the actual ectx:r service session. +Service* ectxrGetServiceSession(void); + +/** + * @brief Retrieves the error context associated with an error descriptor and result. + * @param[out] out0 Output value. + * @param[out] out_total_size Total error context size. + * @param[out] out_size Error context size. + * @param[out] dst Buffer for output error context. + * @param[in] dst_size Buffer size for output error context. + * @param[in] descriptor Error descriptor. + * @param[in] result Error result. + * @return Result code. + */ +Result ectxrPullContext(s32 *out0, u32 *out_total_size, u32 *out_size, void *dst, size_t dst_size, u32 descriptor, Result result); diff --git a/nx/source/services/ectx.c b/nx/source/services/ectx.c new file mode 100644 index 00000000..4f148b57 --- /dev/null +++ b/nx/source/services/ectx.c @@ -0,0 +1,48 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" +#include "runtime/hosversion.h" +#include "services/ectx.h" + +static Service g_ectxrSrv; + +NX_GENERATE_SERVICE_GUARD(ectxr); + +Result _ectxrInitialize(void) { + if (hosversionBefore(11,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return smGetService(&g_ectxrSrv, "ectx:r"); +} + +void _ectxrCleanup(void) { + serviceClose(&g_ectxrSrv); +} + +Service* ectxrGetServiceSession(void) { + return &g_ectxrSrv; +} + +Result ectxrPullContext(s32 *out0, u32 *out_total_size, u32 *out_size, void *dst, size_t dst_size, u32 descriptor, Result result) { + const struct { + u32 desc; + u32 res; + } in = { descriptor, result }; + + struct { + s32 unk0; + u32 total_size; + u32 size; + } out; + + Result rc = serviceDispatchInOut(&g_ectxrSrv, 1, in, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { dst, dst_size } }, + ); + + if (R_SUCCEEDED(rc)) { + if (out0) *out0 = out.unk0; + if (out_total_size) *out_total_size = out.total_size; + if (out_size) *out_size = out.size; + } + + return rc; +}