diff --git a/micropython/stmhal/Makefile.bootloader b/micropython/stmhal/Makefile.bootloader index a8793f393..aab134781 100644 --- a/micropython/stmhal/Makefile.bootloader +++ b/micropython/stmhal/Makefile.bootloader @@ -58,7 +58,7 @@ CFLAGS += -Iboards/$(BOARD) CFLAGS += -DSTM32_HAL_H='' LDFLAGS = -nostdlib -L $(LD_DIR) -T $(LD_FILE) -Map=$(@:.elf=.map) --cref -LIBS = +LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) # Remove uncalled code from the final image. CFLAGS += -fdata-sections -ffunction-sections @@ -72,9 +72,6 @@ else COPT += -Os -DNDEBUG endif -# uncomment this if you want libgcc -LIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) - SRC_LIB = $(addprefix lib/,\ libc/string0.c \ ) @@ -83,7 +80,7 @@ SRC_C = \ bootloader/basic.c \ bootloader/bootloader.c \ bootloader/crypto.c \ - bootloader/header.c \ + bootloader/sdcard.c \ bootloader/ui.c \ system_stm32.c \ $(wildcard boards/$(BOARD)/*.c) diff --git a/micropython/stmhal/bootloader/bootloader.c b/micropython/stmhal/bootloader/bootloader.c index 06eb23000..ac5346ef6 100644 --- a/micropython/stmhal/bootloader/bootloader.c +++ b/micropython/stmhal/bootloader/bootloader.c @@ -1,13 +1,20 @@ #include STM32_HAL_H +#include + #include "crypto.h" #include "ui.h" #include "display.h" +#include "sdcard.h" + +#define STAGE2_SECTOR 4 +#define STAGE2_START 0x08010000 +#define STAGE2_SIZE (64 * 1024) void SystemClock_Config(void); -int main(void) { - +void periph_init(void) +{ HAL_Init(); SystemClock_Config(); @@ -17,23 +24,92 @@ int main(void) { __GPIOC_CLK_ENABLE(); __GPIOD_CLK_ENABLE(); + sdcard_init(); + display_init(); display_clear(); + display_backlight(255); +} - uint8_t hash[32]; - hash_flash(hash); +void check_sdcard() +{ + if (!sdcard_is_present()) return; - screen_welcome(); + sdcard_power_on(); - uint8_t *pubkey = (uint8_t *)"ThisIsJustAFakePublicKeyForTest!"; - uint8_t *signature = (uint8_t *)"ThisIsJustAFakeSignatureToTestTheVerifyMechanismInTRZRBootloader"; - ed25519_verify(hash, 32, pubkey, signature); + uint64_t cap = sdcard_get_capacity_in_bytes(); + if (cap < SDCARD_BLOCK_SIZE + STAGE2_SIZE) { + sdcard_power_off(); + return; + } + + uint8_t buf[SDCARD_BLOCK_SIZE] __attribute__((aligned(4))); + + sdcard_read_blocks(buf, 0, 1); + + if (!check_header(buf)) { + sdcard_power_off(); + return; + } + + // erase STAGE2_SECTOR + HAL_FLASH_Unlock(); + FLASH_EraseInitTypeDef EraseInitStruct; + __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | + FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); + EraseInitStruct.TypeErase = TYPEERASE_SECTORS; + EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V + EraseInitStruct.Sector = STAGE2_SECTOR; + EraseInitStruct.NbSectors = 1; + uint32_t SectorError = 0; + if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK) { + HAL_FLASH_Lock(); + sdcard_power_off(); + return; + } + + // copy stage 2 from SD card to Flash + uint32_t src; + int block = 0; + int offset = 256; + + for (int i = 0; i < STAGE2_SIZE / 4; i++) { + memcpy(&src, buf + offset, 4); + if (HAL_FLASH_Program(TYPEPROGRAM_WORD, STAGE2_START + i * 4, src) != HAL_OK) { + break; + } + offset += 4; + if (offset == SDCARD_BLOCK_SIZE) { + offset = 0; + block++; + sdcard_read_blocks(buf, block, 1); + } + } + HAL_FLASH_Lock(); + sdcard_power_off(); +} + + +int main(void) { + + periph_init(); + + screen_stage1(); + + check_sdcard(); + + if (check_header((const uint8_t *)STAGE2_START)) { + screen_stage2_jump(); + // TODO: jump to second stage + } + + screen_stage2_invalid(); for (;;) { display_backlight(255); - HAL_Delay(250); + HAL_Delay(950); display_backlight(0); - HAL_Delay(250); + HAL_Delay(50); } return 0; diff --git a/micropython/stmhal/bootloader/crypto.c b/micropython/stmhal/bootloader/crypto.c index c7b5ff153..b29a2f0ca 100644 --- a/micropython/stmhal/bootloader/crypto.c +++ b/micropython/stmhal/bootloader/crypto.c @@ -1,9 +1,11 @@ -#include "crypto.h" +#include +#include "sha2.h" #include "ed25519-donna/ed25519.h" -#include "cmsis/stm32f405xx.h" +#include "crypto.h" +/* void hash_flash(uint8_t hash[SHA256_DIGEST_LENGTH]) { sha256_Raw((const uint8_t *)FLASH_BASE, 1024*1024, hash); @@ -13,3 +15,38 @@ bool ed25519_verify(const uint8_t *msg, uint32_t msglen, uint8_t *pubkey, uint8_ { return (0 == ed25519_sign_open(msg, msglen, *(const ed25519_public_key *)pubkey, *(const ed25519_signature *)signature)); } +*/ + +bool check_header(const uint8_t *data) +{ + uint32_t magic; + memcpy(&magic, data, 4); + if (magic != 0x425A5254) return false; // TRZB + + uint32_t hdrlen; + memcpy(&hdrlen, data + 4, 4); + if (hdrlen != 256) return false; + + uint32_t expiry; + memcpy(&expiry, data + 8, 4); + if (expiry != 0) return false; + + uint32_t codelen; + memcpy(&codelen, data + 12, 4); + if (codelen != 64 * 1024) return false; + + uint32_t version; + memcpy(&version, data + 16, 4); + + // uint8_t reserved[171]; + + uint8_t sigidx; + memcpy(&sigidx, data + 0x00BF, 1); + + uint8_t sig[64]; + memcpy(sig, data + 0x00C0, 64); + + // TODO: check signature + + return true; +} diff --git a/micropython/stmhal/bootloader/crypto.h b/micropython/stmhal/bootloader/crypto.h index 892a421c8..c3019f7d7 100644 --- a/micropython/stmhal/bootloader/crypto.h +++ b/micropython/stmhal/bootloader/crypto.h @@ -4,9 +4,6 @@ #include #include -#include "sha2.h" - -void hash_flash(uint8_t hash[SHA256_DIGEST_LENGTH]); -bool ed25519_verify(const uint8_t *msg, uint32_t msglen, uint8_t *pubkey, uint8_t *signature); +bool check_header(const uint8_t *data); #endif diff --git a/micropython/stmhal/bootloader/header.c b/micropython/stmhal/bootloader/header.c deleted file mode 100644 index 2dba30199..000000000 --- a/micropython/stmhal/bootloader/header.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include "header.h" - -bool read_header(const uint8_t *data, uint32_t *expiry, uint32_t *version, uint8_t *sigidx, uint8_t *sig) -{ - uint32_t magic; - memcpy(&magic, data, 4); - if (magic != 0x425A5254) return false; // TRZB - - uint32_t hdrlen; - memcpy(&hdrlen, data + 4, 4); - if (hdrlen != 256) return false; - - memcpy(expiry, data + 8, 4); - - uint32_t codelen; - memcpy(&codelen, data + 12, 4); - if (codelen != 64 * 1024) return false; - - memcpy(version, data + 16, 4); - - // reserved - - memcpy(sigidx, data + 0x00BF, 1); - - memcpy(sig, data + 0x00C0, 64); - - return true; -} diff --git a/micropython/stmhal/bootloader/header.h b/micropython/stmhal/bootloader/header.h deleted file mode 100644 index 272b46b10..000000000 --- a/micropython/stmhal/bootloader/header.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __BOOTLOADER_HEADER_H__ -#define __BOOTLOADER_HEADER_H__ - -#include -#include - -bool read_header(const uint8_t *data, uint32_t *expiry, uint32_t *version, uint8_t *sigidx, uint8_t *sig); - -#endif diff --git a/micropython/stmhal/bootloader/sdcard.c b/micropython/stmhal/bootloader/sdcard.c new file mode 100644 index 000000000..68be6fec9 --- /dev/null +++ b/micropython/stmhal/bootloader/sdcard.c @@ -0,0 +1,158 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include STM32_HAL_H + +#include + +#include "sdcard.h" + +#define IRQ_PRI_SDIO 4 +#define IRQ_SUBPRI_SDIO 0 + +static SD_HandleTypeDef sd_handle; + +void sdcard_init(void) { + // invalidate the sd_handle + sd_handle.Instance = NULL; + + GPIO_InitTypeDef GPIO_InitStructure; + + // configure SD GPIO + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Alternate = GPIO_AF12_SDIO; + GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + GPIO_InitStructure.Pin = GPIO_PIN_2; + HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); + + // configure the SD card detect pin + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Pin = GPIO_PIN_13; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); +} + +void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { + // enable SDIO clock + __SDIO_CLK_ENABLE(); + + // NVIC configuration for SDIO interrupts + HAL_NVIC_SetPriority(SDIO_IRQn, IRQ_PRI_SDIO, IRQ_SUBPRI_SDIO); + HAL_NVIC_EnableIRQ(SDIO_IRQn); + + // GPIO have already been initialised by sdcard_init +} + +void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { + HAL_NVIC_DisableIRQ(SDIO_IRQn); + __SDIO_CLK_DISABLE(); +} + +bool sdcard_is_present(void) { + return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13); +} + +bool sdcard_power_on(void) { + if (!sdcard_is_present()) { + return false; + } + if (sd_handle.Instance) { + return true; + } + + // SD device interface configuration + sd_handle.Instance = SDIO; + sd_handle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + sd_handle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + sd_handle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE; + sd_handle.Init.BusWide = SDIO_BUS_WIDE_1B; + sd_handle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; + sd_handle.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV; + + // init the SD interface, with retry if it's not ready yet + HAL_SD_CardInfoTypedef cardinfo; + for (int retry = 10; HAL_SD_Init(&sd_handle, &cardinfo) != SD_OK; retry--) { + if (retry == 0) { + goto error; + } + HAL_Delay(50); + } + + // configure the SD bus width for wide operation + if (HAL_SD_WideBusOperation_Config(&sd_handle, SDIO_BUS_WIDE_4B) != SD_OK) { + HAL_SD_DeInit(&sd_handle); + goto error; + } + + return true; + +error: + sd_handle.Instance = NULL; + return false; +} + +void sdcard_power_off(void) { + if (!sd_handle.Instance) { + return; + } + HAL_SD_DeInit(&sd_handle); + sd_handle.Instance = NULL; +} + +uint64_t sdcard_get_capacity_in_bytes(void) { + if (sd_handle.Instance == NULL) { + return 0; + } + HAL_SD_CardInfoTypedef cardinfo; + HAL_SD_Get_CardInfo(&sd_handle, &cardinfo); + return cardinfo.CardCapacity; +} + +void SDIO_IRQHandler(void) { + HAL_SD_IRQHandler(&sd_handle); +} + +uint32_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { + // check that SD card is initialised + if (sd_handle.Instance == NULL) { + return SD_ERROR; + } + + HAL_SD_ErrorTypedef err = SD_OK; + + // check that dest pointer is aligned on a 4-byte boundary + if (((uint32_t)dest & 3) != 0) { + return SD_ERROR; + } + + err = HAL_SD_ReadBlocks_BlockNumber(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks); + + return err; +} diff --git a/micropython/stmhal/bootloader/sdcard.h b/micropython/stmhal/bootloader/sdcard.h new file mode 100644 index 000000000..ce6dac2af --- /dev/null +++ b/micropython/stmhal/bootloader/sdcard.h @@ -0,0 +1,42 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __BOOTLOADER_SDCARD_H__ +#define __BOOTLOADER_SDCARD_H__ + +#include + +// this is a fixed size and should not be changed +#define SDCARD_BLOCK_SIZE (512) + +void sdcard_init(void); +bool sdcard_is_present(void); +bool sdcard_power_on(void); +void sdcard_power_off(void); +uint64_t sdcard_get_capacity_in_bytes(void); +uint32_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); + +#endif diff --git a/micropython/stmhal/bootloader/ui.c b/micropython/stmhal/bootloader/ui.c index faf94eb54..9df1f3602 100644 --- a/micropython/stmhal/bootloader/ui.c +++ b/micropython/stmhal/bootloader/ui.c @@ -1,10 +1,20 @@ #include "ui.h" #include "display.h" -#define ui_WHITE 0xFFFF -#define ui_BLACK 0x0000 - -void screen_welcome(void) +void screen_stage1(void) { - display_text(0, 240, "bootloader", 10, FONT_MONO, ui_WHITE, ui_BLACK); + display_clear(); + display_text(0, 240, "BL stage 1", -1, FONT_MONO, ui_WHITE, ui_BLACK); +} + +void screen_stage2_jump(void) +{ + display_clear(); + display_text(0, 240, "BL stage 2 jump", -1, FONT_MONO, ui_WHITE, ui_BLACK); +} + +void screen_stage2_invalid(void) +{ + display_clear(); + display_text(0, 240, "BL stage 2 invalid", -1, FONT_MONO, ui_WHITE, ui_BLACK); } diff --git a/micropython/stmhal/bootloader/ui.h b/micropython/stmhal/bootloader/ui.h index 9f324bfd9..a95c784ce 100644 --- a/micropython/stmhal/bootloader/ui.h +++ b/micropython/stmhal/bootloader/ui.h @@ -1,6 +1,11 @@ #ifndef __BOOTLOADER_UI_H__ #define __BOOTLOADER_UI_H__ -void screen_welcome(void); +#define ui_WHITE 0xFFFF +#define ui_BLACK 0x0000 + +void screen_stage1(void); +void screen_stage2_jump(void); +void screen_stage2_invalid(void); #endif