[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.
This commit is contained in:
Kostas Missos 2019-02-24 02:43:13 +02:00
parent c8052e5b50
commit 2fb37db707
6 changed files with 150 additions and 39 deletions

View File

@ -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/*)

View File

@ -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.

View File

@ -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 : {

View File

@ -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();

View File

@ -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));

View File

@ -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