From 2e9a89aa20ec18baa8a715a57cabe59aef8b4be4 Mon Sep 17 00:00:00 2001 From: Kostas Missos Date: Thu, 7 Mar 2019 23:53:58 +0200 Subject: [PATCH] [Versioning] Better and smarter for update and sept - Still compatible with old hekate. - Allows for hotfix control - Sept is now copied from actual running payload, negating the need to check update.bin - If a foreign payload is found in sept then it is renamed and hekate copies itself. After sept run, it renames it back and continues with boot. --- Makefile | 11 +++- bootloader/hos/sept.c | 63 ++++++++++++++++------- bootloader/link.ld | 1 + bootloader/main.c | 105 +++++++++++---------------------------- bootloader/utils/types.h | 8 +++ 5 files changed, 92 insertions(+), 96 deletions(-) diff --git a/Makefile b/Makefile index ed8f42c..9692da7 100755 --- a/Makefile +++ b/Makefile @@ -5,8 +5,12 @@ endif include $(DEVKITARM)/base_rules IPL_LOAD_ADDR := 0x40008000 +IPL_MAGIC := 0x43544349 #"ICTC" BLVERSION_MAJOR := 4 BLVERSION_MINOR := 8 +BLVERSION_HOTFX := 0 + +BL_RESERVED := 0 TARGET := hekate BUILD := build @@ -65,12 +69,15 @@ OBJS += $(addprefix $(BUILD)/$(TARGET)/, \ elfload.o elfreloc_arm.o \ ) -CUSTOMDEFINES := -DBLVERSIONMJ=$(BLVERSION_MAJOR) -DBLVERSIONMN=$(BLVERSION_MINOR) -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) +CUSTOMDEFINES := -DIPL_LOAD_ADDR=$(IPL_LOAD_ADDR) -DBL_MAGIC=$(IPL_MAGIC) +CUSTOMDEFINES += -DBL_VER_MJ=$(BLVERSION_MAJOR) -DBL_VER_MN=$(BLVERSION_MINOR) -DBL_VER_HF=$(BLVERSION_HOTFX) -DBL_RESERVED=$(BL_RESERVED) CUSTOMDEFINES += -DMENU_LOGO_ENABLE -#CUSTOMDEFINES += -DDEBUG + # 0: UART_A, 1: UART_B. #CUSTOMDEFINES += -DDEBUG_UART_PORT=0 +#CUSTOMDEFINES += -DDEBUG + 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 -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR) diff --git a/bootloader/hos/sept.c b/bootloader/hos/sept.c index 5b2fdb1..8d89212 100644 --- a/bootloader/hos/sept.c +++ b/bootloader/hos/sept.c @@ -35,6 +35,7 @@ extern gfx_con_t gfx_con; #define EPRINTF(text) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, 0xFFCCCCCC) #define EPRINTFARGS(text, args...) gfx_printf(&gfx_con, "%k"text"%k\n", 0xFFFF0000, args, 0xFFCCCCCC) +#define RELOC_META_OFF 0x7C #define PATCHED_RELOC_SZ 0x94 #define WB_RST_ADDR 0x40010ED0 @@ -55,7 +56,6 @@ u8 warmboot_reboot[] = { #define SEPT_PRI_ADDR 0x4003F000 #define SEPT_PK1T_ADDR 0xC0400000 -#define SEPT_PK1T_STACK 0x40008000 #define SEPT_TCSZ_ADDR (SEPT_PK1T_ADDR - 0x4) #define SEPT_STG1_ADDR (SEPT_PK1T_ADDR + 0x2E100) #define SEPT_STG2_ADDR (SEPT_PK1T_ADDR + 0x60E0) @@ -63,13 +63,24 @@ u8 warmboot_reboot[] = { extern boot_cfg_t b_cfg; extern hekate_config h_cfg; +extern const volatile ipl_ver_meta_t ipl_ver; + extern void *sd_file_read(char *path); extern void sd_mount(); extern void sd_unmount(); +extern bool is_ipl_updated(void *buf); extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size); void check_sept() { + // Check if non-hekate payload is used for sept and restore it. + if (h_cfg.sept_run && !f_stat("sept/payload.bak", NULL)) + { + f_unlink("sept/payload.bin"); + f_rename("sept/payload.bak", "sept/payload.bin"); + return; + } + u8 *pkg1 = (u8 *)calloc(1, 0x40000); sdmmc_storage_t storage; @@ -133,25 +144,41 @@ int reboot_to_sept(const u8 *tsec_fw) } f_close(&fp); - // Save auto boot config to payload, if any. - boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t)); - memcpy(tmp_cfg, &b_cfg, sizeof(boot_cfg_t)); + b_cfg.boot_cfg |= (BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_SEPT_RUN); - tmp_cfg->boot_cfg |= (BOOT_CFG_AUTOBOOT_EN | BOOT_CFG_SEPT_RUN); - - if (f_open(&fp, "sept/payload.bin", FA_READ | FA_WRITE)) - goto error; - - u32 magic; - f_lseek(&fp, f_size(&fp) - 6); - f_read(&fp, &magic, 4, NULL); - if (magic == 0x43544349) + bool update_sept_payload = true; + if (!f_open(&fp, "sept/payload.bin", FA_READ | FA_WRITE)) { - f_lseek(&fp, PATCHED_RELOC_SZ); - f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL); + ipl_ver_meta_t tmp_ver; + f_lseek(&fp, PATCHED_RELOC_SZ + sizeof(boot_cfg_t)); + f_read(&fp, &tmp_ver, sizeof(ipl_ver_meta_t), NULL); + + if (tmp_ver.magic == ipl_ver.magic) + { + if (tmp_ver.version == ipl_ver.version) + { + // Save auto boot config to sept payload, if any. + boot_cfg_t *tmp_cfg = malloc(sizeof(boot_cfg_t)); + memcpy(tmp_cfg, &b_cfg, sizeof(boot_cfg_t)); + f_lseek(&fp, PATCHED_RELOC_SZ); + f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL); + f_close(&fp); + update_sept_payload = false; + } + } + else + f_rename("sept/payload.bin", "sept/payload.bak"); // Backup foreign payload. + + f_close(&fp); + } + + if (update_sept_payload) + { + volatile reloc_meta_t *reloc = (reloc_meta_t *)(IPL_LOAD_ADDR + RELOC_META_OFF); + f_open(&fp, "sept/payload.bin", FA_WRITE | FA_CREATE_ALWAYS); + f_write(&fp, (u8 *)reloc->start, reloc->end - reloc->start, NULL); + f_close(&fp); } - - f_close(&fp); sd_unmount(); @@ -172,8 +199,6 @@ int reboot_to_sept(const u8 *tsec_fw) (*sept)(); - return 1; - error: EPRINTF("Failed to run sept\n"); display_backlight_brightness(h_cfg.backlight, 1000); diff --git a/bootloader/link.ld b/bootloader/link.ld index 65d681e..85568dd 100644 --- a/bootloader/link.ld +++ b/bootloader/link.ld @@ -6,6 +6,7 @@ SECTIONS { .text : { *(.text._start); *(._boot_cfg); + *(._ipl_version); *(.text*); } .data : { diff --git a/bootloader/main.c b/bootloader/main.c index be3d2e0..6be5d92 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -279,6 +279,7 @@ void check_power_off_from_hos() // This is a safe and unused DRAM region for our payloads. // IPL_LOAD_ADDR is defined in makefile. #define EXT_PAYLOAD_ADDR 0xC03C0000 +#define RELOC_META_OFF 0x7C #define PATCHED_RELOC_SZ 0x94 #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10)) #define PAYLOAD_ENTRY 0x40010000 @@ -312,9 +313,25 @@ void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size) #define BOOTLOADER_UPDATED_MAGIC 0x424F4F54 // "BOOT". #define BOOTLOADER_UPDATED_MAGIC_ADDR 0x4003E000 +bool is_ipl_updated(void *buf) +{ + ipl_ver_meta_t *update_ft = (ipl_ver_meta_t *)(buf + PATCHED_RELOC_SZ + sizeof(boot_cfg_t)); + + if (update_ft->magic == ipl_ver.magic) + { + if (byte_swap_32(update_ft->version) <= byte_swap_32(ipl_ver.version)) + return true; + return false; + + } + else + return true; +} + int launch_payload(char *path, bool update) { - gfx_clear_grey(&gfx_ctxt, 0x1B); + if (!update) + gfx_clear_grey(&gfx_ctxt, 0x1B); gfx_con_setpos(&gfx_con, 0, 0); if (!path) return 1; @@ -350,66 +367,17 @@ int launch_payload(char *path, bool update) f_close(&fp); free(path); - // Check for updated version. - if (update) - { - u8 *update_ft = calloc(1, 6); + if (update && is_ipl_updated(buf)) + return 1; - bool update_sept = true; - if (!f_open(&fp, "sept/payload.bin", FA_READ | FA_WRITE)) - { - memset(update_ft, 0, 6); - f_lseek(&fp, f_size(&fp) - 6); - f_read(&fp, update_ft, 6, NULL); - f_close(&fp); - update_ft[4] -= '0'; - update_ft[5] -= '0'; - if (*(u32 *)update_ft == 0x43544349) - { - if (update_ft[4] == BLVERSIONMJ && update_ft[5] == BLVERSIONMN) - update_sept = false; - } - else - update_sept = false; - } - - if (update_sept) - { - if (!f_open(&fp, "sept/payload.bin", FA_CREATE_ALWAYS | FA_WRITE)) - { - f_write(&fp, buf, size, NULL); - f_close(&fp); - } - } - - memcpy(update_ft, buf + size - 6, 6); - update_ft[4] -= '0'; - update_ft[5] -= '0'; - if (*(u32 *)update_ft == 0x43544349) - { - if (update_ft[4] < BLVERSIONMJ || (update_ft[4] == BLVERSIONMJ && update_ft[5] <= BLVERSIONMN)) - { - free(update_ft); - return 1; - } - *(vu32 *)BOOTLOADER_UPDATED_MAGIC_ADDR = BOOTLOADER_UPDATED_MAGIC; - } - else - { - free(update_ft); - return 1; - } - - free(update_ft); - } sd_unmount(); if (size < 0x30000) { - if (!update) - reloc_patcher(PAYLOAD_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10)); + if (update) + memcpy((u8 *)(RCM_PAYLOAD_ADDR + PATCHED_RELOC_SZ), &b_cfg, sizeof(boot_cfg_t)); // Transfer boot cfg. else - memcpy((u8 *)(RCM_PAYLOAD_ADDR + PATCHED_RELOC_SZ), (u8 *)(IPL_LOAD_ADDR + PATCHED_RELOC_SZ), sizeof(boot_cfg_t)); + reloc_patcher(PATCHED_RELOC_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10)); reconfig_hw_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32)))); } @@ -433,23 +401,12 @@ 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 + if (EMC(EMC_SCRATCH0) & EMC_HEKA_UPD) + EMC(EMC_SCRATCH0) &= ~EMC_HEKA_UPD; + else if (sd_mount()) { - if (sd_mount()) - { - if (f_open(&fp, "bootloader/update.bin", FA_READ)) - return; - else - { - f_close(&fp); - launch_payload("bootloader/update.bin", true); - } - - } + if (!f_stat("bootloader/update.bin", NULL)) + launch_payload("bootloader/update.bin", true); } } @@ -825,7 +782,7 @@ out: void auto_launch_firmware() { - if (!(b_cfg->boot_cfg & BOOT_CFG_FROM_LAUNCH)) + if (!(b_cfg.boot_cfg & BOOT_CFG_FROM_LAUNCH)) { auto_launch_update(); gfx_con.mute = true; @@ -856,10 +813,8 @@ void auto_launch_firmware() if (sd_mount()) { - if (f_open(&fp, "bootloader/hekate_ipl.ini", FA_READ)) + if (f_stat("bootloader/hekate_ipl.ini", NULL)) create_config_entry(); - else - f_close(&fp); if (ini_parse(&ini_sections, "bootloader/hekate_ipl.ini", false)) { diff --git a/bootloader/utils/types.h b/bootloader/utils/types.h index 9dfa8cb..d1eab24 100644 --- a/bootloader/utils/types.h +++ b/bootloader/utils/types.h @@ -76,4 +76,12 @@ typedef struct __attribute__((__packed__)) _ipl_ver_meta_t u16 rsvd1; } ipl_ver_meta_t; +typedef struct __attribute__((__packed__)) _reloc_meta_t +{ + u32 start; + u32 stack; + u32 end; + u32 ep; +} reloc_meta_t; + #endif