hos: Add Mariko warmboot storage and general configurator

The Mariko warmboot storage is needed because the warmboot exploit is not existant.

Fuses and PA id must match with the proper warmboot binary. Thus for supporting downgrades, we keep a copy of it for future use.
This commit is contained in:
CTCaer 2020-07-04 21:43:34 +03:00
parent 495907b8a4
commit a862b85a46
3 changed files with 100 additions and 11 deletions

View file

@ -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);

View file

@ -24,7 +24,11 @@
#include "../config.h"
#include <gfx_utils.h>
#include <mem/heap.h>
#include <soc/fuse.h>
#include <sec/se.h>
#include <soc/pmc.h>
#include <soc/t210.h>
#include <storage/nx_sd.h>
#include <utils/aarch64_util.h>
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.
}
}

View file

@ -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