Added support for nssu, and added the structs/enums for it. Added NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT. Moved cmd_id param in the ns helper funcs to the last param. Improved docs.

This commit is contained in:
yellows8 2019-09-26 17:07:26 -04:00
parent 0749dfd67f
commit 075a743cfb
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 789 additions and 31 deletions

View File

@ -8,7 +8,39 @@
#include "../types.h"
#include "../nacp.h"
#include "../services/fs.h"
#include "../services/ncm.h"
#include "../services/async.h"
#include "../kernel/event.h"
#include "../kernel/tmem.h"
/// ShellEvent
typedef enum {
NsShellEvent_None = 0, ///< None
NsShellEvent_Exit = 1, ///< Exit
NsShellEvent_Start = 2, ///< Start
NsShellEvent_Crash = 3, ///< Crash
NsShellEvent_Debug = 4, ///< Debug
} NsShellEvent;
/// BackgroundNetworkUpdateState
typedef enum {
NsBackgroundNetworkUpdateState_None = 0, ///< No sysupdate task exists.
NsBackgroundNetworkUpdateState_Downloading = 1, ///< Sysupdate download in progress.
NsBackgroundNetworkUpdateState_Ready = 2, ///< Sysupdate ready, pending install.
} NsBackgroundNetworkUpdateState;
/// LatestSystemUpdate
typedef enum {
NsLatestSystemUpdate_Unknown0 = 0, ///< Unknown.
NsLatestSystemUpdate_Unknown1 = 1, ///< Unknown.
NsLatestSystemUpdate_Unknown2 = 2, ///< Unknown.
} NsLatestSystemUpdate;
/// SystemUpdateControl
typedef struct {
Service s; ///< ISystemUpdateControl
TransferMemory tmem; ///< TransferMemory for SetupCardUpdate/SetupCardUpdateViaSystemUpdater.
} NsSystemUpdateControl;
/// ApplicationControlData
typedef struct {
@ -45,21 +77,39 @@ typedef struct {
u8 is_application; ///< Whether this is an Application.
} NsLaunchProperties;
/// ShellEvent
typedef enum {
NsShellEvent_None = 0, ///< None
NsShellEvent_Exit = 1, ///< Exit
NsShellEvent_Start = 2, ///< Start
NsShellEvent_Crash = 3, ///< Crash
NsShellEvent_Debug = 4, ///< Debug
} NsShellEvent;
/// ShellEventInfo
typedef struct {
NsShellEvent event; ///< \ref NsShellEvent
u64 process_id; ///< processID.
} NsShellEventInfo;
/// SystemUpdateProgress. Commands which have this as output will return 0 with the output cleared, when no task is available.
typedef struct {
u64 unk_x0; ///< Unknown.
u64 unk_x8; ///< Unknown.
} NsSystemUpdateProgress;
/// EulaDataPath
typedef struct {
char path[0x100]; ///< Path.
} NsEulaDataPath;
/// SystemDeliveryInfo
typedef struct {
u32 protocol_version; ///< Must be <= to and match a system-setting.
u8 unk_x4[0x8]; ///< Unknown.
u32 unk_xc; ///< Unknown.
u64 unk_x10; ///< Unknown.
u8 unk_x18[0xc8]; ///< Unknown.
u8 hmac[0x20]; ///< HMAC-SHA256 over the previous 0xe0-bytes.
} NsSystemDeliveryInfo;
/// Default size for \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater. This is the size used by qlaunch for SetupCardUpdate.
#define NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT 0x100000
///@name ns
///@{
Result nsInitialize(void);
void nsExit(void);
@ -106,13 +156,22 @@ Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size);
*/
Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size);
///@}
///@name ns:vm
///@{
Result nsvmInitialize(void);
void nsvmExit(void);
Result nsvmNeedsUpdateVulnerability(bool *out);
Result nsvmGetSafeSystemVersion(u16 *out);
/* ns:dev */
///@}
///@name ns:dev
///@{
Result nsdevInitialize(void);
void nsdevExit(void);
@ -128,3 +187,305 @@ Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 app_title
Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out); ///< [6.0.0-8.1.0]
Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid); ///< [6.0.0+]
Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop(bool can_be_active); ///< [6.0.0+]
///@}
///@name ns:su
///@{
Result nssuInitialize(void);
void nssuExit(void);
/**
* @brief Gets the \ref NsBackgroundNetworkUpdateState.
* @note Internally this uses nim commands ListSystemUpdateTask and GetSystemUpdateTaskInfo to determine the output state.
* @param[out] out \ref NsBackgroundNetworkUpdateState
*/
Result nssuGetBackgroundNetworkUpdateState(NsBackgroundNetworkUpdateState *out);
/**
* @brief Opens a \ref NsSystemUpdateControl.
* @note Only 1 \ref NsSystemUpdateControl can be open at a time.
* @param[out] c \ref NsSystemUpdateControl
*/
Result nssuOpenSystemUpdateControl(NsSystemUpdateControl *c);
/**
* @brief Uses nim ListSystemUpdateTask, then uses the task with DestroySystemUpdateTask if it exists. Then this runs ExFat handling, updates state, and sets the same state flag as \ref nssuRequestBackgroundNetworkUpdate.
* @note Only usable when a \ref NsSystemUpdateControl isn't open.
*/
Result nssuNotifyExFatDriverRequired(void);
/**
* @brief ClearExFatDriverStatusForDebug
*/
Result nssuClearExFatDriverStatusForDebug(void);
/**
* @brief RequestBackgroundNetworkUpdate
* @note Only usable when a \ref NsSystemUpdateControl isn't open.
*/
Result nssuRequestBackgroundNetworkUpdate(void);
/**
* @brief This checks whether a sysupdate is needed with the input \ref NcmContentMetaKey using NCM commands, if not this will just return 0. Otherwise, this will then run code which is identical to \ref nssuRequestBackgroundNetworkUpdate.
* @note Only usable when a \ref NsSystemUpdateControl isn't open.
* @param[in] key \ref NcmContentMetaKey
*/
Result nssuNotifyBackgroundNetworkUpdate(const NcmContentMetaKey *key);
/**
* @brief NotifyExFatDriverDownloadedForDebug
*/
Result nssuNotifyExFatDriverDownloadedForDebug(void);
/**
* @brief Gets an Event which can be signaled by \ref nssuNotifySystemUpdateForContentDelivery.
* @note The Event must be closed by the user once finished with it.
* @param[out] out_event Output Event with autoclear=false.
*/
Result nssuGetSystemUpdateNotificationEventForContentDelivery(Event* out_event);
/**
* @brief Signals the event returned by \ref nssuGetSystemUpdateNotificationEventForContentDelivery.
*/
Result nssuNotifySystemUpdateForContentDelivery(void);
/**
* @brief This does shutdown preparation.
* @note This is used by am-sysmodule, so generally there's no need to use this.
* @note Only available on [3.0.0+].
*/
Result nssuPrepareShutdown(void);
/**
* @brief This uses nim ListSystemUpdateTask, then when a task is returned uses it with DestroySystemUpdateTask.
* @note Only available on [4.0.0+].
*/
Result nssuDestroySystemUpdateTask(void);
/**
* @brief RequestSendSystemUpdate
* @note Only available on [4.0.0+].
* @param[out] a \ref AsyncResult
* @param[in] inval0 Unknown input value.
* @param[in] inval1 Unknown input value. qlaunch uses value 0xD904 (55556).
* @param[in] info \ref NsSystemDeliveryInfo
*/
Result nssuRequestSendSystemUpdate(AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info);
/**
* @brief GetSendSystemUpdateProgress
* @note Only available on [4.0.0+].
* @param[out] out \ref NsSystemUpdateProgress
*/
Result nssuGetSendSystemUpdateProgress(NsSystemUpdateProgress *out);
///@}
///@name ISystemUpdateControl
///@{
/**
* @brief Close a \ref NsSystemUpdateControl.
* @param c \ref NsSystemUpdateControl
*/
void nssuControlClose(NsSystemUpdateControl *c);
/**
* @brief Gets whether a network sysupdate was downloaded, with install pending.
* @param c \ref NsSystemUpdateControl
* @param[out] out Output flag.
*/
Result nssuControlHasDownloaded(NsSystemUpdateControl *c, bool* out);
/**
* @brief RequestCheckLatestUpdate
* @param c \ref NsSystemUpdateControl
* @param[out] a \ref AsyncValue. The data that can be read from this is u8 \ref NsLatestSystemUpdate.
*/
Result nssuControlRequestCheckLatestUpdate(NsSystemUpdateControl *c, AsyncValue *a);
/**
* @brief RequestDownloadLatestUpdate
* @param c \ref NsSystemUpdateControl
* @param[out] a \ref AsyncResult
*/
Result nssuControlRequestDownloadLatestUpdate(NsSystemUpdateControl *c, AsyncResult *a);
/**
* @brief GetDownloadProgress
* @param c \ref NsSystemUpdateControl
* @param[out] out \ref NsSystemUpdateProgress
*/
Result nssuControlGetDownloadProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out);
/**
* @brief ApplyDownloadedUpdate
* @param c \ref NsSystemUpdateControl
*/
Result nssuControlApplyDownloadedUpdate(NsSystemUpdateControl *c);
/**
* @brief RequestPrepareCardUpdate
* @param c \ref NsSystemUpdateControl
* @param[out] a \ref AsyncResult
*/
Result nssuControlRequestPrepareCardUpdate(NsSystemUpdateControl *c, AsyncResult *a);
/**
* @brief GetPrepareCardUpdateProgress
* @note \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater must have been used at some point prior to using this.
* @param c \ref NsSystemUpdateControl
* @param[out] out \ref NsSystemUpdateProgress
*/
Result nssuControlGetPrepareCardUpdateProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out);
/**
* @brief HasPreparedCardUpdate
* @note \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater must have been used at some point prior to using this.
* @param c \ref NsSystemUpdateControl
* @param[out] out Output flag.
*/
Result nssuControlHasPreparedCardUpdate(NsSystemUpdateControl *c, bool* out);
/**
* @brief ApplyCardUpdate
* @note \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater must have been used at some point prior to using this.
* @param c \ref NsSystemUpdateControl
*/
Result nssuControlApplyCardUpdate(NsSystemUpdateControl *c);
/**
* @brief Gets the filesize for the specified DownloadedEulaData.
* @note This mounts the Eula title, then uses the file "<mountname>:/<input path>".
* @param c \ref NsSystemUpdateControl
* @param[in] path EulaData path.
* @param[out] filesize Output filesize.
*/
Result nssuControlGetDownloadedEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize);
/**
* @brief Gets the specified DownloadedEulaData.
* @note See the note for \ref nssuControlGetDownloadedEulaDataSize.
* @param c \ref NsSystemUpdateControl
* @param[in] path EulaData path.
* @param[out] buffer Output buffer.
* @param[in] size Size of the output buffer, must be at least the output size from \ref nssuControlGetDownloadedEulaDataSize.
* @param[out] filesize Output filesize.
*/
Result nssuControlGetDownloadedEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize);
/**
* @brief SetupCardUpdate
* @param c \ref NsSystemUpdateControl
* @param[in] path EulaData path.
* @param[in] buffer TransferMemory buffer, when NULL this is automatically allocated.
* @param[in] size TransferMemory buffer size, see \ref NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT.
*/
Result nssuControlSetupCardUpdate(NsSystemUpdateControl *c, void* buffer, size_t size);
/**
* @brief Gets the filesize for the specified PreparedCardUpdateEulaData.
* @note See the note for \ref nssuControlGetDownloadedEulaDataSize.
* @param c \ref NsSystemUpdateControl
* @param[in] path EulaData path.
* @param[out] filesize Output filesize.
*/
Result nssuControlGetPreparedCardUpdateEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize);
/**
* @brief Gets the specified PreparedCardUpdateEulaData.
* @note See the note for \ref nssuControlGetDownloadedEulaDataSize.
* @param c \ref NsSystemUpdateControl
* @param[in] path EulaData path.
* @param[out] buffer Output buffer.
* @param[in] size Size of the output buffer, must be at least the output size from \ref nssuControlGetPreparedCardUpdateEulaDataSize.
* @param[out] filesize Output filesize.
*/
Result nssuControlGetPreparedCardUpdateEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize);
/**
* @brief SetupCardUpdateViaSystemUpdater
* @note Same as \ref nssuControlSetupCardUpdate, except this doesn't run the code for fs cmds GetGameCardHandle/GetGameCardUpdatePartitionInfo, and uses fs OpenRegisteredUpdatePartition instead of OpenGameCardFileSystem.
* @note Only available on [4.0.0+].
* @param c \ref NsSystemUpdateControl
* @param[in] path EulaData path.
* @param[in] buffer TransferMemory buffer, when NULL this is automatically allocated.
* @param[in] size TransferMemory buffer size, see \ref NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT.
*/
Result nssuControlSetupCardUpdateViaSystemUpdater(NsSystemUpdateControl *c, void* buffer, size_t size);
/**
* @brief HasReceived
* @note Only available on [4.0.0+].
* @param c \ref NsSystemUpdateControl
* @param[out] out Output flag.
*/
Result nssuControlHasReceived(NsSystemUpdateControl *c, bool* out);
/**
* @brief RequestReceiveSystemUpdate
* @note Only available on [4.0.0+].
* @param c \ref NsSystemUpdateControl
* @param[out] a \ref AsyncResult
* @param[in] inval0 Unknown input value.
* @param[in] inval1 Unknown input value. qlaunch uses value 0xD904 (55556).
* @param[in] info \ref NsSystemDeliveryInfo
*/
Result nssuControlRequestReceiveSystemUpdate(NsSystemUpdateControl *c, AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info);
/**
* @brief GetReceiveProgress
* @note Only available on [4.0.0+].
* @param c \ref NsSystemUpdateControl
* @param[out] out \ref NsSystemUpdateProgress
*/
Result nssuControlGetReceiveProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out);
/**
* @brief ApplyReceivedUpdate
* @note Only available on [4.0.0+].
* @param c \ref NsSystemUpdateControl
*/
Result nssuControlApplyReceivedUpdate(NsSystemUpdateControl *c);
/**
* @brief Gets the filesize for the specified ReceivedEulaData.
* @note See the note for \ref nssuControlGetDownloadedEulaDataSize.
* @note Only available on [4.0.0+].
* @param c \ref NsSystemUpdateControl
* @param[in] path EulaData path.
* @param[out] filesize Output filesize.
*/
Result nssuControlGetReceivedEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize);
/**
* @brief Gets the specified ReceivedEulaData.
* @note See the note for \ref nssuControlGetDownloadedEulaDataSize.
* @note Only available on [4.0.0+].
* @param c \ref NsSystemUpdateControl
* @param[in] path EulaData path.
* @param[out] buffer Output buffer.
* @param[in] size Size of the output buffer, must be at least the output size from \ref nssuControlGetReceivedEulaDataSize.
* @param[out] filesize Output filesize.
*/
Result nssuControlGetReceivedEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize);
/**
* @brief Does setup for ReceiveSystemUpdate by using the same nim cmds as \ref nssuDestroySystemUpdateTask.
* @note Only available on [4.0.0+].
* @param c \ref NsSystemUpdateControl
*/
Result nssuControlSetupToReceiveSystemUpdate(NsSystemUpdateControl *c);
/**
* @brief RequestCheckLatestUpdateIncludesRebootlessUpdate
* @note Only available on [6.0.0+].
* @param c \ref NsSystemUpdateControl
* @param[out] a \ref AsyncValue
*/
Result nssuControlRequestCheckLatestUpdateIncludesRebootlessUpdate(NsSystemUpdateControl *c, AsyncValue *a);
///@}

