apt: Revamp chainload handling, see details:
- Added aptClearChainloader (clears pending chainloads) - Added aptSetChainloaderToSelf (reboots to self, i.e. "soft-reset") - Internal refactoring
This commit is contained in:
parent
80fad02255
commit
ea57fb8821
@ -227,13 +227,19 @@ void aptSetMessageCallback(aptMessageCb callback, void* user);
|
|||||||
*/
|
*/
|
||||||
void aptLaunchLibraryApplet(NS_APPID appId, void* buf, size_t bufsize, Handle handle);
|
void aptLaunchLibraryApplet(NS_APPID appId, void* buf, size_t bufsize, Handle handle);
|
||||||
|
|
||||||
|
/// Clears the chainloader state.
|
||||||
|
void aptClearChainloader(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the chainloader target.
|
* @brief Configures the chainloader to launch a specific application.
|
||||||
* @param programID ID of the program to chainload to.
|
* @param programID ID of the program to chainload to.
|
||||||
* @param mediatype Media type of the program to chainload to.
|
* @param mediatype Media type of the program to chainload to.
|
||||||
*/
|
*/
|
||||||
void aptSetChainloader(u64 programID, u8 mediatype);
|
void aptSetChainloader(u64 programID, u8 mediatype);
|
||||||
|
|
||||||
|
/// Configures the chainloader to relaunch the current application (i.e. soft-reset)
|
||||||
|
void aptSetChainloaderToSelf(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Gets an APT lock handle.
|
* @brief Gets an APT lock handle.
|
||||||
* @param flags Flags to use.
|
* @param flags Flags to use.
|
||||||
@ -394,6 +400,7 @@ Result APT_LockTransition(u32 transition, bool flag);
|
|||||||
/**
|
/**
|
||||||
* @brief Tries to lock a transition (?).
|
* @brief Tries to lock a transition (?).
|
||||||
* @param transition Transition ID.
|
* @param transition Transition ID.
|
||||||
|
* @param succeeded Pointer to output whether the lock was successfully applied.
|
||||||
*/
|
*/
|
||||||
Result APT_TryLockTransition(u32 transition, bool* succeeded);
|
Result APT_TryLockTransition(u32 transition, bool* succeeded);
|
||||||
|
|
||||||
|
@ -58,12 +58,14 @@ enum
|
|||||||
FLAG_CANCELLED = BIT(10),
|
FLAG_CANCELLED = BIT(10),
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
|
FLAG_CHAINLOAD = BIT(30),
|
||||||
FLAG_SPURIOUS = BIT(31),
|
FLAG_SPURIOUS = BIT(31),
|
||||||
};
|
};
|
||||||
|
|
||||||
static u8 aptHomeButtonState;
|
static u8 aptHomeButtonState;
|
||||||
static u32 aptFlags;
|
static u32 aptFlags;
|
||||||
static u32 aptParameters[0x1000/4];
|
static u32 aptParameters[0x1000/4];
|
||||||
|
static u8 aptChainloadFlags;
|
||||||
static u64 aptChainloadTid;
|
static u64 aptChainloadTid;
|
||||||
static u8 aptChainloadMediatype;
|
static u8 aptChainloadMediatype;
|
||||||
|
|
||||||
@ -217,8 +219,9 @@ Result aptInit(void)
|
|||||||
ret = APT_Enable(attr);
|
ret = APT_Enable(attr);
|
||||||
if (R_FAILED(ret)) goto _fail3;
|
if (R_FAILED(ret)) goto _fail3;
|
||||||
|
|
||||||
// Get information about ourselves
|
// If the homebrew environment requires it, chainload-to-self by default
|
||||||
APT_GetAppletInfo(envGetAptAppId(), &aptChainloadTid, &aptChainloadMediatype, NULL, NULL, NULL);
|
if (aptIsChainload())
|
||||||
|
aptSetChainloaderToSelf();
|
||||||
|
|
||||||
// Wait for wakeup
|
// Wait for wakeup
|
||||||
aptWaitForWakeUp(TR_ENABLE);
|
aptWaitForWakeUp(TR_ENABLE);
|
||||||
@ -306,16 +309,32 @@ static void aptClearJumpToHome(void)
|
|||||||
APT_SleepIfShellClosed();
|
APT_SleepIfShellClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aptClearChainloader(void)
|
||||||
|
{
|
||||||
|
aptFlags &= ~FLAG_CHAINLOAD;
|
||||||
|
}
|
||||||
|
|
||||||
void aptSetChainloader(u64 programID, u8 mediatype)
|
void aptSetChainloader(u64 programID, u8 mediatype)
|
||||||
{
|
{
|
||||||
|
aptFlags |= FLAG_CHAINLOAD;
|
||||||
|
aptChainloadFlags = 0;
|
||||||
aptChainloadTid = programID;
|
aptChainloadTid = programID;
|
||||||
aptChainloadMediatype = mediatype;
|
aptChainloadMediatype = mediatype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aptSetChainloaderToSelf(void)
|
||||||
|
{
|
||||||
|
aptFlags |= FLAG_CHAINLOAD;
|
||||||
|
aptChainloadFlags = 2;
|
||||||
|
aptChainloadTid = 0;
|
||||||
|
aptChainloadMediatype = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void (*__system_retAddr)(void);
|
||||||
|
|
||||||
static void aptExitProcess(void)
|
static void aptExitProcess(void)
|
||||||
{
|
{
|
||||||
APT_CloseApplication(NULL, 0, 0);
|
APT_CloseApplication(NULL, 0, 0);
|
||||||
svcExitProcess();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void aptExit(void)
|
void aptExit(void)
|
||||||
@ -326,41 +345,60 @@ void aptExit(void)
|
|||||||
|
|
||||||
if (!aptIsCrippled())
|
if (!aptIsCrippled())
|
||||||
{
|
{
|
||||||
bool closing = aptShouldClose();
|
bool doClose;
|
||||||
if (closing)
|
if (aptShouldClose())
|
||||||
|
{
|
||||||
|
// The system instructed us to close, so do just that
|
||||||
aptCallHook(APTHOOK_ONEXIT);
|
aptCallHook(APTHOOK_ONEXIT);
|
||||||
if (closing || !aptIsReinit())
|
doClose = true;
|
||||||
|
}
|
||||||
|
else if (aptIsReinit())
|
||||||
{
|
{
|
||||||
if (!closing && aptIsChainload())
|
// The homebrew environment expects APT to be reinitializable, so unregister ourselves without closing
|
||||||
|
APT_Finalize(envGetAptAppId());
|
||||||
|
doClose = false;
|
||||||
|
}
|
||||||
|
else if (aptFlags & FLAG_CHAINLOAD)
|
||||||
{
|
{
|
||||||
// Check if Home Menu exists and has been launched
|
// A chainload target is configured, so perform a jump to it
|
||||||
|
// Doing this requires help from HOME menu, so ensure that it is running
|
||||||
bool hmRegistered;
|
bool hmRegistered;
|
||||||
if (R_SUCCEEDED(APT_IsRegistered(APPID_HOMEMENU, &hmRegistered)) && hmRegistered)
|
if (R_SUCCEEDED(APT_IsRegistered(aptGetMenuAppID(), &hmRegistered)) && hmRegistered)
|
||||||
{
|
{
|
||||||
// Normal, sane chainload
|
// Normal, sane chainload
|
||||||
u8 param[0x300] = {0};
|
u8 param[0x300] = {0};
|
||||||
u8 hmac[0x20] = {0};
|
u8 hmac[0x20] = {0};
|
||||||
APT_PrepareToDoApplicationJump(0, aptChainloadTid, aptChainloadMediatype);
|
APT_PrepareToDoApplicationJump(aptChainloadFlags, aptChainloadTid, aptChainloadMediatype);
|
||||||
APT_DoApplicationJump(param, sizeof(param), hmac);
|
APT_DoApplicationJump(param, sizeof(param), hmac);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Dirty workaround w/ custom notification
|
// XX: HOME menu doesn't exist, so we need to use a workaround provided by Luma3DS
|
||||||
APT_Finalize(envGetAptAppId());
|
APT_Finalize(envGetAptAppId());
|
||||||
srvPublishToSubscriber(0x3000, 0);
|
srvPublishToSubscriber(0x3000, 0);
|
||||||
}
|
}
|
||||||
while (aptMainLoop())
|
|
||||||
svcSleepThread(25*1000*1000);
|
// After a chainload has been applied, we don't need to manually close
|
||||||
|
doClose = false;
|
||||||
|
__system_retAddr = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// None of the other situations apply, so close anyway by default
|
||||||
|
doClose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If needed, perform the APT application closing sequence
|
||||||
|
if (doClose)
|
||||||
|
{
|
||||||
APT_PrepareToCloseApplication(true);
|
APT_PrepareToCloseApplication(true);
|
||||||
|
|
||||||
extern void (*__system_retAddr)(void);
|
// APT_CloseApplication kills us if we aren't signed up for srv closing notifications, so
|
||||||
|
// defer APT_CloseApplication for as long as possible (TODO: actually use srv notif instead)
|
||||||
__system_retAddr = aptExitProcess;
|
__system_retAddr = aptExitProcess;
|
||||||
closeAptLock = false;
|
closeAptLock = false;
|
||||||
srvInit(); // Keep srv initialized
|
srvInit(); // Keep srv initialized
|
||||||
} else
|
}
|
||||||
APT_Finalize(envGetAptAppId());
|
|
||||||
|
|
||||||
aptEventHandlerThreadQuit = true;
|
aptEventHandlerThreadQuit = true;
|
||||||
svcSignalEvent(aptEvents[0]);
|
svcSignalEvent(aptEvents[0]);
|
||||||
|
Loading…
Reference in New Issue
Block a user