diff --git a/nx/include/switch/kernel/svc.h b/nx/include/switch/kernel/svc.h index b5ca1c1bb..67a993abf 100644 --- a/nx/include/switch/kernel/svc.h +++ b/nx/include/switch/kernel/svc.h @@ -212,6 +212,8 @@ typedef enum { InfoType_IoRegionHint = 27, ///< [16.0.0+] Low bits of the physical address for a KIoRegion. InfoType_AliasRegionExtraSize = 28, ///< [18.0.0+] Extra size added to the reserved region. + InfoType_TransferMemoryHint = 34, ///< [19.0.0+] Low bits of the process address for a KTransferMemory. + InfoType_ThreadTickCountDeprecated = 0xF0000002, ///< [1.0.0-12.1.0] Number of ticks spent on thread. } InfoType; @@ -262,9 +264,10 @@ typedef enum { /// WaitForAddress behaviors. typedef enum { - ArbitrationType_WaitIfLessThan = 0, ///< Wait if the value is less than argument. - ArbitrationType_DecrementAndWaitIfLessThan = 1, ///< Decrement the value and wait if it is less than argument. - ArbitrationType_WaitIfEqual = 2, ///< Wait if the value is equal to argument. + ArbitrationType_WaitIfLessThan = 0, ///< Wait if the 32-bit value is less than argument. + ArbitrationType_DecrementAndWaitIfLessThan = 1, ///< Decrement the 32-bit value and wait if it is less than argument. + ArbitrationType_WaitIfEqual = 2, ///< Wait if the 32-bit value is equal to argument. + ArbitrationType_WaitIfEqual64 = 3, ///< [19.0.0+] Wait if the 64-bit value is equal to argument. } ArbitrationType; /// Context of a scheduled thread. @@ -809,7 +812,7 @@ Result svcGetThreadContext3(ThreadContext* ctx, Handle thread); * @return Result code. * @note Syscall number 0x34. */ -Result svcWaitForAddress(void *address, u32 arb_type, s32 value, s64 timeout); +Result svcWaitForAddress(void *address, u32 arb_type, s64 value, s64 timeout); /** * @brief Signals (and updates) an address depending on type and value. [4.0.0+] diff --git a/nx/include/switch/services/caps.h b/nx/include/switch/services/caps.h index 7604389b5..24671fe8d 100644 --- a/nx/include/switch/services/caps.h +++ b/nx/include/switch/services/caps.h @@ -93,7 +93,9 @@ typedef struct { CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime u8 storage; ///< \ref CapsAlbumStorage u8 content; ///< \ref CapsAlbumFileContents - u8 pad_x12[0x6]; ///< padding + u8 unknown_12; ///< [19.0.0+] + u8 unknown_13; ///< [19.0.0+] + u8 pad_x14[0x4]; ///< padding } CapsAlbumFileId; /// AlbumEntry diff --git a/nx/include/switch/services/capsc.h b/nx/include/switch/services/capsc.h index c348022a0..d44f0c89d 100644 --- a/nx/include/switch/services/capsc.h +++ b/nx/include/switch/services/capsc.h @@ -9,6 +9,13 @@ #include "../sf/service.h" #include "../services/caps.h" +typedef struct { + u64 application_id; + u8 unknown_08; + u8 unknown_09; + u8 reserved[6]; +} CapsApplicationId; + /// Initialize caps:c Result capscInitialize(void); @@ -40,7 +47,7 @@ Result capscNotifyAlbumStorageIsUnAvailable(CapsAlbumStorage storage); * @param[in] appletResourceUserId AppletResourceUserId. * @param[in] application_id ApplicationId. */ -Result capscRegisterAppletResourceUserId(u64 appletResourceUserId, u64 application_id); +Result capscRegisterAppletResourceUserId(u64 appletResourceUserId, const CapsApplicationId *application_id); /** * @brief Unregister an applet. @@ -49,7 +56,7 @@ Result capscRegisterAppletResourceUserId(u64 appletResourceUserId, u64 applicati * @param[in] appletResourceUserId AppletResourceUserId. * @param[in] application_id ApplicationId. */ -Result capscUnregisterAppletResourceUserId(u64 appletResourceUserId, u64 application_id); +Result capscUnregisterAppletResourceUserId(u64 appletResourceUserId, const CapsApplicationId *application_id); /** * @brief Get an ApplicationId that corresponds to an AppletResourceUserId. @@ -58,7 +65,7 @@ Result capscUnregisterAppletResourceUserId(u64 appletResourceUserId, u64 applica * @param[out] application_id ApplicationId. * @param[in] appletResourceUserId AppletResourceUserId. */ -Result capscGetApplicationIdFromAruid(u64 *application_id, u64 aruid); +Result capscGetApplicationIdFromAruid(CapsApplicationId *application_id, u64 aruid); /** * @brief Checks whether an ApplicationId is registered. @@ -74,7 +81,7 @@ Result capscCheckApplicationIdRegistered(u64 application_id); * @param[in] contents \ref CapsAlbumFileContents * @param[out] file_id \ref CapsAlbumFileId */ -Result capscGenerateCurrentAlbumFileId(u64 application_id, CapsAlbumFileContents contents, CapsAlbumFileId *file_id); +Result capscGenerateCurrentAlbumFileId(const CapsApplicationId *application_id, CapsAlbumFileContents contents, CapsAlbumFileId *file_id); /** * @brief Generate an ApplicationAlbumEntry based on parameters. diff --git a/nx/include/switch/services/fs.h b/nx/include/switch/services/fs.h index 4e78e0f4b..387cccfd3 100644 --- a/nx/include/switch/services/fs.h +++ b/nx/include/switch/services/fs.h @@ -553,6 +553,8 @@ Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id); /// Retrieves the rights id and key generation corresponding to the content path. Only available on [3.0.0+], attr is ignored before [16.0.0]. Result fsGetRightsIdAndKeyGenerationByPath(const char* path, FsContentAttributes attr, u8* out_key_generation, FsRightsId* out_rights_id); +Result fsGetContentStorageInfoIndex(s32 *out); ///< [19.0.0+] + Result fsDisableAutoSaveDataCreation(void); Result fsSetGlobalAccessLogMode(u32 mode); @@ -683,7 +685,7 @@ Result fsDeviceOperatorIsGameCardInserted(FsDeviceOperator* d, bool* out); Result fsDeviceOperatorGetGameCardHandle(FsDeviceOperator* d, FsGameCardHandle* out); Result fsDeviceOperatorGetGameCardUpdatePartitionInfo(FsDeviceOperator* d, const FsGameCardHandle* handle, FsGameCardUpdatePartitionInfo* out); Result fsDeviceOperatorGetGameCardAttribute(FsDeviceOperator* d, const FsGameCardHandle* handle, u8 *out); -Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64 size); +Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64* out_size, s64 size); Result fsDeviceOperatorGetGameCardIdSet(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size); Result fsDeviceOperatorGetGameCardErrorReportInfo(FsDeviceOperator* d, FsGameCardErrorReportInfo* out); Result fsDeviceOperatorGetGameCardDeviceId(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size); diff --git a/nx/include/switch/services/ldr.h b/nx/include/switch/services/ldr.h index acc753f15..ac46c1fe1 100644 --- a/nx/include/switch/services/ldr.h +++ b/nx/include/switch/services/ldr.h @@ -20,6 +20,20 @@ typedef struct { u32 acid_fac_size; u32 aci0_fah_size; u8 ac_buffer[0x3E0]; +} LoaderProgramInfoV1; + +typedef struct { + u8 main_thread_priority; + u8 default_cpu_id; + u16 application_type; + u32 main_thread_stack_size; + u64 program_id; + u32 acid_sac_size; + u32 aci0_sac_size; + u32 acid_fac_size; + u32 aci0_fah_size; + u8 unused_20[0x10]; + u8 ac_buffer[0x3E0]; } LoaderProgramInfo; typedef struct { @@ -63,7 +77,8 @@ Result ldrDmntFlushArguments(void); Result ldrDmntGetProcessModuleInfo(u64 pid, LoaderModuleInfo *out_module_infos, size_t max_out_modules, s32 *num_out); Result ldrPmCreateProcess(u64 pin_id, u32 flags, Handle reslimit_h, Handle *out_process_h); -Result ldrPmGetProgramInfo(const NcmProgramLocation *loc, LoaderProgramInfo *out_program_info); +Result ldrPmGetProgramInfo(const NcmProgramLocation *loc, LoaderProgramInfo *out_program_info); ///< [19.0.0+/Atmosphere] +Result ldrPmGetProgramInfoV1(const NcmProgramLocation *loc, LoaderProgramInfoV1 *out_program_info); ///< [1.0.0-18.1.0/Non-Atmosphere] Result ldrPmPinProgram(const NcmProgramLocation *loc, u64 *out_pin_id); Result ldrPmUnpinProgram(u64 pin_id); Result ldrPmSetEnabledProgramVerification(bool enabled); ///< [10.0.0+] diff --git a/nx/source/services/capsc.c b/nx/source/services/capsc.c index 062e49fe7..d8eb74471 100644 --- a/nx/source/services/capsc.c +++ b/nx/source/services/capsc.c @@ -54,30 +54,34 @@ Result capscNotifyAlbumStorageIsUnAvailable(CapsAlbumStorage storage) { return _capscCmdInU8NoOut(&g_capscSrv, 2002, storage); } -Result capscRegisterAppletResourceUserId(u64 appletResourceUserId, u64 application_id) { +Result capscRegisterAppletResourceUserId(u64 appletResourceUserId, const CapsApplicationId *application_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u64 appletResourceUserId; - u64 applicationId; - } in = { appletResourceUserId, application_id }; + CapsApplicationId applicationId; + } in = { appletResourceUserId, *application_id }; return serviceDispatchIn(&g_capscSrv, 2011, in); } -Result capscUnregisterAppletResourceUserId(u64 appletResourceUserId, u64 application_id) { +Result capscUnregisterAppletResourceUserId(u64 appletResourceUserId, const CapsApplicationId *application_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u64 appletResourceUserId; - u64 applicationId; - } in = { appletResourceUserId, application_id }; + CapsApplicationId applicationId; + } in = { appletResourceUserId, *application_id }; return serviceDispatchIn(&g_capscSrv, 2012, in); } -Result capscGetApplicationIdFromAruid(u64 *application_id, u64 aruid) { +Result capscGetApplicationIdFromAruid(CapsApplicationId *application_id, u64 aruid) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - return serviceDispatchInOut(&g_capscSrv, 2013, aruid, *application_id); + + if (hosversionAtLeast(19,0,0)) + return serviceDispatchInOut(&g_capscSrv, 2013, aruid, *application_id); + else + return serviceDispatchInOut(&g_capscSrv, 2013, aruid, application_id->application_id); } Result capscCheckApplicationIdRegistered(u64 application_id) { @@ -86,13 +90,13 @@ Result capscCheckApplicationIdRegistered(u64 application_id) { return serviceDispatchIn(&g_capscSrv, 2014, application_id); } -Result capscGenerateCurrentAlbumFileId(u64 application_id, CapsAlbumFileContents contents, CapsAlbumFileId *file_id) { +Result capscGenerateCurrentAlbumFileId(const CapsApplicationId *application_id, CapsAlbumFileContents contents, CapsAlbumFileId *file_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u8 type; - u64 applicationId; - } in = { contents, application_id }; + CapsApplicationId applicationId; + } in = { contents, *application_id }; return serviceDispatchInOut(&g_capscSrv, 2101, in, *file_id); } diff --git a/nx/source/services/fs.c b/nx/source/services/fs.c index d11bbb174..d1715d26c 100644 --- a/nx/source/services/fs.c +++ b/nx/source/services/fs.c @@ -623,6 +623,13 @@ Result fsGetAndClearErrorInfo(FsFileSystemProxyErrorInfo *out) { return _fsObjectDispatchOut(&g_fsSrv, 800, *out); } +Result fsGetContentStorageInfoIndex(s32 *out) { + if (hosversionBefore(19,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _fsCmdNoInOutU32(&g_fsSrv, (u32 *)out, 820); +} + Result fsDisableAutoSaveDataCreation(void) { return _fsCmdNoIO(&g_fsSrv, 1003); } @@ -1233,15 +1240,30 @@ Result fsDeviceOperatorGetGameCardAttribute(FsDeviceOperator* d, const FsGameCar return _fsObjectDispatchInOut(&d->s, 205, *handle, *out); } -Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64 size) { +Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64* out_size, s64 size) { const struct { FsGameCardHandle handle; s64 buffer_size; } in = { *handle, size }; - return _fsObjectDispatchIn(&d->s, 206, in, + // Assume old gamecard certificate size on pre-19.0.0 + s64 os = 0x200; + Result rc; + + if (hosversionAtLeast(19,0,0)) { + rc = _fsObjectDispatchInOut(&d->s, 206, in, os, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { dst, dst_size } }); + } else { + rc = _fsObjectDispatchIn(&d->s, 206, in, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffers = { { dst, dst_size } }); + } + + if (R_SUCCEEDED(rc)) + *out_size = os; + + return rc; } Result fsDeviceOperatorGetGameCardIdSet(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size) { diff --git a/nx/source/services/ldr.c b/nx/source/services/ldr.c index 8271577d5..bc54e6a45 100644 --- a/nx/source/services/ldr.c +++ b/nx/source/services/ldr.c @@ -94,6 +94,19 @@ Result ldrPmCreateProcess(u64 pin_id, u32 flags, Handle reslimit_h, Handle *out_ } Result ldrPmGetProgramInfo(const NcmProgramLocation *loc, LoaderProgramInfo *out_program_info) { + if (!hosversionIsAtmosphere() && hosversionBefore(19, 0, 0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatchIn(&g_ldrPmSrv, 1, *loc, + .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcPointer | SfBufferAttr_FixedSize }, + .buffers = { { out_program_info, sizeof(*out_program_info) } }, + ); +} + +Result ldrPmGetProgramInfoV1(const NcmProgramLocation *loc, LoaderProgramInfoV1 *out_program_info) { + if (hosversionIsAtmosphere() || hosversionAtLeast(19,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return serviceDispatchIn(&g_ldrPmSrv, 1, *loc, .buffer_attrs = { SfBufferAttr_Out | SfBufferAttr_HipcPointer | SfBufferAttr_FixedSize }, .buffers = { { out_program_info, sizeof(*out_program_info) } }, diff --git a/nx/switch.ld b/nx/switch.ld index 3be8a25a3..29110bdbe 100644 --- a/nx/switch.ld +++ b/nx/switch.ld @@ -181,11 +181,11 @@ SECTIONS PROVIDE_HIDDEN( __bss_start__ = ADDR(.bss) ); PROVIDE_HIDDEN( __bss_end__ = __tls_end ); - PROVIDE_HIDDEN( __end__ = ABSOLUTE(.) ); + PROVIDE_HIDDEN( __end__ = . ); /* =========== Argument buffer =========== */ . = ALIGN(0x1000); - PROVIDE_HIDDEN( __argdata__ = ABSOLUTE(.) ); + PROVIDE_HIDDEN( __argdata__ = . ); /* ================== ==== Metadata ====