[7.0.0-7.0.1] Add full support via Atmosphere's sept

This commit is contained in:
Kostas Missos 2019-02-24 03:03:17 +02:00
parent aae7689bf5
commit f911fab9f2
10 changed files with 288 additions and 32 deletions

View file

@ -30,6 +30,7 @@ OBJS = $(addprefix $(BUILD)/$(TARGET)/, \
hos.o \ hos.o \
hos_config.o \ hos_config.o \
secmon_exo.o \ secmon_exo.o \
sept.o \
i2c.o \ i2c.o \
kfuse.o \ kfuse.o \
bq24193.o \ bq24193.o \

View file

@ -64,7 +64,7 @@ Hekate now has a new storage in the binary that helps it configure it outside of
| Offset / Name | Description | | Offset / Name | Description |
| -------------------- | ----------------------------------------------------------------- | | -------------------- | ----------------------------------------------------------------- |
| '0x94' boot_cfg | bit0: Force AutoBoot, bit1: Show launch log. | | '0x94' boot_cfg | bit0: Force AutoBoot, bit1: Show launch log, bit2: sept run. |
| '0x98' autoboot | If `Force AutoBoot`: 0: Force go to menu, else boot that entry. | | '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. | | '0x9C' autoboot_list | If `Force AutoBoot` and `autoboot` then it boots from ini folder. |
| '0xA0' rsvd_cfg | Reserved. | | '0xA0' rsvd_cfg | Reserved. |

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (c) 2018 CTCaer * Copyright (c) 2018-2019 CTCaer
* Copyright (c) 2018 Reisyukaku * Copyright (c) 2018 Reisyukaku
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@ -26,6 +26,7 @@
#include "../hos/hos.h" #include "../hos/hos.h"
#include "../hos/pkg1.h" #include "../hos/pkg1.h"
#include "../hos/pkg2.h" #include "../hos/pkg2.h"
#include "../hos/sept.h"
#include "../libs/fatfs/ff.h" #include "../libs/fatfs/ff.h"
#include "../mem/heap.h" #include "../mem/heap.h"
#include "../power/max7762x.h" #include "../power/max7762x.h"
@ -35,6 +36,7 @@
#include "../utils/btn.h" #include "../utils/btn.h"
#include "../utils/util.h" #include "../utils/util.h"
extern boot_cfg_t *b_cfg;
extern hekate_config h_cfg; extern hekate_config h_cfg;
extern gfx_ctxt_t gfx_ctxt; extern gfx_ctxt_t gfx_ctxt;
@ -96,6 +98,21 @@ void dump_packages12()
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off; tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
tsec_ctxt.secmon_base = pkg1_id->secmon_base; tsec_ctxt.secmon_base = pkg1_id->secmon_base;
if (kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{
b_cfg->autoboot = 0;
b_cfg->autoboot_list = 0;
gfx_printf(&gfx_con, "sept will run to get the keys.\nThen rerun this option.");
btn_wait();
if (!reboot_to_sept((u8 *)tsec_ctxt.fw))
{
gfx_printf(&gfx_con, "Failed to run sept\n");
goto out_free;
}
}
// Read keyblob. // Read keyblob.
u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1); u8 *keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1);
sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob); sdmmc_storage_read(&storage, 0x180000 / NX_EMMC_BLOCKSIZE + kb, 1, keyblob);

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018 naehrwert * Copyright (c) 2018 naehrwert
* Copyright (C) 2018 CTCaer * Copyright (c) 2018 CTCaer
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,

View file

