From 67d8d4fa2efeadafc6afb046e9d114ac648d159c Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Wed, 27 Sep 2017 12:00:35 +0200 Subject: [PATCH] modtrezorio: add FlashOTP class --- embed/extmod/modtrezorio/modtrezorio-flash.h | 101 +++++++++++++++++++ embed/extmod/modtrezorio/modtrezorio.c | 3 + embed/extmod/modtrezorio/unix-flash-mock.h | 52 ++++++++++ embed/trezorhal/flash.c | 22 ++-- embed/trezorhal/flash.h | 2 +- 5 files changed, 168 insertions(+), 12 deletions(-) create mode 100644 embed/extmod/modtrezorio/modtrezorio-flash.h create mode 100644 embed/extmod/modtrezorio/unix-flash-mock.h diff --git a/embed/extmod/modtrezorio/modtrezorio-flash.h b/embed/extmod/modtrezorio/modtrezorio-flash.h new file mode 100644 index 000000000..ddadef4b7 --- /dev/null +++ b/embed/extmod/modtrezorio/modtrezorio-flash.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) Pavol Rusnak, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ + +#if defined TREZOR_STM32 +#include "flash.h" +#elif defined TREZOR_UNIX +#include "unix-flash-mock.h" +#else +#error Unsupported TREZOR port. Only STM32 and UNIX ports are supported. +#endif + +/// class FlashOTP: +/// ''' +/// ''' +typedef struct _mp_obj_FlashOTP_t { + mp_obj_base_t base; +} mp_obj_FlashOTP_t; + +/// def __init__(self) -> None: +/// ''' +/// ''' +STATIC mp_obj_t mod_trezorio_FlashOTP_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + mp_obj_FlashOTP_t *o = m_new_obj(mp_obj_FlashOTP_t); + o->base.type = type; + return MP_OBJ_FROM_PTR(o); +} + +/// def FlashOTP.write(self, block: int, offset: int, data: bytes) -> None: +/// ''' +/// Writes data to OTP flash +/// ''' +STATIC mp_obj_t mod_trezorio_FlashOTP_write(size_t n_args, const mp_obj_t *args) { + uint8_t block = mp_obj_get_int(args[1]); + uint8_t offset = mp_obj_get_int(args[2]); + mp_buffer_info_t data; + mp_get_buffer_raise(args[3], &data, MP_BUFFER_READ); + if (!flash_otp_write(block, offset, data.buf, data.len)) { + mp_raise_ValueError("write failed"); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_FlashOTP_write_obj, 4, 4, mod_trezorio_FlashOTP_write); + +/// def FlashOTP.read(self, block: int, offset: int, data: bytearray) -> None: +/// ''' +/// Reads data from OTP flash +/// ''' +STATIC mp_obj_t mod_trezorio_FlashOTP_read(size_t n_args, const mp_obj_t *args) { + uint8_t block = mp_obj_get_int(args[1]); + uint8_t offset = mp_obj_get_int(args[2]); + mp_buffer_info_t data; + mp_get_buffer_raise(args[3], &data, MP_BUFFER_WRITE); + if (!flash_otp_read(block, offset, data.buf, data.len)) { + mp_raise_ValueError("read failed"); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorio_FlashOTP_read_obj, 4, 4, mod_trezorio_FlashOTP_read); + +/// def FlashOTP.lock(self, block: int) -> None: +/// ''' +/// Lock OTP flash block +/// ''' +STATIC mp_obj_t mod_trezorio_FlashOTP_lock(mp_obj_t self, mp_obj_t block) { + uint8_t b = mp_obj_get_int(block); + if (!flash_otp_lock(b)) { + mp_raise_ValueError("lock failed"); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_FlashOTP_lock_obj, mod_trezorio_FlashOTP_lock); + +/// def FlashOTP.is_locked(self, block: int) -> bool: +/// ''' +/// Is OTP flash block locked? +/// ''' +STATIC mp_obj_t mod_trezorio_FlashOTP_is_locked(mp_obj_t self, mp_obj_t block) { + uint8_t b = mp_obj_get_int(block); + return flash_otp_is_locked(b) ? mp_const_true : mp_const_false; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorio_FlashOTP_is_locked_obj, mod_trezorio_FlashOTP_is_locked); + +STATIC const mp_rom_map_elem_t mod_trezorio_FlashOTP_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mod_trezorio_FlashOTP_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorio_FlashOTP_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_lock), MP_ROM_PTR(&mod_trezorio_FlashOTP_lock_obj) }, + { MP_ROM_QSTR(MP_QSTR_is_locked), MP_ROM_PTR(&mod_trezorio_FlashOTP_is_locked_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mod_trezorio_FlashOTP_locals_dict, mod_trezorio_FlashOTP_locals_dict_table); + +STATIC const mp_obj_type_t mod_trezorio_FlashOTP_type = { + { &mp_type_type }, + .name = MP_QSTR_FlashOTP, + .make_new = mod_trezorio_FlashOTP_make_new, + .locals_dict = (void*)&mod_trezorio_FlashOTP_locals_dict, +}; diff --git a/embed/extmod/modtrezorio/modtrezorio.c b/embed/extmod/modtrezorio/modtrezorio.c index 0a7bd3bb1..9aa049800 100644 --- a/embed/extmod/modtrezorio/modtrezorio.c +++ b/embed/extmod/modtrezorio/modtrezorio.c @@ -11,6 +11,7 @@ #if MICROPY_PY_TREZORIO +#include "modtrezorio-flash.h" #include "modtrezorio-sbu.h" #include "modtrezorio-sdcard.h" #include "modtrezorio-msg.h" @@ -18,6 +19,8 @@ STATIC const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorio) }, + { MP_ROM_QSTR(MP_QSTR_FlashOTP), MP_ROM_PTR(&mod_trezorio_FlashOTP_type) }, + { MP_ROM_QSTR(MP_QSTR_SBU), MP_ROM_PTR(&mod_trezorio_SBU_type) }, { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&mod_trezorio_SDCard_type) }, diff --git a/embed/extmod/modtrezorio/unix-flash-mock.h b/embed/extmod/modtrezorio/unix-flash-mock.h new file mode 100644 index 000000000..5e9c25d87 --- /dev/null +++ b/embed/extmod/modtrezorio/unix-flash-mock.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) Pavol Rusnak, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ + +#include "../../trezorhal/flash.h" + +int flash_init(void) +{ + return 0; +} + +void flash_set_option_bytes(void) +{ +} + +bool flash_unlock(void) +{ + return false; +} + +bool flash_lock(void) +{ + return false; +} + +bool flash_erase_sectors(int start, int end, void (*progress)(uint16_t val)) +{ + return false; +} + +bool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen) +{ + return false; +} + +bool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen) +{ + return false; +} + +bool flash_otp_lock(uint8_t block) +{ + return false; +} + +bool flash_otp_is_locked(uint8_t block) +{ + return false; +} diff --git a/embed/trezorhal/flash.c b/embed/trezorhal/flash.c index 833760176..01f02873f 100644 --- a/embed/trezorhal/flash.c +++ b/embed/trezorhal/flash.c @@ -84,6 +84,17 @@ bool flash_erase_sectors(int start, int end, void (*progress)(uint16_t val)) #define FLASH_OTP_NUM_BLOCKS 16 #define FLASH_OTP_BLOCK_SIZE 32 +bool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen) +{ + if (block >= FLASH_OTP_NUM_BLOCKS || offset + datalen > FLASH_OTP_BLOCK_SIZE) { + return false; + } + for (uint8_t i = 0; i < datalen; i++) { + data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i); + } + return true; +} + bool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen) { if (block >= FLASH_OTP_NUM_BLOCKS || offset + datalen > FLASH_OTP_BLOCK_SIZE) { @@ -103,17 +114,6 @@ bool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t return ret == HAL_OK; } -bool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen) -{ - if (block >= FLASH_OTP_NUM_BLOCKS || offset + datalen > FLASH_OTP_BLOCK_SIZE) { - return false; - } - for (uint8_t i = 0; i < datalen; i++) { - data[i] = *(__IO uint8_t *)(FLASH_OTP_BASE + block * FLASH_OTP_BLOCK_SIZE + offset + i); - } - return true; -} - bool flash_otp_lock(uint8_t block) { if (block >= FLASH_OTP_NUM_BLOCKS) { diff --git a/embed/trezorhal/flash.h b/embed/trezorhal/flash.h index 0816832af..fb0fcc414 100644 --- a/embed/trezorhal/flash.h +++ b/embed/trezorhal/flash.h @@ -25,8 +25,8 @@ bool flash_lock(void); bool flash_erase_sectors(int start, int end, void (*progress)(uint16_t val)); -bool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen); bool flash_otp_read(uint8_t block, uint8_t offset, uint8_t *data, uint8_t datalen); +bool flash_otp_write(uint8_t block, uint8_t offset, const uint8_t *data, uint8_t datalen); bool flash_otp_lock(uint8_t block); bool flash_otp_is_locked(uint8_t block);