refactor(core): add abstraction over flash memory layout

[no changelog]
tychovrahe/u5/flash_qw
tychovrahe 11 months ago committed by TychoVrahe
parent fa71c8244c
commit 238e3fd7c1

@ -32,6 +32,7 @@ PATH_HAL = []
CCFLAGS_MOD += '-Wno-sequence-point '
CPPPATH_MOD += [
'vendor/trezor-crypto',
'vendor/trezor-storage',
]
CPPDEFINES_MOD += [
'AES_128',
@ -60,7 +61,9 @@ SOURCE_MOD += [
'embed/lib/colors.c',
'embed/lib/fonts/fonts.c',
'embed/lib/fonts/font_bitmap.c',
'embed/lib/image.c',
'embed/lib/mini_printf.c',
'vendor/trezor-storage/flash_common.c',
]
SOURCE_BOARDLOADER = [

@ -47,6 +47,7 @@ elif TREZOR_MODEL in ('T', 'DISC1'):
CCFLAGS_MOD += '-Wno-sequence-point '
CPPPATH_MOD += [
'vendor/trezor-crypto',
'vendor/trezor-storage',
]
CPPDEFINES_MOD += [
'AES_128',
@ -85,10 +86,12 @@ SOURCE_MOD += [
'embed/lib/display.c',
'embed/lib/fonts/fonts.c',
'embed/lib/fonts/font_bitmap.c',
'embed/lib/image.c',
'embed/extmod/modtrezorcrypto/rand.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
'vendor/trezor-storage/flash_common.c',
]
SOURCE_NANOPB = [

@ -45,6 +45,7 @@ elif TREZOR_MODEL in ('T', ):
CCFLAGS_MOD += '-Wno-sequence-point '
CPPPATH_MOD += [
'vendor/trezor-crypto',
'vendor/trezor-storage',
]
CPPDEFINES_MOD += [
'AES_128',
@ -65,6 +66,7 @@ SOURCE_MOD += [
'vendor/trezor-crypto/memzero.c',
'vendor/trezor-crypto/rand.c',
'vendor/trezor-crypto/sha2.c',
'vendor/trezor-storage/flash_common.c',
]
# modtrezorui
@ -76,6 +78,7 @@ SOURCE_MOD += [
'embed/lib/colors.c',
'embed/lib/fonts/fonts.c',
'embed/lib/fonts/font_bitmap.c',
'embed/lib/image.c',
'embed/lib/mini_printf.c',
'embed/extmod/modtrezorcrypto/rand.c',
'vendor/micropython/lib/uzlib/adler32.c',

@ -44,6 +44,7 @@ elif TREZOR_MODEL in ('T', ):
CCFLAGS_MOD += '-Wno-sequence-point '
CPPPATH_MOD += [
'vendor/trezor-crypto',
'vendor/trezor-storage',
]
CPPDEFINES_MOD += [
'AES_128',
@ -82,11 +83,13 @@ SOURCE_MOD += [
'embed/lib/display.c',
'embed/lib/fonts/fonts.c',
'embed/lib/fonts/font_bitmap.c',
'embed/lib/image.c',
'embed/lib/touch.c',
'embed/extmod/modtrezorcrypto/rand.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
'vendor/trezor-storage/flash_common.c',
]
SOURCE_NANOPB = [
@ -104,7 +107,6 @@ SOURCE_BOOTLOADER = [
]
SOURCE_TREZORHAL = [
'embed/trezorhal/unix/image.c',
'embed/trezorhal/unix/display-unix.c',
'embed/trezorhal/unix/flash.c',
'embed/trezorhal/unix/common.c',

@ -53,6 +53,7 @@ SOURCE_MOD += [
'embed/extmod/modtrezorconfig/modtrezorconfig.c',
'vendor/trezor-storage/norcow.c',
'vendor/trezor-storage/storage.c',
'vendor/trezor-storage/flash_common.c',
]
# modtrezorcrypto
@ -184,6 +185,7 @@ SOURCE_MOD += [
'embed/lib/display.c',
'embed/lib/fonts/fonts.c',
'embed/lib/fonts/font_bitmap.c',
'embed/lib/image.c',
'embed/extmod/modtrezorui/modtrezorui.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',

@ -45,6 +45,7 @@ elif TREZOR_MODEL in ('T', ):
# modtrezorcrypto
CPPPATH_MOD += [
'vendor/trezor-crypto',
'vendor/trezor-storage',
]
SOURCE_MOD += [
'vendor/trezor-crypto/chacha_drbg.c',
@ -64,11 +65,13 @@ SOURCE_MOD += [
'embed/lib/colors.c',
'embed/lib/fonts/fonts.c',
'embed/lib/fonts/font_bitmap.c',
'embed/lib/image.c',
'embed/lib/mini_printf.c',
'embed/lib/qr-code-generator/qrcodegen.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
'vendor/trezor-storage/flash_common.c',
]
SOURCE_PRODTEST = [

@ -43,6 +43,7 @@ elif TREZOR_MODEL in ('T', ):
# modtrezorcrypto
CPPPATH_MOD += [
'vendor/trezor-crypto',
'vendor/trezor-storage',
]
SOURCE_MOD += [
'vendor/trezor-crypto/memzero.c',
@ -57,10 +58,12 @@ SOURCE_MOD += [
'embed/lib/colors.c',
'embed/lib/fonts/fonts.c',
'embed/lib/fonts/font_bitmap.c',
'embed/lib/image.c',
'embed/lib/mini_printf.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
'vendor/trezor-storage/flash_common.c',
]
SOURCE_REFLASH = [

@ -58,6 +58,7 @@ SOURCE_MOD += [
'embed/extmod/modtrezorconfig/modtrezorconfig.c',
'vendor/trezor-storage/norcow.c',
'vendor/trezor-storage/storage.c',
'vendor/trezor-storage/flash_common.c',
]
# modtrezorcrypto
@ -190,11 +191,28 @@ SOURCE_MOD += [
'embed/lib/display.c',
'embed/lib/fonts/fonts.c',
'embed/lib/fonts/font_bitmap.c',
'embed/lib/image.c',
'embed/extmod/modtrezorui/modtrezorui.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
]
if TREZOR_MODEL in ('1', ):
SOURCE_MOD += [
'embed/models/model_T1B1_layout.c',
]
elif TREZOR_MODEL in ('T', ):
SOURCE_MOD += [
'embed/models/model_T2T1_layout.c',
]
elif TREZOR_MODEL in ('R', ):
SOURCE_MOD += [
'embed/models/model_T2B1_layout.c',
]
CPPDEFINES_MOD += [
'TREZOR_UI2',
]

@ -19,12 +19,14 @@
#include <string.h>
#include TREZOR_BOARD
#include "board_capabilities.h"
#include "common.h"
#include "compiler_traits.h"
#include "display.h"
#include "flash.h"
#include "image.h"
#include "model.h"
#include "rng.h"
#ifdef USE_SD_CARD
#include "sdcard.h"
@ -141,31 +143,7 @@ static secbool copy_sdcard(void) {
display_printf("\n\nerasing flash:\n\n");
// erase all flash (except boardloader)
static const uint8_t sectors[] = {
FLASH_SECTOR_STORAGE_1,
FLASH_SECTOR_STORAGE_2,
3,
FLASH_SECTOR_BOOTLOADER,
FLASH_SECTOR_FIRMWARE_START,
7,
8,
9,
10,
FLASH_SECTOR_FIRMWARE_END,
FLASH_SECTOR_UNUSED_START,
13,
14,
FLASH_SECTOR_UNUSED_END,
FLASH_SECTOR_FIRMWARE_EXTRA_START,
18,
19,
20,
21,
22,
FLASH_SECTOR_FIRMWARE_EXTRA_END,
};
if (sectrue !=
flash_erase_sectors(sectors, sizeof(sectors), progress_callback)) {
if (sectrue != flash_area_erase(&ALL_WIPE_AREA, progress_callback)) {
display_printf(" failed\n");
return secfalse;
}
@ -183,9 +161,9 @@ static secbool copy_sdcard(void) {
for (int i = 0; i < (IMAGE_HEADER_SIZE + codelen) / SDCARD_BLOCK_SIZE; i++) {
ensure(sdcard_read_blocks(sdcard_buf, i, 1), NULL);
for (int j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) {
ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER,
i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t),
sdcard_buf[j]),
ensure(flash_area_write_word(&BOOTLOADER_AREA,
i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t),
sdcard_buf[j]),
NULL);
}
}
@ -210,7 +188,7 @@ int main(void) {
if (sectrue != flash_configure_option_bytes()) {
// display is not initialized so don't call ensure
const secbool r =
flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL);
flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL);
(void)r;
return 2;
}
@ -232,9 +210,9 @@ int main(void) {
}
#endif
const image_header *hdr =
read_image_header((const uint8_t *)BOOTLOADER_START,
BOOTLOADER_IMAGE_MAGIC, BOOTLOADER_IMAGE_MAXSIZE);
const image_header *hdr = read_image_header(
(const uint8_t *)BOOTLOADER_START, BOOTLOADER_IMAGE_MAGIC,
flash_area_get_size(&BOOTLOADER_AREA));
ensure(hdr == (const image_header *)BOOTLOADER_START ? sectrue : secfalse,
"invalid bootloader header");
@ -243,10 +221,7 @@ int main(void) {
BOARDLOADER_KEYS),
"invalid bootloader signature");
const uint8_t sectors[] = {
FLASH_SECTOR_BOOTLOADER,
};
ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE, sectors, 1),
ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE, &BOOTLOADER_AREA),
"invalid bootloader hash");
ensure_compatible_settings();

@ -4,10 +4,14 @@
#include "bootui.h"
#include "common.h"
#include "display.h"
#include "emulator.h"
#include "flash.h"
#include "model.h"
#include "rust_ui.h"
#include "emulator.h"
#undef FIRMWARE_START
uint8_t *FIRMWARE_START = 0;
uint32_t stay_in_bootloader_flag;
@ -15,7 +19,7 @@ void set_core_clock(int) {}
int bootloader_main(void);
bool sector_is_empty(uint8_t sector) {
bool sector_is_empty(uint16_t sector) {
const uint8_t *storage = flash_get_address(sector, 0, 0);
size_t storage_size = flash_sector_size(sector);
for (size_t i = 0; i < storage_size; i++) {
@ -28,12 +32,11 @@ bool sector_is_empty(uint8_t sector) {
__attribute__((noreturn)) int main(int argc, char **argv) {
flash_init();
FIRMWARE_START =
(uint8_t *)flash_get_address(FLASH_SECTOR_FIRMWARE_START, 0, 0);
FIRMWARE_START = (uint8_t *)flash_area_get_address(&FIRMWARE_AREA, 0, 0);
// simulate non-empty storage so that we know whether it was erased or not
if (sector_is_empty(FLASH_SECTOR_STORAGE_1)) {
secbool ret = flash_write_word(FLASH_SECTOR_STORAGE_1, 16, 0x12345678);
if (sector_is_empty(STORAGE_AREAS[0].subarea[0].first_sector)) {
secbool ret = flash_area_write_word(&STORAGE_AREAS[0], 16, 0x12345678);
(void)ret;
}
@ -63,8 +66,9 @@ void mpu_config_bootloader(void) {}
void mpu_config_off(void) {}
__attribute__((noreturn)) void jump_to(void *addr) {
bool storage_is_erased = sector_is_empty(FLASH_SECTOR_STORAGE_1) &&
sector_is_empty(FLASH_SECTOR_STORAGE_2);
bool storage_is_erased =
sector_is_empty(STORAGE_AREAS[0].subarea[0].first_sector) &&
sector_is_empty(STORAGE_AREAS[1].subarea[0].first_sector);
if (storage_is_erased) {
printf("STORAGE WAS ERASED\n");

@ -26,14 +26,7 @@
#include "image.h"
#include "random_delays.h"
#include "secbool.h"
#ifdef TREZOR_EMULATOR
#include "emulator.h"
#else
#include "compiler_traits.h"
#include "mini_printf.h"
#include "mpu.h"
#include "platform.h"
#endif
#ifdef USE_DMA2D
#include "dma2d.h"
#endif
@ -61,6 +54,15 @@
#include "rust_ui.h"
#include "unit_variant.h"
#ifdef TREZOR_EMULATOR
#include "emulator.h"
#else
#include "compiler_traits.h"
#include "mini_printf.h"
#include "mpu.h"
#include "platform.h"
#endif
const uint8_t BOOTLOADER_KEY_M = 2;
const uint8_t BOOTLOADER_KEY_N = 3;
static const uint8_t * const BOOTLOADER_KEYS[] = {
@ -305,9 +307,10 @@ int bootloader_main(void) {
}
if (sectrue == firmware_present) {
hdr = read_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
if (hdr != (const image_header *)(FIRMWARE_START + vhdr.hdrlen)) {
hdr = read_image_header(
(const uint8_t *)(size_t)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
if (hdr != (const image_header *)(size_t)(FIRMWARE_START + vhdr.hdrlen)) {
firmware_present = secfalse;
}
}
@ -319,9 +322,8 @@ int bootloader_main(void) {
check_image_header_sig(hdr, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub);
}
if (sectrue == firmware_present) {
firmware_present =
check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT);
firmware_present = check_image_contents(
hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, &FIRMWARE_AREA);
}
#if defined TREZOR_MODEL_T
@ -408,7 +410,7 @@ int bootloader_main(void) {
ui_screen_welcome();
// erase storage
ensure(flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL),
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL),
NULL);
// and start the usb loop
@ -502,11 +504,13 @@ int bootloader_main(void) {
ensure(check_vendor_header_lock(&vhdr), "Unauthorized vendor keys");
hdr = read_image_header((const uint8_t *)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
hdr =
read_image_header((const uint8_t *)(size_t)(FIRMWARE_START + vhdr.hdrlen),
FIRMWARE_IMAGE_MAGIC, FIRMWARE_IMAGE_MAXSIZE);
ensure(hdr == (const image_header *)(FIRMWARE_START + vhdr.hdrlen) ? sectrue
: secfalse,
ensure(hdr == (const image_header *)(size_t)(FIRMWARE_START + vhdr.hdrlen)
? sectrue
: secfalse,
"Firmware is corrupted");
ensure(check_image_model(hdr), "Wrong firmware model");
@ -515,7 +519,7 @@ int bootloader_main(void) {
"Firmware is corrupted");
ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT),
&FIRMWARE_AREA),
"Firmware is corrupted");
// if all VTRUST flags are unset = ultimate trust => skip the procedure

@ -352,7 +352,7 @@ void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size,
firmware_remaining = msg_recv.has_length ? msg_recv.length : 0;
if ((firmware_remaining > 0) &&
((firmware_remaining % sizeof(uint32_t)) == 0) &&
(firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) {
(firmware_remaining <= FIRMWARE_IMAGE_MAXSIZE)) {
// request new firmware
chunk_requested = (firmware_remaining > IMAGE_INIT_CHUNK_SIZE)
? IMAGE_INIT_CHUNK_SIZE
@ -591,12 +591,10 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
// if firmware is not upgrade, erase storage
if (sectrue != should_keep_seed) {
ensure(
flash_erase_sectors(STORAGE_SECTORS, STORAGE_SECTORS_COUNT, NULL),
NULL);
ensure(flash_area_erase_bulk(STORAGE_AREAS, STORAGE_AREAS_COUNT, NULL),
NULL);
}
ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT,
ui_screen_install_progress_erase),
ensure(flash_area_erase(&FIRMWARE_AREA, ui_screen_install_progress_erase),
NULL);
headers_offset = IMAGE_HEADER_SIZE + vhdr.hdrlen;
@ -621,7 +619,8 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
}
// should not happen, but double-check
if (firmware_block >= FIRMWARE_SECTORS_COUNT) {
if (flash_area_get_address(&FIRMWARE_AREA, firmware_block * IMAGE_CHUNK_SIZE,
0) == NULL) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Firmware too big");
@ -651,9 +650,12 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
ensure(flash_unlock_write(), NULL);
const uint32_t *const src = (const uint32_t *const)CHUNK_BUFFER_PTR;
for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) {
ensure(flash_write_word(FIRMWARE_SECTORS[firmware_block],
i * sizeof(uint32_t), src[i]),
for (int i = 0; i < chunk_size / (sizeof(uint32_t) * 4); i++) {
ensure(flash_area_write_quadword(
&FIRMWARE_AREA,
firmware_block * IMAGE_CHUNK_SIZE + i * 4 * sizeof(uint32_t),
&src[4 * i]),
NULL);
}
@ -680,29 +682,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
}
secbool bootloader_WipeDevice(void) {
static const uint8_t sectors[] = {
FLASH_SECTOR_STORAGE_1,
FLASH_SECTOR_STORAGE_2,
// 3, // skip because of MPU protection
FLASH_SECTOR_FIRMWARE_START,
7,
8,
9,
10,
FLASH_SECTOR_FIRMWARE_END,
FLASH_SECTOR_UNUSED_START,
13,
14,
// FLASH_SECTOR_UNUSED_END, // skip because of MPU protection
FLASH_SECTOR_FIRMWARE_EXTRA_START,
18,
19,
20,
21,
22,
FLASH_SECTOR_FIRMWARE_EXTRA_END,
};
return flash_erase_sectors(sectors, sizeof(sectors), ui_screen_wipe_progress);
return flash_area_erase(&WIPE_AREA, ui_screen_wipe_progress);
}
int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {

@ -37,6 +37,7 @@
#include "bootui.h"
#include "messages.h"
#include "model.h"
// #include "mpu.h"
const uint8_t BOOTLOADER_KEY_M = 2;
@ -262,9 +263,8 @@ int main(void) {
check_image_header_sig(hdr, vhdr.vsig_m, vhdr.vsig_n, vhdr.vpub);
}
if (sectrue == firmware_present) {
firmware_present =
check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT);
firmware_present = check_image_contents(
hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen, &FIRMWARE_AREA);
}
// always start bootloader even if firmware is already present
@ -299,7 +299,7 @@ int main(void) {
"invalid firmware signature");
ensure(check_image_contents(hdr, IMAGE_HEADER_SIZE + vhdr.hdrlen,
FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT),
&FIRMWARE_AREA),
"invalid firmware hash");
// do not check any trust flags on header, proceed

@ -27,6 +27,7 @@
#include "common.h"
#include "flash.h"
#include "image.h"
#include "model.h"
#include "secbool.h"
#include "usb.h"
#include "version.h"
@ -339,7 +340,7 @@ void process_msg_FirmwareErase(uint8_t iface_num, uint32_t msg_size,
firmware_remaining = msg_recv.has_length ? msg_recv.length : 0;
if ((firmware_remaining > 0) &&
((firmware_remaining % sizeof(uint32_t)) == 0) &&
(firmware_remaining <= (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE))) {
(firmware_remaining <= (FIRMWARE_IMAGE_MAXSIZE))) {
// request new firmware
chunk_requested = (firmware_remaining > IMAGE_INIT_CHUNK_SIZE)
? IMAGE_INIT_CHUNK_SIZE
@ -578,14 +579,14 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
ui_screen_install_start();
ui_fadein();
ensure(flash_erase_sectors(FIRMWARE_SECTORS, FIRMWARE_SECTORS_COUNT,
ui_screen_install_progress_erase),
ensure(flash_area_erase(&FIRMWARE_AREA, ui_screen_install_progress_erase),
NULL);
}
}
// should not happen, but double-check
if (firmware_block >= FIRMWARE_SECTORS_COUNT) {
if (flash_area_get_address(&FIRMWARE_AREA, firmware_block * IMAGE_CHUNK_SIZE,
0) == NULL) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Firmware too big");
@ -615,9 +616,12 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
ensure(flash_unlock_write(), NULL);
const uint32_t *const src = (const uint32_t *const)chunk_buffer;
for (int i = 0; i < chunk_size / sizeof(uint32_t); i++) {
ensure(flash_write_word(FIRMWARE_SECTORS[firmware_block],
i * sizeof(uint32_t), src[i]),
for (int i = 0; i < chunk_size / (sizeof(uint32_t) * 4); i++) {
ensure(flash_area_write_quadword(
&FIRMWARE_AREA,
firmware_block * IMAGE_CHUNK_SIZE + i * 4 * sizeof(uint32_t),
&src[4 * i]),
NULL);
}
@ -644,30 +648,14 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
}
int process_msg_WipeDevice(uint8_t iface_num, uint32_t msg_size, uint8_t *buf) {
static const uint8_t sectors[] = {
FLASH_SECTOR_STORAGE_1,
FLASH_SECTOR_STORAGE_2,
// 3, // skip because of MPU protection
FLASH_SECTOR_FIRMWARE_START,
7,
8,
9,
10,
FLASH_SECTOR_FIRMWARE_END,
FLASH_SECTOR_UNUSED_START,
13,
14,
// FLASH_SECTOR_UNUSED_END, // skip because of MPU protection
FLASH_SECTOR_FIRMWARE_EXTRA_START,
18,
19,
20,
21,
22,
FLASH_SECTOR_FIRMWARE_EXTRA_END,
};
if (sectrue !=
flash_erase_sectors(sectors, sizeof(sectors), ui_screen_wipe_progress)) {
flash_area_t wipe_area[STORAGE_AREAS_COUNT + 1];
for (int i = 0; i < STORAGE_AREAS_COUNT; i++) {
memcpy(&wipe_area[i], &STORAGE_AREAS[i], sizeof(flash_area_t));
}
memcpy(&wipe_area[STORAGE_AREAS_COUNT], &FIRMWARE_AREA, sizeof(flash_area_t));
if (sectrue != flash_area_erase_bulk(wipe_area, STORAGE_AREAS_COUNT + 1,
ui_screen_wipe_progress)) {
MSG_SEND_INIT(Failure);
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
MSG_SEND_ASSIGN_STRING(message, "Could not erase flash");

@ -21,6 +21,7 @@
#define __NORCOW_CONFIG_H__
#include "flash.h"
#include "model.h"
#define NORCOW_HEADER_LEN 0
#define NORCOW_SECTOR_COUNT 2
@ -34,9 +35,6 @@
#error Unknown Trezor model
#endif
#define NORCOW_SECTORS \
{ FLASH_SECTOR_STORAGE_1, FLASH_SECTOR_STORAGE_2 }
/*
* Current storage version.
*/

@ -167,16 +167,18 @@ STATIC mp_obj_t mod_trezorutils_firmware_hash(size_t n_args,
ui_wait_callback = args[1];
}
ui_progress(ui_wait_callback, 0, FIRMWARE_SECTORS_COUNT);
for (int i = 0; i < FIRMWARE_SECTORS_COUNT; i++) {
uint8_t sector = FIRMWARE_SECTORS[i];
uint16_t firmware_sectors = flash_total_sectors(&FIRMWARE_AREA);
ui_progress(ui_wait_callback, 0, firmware_sectors);
for (int i = 0; i < firmware_sectors; i++) {
uint8_t sector = flash_get_sector_num(&FIRMWARE_AREA, i);
uint32_t size = flash_sector_size(sector);
const void *data = flash_get_address(sector, 0, size);
if (data == NULL) {
mp_raise_msg(&mp_type_RuntimeError, "Failed to read firmware.");
}
blake2s_Update(&ctx, data, size);
ui_progress(ui_wait_callback, i + 1, FIRMWARE_SECTORS_COUNT);
ui_progress(ui_wait_callback, i + 1, firmware_sectors);
}
vstr_t vstr = {0};
@ -200,8 +202,9 @@ STATIC mp_obj_t mod_trezorutils_firmware_vendor(void) {
return mp_obj_new_str_copy(&mp_type_str, (const uint8_t *)"EMULATOR", 8);
#else
vendor_header vhdr = {0};
uint32_t size = flash_sector_size(FLASH_SECTOR_FIRMWARE_START);
const void *data = flash_get_address(FLASH_SECTOR_FIRMWARE_START, 0, size);
uint32_t size = flash_sector_size(FIRMWARE_AREA.subarea[0].first_sector);
const void *data =
flash_get_address(FIRMWARE_AREA.subarea[0].first_sector, 0, size);
if (data == NULL || sectrue != read_vendor_header(data, &vhdr)) {
mp_raise_msg(&mp_type_RuntimeError, "Failed to read vendor header.");
}

@ -113,7 +113,7 @@ void check_and_replace_bootloader(void) {
// compute current bootloader hash
uint8_t hash[BLAKE2S_DIGEST_LENGTH];
const uint32_t bl_len = 128 * 1024;
const void *bl_data = flash_get_address(FLASH_SECTOR_BOOTLOADER, 0, bl_len);
const void *bl_data = flash_area_get_address(&BOOTLOADER_AREA, 0, bl_len);
blake2s(bl_data, bl_len, hash, BLAKE2S_DIGEST_LENGTH);
// don't whitelist the valid bootloaders for now
@ -172,16 +172,16 @@ void check_and_replace_bootloader(void) {
ensure(secfalse, "Incompatible embedded bootloader");
}
ensure(flash_erase(FLASH_SECTOR_BOOTLOADER), NULL);
ensure(flash_area_erase(&BOOTLOADER_AREA, NULL), NULL);
ensure(flash_unlock_write(), NULL);
for (int i = 0; i < len / sizeof(uint32_t); i++) {
ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t),
data[i]),
NULL);
ensure(
flash_area_write_word(&BOOTLOADER_AREA, i * sizeof(uint32_t), data[i]),
NULL);
}
for (int i = len / sizeof(uint32_t); i < 128 * 1024 / sizeof(uint32_t); i++) {
ensure(flash_write_word(FLASH_SECTOR_BOOTLOADER, i * sizeof(uint32_t),
0x00000000),
ensure(flash_area_write_word(&BOOTLOADER_AREA, i * sizeof(uint32_t),
0x00000000),
NULL);
}
ensure(flash_lock_write(), NULL);

@ -43,8 +43,10 @@
#include "display.h"
#include "flash.h"
#include "image.h"
#include "model.h"
#include "mpu.h"
#include "random_delays.h"
#ifdef USE_RGB_LED
#include "rgb_led.h"
#endif

@ -93,12 +93,14 @@ secbool check_image_model(const image_header *const hdr) {
}
#endif
#ifndef TREZOR_EMULATOR
if (hdr->hw_model != HW_MODEL) {
return secfalse;
}
if (hdr->hw_revision != HW_REVISION) {
return secfalse;
}
#endif
return sectrue;
}
@ -215,14 +217,15 @@ secbool check_single_hash(const uint8_t *const hash, const uint8_t *const data,
blake2s(data, len, h, BLAKE2S_DIGEST_LENGTH);
return sectrue * (0 == memcmp(h, hash, BLAKE2S_DIGEST_LENGTH));
}
//
secbool check_image_contents(const image_header *const hdr, uint32_t firstskip,
const uint8_t *sectors, int blocks) {
if (0 == sectors || blocks < 1) {
const flash_area_t *area) {
if (0 == area) {
return secfalse;
}
const void *data =
flash_get_address(sectors[0], firstskip, IMAGE_CHUNK_SIZE - firstskip);
flash_area_get_address(area, firstskip, IMAGE_CHUNK_SIZE - firstskip);
if (!data) {
return secfalse;
}
@ -232,22 +235,24 @@ secbool check_image_contents(const image_header *const hdr, uint32_t firstskip,
MIN(remaining, IMAGE_CHUNK_SIZE - firstskip))) {
return secfalse;
}
int block = 1;
remaining -= IMAGE_CHUNK_SIZE - firstskip;
int chunk = 1;
while (remaining > 0) {
if (block >= blocks) {
return secfalse;
}
data = flash_get_address(sectors[block], 0, IMAGE_CHUNK_SIZE);
data = flash_area_get_address(area, chunk * IMAGE_CHUNK_SIZE,
IMAGE_CHUNK_SIZE);
if (!data) {
return secfalse;
}
if (sectrue != check_single_hash(hdr->hashes + block * 32, data,
if (sectrue != check_single_hash(hdr->hashes + chunk * 32, data,
MIN(remaining, IMAGE_CHUNK_SIZE))) {
return secfalse;
}
block++;
chunk++;
remaining -= IMAGE_CHUNK_SIZE;
}
return sectrue;
}

@ -21,22 +21,17 @@
#define __TREZORHAL_IMAGE_H__
#include <stdint.h>
#include "flash.h"
#include "secbool.h"
#define BOARDLOADER_START 0x08000000
#define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000
#define IMAGE_HEADER_SIZE 0x400 // size of the bootloader or firmware header
#define IMAGE_SIG_SIZE 65
#define IMAGE_CHUNK_SIZE (128 * 1024)
#define IMAGE_INIT_CHUNK_SIZE (16 * 1024)
#define BOOTLOADER_IMAGE_MAGIC 0x425A5254 // TRZB
#define BOOTLOADER_IMAGE_MAXSIZE (BOOTLOADER_SECTORS_COUNT * IMAGE_CHUNK_SIZE)
#define FIRMWARE_IMAGE_MAGIC 0x465A5254 // TRZF
#define FIRMWARE_IMAGE_MAXSIZE (FIRMWARE_SECTORS_COUNT * IMAGE_CHUNK_SIZE)
typedef struct {
uint32_t magic;
@ -104,8 +99,8 @@ secbool __wur check_single_hash(const uint8_t *const hash,
const uint8_t *const data, int len);
secbool __wur check_image_contents(const image_header *const hdr,
uint32_t firstskip, const uint8_t *sectors,
int blocks);
uint32_t firstskip,
const flash_area_t *area);
void get_image_fingerprint(const image_header *const hdr, uint8_t *const out);

@ -1,5 +1,6 @@
#include "unit_variant.h"
#include "flash.h"
#include "model.h"
static uint8_t unit_variant_color = 0;
static bool unit_variant_btconly = false;

@ -0,0 +1,22 @@
#ifndef LAYOUT_COMMON_H
#define LAYOUT_COMMON_H
#include "flash.h"
// OTP blocks allocation
#define FLASH_OTP_BLOCK_BATCH 0
#define FLASH_OTP_BLOCK_BOOTLOADER_VERSION 1
#define FLASH_OTP_BLOCK_VENDOR_HEADER_LOCK 2
#define FLASH_OTP_BLOCK_RANDOMNESS 3
#define FLASH_OTP_BLOCK_DEVICE_VARIANT 4
#define STORAGE_AREAS_COUNT (2)
extern const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT];
extern const flash_area_t BOARDLOADER_AREA;
extern const flash_area_t BOOTLOADER_AREA;
extern const flash_area_t FIRMWARE_AREA;
extern const flash_area_t WIPE_AREA;
extern const flash_area_t ALL_WIPE_AREA;
#endif

@ -1,6 +1,8 @@
#ifndef MODELS_MODEL_H_
#define MODELS_MODEL_H_
#include "layout_common.h"
#if defined TREZOR_MODEL_1
#include "model_T1B1.h"
#elif defined TREZOR_MODEL_T

@ -18,4 +18,11 @@
(const uint8_t *)"\x63\x55\x69\x1c\x17\x8a\x8f\xf9\x10\x07\xa7\x47\x8a\xfb\x95\x5e\xf7\x35\x2c\x63\xe7\xb2\x57\x03\x98\x4c\xf7\x8b\x26\xe2\x1a\x56", \
(const uint8_t *)"\xee\x93\xa4\xf6\x6f\x8d\x16\xb8\x19\xbb\x9b\xeb\x9f\xfc\xcd\xfc\xdc\x14\x12\xe8\x7f\xee\x6a\x32\x4c\x2a\x99\xa1\xe0\xe6\x71\x48",
#define BOARDLOADER_START 0x08000000
#define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000
#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB
#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB
#endif

@ -7,4 +7,10 @@
#define MODEL_NAME_QSTR MP_QSTR_1
#define MODEL_INTERNAL_NAME_QSTR MP_QSTR_T1B1
#define BOOTLOADER_START 0x08000000
#define FIRMWARE_START 0x08010000
#define BOOTLOADER_IMAGE_MAXSIZE (32 * 1024 * 1) // 32 KB
#define FIRMWARE_IMAGE_MAXSIZE (64 * 1024 * 15) // 960 KB
#endif

@ -0,0 +1,39 @@
#include "flash.h"
#include "model.h"
const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = {
{
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 2,
.num_sectors = 1,
},
},
{
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 3,
.num_sectors = 1,
},
},
};
const flash_area_t BOOTLOADER_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 0,
.num_sectors = 2,
},
};
const flash_area_t FIRMWARE_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 4,
.num_sectors = 8,
},
};

@ -18,4 +18,11 @@
(const uint8_t *)"\xd2\xde\xf6\x91\xc1\xe9\xd8\x09\xd8\x19\x0c\xf7\xaf\x93\x5c\x10\x68\x8f\x68\x98\x34\x79\xb4\xee\x9a\xba\xc1\x91\x04\x87\x8e\xc1", \
(const uint8_t *)"\x07\xc8\x51\x34\x94\x6b\xf8\x9f\xa1\x9b\xdc\x2c\x5e\x5f\xf9\xce\x01\x29\x65\x08\xee\x08\x63\xd0\xff\x6d\x63\x33\x1d\x1a\x25\x16",
#define BOARDLOADER_START 0x08000000
#define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000
#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB
#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB
#endif

@ -18,4 +18,11 @@
(const uint8_t *)"\x80\xd0\x36\xb0\x87\x39\xb8\x46\xf4\xcb\x77\x59\x30\x78\xde\xb2\x5d\xc9\x48\x7a\xed\xcf\x52\xe3\x0b\x4f\xb7\xcd\x70\x24\x17\x8a", \
(const uint8_t *)"\xb8\x30\x7a\x71\xf5\x52\xc6\x0a\x4c\xbb\x31\x7f\xf4\x8b\x82\xcd\xbf\x6b\x6b\xb5\xf0\x4c\x92\x0f\xec\x7b\xad\xf0\x17\x88\x37\x51",
#define BOARDLOADER_START 0x08000000
#define BOOTLOADER_START 0x08020000
#define FIRMWARE_START 0x08040000
#define BOOTLOADER_IMAGE_MAXSIZE (128 * 1024 * 1) // 128 KB
#define FIRMWARE_IMAGE_MAXSIZE (128 * 1024 * 13) // 1664 KB
#endif

@ -0,0 +1,82 @@
#include "flash.h"
#include "model.h"
const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = {
{
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 4,
.num_sectors = 1,
},
},
{
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 16,
.num_sectors = 1,
},
},
};
const flash_area_t BOARDLOADER_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 0,
.num_sectors = 3,
},
};
const flash_area_t BOOTLOADER_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 5,
.num_sectors = 1,
},
};
const flash_area_t FIRMWARE_AREA = {
.num_subareas = 2,
.subarea[0] =
{
.first_sector = 6,
.num_sectors = 6,
},
.subarea[1] =
{
.first_sector = 17,
.num_sectors = 7,
},
};
const flash_area_t WIPE_AREA = {
.num_subareas = 3,
.subarea[0] =
{
.first_sector = 4,
.num_sectors = 1,
},
.subarea[1] =
{
.first_sector = 6,
.num_sectors =
9, // sector 15 skipped due to bootloader MPU settings
},
.subarea[2] =
{
.first_sector = 16,
.num_sectors = 8,
},
};
const flash_area_t ALL_WIPE_AREA = {
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 3,
.num_sectors = 21,
},
};

@ -29,6 +29,7 @@
#include "flash.h"
#include "i2c.h"
#include "mini_printf.h"
#include "model.h"
#include "random_delays.h"
#include "rng.h"
#include "sbu.h"
@ -426,9 +427,9 @@ static void test_wipe(void) {
// erase start of the firmware (metadata) -> invalidate FW
ensure(flash_unlock_write(), NULL);
for (int i = 0; i < 1024 / sizeof(uint32_t); i++) {
ensure(flash_write_word(FLASH_SECTOR_FIRMWARE_START, i * sizeof(uint32_t),
0x00000000),
NULL);
ensure(
flash_area_write_word(&FIRMWARE_AREA, i * sizeof(uint32_t), 0x00000000),
NULL);
}
ensure(flash_lock_write(), NULL);
display_clear();

@ -27,6 +27,7 @@
#include "display.h"
#include "flash.h"
#include "image.h"
#include "model.h"
#include "rng.h"
#include "sbu.h"
#include "sdcard.h"
@ -35,7 +36,7 @@
static void progress_callback(int pos, int len) { display_printf("."); }
static void flash_from_sdcard(uint8_t sector, uint32_t source,
static void flash_from_sdcard(const flash_area_t* area, uint32_t source,
uint32_t length) {
static uint32_t buf[SDCARD_BLOCK_SIZE / sizeof(uint32_t)];
@ -50,9 +51,10 @@ static void flash_from_sdcard(uint8_t sector, uint32_t source,
ensure(sdcard_read_blocks(buf, i + source / SDCARD_BLOCK_SIZE, 1),
"sdcard_read_blocks");
for (uint32_t j = 0; j < SDCARD_BLOCK_SIZE / sizeof(uint32_t); j++) {
ensure(flash_write_word(
sector, i * SDCARD_BLOCK_SIZE + j * sizeof(uint32_t), buf[j]),
for (uint32_t j = 0; j < SDCARD_BLOCK_SIZE / (sizeof(uint32_t) * 4); j++) {
ensure(flash_area_write_quadword(
area, i * SDCARD_BLOCK_SIZE + j * 4 * sizeof(uint32_t),
&buf[j * 4]),
NULL);
}
}
@ -70,14 +72,10 @@ int main(void) {
display_printf("updating boardloader + bootloader\n");
static const uint8_t sectors[] = {
FLASH_SECTOR_BOARDLOADER_START,
1,
FLASH_SECTOR_BOARDLOADER_END,
FLASH_SECTOR_BOOTLOADER,
};
display_printf("erasing sectors");
ensure(flash_erase_sectors(sectors, sizeof(sectors), progress_callback),
ensure(flash_area_erase(&BOARDLOADER_AREA, progress_callback),
"flash_erase_sectors");
ensure(flash_area_erase(&BOOTLOADER_AREA, progress_callback),
"flash_erase_sectors");
display_printf("\n");
display_printf("erased\n");
@ -90,12 +88,8 @@ int main(void) {
#define BOARDLOADER_TOTAL_SIZE (3 * BOARDLOADER_CHUNK_SIZE)
#define BOOTLOADER_TOTAL_SIZE (128 * 1024)
flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_START, 0 * BOARDLOADER_CHUNK_SIZE,
BOARDLOADER_CHUNK_SIZE);
flash_from_sdcard(1, 1 * BOARDLOADER_CHUNK_SIZE, BOARDLOADER_CHUNK_SIZE);
flash_from_sdcard(FLASH_SECTOR_BOARDLOADER_END, 2 * BOARDLOADER_CHUNK_SIZE,
BOARDLOADER_CHUNK_SIZE);
flash_from_sdcard(FLASH_SECTOR_BOOTLOADER, BOARDLOADER_TOTAL_SIZE,
flash_from_sdcard(&BOARDLOADER_AREA, 0, BOARDLOADER_TOTAL_SIZE);
flash_from_sdcard(&BOOTLOADER_AREA, BOARDLOADER_TOTAL_SIZE,
BOOTLOADER_TOTAL_SIZE);
display_printf("done\n");

@ -22,100 +22,40 @@
#include <stdint.h>
#include <stdlib.h>
#include "platform.h"
#include "secbool.h"
// see docs/memory.md for more information
#if defined STM32F427xx || defined STM32F429xx
#define FLASH_SECTOR_COUNT 24
#elif defined STM32F405xx
#define FLASH_SECTOR_COUNT 12
#else
#error Unsupported MCU
#endif
#define FLASH_SECTOR_BOARDLOADER_START 0
// 1
#define FLASH_SECTOR_BOARDLOADER_END 2
// 3
#if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R || \
defined TREZOR_MODEL_DISC1
#define FLASH_SECTOR_STORAGE_1 4
#define FLASH_SECTOR_STORAGE_2 16
#elif defined TREZOR_MODEL_1
#define FLASH_SECTOR_STORAGE_1 2
#define FLASH_SECTOR_STORAGE_2 3
#else
#error Unknown Trezor model
#endif
#define FLASH_SECTOR_BOOTLOADER 5
#define FLASH_SECTOR_FIRMWARE_START 6
// 7
// 8
// 9
// 10
#define FLASH_SECTOR_FIRMWARE_END 11
#define FLASH_SECTOR_UNUSED_START 12
// 13
// 14
#define FLASH_SECTOR_UNUSED_END 15
#define FLASH_SECTOR_FIRMWARE_EXTRA_START 17
// 18
// 19
// 20
// 21
// 22
#define FLASH_SECTOR_FIRMWARE_EXTRA_END 23
#define BOOTLOADER_SECTORS_COUNT (1)
#define STORAGE_SECTORS_COUNT (2)
#define FIRMWARE_SECTORS_COUNT (6 + 7)
extern const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT];
extern const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT];
#define FLASH_OTP_NUM_BLOCKS 16
#define FLASH_OTP_BLOCK_SIZE 32
// note: FLASH_SR_RDERR is STM32F42xxx and STM32F43xxx specific (STM32F427)
// (reference RM0090 section 3.7.5)
#if !defined STM32F427xx && !defined STM32F429xx
#define FLASH_SR_RDERR 0
#endif
/**
* Flash driver interface is designed to abstract away differences between
* various MCUs used in Trezor devices.
*
* Generally, flash memory is divided into sectors. On different MCUs, sectors
* may have different sizes, and therefore, different number of sectors are used
* for a given purpose. For example, on STM32F4, the sectors are relatively
* large so we use single sector for Storage. On STM32U5, the sectors are
* smaller, so we use multiple sectors for the Storage. Storage implementation
* should not care about this, and should use flash_area_t interface to access
* the flash memory.
*
* flash_area_t represents a location in flash memory. It may be contiguous, or
* it may be composed of multiple non-contiguous subareas.
*
* flash_subarea_t represents a contiguous area in flash memory, specified by
* first_sector and num_sectors.
*/
#define FLASH_STATUS_ALL_FLAGS \
(FLASH_SR_RDERR | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | \
FLASH_SR_WRPERR | FLASH_SR_SOP | FLASH_SR_EOP)
#include "flash_common.h"
void flash_init(void);
uint32_t flash_wait_and_clear_status_flags(void);
secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data);
secbool __wur flash_unlock_write(void);
secbool __wur flash_lock_write(void);
secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data);
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size);
uint32_t flash_sector_size(uint8_t sector);
secbool __wur flash_erase_sectors(const uint8_t *sectors, int len,
void (*progress)(int pos, int len));
static inline secbool flash_erase(uint8_t sector) {
return flash_erase_sectors(&sector, 1, NULL);
}
secbool __wur flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data);
secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data);
#define FLASH_OTP_NUM_BLOCKS 16
#define FLASH_OTP_BLOCK_SIZE 32
// OTP blocks allocation
#define FLASH_OTP_BLOCK_BATCH 0
#define FLASH_OTP_BLOCK_BOOTLOADER_VERSION 1
#define FLASH_OTP_BLOCK_VENDOR_HEADER_LOCK 2
#define FLASH_OTP_BLOCK_RANDOMNESS 3
#define FLASH_OTP_BLOCK_DEVICE_VARIANT 4
uint32_t flash_wait_and_clear_status_flags(void);
secbool __wur flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data,
uint8_t datalen);

@ -23,6 +23,8 @@
#include "common.h"
#include "display.h"
#include "model.h"
#ifdef FANCY_FATAL_ERROR
#include "rust_ui.h"
#endif

@ -24,6 +24,24 @@
#include "common.h"
#include "flash.h"
#if defined STM32F427xx || defined STM32F429xx
#define FLASH_SECTOR_COUNT 24
#elif defined STM32F405x
#define FLASH_SECTOR_COUNT 12
#else
#error Unknown MCU
#endif
// note: FLASH_SR_RDERR is STM32F42xxx and STM32F43xxx specific (STM32F427)
// (reference RM0090 section 3.7.5)
#if !defined STM32F427xx && !defined STM32F429xx
#define FLASH_SR_RDERR 0
#endif
#define FLASH_STATUS_ALL_FLAGS \
(FLASH_SR_RDERR | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | \
FLASH_SR_WRPERR | FLASH_SR_SOP | FLASH_SR_EOP)
// see docs/memory.md for more information
static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
@ -60,26 +78,14 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
#endif
};
const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT] = {
FLASH_SECTOR_FIRMWARE_START,
7,
8,
9,
10,
FLASH_SECTOR_FIRMWARE_END,
FLASH_SECTOR_FIRMWARE_EXTRA_START,
18,
19,
20,
21,
22,
FLASH_SECTOR_FIRMWARE_EXTRA_END,
};
const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT] = {
FLASH_SECTOR_STORAGE_1,
FLASH_SECTOR_STORAGE_2,
};
uint32_t flash_wait_and_clear_status_flags(void) {
while (FLASH->SR & FLASH_SR_BSY)
; // wait for all previous flash operations to complete
const uint32_t result =
FLASH->SR & FLASH_STATUS_ALL_FLAGS; // get the current status flags
FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
return result;
}
secbool flash_unlock_write(void) {
HAL_FLASH_Unlock();
@ -92,7 +98,7 @@ secbool flash_lock_write(void) {
return sectrue;
}
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
if (sector >= FLASH_SECTOR_COUNT) {
return NULL;
}
@ -104,48 +110,64 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
return (const void *)addr;
}
uint32_t flash_sector_size(uint8_t sector) {
uint32_t flash_sector_size(uint16_t sector) {
if (sector >= FLASH_SECTOR_COUNT) {
return 0;
}
return FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
}
secbool flash_erase_sectors(const uint8_t *sectors, int len,
void (*progress)(int pos, int len)) {
secbool flash_area_erase_bulk(const flash_area_t *area, int count,
void (*progress)(int pos, int len)) {
ensure(flash_unlock_write(), NULL);
FLASH_EraseInitTypeDef EraseInitStruct;
FLASH_EraseInitTypeDef EraseInitStruct = {0};
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.NbSectors = 1;
if (progress) {
progress(0, len);
}
for (int i = 0; i < len; i++) {
EraseInitStruct.Sector = sectors[i];
uint32_t SectorError;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
ensure(flash_lock_write(), NULL);
return secfalse;
int total_sectors = 0;
int done_sectors = 0;
for (int a = 0; a < count; a++) {
for (int i = 0; i < area[a].num_subareas; i++) {
total_sectors += area[a].subarea[i].num_sectors;
}
// check whether the sector was really deleted (contains only 0xFF)
const uint32_t addr_start = FLASH_SECTOR_TABLE[sectors[i]],
addr_end = FLASH_SECTOR_TABLE[sectors[i] + 1];
for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
ensure(flash_lock_write(), NULL);
return secfalse;
}
if (progress) {
progress(0, total_sectors);
}
for (int a = 0; a < count; a++) {
for (int s = 0; s < area[a].num_subareas; s++) {
for (int i = 0; i < area[a].subarea[s].num_sectors; i++) {
int sector = area[a].subarea[s].first_sector + i;
EraseInitStruct.Sector = sector;
uint32_t SectorError;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) {
ensure(flash_lock_write(), NULL);
return secfalse;
}
// check whether the sector was really deleted (contains only 0xFF)
const uint32_t addr_start = FLASH_SECTOR_TABLE[sector],
addr_end = FLASH_SECTOR_TABLE[sector + 1];
for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
if (*((const uint32_t *)addr) != 0xFFFFFFFF) {
ensure(flash_lock_write(), NULL);
return secfalse;
}
}
done_sectors++;
if (progress) {
progress(done_sectors, total_sectors);
}
}
}
if (progress) {
progress(i + 1, len);
}
}
ensure(flash_lock_write(), NULL);
return sectrue;
}
secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) {
secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data) {
uint32_t address = (uint32_t)flash_get_address(sector, offset, 1);
if (address == 0) {
return secfalse;
@ -162,7 +184,7 @@ secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) {
return sectrue;
}
secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) {
secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) {
uint32_t address = (uint32_t)flash_get_address(sector, offset, 4);
if (address == 0) {
return secfalse;

@ -57,15 +57,6 @@
#define OPTION_BYTES_BANK1_WRP (*(volatile uint16_t* const)0x1FFFC008U)
#define OPTION_BYTES_BANK2_WRP (*(volatile uint16_t* const)0x1FFEC008U)
uint32_t flash_wait_and_clear_status_flags(void) {
while (FLASH->SR & FLASH_SR_BSY)
; // wait for all previous flash operations to complete
const uint32_t result =
FLASH->SR & FLASH_STATUS_ALL_FLAGS; // get the current status flags
FLASH->SR |= FLASH_STATUS_ALL_FLAGS; // clear all status flags
return result;
}
secbool flash_check_option_bytes(void) {
flash_wait_and_clear_status_flags();
// check values stored in flash interface registers

@ -23,6 +23,8 @@
#include STM32_HAL_H
#include <stdint.h>
#define FLASH_BYTE_ACCESS 1
typedef enum {
CLOCK_180_MHZ = 0,
CLOCK_168_MHZ = 1,

@ -28,12 +28,21 @@
#include "common.h"
#include "flash.h"
#include "model.h"
#include "profile.h"
#ifndef FLASH_FILE
#define FLASH_FILE profile_flash_path()
#endif
#if defined TREZOR_MODEL_T || defined TREZOR_MODEL_R
#define FLASH_SECTOR_COUNT 24
#elif defined TREZOR_MODEL_1
#define FLASH_SECTOR_COUNT 12
#else
#error Unknown MCU
#endif
static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
[0] = 0x08000000, // - 0x08003FFF | 16 KiB
[1] = 0x08004000, // - 0x08007FFF | 16 KiB
@ -68,27 +77,6 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
#endif
};
const uint8_t FIRMWARE_SECTORS[FIRMWARE_SECTORS_COUNT] = {
FLASH_SECTOR_FIRMWARE_START,
7,
8,
9,
10,
FLASH_SECTOR_FIRMWARE_END,
FLASH_SECTOR_FIRMWARE_EXTRA_START,
18,
19,
20,
21,
22,
FLASH_SECTOR_FIRMWARE_EXTRA_END,
};
const uint8_t STORAGE_SECTORS[STORAGE_SECTORS_COUNT] = {
FLASH_SECTOR_STORAGE_1,
FLASH_SECTOR_STORAGE_2,
};
static uint8_t *FLASH_BUFFER = NULL;
static uint32_t FLASH_SIZE;
@ -145,7 +133,7 @@ secbool flash_unlock_write(void) { return sectrue; }
secbool flash_lock_write(void) { return sectrue; }
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
if (sector >= FLASH_SECTOR_COUNT) {
return NULL;
}
@ -157,32 +145,52 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
return FLASH_BUFFER + addr - FLASH_SECTOR_TABLE[0];
}
uint32_t flash_sector_size(uint8_t sector) {
uint32_t flash_sector_size(uint16_t sector) {
if (sector >= FLASH_SECTOR_COUNT) {
return 0;
}
return FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
}
secbool flash_erase_sectors(const uint8_t *sectors, int len,
void (*progress)(int pos, int len)) {
secbool flash_area_erase_bulk(const flash_area_t *area, int count,
void (*progress)(int pos, int len)) {
ensure(flash_unlock_write(), NULL);
int total_sectors = 0;
int done_sectors = 0;
for (int a = 0; a < count; a++) {
for (int i = 0; i < area[a].num_subareas; i++) {
total_sectors += area[a].subarea[i].num_sectors;
}
}
if (progress) {
progress(0, len);
progress(0, total_sectors);
}
for (int i = 0; i < len; i++) {
const uint8_t sector = sectors[i];
const uint32_t offset = FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0];
const uint32_t size =
FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
memset(FLASH_BUFFER + offset, 0xFF, size);
if (progress) {
progress(i + 1, len);
for (int a = 0; a < count; a++) {
for (int s = 0; s < area[a].num_subareas; s++) {
for (int i = 0; i < area[a].subarea[s].num_sectors; i++) {
int sector = area[a].subarea[s].first_sector + i;
const uint32_t offset =
FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0];
const uint32_t size =
FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
memset(FLASH_BUFFER + offset, 0xFF, size);
done_sectors++;
if (progress) {
progress(done_sectors, total_sectors);
}
}
}
}
ensure(flash_lock_write(), NULL);
return sectrue;
}
secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) {
secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data) {
uint8_t *flash = (uint8_t *)flash_get_address(sector, offset, 1);
if (!flash) {
return secfalse;
@ -194,7 +202,7 @@ secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) {
return sectrue;
}
secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) {
secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) {
if (offset % sizeof(uint32_t)) { // we write only at 4-byte boundary
return secfalse;
}

@ -1 +0,0 @@
../stm32f4/image.c

@ -1,2 +1,4 @@
#define FLASH_BYTE_ACCESS 1
void emulator_poll_events(void);

@ -25,6 +25,7 @@
#ifdef USE_TOUCH
#include "common.h"
#include "platform.h"
#include "touch.h"
extern int sdl_display_res_x, sdl_display_res_y;

@ -33,6 +33,9 @@ def configure(
defines += [f'TREZOR_BOARD=\\"boards/{board}\\"']
defines += [f"HW_MODEL={hw_model}"]
defines += [f"HW_REVISION={hw_revision}"]
sources += [
"embed/models/model_D001_layout.c",
]
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
sources += ["embed/trezorhal/stm32f4/displays/ili9341_spi.c"]
sources += ["embed/trezorhal/stm32f4/dma.c"]

@ -38,7 +38,6 @@ def stm32f4_common_files(env, defines, sources, paths):
sources += [
"embed/trezorhal/stm32f4/board_capabilities.c",
"embed/trezorhal/stm32f4/common.c",
"embed/trezorhal/stm32f4/image.c",
"embed/trezorhal/stm32f4/flash.c",
"embed/trezorhal/stm32f4/lowlevel.c",
"embed/trezorhal/stm32f4/mpu.c",

@ -31,6 +31,9 @@ def configure(
defines += [f'TREZOR_BOARD=\\"boards/{board}\\"']
defines += [f"HW_MODEL={hw_model}"]
defines += [f"HW_REVISION={hw_revision}"]
sources += [
"embed/models/model_T1B1_layout.c",
]
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
if "input" in features_wanted:

@ -33,6 +33,9 @@ def configure(
defines += [f'TREZOR_BOARD=\\"boards/{board}\\"']
defines += [f"HW_MODEL={hw_model}"]
defines += [f"HW_REVISION={hw_revision}"]
sources += [
"embed/models/model_T2B1_layout.c",
]
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
sources += ["embed/trezorhal/stm32f4/i2c.c"]

@ -33,6 +33,9 @@ def configure(
defines += [f'TREZOR_BOARD=\\"boards/{board}\\"']
defines += [f"HW_MODEL={hw_model}"]
defines += [f"HW_REVISION={hw_revision}"]
sources += [
"embed/models/model_T2B1_layout.c",
]
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
if "input" in features_wanted:

@ -33,6 +33,9 @@ def configure(
defines += [f'TREZOR_BOARD=\\"boards/{board}\\"']
defines += [f"HW_MODEL={hw_model}"]
defines += [f"HW_REVISION={hw_revision}"]
sources += [
"embed/models/model_T2B1_layout.c",
]
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
if "input" in features_wanted:

@ -33,6 +33,9 @@ def configure(
defines += [f'TREZOR_BOARD=\\"boards/{board}\\"']
defines += [f"HW_MODEL={hw_model}"]
defines += [f"HW_REVISION={hw_revision}"]
sources += [
"embed/models/model_T2B1_layout.c",
]
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
if "input" in features_wanted:

@ -34,6 +34,9 @@ def configure(
defines += [f'TREZOR_BOARD=\\"boards/{board}\\"']
defines += [f"HW_MODEL={hw_model}"]
defines += [f"HW_REVISION={hw_revision}"]
sources += [
"embed/models/model_T2T1_layout.c",
]
sources += [f"embed/trezorhal/stm32f4/displays/{display}"]
sources += ["embed/trezorhal/stm32f4/backlight_pwm.c"]
sources += [

@ -20,6 +20,7 @@ OBJS += usb_standard.o
OBJS += util.o
OBJS += webusb.o
OBJS += winusb.o
OBJS += vendor/trezor-storage/flash_common.o
libtrezor.a: $(OBJS)

@ -25,6 +25,8 @@
#include "memory.h"
#include "supervise.h"
#define STORAGE_AREAS_COUNT 2
static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
[0] = 0x08000000, // - 0x08003FFF | 16 KiB
[1] = 0x08004000, // - 0x08007FFF | 16 KiB
@ -41,6 +43,25 @@ static const uint32_t FLASH_SECTOR_TABLE[FLASH_SECTOR_COUNT + 1] = {
[12] = 0x08100000, // last element - not a valid sector
};
const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = {
{
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 2,
.num_sectors = 1,
},
},
{
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 3,
.num_sectors = 1,
},
},
};
static secbool flash_check_success(uint32_t status) {
return (status & (FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR |
FLASH_SR_WRPERR))
@ -55,7 +76,7 @@ secbool flash_unlock_write(void) {
secbool flash_lock_write(void) { return flash_check_success(svc_flash_lock()); }
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
if (sector >= FLASH_SECTOR_COUNT) {
return NULL;
}
@ -67,29 +88,13 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
return (const void *)FLASH_PTR(addr);
}
uint32_t flash_sector_size(uint8_t sector) {
uint32_t flash_sector_size(uint16_t sector) {
if (sector >= FLASH_SECTOR_COUNT) {
return 0;
}
return FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
}
secbool flash_erase(uint8_t sector) {
ensure(flash_unlock_write(), NULL);
svc_flash_erase_sector(sector);
ensure(flash_lock_write(), NULL);
// Check whether the sector was really deleted (contains only 0xFF).
const uint32_t addr_start = FLASH_SECTOR_TABLE[sector],
addr_end = FLASH_SECTOR_TABLE[sector + 1];
for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
if (*((const uint32_t *)FLASH_PTR(addr)) != 0xFFFFFFFF) {
return secfalse;
}
}
return sectrue;
}
secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) {
uint8_t *address = (uint8_t *)flash_get_address(sector, offset, 1);
if (address == NULL) {
@ -133,3 +138,43 @@ secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) {
return sectrue;
}
secbool flash_area_erase_bulk(const flash_area_t *area, int count,
void (*progress)(int pos, int len)) {
ensure(flash_unlock_write(), NULL);
int total_sectors = 0;
int done_sectors = 0;
for (int a = 0; a < count; a++) {
for (int i = 0; i < area[a].num_subareas; i++) {
total_sectors += area[a].subarea[i].num_sectors;
}
}
if (progress) {
progress(0, total_sectors);
}
for (int a = 0; a < count; a++) {
for (int s = 0; s < area[a].num_subareas; s++) {
for (int i = 0; i < area[a].subarea[s].num_sectors; i++) {
int sector = area[a].subarea[s].first_sector + i;
svc_flash_erase_sector(sector);
// check whether the sector was really deleted (contains only 0xFF)
const uint32_t addr_start = FLASH_SECTOR_TABLE[sector],
addr_end = FLASH_SECTOR_TABLE[sector + 1];
for (uint32_t addr = addr_start; addr < addr_end; addr += 4) {
if (*((const uint32_t *)FLASH_PTR(addr)) != 0xFFFFFFFF) {
ensure(flash_lock_write(), NULL);
return secfalse;
}
}
done_sectors++;
if (progress) {
progress(done_sectors, total_sectors);
}
}
}
}
ensure(flash_lock_write(), NULL);
return sectrue;
}

@ -24,8 +24,11 @@
#include <stdlib.h>
#include "secbool.h"
#define FLASH_BYTE_ACCESS 1
#define FLASH_SECTOR_COUNT 24
#include "flash_common.h"
// note: FLASH_SR_RDERR is STM32F42xxx and STM32F43xxx specific (STM32F427)
// (reference RM0090 section 3.7.5)
#ifndef STM32F427xx
@ -36,12 +39,6 @@
(FLASH_SR_RDERR | FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR | \
FLASH_SR_WRPERR | FLASH_SR_SOP | FLASH_SR_EOP)
secbool __wur flash_unlock_write(void);
secbool __wur flash_lock_write(void);
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size);
uint32_t flash_sector_size(uint8_t sector);
secbool __wur flash_erase(uint8_t sector);
secbool __wur flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data);
secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data);

@ -33,6 +33,8 @@
*/
#define NORCOW_HEADER_LEN (0)
extern const flash_area_t STORAGE_AREAS[NORCOW_SECTOR_COUNT];
/*
* Current storage version.
*/

@ -0,0 +1,127 @@
#include "flash.h"
static uint32_t flash_subarea_get_size(const flash_subarea_t *subarea) {
uint32_t size = 0;
for (int s = 0; s < subarea->num_sectors; s++) {
size += flash_sector_size(subarea->first_sector + s);
}
return size;
}
static secbool subarea_get_sector_and_offset(const flash_subarea_t *subarea,
uint32_t offset,
uint16_t *sector_out,
uint32_t *offset_out) {
uint32_t tmp_offset = offset;
uint16_t sector = subarea->first_sector;
// in correct subarea
for (int s = 0; s < subarea->num_sectors; s++) {
const uint32_t sector_size = flash_sector_size(sector);
if (tmp_offset < sector_size) {
*sector_out = sector;
*offset_out = tmp_offset;
return sectrue;
}
tmp_offset -= sector_size;
sector++;
}
return secfalse;
}
uint32_t flash_area_get_size(const flash_area_t *area) {
uint32_t size = 0;
for (int i = 0; i < area->num_subareas; i++) {
size += flash_subarea_get_size(&area->subarea[i]);
}
return size;
}
uint16_t flash_total_sectors(const flash_area_t *area) {
uint16_t total = 0;
for (int i = 0; i < area->num_subareas; i++) {
total += area->subarea[i].num_sectors;
}
return total;
}
int32_t flash_get_sector_num(const flash_area_t *area,
uint32_t sector_inner_num) {
uint16_t sector = 0;
uint16_t remaining = sector_inner_num;
for (int i = 0; i < area->num_subareas; i++) {
if (remaining < area->subarea[i].num_sectors) {
sector = area->subarea[i].first_sector + remaining;
return sector;
} else {
remaining -= area->subarea[i].num_sectors;
}
}
return -1;
}
static secbool get_sector_and_offset(const flash_area_t *area, uint32_t offset,
uint16_t *sector_out,
uint32_t *offset_out) {
uint32_t tmp_offset = offset;
for (int i = 0; i < area->num_subareas; i++) {
uint32_t sub_size = flash_subarea_get_size(&area->subarea[i]);
if (tmp_offset >= sub_size) {
tmp_offset -= sub_size;
continue;
}
return subarea_get_sector_and_offset(&area->subarea[i], tmp_offset,
sector_out, offset_out);
}
return secfalse;
}
const void *flash_area_get_address(const flash_area_t *area, uint32_t offset,
uint32_t size) {
uint16_t sector;
uint32_t sector_offset;
if (!get_sector_and_offset(area, offset, &sector, &sector_offset)) {
return NULL;
}
return flash_get_address(sector, sector_offset, size);
}
secbool flash_area_erase(const flash_area_t *area,
void (*progress)(int pos, int len)) {
return flash_area_erase_bulk(area, 1, progress);
}
secbool flash_area_write_byte(const flash_area_t *area, uint32_t offset,
uint8_t data) {
uint16_t sector;
uint32_t sector_offset;
if (get_sector_and_offset(area, offset, &sector, &sector_offset) != sectrue) {
return secfalse;
}
return flash_write_byte(sector, sector_offset, data);
}
secbool flash_area_write_word(const flash_area_t *area, uint32_t offset,
uint32_t data) {
uint16_t sector;
uint32_t sector_offset;
if (get_sector_and_offset(area, offset, &sector, &sector_offset) != sectrue) {
return secfalse;
}
return flash_write_word(sector, sector_offset, data);
}
secbool flash_area_write_quadword(const flash_area_t *area, uint32_t offset,
const uint32_t *data) {
for (int i = 0; i < 4; i++) {
if (sectrue !=
flash_area_write_word(area, offset + i * sizeof(uint32_t), data[i])) {
return secfalse;
}
}
return sectrue;
}

@ -0,0 +1,46 @@
#ifndef FLASH_COMMON_H
#define FLASH_COMMON_H
#include <stdint.h>
#include "secbool.h"
typedef struct {
uint16_t first_sector;
uint16_t num_sectors;
} flash_subarea_t;
typedef struct {
flash_subarea_t subarea[4];
uint8_t num_subareas;
} flash_area_t;
void flash_init(void);
secbool __wur flash_unlock_write(void);
secbool __wur flash_lock_write(void);
const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size);
uint32_t flash_sector_size(uint16_t sector);
uint16_t flash_total_sectors(const flash_area_t *area);
int32_t flash_get_sector_num(const flash_area_t *area,
uint32_t sector_inner_num);
const void *flash_area_get_address(const flash_area_t *area, uint32_t offset,
uint32_t size);
uint32_t flash_area_get_size(const flash_area_t *area);
secbool __wur flash_area_erase(const flash_area_t *area,
void (*progress)(int pos, int len));
secbool __wur flash_area_erase_bulk(const flash_area_t *area, int count,
void (*progress)(int pos, int len));
#if defined FLASH_BYTE_ACCESS
secbool __wur flash_area_write_byte(const flash_area_t *area, uint32_t offset,
uint8_t data);
secbool __wur flash_area_write_word(const flash_area_t *area, uint32_t offset,
uint32_t data);
#endif
secbool __wur flash_area_write_quadword(const flash_area_t *area,
uint32_t offset, const uint32_t *data);
#endif

@ -43,9 +43,6 @@
#define NORCOW_STORAGE_START \
(NORCOW_HEADER_LEN + NORCOW_MAGIC_LEN + NORCOW_VERSION_LEN)
// Map from sector index to sector number.
static const uint8_t norcow_sectors[NORCOW_SECTOR_COUNT] = NORCOW_SECTORS;
// The index of the active reading sector and writing sector. These should be
// equal except when storage version upgrade or compaction is in progress.
static uint8_t norcow_active_sector = 0;
@ -63,7 +60,7 @@ static uint32_t norcow_free_offset = 0;
*/
static const void *norcow_ptr(uint8_t sector, uint32_t offset, uint32_t size) {
ensure(sectrue * (sector <= NORCOW_SECTOR_COUNT), "invalid sector");
return flash_get_address(norcow_sectors[sector], offset, size);
return flash_area_get_address(&STORAGE_AREAS[sector], offset, size);
}
/*
@ -82,13 +79,14 @@ static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix,
ensure(flash_unlock_write(), NULL);
// write prefix
ensure(flash_write_word(norcow_sectors[sector], offset, prefix), NULL);
ensure(flash_area_write_word(&STORAGE_AREAS[sector], offset, prefix), NULL);
offset += NORCOW_PREFIX_LEN;
if (data != NULL) {
// write data
for (uint16_t i = 0; i < len; i++, offset++) {
ensure(flash_write_byte(norcow_sectors[sector], offset, data[i]), NULL);
ensure(flash_area_write_byte(&STORAGE_AREAS[sector], offset, data[i]),
NULL);
}
} else {
offset += len;
@ -96,7 +94,7 @@ static secbool norcow_write(uint8_t sector, uint32_t offset, uint32_t prefix,
// pad with zeroes
for (; offset % NORCOW_WORD_SIZE; offset++) {
ensure(flash_write_byte(norcow_sectors[sector], offset, 0x00), NULL);
ensure(flash_area_write_byte(&STORAGE_AREAS[sector], offset, 0x00), NULL);
}
ensure(flash_lock_write(), NULL);
@ -114,7 +112,7 @@ static void erase_sector(uint8_t sector, secbool set_magic) {
memcpy(header_backup, sector_start, sizeof(header_backup));
#endif
ensure(flash_erase(norcow_sectors[sector]), "erase failed");
ensure(flash_area_erase(&STORAGE_AREAS[sector], NULL), "erase failed");
#if NORCOW_HEADER_LEN > 0
// Copy the sector header back.
@ -419,7 +417,6 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
return secfalse;
}
const uint8_t sector_num = norcow_sectors[norcow_write_sector];
secbool ret = secfalse;
const void *ptr = NULL;
uint16_t len_old = 0;
@ -435,8 +432,9 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
ret = sectrue;
ensure(flash_unlock_write(), NULL);
for (uint16_t i = 0; i < len; i++) {
if (sectrue != flash_write_byte(sector_num, offset + i,
((const uint8_t *)val)[i])) {
if (sectrue !=
flash_area_write_byte(&STORAGE_AREAS[norcow_write_sector],
offset + i, ((const uint8_t *)val)[i])) {
ret = secfalse;
break;
}
@ -453,13 +451,16 @@ secbool norcow_set_ex(uint16_t key, const void *val, uint16_t len,
// Update the prefix to indicate that the old item has been deleted.
uint32_t prefix = (uint32_t)len_old << 16;
ensure(flash_write_word(sector_num, offset - NORCOW_PREFIX_LEN, prefix),
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector],
offset - NORCOW_PREFIX_LEN, prefix),
NULL);
// Delete the old item data.
uint32_t end = offset + len_old;
while (offset < end) {
ensure(flash_write_word(sector_num, offset, 0x00000000), NULL);
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector],
offset, 0x00000000),
NULL);
offset += NORCOW_WORD_SIZE;
}
@ -489,7 +490,6 @@ secbool norcow_delete(uint16_t key) {
return secfalse;
}
const uint8_t sector_num = norcow_sectors[norcow_write_sector];
const void *ptr = NULL;
uint16_t len = 0;
if (sectrue != find_item(norcow_write_sector, key, &ptr, &len)) {
@ -504,13 +504,16 @@ secbool norcow_delete(uint16_t key) {
// Update the prefix to indicate that the item has been deleted.
uint32_t prefix = (uint32_t)len << 16;
ensure(flash_write_word(sector_num, offset - NORCOW_PREFIX_LEN, prefix),
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector],
offset - NORCOW_PREFIX_LEN, prefix),
NULL);
// Delete the item data.
uint32_t end = offset + len;
while (offset < end) {
ensure(flash_write_word(sector_num, offset, 0x00000000), NULL);
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector], offset,
0x00000000),
NULL);
offset += NORCOW_WORD_SIZE;
}
@ -537,8 +540,8 @@ secbool norcow_update_word(uint16_t key, uint16_t offset, uint32_t value) {
(const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) +
offset;
ensure(flash_unlock_write(), NULL);
ensure(flash_write_word(norcow_sectors[norcow_write_sector], sector_offset,
value),
ensure(flash_area_write_word(&STORAGE_AREAS[norcow_write_sector],
sector_offset, value),
NULL);
ensure(flash_lock_write(), NULL);
return sectrue;
@ -561,10 +564,11 @@ secbool norcow_update_bytes(const uint16_t key, const uint16_t offset,
(const uint8_t *)ptr -
(const uint8_t *)norcow_ptr(norcow_write_sector, 0, NORCOW_SECTOR_SIZE) +
offset;
uint8_t sector = norcow_sectors[norcow_write_sector];
ensure(flash_unlock_write(), NULL);
for (uint16_t i = 0; i < len; i++, sector_offset++) {
ensure(flash_write_byte(sector, sector_offset, data[i]), NULL);
ensure(flash_area_write_byte(&STORAGE_AREAS[norcow_write_sector],
sector_offset, data[i]),
NULL);
}
ensure(flash_lock_write(), NULL);
return sectrue;

@ -13,6 +13,8 @@ BASE = ../../../
SRC = storage/tests/c/flash.c
SRC += storage/tests/c/common.c
SRC += storage/tests/c/random_delays.c
SRC += storage/tests/c/test_layout.c
SRC += storage/flash_common.c
SRC += storage/storage.c
SRC += storage/norcow.c
SRC += crypto/pbkdf2.c

@ -23,6 +23,9 @@
#include "common.h"
#include "flash.h"
#include "norcow_config.h"
#define FLASH_SECTOR_COUNT 24
static const uint32_t FLASH_START = 0x08000000;
static const uint32_t FLASH_END = 0x08200000;
@ -60,7 +63,14 @@ secbool flash_unlock_write(void) { return sectrue; }
secbool flash_lock_write(void) { return sectrue; }
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
uint32_t flash_sector_size(uint16_t sector) {
if (sector >= FLASH_SECTOR_COUNT) {
return 0;
}
return FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
}
const void *flash_get_address(uint16_t sector, uint32_t offset, uint32_t size) {
if (sector >= FLASH_SECTOR_COUNT) {
return NULL;
}
@ -72,25 +82,45 @@ const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size) {
return FLASH_BUFFER + addr - FLASH_SECTOR_TABLE[0];
}
secbool flash_erase_sectors(const uint8_t *sectors, int len,
void (*progress)(int pos, int len)) {
secbool flash_area_erase_bulk(const flash_area_t *area, int count,
void (*progress)(int pos, int len)) {
ensure(flash_unlock_write(), NULL);
int total_sectors = 0;
int done_sectors = 0;
for (int a = 0; a < count; a++) {
for (int i = 0; i < area[a].num_subareas; i++) {
total_sectors += area[a].subarea[i].num_sectors;
}
}
if (progress) {
progress(0, len);
progress(0, total_sectors);
}
for (int i = 0; i < len; i++) {
const uint8_t sector = sectors[i];
const uint32_t offset = FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0];
const uint32_t size =
FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
memset(FLASH_BUFFER + offset, 0xFF, size);
if (progress) {
progress(i + 1, len);
for (int a = 0; a < count; a++) {
for (int s = 0; s < area[a].num_subareas; s++) {
for (int i = 0; i < area[a].subarea[s].num_sectors; i++) {
int sector = area[a].subarea[s].first_sector + i;
const uint32_t offset =
FLASH_SECTOR_TABLE[sector] - FLASH_SECTOR_TABLE[0];
const uint32_t size =
FLASH_SECTOR_TABLE[sector + 1] - FLASH_SECTOR_TABLE[sector];
memset(FLASH_BUFFER + offset, 0xFF, size);
done_sectors++;
if (progress) {
progress(done_sectors, total_sectors);
}
}
}
}
ensure(flash_lock_write(), NULL);
return sectrue;
}
secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) {
secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data) {
uint8_t *flash = (uint8_t *)flash_get_address(sector, offset, 1);
if (!flash) {
return secfalse;
@ -102,7 +132,7 @@ secbool flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data) {
return sectrue;
}
secbool flash_write_word(uint8_t sector, uint32_t offset, uint32_t data) {
secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data) {
if (offset % 4) { // we write only at 4-byte boundary
return secfalse;
}

@ -24,19 +24,15 @@
#include <stdlib.h>
#include "secbool.h"
#define FLASH_SECTOR_COUNT 24
#define FLASH_BYTE_ACCESS 1
secbool __wur flash_unlock_write(void);
secbool __wur flash_lock_write(void);
#include "flash_common.h"
#include "test_layout.h"
const void *flash_get_address(uint8_t sector, uint32_t offset, uint32_t size);
uint32_t flash_sector_size(uint16_t sector);
secbool __wur flash_erase_sectors(const uint8_t *sectors, int len,
void (*progress)(int pos, int len));
static inline secbool flash_erase(uint8_t sector) {
return flash_erase_sectors(&sector, 1, NULL);
}
secbool __wur flash_write_byte(uint8_t sector, uint32_t offset, uint8_t data);
secbool __wur flash_write_word(uint8_t sector, uint32_t offset, uint32_t data);
secbool flash_write_byte(uint16_t sector, uint32_t offset, uint8_t data);
secbool flash_write_word(uint16_t sector, uint32_t offset, uint32_t data);
#endif

@ -24,8 +24,6 @@
#define NORCOW_SECTOR_COUNT 2
#define NORCOW_SECTOR_SIZE (64 * 1024)
#define NORCOW_SECTORS \
{ 4, 16 }
/*
* The length of the sector header in bytes. The header is preserved between

@ -0,0 +1,21 @@
#include "test_layout.h"
const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT] = {
{
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 4,
.num_sectors = 1,
},
},
{
.num_subareas = 1,
.subarea[0] =
{
.first_sector = 16,
.num_sectors = 1,
},
},
};

@ -0,0 +1,10 @@
#ifndef TEST_LAYOUT_H
#define TEST_LAYOUT_H
#define STORAGE_AREAS_COUNT 2
#include "flash_common.h"
extern const flash_area_t STORAGE_AREAS[STORAGE_AREAS_COUNT];
#endif
Loading…
Cancel
Save