From 43202cc829fba94ff031285da08cdb9f8697f1f6 Mon Sep 17 00:00:00 2001 From: HookedBehemoth Date: Wed, 6 Jan 2021 17:25:29 +0100 Subject: [PATCH] add application version manager service wrapper (#519) --- nx/include/switch.h | 1 + nx/include/switch/services/avm.h | 45 +++++++++++++ nx/source/services/avm.c | 109 +++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 nx/include/switch/services/avm.h create mode 100644 nx/source/services/avm.c diff --git a/nx/include/switch.h b/nx/include/switch.h index 16b0a838..6562f501 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -125,6 +125,7 @@ extern "C" { #include "switch/services/news.h" #include "switch/services/ins.h" #include "switch/services/ectx.h" +#include "switch/services/avm.h" #include "switch/display/binder.h" #include "switch/display/parcel.h" diff --git a/nx/include/switch/services/avm.h b/nx/include/switch/services/avm.h new file mode 100644 index 00000000..1ad59f44 --- /dev/null +++ b/nx/include/switch/services/avm.h @@ -0,0 +1,45 @@ +/** + * @file avm.h + * @brief AVM services IPC wrapper. Only available on [6.0.0+]. + * @author Behemoth + * @copyright libnx Authors + */ +#pragma once + +#include "../types.h" +#include "../sf/service.h" + +typedef struct { + u64 application_id; + u32 version; + u32 required; +} AvmVersionListEntry; + +typedef struct { + u64 application_id; + u32 version; +} AvmRequiredVersionEntry; + +typedef struct { + Service s; +} AvmVersionListImporter; + +Result avmInitialize(void); +void avmExit(void); + +Service *avmGetServiceSession(void); + +Result avmGetHighestAvailableVersion(u64 id_1, u64 id_2, u32 *version); +Result avmGetHighestRequiredVersion(u64 id_1, u64 id_2, u32 *version); +Result avmGetVersionListEntry(u64 application_id, AvmVersionListEntry *entry); +Result avmGetVersionListImporter(AvmVersionListImporter *out); +Result avmGetLaunchRequiredVersion(u64 application_id, u32 *version); +Result avmUpgradeLaunchRequiredVersion(u64 application_id, u32 version); +Result avmPushLaunchVersion(u64 application_id, u32 version); +Result avmListVersionList(AvmVersionListEntry *buffer, size_t count, u32 *out); +Result avmListRequiredVersion(AvmRequiredVersionEntry *buffer, size_t count, u32 *out); + +void avmVersionListImporterClose(AvmVersionListImporter *srv); +Result avmVersionListImporterSetTimestamp(AvmVersionListImporter *srv, u64 timestamp); +Result avmVersionListImporterSetData(AvmVersionListImporter *srv, const AvmVersionListEntry *entries, u32 count); +Result avmVersionListImporterFlush(AvmVersionListImporter *srv); diff --git a/nx/source/services/avm.c b/nx/source/services/avm.c new file mode 100644 index 00000000..1ea4c0b8 --- /dev/null +++ b/nx/source/services/avm.c @@ -0,0 +1,109 @@ +#include "service_guard.h" +#include "services/avm.h" +#include "runtime/hosversion.h" + +static Service g_AvmSrv; + +NX_GENERATE_SERVICE_GUARD(avm); + +Result _avmInitialize(void) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc=0; + + rc = smGetService(&g_AvmSrv, "avm"); + + if (R_SUCCEEDED(rc)) rc = serviceConvertToDomain(&g_AvmSrv); + + return rc; +} + +void _avmCleanup(void) { + serviceClose(&g_AvmSrv); +} + +Service *avmGetServiceSession(void) { + return &g_AvmSrv; +} + +static Result _avmGetVersion(u64 id_1, u64 id_2, u32 *version, u32 cmd_id) { + const struct { + u64 a, b; + } in = { id_1, id_2 }; + + return serviceDispatchInOut(&g_AvmSrv, 100, in, *version); +} + +Result avmGetHighestAvailableVersion(u64 id_1, u64 id_2, u32 *version) { + return _avmGetVersion(id_1, id_2, version, 100); +} + +Result avmGetHighestRequiredVersion(u64 id_1, u64 id_2, u32 *version) { + return _avmGetVersion(id_1, id_2, version, 101); +} + +Result avmGetVersionListEntry(u64 application_id, AvmVersionListEntry *entry) { + return serviceDispatchInOut(&g_AvmSrv, 102, application_id, *entry); +} + +Result avmGetVersionListImporter(AvmVersionListImporter *out) { + return serviceDispatch(&g_AvmSrv, 103, + .out_num_objects = 1, + .out_objects = &out->s, + ); +} + +Result avmGetLaunchRequiredVersion(u64 application_id, u32 *version) { + return serviceDispatchInOut(&g_AvmSrv, 200, application_id, *version); +} + +static Result _avmPushVersion(u64 application_id, u32 version, u32 cmd_id) { + const struct { + u32 version; + u64 application_id; + } in = { version, application_id }; + + return serviceDispatchIn(&g_AvmSrv, cmd_id, in); +} + +Result avmUpgradeLaunchRequiredVersion(u64 application_id, u32 version) { + return _avmPushVersion(application_id, version, 202); +} + +Result avmPushLaunchVersion(u64 application_id, u32 version) { + return _avmPushVersion(application_id, version, 100); +} + +Result avmListVersionList(AvmVersionListEntry *buffer, size_t count, u32 *out) { + return serviceDispatchOut(&g_AvmSrv, 1001, *out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, count * sizeof(*buffer) } }, + ); +} + +Result avmListRequiredVersion(AvmRequiredVersionEntry *buffer, size_t count, u32 *out) { + return serviceDispatchOut(&g_AvmSrv, 1002, *out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, count * sizeof(*buffer) } }, + ); +} + +void avmVersionListImporterClose(AvmVersionListImporter *srv) { + return serviceClose(&srv->s); +} + +Result avmVersionListImporterSetTimestamp(AvmVersionListImporter *srv, u64 timestamp) { + return serviceDispatchIn(&srv->s, 0, timestamp); +} + +Result avmVersionListImporterSetData(AvmVersionListImporter *srv, const AvmVersionListEntry *entries, u32 count) { + return serviceDispatch(&srv->s, 1, + .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias }, + .buffers = { { entries, count * sizeof(entries) } }, + ); +} + +Result avmVersionListImporterFlush(AvmVersionListImporter *srv) { + return serviceDispatch(&srv->s, 2); +}