140 lines
4.4 KiB
C
140 lines
4.4 KiB
C
#include <unistd.h>
|
|
#include "toboot-api.h"
|
|
#include "toboot-internal.h"
|
|
|
|
// #define XXH_NO_LONG_LONG
|
|
// #define XXH_FORCE_ALIGN_CHECK 0
|
|
// #define XXH_FORCE_NATIVE_FORMAT 0
|
|
// #define XXH_PRIVATE_API
|
|
// #include "xxhash.h"
|
|
|
|
static const struct toboot_configuration *current_config = NULL;
|
|
|
|
uint32_t tb_first_free_address(void) {
|
|
return 131072;
|
|
/*
|
|
extern uint32_t _eflash;
|
|
extern uint32_t _sdtext;
|
|
extern uint32_t _edtext;
|
|
#define PADDR(x) ((uint32_t)&x)
|
|
#define PAGE_SIZE 1024
|
|
#define PAGE_ROUND_UP(x) ( (((uint32_t)(x)) + PAGE_SIZE-1) & (~(PAGE_SIZE-1)) )
|
|
return PAGE_ROUND_UP(PADDR(_eflash) + (PADDR(_edtext) - PADDR(_sdtext)));
|
|
#undef PADDR
|
|
#undef PAGE_SIZE
|
|
#undef PAGE_ROUND_UP
|
|
*/
|
|
}
|
|
|
|
uint32_t tb_config_hash(const struct toboot_configuration *cfg) {
|
|
return 0;//XXH32(cfg, sizeof(*cfg) - 4, TOBOOT_HASH_SEED);
|
|
}
|
|
|
|
void tb_sign_config(struct toboot_configuration *cfg) {
|
|
cfg->reserved_hash = tb_config_hash(cfg);
|
|
}
|
|
|
|
int tb_valid_signature_at_page(uint32_t page) {
|
|
const struct toboot_configuration *cfg = (const struct toboot_configuration *)((page * 1024) + 0x94);
|
|
if (cfg->magic != TOBOOT_V2_MAGIC)
|
|
return -1;
|
|
|
|
uint32_t calc_hash = tb_config_hash(cfg);
|
|
if (calc_hash != cfg->reserved_hash)
|
|
return -2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32_t tb_first_free_sector(void) {
|
|
return tb_first_free_address() / 1024;
|
|
}
|
|
|
|
const struct toboot_configuration *tb_get_config(void) {
|
|
uint32_t __app_start__ = 131072;
|
|
|
|
// When examining every application in flash, find the newest program
|
|
// with the highest generation counter.
|
|
uint32_t newest_generation = 0;
|
|
|
|
// Fake toboot config, for v1 and v0 programs.
|
|
static struct toboot_configuration fake_config;
|
|
|
|
if (current_config)
|
|
return current_config;
|
|
|
|
// Look for a V2 header
|
|
uint32_t page;
|
|
for (page = 1; page < 65536/1024; page++) {
|
|
if (!tb_valid_signature_at_page(page)) {
|
|
const struct toboot_configuration *test_cfg = (const struct toboot_configuration *)((page * 1024) + 0x94);
|
|
if (test_cfg->reserved_gen > newest_generation) {
|
|
newest_generation = test_cfg->reserved_gen;
|
|
current_config = test_cfg;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (current_config)
|
|
return current_config;
|
|
|
|
// No V2 header found, so create one.
|
|
|
|
// Fake V2 magic
|
|
fake_config.magic = TOBOOT_V2_MAGIC;
|
|
|
|
if (((*((uint32_t *)(((uint32_t)&__app_start__) + 0x98))) & TOBOOT_V1_MAGIC_MASK) == TOBOOT_V1_MAGIC)
|
|
// Applications that know about Toboot will indicate their block
|
|
// offset by placing a magic byte at offset 0x98.
|
|
// Ordinarily this would be the address offset for IRQ 22,
|
|
// but since there are only 20 IRQs on the EFM32HG, there are three
|
|
// 32-bit values that are unused starting at offset 0x94.
|
|
// We already use offset 0x94 for "disable boot", so use offset 0x98
|
|
// in the incoming stream to indicate flags for Toboot.
|
|
fake_config.start = ((*((uint32_t *)(((uint32_t)&__app_start__) + 0x98))) & TOBOOT_V1_APP_PAGE_MASK) >> TOBOOT_V1_APP_PAGE_SHIFT;
|
|
else
|
|
// Default to offset 0x4000
|
|
fake_config.start = 16;
|
|
|
|
// Leave interrupts enabled (and indicate the header is fake)
|
|
fake_config.config = TOBOOT_CONFIG_FLAG_ENABLE_IRQ | TOBOOT_CONFIG_FAKE;
|
|
|
|
// Lock out bootloader entry, if the magic value is present
|
|
if (((*((uint32_t *)(((uint32_t)&__app_start__) + 0x94))) & TOBOOT_V1_CFG_MAGIC_MASK) == TOBOOT_V1_CFG_MAGIC)
|
|
fake_config.lock_entry = TOBOOT_LOCKOUT_MAGIC;
|
|
else
|
|
fake_config.lock_entry = 0;
|
|
|
|
// Don't erase anything in particular
|
|
fake_config.erase_mask_lo = 0;
|
|
fake_config.erase_mask_hi = 0;
|
|
|
|
// Calculate a valid hash
|
|
tb_sign_config(&fake_config);
|
|
|
|
return &fake_config;
|
|
}
|
|
|
|
uint32_t tb_generation(const struct toboot_configuration *cfg) {
|
|
if (!cfg)
|
|
return 0;
|
|
return cfg->reserved_gen;
|
|
}
|
|
/*
|
|
__attribute__ ((used, section(".toboot_configuration"))) struct toboot_configuration toboot_configuration = {
|
|
.magic = TOBOOT_V2_MAGIC,
|
|
|
|
// The current "generation" flag sits at the same location as the
|
|
// old Toboot "Config" flag. By setting "reserved_gen" to this value,
|
|
// we can make the V1 bootloader treat V2 images as valid.
|
|
.reserved_gen = TOBOOT_V1_APP_MAGIC,
|
|
|
|
.start = 0,
|
|
.config = 0,
|
|
|
|
.lock_entry = 0,
|
|
.erase_mask_lo = 0,
|
|
.erase_mask_hi = 0,
|
|
.reserved_hash = 0,
|
|
};
|
|
*/ |