Implement RUNFLAG_APTCHAINLOAD

This commit is contained in:
fincs 2017-04-14 22:01:13 +02:00
parent 3f7a4d227d
commit 1ed97e8ba2
3 changed files with 38 additions and 2 deletions

View File

@ -8,6 +8,7 @@
enum { enum {
RUNFLAG_APTWORKAROUND = BIT(0), ///< Use APT workaround. RUNFLAG_APTWORKAROUND = BIT(0), ///< Use APT workaround.
RUNFLAG_APTREINIT = BIT(1), ///< Reinitialize APT. RUNFLAG_APTREINIT = BIT(1), ///< Reinitialize APT.
RUNFLAG_APTCHAINLOAD = BIT(2), ///< Chainload APT on return.
}; };
/** /**

View File

@ -195,6 +195,13 @@ void aptSetMessageCallback(aptMessageCb callback, void* user);
*/ */
bool aptLaunchLibraryApplet(NS_APPID appId, void* buf, size_t bufsize, Handle handle); bool aptLaunchLibraryApplet(NS_APPID appId, void* buf, size_t bufsize, Handle handle);
/**
* @brief Sets the chainloader target.
* @param programID ID of the program to chainload to.
* @param mediatype Media type of the program to chainload to.
*/
void aptSetChainloader(u64 programID, u8 mediatype);
/** /**
* @brief Gets an APT lock handle. * @brief Gets an APT lock handle.
* @param flags Flags to use. * @param flags Flags to use.

View File

@ -42,6 +42,8 @@ enum
static u8 aptHomeButtonState; static u8 aptHomeButtonState;
static u32 aptFlags = FLAG_ALLOWSLEEP; static u32 aptFlags = FLAG_ALLOWSLEEP;
static u32 aptParameters[0x1000/4]; static u32 aptParameters[0x1000/4];
static u64 aptChainloadTid;
static u8 aptChainloadMediatype;
typedef enum typedef enum
{ {
@ -74,9 +76,15 @@ static bool aptIsReinit(void)
return (envGetSystemRunFlags() & RUNFLAG_APTREINIT) != 0; return (envGetSystemRunFlags() & RUNFLAG_APTREINIT) != 0;
} }
static bool aptIsChainload(void)
{
return (envGetSystemRunFlags() & RUNFLAG_APTCHAINLOAD) != 0;
}
static bool aptIsCrippled(void) static bool aptIsCrippled(void)
{ {
return (envGetSystemRunFlags() & RUNFLAG_APTWORKAROUND) != 0 && !aptIsReinit(); u32 flags = envGetSystemRunFlags();
return (flags & RUNFLAG_APTWORKAROUND) && !(flags & RUNFLAG_APTREINIT);
} }
static Result aptGetServiceHandle(Handle* aptuHandle) static Result aptGetServiceHandle(Handle* aptuHandle)
@ -203,6 +211,9 @@ Result aptInit(void)
aptEventHandlerThread = threadCreate(aptEventHandler, 0x0, APT_HANDLER_STACKSIZE, 0x31, -2, true); aptEventHandlerThread = threadCreate(aptEventHandler, 0x0, APT_HANDLER_STACKSIZE, 0x31, -2, true);
if (!aptEventHandlerThread) goto _fail4; if (!aptEventHandlerThread) goto _fail4;
// Get information about ourselves
APT_GetAppletInfo(envGetAptAppId(), &aptChainloadTid, &aptChainloadMediatype, NULL, NULL, NULL);
// Special handling for aptReinit (aka hax) // Special handling for aptReinit (aka hax)
APT_Transition transition = TR_ENABLE; APT_Transition transition = TR_ENABLE;
if (aptIsReinit()) if (aptIsReinit())
@ -256,6 +267,12 @@ void aptSetSleepAllowed(bool allowed)
} }
} }
void aptSetChainloader(u64 programID, u8 mediatype)
{
aptChainloadTid = programID;
aptChainloadMediatype = mediatype;
}
static void aptExitProcess(void) static void aptExitProcess(void)
{ {
APT_CloseApplication(NULL, 0, 0); APT_CloseApplication(NULL, 0, 0);
@ -270,8 +287,19 @@ void aptExit(void)
if (!aptIsCrippled()) if (!aptIsCrippled())
{ {
if ((aptFlags & FLAG_EXITED) || !aptIsReinit()) bool exited = (aptFlags & FLAG_EXITED) != 0;
if (exited || !aptIsReinit())
{ {
if (!exited && aptIsChainload())
{
u8 param[0x300] = {0};
u8 hmac[0x20] = {0};
APT_PrepareToDoApplicationJump(0, aptChainloadTid, aptChainloadMediatype);
APT_DoApplicationJump(param, sizeof(param), hmac);
while (aptMainLoop())
svcSleepThread(25*1000*1000);
}
APT_PrepareToCloseApplication(true); APT_PrepareToCloseApplication(true);
extern void (*__system_retAddr)(void); extern void (*__system_retAddr)(void);