diff --git a/bootloader/hos/hos.c b/bootloader/hos/hos.c index 042be2f..1a4a616 100644 --- a/bootloader/hos/hos.c +++ b/bootloader/hos/hos.c @@ -866,10 +866,13 @@ int hos_launch(ini_sec_t *cfg) } } + // Configure and manage Warmboot binary. + pkg1_warmboot_config(&ctxt, kb, warmboot_base); + // Replace 'warmboot.bin' if requested. if (ctxt.warmboot) memcpy((void *)warmboot_base, ctxt.warmboot, ctxt.warmboot_size); - else + else if (!h_cfg.t210b01) { // Patch warmboot on T210 to allow downgrading. if (kb >= KB_FIRMWARE_VERSION_700) @@ -883,9 +886,6 @@ int hos_launch(ini_sec_t *cfg) for (u32 i = 0; warmboot_patchset[i].off != 0xFFFFFFFF; i++) *(vu32 *)(ctxt.pkg1_id->warmboot_base + warmboot_patchset[i].off) = warmboot_patchset[i].val; } - // Set warmboot address in PMC if required. - if (kb <= KB_FIRMWARE_VERSION_301) - PMC(APBDEV_PMC_SCRATCH1) = warmboot_base; // Replace 'SecureMonitor' if requested or patch Pkg2 checks if needed. if (ctxt.secmon) @@ -985,7 +985,6 @@ int hos_launch(ini_sec_t *cfg) } // Merge extra KIP1s into loaded ones. - gfx_printf("%kPatching kips%k\n", 0xFFFFBA00, 0xFFCCCCCC); LIST_FOREACH_ENTRY(merge_kip_t, mki, &ctxt.kip1_list, link) pkg2_merge_kip(&kip1_info, (pkg2_kip1_t *)mki->kip1); @@ -1004,6 +1003,7 @@ int hos_launch(ini_sec_t *cfg) } // Patch kip1s in memory if needed. + gfx_printf("%kPatching kips%k\n", 0xFFFFBA00, 0xFFCCCCCC); const char* unappliedPatch = pkg2_patch_kips(&kip1_info, ctxt.kip1_patches); if (unappliedPatch != NULL) { @@ -1034,12 +1034,6 @@ int hos_launch(ini_sec_t *cfg) int bootStateDramPkg2 = 0; int bootStatePkg2Continue = 0; - // Set warmboot PA address ids for 3.0.0 - 3.0.2. - if (kb == KB_FIRMWARE_VERSION_300) - PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id. - else if (kb == KB_FIRMWARE_VERSION_301) - PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id. - // Clear pkg1/pkg2 keys. se_aes_key_clear(8); se_aes_key_clear(11); diff --git a/bootloader/hos/pkg1.c b/bootloader/hos/pkg1.c index 1b4a673..cfd16f5 100644 --- a/bootloader/hos/pkg1.c +++ b/bootloader/hos/pkg1.c @@ -24,7 +24,11 @@ #include "../config.h" #include #include +#include #include +#include +#include +#include #include extern hekate_config h_cfg; @@ -215,3 +219,93 @@ const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, con return sec_map; } + +static void _warmboot_filename(char *out, u32 fuses) +{ + if (fuses < 16) + { + out[19] = '0'; + itoa(fuses, &out[19 + 1], 10); + } + else + itoa(fuses, &out[19], 10); + strcat(out, ".bin"); +} + +void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base) +{ + launch_ctxt_t *ctxt = (launch_ctxt_t *)hos_ctxt; + + // Set warmboot address in PMC if required. + if (kb <= KB_FIRMWARE_VERSION_301) + PMC(APBDEV_PMC_SCRATCH1) = warmboot_base; + + if (h_cfg.t210b01) + { + u32 pa_id; + u32 fuses_fw = kb + 2; + u32 fuses_max = KB_FIRMWARE_VERSION_MAX + 3; + u8 burnt_fuses = fuse_count_burnt(fuse_read_odm(7)); + + // Add one more fuse for high versions. + if (kb > KB_FIRMWARE_VERSION_910 || !memcmp(ctxt->pkg1_id->id, "20200303104606", 8)) + fuses_fw++; + + // Save current warmboot in storage cache and check if another one is needed. + if (!ctxt->warmboot) + { + char path[128]; + f_mkdir("warmboot_mariko"); + strcpy(path, "warmboot_mariko/wb_"); + _warmboot_filename(path, fuses_fw); + if (f_stat(path, NULL)) + sd_save_to_file((void *)warmboot_base, ctxt->warmboot_size, path); + + // Load warmboot fw from storage if not matched. + if (burnt_fuses > fuses_fw) + { + u32 tmp_fuses = burnt_fuses; + while (true) + { + _warmboot_filename(path, burnt_fuses); + if (!f_stat(path, NULL)) + { + ctxt->warmboot = sd_file_read(path, &ctxt->warmboot_size); + burnt_fuses = tmp_fuses; + break; + } + if (tmp_fuses >= fuses_max) + break; + tmp_fuses++; + } + } + } + + // Configure Warmboot parameters. + switch (burnt_fuses) + { + case KB_FIRMWARE_VERSION_600 + 2: // 7 fuses burnt. + pa_id = 0x87; + break; + case KB_FIRMWARE_VERSION_620 + 2: // 8 fuses burnt. 0x21 raise. + pa_id = 0xA8; + break; + default: // From 7.0.0 and up PA id raises by 0x21 with a static base. + pa_id = 0x129; + pa_id += 0x21 * (burnt_fuses - KB_FIRMWARE_VERSION_700 - 2); + break; + } + + // Set Warmboot Physical Address ID and lock SECURE_SCRATCH32 register. + PMC(APBDEV_PMC_SECURE_SCRATCH32) = pa_id; + PMC(APBDEV_PMC_SEC_DISABLE3) |= BIT(16); + } + else + { + // Set Warmboot Physical Address ID for 3.0.0 - 3.0.2. + if (kb == KB_FIRMWARE_VERSION_300) + PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0xE3; // Warmboot 3.0.0 PA address id. + else if (kb == KB_FIRMWARE_VERSION_301) + PMC(APBDEV_PMC_SECURE_SCRATCH32) = 0x104; // Warmboot 3.0.1/.2 PA address id. + } +} diff --git a/bootloader/hos/pkg1.h b/bootloader/hos/pkg1.h index ef17300..036b438 100644 --- a/bootloader/hos/pkg1.h +++ b/bootloader/hos/pkg1.h @@ -78,5 +78,6 @@ const pkg1_id_t *pkg1_get_latest(); const pkg1_id_t *pkg1_identify(u8 *pkg1); int pkg1_decrypt(const pkg1_id_t *id, u8 *pkg1); const u8 *pkg1_unpack(void *wm_dst, u32 *wb_sz, void *sm_dst, void *ldr_dst, const pkg1_id_t *id, u8 *pkg1); +void pkg1_warmboot_config(void *hos_ctxt, u32 kb, u32 warmboot_base); #endif