From 1d7cca25d17ce8cdf4fb15e30bc50de63391bee1 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Wed, 8 Feb 2023 16:14:59 +0000 Subject: [PATCH] Fix long-standing bug affecting hbldr TID change option This was a long-standing bug since Luma3DS v8.0. If you changed the homebrew title and didn't immediately reboot, then the ExHeader during termination would not match the ExHeader that was was used for loading the process, and thus sysmodule process refcounts would get all messed up. The obvious solution to this is to ensure no application is running while changing the hbldr titleID (hence the changes in custom PM). This was quite possibly one of the cause of homebrew failing to load when using N3DS H&S. --- sysmodules/loader/source/luma_shared_config.h | 7 +++-- sysmodules/loader/source/main.c | 4 ++- sysmodules/pm/pm.rsf | 2 +- sysmodules/pm/source/luma_shared_config.h | 29 ++++++++++++++++++ sysmodules/pm/source/process_monitor.c | 6 ++++ .../rosalina/include/luma_shared_config.h | 7 +++-- sysmodules/rosalina/source/luma_config.c | 2 +- sysmodules/rosalina/source/main.c | 8 ++--- .../rosalina/source/menus/miscellaneous.c | 30 ++++++++++++------- 9 files changed, 72 insertions(+), 23 deletions(-) create mode 100644 sysmodules/pm/source/luma_shared_config.h diff --git a/sysmodules/loader/source/luma_shared_config.h b/sysmodules/loader/source/luma_shared_config.h index ac7eab2..165b130 100644 --- a/sysmodules/loader/source/luma_shared_config.h +++ b/sysmodules/loader/source/luma_shared_config.h @@ -18,10 +18,11 @@ #include <3ds/types.h> -/// Luma shared config type. +/// Luma shared config type (private!). typedef struct LumaSharedConfig { - u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading. - bool use_hbldr; ///< Whether or not Loader should use hb:ldr (reset to true). + u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading (current). + u64 selected_hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading (to be moved to "current" when the current app closes). + bool use_hbldr; ///< Whether or not Loader should use hb:ldr (reset to true). } LumaSharedConfig; /// Luma shared config. diff --git a/sysmodules/loader/source/main.c b/sysmodules/loader/source/main.c index 17f3458..29581ac 100644 --- a/sysmodules/loader/source/main.c +++ b/sysmodules/loader/source/main.c @@ -66,7 +66,9 @@ static inline void loadCFWInfo(void) isSdMode = true; } - Luma_SharedConfig->hbldr_3dsx_tid = hbldrTid == 0 ? HBLDR_DEFAULT_3DSX_TID : hbldrTid; + hbldrTid = hbldrTid == 0 ? HBLDR_DEFAULT_3DSX_TID : hbldrTid; + Luma_SharedConfig->hbldr_3dsx_tid = hbldrTid; + Luma_SharedConfig->selected_hbldr_3dsx_tid = hbldrTid; Luma_SharedConfig->use_hbldr = true; } diff --git a/sysmodules/pm/pm.rsf b/sysmodules/pm/pm.rsf index f98f095..41c1ec7 100644 --- a/sysmodules/pm/pm.rsf +++ b/sysmodules/pm/pm.rsf @@ -25,7 +25,7 @@ AccessControlInfo: DisableDebug : false EnableForceDebug : false - CanWriteSharedPage : false + CanWriteSharedPage : true # changed CanUsePrivilegedPriority : false CanUseNonAlphabetAndNumber : false PermitMainFunctionArgument : false diff --git a/sysmodules/pm/source/luma_shared_config.h b/sysmodules/pm/source/luma_shared_config.h new file mode 100644 index 0000000..165b130 --- /dev/null +++ b/sysmodules/pm/source/luma_shared_config.h @@ -0,0 +1,29 @@ +/* This paricular file is licensed under the following terms: */ + +/* +* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable +* for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it +* and redistribute it freely, subject to the following restrictions: +* +* The origin of this software must not be misrepresented; you must not claim that you wrote the original software. +* If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +* +* Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +* This notice may not be removed or altered from any source distribution. +*/ + +#pragma once + +#include <3ds/types.h> + +/// Luma shared config type (private!). +typedef struct LumaSharedConfig { + u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading (current). + u64 selected_hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading (to be moved to "current" when the current app closes). + bool use_hbldr; ///< Whether or not Loader should use hb:ldr (reset to true). +} LumaSharedConfig; + +/// Luma shared config. +#define Luma_SharedConfig ((volatile LumaSharedConfig *)(OS_SHAREDCFG_VADDR + 0x800)) diff --git a/sysmodules/pm/source/process_monitor.c b/sysmodules/pm/source/process_monitor.c index c2847d6..0e05d4a 100644 --- a/sysmodules/pm/source/process_monitor.c +++ b/sysmodules/pm/source/process_monitor.c @@ -6,6 +6,7 @@ #include "reslimit.h" #include "manager.h" #include "util.h" +#include "luma_shared_config.h" static void cleanupProcess(ProcessData *process) { @@ -33,6 +34,11 @@ static void cleanupProcess(ProcessData *process) assertSuccess(resetAppMemLimit()); } g_manager.runningApplicationData = NULL; + + // We need to do this here to ensure that the ExHeader at init matches the ExHeader + // at termination at all times, otherwise the process refcounts of sysmodules + // get all messed up. + Luma_SharedConfig->hbldr_3dsx_tid = Luma_SharedConfig->selected_hbldr_3dsx_tid; } if (g_manager.debugData != NULL && process->handle == g_manager.debugData->handle) { diff --git a/sysmodules/rosalina/include/luma_shared_config.h b/sysmodules/rosalina/include/luma_shared_config.h index ac7eab2..165b130 100644 --- a/sysmodules/rosalina/include/luma_shared_config.h +++ b/sysmodules/rosalina/include/luma_shared_config.h @@ -18,10 +18,11 @@ #include <3ds/types.h> -/// Luma shared config type. +/// Luma shared config type (private!). typedef struct LumaSharedConfig { - u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading. - bool use_hbldr; ///< Whether or not Loader should use hb:ldr (reset to true). + u64 hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading (current). + u64 selected_hbldr_3dsx_tid; ///< Title ID to use for 3DSX loading (to be moved to "current" when the current app closes). + bool use_hbldr; ///< Whether or not Loader should use hb:ldr (reset to true). } LumaSharedConfig; /// Luma shared config. diff --git a/sysmodules/rosalina/source/luma_config.c b/sysmodules/rosalina/source/luma_config.c index a2cb809..5f1bb49 100644 --- a/sysmodules/rosalina/source/luma_config.c +++ b/sysmodules/rosalina/source/luma_config.c @@ -220,7 +220,7 @@ Result LumaConfig_SaveSettings(void) configData.multiConfig = multiConfig; configData.bootConfig = bootConfig; configData.splashDurationMsec = splashDurationMsec; - configData.hbldr3dsxTitleId = Luma_SharedConfig->hbldr_3dsx_tid; + configData.hbldr3dsxTitleId = Luma_SharedConfig->selected_hbldr_3dsx_tid; configData.rosalinaMenuCombo = menuCombo; configData.ntpTzOffetMinutes = (s16)lastNtpTzOffset; configData.topScreenFilter = topScreenFilter; diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index eb0bbef..d61b740 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -87,10 +87,6 @@ void initSystem(void) svcGetSystemInfo(&out, 0x10000, 0x103); lastNtpTzOffset = (s16)out; - miscellaneousMenu.items[0].title = Luma_SharedConfig->hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID ? - "Switch the hb. title to the current app." : - "Switch the hb. title to " HBLDR_DEFAULT_3DSX_TITLE_NAME; - for(res = 0xD88007FA; res == (Result)0xD88007FA; svcSleepThread(500 * 1000LL)) { res = srvInit(); @@ -107,6 +103,10 @@ void initSystem(void) if (R_FAILED(FSUSER_SetPriority(-16))) svcBreak(USERBREAK_PANIC); + miscellaneousMenu.items[0].title = Luma_SharedConfig->selected_hbldr_3dsx_tid == HBLDR_DEFAULT_3DSX_TID ? + "Switch the hb. title to the current app." : + "Switch the hb. title to " HBLDR_DEFAULT_3DSX_TITLE_NAME; + // **** DO NOT init services that don't come from KIPs here **** // Instead, init the service only where it's actually init (then deinit it). diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index 7ed33ec..534e2c2 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -88,20 +88,19 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void) { Result res; char failureReason[64]; - u64 currentTid = Luma_SharedConfig->hbldr_3dsx_tid; + u64 currentTid = Luma_SharedConfig->selected_hbldr_3dsx_tid; u64 newTid = currentTid; + FS_ProgramInfo progInfo; + u32 pid; + u32 launchFlags; + res = PMDBG_GetCurrentAppInfo(&progInfo, &pid, &launchFlags); + bool appRunning = R_SUCCEEDED(res); + if(compareTids(currentTid, HBLDR_DEFAULT_3DSX_TID)) { - FS_ProgramInfo progInfo; - u32 pid; - u32 launchFlags; - res = PMDBG_GetCurrentAppInfo(&progInfo, &pid, &launchFlags); - if(R_SUCCEEDED(res)) - { + if(appRunning) newTid = progInfo.programId; - Luma_SharedConfig->hbldr_3dsx_tid = progInfo.programId; - } else { res = -1; @@ -114,7 +113,18 @@ void MiscellaneousMenu_SwitchBoot3dsxTargetTitle(void) newTid = HBLDR_DEFAULT_3DSX_TID; } - Luma_SharedConfig->hbldr_3dsx_tid = newTid; + Luma_SharedConfig->selected_hbldr_3dsx_tid = newTid; + + // Move "selected" field to "current" if no app is currently running. + // Otherwise, PM will do it on app exit. + // There's a small possibility of race condition but it shouldn't matter + // here. + // We need to do that to ensure that the ExHeader at init matches the ExHeader + // at termination at all times, otherwise the process refcounts of sysmodules + // get all messed up. + if (!appRunning) + Luma_SharedConfig->hbldr_3dsx_tid = newTid; + if (compareTids(newTid, HBLDR_DEFAULT_3DSX_TID)) miscellaneousMenu.items[0].title = "Switch the hb. title to the current app."; else