From 2fb37db707614ed20a1d2431a077ed7209c506bd Mon Sep 17 00:00:00 2001 From: Kostas Missos Date: Sun, 24 Feb 2019 02:43:13 +0200 Subject: [PATCH] [Boot Config] Add HOS reboot to config This storage allows you to reboot from HOS to the selected ini boot entry. In the future it will be used for far more. --- Makefile | 9 ++- README.md | 19 +++++- bootloader/link.ld | 4 +- bootloader/main.c | 143 ++++++++++++++++++++++++++++++--------- bootloader/soc/hw_init.c | 2 +- bootloader/utils/types.h | 12 ++++ 6 files changed, 150 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index e5aae46..2fa70b3 100755 --- a/Makefile +++ b/Makefile @@ -4,9 +4,11 @@ endif include $(DEVKITARM)/base_rules -TARGET := hekate +IPL_LOAD_ADDR := 0x40008000 BLVERSION_MAJOR := 4 BLVERSION_MINOR := 6 + +TARGET := hekate BUILD := build OUTPUT := output SOURCEDIR = bootloader @@ -62,14 +64,15 @@ OBJS += $(addprefix $(BUILD)/$(TARGET)/, \ elfload.o elfreloc_arm.o \ ) -CUSTOMDEFINES := -DBLVERSIONMJ=$(BLVERSION_MAJOR) -DBLVERSIONMN=$(BLVERSION_MINOR) -DMENU_LOGO_ENABLE +CUSTOMDEFINES := -DBLVERSIONMJ=$(BLVERSION_MAJOR) -DBLVERSIONMN=$(BLVERSION_MINOR) -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) +CUSTOMDEFINES += -DMENU_LOGO_ENABLE #CUSTOMDEFINES += -DDEBUG # 0: UART_A, 1: UART_B. #CUSTOMDEFINES += -DDEBUG_UART_PORT=0 ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork CFLAGS = $(ARCH) -O2 -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -std=gnu11 -Wall $(CUSTOMDEFINES) -LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections +LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) MODULEDIRS := $(wildcard modules/*) diff --git a/README.md b/README.md index 7b2522d..6a53ab8 100644 --- a/README.md +++ b/README.md @@ -29,15 +29,15 @@ The bootloader can be configured via 'bootloader/hekate_ipl.ini' (if it is prese There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Caption, "**#**": Comment, "*newline*": .ini cosmetic newline. -### Configuration keys/values when boot entry is **config**: +### Global Configuration keys/values when boot entry is **config**: | Config option | Description | | ------------------ | ---------------------------------------------------------- | | autoboot=0 | 0: Disable, #: Boot entry number to auto boot. | | bootwait=3 | 0: Disable (It also disables bootlogo. Having **VOL-** pressed since injection goes to menu.), #: Time to wait for **VOL-** to enter menu. | -| customlogo=0 | 0: Use default hekate bootlogo, 1: Use bootlogo.bmp. | | verification=2 | 0: Disable Backup/Restore verification, 1: Sparse (block based, fast and not 100% reliable), 2: Full (sha256 based, slow and 100% reliable). | | autohosoff=1 | 0: Disable, 1: If woke up from HOS via an RTC alarm, shows logo, then powers off completely, 2: No logo, immediately powers off.| +| autonogc=1 | 0: Disable, 1: Automatically applies nogc patch if unburnt fuses found and a >= 4.0.0 HOS is booted. | | backlight=100 | Screen backlight level. 0-255. | @@ -51,13 +51,26 @@ There are four possible type of entries. "**[ ]**": Boot entry, "**{ }**": Capti | kernel={SD path} | Replaces the kernel binary | | kip1={SD path} | Replaces/Adds kernel initial process. Multiple can be set. | | kip1={SD folder}/* | Loads every .kip/.kip1 inside a folder. Compatible with single kip1 keys. | -| kip1patch=patchname| Enables a kip1 patch. Specify with multiple lines and/or as CSV. Implemented patches right now are nosigchk,nogc | +| kip1patch=patchname| Enables a kip1 patch. Specify with multiple lines and/or as CSV. Current available patches nosigchk. | | fullsvcperm=1 | Disables SVC verification (full services permission) | | debugmode=1 | Enables Debug mode | | atmosphere=1 | Enables Atmosphère patching | | payload={SD path} | Payload launching. Tools, Linux, CFW bootloaders, etc. | +### Payload storage: + +Hekate now has a new storage in the binary that helps it configure it outside of BPMP enviroment: + +| Offset / Name | Description | +| -------------------- | ----------------------------------------------------------------- | +| '0x94' boot_cfg | bit0: Force AutoBoot, bit1: Show launch log. | +| '0x98' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. | +| '0x9C' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. | +| '0xA0' rsvd_cfg | Reserved. | +| '0xA4' rsvd[32] | Reserved. | + + You can find a template [Here](./res/hekate_ipl_template.ini) If the main .ini is not found, it is created on the first hekate boot. diff --git a/bootloader/link.ld b/bootloader/link.ld index 2d7956d..79334ab 100644 --- a/bootloader/link.ld +++ b/bootloader/link.ld @@ -1,9 +1,11 @@ ENTRY(_start) SECTIONS { - PROVIDE(__ipl_start = 0x40008000); + PROVIDE(__ipl_start = IPL_LOAD_ADDR); . = __ipl_start; .text : { + *(.text._start); + . = . + 36; *(.text*); } .data : { diff --git a/bootloader/main.c b/bootloader/main.c index 930a568..6c739fa 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -67,6 +67,7 @@ static bool sd_mounted; u8 *Kc_MENU_LOGO; #endif //MENU_LOGO_ENABLE +boot_cfg_t *b_cfg; hekate_config h_cfg; bool sd_mount() @@ -370,6 +371,8 @@ int launch_payload(char *path, bool update) { if (!update) reloc_patcher(ALIGN(size, 0x10)); + else + memcpy((u8 *)(RCM_PAYLOAD_ADDR + PATCHED_RELOC_SZ), (u8 *)(IPL_LOAD_ADDR + PATCHED_RELOC_SZ), sizeof(boot_cfg_t)); reconfig_hw_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32)))); } else @@ -393,6 +396,7 @@ int launch_payload(char *path, bool update) void auto_launch_update() { FIL fp; + if (*(vu32 *)BOOTLOADER_UPDATED_MAGIC_ADDR == BOOTLOADER_UPDATED_MAGIC) *(vu32 *)BOOTLOADER_UPDATED_MAGIC_ADDR = 0; else @@ -526,6 +530,7 @@ void ini_list_launcher() u8 max_entries = 61; char *payload_path = NULL; + ini_sec_t *cfg_tmp = NULL; ini_sec_t *cfg_sec = NULL; LIST_INIT(ini_list_sections); @@ -564,7 +569,30 @@ void ini_list_launcher() menu_t menu = { ments, "Launch ini configurations", 0, 0 }; - cfg_sec = ini_clone_section((ini_sec_t *)tui_do_menu(&gfx_con, &menu)); + + cfg_tmp = (ini_sec_t *)tui_do_menu(&gfx_con, &menu); + + if (cfg_tmp) + { + u32 non_cfg = 1; + for (int j = 2; j < i; j++) + { + if (ments[j].type != INI_CHOICE) + non_cfg++; + + if (ments[j].data == cfg_tmp) + { + b_cfg->boot_cfg = BOOT_CFG_FROM_LAUNCH; + b_cfg->autoboot = j - non_cfg; + b_cfg->autoboot_list = 1; + + break; + } + } + } + + cfg_sec = ini_clone_section(cfg_tmp); + if (!cfg_sec) { free(ments); @@ -574,12 +602,12 @@ void ini_list_launcher() } } else - EPRINTF("No ini configurations found."); + EPRINTF("No ini configs found."); free(ments); ini_free(&ini_list_sections); } else - EPRINTF("Could not find any ini\nin bootloader/ini folder!"); + EPRINTF("Could not find any ini\nin bootloader/ini!"); } if (!cfg_sec) @@ -622,6 +650,7 @@ void launch_firmware() u8 max_entries = 61; char *payload_path = NULL; + ini_sec_t *cfg_tmp = NULL; ini_sec_t *cfg_sec = NULL; LIST_INIT(ini_sections); @@ -674,7 +703,29 @@ void launch_firmware() menu_t menu = { ments, "Launch configurations", 0, 0 }; - cfg_sec = ini_clone_section((ini_sec_t *)tui_do_menu(&gfx_con, &menu)); + + cfg_tmp = (ini_sec_t *)tui_do_menu(&gfx_con, &menu); + + if (cfg_tmp) + { + u8 non_cfg = 4; + for (int j = 5; j < i; j++) + { + if (ments[j].type != INI_CHOICE) + non_cfg++; + if (ments[j].data == cfg_tmp) + { + b_cfg->boot_cfg = BOOT_CFG_FROM_LAUNCH; + b_cfg->autoboot = j - non_cfg; + b_cfg->autoboot_list = 0; + + break; + } + } + } + + + cfg_sec = ini_clone_section(cfg_tmp); if (!cfg_sec) { free(ments); @@ -687,7 +738,7 @@ void launch_firmware() ini_free(&ini_sections); } else - EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists in SD Card!"); + EPRINTF("Could not open 'bootloader/hekate_ipl.ini'.\nMake sure it exists!"); } if (!cfg_sec) @@ -731,11 +782,16 @@ out: void auto_launch_firmware() { - auto_launch_update(); + if (!(b_cfg->boot_cfg & BOOT_CFG_FROM_LAUNCH)) + { + auto_launch_update(); + gfx_con.mute = true; + } u8 *BOOTLOGO = NULL; char *payload_path = NULL; FIL fp; + u32 btn = 0; struct _bmp_data { @@ -755,8 +811,6 @@ void auto_launch_firmware() LIST_INIT(ini_sections); LIST_INIT(ini_list_sections); - gfx_con.mute = true; - if (sd_mount()) { if (f_open(&fp, "bootloader/hekate_ipl.ini", FA_READ)) @@ -796,6 +850,19 @@ void auto_launch_firmware() h_cfg.autonogc = atoi(kv->val); } boot_entry_id++; + + // Override autoboot, otherwise save it for a possbile sept run. + if (b_cfg->boot_cfg & BOOT_CFG_AUTOBOOT_EN) + { + h_cfg.autoboot = b_cfg->autoboot; + h_cfg.autoboot_list = b_cfg->autoboot_list; + } + else + { + b_cfg->autoboot = h_cfg.autoboot; + b_cfg->autoboot_list = h_cfg.autoboot_list; + } + continue; } @@ -813,7 +880,7 @@ void auto_launch_firmware() } } - if (h_cfg.autohosoff) + if (h_cfg.autohosoff && !(b_cfg->boot_cfg & BOOT_CFG_AUTOBOOT_EN)) check_power_off_from_hos(); if (h_cfg.autoboot_list) @@ -867,7 +934,9 @@ void auto_launch_firmware() else goto out; - u8 *bitmap = NULL; + u8 *bitmap = NULL; + if (!(b_cfg->boot_cfg & BOOT_CFG_FROM_LAUNCH)) + { if (bootlogoCustomEntry != NULL) // Check if user set custom logo path at the boot entry. { bitmap = (u8 *)sd_file_read(bootlogoCustomEntry); @@ -915,28 +984,21 @@ void auto_launch_firmware() free(bitmap); } - // Render boot logo. - if (bootlogoFound) - { - gfx_render_bmp_argb(&gfx_ctxt, (u32 *)BOOTLOGO, bmpData.size_x, bmpData.size_y, - bmpData.pos_x, bmpData.pos_y); + // Render boot logo. + if (bootlogoFound) + { + gfx_render_bmp_argb(&gfx_ctxt, (u32 *)BOOTLOGO, bmpData.size_x, bmpData.size_y, + bmpData.pos_x, bmpData.pos_y); + } + else + { + gfx_clear_grey(&gfx_ctxt, 0x1B); + BOOTLOGO = (void *)malloc(0x4000); + blz_uncompress_srcdest(BOOTLOGO_BLZ, SZ_BOOTLOGO_BLZ, BOOTLOGO, SZ_BOOTLOGO); + gfx_set_rect_grey(&gfx_ctxt, BOOTLOGO, X_BOOTLOGO, Y_BOOTLOGO, 326, 544); + } + free(BOOTLOGO); } - else - { - gfx_clear_grey(&gfx_ctxt, 0x1B); - BOOTLOGO = (void *)malloc(0x4000); - blz_uncompress_srcdest(BOOTLOGO_BLZ, SZ_BOOTLOGO_BLZ, BOOTLOGO, SZ_BOOTLOGO); - gfx_set_rect_grey(&gfx_ctxt, BOOTLOGO, X_BOOTLOGO, Y_BOOTLOGO, 326, 544); - } - free(BOOTLOGO); - - display_backlight_brightness(h_cfg.backlight, 1000); - - // Wait before booting. If VOL- is pressed go into bootloader menu. - u32 btn = btn_wait_timeout(h_cfg.bootwait * 1000, BTN_VOL_DOWN); - - if (btn & BTN_VOL_DOWN) - goto out; ini_free(&ini_sections); if (h_cfg.autoboot_list) @@ -946,6 +1008,20 @@ void auto_launch_firmware() free(Kc_MENU_LOGO); #endif //MENU_LOGO_ENABLE + if (b_cfg->boot_cfg & BOOT_CFG_FROM_LAUNCH) + display_backlight_brightness(h_cfg.backlight, 0); + else if (h_cfg.bootwait) + display_backlight_brightness(h_cfg.backlight, 1000); + + // Wait before booting. If VOL- is pressed go into bootloader menu. + if (!(b_cfg->boot_cfg & BOOT_CFG_FROM_LAUNCH)) + { + btn = btn_wait_timeout(h_cfg.bootwait * 1000, BTN_VOL_DOWN); + + if (btn & BTN_VOL_DOWN) + goto out; + } + payload_path = ini_check_payload_section(cfg_sec); if (payload_path) @@ -970,6 +1046,8 @@ out: sd_unmount(); gfx_con.mute = false; + + b_cfg->boot_cfg &= ~(BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_FROM_LAUNCH); } void about() @@ -1148,6 +1226,9 @@ extern void pivot_stack(u32 stack_top); void ipl_main() { + // Set boot config address. + b_cfg = (boot_cfg_t *)(IPL_LOAD_ADDR + PATCHED_RELOC_SZ); + // Do initial HW configuration. This is compatible with consecutive reruns without a reset. config_hw(); diff --git a/bootloader/soc/hw_init.c b/bootloader/soc/hw_init.c index ca0cc50..3ad889c 100644 --- a/bootloader/soc/hw_init.c +++ b/bootloader/soc/hw_init.c @@ -211,7 +211,7 @@ void config_hw() i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_CNFGBBC, MAX77620_CNFGBBC_RESISTOR_1K); i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_ONOFFCNFG1, - (1 << 6) | (0 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. + (1 << 6) | (3 << MAX77620_ONOFFCNFG1_MRT_SHIFT)); // PWR delay for forced shutdown off. i2c_send_byte(I2C_5, MAX77620_I2C_ADDR, MAX77620_REG_FPS_CFG0, (7 << MAX77620_FPS_TIME_PERIOD_SHIFT)); diff --git a/bootloader/utils/types.h b/bootloader/utils/types.h index 9a4d414..ca8dc09 100644 --- a/bootloader/utils/types.h +++ b/bootloader/utils/types.h @@ -51,4 +51,16 @@ typedef int bool; #define true 1 #define false 0 +#define BOOT_CFG_AUTOBOOT_EN (1 << 0) +#define BOOT_CFG_FROM_LAUNCH (1 << 1) + +typedef struct __attribute__((__packed__)) _boot_cfg_t +{ + u8 boot_cfg; + u8 autoboot; + u8 autoboot_list; + u8 rsvd_cfg; + u8 rsvd[32]; +} boot_cfg_t; + #endif