From 647cde94bb694a846cb1d4ecfa37485816ced8bf Mon Sep 17 00:00:00 2001 From: kYc0o Date: Fri, 20 Jan 2017 18:42:48 +0100 Subject: [PATCH 01/43] cpu/stm32f1/include: add cpu defines for FW slots --- cpu/stm32f1/include/cpu_conf.h | 117 +++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/cpu/stm32f1/include/cpu_conf.h b/cpu/stm32f1/include/cpu_conf.h index fed1ee08e916..552675ea4a22 100644 --- a/cpu/stm32f1/include/cpu_conf.h +++ b/cpu/stm32f1/include/cpu_conf.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 INRIA + * Copyright (C) 2013, 2016 Inria * Copyright (C) 2014 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser General @@ -18,6 +18,7 @@ * * @author Alaeddine Weslati * @author Hauke Petersen + * @author Francisco Acosta */ #ifndef CPU_CONF_H @@ -35,13 +36,121 @@ extern "C" { #endif +/** + * @brief Flash page configuration + * @{ + */ +#define FLASHPAGE_SIZE (2048U) + +#if defined(CPU_MODEL_STM32F103CB) || defined(CPU_MODEL_STM32F103RB) +#define FLASHPAGE_NUMOF (64U) +#elif defined(CPU_MODEL_STM32F103RE) +#define FLASHPAGE_NUMOF (256U) +#endif +/** @} */ + +/* + * @brief Offset to reset handler on VTOR + */ +#define VTOR_RESET_HANDLER 0x4 + +#if defined(CPU_MODEL_STM32F103RE) +/* + * @brief Flash partitioning for FW slots + * @{ + */ + +#ifndef FW_METADATA_SPACE +#define FW_METADATA_SPACE (0x100) +#endif + +#define MAX_FW_SLOTS (2) +#define FW_SLOT_PAGES (120) +#define BOOTLOADER_SPACE (0x4000) +#define FW_SLOT_SIZE FLASHPAGE_SIZE * FW_SLOT_PAGES +#define FW_SLOT_1 FLASH_BASE + BOOTLOADER_SPACE +#define FW_SLOT_1_END FW_SLOT_1 + FW_SLOT_SIZE +#define FW_SLOT_1_PAGE (8) +#define FW_SLOT_2 FW_SLOT_1_END +#define FW_SLOT_2_END FW_SLOT_2 + FW_SLOT_SIZE +#define FW_SLOT_2_PAGE (128) + +#ifdef FW_SLOTS + #if FW_SLOT == 1 + #define CURRENT_FIRMWARE_ADDR FW_SLOT_1 + #define CURRENT_FIRMWARE_PAGE FW_SLOT_1_PAGE + #define CURRENT_FIRMWARE_END FW_SLOT_1_END + #endif + + #if FW_SLOT == 2 + #define CURRENT_FIRMWARE_ADDR FW_SLOT_2 + #define CURRENT_FIRMWARE_PAGE FW_SLOT_2_PAGE + #define CURRENT_FIRMWARE_END FW_SLOT_2_END + #endif + +#endif /* FW_SLOTS */ + +/** @} */ + +/** + * @brief Get FW internal address for a given slot + * + * @param[in] slot FW slot + * + * @return FW slot address + */ +static inline uint32_t get_slot_address(uint8_t slot) +{ + switch (slot) { + case 1: + return FW_SLOT_1; + break; + + case 2: + return FW_SLOT_2; + break; + } + + return 0; +} + +/** + * @brief Get internal page for a given slot + * + * @param[in] slot FW slot + * + * @return FW slot page + */ +static inline uint32_t get_slot_page(uint8_t slot) +{ + switch (slot) { + case 1: + return FW_SLOT_1_PAGE; + break; + + case 2: + return FW_SLOT_2_PAGE; + break; + } + + return 0; +} + +#endif /* defined(CPU_MODEL_STM32F103RE) */ +/** @} */ + /** * @brief ARM Cortex-M specific CPU configuration * @{ */ -#define CPU_DEFAULT_IRQ_PRIO (1U) -#define CPU_IRQ_NUMOF (60U) -#define CPU_FLASH_BASE FLASH_BASE +#define CPU_DEFAULT_IRQ_PRIO (1U) +#define CPU_IRQ_NUMOF (60U) + +#ifdef FW_SLOTS +#define CPU_FLASH_BASE (CURRENT_FIRMWARE_ADDR + FW_METADATA_SPACE) +#else +#define CPU_FLASH_BASE FLASH_BASE +#endif /** @} */ /** From 529c71cd04bef31f6b8e221a5f2e070f8e173179 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 30 Nov 2016 15:34:54 +0100 Subject: [PATCH 02/43] sys: Add fw_slots module --- sys/Makefile | 4 + sys/fw_slots/Makefile | 1 + sys/fw_slots/fw_slots.c | 511 ++++++++++++++++++++++++++++++++++++++++ sys/include/fw_slots.h | 278 ++++++++++++++++++++++ 4 files changed, 794 insertions(+) create mode 100644 sys/fw_slots/Makefile create mode 100644 sys/fw_slots/fw_slots.c create mode 100644 sys/include/fw_slots.h diff --git a/sys/Makefile b/sys/Makefile index d25fb28e334c..6b5eba345524 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -120,6 +120,10 @@ ifneq (,$(filter devfs,$(USEMODULE))) DIRS += fs/devfs endif +ifneq (,$(filter fw_slots,$(USEMODULE))) + DIRS += fw_slots +endif + DIRS += $(dir $(wildcard $(addsuffix /Makefile, ${USEMODULE}))) include $(RIOTBASE)/Makefile.base diff --git a/sys/fw_slots/Makefile b/sys/fw_slots/Makefile new file mode 100644 index 000000000000..9c9ae9884ad6 --- /dev/null +++ b/sys/fw_slots/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base \ No newline at end of file diff --git a/sys/fw_slots/fw_slots.c b/sys/fw_slots/fw_slots.c new file mode 100644 index 000000000000..83c95693fd4e --- /dev/null +++ b/sys/fw_slots/fw_slots.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2016, Mark Solters . + * 2016, Francisco Acosta + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * @file + * @author Mark Solters + * @author Francisco Acosta + * + */ + +#include +#include + +#include +#include "fw_slots.h" +#include "cpu_conf.h" +#include "irq.h" +#include "periph/flashpage.h" +#include "hashes/sha256.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define HASH_BUF (1024) + +static uint8_t firmware_buffer[HASH_BUF]; + +/** + * @brief Read internal flash to a buffer at specific address. + * + * @param[in] address - Address to be read. + * @param[in] count - count in bytes. + * + * @param[out] data_buffer - The buffer filled with the read information. + * + */ +static void int_flash_read(uint8_t *data_buffer, uint32_t address, uint32_t count) +{ + uint8_t *read_addres = (uint8_t*)address; + while (count--) { + *data_buffer++ = *read_addres++; + } +} + +int validate_int_fw_slot(uint8_t fw_slot) +{ + FW_metadata_t metadata; + int res; + unsigned char n[crypto_box_NONCEBYTES]; + unsigned char hash[NACL_SIGN]; + + if (verify_int_fw_slot(fw_slot) != 0) { + printf("[fw_slots] ERROR verification for slot %i failed!\n", fw_slot); + return -1; + } + + if (get_int_fw_slot_metadata(fw_slot, &metadata) != 0) { + printf("[fw_slots] ERROR cannot get metadata from slot %i!\n", fw_slot); + return -1; + } + + memset(hash, 0, sizeof(hash)); + + printf("Decrypting metadata.shash...\n"); + + res = crypto_box_open(hash, metadata.shash, NACL_SIGN, n, server_pkey, firmware_skey); + if (res) { + printf("Decryption failed.\n"); + return -1; + } else { + printf("Decryption successful! verifying..."); + for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { + if (metadata.hash[i] != (hash[i + crypto_box_ZEROBYTES])) { + printf("[fw_slots] ERROR incorrect decrypted hash!\n"); + return -1; + } + } + } + + printf("[fw_slots] FW slot %i successfully validated!\n", fw_slot); + + return 0; +} + +uint32_t get_slot_fw_address(uint8_t fw_slot) +{ + return get_slot_address(fw_slot); +} + +uint32_t get_slot_fw_page(uint8_t fw_slot) +{ + return get_slot_page(fw_slot); +} + +void print_metadata(FW_metadata_t *metadata) +{ + printf("Firmware Size: %ld\n", metadata->size); + printf("Firmware Version: %#x\n", metadata->version); + printf("Firmware UUID: %#lx\n", metadata->uuid); + printf("Firmware HASH: "); + for (unsigned long i = 0; i < sizeof(metadata->hash); i++) { + printf("%02x ", metadata->hash[i]); + } + printf("\n"); + printf("Firmware signed HASH: "); + for (unsigned long i = 0; i < sizeof(metadata->shash); i++) { + printf("%02x ", metadata->shash[i]); + } + printf("\n"); +} + +int get_int_metadata(uint8_t fw_slot_page, FW_metadata_t *fw_metadata) +{ + uint32_t fw_address; + + fw_address = fw_slot_page * FLASHPAGE_SIZE + CPU_FLASH_BASE; + + DEBUG("[fw_slots] Getting internal metadata on page %d at address %#lx\n", + fw_slot_page, fw_address); + int_flash_read((uint8_t*)fw_metadata, fw_address, sizeof(FW_metadata_t)); + + return 0; +} + +int get_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) +{ + /* + * TODO + */ + + return 0; +} + +int get_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) +{ + uint32_t page; + + DEBUG("[fw_slots] Getting internal FW slot %d metadata\n", fw_slot); + if (fw_slot > MAX_FW_SLOTS || fw_slot == 0) { + printf("[fw_slots] FW slot not valid, should be <= %d and > 0\n", + MAX_FW_SLOTS); + return -1; + } + + page = get_slot_fw_page(fw_slot); + + return get_int_metadata(page, fw_slot_metadata); +} + +int overwrite_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) +{ + /* + * TODO + */ + return 0; +} + + + +int overwrite_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) +{ + /* + * TODO + */ + return 0; +} + +int backup_golden_image(void) +{ + /* + * TODO + */ + return 0; +} + +int verify_int_fw_slot(uint8_t fw_slot) +{ + FW_metadata_t fw_metadata; + uint32_t fw_image_address; + uint32_t address; + uint16_t rest; + sha256_context_t sha256_ctx; + uint8_t hash[SHA256_DIGEST_LENGTH]; + int parts = 0, i = 0; + + /* Determine the external flash address corresponding to the FW slot */ + if (fw_slot > MAX_FW_SLOTS || fw_slot == 0) { + printf("[fw_slots] FW slot not valid, should be <= %d and > 0\n", + MAX_FW_SLOTS); + return -1; + } + + /* Read the metadata of the corresponding FW slot */ + fw_image_address = get_slot_fw_address(fw_slot); + + if (get_int_fw_slot_metadata(fw_slot, &fw_metadata) == 0) { + print_metadata(&fw_metadata); + } else { + printf("[fw_slots] ERROR cannot get slot metadata.\n"); + } + + printf("Verifying slot %d at 0x%lx \n", fw_slot, fw_image_address); + + address = fw_image_address; + address += FW_METADATA_SPACE; + sha256_init(&sha256_ctx); + + parts = fw_metadata.size / sizeof(firmware_buffer); + rest = fw_metadata.size % sizeof(firmware_buffer); + + while (parts) { + int_flash_read(firmware_buffer, address, sizeof(firmware_buffer)); + sha256_update(&sha256_ctx, firmware_buffer, sizeof(firmware_buffer)); + address += sizeof(firmware_buffer); + parts--; + } + + int_flash_read(firmware_buffer, address, rest); + sha256_update(&sha256_ctx, firmware_buffer, rest); + sha256_final(&sha256_ctx, hash); + + for (i = 0; i < sizeof(hash); i++) { + if (hash[i] != fw_metadata.hash[i]) { + printf("[fw_slots] hash verification failed!\n"); + return -1; + } + } + + return 0; +} + +int validate_fw_metadata(FW_metadata_t *metadata) +{ + /* Is the FW slot erased? + * First, we check to see if every byte in the metadata is 0xFF. + * If this is the case, this metadata is "erased" and therefore we assume + * the FW slot to be empty. + */ + int erased = 1; + uint8_t *metadata_ptr = (uint8_t*)metadata; + int b = FW_METADATA_LENGTH; + + while (b--) { + if (*metadata_ptr++ != 0xff) { + /* We encountered a non-erased byte. + * There's some non-trivial data here. + */ + erased = 0; + break; + } + } + + /* If the FW slot is erased, it's not valid! No more work to do here. */ + if (erased) { + return 0; + } + + /* If we get this far, all metadata bytes were cleared (0xff) */ + return 0; +} + +int find_matching_int_fw_slot(uint16_t version) +{ + int matching_slot = -1; /* Assume there is no matching FW slot. */ + + /* Iterate through each of the FW slots. */ + for (int slot = 1; slot <= MAX_FW_SLOTS; slot++) { + + /* Get the metadata of the current FW slot. */ + FW_metadata_t fw_slot_metadata; + if(get_int_fw_slot_metadata(slot, &fw_slot_metadata) == 0) { + print_metadata(&fw_slot_metadata); + } else { + printf("[fw_slots] ERROR cannot get slot metadata.\n"); + } + + /* Is this slot empty? If yes, skip. */ + if (validate_fw_metadata(&fw_slot_metadata) == false) { + continue; + } + + /* Does this slot's FW version match our search parameter? */ + if (fw_slot_metadata.version == version) { + matching_slot = slot; + break; + } + } + + if (matching_slot == -1) { + printf("[fw_slots] No FW slot matches Firmware v%i\n", version); + } else { + printf("[fw_slots] FW slot #%i matches Firmware v%i\n", matching_slot, + version); + } + + return matching_slot; +} + +int find_empty_int_fw_slot(void) +{ + /* Iterate through each of the MAX_FW_SLOTS internal slots. */ + for (int slot = 1; slot <= MAX_FW_SLOTS; slot++) { + + /* Get the metadata of the current FW slot. */ + FW_metadata_t fw_slot_metadata; + + if(get_int_fw_slot_metadata(slot, &fw_slot_metadata) == 0) { + print_metadata(&fw_slot_metadata); + } else { + printf("[fw_slots] ERROR cannot get slot metadata.\n"); + } + + /* Is this slot invalid? If yes, let's treat it as empty. */ + if (validate_fw_metadata(&fw_slot_metadata) == false) { + return slot; + } + } + + printf("[fw_slots] Could not find any empty FW slots!" + "\nSearching for oldest FW slot...\n"); + /* + * If execution goes this far, no empty slot was found. Now, we look for + * the oldest FW slot instead. + */ + return find_oldest_int_fw_image(); +} + +int find_oldest_int_fw_image(void) +{ + /* The oldest firmware should be the v0 */ + int oldest_fw_slot = 1; + uint16_t oldest_firmware_version = 0; + + /* Iterate through each of the MAX_FW_SLOTS internal slots. */ + for (int slot = 1; slot <= MAX_FW_SLOTS; slot++) { + /* Get the metadata of the current FW slot. */ + FW_metadata_t fw_slot_metadata; + + if(get_int_fw_slot_metadata(slot, &fw_slot_metadata) == 0) { + print_metadata(&fw_slot_metadata); + } else { + printf("[fw_slots] ERROR cannot get slot metadata.\n"); + } + + /* Is this slot populated? If not, skip. */ + if (validate_fw_metadata(&fw_slot_metadata) == false) { + continue; + } + + /* Is this the oldest image we've found thus far? */ + if (oldest_firmware_version) { + if (fw_slot_metadata.version < oldest_firmware_version) { + oldest_fw_slot = slot; + oldest_firmware_version = fw_slot_metadata.version; + } + } else { + oldest_fw_slot = slot; + oldest_firmware_version = fw_slot_metadata.version; + } + } + + printf("[fw_slots] Oldest FW slot: #%u; Firmware v%u\n", oldest_fw_slot, + oldest_firmware_version); + + return oldest_fw_slot; +} + +int find_newest_int_fw_image(void) +{ + /* At first, we only assume knowledge of version v0 */ + int newest_fw_slot = 0; + uint16_t newest_firmware_version = 0; + + /* Iterate through each of the MAX_FW_SLOTS. */ + for (int slot = 1; slot <= MAX_FW_SLOTS ; slot++) { + /* Get the metadata of the current FW slot. */ + FW_metadata_t fw_slot_metadata; + + if(get_int_fw_slot_metadata(slot, &fw_slot_metadata) == 0) { + print_metadata(&fw_slot_metadata); + } else { + printf("[fw_slots] ERROR cannot get slot metadata.\n"); + } + + /* Is this slot populated? If not, skip. */ + if (validate_fw_metadata( &fw_slot_metadata) == false) { + continue; + } + + /* Is this the newest non-Golden Image image we've found thus far? */ + if ( fw_slot_metadata.version > newest_firmware_version ) { + newest_fw_slot = slot; + newest_firmware_version = fw_slot_metadata.version; + } + } + + printf("Newest FW slot: #%u; Firmware v%u\n", newest_fw_slot, + newest_firmware_version); + + return newest_fw_slot; +} + +int erase_int_fw_image(uint8_t fw_slot) +{ + /* Get page address of the fw_slot in internal flash */ + uint32_t fw_image_base_address; + /* Get the page where the fw_slot is located */ + uint8_t slot_page; + + if (fw_slot > MAX_FW_SLOTS || fw_slot == 0) { + printf("[fw_slots] FW slot not valid, should be <= %d and > 0\n", + MAX_FW_SLOTS); + return -1; + } + + fw_image_base_address = get_slot_fw_address(fw_slot); + + printf("[fw_slots] Erasing FW slot %u [%#lx, %#lx]...\n", fw_slot, + fw_image_base_address, + fw_image_base_address + (FW_SLOT_PAGES * FLASHPAGE_SIZE) - 1); + + slot_page = get_slot_fw_page(fw_slot); + + /* Erase each page in the FW internal slot! */ + for (int page = slot_page; page < slot_page + FW_SLOT_PAGES; page++) { + DEBUG("[fw_slots] Erasing page %d\n", page); + flashpage_write(page, NULL); + } + + printf("[fw_slots] Erase successful\n"); + + return 0; +} + +int update_firmware(uint8_t fw_slot) +{ + /* + * TODO + */ + return 0; +} + +int store_firmware_data( uint32_t ext_address, uint8_t *data, size_t data_length ) +{ + /* + * TODO + */ + return 0; +} + +/* + * _estack pointer needed to reset PSP position + */ +extern uint32_t _estack; + +void jump_to_image(uint32_t destination_address) +{ + if (destination_address) { + /* + * Only add the metadata length offset if destination_address is NOT 0! + * (Jumping to 0x0 is used to reboot the device) + */ + destination_address += FW_METADATA_SPACE; + } + + /* Disable IRQ */ + (void)irq_disable(); + + /* Move PSP to the end of the stack */ + __set_PSP((uint32_t)&_estack); + + /* Move to the second pointer on VTOR (reset_handler_default) */ + destination_address += VTOR_RESET_HANDLER; + + printf("Addr: 0x%lx\n", destination_address); + + /* Load the destination address */ + __asm("LDR R0, [%[dest]]"::[dest]"r"(destination_address)); + /* Make sure the Thumb State bit is set. */ + __asm("ORR R0, #1"); + /* Branch execution */ + __asm("BX R0"); +} diff --git a/sys/include/fw_slots.h b/sys/include/fw_slots.h new file mode 100644 index 000000000000..36d896698be2 --- /dev/null +++ b/sys/include/fw_slots.h @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2016, Mark Solters + * 2016, Francisco Acosta + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * @defgroup sys_fw_slots Firmware Slots + * @ingroup sys + * + * @file + * @brief FW Image R/W and Verification + * + * @author Mark Solters + * @author Francisco Acosta + */ + +#ifndef FW_SLOTS_H +#define FW_SLOTS_H + +#include "hashes/sha256.h" +#include "tweetnacl.h" + +/* + * FW_METADATA_LENGTH: + * This is just the size of the FW_metadata_t struct, which is 4-byte + * aligned. We use 104 bytes currently, so this struct will be 104 bytes. + */ +#define FW_METADATA_LENGTH sizeof(FW_metadata_t) + +#define NACL_SIGN (SHA256_DIGEST_LENGTH + crypto_box_ZEROBYTES) + +typedef struct FW_metadata { + uint8_t hash[SHA256_DIGEST_LENGTH]; /* SHA256 Hash of firmware image */ + uint8_t shash[NACL_SIGN]; /* Signed SHA256 */ + uint32_t size; /* Size of firmware image */ + uint32_t uuid; /* Integer representing unique firmware ID */ + uint16_t version; /* Integer representing firmware version */ +} FW_metadata_t; + +extern const unsigned char server_pkey[]; +extern const unsigned char firmware_skey[]; + +/** + * @brief Print formatted FW image metadata to STDIO. + * + * @param[in] metadata Metadata struct to fill with firmware metadata + * + */ +void print_metadata(FW_metadata_t *metadata); + +/** + * @brief Validate internal FW slot as a secure firmware + * + * @param[in] fw_slot The FW slot to be validated. + * + * @return 0 on success or error code + */ +int validate_int_fw_slot(uint8_t fw_slot); + +/** + * @brief Get the internal metadata belonging to an FW slot in internal + * flash. + * + * @param[in] fw_slot The FW slot to be read for metadata. + * + * @param[in] *fw_slot_metadata Pointer to the FW_metadata_t struct where + * the metadata is to be written. + * + * @return 0 on success or error code + */ +int get_int_metadata(uint8_t fw_slot_page, FW_metadata_t *fw_metadata); + +/** + * @brief Get the metadata belonging to an FW slot in external flash. + * + * @param[in] fw_slot The FW slot to be read for metadata. + * + * @param[in] *fw_slot_metadata Pointer to the FW_metadata_t struct where + * the metadata is to be written. + * + * @return 0 on success or error code + */ +int get_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); + +/** + * @brief Get the metadata belonging to an FW slot in internal flash. + * + * @param[in] fw_slot The FW slot to be read for metadata. + * + * @param[in] *fw_slot_metadata Pointer to the FW_metadata_t struct where + * the metadata is to be written. + * + * @return 0 on success or error code + */ +int get_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); + +/** + * @brief Get the address corresponding to a given slot + * + * @param[in] fw_slot The FW slot to get the address. + * + * + * @return 0 on success or error code + */ +uint32_t get_slot_fw_address(uint8_t fw_slot); + +/** + * @brief Get the page corresponding to a given slot + * + * @param[in] fw_slot The FW slot to get the page. + * + * + * @return 0 on success or error code + */ +uint32_t get_slot_fw_page(uint8_t fw_slot); + +/** + * @brief Write new metadata to a specific FW slot in internal flash. + * + * @param fw_slot The FW slot to be modified. + * + * @param *fw_slot_metadata Pointer to the new FW_metadata_t data. + * + * @return 0 on success or error code + */ +int overwrite_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); + +/** + * @brief Write new metadata to a specific FW slot in external flash. + * + * @param fw_slot The FW slot to be modified. + * + * @param *fw_slot_metadata Pointer to the new FW_metadata_t data. + * + * @return 0 on success or error code + */ +int overwrite_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); + +/** + * @brief Copy the current firmware into FW slot 0 as the "Golden Image" + * + * @return 0 for success or error code + */ +int backup_golden_image(void); + +/** + * @brief Given an FW slot, verify the firmware content against the metadata. + * If everything is fine, update the metadata to indicate this FW slot + * is valid. + * + * @param[in] fw_slot - FW slot index to verify. (1-3) + * + * @return 0 for success or error code + */ +int verify_int_fw_slot(uint8_t fw_slot); + +/** + * @brief Returns true only if the metadata provided indicates the FW slot + * is populated and valid. + * + * @param[in] *metadata FW metadata to be validated + * + * @return True if the FW slot is populated and valid. Otherwise, false. + */ +int validate_fw_metadata(FW_metadata_t *metadata); + +/** + * @brief Find a FW slot containing firmware matching the supplied + * firmware version number. Will only find the first matching + * slot. + * + * @param[in] version FW slot version. + * + * @return The FW slot index of the matching FW slot. Return -1 in the event + * of no match. + */ +int find_matching_int_fw_slot(uint16_t version); + +/** + * @brief Find the first empty FW download slot. Failing this, find the slot + * with the most out-of-date firmware version. + * + * @return The FW slot index of the empty/oldest FW slot. This will never be + * 0 because the Golden Image should never be erased. + */ +int find_empty_int_fw_slot(void); + +/** + * @brief Find the FW slot containing the most out-of-date firmware version. + * FW slots are in external flash. + * + * @return The FW slot index of the oldest firmware version. + */ +int find_oldest_int_fw_image(void); + +/** + * @brief Find the FW slot containing the most recent firmware version. + * FW slots are in external flash. + * + * @return The FW slot index of the newest firmware version. + */ +int find_newest_int_fw_image(void); + +/** + * @brief Clear an FW slot in external flash. + * + * @param[in] fw_slot The FW slot index of the firmware image to be copied. + * + * @return 0 or error code + */ +int erase_int_fw_image(uint8_t fw_slot); + +/** + * @brief Overwrite firmware located in internal flash with the firmware + * stored in an external flash FW slot. + * + * @param[in] fw_slot The FW slot index of the firmware image to be copied. + * 0 = "Golden Image" backup, aka factory restore + * 1, 2, 3 = FW Download slots + * + * @return 0 or error code + */ +int update_firmware(uint8_t fw_slot); + +/** + * @brief Store firmware data in external flash at the specified + * address. + * + * @param[in] ext_address External flash address to begin writing data. + * + * @param[in] data Pointer to the data buffer to be written. + * Note: page_data can be larger than 4096 bytes, but + * only the first 4096 bytes will be written! + * + * @return 0 or error code + */ +int store_firmware_data(uint32_t ext_address, uint8_t *data, size_t data_length); + +/** + * @brief Begin executing another firmware binary located in internal flash. + * + * @param[in] destination_address Internal flash address of the vector table + * for the firmware binary that is to be booted + * into. Since this FW lib prepends metadata + * to each binary, the true VTOR start address + * will be FW_METADATA_SPACE bytes past this + * address. + * + */ +void jump_to_image(uint32_t destination_address); + +#endif /* FW_SLOTS_H */ From 0b6d336922d2b08906c938b8e8e73b0c370cca15 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 23 Jan 2017 23:57:06 +0100 Subject: [PATCH 03/43] Makefile.dep: add dependencies for fw_slots --- Makefile.dep | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile.dep b/Makefile.dep index 9037185244a4..c558a586c4f9 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -611,6 +611,11 @@ ifneq (,$(filter vfs,$(USEMODULE))) endif endif +ifneq (,$(filter fw_slots,$(USEMODULE))) + FEATURES_REQUIRED += periph_flashpage + USEMODULE += hashes +endif + # include package dependencies -include $(USEPKG:%=$(RIOTPKG)/%/Makefile.dep) From 019812f36ac5209e5c67d5be4fc8d1af669396ad Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 24 Oct 2016 17:49:38 +0200 Subject: [PATCH 04/43] examples: Add bootloader example --- examples/bootloader/Makefile | 27 ++++++ examples/bootloader/README.md | 1 + examples/bootloader/main.c | 177 ++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 examples/bootloader/Makefile create mode 100644 examples/bootloader/README.md create mode 100644 examples/bootloader/main.c diff --git a/examples/bootloader/Makefile b/examples/bootloader/Makefile new file mode 100644 index 000000000000..f0eb30c303c8 --- /dev/null +++ b/examples/bootloader/Makefile @@ -0,0 +1,27 @@ +# name of your application +APPLICATION = bootloader + +# If no BOARD is found in the environment, use this default: +BOARD ?= iotlab-m3 + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# Comment this out to disable code in RIOT that does safety checking +# which is not needed in a production environment but helps in the +# development process: +#CFLAGS += -DDEVELHELP + +# Mark this example as the bootloader +BOOTLOADER = 1 + +# Change this to 0 show compiler invocation lines by default: +QUIET ?= 1 + +# Use fw_slots module to manage images on ROM +USEMODULE += fw_slots + +# TweetNaCl needs a lot of stack +CFLAGS += '-DTHREAD_STACKSIZE_MAIN=(THREAD_STACKSIZE_DEFAULT + 2048)' + +include $(RIOTBASE)/Makefile.include diff --git a/examples/bootloader/README.md b/examples/bootloader/README.md new file mode 100644 index 000000000000..30404ce4c546 --- /dev/null +++ b/examples/bootloader/README.md @@ -0,0 +1 @@ +TODO \ No newline at end of file diff --git a/examples/bootloader/main.c b/examples/bootloader/main.c new file mode 100644 index 000000000000..54830cc39dec --- /dev/null +++ b/examples/bootloader/main.c @@ -0,0 +1,177 @@ +/* + * Copyright (C)2016 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup examples + * @{ + * + * @file + * @brief Default bootloader application to manage FW slots + * + * @author Francisco Acosta + * + * @} + */ + +#include +#include +#include + +#include "thread.h" +#include "shell.h" +#include "shell_commands.h" +#include "fw_slots.h" +#include "cpu_conf.h" + +static int cmd_lsimg(int argc, char **argv) +{ + (void)argc; + (void)argv; + + FW_metadata_t fw_metadata; + + for (uint8_t i = 1; i <= MAX_FW_SLOTS; i++) { + if (get_int_fw_slot_metadata(i, &fw_metadata) == 0) { + printf("Metadata slot %d:\n", i); + print_metadata(&fw_metadata); + } else { + printf("ERROR: Cannot retrieve metadata.\n"); + } + } + + return 0; +} + +static int cmd_get_metadata(int argc, char **argv) +{ + uint8_t slot; + FW_metadata_t fw_metadata; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return -1; + } + + slot = atoi(argv[1]); + + if (get_int_fw_slot_metadata(slot, &fw_metadata) == 0) { + printf("Metadata slot %d\n", slot); + print_metadata(&fw_metadata); + return 0; + } else { + printf("ERROR: Cannot retrieve metadata from slot %d.\n", slot); + return -1; + } + + return 0; +} + +static int cmd_verify(int argc, char **argv) +{ + uint8_t slot; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return -1; + } + + slot = atoi(argv[1]); + + if (verify_int_fw_slot(slot) == 0) { + printf("Verified slot %d\n", slot); + return 0; + } else { + return -1; + } + + return 0; +} + +static int cmd_validate(int argc, char **argv) +{ + uint8_t slot; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return -1; + } + + slot = atoi(argv[1]); + + if (validate_int_fw_slot(slot) == 0) { + printf("Validated slot %d\n", slot); + return 0; + } else { + return -1; + } + + return 0; +} + +static int cmd_erase_slot(int argc, char**argv) +{ + uint8_t slot; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return -1; + } + + slot = atoi(argv[1]); + + return erase_int_fw_image(slot); +} + +static int cmd_jump(int argc, char **argv) +{ + uint32_t address; + + uint8_t slot; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return -1; + } + + slot = atoi(argv[1]); + + /*if (validate_int_fw_slot(slot) == 0) { + printf("Validated slot %d\n", slot); + } else { + printf("Slot %u not valid!\n", slot); + return -1; + }*/ + + address = get_slot_fw_address(slot); + + jump_to_image(address); + + return 0; +} + +static const shell_command_t shell_commands[] = { + { "lsimg", "List the available firmwares on ROM", cmd_lsimg }, + { "get_metadata", "Get metadata from slot", cmd_get_metadata }, + { "verify", "Verify consistency (sha256) of slot", cmd_verify }, + { "validate", "Validates authenticity of slot", cmd_validate }, + { "erase", "Erase slot *WARNING use with caution*", cmd_erase_slot }, + { "jump", "Jump to specific FW slot (cause reset)", cmd_jump }, + { NULL, NULL, NULL } +}; + +int main(void) +{ + (void) puts("Welcome to RIOT bootloader!"); + + /* run the shell */ + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + + /* Should never happen */ + return 0; +} From aa235e7e25cbf2033ebb049087a681939ff208e1 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 24 Oct 2016 16:04:16 +0200 Subject: [PATCH 05/43] cpu/stm32f1/ldscripts: add bootloader and slots linker scripts --- .../ldscripts/stm32f103re-bootloader.ld | 30 ++++++++++++++++++ cpu/stm32f1/ldscripts/stm32f103re-slots.c | 31 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 cpu/stm32f1/ldscripts/stm32f103re-bootloader.ld create mode 100644 cpu/stm32f1/ldscripts/stm32f103re-slots.c diff --git a/cpu/stm32f1/ldscripts/stm32f103re-bootloader.ld b/cpu/stm32f1/ldscripts/stm32f103re-bootloader.ld new file mode 100644 index 000000000000..02d4af946efc --- /dev/null +++ b/cpu/stm32f1/ldscripts/stm32f103re-bootloader.ld @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup cpu_stm32f1 + * @{ + * + * @file + * @brief Memory definitions for the STM32F103RE + * + * @author Hauke Petersen + * + * @} + */ + +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K + ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K + cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 +} + +_cpuid_address = ORIGIN(cpuid); + +INCLUDE cortexm_base.ld diff --git a/cpu/stm32f1/ldscripts/stm32f103re-slots.c b/cpu/stm32f1/ldscripts/stm32f103re-slots.c new file mode 100644 index 000000000000..c1ab60c90bc2 --- /dev/null +++ b/cpu/stm32f1/ldscripts/stm32f103re-slots.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup cpu_stm32f1 + * @{ + * + * @file + * @brief Memory definitions for different FW slots on + * the STM32F103RE + * + * @author Hauke Petersen + * + * @} + */ + +MEMORY +{ + rom (rx) : ORIGIN = (FW_IMAGE_OFFSET + FW_METADATA_SPACE), LENGTH = FW_IMAGE_LENGTH + ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K + cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 +} + +_cpuid_address = ORIGIN(cpuid); + +INCLUDE cortexm_base.ld From 2ac7dc70c35b3df88eefd603be2765633c9c8a05 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 24 Oct 2016 15:47:15 +0200 Subject: [PATCH 06/43] Makefile.include: add FW slots and Bootlaoder specific rules --- Makefile.include | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Makefile.include b/Makefile.include index 77f021992dd9..d1ffa6ebc995 100644 --- a/Makefile.include +++ b/Makefile.include @@ -11,6 +11,7 @@ RIOTBOARD ?= $(RIOTBASE)/boards RIOTPKG ?= $(RIOTBASE)/pkg RIOTPROJECT ?= $(shell git rev-parse --show-toplevel 2>/dev/null || pwd) GITCACHE ?= $(RIOTBASE)/dist/tools/git/git-cache +FW_METADATA ?= $(RIOTBASE)/dist/tools/firmware_metadata APPDIR ?= $(CURDIR) BINDIRBASE ?= $(APPDIR)/bin BINDIR ?= $(BINDIRBASE)/$(BOARD) @@ -26,6 +27,7 @@ override RIOTBOARD := $(abspath $(RIOTBOARD)) override RIOTPKG := $(abspath $(RIOTPKG)) override RIOTPROJECT := $(abspath $(RIOTPROJECT)) override GITCACHE := $(abspath $(GITCACHE)) +override FW_METADATA := $(abspath $(FW_METADATA)) override APPDIR := $(abspath $(APPDIR)) override BINDIRBASE := $(abspath $(BINDIRBASE)) override BINDIR := $(abspath $(BINDIR)) @@ -261,6 +263,10 @@ BASELIBS += $(APPDEPS) ELFFILE ?= $(BINDIR)/$(APPLICATION).elf HEXFILE ?= $(ELFFILE:.elf=.hex) +ifeq ($(FW_SLOTS),1) +BINFILE = $(ELFFILE:.elf=.bin) +endif + # variables used to compile and link c++ CPPMIX ?= $(if $(wildcard *.cpp),1,) @@ -275,11 +281,20 @@ else ## make script for your application. Build RIOT-base here! all: ..compiler-check ..build-message $(RIOTBUILD_CONFIG_HEADER_C) $(USEPKG:%=${BINDIR}/%.a) $(APPDEPS) $(Q)DIRS="$(DIRS)" "$(MAKE)" -C $(APPDIR) -f $(RIOTBASE)/Makefile.application +ifeq ($(FW_SLOTS),1) + $(GENERATE_LDSCRIPT) +endif ifeq (,$(RIOTNOLINK)) ifeq ($(BUILDOSXNATIVE),1) $(Q)$(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) -o $(ELFFILE) $$(find $(BASELIBS) -size +8c) $(LINKFLAGS) $(LINKFLAGPREFIX)-no_pie else $(Q)$(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) -o $(ELFFILE) $(LINKFLAGPREFIX)--start-group $(BASELIBS) -lm $(LINKFLAGPREFIX)--end-group $(LINKFLAGPREFIX)-Map=$(BINDIR)/$(APPLICATION).map $(LINKFLAGPREFIX)--cref $(LINKFLAGS) +endif +ifeq ($(FW_SLOTS),1) + $(STRIP) --strip-unneeded --strip-debug $(ELFFILE) + $(OBJCOPY) -O binary $(ELFFILE) $(BINFILE) + $(FW_METADATA)/bin/./generate-metadata $(BINFILE) $(VERSION) $(UUID) + srec_cat $(BINFILE) -binary -offset $(FW_METADATA_SPACE) firmware-metadata.bin -binary -o $(BINDIR)/slot-image-$(UUID)-$(VERSION).bin -binary endif $(Q)$(SIZE) $(ELFFILE) $(Q)$(OBJCOPY) $(OFLAGS) $(ELFFILE) $(HEXFILE) @@ -294,6 +309,12 @@ endif # BUILD_IN_DOCKER ..build-message: @$(COLOR_ECHO) '${COLOR_GREEN}Building application "$(APPLICATION)" for "$(BOARD)" with MCU "$(MCU)".${COLOR_RESET}' +ifeq ($(FW_SLOTS),1) + @$(COLOR_ECHO) '${COLOR_RED}This is a build for FW slot $(FW_SLOT).${COLOR_RESET}' +endif +ifeq ($(BOOTLOADER),1) + @$(COLOR_ECHO) '${COLOR_RED}This is a Bootloader build.${COLOR_RESET}' +endif @$(COLOR_ECHO) # add extra include paths for packages in $(USEMODULE) From 52e0c8bc48ae3f997e1a1662a61cadbfaaf78311 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 24 Oct 2016 16:15:14 +0200 Subject: [PATCH 07/43] cpu/stm32f1/ldscripts: add gitignore to ignore C linker files --- cpu/stm32f1/ldscripts/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 cpu/stm32f1/ldscripts/.gitignore diff --git a/cpu/stm32f1/ldscripts/.gitignore b/cpu/stm32f1/ldscripts/.gitignore new file mode 100644 index 000000000000..dfde6fe8c3fc --- /dev/null +++ b/cpu/stm32f1/ldscripts/.gitignore @@ -0,0 +1 @@ +/stm32f103re-slots.ld From 675c879992f70da2856e178b1841ce1e5672a1e1 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 24 Oct 2016 15:50:35 +0200 Subject: [PATCH 08/43] cpu/Makefile.include.cortexm_common: add rules for linking FW slots and bootloader images --- cpu/Makefile.include.cortexm_common | 18 ++++++++++++++++++ cpu/Makefile.include.gnu | 1 + 2 files changed, 19 insertions(+) diff --git a/cpu/Makefile.include.cortexm_common b/cpu/Makefile.include.cortexm_common index e46b85157638..0e4469d3f5ae 100644 --- a/cpu/Makefile.include.cortexm_common +++ b/cpu/Makefile.include.cortexm_common @@ -15,6 +15,24 @@ export CFLAGS_OPT ?= -Os export CFLAGS += $(CFLAGS_CPU) $(CFLAGS_LINK) $(CFLAGS_DBG) $(CFLAGS_OPT) export ASFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) + +# If the FW_SLOTS flag is set, we will generate a linker script at compile-time +# reflecting the FW_IMAGE_OFFSET and FW_IMAGE_LENGTH values defined in the +# target project's Makefile. +ifeq ($(FW_SLOTS),1) +FWDEFINES = -DFW_IMAGE_OFFSET=$(FW_IMAGE_OFFSET) -DFW_IMAGE_LENGTH=$(FW_IMAGE_LENGTH) \ + -DFW_METADATA_SPACE=$(FW_METADATA_SPACE) +CFLAGS += $(FWDEFINES) +GENERATE_LDSCRIPT = $(Q)$(LINK) -P -E $(FWDEFINES) $(RIOTCPU)/$(CPU)/ldscripts/$(CPU_MODEL)-slots.c \ + -o $(RIOTCPU)/$(CPU)/ldscripts/$(CPU_MODEL)-slots.ld +LINKER_SCRIPT = $(CPU_MODEL)-slots.ld +endif + +# If we compile a bootloader, set the correct linker script +ifeq ($(BOOTLOADER),1) +export LINKER_SCRIPT = $(CPU_MODEL)-bootloader.ld +endif + export LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ldscripts -L$(RIOTCPU)/cortexm_common/ldscripts export LINKER_SCRIPT ?= $(CPU_MODEL).ld export LINKFLAGS += -T$(LINKER_SCRIPT) -Wl,--fatal-warnings diff --git a/cpu/Makefile.include.gnu b/cpu/Makefile.include.gnu index ea61b4cc7628..88cca20e604c 100644 --- a/cpu/Makefile.include.gnu +++ b/cpu/Makefile.include.gnu @@ -16,3 +16,4 @@ export OBJCOPY = true endif export OBJDUMP = $(PREFIX)objdump export DBG = $(GDBPREFIX)gdb +export STRIP = $(PREFIX)strip From e692a478bef1c82c157b41d899d690c52617fa6f Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 30 Nov 2016 16:01:51 +0100 Subject: [PATCH 09/43] cpu/stm32f1: avoid clock initialisation for FW slots --- cpu/stm32f1/cpu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cpu/stm32f1/cpu.c b/cpu/stm32f1/cpu.c index c2d465a64054..c531c4518e50 100644 --- a/cpu/stm32f1/cpu.c +++ b/cpu/stm32f1/cpu.c @@ -96,14 +96,19 @@ #endif #endif +#ifndef FW_SLOTS static void clk_init(void); +#endif void cpu_init(void) { /* initialize the Cortex-M core */ cortexm_init(); + /* initialize system clocks */ +#ifndef FW_SLOTS clk_init(); +#endif /* trigger static peripheral initialization */ periph_init(); } @@ -111,6 +116,7 @@ void cpu_init(void) /** * @brief Configure the clock system of the stm32f1 */ +#ifndef FW_SLOTS static void clk_init(void) { /* Reset the RCC clock configuration to the default reset state(for debug purpose) */ @@ -162,3 +168,4 @@ static void clk_init(void) while ((RCC->CR & RCC_CR_HSIRDY) != 0) {} #endif } +#endif From 2778f72f57623c1f5f193adb365309b6cfb52f2f Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 30 Nov 2016 15:42:10 +0100 Subject: [PATCH 10/43] dist/tools: Add firmware metadata generator --- dist/tools/firmware_metadata/.gitignore | 3 + dist/tools/firmware_metadata/Makefile | 31 +++ dist/tools/firmware_metadata/README.md | 33 ++++ .../firmware_metadata/generate-metadata.c | 183 ++++++++++++++++++ dist/tools/firmware_metadata/randombytes.c | 47 +++++ 5 files changed, 297 insertions(+) create mode 100644 dist/tools/firmware_metadata/.gitignore create mode 100644 dist/tools/firmware_metadata/Makefile create mode 100644 dist/tools/firmware_metadata/README.md create mode 100644 dist/tools/firmware_metadata/generate-metadata.c create mode 100644 dist/tools/firmware_metadata/randombytes.c diff --git a/dist/tools/firmware_metadata/.gitignore b/dist/tools/firmware_metadata/.gitignore new file mode 100644 index 000000000000..54b488b3e122 --- /dev/null +++ b/dist/tools/firmware_metadata/.gitignore @@ -0,0 +1,3 @@ +/generate-metadata +/git-fetch-tweetnacl +tweetnacl \ No newline at end of file diff --git a/dist/tools/firmware_metadata/Makefile b/dist/tools/firmware_metadata/Makefile new file mode 100644 index 000000000000..1298859382f1 --- /dev/null +++ b/dist/tools/firmware_metadata/Makefile @@ -0,0 +1,31 @@ +RIOTBASE := ../../.. +RIOT_INCLUDE = $(RIOTBASE)/sys/include +TWEETNACL_INCLUDE := tweetnacl +SHA256_DIR := $(RIOTBASE)/sys/hashes +SHA256_INCLUDE := $(RIOT_INCLUDE)/hashes +TWEETNACL_DIR := tweetnacl +TWEETNACL_SRC := $(TWEETNACL_DIR)/tweetnacl.c randombytes.c +METADATA_SRC := generate-metadata.c $(SHA256_DIR)/sha256.c $(TWEETNACL_SRC) +METADATA_HDR := $(RIOT_INCLUDE)/fw_slots.h $(RIOT_INCLUDE)/hashes/sha256.h $(TWEETNACL_INCLUDE)/tweetnacl.h +GITCACHE = ../git/git-cache +TWEETNACL_URL = https://github.com/RIOT-OS/tweetnacl.git +TWEETNACL_VERSION = 7ea05c7098a16c87fa66e9166ce301666f3f2623 + +CFLAGS += -g -O3 -Wall -Wextra -pedantic -std=c99 + +all: bin bin/generate-metadata + +bin: + mkdir bin + +git-fetch-tweetnacl: + rm -Rf $(TWEETNACL_DIR) + mkdir -p $(TWEETNACL_DIR) + $(GITCACHE) clone "$(TWEETNACL_URL)" "$(TWEETNACL_VERSION)" "$(TWEETNACL_DIR)" + touch $@ + +bin/generate-metadata: git-fetch-tweetnacl + $(CC) $(CFLAGS) -I$(RIOT_INCLUDE) -I$(TWEETNACL_INCLUDE) $(METADATA_SRC) -o $@ + +clean: + rm -rf bin/generate-metadata diff --git a/dist/tools/firmware_metadata/README.md b/dist/tools/firmware_metadata/README.md new file mode 100644 index 000000000000..b5e21c7ec5c5 --- /dev/null +++ b/dist/tools/firmware_metadata/README.md @@ -0,0 +1,33 @@ +# Metadata generator for firmware verification +This program will generate a binary file containing a metadata structure as +follows: + +```c +typedef struct FW_metadata { + uint8_t hash[SHA256_DIGEST_LENGTH]; /* SHA256 Hash of firmware image */ + uint8_t shash[NACL_SIGN]; /* Signed SHA256 */ + uint32_t size; /* Size of firmware image */ + uint32_t uuid; /* Integer representing unique firmware ID */ + uint16_t version; /* Integer representing firmware version */ +} FW_metadata_t; +``` + +This structure will be filled with the data obtained from the firmware. + +## Usage +To use, you should call `generate-metadata` with the following arguments: + +```console +./generate-metadata +``` + +Where: + +_:_ The firmware in binary format + +_:_ The firmware version in 16-bit HEX + +__ Unique ID for the application in 32-bit HEX + +The results will be printed if the operation is successful, and a binary +called "firmware-metadata.bin" will be created. diff --git a/dist/tools/firmware_metadata/generate-metadata.c b/dist/tools/firmware_metadata/generate-metadata.c new file mode 100644 index 000000000000..ff222363e218 --- /dev/null +++ b/dist/tools/firmware_metadata/generate-metadata.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016, Mark Solters . + * 2016, Francisco Acosta + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * @ingroup FW + * @file + * @brief Meta-data generation for FW images + * + * @author Mark Solters + * @author Francisco Acosta + */ + +#include +#include +#include +#include + +#include "fw_slots.h" +#include "tweetnacl/tweetnacl.h" +#include "hashes/sha256.h" + +/* Input firmware .bin file */ +FILE *firmware_bin; + +/* Output metadata .bin file */ +FILE *metadata_bin; + +/* Pointer to firmware's public key */ +FILE *firmware_pk; + +/* Pointer to server's secret key */ +FILE *server_sk; + +/* Keys buffers */ +static unsigned char firmware_pkey[crypto_box_PUBLICKEYBYTES]; +static unsigned char server_skey[crypto_box_SECRETKEYBYTES]; + +/* Crypto helpers */ +static const unsigned char n[crypto_box_NONCEBYTES]; +static unsigned char m[NACL_SIGN]; + +uint32_t firmware_size = 0; + +int main(int argc, char *argv[]) +{ + FW_metadata_t metadata; + sha256_context_t firmware_sha256; + uint8_t output_buffer[sizeof(FW_metadata_t)]; + int bytes_read = 0; + uint8_t firmware_buffer[1024]; + + (void)argc; + + if (!argv[1]) { + printf("Please provide a .bin file to perform SHA256 on as the first argument.\n"); + return -1; + } + + if (!argv[2]) { + printf("Please provide a 16-bit hex firmware version integer as the second argument.\n"); + return -1; + } + + if (!argv[3]) { + printf("Please provide a 32-bit hex UUID integer as the third argument.\n"); + return -1; + } + + /* (1) Open the firmware .bin file */ + firmware_bin = fopen(argv[1], "r"); + + sha256_init(&firmware_sha256); + + while((bytes_read = fread(firmware_buffer, 1, sizeof(firmware_buffer), firmware_bin))) { + sha256_update(&firmware_sha256, firmware_buffer, bytes_read); + firmware_size += bytes_read; + } + sha256_final(&firmware_sha256, metadata.hash); + + printf("Firmware bytes read: %u\n", firmware_size); + + /* Close the .bin file. */ + fclose(firmware_bin); + + printf("Encrypting using firmware_pkey.pub ...\n"); + printf("Reading firmware public key...\n"); + firmware_pk = fopen("firmware_pkey.pub", "r"); + if (firmware_pk != NULL) { + size_t size = fread(firmware_pkey, 1, sizeof(firmware_pkey), firmware_pk); + printf("Read %zu bytes from firmware_pkey.pub\n", size); + fclose(firmware_pk); + } else { + printf("ERROR! Cannot open firmware public key\n"); + return -1; + } + + printf("Reading server secret key \"server_skey\"...\n"); + server_sk = fopen("server_skey", "r"); + if (server_sk != NULL) { + size_t size = fread(server_skey, 1, sizeof(server_skey), server_sk); + printf("Read %zu bytes from server_skey\n", size); + fclose(server_sk); + } else { + printf("ERROR! Cannot open server secret key\n"); + return -1; + } + + memset(metadata.shash, 0, NACL_SIGN); + memset(m, 0, crypto_box_ZEROBYTES); + memcpy(m + crypto_box_ZEROBYTES, metadata.hash, NACL_SIGN - crypto_box_ZEROBYTES); + + crypto_box(metadata.shash, m, NACL_SIGN, n, firmware_pkey, server_skey); + + /* Generate FW image metadata */ + + metadata.size = firmware_size; + sscanf(argv[2], "%xu", (unsigned int *)&(metadata.version)); + sscanf(argv[3], "%xu", &(metadata.uuid)); + memcpy(output_buffer, (uint8_t*)&metadata, sizeof(FW_metadata_t)); + + printf("Firmware Size: %d\n", metadata.size); + printf("Firmware Version: %#x\n", metadata.version); + printf("Firmware UUID: %#x\n", metadata.uuid); + printf("Firmware HASH: "); + for (unsigned long i = 0; i < sizeof(metadata.hash); i++) { + printf("%02x ", metadata.hash[i]); + } + printf("\n"); + printf("Firmware signed HASH: "); + for (unsigned long i = 0; i < sizeof(metadata.shash); i++) { + printf("%02x ", metadata.shash[i]); + } + printf("\n"); + + /* Open the output firmware .bin file */ + metadata_bin = fopen("firmware-metadata.bin", "w"); + + /* Write the metadata */ + printf("Metadata size: %lu\n", sizeof(FW_metadata_t)); + fwrite(output_buffer, sizeof(output_buffer), 1, metadata_bin); + + /* 0xff spacing until firmware binary starts */ + uint8_t blank_buffer[256 - sizeof(FW_metadata_t)]; + + for (unsigned long b = 0; b < sizeof(blank_buffer); b++) { + blank_buffer[b] = 0xff; + } + + fwrite(blank_buffer, sizeof(blank_buffer), 1, metadata_bin); + + /* Close the metadata file */ + fclose(metadata_bin); + + return 0; +} diff --git a/dist/tools/firmware_metadata/randombytes.c b/dist/tools/firmware_metadata/randombytes.c new file mode 100644 index 000000000000..9623da948436 --- /dev/null +++ b/dist/tools/firmware_metadata/randombytes.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 Francisco Acosta + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include +#include +#include +#include +#include + +static void seed_rng(void) +{ + int fp = open("/dev/random", O_RDONLY); + unsigned seed; + unsigned pos = 0; + + if (fp == -1) { + abort(); + } + + while (pos < sizeof(seed)) { + int amt = read(fp, (char*)&seed + pos, sizeof(seed) - pos); + + if (amt <= 0) { + abort(); + } + + pos += amt; + } + + srand(seed); + close(fp); +} + +void randombytes(uint8_t *target, uint64_t n) +{ + seed_rng(); + + while (n--) { + *target++ = rand(); + } +} From fda0cd08a3821cec8755388defb6dc6c560c2c7c Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 4 Jan 2017 16:24:55 +0100 Subject: [PATCH 11/43] dist/tools: add NaCl key generator --- dist/tools/nacl_key_generator/.gitignore | 2 + dist/tools/nacl_key_generator/Makefile | 28 ++++ dist/tools/nacl_key_generator/README.md | 13 ++ .../nacl_key_generator/generate-nacl-keys.c | 148 ++++++++++++++++++ dist/tools/nacl_key_generator/randombytes.c | 47 ++++++ 5 files changed, 238 insertions(+) create mode 100644 dist/tools/nacl_key_generator/.gitignore create mode 100644 dist/tools/nacl_key_generator/Makefile create mode 100644 dist/tools/nacl_key_generator/README.md create mode 100644 dist/tools/nacl_key_generator/generate-nacl-keys.c create mode 100644 dist/tools/nacl_key_generator/randombytes.c diff --git a/dist/tools/nacl_key_generator/.gitignore b/dist/tools/nacl_key_generator/.gitignore new file mode 100644 index 000000000000..6f47d3a1fe46 --- /dev/null +++ b/dist/tools/nacl_key_generator/.gitignore @@ -0,0 +1,2 @@ +/git-fetch-tweetnacl +tweetnacl \ No newline at end of file diff --git a/dist/tools/nacl_key_generator/Makefile b/dist/tools/nacl_key_generator/Makefile new file mode 100644 index 000000000000..64cde3625033 --- /dev/null +++ b/dist/tools/nacl_key_generator/Makefile @@ -0,0 +1,28 @@ +RIOTBASE := ../../.. +RIOT_INCLUDE = $(RIOTBASE)/sys/include +TWEETNACL_INCLUDE := tweetnacl +TWEETNACL_DIR := tweetnacl +TWEETNACL_SRC := $(TWEETNACL_DIR)/tweetnacl.c randombytes.c +KEYPAIR_SRC := generate-nacl-keys.c $(TWEETNACL_SRC) +GITCACHE = ../git/git-cache +TWEETNACL_URL = https://github.com/RIOT-OS/tweetnacl.git +TWEETNACL_VERSION = 7ea05c7098a16c87fa66e9166ce301666f3f2623 + +CFLAGS += -g -O3 -Wall -Wextra -pedantic -std=c99 + +all: bin bin/generate-nacl-keys + +bin: + mkdir bin + +git-fetch-tweetnacl: + rm -Rf $(TWEETNACL_DIR) + mkdir -p $(TWEETNACL_DIR) + $(GITCACHE) clone "$(TWEETNACL_URL)" "$(TWEETNACL_VERSION)" "$(TWEETNACL_DIR)" + touch $@ + +bin/generate-nacl-keys: git-fetch-tweetnacl + $(CC) $(CFLAGS) -I$(TWEETNACL_INCLUDE) $(KEYPAIR_SRC) -o $@ + +clean: + rm -rf bin/generate-nacl-keys diff --git a/dist/tools/nacl_key_generator/README.md b/dist/tools/nacl_key_generator/README.md new file mode 100644 index 000000000000..236154dbf131 --- /dev/null +++ b/dist/tools/nacl_key_generator/README.md @@ -0,0 +1,13 @@ +# Key-pair generator using [NaCL](https://nacl.cr.yp.to/) +This program will generate two key-pairs and store them as binary files, using +tweetNaCl package in RIOT + +## Usage +To use, you should call `generate-nacl-keys` without any arguments + +The results will be printed if the operation is successful, and four binary +files called "server_skey", "server_pkey.pub", "firmware_skey" and +"firmware_pkey.pub" will be created. + +Additionally, a "keys.c" file will be also generated containing "server_pkey" +and "firmware_skey" as unsigned char arrays. diff --git a/dist/tools/nacl_key_generator/generate-nacl-keys.c b/dist/tools/nacl_key_generator/generate-nacl-keys.c new file mode 100644 index 000000000000..684f30a3ce46 --- /dev/null +++ b/dist/tools/nacl_key_generator/generate-nacl-keys.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2016 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @author Francisco Acosta + */ + +#include +#include + +#include "tweetnacl.h" + +static unsigned char server_pk[crypto_box_PUBLICKEYBYTES]; +static unsigned char server_sk[crypto_box_SECRETKEYBYTES]; + +/* Public Key file */ +FILE *server_pkey; + +/* Secret Key file */ +FILE *server_skey; + +static unsigned char firmware_pk[crypto_box_PUBLICKEYBYTES]; +static unsigned char firmware_sk[crypto_box_SECRETKEYBYTES]; + +/* Public Key file */ +FILE *firmware_pkey; + +/* Secret Key file */ +FILE *firmware_skey; + +/* Keys C File */ +FILE *keys; + +int main(void) +{ + printf("Creating server keypair...\n"); + crypto_box_keypair(server_pk, server_sk); + printf("Done.\n"); + + printf("Server Secret Key:\n"); + for (int i = 0; i < crypto_box_SECRETKEYBYTES; i++) { + printf("%02x", server_sk[i]); + } + printf("\n"); + + printf("Writing server secret key to server_skey\n"); + if ((server_skey = fopen("server_skey", "w")) != NULL) { + fwrite(server_sk, sizeof(server_sk), 1, server_skey); + fclose(server_skey); + } else { + printf("ERROR! Cannot write file\n"); + return -1; + } + + printf("Server Public Key:\n"); + for (int i = 0; i < crypto_box_PUBLICKEYBYTES; i++) { + printf("%02x", server_pk[i]); + } + printf("\n"); + + printf("Writing server public key to keys.c\n"); + if ((keys = fopen("keys.c", "w")) != NULL) { + fprintf(keys, "const unsigned char server_pkey[] = {"); + for (int i = 1; i <= crypto_box_PUBLICKEYBYTES; i++) { + if (i < crypto_box_PUBLICKEYBYTES) { + fprintf(keys, "0x%02x, ", server_pk[i-1]); + if (i%8 == 0 && i > 0) { + fprintf(keys, "\n "); + } + } else { + fprintf(keys, "0x%02x};\n\n", server_pk[i-1]); + } + } + fclose(keys); + } else { + printf("ERROR! Cannot write file\n"); + return -1; + } + + printf("Writing server public key to server_pkey.pub\n"); + if ((server_pkey = fopen("server_pkey.pub", "w")) != NULL) { + fwrite(server_pk, sizeof(server_pk), 1, server_pkey); + fclose(server_pkey); + } else { + printf("ERROR! Cannot write file\n"); + return -1; + } + + printf("Creating firmware keypair...\n"); + crypto_box_keypair(firmware_pk, firmware_sk); + printf("Done.\n"); + + printf("Firmware Secret Key:\n"); + for (int i = 0; i < crypto_box_SECRETKEYBYTES; i++) { + printf("%02x", firmware_sk[i]); + } + printf("\n"); + + printf("Writing firmware secret key to firmware_skey\n"); + if ((firmware_skey = fopen("firmware_skey", "w")) != NULL) { + fwrite(firmware_sk, sizeof(firmware_sk), 1, firmware_skey); + fclose(firmware_skey); + } else { + printf("ERROR! Cannot write file\n"); + return -1; + } + + printf("Writing firmware secret key to keys.c\n"); + if ((keys = fopen("keys.c", "a")) != NULL) { + fprintf(keys, "const unsigned char firmware_skey[] = {"); + for (int i = 1; i <= crypto_box_PUBLICKEYBYTES; i++) { + if (i < crypto_box_PUBLICKEYBYTES) { + fprintf(keys, "0x%02x, ", firmware_sk[i-1]); + if (i%8 == 0 && i > 0) { + fprintf(keys, "\n "); + } + } else { + fprintf(keys, "0x%02x};\n", firmware_sk[i-1]); + } + } + fclose(keys); + } else { + printf("ERROR! Cannot write file\n"); + return -1; + } + + printf("Firmware Public Key:\n"); + for (int i = 0; i < crypto_box_PUBLICKEYBYTES; i++) { + printf("%02x", firmware_pk[i]); + } + printf("\n"); + + printf("Writing firmware public key to firmware_pkey.pub\n"); + if ((firmware_pkey = fopen("firmware_pkey.pub", "w")) != NULL) { + fwrite(firmware_pk, sizeof(firmware_pk), 1, firmware_pkey); + fclose(firmware_pkey); + } else { + printf("ERROR! Cannot write file\n"); + return -1; + } + + return 0; +} diff --git a/dist/tools/nacl_key_generator/randombytes.c b/dist/tools/nacl_key_generator/randombytes.c new file mode 100644 index 000000000000..9623da948436 --- /dev/null +++ b/dist/tools/nacl_key_generator/randombytes.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 Francisco Acosta + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include +#include +#include +#include +#include +#include + +static void seed_rng(void) +{ + int fp = open("/dev/random", O_RDONLY); + unsigned seed; + unsigned pos = 0; + + if (fp == -1) { + abort(); + } + + while (pos < sizeof(seed)) { + int amt = read(fp, (char*)&seed + pos, sizeof(seed) - pos); + + if (amt <= 0) { + abort(); + } + + pos += amt; + } + + srand(seed); + close(fp); +} + +void randombytes(uint8_t *target, uint64_t n) +{ + seed_rng(); + + while (n--) { + *target++ = rand(); + } +} From b35a4eceb98ef5da0603dd6074b1e6b23c451a88 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Fri, 20 Jan 2017 17:34:50 +0100 Subject: [PATCH 12/43] examples: add firmware swapping example --- examples/firmware_swapping/Makefile | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 examples/firmware_swapping/Makefile diff --git a/examples/firmware_swapping/Makefile b/examples/firmware_swapping/Makefile new file mode 100644 index 000000000000..8255d6d51598 --- /dev/null +++ b/examples/firmware_swapping/Makefile @@ -0,0 +1,54 @@ +# If no BOARD is found in the environment, use this default: +export BOARD ?= iotlab-m3 + +# This has to be the absolute path to the RIOT base directory: +RIOTBASE ?= $(CURDIR)/../.. + +# Activate FW slots +FW_SLOTS = 1 + +# Select slot 1 +FW_SLOT = 1 + +# Give a version to this build +VERSION = 0x0 + +# Give an UUID +UUID = 0xabcd1234 + +# Define the parameters for the FW Update +FW_IMAGE_OFFSET = 0x08004000 # Start at page 8 +FW_IMAGE_LENGTH = 0x3C000 # Reserve 120 pages +FW_METADATA_SPACE = 0x100 # 108 bytes meta-data, 256 byte aligned +FW_IMAGE_END = 0x08040000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH + +generate-keys: + $(RIOTBASE)/dist/tools/nacl_key_generator/bin/./generate-nacl-keys + +bootloader: + @cp keys.c ../bootloader + @cd ../bootloader; \ + CFLAGS+=-DFW_METADATA_SPACE=$(FW_METADATA_SPACE) make clean all; \ + cp bin/$(BOARD)/bootloader.hex ../firmware_swapping + +gcoap-slot1: + @cp firmware_pkey.pub server_skey ../gcoap + @cd ../gcoap; \ + CFLAGS="-DFW_SLOT=$(FW_SLOT) -DVERSION=$(VERSION) -DUUID=$(UUID) -DFW_SLOTS=$(FW_SLOTS)" \ + FW_SLOTS=$(FW_SLOTS) FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=$(FW_SLOT) \ + FW_IMAGE_OFFSET=$(FW_IMAGE_OFFSET) FW_IMAGE_LENGTH=$(FW_IMAGE_LENGTH) \ + FW_IMAGE_END=$(FW_IMAGE_END) VERSION=$(VERSION) UUID=$(UUID) \ + make clean all; \ + cp bin/$(BOARD)/slot-image-$(UUID)-$(VERSION).bin ../firmware_swapping + +merge-binary: + srec_cat bootloader.hex -intel -crop 0x08000000 $(FW_IMAGE_OFFSET) \ + slot-image-$(UUID)-$(VERSION).bin -binary -offset $(FW_IMAGE_OFFSET) \ + -crop $(FW_IMAGE_OFFSET) $(FW_IMAGE_END) \ + -o firmware-slot-$(FW_SLOT).hex -intel + +master-hex: generate-keys bootloader gcoap-slot1 merge-binary + @true + +clean: + @rm *.hex *.key firmware* server_skey keys.c *.bin *.pub \ No newline at end of file From bf998ac2275ba3ba719c8fa90e4cd15899ece609 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Fri, 20 Jan 2017 17:36:26 +0100 Subject: [PATCH 13/43] examples/firmware_swapping: ignore helpers --- examples/firmware_swapping/.gitignore | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 examples/firmware_swapping/.gitignore diff --git a/examples/firmware_swapping/.gitignore b/examples/firmware_swapping/.gitignore new file mode 100644 index 000000000000..9f74057f541e --- /dev/null +++ b/examples/firmware_swapping/.gitignore @@ -0,0 +1,6 @@ +*.hex +/firmware_pkey.pub +/firmware_skey +/keys.c +/server_pkey.pub +/server_skey From d1769bc2de585e76d7261995246d25d4508dd521 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Fri, 20 Jan 2017 17:34:10 +0100 Subject: [PATCH 14/43] examples/gcoap: ignore crypto keys --- examples/gcoap/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/gcoap/.gitignore diff --git a/examples/gcoap/.gitignore b/examples/gcoap/.gitignore new file mode 100644 index 000000000000..593368145d79 --- /dev/null +++ b/examples/gcoap/.gitignore @@ -0,0 +1,3 @@ +/firmware_pkey.pub +/keys.c +/server_skey From 5223f4a0eaa2983cbebc724accae6bc1db3ba9af Mon Sep 17 00:00:00 2001 From: kYc0o Date: Fri, 20 Jan 2017 17:30:53 +0100 Subject: [PATCH 15/43] examples/bootloader: ignore crypto keys --- examples/bootloader/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 examples/bootloader/.gitignore diff --git a/examples/bootloader/.gitignore b/examples/bootloader/.gitignore new file mode 100644 index 000000000000..dd06d8af3dd7 --- /dev/null +++ b/examples/bootloader/.gitignore @@ -0,0 +1 @@ +/keys.c From a2f738bfd10001e3f51012227dc6671b6a14f0af Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 00:40:01 +0100 Subject: [PATCH 16/43] f dist/tools/firmware_metadata: remove tweetnacl --- dist/tools/firmware_metadata/Makefile | 20 ++------ dist/tools/firmware_metadata/README.md | 2 +- .../firmware_metadata/generate-metadata.c | 47 ++----------------- dist/tools/firmware_metadata/randombytes.c | 47 ------------------- 4 files changed, 10 insertions(+), 106 deletions(-) delete mode 100644 dist/tools/firmware_metadata/randombytes.c diff --git a/dist/tools/firmware_metadata/Makefile b/dist/tools/firmware_metadata/Makefile index 1298859382f1..42c9ff280134 100644 --- a/dist/tools/firmware_metadata/Makefile +++ b/dist/tools/firmware_metadata/Makefile @@ -1,15 +1,9 @@ RIOTBASE := ../../.. RIOT_INCLUDE = $(RIOTBASE)/sys/include -TWEETNACL_INCLUDE := tweetnacl SHA256_DIR := $(RIOTBASE)/sys/hashes SHA256_INCLUDE := $(RIOT_INCLUDE)/hashes -TWEETNACL_DIR := tweetnacl -TWEETNACL_SRC := $(TWEETNACL_DIR)/tweetnacl.c randombytes.c -METADATA_SRC := generate-metadata.c $(SHA256_DIR)/sha256.c $(TWEETNACL_SRC) -METADATA_HDR := $(RIOT_INCLUDE)/fw_slots.h $(RIOT_INCLUDE)/hashes/sha256.h $(TWEETNACL_INCLUDE)/tweetnacl.h -GITCACHE = ../git/git-cache -TWEETNACL_URL = https://github.com/RIOT-OS/tweetnacl.git -TWEETNACL_VERSION = 7ea05c7098a16c87fa66e9166ce301666f3f2623 +METADATA_SRC := generate-metadata.c $(SHA256_DIR)/sha256.c +METADATA_HDR := $(RIOT_INCLUDE)/fw_slots.h $(RIOT_INCLUDE)/hashes/sha256.h CFLAGS += -g -O3 -Wall -Wextra -pedantic -std=c99 @@ -18,14 +12,8 @@ all: bin bin/generate-metadata bin: mkdir bin -git-fetch-tweetnacl: - rm -Rf $(TWEETNACL_DIR) - mkdir -p $(TWEETNACL_DIR) - $(GITCACHE) clone "$(TWEETNACL_URL)" "$(TWEETNACL_VERSION)" "$(TWEETNACL_DIR)" - touch $@ - -bin/generate-metadata: git-fetch-tweetnacl - $(CC) $(CFLAGS) -I$(RIOT_INCLUDE) -I$(TWEETNACL_INCLUDE) $(METADATA_SRC) -o $@ +bin/generate-metadata: + $(CC) $(CFLAGS) -I$(RIOT_INCLUDE) $(METADATA_SRC) -o $@ clean: rm -rf bin/generate-metadata diff --git a/dist/tools/firmware_metadata/README.md b/dist/tools/firmware_metadata/README.md index b5e21c7ec5c5..7e6830b0d475 100644 --- a/dist/tools/firmware_metadata/README.md +++ b/dist/tools/firmware_metadata/README.md @@ -5,7 +5,7 @@ follows: ```c typedef struct FW_metadata { uint8_t hash[SHA256_DIGEST_LENGTH]; /* SHA256 Hash of firmware image */ - uint8_t shash[NACL_SIGN]; /* Signed SHA256 */ + uint8_t shash[SIGN_LEN]; /* Signed SHA256 */ uint32_t size; /* Size of firmware image */ uint32_t uuid; /* Integer representing unique firmware ID */ uint16_t version; /* Integer representing firmware version */ diff --git a/dist/tools/firmware_metadata/generate-metadata.c b/dist/tools/firmware_metadata/generate-metadata.c index ff222363e218..776d7fcbbba5 100644 --- a/dist/tools/firmware_metadata/generate-metadata.c +++ b/dist/tools/firmware_metadata/generate-metadata.c @@ -44,7 +44,6 @@ #include #include "fw_slots.h" -#include "tweetnacl/tweetnacl.h" #include "hashes/sha256.h" /* Input firmware .bin file */ @@ -53,20 +52,6 @@ FILE *firmware_bin; /* Output metadata .bin file */ FILE *metadata_bin; -/* Pointer to firmware's public key */ -FILE *firmware_pk; - -/* Pointer to server's secret key */ -FILE *server_sk; - -/* Keys buffers */ -static unsigned char firmware_pkey[crypto_box_PUBLICKEYBYTES]; -static unsigned char server_skey[crypto_box_SECRETKEYBYTES]; - -/* Crypto helpers */ -static const unsigned char n[crypto_box_NONCEBYTES]; -static unsigned char m[NACL_SIGN]; - uint32_t firmware_size = 0; int main(int argc, char *argv[]) @@ -110,35 +95,13 @@ int main(int argc, char *argv[]) /* Close the .bin file. */ fclose(firmware_bin); - printf("Encrypting using firmware_pkey.pub ...\n"); - printf("Reading firmware public key...\n"); - firmware_pk = fopen("firmware_pkey.pub", "r"); - if (firmware_pk != NULL) { - size_t size = fread(firmware_pkey, 1, sizeof(firmware_pkey), firmware_pk); - printf("Read %zu bytes from firmware_pkey.pub\n", size); - fclose(firmware_pk); - } else { - printf("ERROR! Cannot open firmware public key\n"); - return -1; - } - - printf("Reading server secret key \"server_skey\"...\n"); - server_sk = fopen("server_skey", "r"); - if (server_sk != NULL) { - size_t size = fread(server_skey, 1, sizeof(server_skey), server_sk); - printf("Read %zu bytes from server_skey\n", size); - fclose(server_sk); - } else { - printf("ERROR! Cannot open server secret key\n"); - return -1; + /* + * TODO Sign hash + */ + for (unsigned long i = 0; i < sizeof(metadata.shash); i++) { + metadata.shash[i] = 0; } - memset(metadata.shash, 0, NACL_SIGN); - memset(m, 0, crypto_box_ZEROBYTES); - memcpy(m + crypto_box_ZEROBYTES, metadata.hash, NACL_SIGN - crypto_box_ZEROBYTES); - - crypto_box(metadata.shash, m, NACL_SIGN, n, firmware_pkey, server_skey); - /* Generate FW image metadata */ metadata.size = firmware_size; diff --git a/dist/tools/firmware_metadata/randombytes.c b/dist/tools/firmware_metadata/randombytes.c deleted file mode 100644 index 9623da948436..000000000000 --- a/dist/tools/firmware_metadata/randombytes.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2016 Francisco Acosta - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#include -#include -#include -#include -#include -#include - -static void seed_rng(void) -{ - int fp = open("/dev/random", O_RDONLY); - unsigned seed; - unsigned pos = 0; - - if (fp == -1) { - abort(); - } - - while (pos < sizeof(seed)) { - int amt = read(fp, (char*)&seed + pos, sizeof(seed) - pos); - - if (amt <= 0) { - abort(); - } - - pos += amt; - } - - srand(seed); - close(fp); -} - -void randombytes(uint8_t *target, uint64_t n) -{ - seed_rng(); - - while (n--) { - *target++ = rand(); - } -} From 41ff85227b34435f9b2aa7586490db19c0e026ef Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 00:40:39 +0100 Subject: [PATCH 17/43] f dist/tools: remove NaCl key generator --- dist/tools/nacl_key_generator/.gitignore | 2 - dist/tools/nacl_key_generator/Makefile | 28 ---- dist/tools/nacl_key_generator/README.md | 13 -- .../nacl_key_generator/generate-nacl-keys.c | 148 ------------------ dist/tools/nacl_key_generator/randombytes.c | 47 ------ 5 files changed, 238 deletions(-) delete mode 100644 dist/tools/nacl_key_generator/.gitignore delete mode 100644 dist/tools/nacl_key_generator/Makefile delete mode 100644 dist/tools/nacl_key_generator/README.md delete mode 100644 dist/tools/nacl_key_generator/generate-nacl-keys.c delete mode 100644 dist/tools/nacl_key_generator/randombytes.c diff --git a/dist/tools/nacl_key_generator/.gitignore b/dist/tools/nacl_key_generator/.gitignore deleted file mode 100644 index 6f47d3a1fe46..000000000000 --- a/dist/tools/nacl_key_generator/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/git-fetch-tweetnacl -tweetnacl \ No newline at end of file diff --git a/dist/tools/nacl_key_generator/Makefile b/dist/tools/nacl_key_generator/Makefile deleted file mode 100644 index 64cde3625033..000000000000 --- a/dist/tools/nacl_key_generator/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -RIOTBASE := ../../.. -RIOT_INCLUDE = $(RIOTBASE)/sys/include -TWEETNACL_INCLUDE := tweetnacl -TWEETNACL_DIR := tweetnacl -TWEETNACL_SRC := $(TWEETNACL_DIR)/tweetnacl.c randombytes.c -KEYPAIR_SRC := generate-nacl-keys.c $(TWEETNACL_SRC) -GITCACHE = ../git/git-cache -TWEETNACL_URL = https://github.com/RIOT-OS/tweetnacl.git -TWEETNACL_VERSION = 7ea05c7098a16c87fa66e9166ce301666f3f2623 - -CFLAGS += -g -O3 -Wall -Wextra -pedantic -std=c99 - -all: bin bin/generate-nacl-keys - -bin: - mkdir bin - -git-fetch-tweetnacl: - rm -Rf $(TWEETNACL_DIR) - mkdir -p $(TWEETNACL_DIR) - $(GITCACHE) clone "$(TWEETNACL_URL)" "$(TWEETNACL_VERSION)" "$(TWEETNACL_DIR)" - touch $@ - -bin/generate-nacl-keys: git-fetch-tweetnacl - $(CC) $(CFLAGS) -I$(TWEETNACL_INCLUDE) $(KEYPAIR_SRC) -o $@ - -clean: - rm -rf bin/generate-nacl-keys diff --git a/dist/tools/nacl_key_generator/README.md b/dist/tools/nacl_key_generator/README.md deleted file mode 100644 index 236154dbf131..000000000000 --- a/dist/tools/nacl_key_generator/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Key-pair generator using [NaCL](https://nacl.cr.yp.to/) -This program will generate two key-pairs and store them as binary files, using -tweetNaCl package in RIOT - -## Usage -To use, you should call `generate-nacl-keys` without any arguments - -The results will be printed if the operation is successful, and four binary -files called "server_skey", "server_pkey.pub", "firmware_skey" and -"firmware_pkey.pub" will be created. - -Additionally, a "keys.c" file will be also generated containing "server_pkey" -and "firmware_skey" as unsigned char arrays. diff --git a/dist/tools/nacl_key_generator/generate-nacl-keys.c b/dist/tools/nacl_key_generator/generate-nacl-keys.c deleted file mode 100644 index 684f30a3ce46..000000000000 --- a/dist/tools/nacl_key_generator/generate-nacl-keys.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2016 Inria - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @author Francisco Acosta - */ - -#include -#include - -#include "tweetnacl.h" - -static unsigned char server_pk[crypto_box_PUBLICKEYBYTES]; -static unsigned char server_sk[crypto_box_SECRETKEYBYTES]; - -/* Public Key file */ -FILE *server_pkey; - -/* Secret Key file */ -FILE *server_skey; - -static unsigned char firmware_pk[crypto_box_PUBLICKEYBYTES]; -static unsigned char firmware_sk[crypto_box_SECRETKEYBYTES]; - -/* Public Key file */ -FILE *firmware_pkey; - -/* Secret Key file */ -FILE *firmware_skey; - -/* Keys C File */ -FILE *keys; - -int main(void) -{ - printf("Creating server keypair...\n"); - crypto_box_keypair(server_pk, server_sk); - printf("Done.\n"); - - printf("Server Secret Key:\n"); - for (int i = 0; i < crypto_box_SECRETKEYBYTES; i++) { - printf("%02x", server_sk[i]); - } - printf("\n"); - - printf("Writing server secret key to server_skey\n"); - if ((server_skey = fopen("server_skey", "w")) != NULL) { - fwrite(server_sk, sizeof(server_sk), 1, server_skey); - fclose(server_skey); - } else { - printf("ERROR! Cannot write file\n"); - return -1; - } - - printf("Server Public Key:\n"); - for (int i = 0; i < crypto_box_PUBLICKEYBYTES; i++) { - printf("%02x", server_pk[i]); - } - printf("\n"); - - printf("Writing server public key to keys.c\n"); - if ((keys = fopen("keys.c", "w")) != NULL) { - fprintf(keys, "const unsigned char server_pkey[] = {"); - for (int i = 1; i <= crypto_box_PUBLICKEYBYTES; i++) { - if (i < crypto_box_PUBLICKEYBYTES) { - fprintf(keys, "0x%02x, ", server_pk[i-1]); - if (i%8 == 0 && i > 0) { - fprintf(keys, "\n "); - } - } else { - fprintf(keys, "0x%02x};\n\n", server_pk[i-1]); - } - } - fclose(keys); - } else { - printf("ERROR! Cannot write file\n"); - return -1; - } - - printf("Writing server public key to server_pkey.pub\n"); - if ((server_pkey = fopen("server_pkey.pub", "w")) != NULL) { - fwrite(server_pk, sizeof(server_pk), 1, server_pkey); - fclose(server_pkey); - } else { - printf("ERROR! Cannot write file\n"); - return -1; - } - - printf("Creating firmware keypair...\n"); - crypto_box_keypair(firmware_pk, firmware_sk); - printf("Done.\n"); - - printf("Firmware Secret Key:\n"); - for (int i = 0; i < crypto_box_SECRETKEYBYTES; i++) { - printf("%02x", firmware_sk[i]); - } - printf("\n"); - - printf("Writing firmware secret key to firmware_skey\n"); - if ((firmware_skey = fopen("firmware_skey", "w")) != NULL) { - fwrite(firmware_sk, sizeof(firmware_sk), 1, firmware_skey); - fclose(firmware_skey); - } else { - printf("ERROR! Cannot write file\n"); - return -1; - } - - printf("Writing firmware secret key to keys.c\n"); - if ((keys = fopen("keys.c", "a")) != NULL) { - fprintf(keys, "const unsigned char firmware_skey[] = {"); - for (int i = 1; i <= crypto_box_PUBLICKEYBYTES; i++) { - if (i < crypto_box_PUBLICKEYBYTES) { - fprintf(keys, "0x%02x, ", firmware_sk[i-1]); - if (i%8 == 0 && i > 0) { - fprintf(keys, "\n "); - } - } else { - fprintf(keys, "0x%02x};\n", firmware_sk[i-1]); - } - } - fclose(keys); - } else { - printf("ERROR! Cannot write file\n"); - return -1; - } - - printf("Firmware Public Key:\n"); - for (int i = 0; i < crypto_box_PUBLICKEYBYTES; i++) { - printf("%02x", firmware_pk[i]); - } - printf("\n"); - - printf("Writing firmware public key to firmware_pkey.pub\n"); - if ((firmware_pkey = fopen("firmware_pkey.pub", "w")) != NULL) { - fwrite(firmware_pk, sizeof(firmware_pk), 1, firmware_pkey); - fclose(firmware_pkey); - } else { - printf("ERROR! Cannot write file\n"); - return -1; - } - - return 0; -} diff --git a/dist/tools/nacl_key_generator/randombytes.c b/dist/tools/nacl_key_generator/randombytes.c deleted file mode 100644 index 9623da948436..000000000000 --- a/dist/tools/nacl_key_generator/randombytes.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2016 Francisco Acosta - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -#include -#include -#include -#include -#include -#include - -static void seed_rng(void) -{ - int fp = open("/dev/random", O_RDONLY); - unsigned seed; - unsigned pos = 0; - - if (fp == -1) { - abort(); - } - - while (pos < sizeof(seed)) { - int amt = read(fp, (char*)&seed + pos, sizeof(seed) - pos); - - if (amt <= 0) { - abort(); - } - - pos += amt; - } - - srand(seed); - close(fp); -} - -void randombytes(uint8_t *target, uint64_t n) -{ - seed_rng(); - - while (n--) { - *target++ = rand(); - } -} From cc1ccd9d31f422be07c43c1ccf3f3f7ded9ba6c2 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 00:41:00 +0100 Subject: [PATCH 18/43] f examples/bootloader: remove tweetnacl --- examples/bootloader/.gitignore | 1 - examples/bootloader/Makefile | 3 --- examples/bootloader/main.c | 34 +++++++--------------------------- 3 files changed, 7 insertions(+), 31 deletions(-) delete mode 100644 examples/bootloader/.gitignore diff --git a/examples/bootloader/.gitignore b/examples/bootloader/.gitignore deleted file mode 100644 index dd06d8af3dd7..000000000000 --- a/examples/bootloader/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/keys.c diff --git a/examples/bootloader/Makefile b/examples/bootloader/Makefile index f0eb30c303c8..5d6aff4cb29a 100644 --- a/examples/bootloader/Makefile +++ b/examples/bootloader/Makefile @@ -21,7 +21,4 @@ QUIET ?= 1 # Use fw_slots module to manage images on ROM USEMODULE += fw_slots -# TweetNaCl needs a lot of stack -CFLAGS += '-DTHREAD_STACKSIZE_MAIN=(THREAD_STACKSIZE_DEFAULT + 2048)' - include $(RIOTBASE)/Makefile.include diff --git a/examples/bootloader/main.c b/examples/bootloader/main.c index 54830cc39dec..21c8d5090cc5 100644 --- a/examples/bootloader/main.c +++ b/examples/bootloader/main.c @@ -83,28 +83,7 @@ static int cmd_verify(int argc, char **argv) slot = atoi(argv[1]); if (verify_int_fw_slot(slot) == 0) { - printf("Verified slot %d\n", slot); - return 0; - } else { - return -1; - } - - return 0; -} - -static int cmd_validate(int argc, char **argv) -{ - uint8_t slot; - - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } - - slot = atoi(argv[1]); - - if (validate_int_fw_slot(slot) == 0) { - printf("Validated slot %d\n", slot); + printf("Slot %d successfully verified\n", slot); return 0; } else { return -1; @@ -140,15 +119,17 @@ static int cmd_jump(int argc, char **argv) slot = atoi(argv[1]); - /*if (validate_int_fw_slot(slot) == 0) { - printf("Validated slot %d\n", slot); + if (verify_int_fw_slot(slot) == 0) { + printf("Slot %d verified!\n", slot); } else { - printf("Slot %u not valid!\n", slot); + printf("Slot %u inconsistent!\n", slot); return -1; - }*/ + } address = get_slot_fw_address(slot); + printf("Booting slot %d at 0x%lx...\n", slot, address); + jump_to_image(address); return 0; @@ -158,7 +139,6 @@ static const shell_command_t shell_commands[] = { { "lsimg", "List the available firmwares on ROM", cmd_lsimg }, { "get_metadata", "Get metadata from slot", cmd_get_metadata }, { "verify", "Verify consistency (sha256) of slot", cmd_verify }, - { "validate", "Validates authenticity of slot", cmd_validate }, { "erase", "Erase slot *WARNING use with caution*", cmd_erase_slot }, { "jump", "Jump to specific FW slot (cause reset)", cmd_jump }, { NULL, NULL, NULL } From 1ef2ba7b80e8414f29e82228546f822404858cb4 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 00:41:25 +0100 Subject: [PATCH 19/43] f examples/firmware_swapping: remove tweetnacl --- examples/firmware_swapping/.gitignore | 5 ----- examples/firmware_swapping/Makefile | 14 +++++--------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/examples/firmware_swapping/.gitignore b/examples/firmware_swapping/.gitignore index 9f74057f541e..eee4db0f36a1 100644 --- a/examples/firmware_swapping/.gitignore +++ b/examples/firmware_swapping/.gitignore @@ -1,6 +1 @@ *.hex -/firmware_pkey.pub -/firmware_skey -/keys.c -/server_pkey.pub -/server_skey diff --git a/examples/firmware_swapping/Makefile b/examples/firmware_swapping/Makefile index 8255d6d51598..c51e9dc62cc1 100644 --- a/examples/firmware_swapping/Makefile +++ b/examples/firmware_swapping/Makefile @@ -21,21 +21,17 @@ FW_IMAGE_OFFSET = 0x08004000 # Start at page 8 FW_IMAGE_LENGTH = 0x3C000 # Reserve 120 pages FW_METADATA_SPACE = 0x100 # 108 bytes meta-data, 256 byte aligned FW_IMAGE_END = 0x08040000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH - -generate-keys: - $(RIOTBASE)/dist/tools/nacl_key_generator/bin/./generate-nacl-keys bootloader: - @cp keys.c ../bootloader @cd ../bootloader; \ CFLAGS+=-DFW_METADATA_SPACE=$(FW_METADATA_SPACE) make clean all; \ cp bin/$(BOARD)/bootloader.hex ../firmware_swapping gcoap-slot1: - @cp firmware_pkey.pub server_skey ../gcoap @cd ../gcoap; \ - CFLAGS="-DFW_SLOT=$(FW_SLOT) -DVERSION=$(VERSION) -DUUID=$(UUID) -DFW_SLOTS=$(FW_SLOTS)" \ - FW_SLOTS=$(FW_SLOTS) FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=$(FW_SLOT) \ + CFLAGS="-DFW_SLOT=$(FW_SLOT) -DVERSION=$(VERSION) -DUUID=$(UUID) \ + -DFW_SLOTS=$(FW_SLOTS)" FW_SLOTS=$(FW_SLOTS) \ + FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=$(FW_SLOT) \ FW_IMAGE_OFFSET=$(FW_IMAGE_OFFSET) FW_IMAGE_LENGTH=$(FW_IMAGE_LENGTH) \ FW_IMAGE_END=$(FW_IMAGE_END) VERSION=$(VERSION) UUID=$(UUID) \ make clean all; \ @@ -47,8 +43,8 @@ merge-binary: -crop $(FW_IMAGE_OFFSET) $(FW_IMAGE_END) \ -o firmware-slot-$(FW_SLOT).hex -intel -master-hex: generate-keys bootloader gcoap-slot1 merge-binary +master-hex: bootloader gcoap-slot1 merge-binary @true clean: - @rm *.hex *.key firmware* server_skey keys.c *.bin *.pub \ No newline at end of file + @rm *.hex firmware* *.bin \ No newline at end of file From d1de5b5cd121f7f25348cbee451b77a7d410b2d6 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 00:41:45 +0100 Subject: [PATCH 20/43] f examples/gcoap: remove tweetnacl --- examples/gcoap/.gitignore | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 examples/gcoap/.gitignore diff --git a/examples/gcoap/.gitignore b/examples/gcoap/.gitignore deleted file mode 100644 index 593368145d79..000000000000 --- a/examples/gcoap/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/firmware_pkey.pub -/keys.c -/server_skey From aeddcbefc93de88ab82453bd0a4d2386e8d12615 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 00:42:19 +0100 Subject: [PATCH 21/43] f sys/fw_slots: remove tweetnacl --- sys/fw_slots/fw_slots.c | 40 +++------------------------------------- sys/include/fw_slots.h | 14 +++++++------- 2 files changed, 10 insertions(+), 44 deletions(-) diff --git a/sys/fw_slots/fw_slots.c b/sys/fw_slots/fw_slots.c index 83c95693fd4e..15fb2c7dea9a 100644 --- a/sys/fw_slots/fw_slots.c +++ b/sys/fw_slots/fw_slots.c @@ -39,7 +39,6 @@ #include #include -#include #include "fw_slots.h" #include "cpu_conf.h" #include "irq.h" @@ -72,40 +71,9 @@ static void int_flash_read(uint8_t *data_buffer, uint32_t address, uint32_t coun int validate_int_fw_slot(uint8_t fw_slot) { - FW_metadata_t metadata; - int res; - unsigned char n[crypto_box_NONCEBYTES]; - unsigned char hash[NACL_SIGN]; - - if (verify_int_fw_slot(fw_slot) != 0) { - printf("[fw_slots] ERROR verification for slot %i failed!\n", fw_slot); - return -1; - } - - if (get_int_fw_slot_metadata(fw_slot, &metadata) != 0) { - printf("[fw_slots] ERROR cannot get metadata from slot %i!\n", fw_slot); - return -1; - } - - memset(hash, 0, sizeof(hash)); - - printf("Decrypting metadata.shash...\n"); - - res = crypto_box_open(hash, metadata.shash, NACL_SIGN, n, server_pkey, firmware_skey); - if (res) { - printf("Decryption failed.\n"); - return -1; - } else { - printf("Decryption successful! verifying..."); - for (int i = 0; i < SHA256_DIGEST_LENGTH; i++) { - if (metadata.hash[i] != (hash[i + crypto_box_ZEROBYTES])) { - printf("[fw_slots] ERROR incorrect decrypted hash!\n"); - return -1; - } - } - } - - printf("[fw_slots] FW slot %i successfully validated!\n", fw_slot); + /* + * TODO + */ return 0; } @@ -500,8 +468,6 @@ void jump_to_image(uint32_t destination_address) /* Move to the second pointer on VTOR (reset_handler_default) */ destination_address += VTOR_RESET_HANDLER; - printf("Addr: 0x%lx\n", destination_address); - /* Load the destination address */ __asm("LDR R0, [%[dest]]"::[dest]"r"(destination_address)); /* Make sure the Thumb State bit is set. */ diff --git a/sys/include/fw_slots.h b/sys/include/fw_slots.h index 36d896698be2..e57c3e96c0b9 100644 --- a/sys/include/fw_slots.h +++ b/sys/include/fw_slots.h @@ -30,7 +30,7 @@ */ /** - * @defgroup sys_fw_slots Firmware Slots + * @defgroup sys_fw_slots Firmware slots management * @ingroup sys * * @file @@ -44,7 +44,6 @@ #define FW_SLOTS_H #include "hashes/sha256.h" -#include "tweetnacl.h" /* * FW_METADATA_LENGTH: @@ -53,19 +52,20 @@ */ #define FW_METADATA_LENGTH sizeof(FW_metadata_t) -#define NACL_SIGN (SHA256_DIGEST_LENGTH + crypto_box_ZEROBYTES) +/* + * SIGN_LEN: + * Provisional length for signed hash + */ +#define SIGN_LEN (SHA256_DIGEST_LENGTH) typedef struct FW_metadata { uint8_t hash[SHA256_DIGEST_LENGTH]; /* SHA256 Hash of firmware image */ - uint8_t shash[NACL_SIGN]; /* Signed SHA256 */ + uint8_t shash[SIGN_LEN]; /* Signed SHA256 */ uint32_t size; /* Size of firmware image */ uint32_t uuid; /* Integer representing unique firmware ID */ uint16_t version; /* Integer representing firmware version */ } FW_metadata_t; -extern const unsigned char server_pkey[]; -extern const unsigned char firmware_skey[]; - /** * @brief Print formatted FW image metadata to STDIO. * From 6027cd45daba21ba499fa53c2a91c83d09d6ec84 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 01:12:20 +0100 Subject: [PATCH 22/43] f examples/bootloader: prefix fw_slots functions --- examples/bootloader/main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/bootloader/main.c b/examples/bootloader/main.c index 21c8d5090cc5..9d9225333596 100644 --- a/examples/bootloader/main.c +++ b/examples/bootloader/main.c @@ -36,9 +36,9 @@ static int cmd_lsimg(int argc, char **argv) FW_metadata_t fw_metadata; for (uint8_t i = 1; i <= MAX_FW_SLOTS; i++) { - if (get_int_fw_slot_metadata(i, &fw_metadata) == 0) { + if (fw_slots_get_int_slot_metadata(i, &fw_metadata) == 0) { printf("Metadata slot %d:\n", i); - print_metadata(&fw_metadata); + fw_slots_print_metadata(&fw_metadata); } else { printf("ERROR: Cannot retrieve metadata.\n"); } @@ -59,9 +59,9 @@ static int cmd_get_metadata(int argc, char **argv) slot = atoi(argv[1]); - if (get_int_fw_slot_metadata(slot, &fw_metadata) == 0) { + if (fw_slots_get_int_slot_metadata(slot, &fw_metadata) == 0) { printf("Metadata slot %d\n", slot); - print_metadata(&fw_metadata); + fw_slots_print_metadata(&fw_metadata); return 0; } else { printf("ERROR: Cannot retrieve metadata from slot %d.\n", slot); @@ -82,7 +82,7 @@ static int cmd_verify(int argc, char **argv) slot = atoi(argv[1]); - if (verify_int_fw_slot(slot) == 0) { + if (fw_slots_verify_int_slot(slot) == 0) { printf("Slot %d successfully verified\n", slot); return 0; } else { @@ -103,7 +103,7 @@ static int cmd_erase_slot(int argc, char**argv) slot = atoi(argv[1]); - return erase_int_fw_image(slot); + return fw_slots_erase_int_image(slot); } static int cmd_jump(int argc, char **argv) @@ -119,18 +119,18 @@ static int cmd_jump(int argc, char **argv) slot = atoi(argv[1]); - if (verify_int_fw_slot(slot) == 0) { + if (fw_slots_verify_int_slot(slot) == 0) { printf("Slot %d verified!\n", slot); } else { printf("Slot %u inconsistent!\n", slot); return -1; } - address = get_slot_fw_address(slot); + address = fw_slots_get_slot_address(slot); printf("Booting slot %d at 0x%lx...\n", slot, address); - jump_to_image(address); + fw_slots_jump_to_image(address); return 0; } From 01ecff602230c0b9528d1628b031cac7cfe05e83 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 01:12:50 +0100 Subject: [PATCH 23/43] f sys/fw_slots: prefix fw_slots functions --- sys/fw_slots/fw_slots.c | 82 ++++++++++++++++++++-------------------- sys/include/fw_slots.h | 84 ++++++++++++++++++++--------------------- 2 files changed, 83 insertions(+), 83 deletions(-) diff --git a/sys/fw_slots/fw_slots.c b/sys/fw_slots/fw_slots.c index 15fb2c7dea9a..c2756e3658c3 100644 --- a/sys/fw_slots/fw_slots.c +++ b/sys/fw_slots/fw_slots.c @@ -69,7 +69,7 @@ static void int_flash_read(uint8_t *data_buffer, uint32_t address, uint32_t coun } } -int validate_int_fw_slot(uint8_t fw_slot) +int fw_slots_validate_int_slot(uint8_t fw_slot) { /* * TODO @@ -78,17 +78,17 @@ int validate_int_fw_slot(uint8_t fw_slot) return 0; } -uint32_t get_slot_fw_address(uint8_t fw_slot) +uint32_t fw_slots_get_slot_address(uint8_t fw_slot) { return get_slot_address(fw_slot); } -uint32_t get_slot_fw_page(uint8_t fw_slot) +uint32_t fw_slots_get_slot_page(uint8_t fw_slot) { return get_slot_page(fw_slot); } -void print_metadata(FW_metadata_t *metadata) +void fw_slots_print_metadata(FW_metadata_t *metadata) { printf("Firmware Size: %ld\n", metadata->size); printf("Firmware Version: %#x\n", metadata->version); @@ -105,7 +105,7 @@ void print_metadata(FW_metadata_t *metadata) printf("\n"); } -int get_int_metadata(uint8_t fw_slot_page, FW_metadata_t *fw_metadata) +int fw_slots_get_int_metadata(uint8_t fw_slot_page, FW_metadata_t *fw_metadata) { uint32_t fw_address; @@ -118,7 +118,7 @@ int get_int_metadata(uint8_t fw_slot_page, FW_metadata_t *fw_metadata) return 0; } -int get_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) +int fw_slots_get_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) { /* * TODO @@ -127,7 +127,7 @@ int get_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) return 0; } -int get_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) +int fw_slots_get_int_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) { uint32_t page; @@ -138,12 +138,12 @@ int get_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) return -1; } - page = get_slot_fw_page(fw_slot); + page = fw_slots_get_slot_page(fw_slot); - return get_int_metadata(page, fw_slot_metadata); + return fw_slots_get_int_metadata(page, fw_slot_metadata); } -int overwrite_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) +int fw_slots_overwrite_int_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) { /* * TODO @@ -153,7 +153,7 @@ int overwrite_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metad -int overwrite_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) +int fw_slots_overwrite_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) { /* * TODO @@ -161,7 +161,7 @@ int overwrite_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata) return 0; } -int backup_golden_image(void) +int fw_slots_backup_golden_image(void) { /* * TODO @@ -169,7 +169,7 @@ int backup_golden_image(void) return 0; } -int verify_int_fw_slot(uint8_t fw_slot) +int fw_slots_verify_int_slot(uint8_t fw_slot) { FW_metadata_t fw_metadata; uint32_t fw_image_address; @@ -187,10 +187,10 @@ int verify_int_fw_slot(uint8_t fw_slot) } /* Read the metadata of the corresponding FW slot */ - fw_image_address = get_slot_fw_address(fw_slot); + fw_image_address = fw_slots_get_slot_address(fw_slot); - if (get_int_fw_slot_metadata(fw_slot, &fw_metadata) == 0) { - print_metadata(&fw_metadata); + if (fw_slots_get_int_slot_metadata(fw_slot, &fw_metadata) == 0) { + fw_slots_print_metadata(&fw_metadata); } else { printf("[fw_slots] ERROR cannot get slot metadata.\n"); } @@ -225,7 +225,7 @@ int verify_int_fw_slot(uint8_t fw_slot) return 0; } -int validate_fw_metadata(FW_metadata_t *metadata) +int fw_slots_validate_metadata(FW_metadata_t *metadata) { /* Is the FW slot erased? * First, we check to see if every byte in the metadata is 0xFF. @@ -248,14 +248,14 @@ int validate_fw_metadata(FW_metadata_t *metadata) /* If the FW slot is erased, it's not valid! No more work to do here. */ if (erased) { - return 0; + return -1; } /* If we get this far, all metadata bytes were cleared (0xff) */ return 0; } -int find_matching_int_fw_slot(uint16_t version) +int fw_slots_find_matching_int_slot(uint16_t version) { int matching_slot = -1; /* Assume there is no matching FW slot. */ @@ -264,14 +264,14 @@ int find_matching_int_fw_slot(uint16_t version) /* Get the metadata of the current FW slot. */ FW_metadata_t fw_slot_metadata; - if(get_int_fw_slot_metadata(slot, &fw_slot_metadata) == 0) { - print_metadata(&fw_slot_metadata); + if(fw_slots_get_int_slot_metadata(slot, &fw_slot_metadata) == 0) { + fw_slots_print_metadata(&fw_slot_metadata); } else { printf("[fw_slots] ERROR cannot get slot metadata.\n"); } /* Is this slot empty? If yes, skip. */ - if (validate_fw_metadata(&fw_slot_metadata) == false) { + if (fw_slots_validate_metadata(&fw_slot_metadata) == false) { continue; } @@ -292,7 +292,7 @@ int find_matching_int_fw_slot(uint16_t version) return matching_slot; } -int find_empty_int_fw_slot(void) +int fw_slots_find_empty_int_slot(void) { /* Iterate through each of the MAX_FW_SLOTS internal slots. */ for (int slot = 1; slot <= MAX_FW_SLOTS; slot++) { @@ -300,14 +300,14 @@ int find_empty_int_fw_slot(void) /* Get the metadata of the current FW slot. */ FW_metadata_t fw_slot_metadata; - if(get_int_fw_slot_metadata(slot, &fw_slot_metadata) == 0) { - print_metadata(&fw_slot_metadata); + if(fw_slots_get_int_slot_metadata(slot, &fw_slot_metadata) == 0) { + fw_slots_print_metadata(&fw_slot_metadata); } else { printf("[fw_slots] ERROR cannot get slot metadata.\n"); } /* Is this slot invalid? If yes, let's treat it as empty. */ - if (validate_fw_metadata(&fw_slot_metadata) == false) { + if (fw_slots_validate_metadata(&fw_slot_metadata) == false) { return slot; } } @@ -318,10 +318,10 @@ int find_empty_int_fw_slot(void) * If execution goes this far, no empty slot was found. Now, we look for * the oldest FW slot instead. */ - return find_oldest_int_fw_image(); + return fw_slots_find_oldest_int_image(); } -int find_oldest_int_fw_image(void) +int fw_slots_find_oldest_int_image(void) { /* The oldest firmware should be the v0 */ int oldest_fw_slot = 1; @@ -332,14 +332,14 @@ int find_oldest_int_fw_image(void) /* Get the metadata of the current FW slot. */ FW_metadata_t fw_slot_metadata; - if(get_int_fw_slot_metadata(slot, &fw_slot_metadata) == 0) { - print_metadata(&fw_slot_metadata); + if(fw_slots_get_int_slot_metadata(slot, &fw_slot_metadata) == 0) { + fw_slots_print_metadata(&fw_slot_metadata); } else { printf("[fw_slots] ERROR cannot get slot metadata.\n"); } /* Is this slot populated? If not, skip. */ - if (validate_fw_metadata(&fw_slot_metadata) == false) { + if (fw_slots_validate_metadata(&fw_slot_metadata) == false) { continue; } @@ -361,7 +361,7 @@ int find_oldest_int_fw_image(void) return oldest_fw_slot; } -int find_newest_int_fw_image(void) +int fw_slots_find_newest_int_image(void) { /* At first, we only assume knowledge of version v0 */ int newest_fw_slot = 0; @@ -372,14 +372,14 @@ int find_newest_int_fw_image(void) /* Get the metadata of the current FW slot. */ FW_metadata_t fw_slot_metadata; - if(get_int_fw_slot_metadata(slot, &fw_slot_metadata) == 0) { - print_metadata(&fw_slot_metadata); + if(fw_slots_get_int_slot_metadata(slot, &fw_slot_metadata) == 0) { + fw_slots_print_metadata(&fw_slot_metadata); } else { printf("[fw_slots] ERROR cannot get slot metadata.\n"); } /* Is this slot populated? If not, skip. */ - if (validate_fw_metadata( &fw_slot_metadata) == false) { + if (fw_slots_validate_metadata( &fw_slot_metadata) == false) { continue; } @@ -396,7 +396,7 @@ int find_newest_int_fw_image(void) return newest_fw_slot; } -int erase_int_fw_image(uint8_t fw_slot) +int fw_slots_erase_int_image(uint8_t fw_slot) { /* Get page address of the fw_slot in internal flash */ uint32_t fw_image_base_address; @@ -409,13 +409,13 @@ int erase_int_fw_image(uint8_t fw_slot) return -1; } - fw_image_base_address = get_slot_fw_address(fw_slot); + fw_image_base_address = fw_slots_get_slot_address(fw_slot); printf("[fw_slots] Erasing FW slot %u [%#lx, %#lx]...\n", fw_slot, fw_image_base_address, fw_image_base_address + (FW_SLOT_PAGES * FLASHPAGE_SIZE) - 1); - slot_page = get_slot_fw_page(fw_slot); + slot_page = fw_slots_get_slot_page(fw_slot); /* Erase each page in the FW internal slot! */ for (int page = slot_page; page < slot_page + FW_SLOT_PAGES; page++) { @@ -428,7 +428,7 @@ int erase_int_fw_image(uint8_t fw_slot) return 0; } -int update_firmware(uint8_t fw_slot) +int fw_slots_update_firmware(uint8_t fw_slot) { /* * TODO @@ -436,7 +436,7 @@ int update_firmware(uint8_t fw_slot) return 0; } -int store_firmware_data( uint32_t ext_address, uint8_t *data, size_t data_length ) +int fw_slots_store_fw_data( uint32_t ext_address, uint8_t *data, size_t data_length ) { /* * TODO @@ -449,7 +449,7 @@ int store_firmware_data( uint32_t ext_address, uint8_t *data, size_t data_length */ extern uint32_t _estack; -void jump_to_image(uint32_t destination_address) +void fw_slots_jump_to_image(uint32_t destination_address) { if (destination_address) { /* diff --git a/sys/include/fw_slots.h b/sys/include/fw_slots.h index e57c3e96c0b9..be9194996f76 100644 --- a/sys/include/fw_slots.h +++ b/sys/include/fw_slots.h @@ -48,7 +48,7 @@ /* * FW_METADATA_LENGTH: * This is just the size of the FW_metadata_t struct, which is 4-byte - * aligned. We use 104 bytes currently, so this struct will be 104 bytes. + * aligned. We use 76 bytes currently, so this struct will be 76 bytes. */ #define FW_METADATA_LENGTH sizeof(FW_metadata_t) @@ -69,10 +69,10 @@ typedef struct FW_metadata { /** * @brief Print formatted FW image metadata to STDIO. * - * @param[in] metadata Metadata struct to fill with firmware metadata + * @param[in] metadata Metadata struct to fill with firmware metadata * */ -void print_metadata(FW_metadata_t *metadata); +void fw_slots_print_metadata(FW_metadata_t *metadata); /** * @brief Validate internal FW slot as a secure firmware @@ -81,7 +81,7 @@ void print_metadata(FW_metadata_t *metadata); * * @return 0 on success or error code */ -int validate_int_fw_slot(uint8_t fw_slot); +int fw_slots_validate_int_slot(uint8_t fw_slot); /** * @brief Get the internal metadata belonging to an FW slot in internal @@ -90,11 +90,12 @@ int validate_int_fw_slot(uint8_t fw_slot); * @param[in] fw_slot The FW slot to be read for metadata. * * @param[in] *fw_slot_metadata Pointer to the FW_metadata_t struct where - * the metadata is to be written. + * the metadata is to be written. * * @return 0 on success or error code */ -int get_int_metadata(uint8_t fw_slot_page, FW_metadata_t *fw_metadata); +int fw_slots_get_int_metadata(uint8_t fw_slot_page, + FW_metadata_t *fw_metadata); /** * @brief Get the metadata belonging to an FW slot in external flash. @@ -106,7 +107,7 @@ int get_int_metadata(uint8_t fw_slot_page, FW_metadata_t *fw_metadata); * * @return 0 on success or error code */ -int get_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); +int fw_slots_get_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); /** * @brief Get the metadata belonging to an FW slot in internal flash. @@ -118,7 +119,8 @@ int get_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); * * @return 0 on success or error code */ -int get_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); +int fw_slots_get_int_slot_metadata(uint8_t fw_slot, + FW_metadata_t *fw_slot_metadata); /** * @brief Get the address corresponding to a given slot @@ -128,7 +130,7 @@ int get_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); * * @return 0 on success or error code */ -uint32_t get_slot_fw_address(uint8_t fw_slot); +uint32_t fw_slots_get_slot_address(uint8_t fw_slot); /** * @brief Get the page corresponding to a given slot @@ -138,7 +140,7 @@ uint32_t get_slot_fw_address(uint8_t fw_slot); * * @return 0 on success or error code */ -uint32_t get_slot_fw_page(uint8_t fw_slot); +uint32_t fw_slots_get_slot_page(uint8_t fw_slot); /** * @brief Write new metadata to a specific FW slot in internal flash. @@ -149,7 +151,8 @@ uint32_t get_slot_fw_page(uint8_t fw_slot); * * @return 0 on success or error code */ -int overwrite_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); +int fw_slots_overwrite_int_slot_metadata(uint8_t fw_slot, + FW_metadata_t *fw_slot_metadata); /** * @brief Write new metadata to a specific FW slot in external flash. @@ -160,81 +163,80 @@ int overwrite_int_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metad * * @return 0 on success or error code */ -int overwrite_fw_slot_metadata(uint8_t fw_slot, FW_metadata_t *fw_slot_metadata); +int fw_slots_overwrite_slot_metadata(uint8_t fw_slot, + FW_metadata_t *fw_slot_metadata); /** * @brief Copy the current firmware into FW slot 0 as the "Golden Image" * * @return 0 for success or error code */ -int backup_golden_image(void); +int fw_slots_backup_golden_image(void); /** * @brief Given an FW slot, verify the firmware content against the metadata. - * If everything is fine, update the metadata to indicate this FW slot - * is valid. * - * @param[in] fw_slot - FW slot index to verify. (1-3) + * @param[in] fw_slot FW slot index to verify. (1-N) * * @return 0 for success or error code */ -int verify_int_fw_slot(uint8_t fw_slot); +int fw_slots_verify_int_slot(uint8_t fw_slot); /** * @brief Returns true only if the metadata provided indicates the FW slot * is populated and valid. * - * @param[in] *metadata FW metadata to be validated + * @param[in] *metadata FW metadata to be validated * - * @return True if the FW slot is populated and valid. Otherwise, false. + * @return 0 if the FW slot is populated and valid. Otherwise, -1. */ -int validate_fw_metadata(FW_metadata_t *metadata); +int fw_slots_validate_metadata(FW_metadata_t *metadata); /** * @brief Find a FW slot containing firmware matching the supplied * firmware version number. Will only find the first matching * slot. * - * @param[in] version FW slot version. + * @param[in] version FW slot version. * * @return The FW slot index of the matching FW slot. Return -1 in the event * of no match. */ -int find_matching_int_fw_slot(uint16_t version); +int fw_slots_find_matching_int_slot(uint16_t version); /** - * @brief Find the first empty FW download slot. Failing this, find the slot - * with the most out-of-date firmware version. + * @brief Find the first empty FW slot. Failing this, find the slot with the + * most out-of-date firmware version. * - * @return The FW slot index of the empty/oldest FW slot. This will never be + * @return The FW slot index of the empty/oldest FW slot. This will never be * 0 because the Golden Image should never be erased. */ -int find_empty_int_fw_slot(void); +int fw_slots_find_empty_int_slot(void); /** * @brief Find the FW slot containing the most out-of-date firmware version. - * FW slots are in external flash. + * FW slots are in internal flash. * * @return The FW slot index of the oldest firmware version. */ -int find_oldest_int_fw_image(void); +int fw_slots_find_oldest_int_image(void); /** * @brief Find the FW slot containing the most recent firmware version. - * FW slots are in external flash. + * FW slots are in internal flash. * * @return The FW slot index of the newest firmware version. */ -int find_newest_int_fw_image(void); +int fw_slots_find_newest_int_image(void); /** - * @brief Clear an FW slot in external flash. + * @brief Clear an FW slot in internal flash. * - * @param[in] fw_slot The FW slot index of the firmware image to be copied. + * @param[in] fw_slot The FW slot index of the firmware image to be erased. * - * @return 0 or error code + * @return -1 or error code */ -int erase_int_fw_image(uint8_t fw_slot); +int fw_slots_erase_int_image(uint8_t fw_slot); /** * @brief Overwrite firmware located in internal flash with the firmware @@ -242,11 +244,11 @@ int erase_int_fw_image(uint8_t fw_slot); * * @param[in] fw_slot The FW slot index of the firmware image to be copied. * 0 = "Golden Image" backup, aka factory restore - * 1, 2, 3 = FW Download slots + * 1, 2, 3, n = FW Download slots * - * @return 0 or error code + * @return -1 or error code */ -int update_firmware(uint8_t fw_slot); +int fw_slots_update_firmware(uint8_t fw_slot); /** * @brief Store firmware data in external flash at the specified @@ -255,12 +257,10 @@ int update_firmware(uint8_t fw_slot); * @param[in] ext_address External flash address to begin writing data. * * @param[in] data Pointer to the data buffer to be written. - * Note: page_data can be larger than 4096 bytes, but - * only the first 4096 bytes will be written! * - * @return 0 or error code + * @return -1 or error code */ -int store_firmware_data(uint32_t ext_address, uint8_t *data, size_t data_length); +int fw_slots_store_fw_data(uint32_t ext_address, uint8_t *data, size_t data_length); /** * @brief Begin executing another firmware binary located in internal flash. @@ -273,6 +273,6 @@ int store_firmware_data(uint32_t ext_address, uint8_t *data, size_t data_length) * address. * */ -void jump_to_image(uint32_t destination_address); +void fw_slots_jump_to_image(uint32_t destination_address); #endif /* FW_SLOTS_H */ From ce134505a85467f2eef03ecbd4f6b2dac5c3f5a6 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Tue, 24 Jan 2017 01:56:26 +0100 Subject: [PATCH 24/43] examples/firmware_swapping: add second fw slot --- examples/firmware_swapping/Makefile | 65 +++++++++++++++++------------ 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/examples/firmware_swapping/Makefile b/examples/firmware_swapping/Makefile index c51e9dc62cc1..e41e59d1ef57 100644 --- a/examples/firmware_swapping/Makefile +++ b/examples/firmware_swapping/Makefile @@ -7,21 +7,22 @@ RIOTBASE ?= $(CURDIR)/../.. # Activate FW slots FW_SLOTS = 1 -# Select slot 1 -FW_SLOT = 1 +# Define the parameters for the FW slot 1 +FW_IMAGE1_OFFSET = 0x08004000 # Start at page 8 +FW_IMAGE1_LENGTH = 0x3C000 # Reserve 120 pages +FW_METADATA_SPACE = 0x100 # 76 bytes meta-data, 256 byte aligned +FW_IMAGE1_END = 0x08040000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH +VERSION_IMG1 = 0x0 +UUID_IMG1 = 0xabcd1234 + +# Define the parameters for the FW slot 1 +FW_IMAGE2_OFFSET = 0x08040000 # Start at page 128 +FW_IMAGE2_LENGTH = 0x3C000 # Reserve 120 pages +FW_METADATA_SPACE = 0x100 # 76 bytes meta-data, 256 byte aligned +FW_IMAGE1_END = 0x0807C000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH +VERSION_IMG2 = 0x0 +UUID_IMG2 = 0xefab5678 -# Give a version to this build -VERSION = 0x0 - -# Give an UUID -UUID = 0xabcd1234 - -# Define the parameters for the FW Update -FW_IMAGE_OFFSET = 0x08004000 # Start at page 8 -FW_IMAGE_LENGTH = 0x3C000 # Reserve 120 pages -FW_METADATA_SPACE = 0x100 # 108 bytes meta-data, 256 byte aligned -FW_IMAGE_END = 0x08040000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH - bootloader: @cd ../bootloader; \ CFLAGS+=-DFW_METADATA_SPACE=$(FW_METADATA_SPACE) make clean all; \ @@ -29,22 +30,34 @@ bootloader: gcoap-slot1: @cd ../gcoap; \ - CFLAGS="-DFW_SLOT=$(FW_SLOT) -DVERSION=$(VERSION) -DUUID=$(UUID) \ + CFLAGS="-DFW_SLOT=1 -DVERSION=$(VERSION_IMG1) -DUUID=$(UUID_IMG1) \ -DFW_SLOTS=$(FW_SLOTS)" FW_SLOTS=$(FW_SLOTS) \ - FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=$(FW_SLOT) \ - FW_IMAGE_OFFSET=$(FW_IMAGE_OFFSET) FW_IMAGE_LENGTH=$(FW_IMAGE_LENGTH) \ - FW_IMAGE_END=$(FW_IMAGE_END) VERSION=$(VERSION) UUID=$(UUID) \ + FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=1 \ + FW_IMAGE_OFFSET=$(FW_IMAGE1_OFFSET) FW_IMAGE_LENGTH=$(FW_IMAGE1_LENGTH) \ + FW_IMAGE_END=$(FW_IMAGE1_END) VERSION=$(VERSION_IMG1) UUID=$(UUID_IMG1) \ make clean all; \ - cp bin/$(BOARD)/slot-image-$(UUID)-$(VERSION).bin ../firmware_swapping + cp bin/$(BOARD)/slot-image-$(UUID_IMG1)-$(VERSION_IMG1).bin ../firmware_swapping + +default-slot2: + @cd ../default; \ + CFLAGS="-DFW_SLOT=2 -DVERSION=$(VERSION_IMG2) -DUUID=$(UUID_IMG2) \ + -DFW_SLOTS=$(FW_SLOTS)" FW_SLOTS=$(FW_SLOTS) \ + FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=2 \ + FW_IMAGE_OFFSET=$(FW_IMAGE2_OFFSET) FW_IMAGE_LENGTH=$(FW_IMAGE2_LENGTH) \ + FW_IMAGE_END=$(FW_IMAGE2_END) VERSION=$(VERSION_IMG2) UUID=$(UUID_IMG2) \ + make clean all; \ + cp bin/$(BOARD)/slot-image-$(UUID_IMG2)-$(VERSION_IMG2).bin ../firmware_swapping merge-binary: - srec_cat bootloader.hex -intel -crop 0x08000000 $(FW_IMAGE_OFFSET) \ - slot-image-$(UUID)-$(VERSION).bin -binary -offset $(FW_IMAGE_OFFSET) \ - -crop $(FW_IMAGE_OFFSET) $(FW_IMAGE_END) \ - -o firmware-slot-$(FW_SLOT).hex -intel - -master-hex: bootloader gcoap-slot1 merge-binary + srec_cat bootloader.hex -intel -crop 0x08000000 $(FW_IMAGE1_OFFSET) \ + slot-image-$(UUID_IMG1)-$(VERSION_IMG1).bin -binary -offset $(FW_IMAGE1_OFFSET) \ + -crop $(FW_IMAGE1_OFFSET) $(FW_IMAGE1_END) \ + slot-image-$(UUID_IMG2)-$(VERSION_IMG2).bin -binary -offset $(FW_IMAGE2_OFFSET) \ + -crop $(FW_IMAGE2_OFFSET) $(FW_IMAGE2_END) \ + -o firmware-slots.hex -intel + +master-hex: bootloader gcoap-slot1 default-slot2 merge-binary @true clean: - @rm *.hex firmware* *.bin \ No newline at end of file + @rm *.hex *.bin \ No newline at end of file From de9143d0e5539e2c710421d24174572960f24409 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 25 Jan 2017 14:17:27 +0100 Subject: [PATCH 25/43] f cpu/stm32f1/include: fix doxygen issues --- cpu/stm32f1/include/cpu_conf.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cpu/stm32f1/include/cpu_conf.h b/cpu/stm32f1/include/cpu_conf.h index 552675ea4a22..8e0797facd96 100644 --- a/cpu/stm32f1/include/cpu_conf.h +++ b/cpu/stm32f1/include/cpu_conf.h @@ -49,10 +49,12 @@ extern "C" { #endif /** @} */ -/* +/** * @brief Offset to reset handler on VTOR + * @{ */ -#define VTOR_RESET_HANDLER 0x4 +#define VTOR_RESET_HANDLER 0x4 /** One pointer after the beginning */ +/** @} */ #if defined(CPU_MODEL_STM32F103RE) /* From adf699d7704d49fcf0754535f6eacbdf72a90659 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 25 Jan 2017 14:18:43 +0100 Subject: [PATCH 26/43] f dist/tools/firmware_metadata: fix whitespaces --- dist/tools/firmware_metadata/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/tools/firmware_metadata/Makefile b/dist/tools/firmware_metadata/Makefile index 42c9ff280134..969aaa9cd094 100644 --- a/dist/tools/firmware_metadata/Makefile +++ b/dist/tools/firmware_metadata/Makefile @@ -11,9 +11,9 @@ all: bin bin/generate-metadata bin: mkdir bin - + bin/generate-metadata: $(CC) $(CFLAGS) -I$(RIOT_INCLUDE) $(METADATA_SRC) -o $@ clean: - rm -rf bin/generate-metadata + rm -rf bin/generate-metadata \ No newline at end of file From cb267883ebc46f11550d123663e4d9a6c121882b Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 25 Jan 2017 14:19:04 +0100 Subject: [PATCH 27/43] f examples/firmware_swapping: fix whitespaces --- examples/firmware_swapping/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/firmware_swapping/Makefile b/examples/firmware_swapping/Makefile index e41e59d1ef57..863b966c242e 100644 --- a/examples/firmware_swapping/Makefile +++ b/examples/firmware_swapping/Makefile @@ -37,7 +37,7 @@ gcoap-slot1: FW_IMAGE_END=$(FW_IMAGE1_END) VERSION=$(VERSION_IMG1) UUID=$(UUID_IMG1) \ make clean all; \ cp bin/$(BOARD)/slot-image-$(UUID_IMG1)-$(VERSION_IMG1).bin ../firmware_swapping - + default-slot2: @cd ../default; \ CFLAGS="-DFW_SLOT=2 -DVERSION=$(VERSION_IMG2) -DUUID=$(UUID_IMG2) \ @@ -47,7 +47,7 @@ default-slot2: FW_IMAGE_END=$(FW_IMAGE2_END) VERSION=$(VERSION_IMG2) UUID=$(UUID_IMG2) \ make clean all; \ cp bin/$(BOARD)/slot-image-$(UUID_IMG2)-$(VERSION_IMG2).bin ../firmware_swapping - + merge-binary: srec_cat bootloader.hex -intel -crop 0x08000000 $(FW_IMAGE1_OFFSET) \ slot-image-$(UUID_IMG1)-$(VERSION_IMG1).bin -binary -offset $(FW_IMAGE1_OFFSET) \ @@ -58,6 +58,6 @@ merge-binary: master-hex: bootloader gcoap-slot1 default-slot2 merge-binary @true - + clean: @rm *.hex *.bin \ No newline at end of file From cf1a08526486fdd4e311394c8f814b4b6201ff73 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 25 Jan 2017 14:19:41 +0100 Subject: [PATCH 28/43] f sys/include: fix fw_slots.h doxygen --- sys/include/fw_slots.h | 46 +++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/sys/include/fw_slots.h b/sys/include/fw_slots.h index be9194996f76..36062bd8c8f6 100644 --- a/sys/include/fw_slots.h +++ b/sys/include/fw_slots.h @@ -32,6 +32,8 @@ /** * @defgroup sys_fw_slots Firmware slots management * @ingroup sys + * @brief Slots management for several FW in ROM and ext Flash + * @{ * * @file * @brief FW Image R/W and Verification @@ -45,26 +47,35 @@ #include "hashes/sha256.h" -/* - * FW_METADATA_LENGTH: - * This is just the size of the FW_metadata_t struct, which is 4-byte - * aligned. We use 76 bytes currently, so this struct will be 76 bytes. +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief FW_METADATA_LENGTH: + * This is just the size of the FW_metadata_t struct, which is 4-byte + * aligned. We use 76 bytes currently, so this struct will be 76 bytes. */ #define FW_METADATA_LENGTH sizeof(FW_metadata_t) -/* - * SIGN_LEN: - * Provisional length for signed hash +/** + * @brief SIGN_LEN: + * Provisional length for signed hash */ #define SIGN_LEN (SHA256_DIGEST_LENGTH) +/** + * @brief Structure to store firmware metadata + * @{ + */ typedef struct FW_metadata { - uint8_t hash[SHA256_DIGEST_LENGTH]; /* SHA256 Hash of firmware image */ - uint8_t shash[SIGN_LEN]; /* Signed SHA256 */ - uint32_t size; /* Size of firmware image */ - uint32_t uuid; /* Integer representing unique firmware ID */ - uint16_t version; /* Integer representing firmware version */ + uint8_t hash[SHA256_DIGEST_LENGTH]; /**< SHA256 Hash of firmware image */ + uint8_t shash[SIGN_LEN]; /**< Signed SHA256 */ + uint32_t size; /**< Size of firmware image */ + uint32_t uuid; /**< Integer representing unique firmware ID */ + uint16_t version; /**< Integer representing firmware version */ } FW_metadata_t; +/** @} */ /** * @brief Print formatted FW image metadata to STDIO. @@ -85,12 +96,12 @@ int fw_slots_validate_int_slot(uint8_t fw_slot); /** * @brief Get the internal metadata belonging to an FW slot in internal - * flash. + * flash, using the flash page. * - * @param[in] fw_slot The FW slot to be read for metadata. + * @param[in] fw_slot_page The FW slot page to be read for metadata. * - * @param[in] *fw_slot_metadata Pointer to the FW_metadata_t struct where - * the metadata is to be written. + * @param[in] *fw_metadata Pointer to the FW_metadata_t struct where + * the metadata is to be written. * * @return 0 on success or error code */ @@ -258,6 +269,8 @@ int fw_slots_update_firmware(uint8_t fw_slot); * * @param[in] data Pointer to the data buffer to be written. * + * @param[in] data_length Length of the buffer + * * @return -1 or error code */ int fw_slots_store_fw_data(uint32_t ext_address, uint8_t *data, size_t data_length); @@ -276,3 +289,4 @@ int fw_slots_store_fw_data(uint32_t ext_address, uint8_t *data, size_t data_leng void fw_slots_jump_to_image(uint32_t destination_address); #endif /* FW_SLOTS_H */ +/** @} */ From 3e9fdc3711437b61f7f79ec804902b802e193722 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 25 Jan 2017 14:22:55 +0100 Subject: [PATCH 29/43] f sys/include: fix fw_slots.h cpp compat --- sys/include/fw_slots.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/include/fw_slots.h b/sys/include/fw_slots.h index 36062bd8c8f6..4f37022f048e 100644 --- a/sys/include/fw_slots.h +++ b/sys/include/fw_slots.h @@ -288,5 +288,9 @@ int fw_slots_store_fw_data(uint32_t ext_address, uint8_t *data, size_t data_leng */ void fw_slots_jump_to_image(uint32_t destination_address); +#ifdef __cplusplus +} +#endif + #endif /* FW_SLOTS_H */ /** @} */ From 8bb151f82730087ad8774c962f392af65439d48b Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 25 Jan 2017 14:23:26 +0100 Subject: [PATCH 30/43] f sys/fw_slots: fix integer size in printf --- sys/fw_slots/fw_slots.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/fw_slots/fw_slots.c b/sys/fw_slots/fw_slots.c index c2756e3658c3..2c33e34f80cf 100644 --- a/sys/fw_slots/fw_slots.c +++ b/sys/fw_slots/fw_slots.c @@ -355,7 +355,7 @@ int fw_slots_find_oldest_int_image(void) } } - printf("[fw_slots] Oldest FW slot: #%u; Firmware v%u\n", oldest_fw_slot, + printf("[fw_slots] Oldest FW slot: #%d; Firmware v%d\n", oldest_fw_slot, oldest_firmware_version); return oldest_fw_slot; @@ -390,7 +390,7 @@ int fw_slots_find_newest_int_image(void) } } - printf("Newest FW slot: #%u; Firmware v%u\n", newest_fw_slot, + printf("Newest FW slot: #%d; Firmware v%d\n", newest_fw_slot, newest_firmware_version); return newest_fw_slot; From 511a8520976261e774a11b3e15130d7a2516669b Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 25 Jan 2017 14:27:33 +0100 Subject: [PATCH 31/43] cpu/stm32f1: add periph_slots as a feature --- cpu/stm32f1/Makefile.features | 1 + 1 file changed, 1 insertion(+) diff --git a/cpu/stm32f1/Makefile.features b/cpu/stm32f1/Makefile.features index 7a418ea511cb..71946471e0f1 100644 --- a/cpu/stm32f1/Makefile.features +++ b/cpu/stm32f1/Makefile.features @@ -1 +1,2 @@ FEATURES_PROVIDED += periph_pm +FEATURES_PROVIDED += periph_slots \ No newline at end of file From 0b8f2644c69776d3ccd1c99b66342661c10c91ef Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 25 Jan 2017 14:27:57 +0100 Subject: [PATCH 32/43] f Makefile.dep: require periph_slots feature --- Makefile.dep | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.dep b/Makefile.dep index c558a586c4f9..364eeb333f6f 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -613,6 +613,7 @@ endif ifneq (,$(filter fw_slots,$(USEMODULE))) FEATURES_REQUIRED += periph_flashpage + FEATURES_REQUIRED += periph_slots USEMODULE += hashes endif From 7eeafc5ad0c601c67f10d4f2ad4021385d5cfa93 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 1 Mar 2017 16:12:47 +0100 Subject: [PATCH 33/43] f cpu/Makefile.include.cortexm_common: no need of ld --- cpu/Makefile.include.cortexm_common | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpu/Makefile.include.cortexm_common b/cpu/Makefile.include.cortexm_common index 0e4469d3f5ae..d21eba4be54a 100644 --- a/cpu/Makefile.include.cortexm_common +++ b/cpu/Makefile.include.cortexm_common @@ -20,12 +20,12 @@ export ASFLAGS += $(CFLAGS_CPU) $(CFLAGS_DBG) # reflecting the FW_IMAGE_OFFSET and FW_IMAGE_LENGTH values defined in the # target project's Makefile. ifeq ($(FW_SLOTS),1) -FWDEFINES = -DFW_IMAGE_OFFSET=$(FW_IMAGE_OFFSET) -DFW_IMAGE_LENGTH=$(FW_IMAGE_LENGTH) \ - -DFW_METADATA_SPACE=$(FW_METADATA_SPACE) -CFLAGS += $(FWDEFINES) -GENERATE_LDSCRIPT = $(Q)$(LINK) -P -E $(FWDEFINES) $(RIOTCPU)/$(CPU)/ldscripts/$(CPU_MODEL)-slots.c \ - -o $(RIOTCPU)/$(CPU)/ldscripts/$(CPU_MODEL)-slots.ld -LINKER_SCRIPT = $(CPU_MODEL)-slots.ld +ifeq ($(FW_SLOT),1) +LINKER_SCRIPT = $(CPU_MODEL)_slot1.ld +endif +ifeq ($(FW_SLOT),2) +LINKER_SCRIPT = $(CPU_MODEL)_slot2.ld +endif endif # If we compile a bootloader, set the correct linker script From 6e99a86696dbbcbdb843faa5a500785ea661cae7 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 1 Mar 2017 16:13:03 +0100 Subject: [PATCH 34/43] f Makefile.include: remove ld generation --- Makefile.include | 3 --- 1 file changed, 3 deletions(-) diff --git a/Makefile.include b/Makefile.include index d1ffa6ebc995..f43e65132712 100644 --- a/Makefile.include +++ b/Makefile.include @@ -281,9 +281,6 @@ else ## make script for your application. Build RIOT-base here! all: ..compiler-check ..build-message $(RIOTBUILD_CONFIG_HEADER_C) $(USEPKG:%=${BINDIR}/%.a) $(APPDEPS) $(Q)DIRS="$(DIRS)" "$(MAKE)" -C $(APPDIR) -f $(RIOTBASE)/Makefile.application -ifeq ($(FW_SLOTS),1) - $(GENERATE_LDSCRIPT) -endif ifeq (,$(RIOTNOLINK)) ifeq ($(BUILDOSXNATIVE),1) $(Q)$(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) -o $(ELFFILE) $$(find $(BASELIBS) -size +8c) $(LINKFLAGS) $(LINKFLAGPREFIX)-no_pie From f3c0b13ae611b415e3a2212073cea853bb38452a Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 1 Mar 2017 16:13:55 +0100 Subject: [PATCH 35/43] f expamples/firmware_swapping: reduce address defines --- examples/firmware_swapping/Makefile | 31 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/examples/firmware_swapping/Makefile b/examples/firmware_swapping/Makefile index 863b966c242e..a30ac45b2fbc 100644 --- a/examples/firmware_swapping/Makefile +++ b/examples/firmware_swapping/Makefile @@ -7,10 +7,11 @@ RIOTBASE ?= $(CURDIR)/../.. # Activate FW slots FW_SLOTS = 1 +FW_METADATA_SPACE = 0x100 # 76 bytes meta-data, 256 byte aligned + # Define the parameters for the FW slot 1 FW_IMAGE1_OFFSET = 0x08004000 # Start at page 8 FW_IMAGE1_LENGTH = 0x3C000 # Reserve 120 pages -FW_METADATA_SPACE = 0x100 # 76 bytes meta-data, 256 byte aligned FW_IMAGE1_END = 0x08040000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH VERSION_IMG1 = 0x0 UUID_IMG1 = 0xabcd1234 @@ -18,33 +19,30 @@ UUID_IMG1 = 0xabcd1234 # Define the parameters for the FW slot 1 FW_IMAGE2_OFFSET = 0x08040000 # Start at page 128 FW_IMAGE2_LENGTH = 0x3C000 # Reserve 120 pages -FW_METADATA_SPACE = 0x100 # 76 bytes meta-data, 256 byte aligned FW_IMAGE1_END = 0x0807C000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH -VERSION_IMG2 = 0x0 -UUID_IMG2 = 0xefab5678 +VERSION_IMG2 = 0x1 +UUID_IMG2 = 0xabcd1234 bootloader: @cd ../bootloader; \ CFLAGS+=-DFW_METADATA_SPACE=$(FW_METADATA_SPACE) make clean all; \ cp bin/$(BOARD)/bootloader.hex ../firmware_swapping -gcoap-slot1: - @cd ../gcoap; \ +gnrc_networking-slot1: + @cd ../gnrc_networking; \ CFLAGS="-DFW_SLOT=1 -DVERSION=$(VERSION_IMG1) -DUUID=$(UUID_IMG1) \ -DFW_SLOTS=$(FW_SLOTS)" FW_SLOTS=$(FW_SLOTS) \ FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=1 \ - FW_IMAGE_OFFSET=$(FW_IMAGE1_OFFSET) FW_IMAGE_LENGTH=$(FW_IMAGE1_LENGTH) \ - FW_IMAGE_END=$(FW_IMAGE1_END) VERSION=$(VERSION_IMG1) UUID=$(UUID_IMG1) \ + VERSION=$(VERSION_IMG1) UUID=$(UUID_IMG1) \ make clean all; \ cp bin/$(BOARD)/slot-image-$(UUID_IMG1)-$(VERSION_IMG1).bin ../firmware_swapping -default-slot2: - @cd ../default; \ +gnrc_networking-slot2: + @cd ../gnrc_networking; \ CFLAGS="-DFW_SLOT=2 -DVERSION=$(VERSION_IMG2) -DUUID=$(UUID_IMG2) \ -DFW_SLOTS=$(FW_SLOTS)" FW_SLOTS=$(FW_SLOTS) \ FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=2 \ - FW_IMAGE_OFFSET=$(FW_IMAGE2_OFFSET) FW_IMAGE_LENGTH=$(FW_IMAGE2_LENGTH) \ - FW_IMAGE_END=$(FW_IMAGE2_END) VERSION=$(VERSION_IMG2) UUID=$(UUID_IMG2) \ + VERSION=$(VERSION_IMG2) UUID=$(UUID_IMG2) \ make clean all; \ cp bin/$(BOARD)/slot-image-$(UUID_IMG2)-$(VERSION_IMG2).bin ../firmware_swapping @@ -56,8 +54,13 @@ merge-binary: -crop $(FW_IMAGE2_OFFSET) $(FW_IMAGE2_END) \ -o firmware-slots.hex -intel -master-hex: bootloader gcoap-slot1 default-slot2 merge-binary +master-hex: bootloader gnrc_networking-slot1 gnrc_networking-slot2 merge-binary @true clean: - @rm *.hex *.bin \ No newline at end of file + @rm *.hex *.bin + +flash: + OPENOCD_CONFIG=../../boards/$(BOARD)/dist/openocd.cfg \ + HEXFILE=firmware-slots.hex \ + ../../dist/tools/openocd/openocd.sh flash \ No newline at end of file From 0c83e30938fc4f47258a07ecf31bbec2c981cc61 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 1 Mar 2017 16:15:02 +0100 Subject: [PATCH 36/43] f cpu/stm32f1/ldscripts: no more ld generation --- cpu/stm32f1/ldscripts/.gitignore | 1 - cpu/stm32f1/ldscripts/stm32f103re-slots.c | 31 ----------------------- 2 files changed, 32 deletions(-) delete mode 100644 cpu/stm32f1/ldscripts/.gitignore delete mode 100644 cpu/stm32f1/ldscripts/stm32f103re-slots.c diff --git a/cpu/stm32f1/ldscripts/.gitignore b/cpu/stm32f1/ldscripts/.gitignore deleted file mode 100644 index dfde6fe8c3fc..000000000000 --- a/cpu/stm32f1/ldscripts/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/stm32f103re-slots.ld diff --git a/cpu/stm32f1/ldscripts/stm32f103re-slots.c b/cpu/stm32f1/ldscripts/stm32f103re-slots.c deleted file mode 100644 index c1ab60c90bc2..000000000000 --- a/cpu/stm32f1/ldscripts/stm32f103re-slots.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2015 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @addtogroup cpu_stm32f1 - * @{ - * - * @file - * @brief Memory definitions for different FW slots on - * the STM32F103RE - * - * @author Hauke Petersen - * - * @} - */ - -MEMORY -{ - rom (rx) : ORIGIN = (FW_IMAGE_OFFSET + FW_METADATA_SPACE), LENGTH = FW_IMAGE_LENGTH - ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K - cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 -} - -_cpuid_address = ORIGIN(cpuid); - -INCLUDE cortexm_base.ld From 600d964a8c6ecad12efbf2de92278f4975ad9e67 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 1 Mar 2017 16:15:38 +0100 Subject: [PATCH 37/43] cpu/stm32f1/ldscripts: add fixed slot ld scripts --- cpu/stm32f1/ldscripts/stm32f103re_slot1.ld | 30 ++++++++++++++++++++++ cpu/stm32f1/ldscripts/stm32f103re_slot2.ld | 30 ++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 cpu/stm32f1/ldscripts/stm32f103re_slot1.ld create mode 100644 cpu/stm32f1/ldscripts/stm32f103re_slot2.ld diff --git a/cpu/stm32f1/ldscripts/stm32f103re_slot1.ld b/cpu/stm32f1/ldscripts/stm32f103re_slot1.ld new file mode 100644 index 000000000000..b3c457fba4a2 --- /dev/null +++ b/cpu/stm32f1/ldscripts/stm32f103re_slot1.ld @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup cpu_stm32f1 + * @{ + * + * @file + * @brief Memory definitions for the STM32F103RE Slot 0 + * + * @author Francisco Acosta + * + * @} + */ + +MEMORY +{ + rom (rx) : ORIGIN = 0x08004100, LENGTH = 0x3C000 + ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K + cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 +} + +_cpuid_address = ORIGIN(cpuid); + +INCLUDE cortexm_base.ld diff --git a/cpu/stm32f1/ldscripts/stm32f103re_slot2.ld b/cpu/stm32f1/ldscripts/stm32f103re_slot2.ld new file mode 100644 index 000000000000..4ea73fb00007 --- /dev/null +++ b/cpu/stm32f1/ldscripts/stm32f103re_slot2.ld @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2017 Inria + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @addtogroup cpu_stm32f1 + * @{ + * + * @file + * @brief Memory definitions for the STM32F103RE Slot 1 + * + * @author Francisco Acosta + * + * @} + */ + +MEMORY +{ + rom (rx) : ORIGIN = 0x08040100, LENGTH = 0x3C000 + ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K + cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 +} + +_cpuid_address = ORIGIN(cpuid); + +INCLUDE cortexm_base.ld From 281c1c824b52e8619ef1a1c97998bfd34aea43ec Mon Sep 17 00:00:00 2001 From: kYc0o Date: Wed, 1 Mar 2017 17:30:29 +0100 Subject: [PATCH 38/43] f Makefile.include: alignment --- Makefile.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.include b/Makefile.include index f43e65132712..ad99725dd907 100644 --- a/Makefile.include +++ b/Makefile.include @@ -11,7 +11,7 @@ RIOTBOARD ?= $(RIOTBASE)/boards RIOTPKG ?= $(RIOTBASE)/pkg RIOTPROJECT ?= $(shell git rev-parse --show-toplevel 2>/dev/null || pwd) GITCACHE ?= $(RIOTBASE)/dist/tools/git/git-cache -FW_METADATA ?= $(RIOTBASE)/dist/tools/firmware_metadata +FW_METADATA ?= $(RIOTBASE)/dist/tools/firmware_metadata APPDIR ?= $(CURDIR) BINDIRBASE ?= $(APPDIR)/bin BINDIR ?= $(BINDIRBASE)/$(BOARD) From f7021b8d699f121feafa1039b89eafdf538e2675 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Thu, 2 Mar 2017 18:43:12 +0100 Subject: [PATCH 39/43] f examples/bootloader: boot newest image --- examples/bootloader/main.c | 138 +++++-------------------------------- 1 file changed, 18 insertions(+), 120 deletions(-) diff --git a/examples/bootloader/main.c b/examples/bootloader/main.c index 9d9225333596..f6af8bef7985 100644 --- a/examples/bootloader/main.c +++ b/examples/bootloader/main.c @@ -22,136 +22,34 @@ #include #include -#include "thread.h" -#include "shell.h" -#include "shell_commands.h" #include "fw_slots.h" -#include "cpu_conf.h" -static int cmd_lsimg(int argc, char **argv) -{ - (void)argc; - (void)argv; - - FW_metadata_t fw_metadata; - - for (uint8_t i = 1; i <= MAX_FW_SLOTS; i++) { - if (fw_slots_get_int_slot_metadata(i, &fw_metadata) == 0) { - printf("Metadata slot %d:\n", i); - fw_slots_print_metadata(&fw_metadata); - } else { - printf("ERROR: Cannot retrieve metadata.\n"); - } - } - - return 0; -} - -static int cmd_get_metadata(int argc, char **argv) -{ - uint8_t slot; - FW_metadata_t fw_metadata; - - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } - - slot = atoi(argv[1]); - - if (fw_slots_get_int_slot_metadata(slot, &fw_metadata) == 0) { - printf("Metadata slot %d\n", slot); - fw_slots_print_metadata(&fw_metadata); - return 0; - } else { - printf("ERROR: Cannot retrieve metadata from slot %d.\n", slot); - return -1; - } - - return 0; -} - -static int cmd_verify(int argc, char **argv) -{ - uint8_t slot; - - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } - - slot = atoi(argv[1]); - - if (fw_slots_verify_int_slot(slot) == 0) { - printf("Slot %d successfully verified\n", slot); - return 0; - } else { - return -1; - } - - return 0; -} - -static int cmd_erase_slot(int argc, char**argv) -{ - uint8_t slot; - - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } - - slot = atoi(argv[1]); - - return fw_slots_erase_int_image(slot); -} - -static int cmd_jump(int argc, char **argv) +int main(void) { + uint8_t boot_slot = 0; uint32_t address; - uint8_t slot; + (void) puts("Welcome to RIOT bootloader!\n"); + (void) puts("Trying to boot the newest firmware version\n"); - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } + boot_slot = fw_slots_find_newest_int_image(); - slot = atoi(argv[1]); - - if (fw_slots_verify_int_slot(slot) == 0) { - printf("Slot %d verified!\n", slot); + if (boot_slot > 0) { + if (fw_slots_verify_int_slot(boot_slot) == 0) { + printf("Image on slot %d verified! Booting...\n", boot_slot); + address = fw_slots_get_slot_address(boot_slot); + fw_slots_jump_to_image(address); + } else { + printf("Slot %u inconsistent!\n", boot_slot); + } } else { - printf("Slot %u inconsistent!\n", slot); - return -1; + (void) puts("No bootable slot found!\n"); } - address = fw_slots_get_slot_address(slot); - - printf("Booting slot %d at 0x%lx...\n", slot, address); - - fw_slots_jump_to_image(address); - - return 0; -} - -static const shell_command_t shell_commands[] = { - { "lsimg", "List the available firmwares on ROM", cmd_lsimg }, - { "get_metadata", "Get metadata from slot", cmd_get_metadata }, - { "verify", "Verify consistency (sha256) of slot", cmd_verify }, - { "erase", "Erase slot *WARNING use with caution*", cmd_erase_slot }, - { "jump", "Jump to specific FW slot (cause reset)", cmd_jump }, - { NULL, NULL, NULL } -}; - -int main(void) -{ - (void) puts("Welcome to RIOT bootloader!"); - - /* run the shell */ - char line_buf[SHELL_DEFAULT_BUFSIZE]; - shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + /* + * TODO Add serial bootloader + */ - /* Should never happen */ + /* Should not happen */ return 0; } From 9648d6ae6383e662a1719aa6d76a080defa09849 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Thu, 2 Mar 2017 18:44:24 +0100 Subject: [PATCH 40/43] f sys/fw_slots: fix bug finding newest image --- sys/fw_slots/fw_slots.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/fw_slots/fw_slots.c b/sys/fw_slots/fw_slots.c index 2c33e34f80cf..c2882675f319 100644 --- a/sys/fw_slots/fw_slots.c +++ b/sys/fw_slots/fw_slots.c @@ -379,7 +379,7 @@ int fw_slots_find_newest_int_image(void) } /* Is this slot populated? If not, skip. */ - if (fw_slots_validate_metadata( &fw_slot_metadata) == false) { + if (fw_slots_validate_metadata(&fw_slot_metadata) == -1) { continue; } From 5b3cb9fa76af27f344e5afc255e7e97f05a17272 Mon Sep 17 00:00:00 2001 From: kYc0o Date: Thu, 2 Mar 2017 19:03:29 +0100 Subject: [PATCH 41/43] f examples/bootloader: fix style --- examples/bootloader/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/bootloader/main.c b/examples/bootloader/main.c index f6af8bef7985..aa264455301c 100644 --- a/examples/bootloader/main.c +++ b/examples/bootloader/main.c @@ -27,7 +27,6 @@ int main(void) { uint8_t boot_slot = 0; - uint32_t address; (void) puts("Welcome to RIOT bootloader!\n"); (void) puts("Trying to boot the newest firmware version\n"); @@ -36,6 +35,7 @@ int main(void) if (boot_slot > 0) { if (fw_slots_verify_int_slot(boot_slot) == 0) { + uint32_t address; printf("Image on slot %d verified! Booting...\n", boot_slot); address = fw_slots_get_slot_address(boot_slot); fw_slots_jump_to_image(address); From 98ace9e221f78d6acf5bfd31316deec0cc90f82b Mon Sep 17 00:00:00 2001 From: kYc0o Date: Mon, 20 Mar 2017 16:24:12 +0100 Subject: [PATCH 42/43] f examples/firmware_swapping: change versions to 1 and 2 --- examples/firmware_swapping/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/firmware_swapping/Makefile b/examples/firmware_swapping/Makefile index a30ac45b2fbc..0b37dc8a7fa3 100644 --- a/examples/firmware_swapping/Makefile +++ b/examples/firmware_swapping/Makefile @@ -13,14 +13,14 @@ FW_METADATA_SPACE = 0x100 # 76 bytes meta-data, 256 byte aligned FW_IMAGE1_OFFSET = 0x08004000 # Start at page 8 FW_IMAGE1_LENGTH = 0x3C000 # Reserve 120 pages FW_IMAGE1_END = 0x08040000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH -VERSION_IMG1 = 0x0 +VERSION_IMG1 = 0x1 UUID_IMG1 = 0xabcd1234 # Define the parameters for the FW slot 1 FW_IMAGE2_OFFSET = 0x08040000 # Start at page 128 FW_IMAGE2_LENGTH = 0x3C000 # Reserve 120 pages FW_IMAGE1_END = 0x0807C000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH -VERSION_IMG2 = 0x1 +VERSION_IMG2 = 0x2 UUID_IMG2 = 0xabcd1234 bootloader: From 1f549647b337c291ac72353697bc6d83992c2320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Harter?= Date: Tue, 4 Apr 2017 17:45:06 +0200 Subject: [PATCH 43/43] firmware_swapping: compile to an elf file Allow compiling any firmware by using: make FIRMWARE=firmware_name Main thing to make it work was adding 'romslot1' and 'romslot2' in the bootloader linker script with the section names '.slot.1.*' The bootloader is compiled with .o of the firmware slots. To create the firmware slots .o files, I use objcopy to load the binaries at sections called '.slot.1.*'. --- .../ldscripts/stm32f103re-bootloader.ld | 17 ++ examples/firmware_swapping/Makefile | 159 ++++++++++++------ 2 files changed, 127 insertions(+), 49 deletions(-) diff --git a/cpu/stm32f1/ldscripts/stm32f103re-bootloader.ld b/cpu/stm32f1/ldscripts/stm32f103re-bootloader.ld index 02d4af946efc..fcffe7e5a93f 100644 --- a/cpu/stm32f1/ldscripts/stm32f103re-bootloader.ld +++ b/cpu/stm32f1/ldscripts/stm32f103re-bootloader.ld @@ -21,6 +21,8 @@ MEMORY { rom (rx) : ORIGIN = 0x08000000, LENGTH = 16K + romslot1 (rx) : ORIGIN = 0x08004000, LENGTH = 0x3C100 + romslot2 (rx) : ORIGIN = 0x08040000, LENGTH = 0x3C100 ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12 } @@ -28,3 +30,18 @@ MEMORY _cpuid_address = ORIGIN(cpuid); INCLUDE cortexm_base.ld + +SECTIONS +{ + . = ALIGN(0x1000); + .slot.1 : + { + KEEP(*(.slot.1.*)) + } > romslot1 + + . = ALIGN(0x1000); + .slot.2 : + { + KEEP(*(.slot.2.*)) + } > romslot2 +} diff --git a/examples/firmware_swapping/Makefile b/examples/firmware_swapping/Makefile index 0b37dc8a7fa3..b0f8a706c5da 100644 --- a/examples/firmware_swapping/Makefile +++ b/examples/firmware_swapping/Makefile @@ -4,63 +4,124 @@ export BOARD ?= iotlab-m3 # This has to be the absolute path to the RIOT base directory: RIOTBASE ?= $(CURDIR)/../.. -# Activate FW slots -FW_SLOTS = 1 -FW_METADATA_SPACE = 0x100 # 76 bytes meta-data, 256 byte aligned +FIRMWARE ?= gnrc_networking # Define the parameters for the FW slot 1 -FW_IMAGE1_OFFSET = 0x08004000 # Start at page 8 -FW_IMAGE1_LENGTH = 0x3C000 # Reserve 120 pages -FW_IMAGE1_END = 0x08040000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH -VERSION_IMG1 = 0x1 -UUID_IMG1 = 0xabcd1234 +VERSION_IMAGE_1 = 0x1 +UUID_IMAGE_1 = 0xabcd1234 # Define the parameters for the FW slot 1 -FW_IMAGE2_OFFSET = 0x08040000 # Start at page 128 -FW_IMAGE2_LENGTH = 0x3C000 # Reserve 120 pages -FW_IMAGE1_END = 0x0807C000 # FW_IMAGE_OFFSET + FW_IMAGE_LENGTH -VERSION_IMG2 = 0x2 -UUID_IMG2 = 0xabcd1234 - -bootloader: - @cd ../bootloader; \ - CFLAGS+=-DFW_METADATA_SPACE=$(FW_METADATA_SPACE) make clean all; \ - cp bin/$(BOARD)/bootloader.hex ../firmware_swapping - -gnrc_networking-slot1: - @cd ../gnrc_networking; \ - CFLAGS="-DFW_SLOT=1 -DVERSION=$(VERSION_IMG1) -DUUID=$(UUID_IMG1) \ - -DFW_SLOTS=$(FW_SLOTS)" FW_SLOTS=$(FW_SLOTS) \ - FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=1 \ - VERSION=$(VERSION_IMG1) UUID=$(UUID_IMG1) \ - make clean all; \ - cp bin/$(BOARD)/slot-image-$(UUID_IMG1)-$(VERSION_IMG1).bin ../firmware_swapping - -gnrc_networking-slot2: - @cd ../gnrc_networking; \ - CFLAGS="-DFW_SLOT=2 -DVERSION=$(VERSION_IMG2) -DUUID=$(UUID_IMG2) \ - -DFW_SLOTS=$(FW_SLOTS)" FW_SLOTS=$(FW_SLOTS) \ - FW_METADATA_SPACE=$(FW_METADATA_SPACE) FW_SLOT=2 \ - VERSION=$(VERSION_IMG2) UUID=$(UUID_IMG2) \ - make clean all; \ - cp bin/$(BOARD)/slot-image-$(UUID_IMG2)-$(VERSION_IMG2).bin ../firmware_swapping - -merge-binary: - srec_cat bootloader.hex -intel -crop 0x08000000 $(FW_IMAGE1_OFFSET) \ - slot-image-$(UUID_IMG1)-$(VERSION_IMG1).bin -binary -offset $(FW_IMAGE1_OFFSET) \ - -crop $(FW_IMAGE1_OFFSET) $(FW_IMAGE1_END) \ - slot-image-$(UUID_IMG2)-$(VERSION_IMG2).bin -binary -offset $(FW_IMAGE2_OFFSET) \ - -crop $(FW_IMAGE2_OFFSET) $(FW_IMAGE2_END) \ - -o firmware-slots.hex -intel - -master-hex: bootloader gnrc_networking-slot1 gnrc_networking-slot2 merge-binary - @true +VERSION_IMAGE_2 = 0x2 +UUID_IMAGE_2 = 0xabcd1234 + + + +# # # # # # # # # # # # # +# General configuration # +# # # # # # # # # # # # # + +# Activate FW slots +FW_SLOTS = 1 + +FW_METADATA_SPACE = 0x100 # 76 bytes meta-data, 256 byte aligned +FIRMWARE_IMAGE_OFFSET_1 = 0x08004000 # Start at page 8 +FIRMWARE_IMAGE_OFFSET_2 = 0x08040000 # Start at page 128 + +# OBJCOPY config (specific for M3 nodes should use +OBJCOPY ?= arm-none-eabi-objcopy +OBJCOPYFLAGS = --output-target elf32-littlearm +OBJCOPYFLAGS += --binary-architecture=arm + +# Configured output by root Makefile.include +# $* will be replaced by the slot number +FIRMWARE_PATH = ../$(FIRMWARE) +FIRMWARE_BIN_PATH = $(FIRMWARE_PATH)/bin/$(BOARD) +FIRMWARE_SLOT_BIN=$(FIRMWARE_BIN_PATH)/slot-image-$(UUID_IMAGE_$*)-$(VERSION_IMAGE_$*).bin + + +.PHONY: all generate-metadata bootloader-$(FIRMWARE).elf + +all: bootloader-$(FIRMWARE).elf + +SLOTS = $(FIRMWARE)-slot-1.o $(FIRMWARE)-slot-2.o + +bootloader-$(FIRMWARE).elf: $(FIRMWARE)-slot-1.o $(FIRMWARE)-slot-2.o + CFLAGS+=-DFW_METADATA_SPACE=$(FW_METADATA_SPACE) \ + BASELIBS+=" $(CURDIR)/$(FIRMWARE)-slot-1.o" \ + BASELIBS+=" $(CURDIR)/$(FIRMWARE)-slot-2.o" \ + ELFFILE=$(CURDIR)/$@ \ + make -C ../bootloader clean all + + +$(SLOTS): $(FIRMWARE)-slot-%.o: generate-metadata + CFLAGS="-DFW_SLOT=$* \ + -DVERSION=$(VERSION_IMAGE_$*) \ + -DUUID=$(UUID_IMAGE_$*) \ + -DFW_SLOTS=$(FW_SLOTS)" \ + FW_SLOTS=$(FW_SLOTS) FW_SLOT=$* \ + FW_METADATA_SPACE=$(FW_METADATA_SPACE) \ + VERSION=$(VERSION_IMAGE_$*) UUID=$(UUID_IMAGE_$*) \ + make -C $(FIRMWARE_PATH) clean all + @ + $(OBJCOPY) $(OBJCOPYFLAGS) \ + --change-section-vma .data=$(FIRMWARE_IMAGE_OFFSET_$*)\ + --change-section-lma .data=$(FIRMWARE_IMAGE_OFFSET_$*)\ + --rename-section .data=.slot.$*.text \ + --input-target binary $(FIRMWARE_SLOT_BIN) \ + $@ + + +# +# Version without using the magic with $* to get slot number +# +# FIRMWARE_SLOT_1 = slot-image-$(UUID_IMAGE_1)-$(VERSION_IMAGE_1).bin +# $(FIRMWARE)-slot-1.o: +# CFLAGS="-DFW_SLOT=1 -DVERSION=$(VERSION_IMAGE_1) -DUUID=$(UUID_IMAGE_1) \ +# -DFW_SLOTS=$(FW_SLOTS)" \ +# FW_SLOTS=$(FW_SLOTS) FW_SLOT=1 \ +# FW_METADATA_SPACE=$(FW_METADATA_SPACE) \ +# VERSION=$(VERSION_IMAGE_1) UUID=$(UUID_IMAGE_1) \ +# make -C $(FIRMWARE_PATH) clean all +# @ +# cp $(FIRMWARE_PATH)/bin/$(BOARD)/$(FIRMWARE_SLOT_1) $(FIRMWARE_SLOT_1) +# @ +# $(OBJCOPY) $(OBJCOPYFLAGS) \ +# --change-section-vma .data=$(FIRMWARE_IMAGE_OFFSET_1)\ +# --change-section-lma .data=$(FIRMWARE_IMAGE_OFFSET_1)\ +# --rename-section .data=.slot.1.text \ +# --input-target binary $(FIRMWARE_SLOT_1) \ +# $@ +# +# FIRMWARE_SLOT_2 = slot-image-$(UUID_IMAGE_2)-$(VERSION_IMAGE_2).bin +# $(FIRMWARE)-slot-2.o: +# CFLAGS="-DFW_SLOT=2 -DVERSION=$(VERSION_IMAGE_2) -DUUID=$(UUID_IMAGE_2) \ +# -DFW_SLOTS=$(FW_SLOTS)" \ +# FW_SLOTS=$(FW_SLOTS) FW_SLOT=2 \ +# FW_METADATA_SPACE=$(FW_METADATA_SPACE) \ +# VERSION=$(VERSION_IMAGE_2) UUID=$(UUID_IMAGE_2) \ +# make -C $(FIRMWARE_PATH) clean all +# @ +# cp $(FIRMWARE_PATH)/bin/$(BOARD)/$(FIRMWARE_SLOT_2) $(FIRMWARE_SLOT_2) +# @ +# $(OBJCOPY) $(OBJCOPYFLAGS) \ +# --change-section-vma .data=$(FIRMWARE_IMAGE_OFFSET_2)\ +# --change-section-lma .data=$(FIRMWARE_IMAGE_OFFSET_2)\ +# --rename-section .data=.slot.2.text \ +# --input-target binary $(FIRMWARE_SLOT_2) \ +# $@ + + +GENERATE_METADA_DIR = ../../dist/tools/firmware_metadata +generate-metadata: $(GENERATE_METADA_DIR)/bin/generate-metadata + +$(GENERATE_METADA_DIR)/bin/generate-metadata: + make -C $(GENERATE_METADA_DIR) clean: - @rm *.hex *.bin + @rm -f *.hex *.bin *.elf *.o flash: OPENOCD_CONFIG=../../boards/$(BOARD)/dist/openocd.cfg \ HEXFILE=firmware-slots.hex \ - ../../dist/tools/openocd/openocd.sh flash \ No newline at end of file + ../../dist/tools/openocd/openocd.sh flash