diff --git a/bootloader/frontend/fe_tools.c b/bootloader/frontend/fe_tools.c index 484364c..92e6e6b 100644 --- a/bootloader/frontend/fe_tools.c +++ b/bootloader/frontend/fe_tools.c @@ -223,9 +223,17 @@ void dump_packages12() ini1_off = pkg2_newkern_ini1_start; ini1_size = pkg2_newkern_ini1_end - pkg2_newkern_ini1_start; } - if (sd_save_to_file(pkg2_hdr->data + ini1_off, ini1_size, path)) + if (ini1_off) + { + if (sd_save_to_file(pkg2_hdr->data + ini1_off, ini1_size, path)) + goto out; + gfx_puts("INI1 dumped to ini1.bin\n"); + } + else + { + gfx_puts("Failed to dump INI1!\n"); goto out; - gfx_puts("INI1 dumped to ini1.bin\n"); + } gfx_puts("\nDone. Press any key...\n"); diff --git a/bootloader/hos/fss.c b/bootloader/hos/fss.c index 3164cad..3fdad9c 100644 --- a/bootloader/hos/fss.c +++ b/bootloader/hos/fss.c @@ -43,6 +43,8 @@ extern bool is_ipl_updated(void *buf, char *path, bool force); #define CNT_TYPE_KIP 6 #define CNT_TYPE_BMP 7 #define CNT_TYPE_EMC 8 +#define CNT_TYPE_KLD 9 +#define CNT_TYPE_KRN 10 #define CNT_FLAG0_EXPERIMENTAL (1 << 0) diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index d8c0be5..b044cff 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -581,7 +581,11 @@ int hos_launch(ini_sec_t *cfg) } LIST_INIT(kip1_info); - pkg2_parse_kips(&kip1_info, pkg2_hdr, &ctxt.new_pkg2); + if (!pkg2_parse_kips(&kip1_info, pkg2_hdr, &ctxt.new_pkg2)) + { + _hos_crit_error("INI1 parsing failed!"); + return 0; + } gfx_printf("Parsed ini1\n"); diff --git a/bootloader/hos/pkg2.c b/bootloader/hos/pkg2.c index 3253a79..bff785f 100644 --- a/bootloader/hos/pkg2.c +++ b/bootloader/hos/pkg2.c @@ -692,14 +692,34 @@ static u32 _pkg2_calc_kip1_size(pkg2_kip1_t *kip1) void pkg2_get_newkern_info(u8 *kern_data) { - u32 info_op = *(u32 *)(kern_data + PKG2_NEWKERN_GET_INI1); - pkg2_newkern_ini1_val = ((info_op & 0xFFFF) >> 3) + PKG2_NEWKERN_GET_INI1; // Parse ADR and PC. + u32 pkg2_newkern_ini1_off = 0; + pkg2_newkern_ini1_start = 0; + + // Find static OP offset that is close to INI1 offset. + u32 counter_ops = 0x100; + while (counter_ops) + { + if (*(u32 *)(kern_data + 0x100 - counter_ops) == PKG2_NEWKERN_GET_INI1_HEURISTIC) + { + pkg2_newkern_ini1_off = 0x100 - counter_ops + 12; // OP found. Add 12 for the INI1 offset. + break; + } + + counter_ops -= 4; + } + + // Offset not found? + if (!counter_ops) + return; + + u32 info_op = *(u32 *)(kern_data + pkg2_newkern_ini1_off); + pkg2_newkern_ini1_val = ((info_op & 0xFFFF) >> 3) + pkg2_newkern_ini1_off; // Parse ADR and PC. pkg2_newkern_ini1_start = *(u32 *)(kern_data + pkg2_newkern_ini1_val); pkg2_newkern_ini1_end = *(u32 *)(kern_data + pkg2_newkern_ini1_val + 0x8); } -void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) +bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) { u8 *ptr; // Check for new pkg2 type. @@ -707,6 +727,9 @@ void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) { pkg2_get_newkern_info(pkg2->data); + if (!pkg2_newkern_ini1_start) + return false; + ptr = pkg2->data + pkg2_newkern_ini1_start; *new_pkg2 = true; } @@ -726,6 +749,8 @@ void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) ptr += ki->size; DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size); } + + return true; } int pkg2_has_kip(link_t *info, u64 tid) diff --git a/bootloader/hos/pkg2.h b/bootloader/hos/pkg2.h index 1a5f7ab..2dbe0cc 100644 --- a/bootloader/hos/pkg2.h +++ b/bootloader/hos/pkg2.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2020 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, @@ -27,7 +27,7 @@ #define PKG2_SEC_INI1 1 #define INI1_MAGIC 0x31494E49 -#define PKG2_NEWKERN_GET_INI1 0x44 +#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // Offset of OP + 12 is the INI1 offset. #define PKG2_NEWKERN_START 0x800 u32 pkg2_newkern_ini1_val; @@ -144,7 +144,7 @@ typedef struct _kip1_id_t } kip1_id_t; void pkg2_get_newkern_info(u8 *kern_data); -void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2); +bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2); int pkg2_has_kip(link_t *info, u64 tid); void pkg2_replace_kip(link_t *info, u64 tid, pkg2_kip1_t *kip1); void pkg2_add_kip(link_t *info, pkg2_kip1_t *kip1); diff --git a/nyx/nyx_gui/frontend/gui_tools.c b/nyx/nyx_gui/frontend/gui_tools.c index c586ea2..a377114 100644 --- a/nyx/nyx_gui/frontend/gui_tools.c +++ b/nyx/nyx_gui/frontend/gui_tools.c @@ -549,6 +549,13 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn) ini1_off = pkg2_newkern_ini1_start; ini1_size = pkg2_newkern_ini1_end - pkg2_newkern_ini1_start; } + + if (!ini1_off) + { + s_printf(txt_buf + strlen(txt_buf), "#FFDD00 Failed to dump INI1 and kips!#\n"); + goto out; + } + pkg2_ini1_t *ini1 = (pkg2_ini1_t *)(pkg2_hdr->data + ini1_off); emmcsn_path_impl(path, "/pkg2", "ini1.bin", &storage); if (sd_save_to_file(ini1, ini1_size, path)) diff --git a/nyx/nyx_gui/hos/pkg2.c b/nyx/nyx_gui/hos/pkg2.c index 8462d1c..a58714e 100644 --- a/nyx/nyx_gui/hos/pkg2.c +++ b/nyx/nyx_gui/hos/pkg2.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2020 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, @@ -45,14 +45,34 @@ u32 pkg2_calc_kip1_size(pkg2_kip1_t *kip1) void pkg2_get_newkern_info(u8 *kern_data) { - u32 info_op = *(u32 *)(kern_data + PKG2_NEWKERN_GET_INI1); - pkg2_newkern_ini1_val = ((info_op & 0xFFFF) >> 3) + PKG2_NEWKERN_GET_INI1; // Parse ADR and PC. + u32 pkg2_newkern_ini1_off = 0; + pkg2_newkern_ini1_start = 0; + + // Find static OP offset that is close to INI1 offset. + u32 counter_ops = 0x100; + while (counter_ops) + { + if (*(u32 *)(kern_data + 0x100 - counter_ops) == PKG2_NEWKERN_GET_INI1_HEURISTIC) + { + pkg2_newkern_ini1_off = 0x100 - counter_ops + 12; // OP found. Add 12 for the INI1 offset. + break; + } + + counter_ops -= 4; + } + + // Offset not found? + if (!counter_ops) + return; + + u32 info_op = *(u32 *)(kern_data + pkg2_newkern_ini1_off); + pkg2_newkern_ini1_val = ((info_op & 0xFFFF) >> 3) + pkg2_newkern_ini1_off; // Parse ADR and PC. pkg2_newkern_ini1_start = *(u32 *)(kern_data + pkg2_newkern_ini1_val); pkg2_newkern_ini1_end = *(u32 *)(kern_data + pkg2_newkern_ini1_val + 0x8); } -void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) +bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) { u8 *ptr; // Check for new pkg2 type. @@ -60,6 +80,9 @@ void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) { pkg2_get_newkern_info(pkg2->data); + if (!pkg2_newkern_ini1_start) + return false; + ptr = pkg2->data + pkg2_newkern_ini1_start; *new_pkg2 = true; } @@ -79,6 +102,8 @@ void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2) ptr += ki->size; DPRINTF(" kip1 %d:%s @ %08X (%08X)\n", i, kip1->name, (u32)kip1, ki->size); } + + return true; } static const u8 mkey_keyseed_8xx[][0x10] = diff --git a/nyx/nyx_gui/hos/pkg2.h b/nyx/nyx_gui/hos/pkg2.h index db6c03c..1a48f33 100644 --- a/nyx/nyx_gui/hos/pkg2.h +++ b/nyx/nyx_gui/hos/pkg2.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018 naehrwert - * Copyright (c) 2018-2019 CTCaer + * Copyright (c) 2018-2020 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, @@ -27,7 +27,7 @@ #define PKG2_SEC_INI1 1 #define INI1_MAGIC 0x31494E49 -#define PKG2_NEWKERN_GET_INI1 0x44 +#define PKG2_NEWKERN_GET_INI1_HEURISTIC 0xD2800015 // Offset of OP + 12 is the INI1 offset. #define PKG2_NEWKERN_START 0x800 u32 pkg2_newkern_ini1_val; @@ -91,7 +91,7 @@ typedef struct _pkg2_kip1_info_t void pkg2_get_newkern_info(u8 *kern_data); u32 pkg2_calc_kip1_size(pkg2_kip1_t *kip1); -void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2); +bool pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2, bool *new_pkg2); pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb);