From 828ba7b5b01f9997a2f8e63e2e5f19d4a3f607af Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Thu, 21 Feb 2019 09:52:28 +0100 Subject: [PATCH] bootloader: enable MPU, introduce delays to USB stack --- SConscript.bootloader | 1 + embed/bootloader/main.c | 6 +++- embed/firmware/main.c | 2 +- embed/trezorhal/common.c | 21 ++++++++++++- embed/trezorhal/common.h | 9 ++++-- embed/trezorhal/mpu.c | 55 ++++++++++++++++++++++++++++++++-- embed/trezorhal/mpu.h | 4 ++- embed/trezorhal/stm32.c | 3 +- embed/trezorhal/usb.c | 10 +++++-- embed/trezorhal/usb_hid-impl.h | 5 ++-- embed/trezorhal/usb_vcp-impl.h | 6 ++-- embed/trezorhal/usbd_def.h | 5 +++- embed/unix/common.h | 4 +-- 13 files changed, 110 insertions(+), 21 deletions(-) diff --git a/SConscript.bootloader b/SConscript.bootloader index 1d7953765..ec0ba8462 100644 --- a/SConscript.bootloader +++ b/SConscript.bootloader @@ -83,6 +83,7 @@ SOURCE_TREZORHAL = [ 'embed/trezorhal/image.c', 'embed/trezorhal/flash.c', 'embed/trezorhal/mini_printf.c', + 'embed/trezorhal/mpu.c', 'embed/trezorhal/rng.c', 'embed/trezorhal/stm32.c', 'embed/trezorhal/touch.c', diff --git a/embed/bootloader/main.c b/embed/bootloader/main.c index 61fa8df1c..f48d72cdd 100644 --- a/embed/bootloader/main.c +++ b/embed/bootloader/main.c @@ -21,6 +21,7 @@ #include #include "common.h" +#include "mpu.h" #include "image.h" #include "flash.h" #include "display.h" @@ -224,6 +225,8 @@ static void check_bootloader_version(void) int main(void) { + mpu_config_bootloader(); + main_start: display_clear(); @@ -379,9 +382,10 @@ main_start: ui_fadeout(); } - // mpu_config(); + // mpu_config_firmware(); // jump_to_unprivileged(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE); + mpu_config_off(); jump_to(FIRMWARE_START + vhdr.hdrlen + IMAGE_HEADER_SIZE); return 0; diff --git a/embed/firmware/main.c b/embed/firmware/main.c index 5d517fcc0..e0b5f2caf 100644 --- a/embed/firmware/main.c +++ b/embed/firmware/main.c @@ -54,7 +54,7 @@ int main(void) #if TREZOR_MODEL == T check_and_replace_bootloader(); // Enable MPU - mpu_config(); + mpu_config_firmware(); #endif // Init peripherals diff --git a/embed/trezorhal/common.c b/embed/trezorhal/common.c index c3afd9261..d0dc28f8d 100644 --- a/embed/trezorhal/common.c +++ b/embed/trezorhal/common.c @@ -29,7 +29,8 @@ #include "stm32f4xx_ll_utils.h" -void shutdown(void); +// from util.s +extern void shutdown(void); #define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00) @@ -115,6 +116,24 @@ void hal_delay(uint32_t ms) HAL_Delay(ms); } +void delay_random(void) +{ + int wait = rng_get() & 0xff; + volatile int i = 0; + volatile int j = wait; + while (i < wait) { + if (i + j != wait) { + shutdown(); + } + ++i; + --j; + } + // Double-check loop completion. + if (i != wait || j != 0) { + shutdown(); + } +} + // reference RM0090 section 35.12.1 Figure 413 #define USB_OTG_HS_DATA_FIFO_RAM (USB_OTG_HS_PERIPH_BASE + 0x20000U) #define USB_OTG_HS_DATA_FIFO_SIZE (4096U) diff --git a/embed/trezorhal/common.h b/embed/trezorhal/common.h index f886739e0..3fac1dec6 100644 --- a/embed/trezorhal/common.h +++ b/embed/trezorhal/common.h @@ -26,11 +26,14 @@ #define XSTR(s) STR(s) #define STR(s) #s +#ifndef MIN_8bits +#define MIN_8bits(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? (_a & 0xFF) : (_b & 0xFF); }) +#endif #ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MIN(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) #endif #ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MAX(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) #endif void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func); @@ -40,6 +43,8 @@ void __attribute__((noreturn)) error_shutdown(const char *line1, const char *lin void hal_delay(uint32_t ms); +void delay_random(void); + void clear_otg_hs_memory(void); extern uint32_t __stack_chk_guard; diff --git a/embed/trezorhal/mpu.c b/embed/trezorhal/mpu.c index 17fc68cc2..05e045335 100644 --- a/embed/trezorhal/mpu.c +++ b/embed/trezorhal/mpu.c @@ -27,10 +27,61 @@ #define MPU_SUBREGION_DISABLE(X) ((X) << MPU_RASR_SRD_Pos) -void mpu_config(void) +void mpu_config_off(void) { // Disable MPU HAL_MPU_Disable(); +} + +void mpu_config_bootloader(void) +{ + // Disable MPU + HAL_MPU_Disable(); + + // Note: later entries overwrite previous ones + + // Flash (0x08000000 - 0x081FFFFF, 2 MiB, read-write) + MPU->RBAR = FLASH_BASE | MPU_RBAR_VALID_Msk | MPU_REGION_NUMBER0; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_2MB | LL_MPU_REGION_PRIV_RO_URO; + + // Flash (0x0800C000 - 0x0800FFFF, 16 KiB, no access) + MPU->RBAR = FLASH_BASE | 0xC000 | MPU_RBAR_VALID_Msk | MPU_REGION_NUMBER1; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; + + // Flash (0x0810C000 - 0x0810FFFF, 16 KiB, no access) + MPU->RBAR = FLASH_BASE | 0x10C000 | MPU_RBAR_VALID_Msk | MPU_REGION_NUMBER2; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_FLASH | LL_MPU_REGION_SIZE_16KB | LL_MPU_REGION_NO_ACCESS; + + // SRAM (0x20000000 - 0x2002FFFF, 192 KiB = 256 KiB except 2/8 at end, read-write, execute never) + MPU->RBAR = SRAM_BASE | MPU_RBAR_VALID_Msk | MPU_REGION_NUMBER3; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | LL_MPU_REGION_SIZE_256KB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk | MPU_SUBREGION_DISABLE(0xC0); + + // Peripherals (0x40000000 - 0x5FFFFFFF, read-write, execute never) + // External RAM (0x60000000 - 0x7FFFFFFF, read-write, execute never) + MPU->RBAR = PERIPH_BASE | MPU_RBAR_VALID_Msk | MPU_REGION_NUMBER4; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_PERIPH | LL_MPU_REGION_SIZE_1GB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk; + +#ifdef STM32F427xx + // CCMRAM (0x10000000 - 0x1000FFFF, read-write, execute never) + MPU->RBAR = CCMDATARAM_BASE | MPU_RBAR_VALID_Msk | MPU_REGION_NUMBER5; + MPU->RASR = MPU_RASR_ENABLE_Msk | MPU_RASR_ATTR_SRAM | LL_MPU_REGION_SIZE_64KB | LL_MPU_REGION_FULL_ACCESS | MPU_RASR_XN_Msk; +#elif STM32F405xx + // no CCMRAM +#else +#error Unsupported MCU +#endif + + // Enable MPU + HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); +} + + +void mpu_config_firmware(void) +{ + // Disable MPU + HAL_MPU_Disable(); + + // Note: later entries overwrite previous ones /* // Boardloader (0x08000000 - 0x0800FFFF, 64 KiB, read-only, execute never) @@ -77,5 +128,5 @@ void mpu_config(void) #endif // Enable MPU - HAL_MPU_Enable(0); + HAL_MPU_Enable(LL_MPU_CTRL_HARDFAULT_NMI); } diff --git a/embed/trezorhal/mpu.h b/embed/trezorhal/mpu.h index 2a7ccf6fc..c7c136849 100644 --- a/embed/trezorhal/mpu.h +++ b/embed/trezorhal/mpu.h @@ -20,6 +20,8 @@ #ifndef __MPU_H__ #define __MPU_H__ -void mpu_config(void); +void mpu_config_off(void); +void mpu_config_bootloader(void); +void mpu_config_firmware(void); #endif diff --git a/embed/trezorhal/stm32.c b/embed/trezorhal/stm32.c index 41de13aaf..5c74fd350 100644 --- a/embed/trezorhal/stm32.c +++ b/embed/trezorhal/stm32.c @@ -79,7 +79,8 @@ void SysTick_Handler(void) uwTick++; } -void shutdown(void); +// from util.s +extern void shutdown(void); void PVD_IRQHandler(void) { diff --git a/embed/trezorhal/usb.c b/embed/trezorhal/usb.c index 57dff2b0f..03ac2cd5b 100644 --- a/embed/trezorhal/usb.c +++ b/embed/trezorhal/usb.c @@ -314,6 +314,7 @@ static uint8_t usb_class_deinit(USBD_HandleTypeDef *dev, uint8_t cfg_idx) { #define USB_WEBUSB_URL_SCHEME_HTTPS 1 static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *req) { + delay_random(); if (((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_CLASS) && ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_STANDARD) && ((req->bmRequest & USB_REQ_TYPE_MASK) != USB_REQ_TYPE_VENDOR)) { @@ -330,7 +331,7 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re USB_WEBUSB_URL_SCHEME_HTTPS, // uint8_t bScheme 't', 'r', 'e', 'z', 'o', 'r', '.', 'i', 'o', '/', 's', 't', 'a', 'r', 't', // char URL[] }; - USBD_CtlSendData(dev, UNCONST(webusb_url), MIN(req->wLength, sizeof(webusb_url))); + USBD_CtlSendData(dev, UNCONST(webusb_url), MIN_8bits(req->wLength, sizeof(webusb_url))); return USBD_OK; } else { USBD_CtlError(dev, req); @@ -354,7 +355,7 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompatibleId 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // reserved }; - USBD_CtlSendData(dev, UNCONST(winusb_wcid), MIN(req->wLength, sizeof(winusb_wcid))); + USBD_CtlSendData(dev, UNCONST(winusb_wcid), MIN_8bits(req->wLength, sizeof(winusb_wcid))); return USBD_OK; } else { USBD_CtlError(dev, req); @@ -380,7 +381,7 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re 0x50, 0x00, 0x00, 0x00, // dwPropertyDataLength '{', 0x00, 'c', 0x00, '6', 0x00, 'c', 0x00, '3', 0x00, '7', 0x00, '4', 0x00, 'a', 0x00, '6', 0x00, '-', 0x00, '2', 0x00, '2', 0x00, '8', 0x00, '5', 0x00, '-', 0x00, '4', 0x00, 'c', 0x00, 'b', 0x00, '8', 0x00, '-', 0x00, 'a', 0x00, 'b', 0x00, '4', 0x00, '3', 0x00, '-', 0x00, '1', 0x00, '7', 0x00, '6', 0x00, '4', 0x00, '7', 0x00, 'c', 0x00, 'e', 0x00, 'a', 0x00, '5', 0x00, '0', 0x00, '3', 0x00, 'd', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00, // propertyData }; - USBD_CtlSendData(dev, UNCONST(winusb_guid), MIN(req->wLength, sizeof(winusb_guid))); + USBD_CtlSendData(dev, UNCONST(winusb_guid), MIN_8bits(req->wLength, sizeof(winusb_guid))); return USBD_OK; } else { USBD_CtlError(dev, req); @@ -410,6 +411,7 @@ static uint8_t usb_class_setup(USBD_HandleTypeDef *dev, USBD_SetupReqTypedef *re } static uint8_t usb_class_data_in(USBD_HandleTypeDef *dev, uint8_t ep_num) { + delay_random(); for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { switch (usb_ifaces[i].type) { case USB_IFACE_TYPE_HID: @@ -429,6 +431,7 @@ static uint8_t usb_class_data_in(USBD_HandleTypeDef *dev, uint8_t ep_num) { } static uint8_t usb_class_data_out(USBD_HandleTypeDef *dev, uint8_t ep_num) { + delay_random(); for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { switch (usb_ifaces[i].type) { case USB_IFACE_TYPE_HID: @@ -448,6 +451,7 @@ static uint8_t usb_class_data_out(USBD_HandleTypeDef *dev, uint8_t ep_num) { } static uint8_t usb_class_sof(USBD_HandleTypeDef *dev) { + delay_random(); for (int i = 0; i < USBD_MAX_NUM_INTERFACES; i++) { switch (usb_ifaces[i].type) { case USB_IFACE_TYPE_VCP: diff --git a/embed/trezorhal/usb_hid-impl.h b/embed/trezorhal/usb_hid-impl.h index 084342557..7b20c9bee 100644 --- a/embed/trezorhal/usb_hid-impl.h +++ b/embed/trezorhal/usb_hid-impl.h @@ -254,7 +254,6 @@ static void usb_hid_class_deinit(USBD_HandleTypeDef *dev, usb_hid_state_t *state } static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state, USBD_SetupReqTypedef *req) { - switch (req->bmRequest & USB_REQ_TYPE_MASK) { // Class request @@ -302,11 +301,11 @@ static int usb_hid_class_setup(USBD_HandleTypeDef *dev, usb_hid_state_t *state, switch (req->wValue >> 8) { case USB_DESC_TYPE_HID: - USBD_CtlSendData(dev, UNCONST(&state->desc_block->hid), MIN(req->wLength, sizeof(state->desc_block->hid))); + USBD_CtlSendData(dev, UNCONST(&state->desc_block->hid), MIN_8bits(req->wLength, sizeof(state->desc_block->hid))); return USBD_OK; case USB_DESC_TYPE_REPORT: - USBD_CtlSendData(dev, UNCONST(state->report_desc), MIN(req->wLength, state->report_desc_len)); + USBD_CtlSendData(dev, UNCONST(state->report_desc), MIN_8bits(req->wLength, state->report_desc_len)); return USBD_OK; default: diff --git a/embed/trezorhal/usb_vcp-impl.h b/embed/trezorhal/usb_vcp-impl.h index 28aa63875..9f8d81e2a 100644 --- a/embed/trezorhal/usb_vcp-impl.h +++ b/embed/trezorhal/usb_vcp-impl.h @@ -364,13 +364,13 @@ static int usb_vcp_class_setup(USBD_HandleTypeDef *dev, usb_vcp_state_t *state, if ((req->bmRequest & USB_REQ_DIR_MASK) == USB_REQ_DIR_D2H) { if (req->bRequest == USB_CDC_GET_LINE_CODING) { - USBD_CtlSendData(dev, UNCONST(&line_coding), MIN(req->wLength, sizeof(line_coding))); + USBD_CtlSendData(dev, UNCONST(&line_coding), MIN_8bits(req->wLength, sizeof(line_coding))); } else { - USBD_CtlSendData(dev, state->cmd_buffer, MIN(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); + USBD_CtlSendData(dev, state->cmd_buffer, MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); } } else { // USB_REQ_DIR_H2D if (req->wLength > 0) { - USBD_CtlPrepareRx(dev, state->cmd_buffer, MIN(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); + USBD_CtlPrepareRx(dev, state->cmd_buffer, MIN_8bits(req->wLength, USB_CDC_MAX_CMD_PACKET_LEN)); } } diff --git a/embed/trezorhal/usbd_def.h b/embed/trezorhal/usbd_def.h index d3c3e5b99..e3da6243d 100644 --- a/embed/trezorhal/usbd_def.h +++ b/embed/trezorhal/usbd_def.h @@ -263,9 +263,12 @@ typedef struct _USBD_HandleTypeDef #define LOBYTE(x) ((uint8_t)(x & 0x00FF)) #define HIBYTE(x) ((uint8_t)((x & 0xFF00) >>8)) +#ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) - +#endif #if defined ( __GNUC__ ) #ifndef __weak diff --git a/embed/unix/common.h b/embed/unix/common.h index fd6c95949..e0bc6dde8 100644 --- a/embed/unix/common.h +++ b/embed/unix/common.h @@ -27,10 +27,10 @@ #define STR(s) #s #ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MIN(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a < _b ? _a : _b; }) #endif #ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define MAX(a, b) ({ typeof(a) _a = (a); typeof(b) _b = (b); _a > _b ? _a : _b; }) #endif void __attribute__((noreturn)) __fatal_error(const char *expr, const char *msg, const char *file, int line, const char *func);