From 65b3b87c9962b6463f3d1da38f5f37b01942e214 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Fri, 15 Oct 2021 16:42:39 +0300 Subject: [PATCH] hos: pkg1: explicitly which type pkg1 is wrongly flashed --- bootloader/hos/hos.c | 40 ++++++++++++++++++++-------------------- bootloader/hos/pkg1.c | 9 ++++++--- bootloader/hos/pkg1.h | 37 ++++++++++++++++++++++++++++--------- bootloader/hos/pkg2.c | 2 ++ bootloader/hos/pkg2.h | 22 +++++++++++----------- 5 files changed, 67 insertions(+), 43 deletions(-) diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index 257e8ee..d0e9250 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -623,35 +623,35 @@ int hos_keygen(void *keyblob, u32 kb, tsec_ctxt_t *tsec_ctxt, bool stock, bool i static int _read_emmc_pkg1(launch_ctxt_t *ctxt) { - const u32 BOOTLOADER_SIZE = SZ_256K; - const u32 BOOTLOADER_MAIN_OFFSET = 0x100000; - const u32 BOOTLOADER_BACKUP_OFFSET = 0x140000; - const u32 HOS_KEYBLOBS_OFFSET = 0x180000; - - const u32 ERISTA_PKG1_ON_MARIKO_MAGIC = 0x20014770; // For 8.0.0 Erista and up. - - u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. - u32 bootloader_offset = BOOTLOADER_MAIN_OFFSET; - ctxt->pkg1 = (void *)malloc(BOOTLOADER_SIZE); + const u32 pk1_offset = h_cfg.t210b01 ? sizeof(bl_hdr_t210b01_t) : 0; // Skip T210B01 OEM header. + u32 bootloader_offset = PKG1_BOOTLOADER_MAIN_OFFSET; + ctxt->pkg1 = (void *)malloc(PKG1_BOOTLOADER_SIZE); try_load: // Read package1. emummc_storage_set_mmc_partition(EMMC_BOOT0); - emummc_storage_read(bootloader_offset / NX_EMMC_BLOCKSIZE, BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1); + emummc_storage_read(bootloader_offset / NX_EMMC_BLOCKSIZE, PKG1_BOOTLOADER_SIZE / NX_EMMC_BLOCKSIZE, ctxt->pkg1); ctxt->pkg1_id = pkg1_identify(ctxt->pkg1 + pk1_offset); if (!ctxt->pkg1_id) { // Check if wrong pkg1 was flashed. bool wrong_pkg1; - u32 pkg1_build_check = *(u32 *)(ctxt->pkg1 + pk1_offset + 0x10); - if (!h_cfg.t210b01) // For Erista check if start is 0 and build offset is not 0. - wrong_pkg1 = *(u32 *)ctxt->pkg1 == 0 && pkg1_build_check != 0; - else // For Mariko works for 8.0.0 Erista pkg1 and up. - wrong_pkg1 = pkg1_build_check == ERISTA_PKG1_ON_MARIKO_MAGIC; + + const u32 pkg1_erista_check = ((bl_hdr_t210b01_t *)ctxt->pkg1)->entrypoint; + const u32 pkg1_mariko_check = *(u32 *)(ctxt->pkg1 + sizeof(pk1_hdr_t) * 2); + + if (!h_cfg.t210b01) // For Erista check if start is 0 and entrypoint matches Mariko. + wrong_pkg1 = *(u32 *)ctxt->pkg1 == 0 && pkg1_erista_check == PKG1_MARIKO_ON_ERISTA_MAGIC; + else // For Mariko check if start is not 0 and build id. It works for 8.0.0 Erista pkg1 and up. + wrong_pkg1 = *(u32 *)ctxt->pkg1 != 0 && pkg1_mariko_check == PKG1_ERISTA_ON_MARIKO_MAGIC; if (wrong_pkg1) - _hos_crit_error("Wrong pkg1 flashed!"); + { + _hos_crit_error("Wrong pkg1 flashed:"); + EPRINTFARGS("%s pkg1 on %s!", + !h_cfg.t210b01 ? "Mariko" : "Erista", !h_cfg.t210b01 ? "Erista" : "Mariko"); + } else { _hos_crit_error("Unknown pkg1 version."); @@ -660,10 +660,10 @@ try_load: } // Try backup bootloader. - if (bootloader_offset != BOOTLOADER_BACKUP_OFFSET) + if (bootloader_offset != PKG1_BOOTLOADER_BACKUP_OFFSET) { EPRINTF("\nTrying backup bootloader..."); - bootloader_offset = BOOTLOADER_BACKUP_OFFSET; + bootloader_offset = PKG1_BOOTLOADER_BACKUP_OFFSET; goto try_load; } @@ -675,7 +675,7 @@ try_load: if (ctxt->pkg1_id->kb <= KB_FIRMWARE_VERSION_600) { ctxt->keyblob = (u8 *)calloc(NX_EMMC_BLOCKSIZE, 1); - emummc_storage_read(HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob); + emummc_storage_read(PKG1_HOS_KEYBLOBS_OFFSET / NX_EMMC_BLOCKSIZE + ctxt->pkg1_id->kb, 1, ctxt->keyblob); } return 1; diff --git a/bootloader/hos/pkg1.c b/bootloader/hos/pkg1.c index f4ae12c..bcc8d59 100644 --- a/bootloader/hos/pkg1.c +++ b/bootloader/hos/pkg1.c @@ -182,13 +182,16 @@ const pkg1_id_t *pkg1_get_latest() const pkg1_id_t *pkg1_identify(u8 *pkg1) { char build_date[15]; - memcpy(build_date, (char *)(pkg1 + 0x10), 14); + pk1_hdr_t *hdr = (pk1_hdr_t *)pkg1; + + memcpy(build_date, hdr->timestamp, 14); build_date[14] = 0; gfx_printf("Found pkg1 ('%s').\n\n", build_date); - for (u32 i = 0; i < ARRAY_SIZE(_pkg1_ids); i++) - if (!memcmp(pkg1 + 0x10, _pkg1_ids[i].id, 8)) + for (int i = ARRAY_SIZE(_pkg1_ids) - 1; i >= 0; i--) + if (!memcmp(hdr->timestamp, _pkg1_ids[i].id, 8)) return &_pkg1_ids[i]; + return NULL; } diff --git a/bootloader/hos/pkg1.h b/bootloader/hos/pkg1.h index 15565c0..6ae45f9 100644 --- a/bootloader/hos/pkg1.h +++ b/bootloader/hos/pkg1.h @@ -25,6 +25,14 @@ #define PK11_SECTION_LD 1 #define PK11_SECTION_SM 2 +#define PKG1_BOOTLOADER_SIZE SZ_256K +#define PKG1_BOOTLOADER_MAIN_OFFSET 0x100000 +#define PKG1_BOOTLOADER_BACKUP_OFFSET 0x140000 +#define PKG1_HOS_KEYBLOBS_OFFSET 0x180000 + +#define PKG1_ERISTA_ON_MARIKO_MAGIC 0xE59FD00C // For 4.0.0 Erista and up. +#define PKG1_MARIKO_ON_ERISTA_MAGIC 0x40010040 // Mariko pkg1 entrypoint. + typedef struct _patch_t { u32 off; @@ -39,17 +47,28 @@ typedef struct _patch_t typedef struct _bl_hdr_t210b01_t { - u8 aes_mac[0x10]; - u8 rsa_sig[0x100]; - u8 salt[0x20]; - u8 sha256[0x20]; - u32 version; - u32 size; - u32 load_addr; - u32 entrypoint; - u8 rsvd[0x10]; +/* 0x000 */ u8 aes_mac[0x10]; +/* 0x010 */ u8 rsa_sig[0x100]; +/* 0x110 */ u8 salt[0x20]; +/* 0x130 */ u8 sha256[0x20]; +/* 0x150 */ u32 version; +/* 0x154 */ u32 size; +/* 0x158 */ u32 load_addr; +/* 0x15C */ u32 entrypoint; +/* 0x160 */ u8 rsvd[0x10]; } bl_hdr_t210b01_t; +typedef struct _pk1_hdr_t +{ +/* 0x00 */ u32 si_sha256; // Secure Init. +/* 0x04 */ u32 sm_sha256; // Secure Monitor. +/* 0x08 */ u32 sl_sha256; // Secure Loader. +/* 0x0C */ u32 unk; // what's this? It's not warmboot. +/* 0x10 */ char timestamp[14]; +/* 0x1E */ u8 keygen; +/* 0x1F */ u8 version; +} pk1_hdr_t; + typedef struct _pkg1_id_t { const char *id; diff --git a/bootloader/hos/pkg2.c b/bootloader/hos/pkg2.c index cb3d74b..b0792b2 100644 --- a/bootloader/hos/pkg2.c +++ b/bootloader/hos/pkg2.c @@ -648,6 +648,7 @@ const char* pkg2_patch_kips(link_t *info, char* patchNames) } currPatchset++; } + if (emummc_patch_selected && !strncmp(_kip_id_sets[currKipIdx].name, "FS", sizeof(ki->kip1->name))) { emummc_patch_selected = false; @@ -715,6 +716,7 @@ pkg2_hdr_t *pkg2_decrypt(void *data, u8 kb, bool is_exo) if (hdr->magic != PKG2_MAGIC) return NULL; + // Decrypt sections. for (u32 i = 0; i < 4; i++) { DPRINTF("sec %d has size %08X\n", i, hdr->sec_size[i]); diff --git a/bootloader/hos/pkg2.h b/bootloader/hos/pkg2.h index 8a63a86..2c2fdc9 100644 --- a/bootloader/hos/pkg2.h +++ b/bootloader/hos/pkg2.h @@ -99,17 +99,17 @@ typedef struct _pkg2_kip1_sec_t typedef struct _pkg2_kip1_t { - u32 magic; - u8 name[12]; - u64 tid; - u32 proc_cat; - u8 main_thrd_prio; - u8 def_cpu_core; - u8 res; - u8 flags; - pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS]; - u32 caps[0x20]; - u8 data[]; +/* 0x000 */ u32 magic; +/* 0x004*/ u8 name[12]; +/* 0x010 */ u64 tid; +/* 0x018 */ u32 proc_cat; +/* 0x01C */ u8 main_thrd_prio; +/* 0x01D */ u8 def_cpu_core; +/* 0x01E */ u8 res; +/* 0x01F */ u8 flags; +/* 0x020 */ pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS]; +/* 0x080 */ u32 caps[0x20]; +/* 0x100 */ u8 data[]; } pkg2_kip1_t; typedef struct _pkg2_kip1_info_t