nyx: boost dump pkg1/2 functionality

The tool can now dump main and safe pkg1/2.
Additionally, it can identify if FS is exfat or not and set the proper filename.
(FAT32 only FS will still use FS.kip1)
Lastly, this will also dump and decrypt the main/safe BCT structures.
This commit is contained in:
CTCaer
2025-08-08 15:34:17 +03:00
parent 885cc195c0
commit b33ab240f2
2 changed files with 322 additions and 240 deletions

View File

@@ -28,6 +28,7 @@
#include "../hos/pkg1.h"
#include "../hos/pkg2.h"
#include "../hos/hos.h"
#include <libs/compr/blz.h>
#include <libs/fatfs/ff.h>
extern volatile boot_cfg_t *b_cfg;
@@ -1127,11 +1128,20 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
lv_obj_t *desc = lv_cont_create(win, NULL);
lv_obj_set_size(desc, LV_HOR_RES * 10 / 11, LV_VER_RES - (LV_DPI * 12 / 7));
lv_obj_t * lb_desc = lv_label_create(desc, NULL);
lv_obj_t *lb_desc = lv_label_create(desc, NULL);
lv_obj_set_style(lb_desc, &monospace_text);
lv_label_set_long_mode(lb_desc, LV_LABEL_LONG_BREAK);
lv_label_set_recolor(lb_desc, true);
lv_obj_set_width(lb_desc, lv_obj_get_width(desc));
lv_obj_set_width(lb_desc, lv_obj_get_width(desc) / 2);
lv_obj_t *lb_desc2 = lv_label_create(desc, NULL);
lv_obj_set_style(lb_desc2, &monospace_text);
lv_label_set_long_mode(lb_desc2, LV_LABEL_LONG_BREAK);
lv_label_set_recolor(lb_desc2, true);
lv_obj_set_width(lb_desc2, lv_obj_get_width(desc) / 2);
lv_label_set_text(lb_desc2, " ");
lv_obj_align(lb_desc2, lb_desc, LV_ALIGN_OUT_RIGHT_TOP, 0, 0);
if (!sd_mount())
{
@@ -1147,7 +1157,7 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
u8 *warmboot = (u8 *)zalloc(SZ_256K);
u8 *secmon = (u8 *)zalloc(SZ_256K);
u8 *loader = (u8 *)zalloc(SZ_256K);
u8 *pkg2 = NULL;
u8 *pkg2 = (u8 *)zalloc(SZ_8M);
char *txt_buf = (char *)malloc(SZ_16K);
@@ -1158,266 +1168,332 @@ static lv_res_t _create_window_dump_pk12_tool(lv_obj_t *btn)
goto out_free;
}
emmc_set_partition(EMMC_BOOT0);
char *bct_paths[2] = {
"/pkg/main",
"/pkg/safe"
};
// Read package1.
static const u32 BOOTLOADER_SIZE = SZ_256K;
static const u32 BOOTLOADER_MAIN_OFFSET = 0x100000;
static const u32 HOS_EKS_OFFSET = 0x180000;
char *pkg1_paths[2] = {
"/pkg/main/pkg1",
"/pkg/safe/pkg1"
};
char *build_date = malloc(32);
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
sdmmc_storage_read(&emmc_storage, BOOTLOADER_MAIN_OFFSET / EMMC_BLOCKSIZE, BOOTLOADER_SIZE / EMMC_BLOCKSIZE, pkg1);
char *pkg2_partitions[2] = {
"BCPKG2-1-Normal-Main",
"BCPKG2-3-SafeMode-Main"
};
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date);
char *pkg2_paths[2] = {
"/pkg/main/pkg2",
"/pkg/safe/pkg2"
};
s_printf(txt_buf, "#00DDFF Found pkg1 ('%s')#\n\n", build_date);
free(build_date);
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
char *pkg2ini_paths[2] = {
"/pkg/main/pkg2/ini",
"/pkg/safe/pkg2/ini"
};
// Dump package1 in its encrypted state.
emmcsn_path_impl(path, "/pkg1", "pkg1_enc.bin", &emmc_storage);
bool res = sd_save_to_file(pkg1, BOOTLOADER_SIZE, path);
// Create main directories.
emmcsn_path_impl(path, "/pkg", "", &emmc_storage);
emmcsn_path_impl(path, "/pkg/main", "", &emmc_storage);
emmcsn_path_impl(path, "/pkg/safe", "", &emmc_storage);
// Exit if unknown.
if (!pkg1_id)
{
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
if (!res)
{
strcat(txt_buf, "\nEncrypted pkg1 dumped to pkg1_enc.bin");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
}
goto out_free;
}
mkey = pkg1_id->mkey;
tsec_ctxt_t tsec_ctxt = {0};
tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off);
tsec_ctxt.pkg1 = (void *)pkg1;
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
// Read the correct eks for older HOS versions.
const u32 eks_size = sizeof(pkg1_eks_t);
pkg1_eks_t *eks = (pkg1_eks_t *)malloc(eks_size);
emmc_set_partition(EMMC_BOOT0);
sdmmc_storage_read(&emmc_storage, HOS_EKS_OFFSET + (mkey * eks_size) / EMMC_BLOCKSIZE,
eks_size / EMMC_BLOCKSIZE, eks);
// Generate keys.
hos_keygen(eks, mkey, &tsec_ctxt);
free(eks);
if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_600)
{
if (!pkg1_decrypt(pkg1_id, pkg1))
{
strcat(txt_buf, "#FFDD00 Pkg1 decryption failed!#\n");
if (h_cfg.t210b01)
strcat(txt_buf, "#FFDD00 Is BEK missing?#\n");
lv_label_set_text(lb_desc, txt_buf);
goto out_free;
}
}
if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_620)
{
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1 + pk1_offset);
pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pk1_offset + pkg1_id->pkg11_off + 0x20);
// Display info.
s_printf(txt_buf + strlen(txt_buf),
"#C7EA46 NX Bootloader size: #0x%05X\n"
"#C7EA46 Secure monitor addr: #0x%05X\n"
"#C7EA46 Secure monitor size: #0x%05X\n"
"#C7EA46 Warmboot addr: #0x%05X\n"
"#C7EA46 Warmboot size: #0x%05X\n\n",
hdr_pk11->ldr_size, pkg1_id->secmon_base, hdr_pk11->sm_size, pkg1_id->warmboot_base, hdr_pk11->wb_size);
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump package1.1.
emmcsn_path_impl(path, "/pkg1", "pkg1_decr.bin", &emmc_storage);
if (sd_save_to_file(pkg1, SZ_256K, path))
goto out_free;
strcat(txt_buf, "pkg1 dumped to pkg1_decr.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump nxbootloader.
emmcsn_path_impl(path, "/pkg1", "nxloader.bin", &emmc_storage);
if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
goto out_free;
strcat(txt_buf, "NX Bootloader dumped to nxloader.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump secmon.
emmcsn_path_impl(path, "/pkg1", "secmon.bin", &emmc_storage);
if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
goto out_free;
strcat(txt_buf, "Secure Monitor dumped to secmon.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump warmboot.
emmcsn_path_impl(path, "/pkg1", "warmboot.bin", &emmc_storage);
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free;
// If T210B01, save a copy of decrypted warmboot binary also.
if (h_cfg.t210b01)
{
se_aes_iv_clear(13);
se_aes_crypt_cbc(13, DECRYPT, warmboot + 0x330, hdr_pk11->wb_size - 0x330,
warmboot + 0x330, hdr_pk11->wb_size - 0x330);
emmcsn_path_impl(path, "/pkg1", "warmboot_dec.bin", &emmc_storage);
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out_free;
}
strcat(txt_buf, "Warmboot dumped to warmboot.bin\n\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
}
// Dump package2.1.
emmc_set_partition(EMMC_GPP);
// Parse eMMC GPT.
emmc_set_partition(EMMC_GPP);
LIST_INIT(gpt);
emmc_gpt_parse(&gpt);
// Find package2 partition.
emmc_part_t *pkg2_part = emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
if (!pkg2_part)
goto out;
// Read in package2 header and get package2 real size.
u8 *tmp = (u8 *)malloc(EMMC_BLOCKSIZE);
emmc_part_read(pkg2_part, 0x4000 / EMMC_BLOCKSIZE, 1, tmp);
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
free(tmp);
// Read in package2.
u32 pkg2_size_aligned = ALIGN(pkg2_size, EMMC_BLOCKSIZE);
pkg2 = malloc(pkg2_size_aligned);
emmc_part_read(pkg2_part, 0x4000 / EMMC_BLOCKSIZE,
pkg2_size_aligned / EMMC_BLOCKSIZE, pkg2);
// Dump encrypted package2.
emmcsn_path_impl(path, "/pkg2", "pkg2_encr.bin", &emmc_storage);
res = sd_save_to_file(pkg2, pkg2_size, path);
// Decrypt package2 and parse KIP1 blobs in INI1 section.
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, mkey);
if (!pkg2_hdr)
lv_obj_t *lb_log = lb_desc;
for (u32 idx = 0; idx < 2; idx++)
{
strcat(txt_buf, "#FFDD00 Pkg2 decryption failed!#");
lv_label_set_text(lb_desc, txt_buf);
if (idx)
lb_log = lb_desc2;
// Read package1.
char *build_date = malloc(32);
u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header.
emmc_set_partition(!idx ? EMMC_BOOT0 : EMMC_BOOT1);
sdmmc_storage_read(&emmc_storage,
!idx ? PKG1_BOOTLOADER_MAIN_OFFSET : PKG1_BOOTLOADER_SAFE_OFFSET, PKG1_BOOTLOADER_SIZE / EMMC_BLOCKSIZE, pkg1);
const pkg1_id_t *pkg1_id = pkg1_identify(pkg1 + pk1_offset, build_date);
s_printf(txt_buf, "#00DDFF Found %s pkg1 ('%s')#\n\n", !idx ? "Main" : "Safe", build_date);
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
free(build_date);
if (!res)
// Dump package1 in its encrypted state.
emmcsn_path_impl(path, pkg1_paths[idx], "pkg1_enc.bin", &emmc_storage);
bool res = sd_save_to_file(pkg1, PKG1_BOOTLOADER_SIZE, path);
// Exit if unknown.
if (!pkg1_id)
{
strcat(txt_buf, "\npkg2 encrypted dumped to pkg2_encr.bin\n");
lv_label_set_text(lb_desc, txt_buf);
strcat(txt_buf, "#FFDD00 Unknown pkg1 version!#");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
}
// Clear EKS slot, in case something went wrong with tsec keygen.
hos_eks_clear(mkey);
if (!res)
{
strcat(txt_buf, "\nEncrypted pkg1 extracted to pkg1_enc.bin");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
}
goto out;
}
// Display info.
s_printf(txt_buf + strlen(txt_buf),
"#C7EA46 Kernel size: #0x%05X\n"
"#C7EA46 INI1 size: #0x%05X\n\n",
pkg2_hdr->sec_size[PKG2_SEC_KERNEL], pkg2_hdr->sec_size[PKG2_SEC_INI1]);
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump pkg2.1.
emmcsn_path_impl(path, "/pkg2", "pkg2_decr.bin", &emmc_storage);
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
goto out;
strcat(txt_buf, "pkg2 dumped to pkg2_decr.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump kernel.
emmcsn_path_impl(path, "/pkg2", "kernel.bin", &emmc_storage);
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
goto out;
strcat(txt_buf, "Kernel dumped to kernel.bin\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
// Dump INI1.
u32 ini1_off = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
u32 ini1_size = pkg2_hdr->sec_size[PKG2_SEC_INI1];
if (!ini1_size)
{
pkg2_get_newkern_info(pkg2_hdr->data);
ini1_off = pkg2_newkern_ini1_start;
ini1_size = pkg2_newkern_ini1_end - pkg2_newkern_ini1_start;
}
if (!ini1_off)
{
strcat(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", &emmc_storage);
if (sd_save_to_file(ini1, ini1_size, path))
goto out;
strcat(txt_buf, "INI1 dumped to ini1.bin\n\n");
lv_label_set_text(lb_desc, txt_buf);
manual_system_maintenance(true);
char filename[32];
u8 *ptr = (u8 *)ini1;
ptr += sizeof(pkg2_ini1_t);
// Dump all kips.
u8 *kip_buffer = (u8 *)malloc(SZ_4M);
for (u32 i = 0; i < ini1->num_procs; i++)
{
pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr;
u32 kip1_size = pkg2_calc_kip1_size(kip1);
s_printf(filename, "%s.kip1", kip1->name);
if ((u32)kip1 % 8)
{
memcpy(kip_buffer, kip1, kip1_size);
kip1 = (pkg2_kip1_t *)kip_buffer;
}
emmcsn_path_impl(path, "/pkg2/ini1", filename, &emmc_storage);
if (sd_save_to_file(kip1, kip1_size, path))
{
free(kip_buffer);
goto out;
}
s_printf(txt_buf + strlen(txt_buf), "%s kip dumped to %s.kip1\n", kip1->name, kip1->name);
lv_label_set_text(lb_desc, txt_buf);
mkey = pkg1_id->mkey;
tsec_ctxt_t tsec_ctxt = {0};
tsec_ctxt.fw = (void *)(pkg1 + pkg1_id->tsec_off);
tsec_ctxt.pkg1 = (void *)pkg1;
tsec_ctxt.pkg11_off = pkg1_id->pkg11_off;
// Read the correct eks for older HOS versions.
const u32 eks_size = sizeof(pkg1_eks_t);
pkg1_eks_t *eks = (pkg1_eks_t *)malloc(eks_size);
emmc_set_partition(EMMC_BOOT0);
sdmmc_storage_read(&emmc_storage, PKG1_HOS_EKS_OFFSET + (mkey * eks_size) / EMMC_BLOCKSIZE,
eks_size / EMMC_BLOCKSIZE, eks);
// Generate keys.
hos_keygen(eks, mkey, &tsec_ctxt);
free(eks);
// Decrypt.
if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_600)
{
if (!pkg1_decrypt(pkg1_id, pkg1))
{
strcat(txt_buf, "#FFDD00 Pkg1 decryption failed!#\n");
if (h_cfg.t210b01)
strcat(txt_buf, "#FFDD00 Is BEK missing?#\n");
lv_label_set_text(lb_log, txt_buf);
goto out;
}
}
// Dump the BCTs from blocks 2/3 (backup) which are normally valid.
static const u32 BCT_SIZE = 0x2800;
static const u32 BLK_SIZE = SZ_16K / EMMC_BLOCKSIZE;
u8 *bct = (u8 *)zalloc(BCT_SIZE);
sdmmc_storage_read(&emmc_storage, BLK_SIZE * 2 + BLK_SIZE * idx, BCT_SIZE / EMMC_BLOCKSIZE, bct);
emmcsn_path_impl(path, bct_paths[idx], "bct.bin", &emmc_storage);
if (sd_save_to_file(bct, 0x2800, path))
goto out;
if (h_cfg.t210b01)
{
se_aes_iv_clear(13);
se_aes_crypt_cbc(13, DECRYPT, bct + 0x480, BCT_SIZE - 0x480, bct + 0x480, BCT_SIZE - 0x480);
emmcsn_path_impl(path, bct_paths[idx], "bct_decr.bin", &emmc_storage);
if (sd_save_to_file(bct, 0x2800, path))
goto out;
}
// Dump package1.1 contents.
if (h_cfg.t210b01 || mkey <= HOS_MKEY_VER_620)
{
pkg1_unpack(warmboot, secmon, loader, pkg1_id, pkg1 + pk1_offset);
pk11_hdr_t *hdr_pk11 = (pk11_hdr_t *)(pkg1 + pk1_offset + pkg1_id->pkg11_off + 0x20);
// Display info.
s_printf(txt_buf + strlen(txt_buf),
"#C7EA46 NX Bootloader size: #0x%05X\n"
"#C7EA46 Secure monitor size: #0x%05X\n"
"#C7EA46 Warmboot size: #0x%05X\n\n",
hdr_pk11->ldr_size, hdr_pk11->sm_size, hdr_pk11->wb_size);
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
// Dump package1.1.
emmcsn_path_impl(path, pkg1_paths[idx], "pkg1_decr.bin", &emmc_storage);
if (sd_save_to_file(pkg1, SZ_256K, path))
goto out;
strcat(txt_buf, "Package1 extracted to pkg1_decr.bin\n");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
// Dump nxbootloader.
emmcsn_path_impl(path, pkg1_paths[idx], "nxloader.bin", &emmc_storage);
if (sd_save_to_file(loader, hdr_pk11->ldr_size, path))
goto out;
strcat(txt_buf, "NX Bootloader extracted to nxloader.bin\n");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
// Dump secmon.
emmcsn_path_impl(path, pkg1_paths[idx], "secmon.bin", &emmc_storage);
if (sd_save_to_file(secmon, hdr_pk11->sm_size, path))
goto out;
strcat(txt_buf, "Secure Monitor extracted to secmon.bin\n");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
// Dump warmboot.
emmcsn_path_impl(path, pkg1_paths[idx], "warmboot.bin", &emmc_storage);
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out;
// If T210B01, save a copy of decrypted warmboot binary also.
if (h_cfg.t210b01)
{
se_aes_iv_clear(13);
se_aes_crypt_cbc(13, DECRYPT, warmboot + 0x330, hdr_pk11->wb_size - 0x330,
warmboot + 0x330, hdr_pk11->wb_size - 0x330);
emmcsn_path_impl(path, pkg1_paths[idx], "warmboot_dec.bin", &emmc_storage);
if (sd_save_to_file(warmboot, hdr_pk11->wb_size, path))
goto out;
}
strcat(txt_buf, "Warmboot extracted to warmboot.bin\n\n");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
}
// Find and dump package2 partition.
emmc_set_partition(EMMC_GPP);
emmc_part_t *pkg2_part = emmc_part_find(&gpt, pkg2_partitions[idx]);
if (!pkg2_part)
goto out;
// Read in package2 header and get package2 real size.
static const u32 PKG2_OFFSET = 0x4000;
u8 *tmp = (u8 *)malloc(EMMC_BLOCKSIZE);
emmc_part_read(pkg2_part, PKG2_OFFSET / EMMC_BLOCKSIZE, 1, tmp);
u32 *hdr_pkg2_raw = (u32 *)(tmp + 0x100);
u32 pkg2_size = hdr_pkg2_raw[0] ^ hdr_pkg2_raw[2] ^ hdr_pkg2_raw[3];
free(tmp);
// Read in package2.
u32 pkg2_size_aligned = ALIGN(pkg2_size, EMMC_BLOCKSIZE);
emmc_part_read(pkg2_part, PKG2_OFFSET / EMMC_BLOCKSIZE, pkg2_size_aligned / EMMC_BLOCKSIZE, pkg2);
// Dump encrypted package2.
emmcsn_path_impl(path, pkg2_paths[idx], "pkg2_encr.bin", &emmc_storage);
res = sd_save_to_file(pkg2, pkg2_size, path);
// Decrypt package2 and parse KIP1 blobs in INI1 section.
pkg2_hdr_t *pkg2_hdr = pkg2_decrypt(pkg2, mkey);
if (!pkg2_hdr)
{
strcat(txt_buf, "#FFDD00 Pkg2 decryption failed!#");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
if (!res)
{
strcat(txt_buf, "\npkg2 encrypted extracted to pkg2_encr.bin\n");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
}
// Clear EKS slot, in case something went wrong with tsec keygen.
hos_eks_clear(mkey);
goto out;
}
// Display info.
s_printf(txt_buf + strlen(txt_buf),
"#C7EA46 Kernel size: #0x%06X\n"
"#C7EA46 INI1 size: #0x%06X\n\n",
pkg2_hdr->sec_size[PKG2_SEC_KERNEL], pkg2_hdr->sec_size[PKG2_SEC_INI1]);
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
ptr += kip1_size;
// Dump pkg2.1.
emmcsn_path_impl(path, pkg2_paths[idx], "pkg2_decr.bin", &emmc_storage);
if (sd_save_to_file(pkg2, pkg2_hdr->sec_size[PKG2_SEC_KERNEL] + pkg2_hdr->sec_size[PKG2_SEC_INI1], path))
goto out;
strcat(txt_buf, "Package2 extracted to pkg2_decr.bin\n");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
// Dump kernel.
emmcsn_path_impl(path, pkg2_paths[idx], "kernel.bin", &emmc_storage);
if (sd_save_to_file(pkg2_hdr->data, pkg2_hdr->sec_size[PKG2_SEC_KERNEL], path))
goto out;
strcat(txt_buf, "Kernel extracted to kernel.bin\n");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
// Dump INI1.
u32 ini1_off = pkg2_hdr->sec_size[PKG2_SEC_KERNEL];
u32 ini1_size = pkg2_hdr->sec_size[PKG2_SEC_INI1];
if (!ini1_size)
{
pkg2_get_newkern_info(pkg2_hdr->data);
ini1_off = pkg2_newkern_ini1_start;
ini1_size = pkg2_newkern_ini1_end - pkg2_newkern_ini1_start;
}
if (!ini1_off)
{
strcat(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_paths[idx], "ini1.bin", &emmc_storage);
if (sd_save_to_file(ini1, ini1_size, path))
goto out;
strcat(txt_buf, "INI1 extracted to ini1.bin\n");
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
char filename[32];
u8 *ptr = (u8 *)ini1;
ptr += sizeof(pkg2_ini1_t);
// Dump all kips.
for (u32 i = 0; i < ini1->num_procs; i++)
{
pkg2_kip1_t *kip1 = (pkg2_kip1_t *)ptr;
u32 kip1_size = pkg2_calc_kip1_size(kip1);
char *kip_name = kip1->name;
// Check if FS supports exFAT.
if (!strcmp("FS", kip_name))
{
u8 *ro_data = malloc(SZ_4M);
u32 offset = (kip1->flags & BIT(KIP_TEXT)) ? kip1->sections[KIP_TEXT].size_comp :
kip1->sections[KIP_TEXT].size_decomp;
u32 size_comp = kip1->sections[KIP_RODATA].size_comp;
u32 size_decomp = kip1->sections[KIP_RODATA].size_decomp;
if (kip1->flags & BIT(KIP_RODATA))
blz_uncompress_srcdest(&kip1->data[offset], size_comp, ro_data, size_decomp);
else
memcpy(ro_data, &kip1->data[offset], size_decomp);
for (u32 i = 0; i < 0x100; i+= sizeof(u32))
{
// Check size and name of nss matches.
if (*(u32 *)&ro_data[i] == 8 && !memcmp("fs.exfat", &ro_data[i + 4], 8))
{
kip_name = "FS_exfat";
break;
}
}
free(ro_data);
}
s_printf(filename, "%s.kip1", kip_name);
emmcsn_path_impl(path, pkg2ini_paths[idx], filename, &emmc_storage);
if (sd_save_to_file(kip1, kip1_size, path))
goto out;
s_printf(txt_buf + strlen(txt_buf), "- Extracted %s.kip1\n", kip_name);
lv_label_set_text(lb_log, txt_buf);
manual_system_maintenance(true);
ptr += kip1_size;
}
}
free(kip_buffer);
out:
emmc_gpt_free(&gpt);

View File

@@ -26,6 +26,12 @@
#define PK11_SECTION_LD 1
#define PK11_SECTION_SM 2
#define PKG1_BOOTLOADER_SIZE SZ_256K
#define PKG1_BOOTLOADER_MAIN_OFFSET (0x100000 / EMMC_BLOCKSIZE)
#define PKG1_BOOTLOADER_BACKUP_OFFSET (0x140000 / EMMC_BLOCKSIZE)
#define PKG1_BOOTLOADER_SAFE_OFFSET (0x000000 / EMMC_BLOCKSIZE)
#define PKG1_HOS_EKS_OFFSET (0x180000 / EMMC_BLOCKSIZE)
typedef struct _bl_hdr_t210b01_t
{
/* 0x000 */ u8 aes_mac[0x10];