View File

@ -1,11 +1,21 @@
#define NX_SERVICE_ASSUME_NON_DOMAIN
#include <string.h>
#include "service_guard.h"
#include "runtime/hosversion.h"
#include "services/ns.h"
#include "services/fs.h"
#include "services/ncm.h"
#include "services/async.h"
#include "kernel/tmem.h"
static Service g_nsAppManSrv, g_nsGetterSrv, g_nsvmSrv, g_nsdevSrv;
static Service g_nsAppManSrv, g_nsGetterSrv;
static Service g_nsvmSrv;
static Service g_nsdevSrv;
static Service g_nssuSrv;
static Result _nsGetInterface(Service* srv_out, u32 cmd_id);
static Result _nsGetSession(Service* srv, Service* srv_out, u32 cmd_id);
// ns
NX_GENERATE_SERVICE_GUARD(ns);
@ -19,7 +29,7 @@ Result _nsInitialize(void)
rc = smGetService(&g_nsGetterSrv, "ns:am2");//TODO: Support the other services?(Only useful when ns:am2 isn't accessible)
if (R_FAILED(rc)) return rc;
rc = _nsGetInterface(&g_nsAppManSrv, 7996);
rc = _nsGetSession(&g_nsGetterSrv, &g_nsAppManSrv, 7996);
if (R_FAILED(rc)) serviceClose(&g_nsGetterSrv);
@ -34,14 +44,14 @@ void _nsCleanup(void)
serviceClose(&g_nsGetterSrv);
}
static Result _nsGetInterface(Service* srv_out, u32 cmd_id) {
return serviceDispatch(&g_nsGetterSrv, cmd_id,
static Result _nsGetSession(Service* srv, Service* srv_out, u32 cmd_id) {
return serviceDispatch(srv, cmd_id,
.out_num_objects = 1,
.out_objects = srv_out,
);
}
static Result _appletGetEvent(Service* srv, u32 cmd_id, Event* out_event, bool autoclear) {
static Result _nsCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) {
Handle event = INVALID_HANDLE;
Result rc = serviceDispatch(srv, cmd_id,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
@ -54,35 +64,109 @@ static Result _appletGetEvent(Service* srv, u32 cmd_id, Event* out_event, bool a
return rc;
}
static Result _nsCmdInHandle64NoOut(Service* srv, Handle handle, u64 inval, u32 cmd_id) {
return serviceDispatchIn(srv, cmd_id, inval,
.in_num_handles = 1,
.in_handles = { handle },
);
}
static Result _nsCmdInTmemNoOut(Service* srv, TransferMemory *tmem, u32 cmd_id) {
return _nsCmdInHandle64NoOut(srv, tmem->handle, tmem->size, cmd_id);
}
static Result _nsCmdNoIO(Service* srv, u32 cmd_id) {
return serviceDispatch(srv, cmd_id);
}
static Result _nsCmdInBool(Service* srv, u32 cmd_id, bool inval) {
static Result _nsCmdInBool(Service* srv, bool inval, u32 cmd_id) {
u8 in = inval!=0;
return serviceDispatchIn(srv, cmd_id, in);
}
static Result _nsCmdInU64(Service* srv, u32 cmd_id, u64 inval) {
static Result _nsCmdInU64(Service* srv, u64 inval, u32 cmd_id) {
return serviceDispatchIn(srv, cmd_id, inval);
}
static Result _nsCmdInU64OutU64(Service* srv, u32 cmd_id, u64 inval, u64 *out) {
static Result _nsCmdInU64OutU64(Service* srv, u64 inval, u64 *out, u32 cmd_id) {
return serviceDispatchInOut(srv, cmd_id, inval, *out);
}
static Result _nsCmdNoInOutBool(Service* srv, u32 cmd_id, bool *out) {
static Result _nsCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) {
return serviceDispatchOut(srv, cmd_id, *out);
}
static Result _nsCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) {
u8 tmpout=0;
Result rc = serviceDispatchOut(srv, cmd_id, tmpout);
Result rc = _nsCmdNoInOutU8(srv, &tmpout, cmd_id);
if (R_SUCCEEDED(rc) && out) *out = tmpout!=0;
return rc;
}
static Result _nsCmdNoInOutU64(Service* srv, u32 cmd_id, u64 *out) {
static Result _nsCmdNoInOutU64(Service* srv, u64 *out, u32 cmd_id) {
return serviceDispatchOut(srv, cmd_id, *out);
}
static Result _nsCmdNoInOutSystemUpdateProgress(Service* srv, NsSystemUpdateProgress *out, u32 cmd_id) {
return serviceDispatchOut(srv, cmd_id, *out);
}
static Result _nsCmdRequestSendReceiveSystemUpdate(Service* srv, AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info, u32 cmd_id) {
const struct {
u16 inval0;
u32 inval1;
} in = { inval0, inval1 };
memset(a, 0, sizeof(*a));
Handle event = INVALID_HANDLE;
Result rc = serviceDispatchIn(srv, cmd_id, in,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { info, sizeof(*info) } },
.out_num_objects = 1,
.out_objects = &a->s,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = &event,
);
if (R_SUCCEEDED(rc))
eventLoadRemote(&a->event, event, false);
return rc;
}
static Result _nsCmdNoInOutAsyncValue(Service* srv, AsyncValue *a, u32 cmd_id) {
memset(a, 0, sizeof(*a));
Handle event = INVALID_HANDLE;
Result rc = serviceDispatch(srv, cmd_id,
.out_num_objects = 1,
.out_objects = &a->s,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = &event,
);
if (R_SUCCEEDED(rc))
eventLoadRemote(&a->event, event, false);
return rc;
}
static Result _nsCmdNoInOutAsyncResult(Service* srv, AsyncResult *a, u32 cmd_id) {
memset(a, 0, sizeof(*a));
Handle event = INVALID_HANDLE;
Result rc = serviceDispatch(srv, cmd_id,
.out_num_objects = 1,
.out_objects = &a->s,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy },
.out_handles = &event,
);
if (R_SUCCEEDED(rc))
eventLoadRemote(&a->event, event, false);
return rc;
}
Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entry_offset, s32* out_entrycount) {
return serviceDispatchInOut(&g_nsAppManSrv, 0, entry_offset, *out_entrycount,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
@ -115,13 +199,15 @@ Result nsGetApplicationControlData(u8 flag, u64 titleID, NsApplicationControlDat
}
Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size) {
return _nsCmdInU64OutU64(&g_nsAppManSrv, 47, storage_id, size);
return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 47);
}
Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size) {
return _nsCmdInU64OutU64(&g_nsAppManSrv, 48, storage_id, size);
return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 48);
}
// ns:vm
NX_GENERATE_SERVICE_GUARD(nsvm);
Result _nsvmInitialize(void)
@ -144,7 +230,7 @@ Result nsvmNeedsUpdateVulnerability(bool *out) {
Service *srv = &g_nsAppManSrv;
if (hosversionAtLeast(3,0,0)) srv = &g_nsvmSrv;
return _nsCmdNoInOutBool(srv, 1200, out);
return _nsCmdNoInOutBool(srv, out, 1200);
}
Result nsvmGetSafeSystemVersion(u16 *out) {
@ -154,6 +240,8 @@ Result nsvmGetSafeSystemVersion(u16 *out) {
return serviceDispatchOut(&g_nsvmSrv, 1202, out);
}
// ns:dev
NX_GENERATE_SERVICE_GUARD(nsdev);
Result _nsdevInitialize(void) {
@ -174,15 +262,15 @@ Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u3
}
Result nsdevTerminateProcess(u64 pid) {
return _nsCmdInU64(&g_nsdevSrv, 1, pid);
return _nsCmdInU64(&g_nsdevSrv, pid, 1);
}
Result nsdevTerminateProgram(u64 tid) {
return _nsCmdInU64(&g_nsdevSrv, 2, tid);
return _nsCmdInU64(&g_nsdevSrv, tid, 2);
}
Result nsdevGetShellEvent(Event* out_event) {
return _appletGetEvent(&g_nsdevSrv, 4, out_event, true);
return _nsCmdGetEvent(&g_nsdevSrv, out_event, true, 4);
}
Result nsdevGetShellEventInfo(NsShellEventInfo* out) {
@ -233,17 +321,326 @@ Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 app_title
Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out) {
if (hosversionBefore(6,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoInOutBool(&g_nsdevSrv, 10, out);
return _nsCmdNoInOutBool(&g_nsdevSrv, out, 10);
}
Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid) {
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoInOutU64(&g_nsdevSrv, 11, out_pid);
return _nsCmdNoInOutU64(&g_nsdevSrv, out_pid, 11);
}
Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop(bool can_be_active) {
if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdInBool(&g_nsdevSrv, 12, can_be_active);
return _nsCmdInBool(&g_nsdevSrv, can_be_active, 12);
}
// ns:su
NX_GENERATE_SERVICE_GUARD(nssu);
Result _nssuInitialize(void) {
return smGetService(&g_nssuSrv, "ns:su");
}
void _nssuCleanup(void) {
serviceClose(&g_nssuSrv);
}
Result nssuGetBackgroundNetworkUpdateState(NsBackgroundNetworkUpdateState *out) {
u8 tmpout=0;
Result rc = _nsCmdNoInOutU8(&g_nssuSrv, &tmpout, 0);
if (R_SUCCEEDED(rc)) *out = tmpout;
return rc;
}
Result nssuOpenSystemUpdateControl(NsSystemUpdateControl *c) {
return _nsGetSession(&g_nssuSrv, &c->s, 1);
}
Result nssuNotifyExFatDriverRequired(void) {
return _nsCmdNoIO(&g_nssuSrv, 2);
}
Result nssuClearExFatDriverStatusForDebug(void) {
return _nsCmdNoIO(&g_nssuSrv, 3);
}
Result nssuRequestBackgroundNetworkUpdate(void) {
return _nsCmdNoIO(&g_nssuSrv, 4);
}
Result nssuNotifyBackgroundNetworkUpdate(const NcmContentMetaKey *key) {
return serviceDispatchIn(&g_nssuSrv, 5, *key);
}
Result nssuNotifyExFatDriverDownloadedForDebug(void) {
return _nsCmdNoIO(&g_nssuSrv, 6);
}
Result nssuGetSystemUpdateNotificationEventForContentDelivery(Event* out_event) {
return _nsCmdGetEvent(&g_nssuSrv, out_event, false, 9);
}
Result nssuNotifySystemUpdateForContentDelivery(void) {
return _nsCmdNoIO(&g_nssuSrv, 10);
}
Result nssuPrepareShutdown(void) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoIO(&g_nssuSrv, 11);
}
Result nssuDestroySystemUpdateTask(void) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoIO(&g_nssuSrv, 16);
}
Result nssuRequestSendSystemUpdate(AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdRequestSendReceiveSystemUpdate(&g_nssuSrv, a, inval0, inval1, info, 17);
}
Result nssuGetSendSystemUpdateProgress(NsSystemUpdateProgress *out) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoInOutSystemUpdateProgress(&g_nssuSrv, out, 18);
}
// ISystemUpdateControl
void nssuControlClose(NsSystemUpdateControl *c) {
serviceClose(&c->s);
tmemClose(&c->tmem);
}
static Result _nssuControlGetEulaDataSize(NsSystemUpdateControl *c, u32 cmd_id, const char* path, u64 *filesize) {
NsEulaDataPath datapath;
memset(&datapath, 0, sizeof(datapath));
strncpy(datapath.path, path, sizeof(datapath.path)-1);
return serviceDispatchOut(&c->s, cmd_id, *filesize,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
.buffers = { { &datapath, sizeof(datapath) } },
);
}
static Result _nssuControlGetEulaData(NsSystemUpdateControl *c, u32 cmd_id, const char* path, void* buffer, size_t size, u64 *filesize) {
NsEulaDataPath datapath;
memset(&datapath, 0, sizeof(datapath));
strncpy(datapath.path, path, sizeof(datapath.path)-1);
return serviceDispatchOut(&c->s, cmd_id, *filesize,
.buffer_attrs = {
SfBufferAttr_HipcMapAlias | SfBufferAttr_In,
SfBufferAttr_HipcMapAlias | SfBufferAttr_Out,
},
.buffers = {
{ &datapath, sizeof(datapath) },
{ buffer, size },
},
);
}
static Result _nssuControlCmdTmemNoOut(NsSystemUpdateControl *c, void* buffer, size_t size, u32 cmd_id) {
Result rc=0;
if (buffer==NULL) rc = tmemCreate(&c->tmem, size, Perm_None);
else rc = tmemCreateFromMemory(&c->tmem, buffer, size, Perm_None);
if (R_FAILED(rc)) return rc;
rc = _nsCmdInTmemNoOut(&c->s, &c->tmem, cmd_id);
if (R_FAILED(rc)) tmemClose(&c->tmem);
return rc;
}
Result nssuControlHasDownloaded(NsSystemUpdateControl *c, bool* out) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoInOutBool(&c->s, out, 0);
}
Result nssuControlRequestCheckLatestUpdate(NsSystemUpdateControl *c, AsyncValue *a) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoInOutAsyncValue(&c->s, a, 1);
}
Result nssuControlRequestDownloadLatestUpdate(NsSystemUpdateControl *c, AsyncResult *a) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoInOutAsyncResult(&c->s, a, 2);
}
Result nssuControlGetDownloadProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoInOutSystemUpdateProgress(&c->s, out, 3);
}
Result nssuControlApplyDownloadedUpdate(NsSystemUpdateControl *c) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoIO(&c->s, 4);
}
Result nssuControlRequestPrepareCardUpdate(NsSystemUpdateControl *c, AsyncResult *a) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoInOutAsyncResult(&c->s, a, 5);
}
Result nssuControlGetPrepareCardUpdateProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoInOutSystemUpdateProgress(&c->s, out, 6);
}
Result nssuControlHasPreparedCardUpdate(NsSystemUpdateControl *c, bool* out) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoInOutBool(&c->s, out, 7);
}
Result nssuControlApplyCardUpdate(NsSystemUpdateControl *c) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nsCmdNoIO(&c->s, 8);
}
Result nssuControlGetDownloadedEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nssuControlGetEulaDataSize(c, 9, path, filesize);
}
Result nssuControlGetDownloadedEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nssuControlGetEulaData(c, 10, path, buffer, size, filesize);
}
Result nssuControlSetupCardUpdate(NsSystemUpdateControl *c, void* buffer, size_t size) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nssuControlCmdTmemNoOut(c, buffer, size, 11);
}
Result nssuControlGetPreparedCardUpdateEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nssuControlGetEulaDataSize(c, 12, path, filesize);
}
Result nssuControlGetPreparedCardUpdateEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
return _nssuControlGetEulaData(c, 13, path, buffer, size, filesize);
}
Result nssuControlSetupCardUpdateViaSystemUpdater(NsSystemUpdateControl *c, void* buffer, size_t size) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nssuControlCmdTmemNoOut(c, buffer, size, 14);
}
Result nssuControlHasReceived(NsSystemUpdateControl *c, bool* out) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoInOutBool(&c->s, out, 15);
}
Result nssuControlRequestReceiveSystemUpdate(NsSystemUpdateControl *c, AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdRequestSendReceiveSystemUpdate(&c->s, a, inval0, inval1, info, 16);
}
Result nssuControlGetReceiveProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoInOutSystemUpdateProgress(&c->s, out, 17);
}
Result nssuControlApplyReceivedUpdate(NsSystemUpdateControl *c) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoIO(&c->s, 18);
}
Result nssuControlGetReceivedEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nssuControlGetEulaDataSize(c, 19, path, filesize);
}
Result nssuControlGetReceivedEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nssuControlGetEulaData(c, 20, path, buffer, size, filesize);
}
Result nssuControlSetupToReceiveSystemUpdate(NsSystemUpdateControl *c) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoIO(&c->s, 21);
}
Result nssuControlRequestCheckLatestUpdateIncludesRebootlessUpdate(NsSystemUpdateControl *c, AsyncValue *a) {
if (!serviceIsActive(&c->s))
return MAKERESULT(Module_Libnx, LibnxError_NotInitialized);
if (hosversionBefore(6,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _nsCmdNoInOutAsyncValue(&c->s, a, 22);
}