@ -22,6 +22,7 @@
#include "hos.h" #include "hos.h"
#include "hos_config.h" #include "hos_config.h"
#include "sept.h"
#include "secmon_exo.h" #include "secmon_exo.h"
#include "../config/config.h" #include "../config/config.h"
#include "../gfx/di.h" #include "../gfx/di.h"
@ -43,6 +44,7 @@
extern gfx_ctxt_t gfx_ctxt; extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con; extern gfx_con_t gfx_con;
extern boot_cfg_t *b_cfg;
extern hekate_config h_cfg; extern hekate_config h_cfg;
extern void sd_unmount(); extern void sd_unmount();
@ -416,6 +418,12 @@ int hos_launch(ini_sec_t *cfg)
tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off; tsec_ctxt.pkg11_off = ctxt.pkg1_id->pkg11_off;
tsec_ctxt.secmon_base = ctxt.pkg1_id->secmon_base; tsec_ctxt.secmon_base = ctxt.pkg1_id->secmon_base;
if (ctxt.pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{
gfx_printf(&gfx_con, "Failed to run sept\n");
return 0;
}
if (!keygen(ctxt.keyblob, ctxt.pkg1_id->kb, &tsec_ctxt)) if (!keygen(ctxt.keyblob, ctxt.pkg1_id->kb, &tsec_ctxt))
return 0; return 0;
DPRINTF("Generated keys\n"); DPRINTF("Generated keys\n");
@ -637,6 +645,9 @@ int hos_launch(ini_sec_t *cfg)
// Disable display. This must be executed before secmon to provide support for all fw versions. // Disable display. This must be executed before secmon to provide support for all fw versions.
display_end(); display_end();
// Clear EMC_SCRATCH0.
EMC(EMC_SCRATCH0) = 0;
// Wait for secmon to get ready. // Wait for secmon to get ready.
if (smmu_is_used()) if (smmu_is_used())
smmu_exit(); smmu_exit();

184
bootloader/hos/sept.c Normal file
View file

@ -0,0 +1,184 @@
/*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "hos.h"
#include "sept.h"
#include "../config/config.h"
#include "../gfx/di.h"
#include "../ianos/ianos.h"
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../soc/pmc.h"
#include "../soc/t210.h"
#include "../storage/nx_emmc.h"
#include "../storage/sdmmc.h"
#include "../utils/btn.h"
#include "../utils/types.h"
#include "../gfx/gfx.h"
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 PATCHED_RELOC_SZ 0x94
#define WB_RST_ADDR 0x40010ED0
#define WB_RST_SIZE 0x30
u8 warmboot_reboot[] = {
0x14, 0x00, 0x9F, 0xE5, // LDR R0, =0x7000E450
0x01, 0x10, 0xB0, 0xE3, // MOVS R1, #1
0x00, 0x10, 0x80, 0xE5, // STR R1, [R0]
0x0C, 0x00, 0x9F, 0xE5, // LDR R0, =0x7000E400
0x10, 0x10, 0xB0, 0xE3, // MOVS R1, #0x10
0x00, 0x10, 0x80, 0xE5, // STR R1, [R0]
0xFE, 0xFF, 0xFF, 0xEA, // LOOP
0x50, 0xE4, 0x00, 0x70, // #0x7000E450
0x00, 0xE4, 0x00, 0x70 // #0x7000E400
};
#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)
#define SEPT_PKG_SZ (0x2F100 + WB_RST_SIZE)
extern boot_cfg_t *b_cfg;
extern hekate_config h_cfg;
extern void *sd_file_read(char *path);
extern void sd_mount();
extern void sd_unmount();
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
void check_sept()
{
u8 *pkg1 = (u8 *)calloc(1, 0x40000);
sdmmc_storage_t storage;
sdmmc_t sdmmc;
if (!sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4))
{
EPRINTF("Failed to init eMMC.");
goto out_free;
}
sdmmc_storage_set_mmc_partition(&storage, 1);
// Read package1.
sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1);
if (!pkg1_id)
{
gfx_con.fntsz = 16;
EPRINTF("Unknown pkg1 version.");
goto out_free;
}
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_700 && !h_cfg.sept_run)
{
sdmmc_storage_end(&storage);
reboot_to_sept((u8 *)pkg1 + pkg1_id->tsec_off);
}
out_free:
free(pkg1);
sdmmc_storage_end(&storage);
}
int reboot_to_sept(const u8 *tsec_fw)
{
FIL fp;
// Copy warmboot reboot code and TSEC fw.
memcpy((u8 *)(SEPT_PK1T_ADDR - WB_RST_SIZE), (u8 *)warmboot_reboot, sizeof(warmboot_reboot));
memcpy((void *)SEPT_PK1T_ADDR, tsec_fw, 0x3000);
*(vu32 *)SEPT_TCSZ_ADDR = 0x3000;
// Copy sept-primary.
if (f_open(&fp, "sept/sept-primary.bin", FA_READ))
goto error;
if (f_read(&fp, (u8 *)SEPT_STG1_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
f_close(&fp);
// Copy sept-secondary.
if (f_open(&fp, "sept/sept-secondary.enc", FA_READ))
goto error;
if (f_read(&fp, (u8 *)SEPT_STG2_ADDR, f_size(&fp), NULL))
{
f_close(&fp);
goto error;
}
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));
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)
{
f_lseek(&fp, PATCHED_RELOC_SZ);
f_write(&fp, tmp_cfg, sizeof(boot_cfg_t), NULL);
}
f_close(&fp);
sd_unmount();
u32 pk1t_sept = SEPT_PK1T_ADDR - (ALIGN(PATCHED_RELOC_SZ, 0x10) + WB_RST_SIZE);
void (*sept)() = (void *)pk1t_sept;
reloc_patcher(WB_RST_ADDR, pk1t_sept, SEPT_PKG_SZ);
// Patch SDRAM init to perform an SVC immediately after second write.
PMC(APBDEV_PMC_SCRATCH45) = 0x2E38DFFF;
PMC(APBDEV_PMC_SCRATCH46) = 0x6001DC28;
// Set SVC handler to jump to sept-primary in IRAM.
PMC(APBDEV_PMC_SCRATCH33) = SEPT_PRI_ADDR;
PMC(APBDEV_PMC_SCRATCH40) = 0x6000F208;
display_end();
(*sept)();
return 1;
error:
EPRINTF("Failed to run sept\n");
display_backlight_brightness(h_cfg.backlight, 1000);
btn_wait();
return 0;
}

25
bootloader/hos/sept.h Normal file
View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2019 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SEPT_H_
#define _SEPT_H_
#include "../utils/types.h"
void check_sept();
int reboot_to_sept(const u8 *tsec_fw);
#endif

View file

@ -25,6 +25,7 @@
#include "gfx/logos.h" #include "gfx/logos.h"
#include "gfx/tui.h" #include "gfx/tui.h"
#include "hos/hos.h" #include "hos/hos.h"
#include "hos/sept.h"
#include "ianos/ianos.h" #include "ianos/ianos.h"
#include "libs/compr/blz.h" #include "libs/compr/blz.h"
#include "libs/fatfs/ff.h" #include "libs/fatfs/ff.h"
@ -270,7 +271,7 @@ void check_power_off_from_hos()
} }
// This is a safe and unused DRAM region for our payloads. // This is a safe and unused DRAM region for our payloads.
#define IPL_LOAD_ADDR 0x40008000 // IPL_LOAD_ADDR is defined in makefile.
#define EXT_PAYLOAD_ADDR 0xC03C0000 #define EXT_PAYLOAD_ADDR 0xC03C0000
#define PATCHED_RELOC_SZ 0x94 #define PATCHED_RELOC_SZ 0x94
#define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10)) #define RCM_PAYLOAD_ADDR (EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10))
@ -281,21 +282,23 @@ void check_power_off_from_hos()
void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR; void (*ext_payload_ptr)() = (void *)EXT_PAYLOAD_ADDR;
void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR; void (*update_ptr)() = (void *)RCM_PAYLOAD_ADDR;
void reloc_patcher(u32 payload_size) void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size)
{ {
static const u32 START_OFF = 0x7C; static const u32 START_OFF = 0x7C;
static const u32 STACK_OFF = 0x80;
static const u32 PAYLOAD_END_OFF = 0x84; static const u32 PAYLOAD_END_OFF = 0x84;
static const u32 IPL_START_OFF = 0x88; static const u32 IPL_START_OFF = 0x88;
memcpy((u8 *)EXT_PAYLOAD_ADDR, (u8 *)IPL_LOAD_ADDR, PATCHED_RELOC_SZ); memcpy((u8 *)payload_src, (u8 *)IPL_LOAD_ADDR, PATCHED_RELOC_SZ);
*(vu32 *)(EXT_PAYLOAD_ADDR + START_OFF) = PAYLOAD_ENTRY - ALIGN(PATCHED_RELOC_SZ, 0x10); *(vu32 *)(payload_src + START_OFF) = payload_dst - ALIGN(PATCHED_RELOC_SZ, 0x10);
*(vu32 *)(EXT_PAYLOAD_ADDR + PAYLOAD_END_OFF) = PAYLOAD_ENTRY + payload_size; *(vu32 *)(payload_src + PAYLOAD_END_OFF) = payload_dst + payload_size;
*(vu32 *)(EXT_PAYLOAD_ADDR + IPL_START_OFF) = PAYLOAD_ENTRY; *(vu32 *)(payload_src + STACK_OFF) = 0x40008000;
*(vu32 *)(payload_src + IPL_START_OFF) = payload_dst;
if (payload_size == 0x7000) if (payload_size == 0x7000)
{ {
memcpy((u8 *)(EXT_PAYLOAD_ADDR + ALIGN(PATCHED_RELOC_SZ, 0x10)), (u8 *)COREBOOT_ADDR, 0x7000); //Bootblock memcpy((u8 *)(payload_src + ALIGN(PATCHED_RELOC_SZ, 0x10)), (u8 *)COREBOOT_ADDR, 0x7000); //Bootblock
*(vu32 *)CBFS_SDRAM_EN_ADDR = 0x4452414D; *(vu32 *)CBFS_SDRAM_EN_ADDR = 0x4452414D;
} }
} }
@ -370,14 +373,15 @@ int launch_payload(char *path, bool update)
if (size < 0x30000) if (size < 0x30000)
{ {
if (!update) if (!update)
reloc_patcher(ALIGN(size, 0x10)); reloc_patcher(PAYLOAD_ENTRY, EXT_PAYLOAD_ADDR, ALIGN(size, 0x10));
else else
memcpy((u8 *)(RCM_PAYLOAD_ADDR + PATCHED_RELOC_SZ), (u8 *)(IPL_LOAD_ADDR + PATCHED_RELOC_SZ), sizeof(boot_cfg_t)); 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)))); reconfig_hw_workaround(false, byte_swap_32(*(u32 *)(buf + size - sizeof(u32))));
} }
else else
{ {
reloc_patcher(0x7000); reloc_patcher(PAYLOAD_ENTRY, EXT_PAYLOAD_ADDR, 0x7000);
if (*(vu32 *)CBFS_SDRAM_EN_ADDR != 0x4452414D) if (*(vu32 *)CBFS_SDRAM_EN_ADDR != 0x4452414D)
return 1; return 1;
reconfig_hw_workaround(true, 0); reconfig_hw_workaround(true, 0);
@ -591,6 +595,11 @@ void ini_list_launcher()
} }
} }
payload_path = ini_check_payload_section(cfg_tmp);
if (cfg_tmp && !payload_path)
check_sept();
cfg_sec = ini_clone_section(cfg_tmp); cfg_sec = ini_clone_section(cfg_tmp);
if (!cfg_sec) if (!cfg_sec)
@ -617,8 +626,6 @@ void ini_list_launcher()
free(Kc_MENU_LOGO); free(Kc_MENU_LOGO);
#endif //MENU_LOGO_ENABLE #endif //MENU_LOGO_ENABLE
payload_path = ini_check_payload_section(cfg_sec);
if (payload_path) if (payload_path)
{ {
ini_free_section(cfg_sec); ini_free_section(cfg_sec);
@ -724,6 +731,10 @@ void launch_firmware()
} }
} }
payload_path = ini_check_payload_section(cfg_tmp);
if (cfg_tmp && !payload_path)
check_sept();
cfg_sec = ini_clone_section(cfg_tmp); cfg_sec = ini_clone_section(cfg_tmp);
if (!cfg_sec) if (!cfg_sec)
@ -754,8 +765,6 @@ void launch_firmware()
free(Kc_MENU_LOGO); free(Kc_MENU_LOGO);
#endif //MENU_LOGO_ENABLE #endif //MENU_LOGO_ENABLE
payload_path = ini_check_payload_section(cfg_sec);
if (payload_path) if (payload_path)
{ {
ini_free_section(cfg_sec); ini_free_section(cfg_sec);
@ -934,6 +943,11 @@ void auto_launch_firmware()
else else
goto out; goto out;
payload_path = ini_check_payload_section(cfg_sec);
if (!payload_path)
check_sept();
u8 *bitmap = NULL; u8 *bitmap = NULL;
if (!(b_cfg->boot_cfg & BOOT_CFG_FROM_LAUNCH)) if (!(b_cfg->boot_cfg & BOOT_CFG_FROM_LAUNCH))
{ {
@ -1022,8 +1036,6 @@ void auto_launch_firmware()
goto out; goto out;
} }
payload_path = ini_check_payload_section(cfg_sec);
if (payload_path) if (payload_path)
{ {
ini_free_section(cfg_sec); ini_free_section(cfg_sec);

View file

@ -37,6 +37,7 @@
#include "../utils/util.h" #include "../utils/util.h"
extern sdmmc_t sd_sdmmc; extern sdmmc_t sd_sdmmc;
extern boot_cfg_t *b_cfg;
void _config_oscillators() void _config_oscillators()
{ {
@ -144,6 +145,9 @@ void _mbist_workaround()
} }
void _config_se_brom() void _config_se_brom()
{
// Skip SBK/SSK if sept was run.
if (!(b_cfg->boot_cfg & BOOT_CFG_SEPT_RUN))
{ {
// Bootrom part we skipped. // Bootrom part we skipped.
u32 sbk[4] = { u32 sbk[4] = {
@ -158,14 +162,15 @@ void _config_se_brom()
// Lock SBK from being read. // Lock SBK from being read.
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 14 * 4) = 0x7E; SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 14 * 4) = 0x7E;
// Lock SSK (although it's not set and unused anyways).
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 15 * 4) = 0x7E;
}
// This memset needs to happen here, else TZRAM will behave weirdly later on. // This memset needs to happen here, else TZRAM will behave weirdly later on.
memset((void *)TZRAM_BASE, 0, 0x10000); memset((void *)TZRAM_BASE, 0, 0x10000);
PMC(APBDEV_PMC_CRYPTO_OP) = 0; PMC(APBDEV_PMC_CRYPTO_OP) = 0;
SE(SE_INT_STATUS_REG_OFFSET) = 0x1F; SE(SE_INT_STATUS_REG_OFFSET) = 0x1F;
// Lock SSK (although it's not set and unused anyways).
SE(SE_KEY_TABLE_ACCESS_REG_OFFSET + 15 * 4) = 0x7E;
// Clear the boot reason to avoid problems later // Clear the boot reason to avoid problems later
PMC(APBDEV_PMC_SCRATCH200) = 0x0; PMC(APBDEV_PMC_SCRATCH200) = 0x0;
PMC(APBDEV_PMC_RST_STATUS) = 0x0; PMC(APBDEV_PMC_RST_STATUS) = 0x0;

View file

@ -53,6 +53,7 @@ typedef int bool;
#define BOOT_CFG_AUTOBOOT_EN (1 << 0) #define BOOT_CFG_AUTOBOOT_EN (1 << 0)
#define BOOT_CFG_FROM_LAUNCH (1 << 1) #define BOOT_CFG_FROM_LAUNCH (1 << 1)
#define BOOT_CFG_SEPT_RUN (1 << 7)
typedef struct __attribute__((__packed__)) _boot_cfg_t typedef struct __attribute__((__packed__)) _boot_cfg_t
{ {