mirror of
https://github.com/CTCaer/hekate.git
synced 2024-11-22 09:56:40 +00:00
[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:
parent
c8052e5b50
commit
2fb37db707
6 changed files with 150 additions and 39 deletions
9
Makefile
9
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/*)
|
||||
|
||||
|
|
19
README.md
19
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.
|
||||
|
|
|
@ -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 : {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue