From 1b63a03b01274c1faa4a953585bd5604a787f988 Mon Sep 17 00:00:00 2001 From: niklascfw Date: Fri, 3 Jul 2026 17:17:56 +0200 Subject: [PATCH] Reboot to Hekate menu once without changing hekate_ipl.ini Mariko: RTC REBOOT_REASON_MENU + PMIC reboot. Erista: patch in-memory boot_cfg on valid Hekate payload and try common SD paths. --- source/main.c | 36 +++++++++++++++++++++++- source/tegraexplorer/mainmenu.c | 6 ++-- source/utils/utils.c | 50 ++++++++++++++++++++++++++++++++- source/utils/utils.h | 4 +++ 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/source/main.c b/source/main.c index 476e45f..c2dec3b 100644 --- a/source/main.c +++ b/source/main.c @@ -94,7 +94,26 @@ void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size) } } -int launch_payload(char *path) +#define HEKATE_BOOT_CFG_OFFSET 0x94 +#define HEKATE_MAGIC_OFFSET 0x118 +#define HEKATE_MAGIC 0x43544349u +#define HEKATE_PAYLOAD_MAX 0x24000 + +static void _patch_hekate_menu_skip(void *buf, u32 size) +{ + if (size > HEKATE_PAYLOAD_MAX) + return; + + if (*(u32 *)((u8 *)buf + HEKATE_MAGIC_OFFSET) != HEKATE_MAGIC) + return; + + boot_cfg_t *cfg = (boot_cfg_t *)((u8 *)buf + HEKATE_BOOT_CFG_OFFSET); + memset(cfg, 0, sizeof(boot_cfg_t)); + cfg->boot_cfg = 1; + cfg->autoboot = 0; +} + +int launch_payload_ex(char *path, bool force_hekate_menu) { gfx_clear_grey(0x1B); gfx_con_setpos(0, 0); @@ -134,6 +153,16 @@ int launch_payload(char *path) f_close(&fp); + if (force_hekate_menu) + { + if (size > HEKATE_PAYLOAD_MAX || *(u32 *)((u8 *)buf + HEKATE_MAGIC_OFFSET) != HEKATE_MAGIC) + { + sd_unmount(); + return 2; + } + _patch_hekate_menu_skip(buf, size); + } + sd_unmount(); if (size < 0x30000) @@ -160,6 +189,11 @@ int launch_payload(char *path) return 1; } +int launch_payload(char *path) +{ + return launch_payload_ex(path, false); +} + extern void pivot_stack(u32 stack_top); #define EXCP_EN_ADDR 0x4003FFFC diff --git a/source/tegraexplorer/mainmenu.c b/source/tegraexplorer/mainmenu.c index 9d8f2d0..9a6ab37 100644 --- a/source/tegraexplorer/mainmenu.c +++ b/source/tegraexplorer/mainmenu.c @@ -105,10 +105,8 @@ void HandleSD(){ extern bool is_sd_inited; -extern int launch_payload(char *path); - void RebootToHekate(){ - launch_payload("sd:/bootloader/update.bin"); + reboot_to_hekate_menu(); } void MountOrUnmountSD(){ @@ -153,7 +151,7 @@ void EnterMainMenu(){ sd_unmount(); // // -- Exit -- - mainMenuEntries[MainRebootHekate].hide = (!sd_get_card_mounted() || !FileExists("sd:/bootloader/update.bin")); + mainMenuEntries[MainRebootHekate].hide = !h_cfg.t210b01 && (!sd_get_card_mounted() || !hekate_reboot_available()); mainMenuEntries[MainRebootRCM].hide = h_cfg.t210b01; mainMenuEntries[FixMarikoWarmbootSleep].hide = !h_cfg.t210b01; diff --git a/source/utils/utils.c b/source/utils/utils.c index df23a9f..e963576 100644 --- a/source/utils/utils.c +++ b/source/utils/utils.c @@ -11,10 +11,58 @@ #include "../hid/hid.h" #include "../fs/fsutils.h" #include "../config.h" +#include +#include extern hekate_config h_cfg; -extern int launch_payload(char *path); +extern int launch_payload_ex(char *path, bool force_hekate_menu); + +static const char *hekate_payload_paths[] = { + "sd:/atmosphere/reboot_payload.bin", + "sd:/bootloader/update.bin", + "sd:/bootloader/payloads/hekate.bin", + "sd:/sept/payload.bin", +}; + +bool hekate_reboot_available(void) +{ + if (h_cfg.t210b01) + return true; + + for (u32 i = 0; i < sizeof(hekate_payload_paths) / sizeof(hekate_payload_paths[0]); i++) + { + if (FileExists(hekate_payload_paths[i])) + return true; + } + + return false; +} + +void reboot_to_hekate_menu(void) +{ + if (h_cfg.t210b01) + { + rtc_reboot_reason_t rr = {0}; + rr.dec.reason = REBOOT_REASON_MENU; + max77620_rtc_set_reboot_reason(&rr); + power_set_state(POWER_OFF_REBOOT); + return; + } + + for (u32 i = 0; i < sizeof(hekate_payload_paths) / sizeof(hekate_payload_paths[0]); i++) + { + if (!FileExists(hekate_payload_paths[i])) + continue; + + if (launch_payload_ex((char *)hekate_payload_paths[i], true) != 2) + return; + } + + gfx_clearscreen(); + gfx_printf("\n\nHekate nicht gefunden.\n\nDruecke eine Taste um zurueckzukehren"); + hidWait(); +} void inline __attribute__((always_inline)) power_off(){ power_set_state(POWER_OFF_RESET); diff --git a/source/utils/utils.h b/source/utils/utils.h index d62bf72..ef1f1d2 100644 --- a/source/utils/utils.h +++ b/source/utils/utils.h @@ -6,6 +6,10 @@ void MaskIn(char *mod, u32 bitstream, char mask); bool StrEndsWith(char *begin, char *end); void WaitFor(u32 ms); void RebootToPayloadOrRcm(); +void reboot_to_hekate_menu(void); +bool hekate_reboot_available(void); +int launch_payload_ex(char *path, bool force_hekate_menu); +int launch_payload(char *path); #define FREE(x) free(x); x = NULL; char *ShowKeyboard(const char *toEdit, u8 alwaysRet);