mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-27 00:28:10 +00:00
refactor(core): add abstraction over flash memory layout
[no changelog]
This commit is contained in:
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;
|
||||
|
22
core/embed/models/layout_common.h
Normal file
22
core/embed/models/layout_common.h
Normal file
@ -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
|
||||
|
1
core/embed/models/model_D001_layout.c
Symbolic link
1
core/embed/models/model_D001_layout.c
Symbolic link
@ -0,0 +1 @@
|
||||
model_T2T1_layout.c
|
@ -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
|
||||
|
39
core/embed/models/model_T1B1_layout.c
Normal file
39
core/embed/models/model_T1B1_layout.c
Normal file
@ -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
|
||||
|
1
core/embed/models/model_T2B1_layout.c
Symbolic link
1
core/embed/models/model_T2B1_layout.c
Symbolic link
@ -0,0 +1 @@
|
||||
model_T2T1_layout.c
|
@ -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
|
||||
|
82
core/embed/models/model_T2T1_layout.c
Normal file
82
core/embed/models/model_T2T1_layout.c
Normal file
@ -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];
|
||||
|
||||
// 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)
|
||||
|
||||
void flash_init(void);
|
||||
|
||||
uint32_t flash_wait_and_clear_status_flags(void);
|
||||
|
||||
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_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(§or, 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
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "flash_common.h"
|
||||
|
||||
void flash_init(void);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
// 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)) {
|
||||
if (progress) {
|
||||
progress(0, len);
|
||||
}
|
||||
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);
|
||||
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;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
127
storage/flash_common.c
Normal file
127
storage/flash_common.c
Normal file
@ -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, §or, §or_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, §or, §or_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, §or, §or_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;
|
||||
}
|
46
storage/flash_common.h
Normal file
46
storage/flash_common.h
Normal file
@ -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)) {
|
||||
if (progress) {
|
||||
progress(0, len);
|
||||
}
|
||||
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);
|
||||
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;
|
||||
|
||||
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(§or, 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
|
||||
|
21
storage/tests/c/test_layout.c
Normal file
21
storage/tests/c/test_layout.c
Normal file
@ -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,
|
||||
},
|
||||
},
|
||||
};
|
10
storage/tests/c/test_layout.h
Normal file
10
storage/tests/c/test_layout.h
Normal file
@ -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…
Reference in New Issue
Block a user