diff --git a/libctru/include/3ds/services/apt.h b/libctru/include/3ds/services/apt.h index 6f9f6d6f7..ff4bb574c 100644 --- a/libctru/include/3ds/services/apt.h +++ b/libctru/include/3ds/services/apt.h @@ -237,9 +237,22 @@ void aptClearChainloader(void); */ void aptSetChainloader(u64 programID, u8 mediatype); +/// Configures the chainloader to launch the previous application. +void aptSetChainloaderToCaller(void); + /// Configures the chainloader to relaunch the current application (i.e. soft-reset) void aptSetChainloaderToSelf(void); +/** + * @brief Sets the "deliver arg" and HMAC for the chainloader, which will + * be passed to the target 3DS/DS(i) application. The meaning of each + * parameter varies on a per-application basis. + * @param deliverArg Deliver arg to pass to the target application. + * @param deliverArgSize Size of the deliver arg, maximum 0x300 bytes. + * @param hmac HMAC buffer, 32 bytes. Use NULL to pass an all-zero dummy HMAC. + */ +void aptSetChainloaderArgs(const void *deliverArg, size_t deliverArgSize, const void *hmac); + /** * @brief Gets an APT lock handle. * @param flags Flags to use. @@ -565,4 +578,4 @@ Result APT_GetSharedFont(Handle* fontHandle, u32* mapAddr); * @param sender Pointer to output the sender's AppID to. * @param received Pointer to output whether an argument was received to. */ -Result APT_ReceiveDeliverArg(const void* param, size_t paramSize, const void* hmac, u64* sender, bool* received); +Result APT_ReceiveDeliverArg(void* param, size_t paramSize, void* hmac, u64* sender, bool* received); diff --git a/libctru/source/services/apt.c b/libctru/source/services/apt.c index e5078974f..93743de1d 100644 --- a/libctru/source/services/apt.c +++ b/libctru/source/services/apt.c @@ -63,9 +63,12 @@ enum static u8 aptHomeButtonState; static u32 aptFlags; static u32 aptParameters[0x1000/4]; -static u8 aptChainloadFlags; static u64 aptChainloadTid; +static u8 aptChainloadDeliverArg[0x300]; +static u32 aptChainloadDeliverArgSize = sizeof(aptChainloadDeliverArg); +static u8 aptChainloadHmac[0x20]; static u8 aptChainloadMediatype; +static u8 aptChainloadFlags; typedef enum { @@ -315,6 +318,9 @@ static void aptClearJumpToHome(void) void aptClearChainloader(void) { aptFlags &= ~FLAG_CHAINLOAD; + aptChainloadDeliverArgSize = sizeof(aptChainloadDeliverArg); + memset(aptChainloadDeliverArg, 0, sizeof(aptChainloadDeliverArg)); + memset(aptChainloadHmac, 0, sizeof(aptChainloadHmac)); } void aptSetChainloader(u64 programID, u8 mediatype) @@ -325,6 +331,14 @@ void aptSetChainloader(u64 programID, u8 mediatype) aptChainloadMediatype = mediatype; } +void aptSetChainloaderToCaller(void) +{ + aptFlags |= FLAG_CHAINLOAD; + aptChainloadFlags = 1; + aptChainloadTid = 0; + aptChainloadMediatype = 0; +} + void aptSetChainloaderToSelf(void) { aptFlags |= FLAG_CHAINLOAD; @@ -333,6 +347,20 @@ void aptSetChainloaderToSelf(void) aptChainloadMediatype = 0; } +void aptSetChainloaderArgs(const void *deliverArg, size_t deliverArgSize, const void *hmac) +{ + if (deliverArgSize >= sizeof(aptChainloadDeliverArg)) + deliverArgSize = sizeof(aptChainloadDeliverArg); + + aptChainloadDeliverArgSize = deliverArgSize; + memcpy(aptChainloadDeliverArg, deliverArg, deliverArgSize); + + if (hmac != NULL) + memcpy(aptChainloadHmac, hmac, sizeof(aptChainloadHmac)); + else + memset(aptChainloadHmac, 0, sizeof(aptChainloadHmac)); +} + extern void (*__system_retAddr)(void); static void aptExitProcess(void) @@ -370,10 +398,8 @@ void aptExit(void) if (R_SUCCEEDED(APT_IsRegistered(aptGetMenuAppID(), &hmRegistered)) && hmRegistered) { // Normal, sane chainload - u8 param[0x300] = {0}; - u8 hmac[0x20] = {0}; APT_PrepareToDoApplicationJump(aptChainloadFlags, aptChainloadTid, aptChainloadMediatype); - APT_DoApplicationJump(param, sizeof(param), hmac); + APT_DoApplicationJump(aptChainloadDeliverArg, aptChainloadDeliverArgSize, aptChainloadHmac); } else { @@ -1430,7 +1456,7 @@ Result APT_GetSharedFont(Handle* fontHandle, u32* mapAddr) return ret; } -Result APT_ReceiveDeliverArg(const void* param, size_t paramSize, const void* hmac, u64* sender, bool* received) +Result APT_ReceiveDeliverArg(void* param, size_t paramSize, void* hmac, u64* sender, bool* received) { u32 cmdbuf[16]; cmdbuf[0]=IPC_MakeHeader(0x35,2,0); // 0x350080