mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 23:08:14 +00:00
Cleaner flash handling using FLASH_PTR
Use `FLASH_PTR` macro to convert a flash address to a const pointer. For real hardware it is just a cast, for emulator we subtract the `FLASH_ORIGIN` and use it as index into the memory mapped flash file. Make write access to flash with volatile pointers Also use FLASH_PTR in DebugMemory* for now. This allows for reading and writing the flash in the emulator or just crash it by reading outside the flash...
This commit is contained in:
parent
1fcd512b7f
commit
c09590b54d
@ -13,7 +13,7 @@ AS := as
|
||||
|
||||
OPTFLAGS ?= -O3
|
||||
DBGFLAGS ?= -g3 -ggdb3
|
||||
CPUFLAGS ?= -m32
|
||||
CPUFLAGS ?=
|
||||
FPUFLAGS ?=
|
||||
else
|
||||
PREFIX ?= arm-none-eabi-
|
||||
|
@ -81,19 +81,19 @@ void __attribute__((noreturn)) load_app(int signed_firmware)
|
||||
// zero out SRAM
|
||||
memset_reg(_ram_start, _ram_end, 0);
|
||||
|
||||
jump_to_firmware((const vector_table_t *) FLASH_APP_START, signed_firmware);
|
||||
jump_to_firmware((const vector_table_t *) FLASH_PTR(FLASH_APP_START), signed_firmware);
|
||||
}
|
||||
|
||||
bool firmware_present(void)
|
||||
{
|
||||
#ifndef APPVER
|
||||
if (memcmp((const void *)FLASH_META_MAGIC, "TRZR", 4)) { // magic does not match
|
||||
if (memcmp(FLASH_PTR(FLASH_META_MAGIC), "TRZR", 4)) { // magic does not match
|
||||
return false;
|
||||
}
|
||||
if (*((const uint32_t *)FLASH_META_CODELEN) < 4096) { // firmware reports smaller size than 4kB
|
||||
if (*((const uint32_t *)FLASH_PTR(FLASH_META_CODELEN)) < 4096) { // firmware reports smaller size than 4kB
|
||||
return false;
|
||||
}
|
||||
if (*((const uint32_t *)FLASH_META_CODELEN) > FLASH_TOTAL_SIZE - (FLASH_APP_START - FLASH_ORIGIN)) { // firmware reports bigger size than flash size
|
||||
if (*((const uint32_t *)FLASH_PTR(FLASH_META_CODELEN)) > FLASH_TOTAL_SIZE - (FLASH_APP_START - FLASH_ORIGIN)) { // firmware reports bigger size than flash size
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@ -302,7 +302,7 @@ static void erase_metadata_sectors(void)
|
||||
|
||||
static void backup_metadata(uint8_t *backup)
|
||||
{
|
||||
memcpy(backup, (void *)FLASH_META_START, FLASH_META_LEN);
|
||||
memcpy(backup, FLASH_PTR(FLASH_META_START), FLASH_META_LEN);
|
||||
}
|
||||
|
||||
static void restore_metadata(const uint8_t *backup)
|
||||
@ -434,7 +434,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
|
||||
|
||||
// compute hash of written test pattern
|
||||
uint8_t hash[32];
|
||||
sha256_Raw((unsigned char *)FLASH_META_START, FLASH_META_LEN, hash);
|
||||
sha256_Raw(FLASH_PTR(FLASH_META_START), FLASH_META_LEN, hash);
|
||||
|
||||
// restore metadata from backup
|
||||
erase_metadata_sectors();
|
||||
@ -504,7 +504,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
|
||||
// flash status register should show now error and
|
||||
// the config block should contain only \xff.
|
||||
uint8_t hash[32];
|
||||
sha256_Raw((unsigned char *)FLASH_META_START, FLASH_META_LEN, hash);
|
||||
sha256_Raw(FLASH_PTR(FLASH_META_START), FLASH_META_LEN, hash);
|
||||
if ((FLASH_SR & (FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR)) != 0
|
||||
|| memcmp(hash, "\x2d\x86\x4c\x0b\x78\x9a\x43\x21\x4e\xee\x85\x24\xd3\x18\x20\x75\x12\x5e\x5c\xa2\xcd\x52\x7f\x35\x82\xec\x87\xff\xd9\x40\x76\xbc", 32) != 0) {
|
||||
send_msg_failure(dev);
|
||||
@ -619,7 +619,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
|
||||
return;
|
||||
}
|
||||
uint8_t hash[32];
|
||||
sha256_Raw((unsigned char *)FLASH_APP_START, flash_len - FLASH_META_DESC_LEN, hash);
|
||||
sha256_Raw(FLASH_PTR(FLASH_APP_START), flash_len - FLASH_META_DESC_LEN, hash);
|
||||
layoutFirmwareHash(hash);
|
||||
do {
|
||||
delay(100000);
|
||||
@ -630,7 +630,7 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
|
||||
bool hash_check_ok = brand_new_firmware || button.YesUp;
|
||||
|
||||
layoutProgress("INSTALLING ... Please wait", 1000);
|
||||
uint8_t flags = *((uint8_t *)FLASH_META_FLAGS);
|
||||
uint8_t flags = *FLASH_PTR(FLASH_META_FLAGS);
|
||||
// wipe storage if:
|
||||
// 0) there was no firmware
|
||||
// 1) old firmware was unsigned
|
||||
|
@ -26,8 +26,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
extern void *emulator_flash_base;
|
||||
|
||||
void emulatorPoll(void);
|
||||
void emulatorRandom(void *buffer, size_t size);
|
||||
|
||||
|
@ -17,8 +17,6 @@
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/stm32/flash.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "memory.h"
|
||||
@ -66,7 +64,7 @@ static void *sector_to_address(uint8_t sector) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *) (FLASH_ORIGIN + offset);
|
||||
return (void *) FLASH_PTR(FLASH_ORIGIN + offset);
|
||||
}
|
||||
|
||||
static ssize_t sector_to_size(uint8_t sector) {
|
||||
@ -106,9 +104,9 @@ void flash_erase_all_sectors(uint32_t program_size) {
|
||||
}
|
||||
|
||||
void flash_program_word(uint32_t address, uint32_t data) {
|
||||
MMIO32(address) = data;
|
||||
*(volatile uint32_t *)FLASH_PTR(address) = data;
|
||||
}
|
||||
|
||||
void flash_program_byte(uint32_t address, uint8_t data) {
|
||||
MMIO8(address) = data;
|
||||
*(volatile uint8_t *)FLASH_PTR(address) = data;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#define EMULATOR_FLASH_FILE "emulator.img"
|
||||
|
||||
void *emulator_flash_base = NULL;
|
||||
uint8_t *emulator_flash_base = NULL;
|
||||
|
||||
uint32_t __stack_chk_guard;
|
||||
|
||||
|
@ -1678,7 +1678,7 @@ void fsm_msgDebugLinkMemoryRead(DebugLinkMemoryRead *msg)
|
||||
if (msg->has_length && msg->length < length)
|
||||
length = msg->length;
|
||||
resp->has_memory = true;
|
||||
memcpy(resp->memory.bytes, (void*) msg->address, length);
|
||||
memcpy(resp->memory.bytes, FLASH_PTR(msg->address), length);
|
||||
resp->memory.size = length;
|
||||
msg_debug_write(MessageType_MessageType_DebugLinkMemory, resp);
|
||||
}
|
||||
@ -1696,7 +1696,9 @@ void fsm_msgDebugLinkMemoryWrite(DebugLinkMemoryWrite *msg)
|
||||
}
|
||||
flash_lock();
|
||||
} else {
|
||||
#if !EMULATOR
|
||||
memcpy((void *) msg->address, msg->memory.bytes, length);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "protect.h"
|
||||
#include "storage.h"
|
||||
#include "memory.h"
|
||||
#include "messages.h"
|
||||
#include "usb.h"
|
||||
#include "oled.h"
|
||||
@ -159,8 +160,8 @@ bool protectPin(bool use_cached)
|
||||
if (!storage_hasPin() || (use_cached && session_isPinCached())) {
|
||||
return true;
|
||||
}
|
||||
uint32_t *fails = storage_getPinFailsPtr();
|
||||
uint32_t wait = ~*fails;
|
||||
uint32_t fails = storage_getPinFailsOffset();
|
||||
uint32_t wait = ~*(const uint32_t*)FLASH_PTR(fails);
|
||||
protectCheckMaxTry(wait);
|
||||
usbTiny(1);
|
||||
while (wait > 0) {
|
||||
@ -205,7 +206,7 @@ bool protectPin(bool use_cached)
|
||||
storage_resetPinFails(fails);
|
||||
return true;
|
||||
} else {
|
||||
protectCheckMaxTry(~*fails);
|
||||
protectCheckMaxTry(~*(const uint32_t*)FLASH_PTR(fails));
|
||||
fsm_sendFailure(FailureType_Failure_PinInvalid, NULL);
|
||||
return false;
|
||||
}
|
||||
|
@ -48,27 +48,13 @@
|
||||
static const uint32_t storage_magic = 0x726f7473; // 'stor' as uint32_t
|
||||
|
||||
static uint32_t storage_uuid[12 / sizeof(uint32_t)];
|
||||
#ifndef __clang__
|
||||
// TODO: Fix this for Clang
|
||||
_Static_assert(((uint32_t)storage_uuid & 3) == 0, "uuid unaligned");
|
||||
_Static_assert((sizeof(storage_uuid) & 3) == 0, "uuid unaligned");
|
||||
#endif
|
||||
_Static_assert(sizeof(storage_uuid) == 12, "storage_uuid has wrong size");
|
||||
|
||||
Storage CONFIDENTIAL storageUpdate;
|
||||
#ifndef __clang__
|
||||
// TODO: Fix this for Clang
|
||||
_Static_assert(((uint32_t)&storageUpdate & 3) == 0, "storage unaligned");
|
||||
Storage CONFIDENTIAL storageUpdate __attribute__((aligned(4)));
|
||||
_Static_assert((sizeof(storageUpdate) & 3) == 0, "storage unaligned");
|
||||
#endif
|
||||
|
||||
#define STORAGE_ROM ((const Storage *)(FLASH_STORAGE_START + sizeof(storage_magic) + sizeof(storage_uuid)))
|
||||
|
||||
#if EMULATOR
|
||||
// TODO: Fix this for emulator
|
||||
#define storageRom STORAGE_ROM
|
||||
#else
|
||||
const Storage *storageRom = STORAGE_ROM;
|
||||
#endif
|
||||
#define FLASH_STORAGE (FLASH_STORAGE_START + sizeof(storage_magic) + sizeof(storage_uuid))
|
||||
#define storageRom ((const Storage *) FLASH_PTR(FLASH_STORAGE))
|
||||
|
||||
char storage_uuid_str[25];
|
||||
|
||||
@ -146,7 +132,7 @@ void storage_check_flash_errors(void)
|
||||
bool storage_from_flash(void)
|
||||
{
|
||||
storage_clear_update();
|
||||
if (memcmp((void *)FLASH_STORAGE_START, &storage_magic, sizeof(storage_magic)) != 0) {
|
||||
if (memcmp(FLASH_PTR(FLASH_STORAGE_START), &storage_magic, sizeof(storage_magic)) != 0) {
|
||||
// wrong magic
|
||||
return false;
|
||||
}
|
||||
@ -167,7 +153,7 @@ bool storage_from_flash(void)
|
||||
}
|
||||
|
||||
// load uuid
|
||||
memcpy(storage_uuid, (void *)(FLASH_STORAGE_START + sizeof(storage_magic)), sizeof(storage_uuid));
|
||||
memcpy(storage_uuid, FLASH_PTR(FLASH_STORAGE_START + sizeof(storage_magic)), sizeof(storage_uuid));
|
||||
data2hex(storage_uuid, sizeof(storage_uuid), storage_uuid_str);
|
||||
|
||||
#define OLD_STORAGE_SIZE(last_member) (((offsetof(Storage, last_member) + pb_membersize(Storage, last_member)) + 3) & ~3)
|
||||
@ -215,20 +201,17 @@ bool storage_from_flash(void)
|
||||
flash_erase_sector(FLASH_META_SECTOR_LAST, FLASH_CR_PROGRAM_X32);
|
||||
flash_program_word(FLASH_STORAGE_PINAREA, 0xffffffff << pinctr);
|
||||
// erase storageRom.has_pin_failed_attempts and storageRom.pin_failed_attempts
|
||||
#if !EMULATOR
|
||||
// TODO: Fix this for emulator
|
||||
_Static_assert(((uint32_t)&STORAGE_ROM->pin_failed_attempts & 3) == 0, "storage.pin_failed_attempts unaligned");
|
||||
#endif
|
||||
flash_program_byte((uint32_t)&storageRom->has_pin_failed_attempts, 0);
|
||||
flash_program_word((uint32_t)&storageRom->pin_failed_attempts, 0);
|
||||
_Static_assert(((FLASH_STORAGE + offsetof(Storage, pin_failed_attempts)) & 3) == 0, "storage.pin_failed_attempts unaligned");
|
||||
flash_program_byte(FLASH_STORAGE + offsetof(Storage, has_pin_failed_attempts), 0);
|
||||
flash_program_word(FLASH_STORAGE + offsetof(Storage, pin_failed_attempts), 0);
|
||||
flash_lock();
|
||||
storage_check_flash_errors();
|
||||
}
|
||||
uint32_t *u2fptr = (uint32_t*) FLASH_STORAGE_U2FAREA;
|
||||
const uint32_t *u2fptr = (const uint32_t*) FLASH_PTR(FLASH_STORAGE_U2FAREA);
|
||||
while (*u2fptr == 0) {
|
||||
u2fptr++;
|
||||
}
|
||||
storage_u2f_offset = 32 * (u2fptr - (uint32_t*) FLASH_STORAGE_U2FAREA);
|
||||
storage_u2f_offset = 32 * (u2fptr - (const uint32_t*) FLASH_PTR(FLASH_STORAGE_U2FAREA));
|
||||
uint32_t u2fword = *u2fptr;
|
||||
while ((u2fword & 1) == 0) {
|
||||
storage_u2f_offset++;
|
||||
@ -374,7 +357,7 @@ static void storage_commit_locked(bool update)
|
||||
|
||||
// backup meta
|
||||
uint32_t meta_backup[FLASH_META_DESC_LEN / sizeof(uint32_t)];
|
||||
memcpy(meta_backup, (uint8_t*)FLASH_META_START, FLASH_META_DESC_LEN);
|
||||
memcpy(meta_backup, FLASH_PTR(FLASH_META_START), FLASH_META_DESC_LEN);
|
||||
|
||||
// erase storage
|
||||
flash_erase_sector(FLASH_META_SECTOR_FIRST, FLASH_CR_PROGRAM_X32);
|
||||
@ -763,14 +746,14 @@ static void storage_area_recycle(uint32_t new_pinfails)
|
||||
// first clear storage marker. In case of a failure below it is better
|
||||
// to clear the storage than to allow restarting with zero PIN failures
|
||||
flash_program_word(FLASH_STORAGE_START, 0);
|
||||
if (*(uint32_t *)FLASH_STORAGE_START != 0) {
|
||||
if (*(const uint32_t *)FLASH_PTR(FLASH_STORAGE_START) != 0) {
|
||||
storage_show_error();
|
||||
}
|
||||
|
||||
// erase storage sector
|
||||
flash_erase_sector(FLASH_META_SECTOR_LAST, FLASH_CR_PROGRAM_X32);
|
||||
flash_program_word(FLASH_STORAGE_PINAREA, new_pinfails);
|
||||
if (*(uint32_t *)FLASH_STORAGE_PINAREA != new_pinfails) {
|
||||
if (*(const uint32_t *)FLASH_PTR(FLASH_STORAGE_PINAREA) != new_pinfails) {
|
||||
storage_show_error();
|
||||
}
|
||||
|
||||
@ -782,24 +765,24 @@ static void storage_area_recycle(uint32_t new_pinfails)
|
||||
}
|
||||
}
|
||||
|
||||
void storage_resetPinFails(uint32_t *pinfailsptr)
|
||||
void storage_resetPinFails(uint32_t flash_pinfails)
|
||||
{
|
||||
flash_clear_status_flags();
|
||||
flash_unlock();
|
||||
if ((uint32_t) (pinfailsptr + 1)
|
||||
if (flash_pinfails + sizeof(uint32_t)
|
||||
>= FLASH_STORAGE_PINAREA + FLASH_STORAGE_PINAREA_LEN) {
|
||||
// recycle extra storage sector
|
||||
storage_area_recycle(0xffffffff);
|
||||
} else {
|
||||
flash_program_word((uint32_t) pinfailsptr, 0);
|
||||
flash_program_word(flash_pinfails, 0);
|
||||
}
|
||||
flash_lock();
|
||||
storage_check_flash_errors();
|
||||
}
|
||||
|
||||
bool storage_increasePinFails(uint32_t *pinfailsptr)
|
||||
bool storage_increasePinFails(uint32_t flash_pinfails)
|
||||
{
|
||||
uint32_t newctr = *pinfailsptr << 1;
|
||||
uint32_t newctr = *(const uint32_t*)FLASH_PTR(flash_pinfails) << 1;
|
||||
// counter already at maximum, we do not increase it any more
|
||||
// return success so that a good pin is accepted
|
||||
if (!newctr)
|
||||
@ -807,19 +790,19 @@ bool storage_increasePinFails(uint32_t *pinfailsptr)
|
||||
|
||||
flash_clear_status_flags();
|
||||
flash_unlock();
|
||||
flash_program_word((uint32_t) pinfailsptr, newctr);
|
||||
flash_program_word(flash_pinfails, newctr);
|
||||
flash_lock();
|
||||
storage_check_flash_errors();
|
||||
|
||||
return *pinfailsptr == newctr;
|
||||
return *(const uint32_t*)FLASH_PTR(flash_pinfails) == newctr;
|
||||
}
|
||||
|
||||
uint32_t *storage_getPinFailsPtr(void)
|
||||
uint32_t storage_getPinFailsOffset(void)
|
||||
{
|
||||
uint32_t *pinfailsptr = (uint32_t *) FLASH_STORAGE_PINAREA;
|
||||
while (*pinfailsptr == 0)
|
||||
pinfailsptr++;
|
||||
return pinfailsptr;
|
||||
uint32_t flash_pinfails = FLASH_STORAGE_PINAREA;
|
||||
while (*(const uint32_t*)FLASH_PTR(flash_pinfails) == 0)
|
||||
flash_pinfails += sizeof(uint32_t);
|
||||
return flash_pinfails;
|
||||
}
|
||||
|
||||
bool storage_isInitialized(void)
|
||||
@ -866,15 +849,17 @@ uint32_t storage_getFlags(void)
|
||||
|
||||
uint32_t storage_nextU2FCounter(void)
|
||||
{
|
||||
uint32_t *ptr = ((uint32_t *) FLASH_STORAGE_U2FAREA) + (storage_u2f_offset / 32);
|
||||
uint32_t flash_u2f_offset = FLASH_STORAGE_U2FAREA +
|
||||
sizeof(uint32_t) * (storage_u2f_offset / 32);
|
||||
uint32_t newval = 0xfffffffe << (storage_u2f_offset & 31);
|
||||
|
||||
flash_clear_status_flags();
|
||||
flash_unlock();
|
||||
flash_program_word((uint32_t) ptr, newval);
|
||||
flash_program_word(flash_u2f_offset, newval);
|
||||
storage_u2f_offset++;
|
||||
if (storage_u2f_offset >= 8 * FLASH_STORAGE_U2FAREA_LEN) {
|
||||
storage_area_recycle(*storage_getPinFailsPtr());
|
||||
storage_area_recycle(*(const uint32_t*)
|
||||
FLASH_PTR(storage_getPinFailsOffset()));
|
||||
}
|
||||
flash_lock();
|
||||
storage_check_flash_errors();
|
||||
|
@ -122,9 +122,9 @@ void storage_setPin(const char *pin);
|
||||
void session_cachePin(void);
|
||||
bool session_isPinCached(void);
|
||||
void storage_clearPinArea(void);
|
||||
void storage_resetPinFails(uint32_t *pinfailptr);
|
||||
bool storage_increasePinFails(uint32_t *pinfailptr);
|
||||
uint32_t *storage_getPinFailsPtr(void);
|
||||
void storage_resetPinFails(uint32_t flash_pinfails);
|
||||
bool storage_increasePinFails(uint32_t flash_pinfails);
|
||||
uint32_t storage_getPinFailsOffset(void);
|
||||
|
||||
uint32_t storage_nextU2FCounter(void);
|
||||
void storage_setU2FCounter(uint32_t u2fcounter);
|
||||
|
2
memory.c
2
memory.c
@ -69,7 +69,7 @@ void memory_write_unlock(void)
|
||||
int memory_bootloader_hash(uint8_t *hash)
|
||||
|
||||
{
|
||||
sha256_Raw((const uint8_t *)FLASH_BOOT_START, FLASH_BOOT_LEN, hash);
|
||||
sha256_Raw(FLASH_PTR(FLASH_BOOT_START), FLASH_BOOT_LEN, hash);
|
||||
sha256_Raw(hash, 32, hash);
|
||||
return 32;
|
||||
}
|
||||
|
11
memory.h
11
memory.h
@ -20,6 +20,8 @@
|
||||
#ifndef __MEMORY_H__
|
||||
#define __MEMORY_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
|
||||
flash memory layout:
|
||||
@ -62,10 +64,13 @@
|
||||
|
||||
*/
|
||||
|
||||
#if EMULATOR
|
||||
#define FLASH_ORIGIN ((uint32_t) emulator_flash_base)
|
||||
#else
|
||||
#define FLASH_ORIGIN (0x08000000)
|
||||
|
||||
#if EMULATOR
|
||||
extern uint8_t *emulator_flash_base;
|
||||
#define FLASH_PTR(x) (emulator_flash_base + (x - FLASH_ORIGIN))
|
||||
#else
|
||||
#define FLASH_PTR(x) (const uint8_t*) (x)
|
||||
#endif
|
||||
|
||||
#define FLASH_TOTAL_SIZE (512 * 1024)
|
||||
|
Loading…
Reference in New Issue
Block a user