Skip to content

Commit

Permalink
🔀 Merge branch 'yann/feature/basic-bootloader' into develop
Browse files Browse the repository at this point in the history
* yann/feature/basic-bootloader:
  🙈 (firmware): Ignore _tmp and _release folders
  🔨 (firmware): Script to generate firmware
  🚚 (mcuboot): Add spikes to demonstrate how to use mcuboot in apps
  🎉 (boot): Add bootloader
  🚚 (cmake): Rename ENABLE_BOOTLOADER to BUILD_TARGETS_TO_USE_WITH_BOOTLOADER
  🔧 (mcuboot): Add missing macro to use MCUBoot in bootloader or apps
  🐛 (qspi): Up address size from 8 to 24bits
  • Loading branch information
ladislas committed Oct 15, 2021
2 parents 103c9f5 + 67edae7 commit b1eefc4
Show file tree
Hide file tree
Showing 19 changed files with 501 additions and 19 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -12,6 +12,8 @@ cmake/config/
.clangd
*.ioc.csv
cube_path.json
_release
_tmp


#
Expand Down
36 changes: 23 additions & 13 deletions CMakeLists.txt
Expand Up @@ -53,14 +53,14 @@ set(MBED_OS_DIR ${ROOT_DIR}/extern/mbed-os)
set(MCUBOOT_DIR ${ROOT_DIR}/extern/mcuboot/boot)

# Bootloader option
option(ENABLE_BOOTLOADER "Build LekaOS with bootloader" OFF)
message(STATUS "ENABLE_BOOTLOADER (Build LekaOS with bootloader) --> ${ENABLE_BOOTLOADER}")
if (ENABLE_BOOTLOADER)
option(BUILD_TARGETS_TO_USE_WITH_BOOTLOADER "Build targets with padding to use with bootloader" OFF)
message(STATUS "Build targets with padding to use with bootloader --> ${BUILD_TARGETS_TO_USE_WITH_BOOTLOADER}")
if (BUILD_TARGETS_TO_USE_WITH_BOOTLOADER)
set(MBED_APP_FLAGS
-DMBED_APP_START=0x08040000
-DMBED_APP_SIZE=0x180000
-DMBED_APP_START=0x08041000
-DMBED_APP_SIZE=0x17E000
)
endif(ENABLE_BOOTLOADER)
endif(BUILD_TARGETS_TO_USE_WITH_BOOTLOADER)

# And include mbed-cmake.cmake
include(./mbed-cmake.cmake)
Expand All @@ -76,13 +76,14 @@ if(CMAKE_EXPORT_COMPILE_COMMANDS)
endif()

# For convenience you can define useful variables
set(OS_DIR ${ROOT_DIR}/src)
set(LIBS_DIR ${ROOT_DIR}/libs)
set(TESTS_DIR ${ROOT_DIR}/tests)
set(SPIKES_DIR ${ROOT_DIR}/spikes)
set(DRIVERS_DIR ${ROOT_DIR}/drivers)
set(TARGETS_DIR ${ROOT_DIR}/targets)
set(INCLUDE_DIR ${ROOT_DIR}/include)
set(OS_DIR ${ROOT_DIR}/src)
set(LIBS_DIR ${ROOT_DIR}/libs)
set(TESTS_DIR ${ROOT_DIR}/tests)
set(SPIKES_DIR ${ROOT_DIR}/spikes)
set(DRIVERS_DIR ${ROOT_DIR}/drivers)
set(TARGETS_DIR ${ROOT_DIR}/targets)
set(INCLUDE_DIR ${ROOT_DIR}/include)
set(BOOTLOADER_DIR ${ROOT_DIR}/bootloader)

# Add custom target subdirectory
set(AVAILABLE_CUSTOM_TARGETS DISCO_ORIGINAL LEKA_V1_0_DEV LEKA_V1_1_DEV LEKA_V1_2_DEV)
Expand Down Expand Up @@ -114,6 +115,12 @@ link_libraries(
)

# Add external libraries
add_compile_definitions(MCUBOOT_BOOTLOADER_SIZE=0x40000)
add_compile_definitions(MCUBOOT_SCRATCH_SIZE=0x40000)
add_compile_definitions(MCUBOOT_SCRATCH_START_ADDR=0x081C0000)
add_compile_definitions(MCUBOOT_RSA_SIGNATURE_LENGTH=2048)
add_compile_definitions(MCUBOOT_SLOT_SIZE=0x200000-MCUBOOT_BOOTLOADER_SIZE-MCUBOOT_SCRATCH_SIZE)

add_subdirectory(${MCUBOOT_DIR})

# Add drivers & libraries
Expand All @@ -124,6 +131,9 @@ add_subdirectory(${LIBS_DIR})
add_subdirectory(${SPIKES_DIR})
add_subdirectory(${TESTS_DIR}/functional)

# Add bootloader
add_subdirectory(${BOOTLOADER_DIR})

# Add LekaOS
add_subdirectory(${OS_DIR})

Expand Down
4 changes: 2 additions & 2 deletions Makefile
Expand Up @@ -29,7 +29,7 @@ TARGET_BOARD ?= LEKA_V1_2_DEV
#

ENABLE_CODE_ANALYSIS ?= OFF
ENABLE_BOOTLOADER ?= OFF
BUILD_TARGETS_TO_USE_WITH_BOOTLOADER ?= OFF

#
# MARK: - Build dirs
Expand Down Expand Up @@ -121,7 +121,7 @@ config_tools_target: mkdir_cmake_config
config_cmake_build: mkdir_tools_config
@echo ""
@echo "🏃 Running cmake configuration script for target $(TARGET_BOARD) 📝"
@cmake -S . -B $(TARGET_BUILD_DIR) -GNinja -DCMAKE_CONFIG_DIR="$(CMAKE_CONFIG_DIR)" -DTARGET_BOARD="$(TARGET_BOARD)" -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DENABLE_CODE_ANALYSIS=$(ENABLE_CODE_ANALYSIS) -DENABLE_BOOTLOADER=$(ENABLE_BOOTLOADER)
@cmake -S . -B $(TARGET_BUILD_DIR) -GNinja -DCMAKE_CONFIG_DIR="$(CMAKE_CONFIG_DIR)" -DTARGET_BOARD="$(TARGET_BOARD)" -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DENABLE_CODE_ANALYSIS=$(ENABLE_CODE_ANALYSIS) -DBUILD_TARGETS_TO_USE_WITH_BOOTLOADER=$(BUILD_TARGETS_TO_USE_WITH_BOOTLOADER)

config_tools_build: mkdir_tools_config
@echo ""
Expand Down
23 changes: 23 additions & 0 deletions bootloader/CMakeLists.txt
@@ -0,0 +1,23 @@
# Leka - LekaOS
# Copyright 2021 APF France handicap
# SPDX-License-Identifier: Apache-2.0

add_mbed_executable(bootloader)

target_include_directories(bootloader
PRIVATE
.
)

target_sources(bootloader
PRIVATE
main.cpp
default_bd.cpp
signing_keys.c
)

target_link_libraries(bootloader
bootutil
)

target_link_custom_leka_targets(bootloader)
18 changes: 18 additions & 0 deletions bootloader/default_bd.cpp
@@ -0,0 +1,18 @@
// Leka - LekaOS
// Copyright 2021 APF France handicap
// SPDX-License-Identifier: Apache-2.0

#include "QSPIFBlockDevice.h"
#include "SlicingBlockDevice.h"

auto get_secondary_bd() -> mbed::BlockDevice *
{
// In this case, our flash is much larger than a single image so
// slice it into the size of an image slot

static auto _bd = QSPIFBlockDevice {};

static auto sliced_bd = mbed::SlicingBlockDevice {&_bd, 0x0, MCUBOOT_SLOT_SIZE};

return &sliced_bd;
}
62 changes: 62 additions & 0 deletions bootloader/main.cpp
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2020 Embedded Planet
* Copyright (c) 2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/

#include "mbed_application.h"
#include "mbedtls/platform.h"

#include "drivers/BufferedSerial.h"

#include "LogKit.h"
#include "bootutil/bootutil.h"
#include "bootutil/image.h"
#include "hal/serial_api.h"

static auto serial = mbed::BufferedSerial(USBTX, USBRX, 115200);

auto main() -> int
{
int rc;

log_info("Starting MCUboot");

// Initialize mbedtls crypto for use by MCUboot
mbedtls_platform_context unused_ctx;
rc = mbedtls_platform_setup(&unused_ctx);
if (rc != 0) {
log_error("Failed to setup Mbed TLS, error: %d", rc);
exit(rc);
}

struct boot_rsp rsp;
rc = boot_go(&rsp);
if (rc != 0) {
log_error("Failed to locate firmware image, error: %d", rc);
exit(rc);
}

uint32_t address = rsp.br_image_off + rsp.br_hdr->ih_hdr_size;

// Workaround: The extra \n ensures the last trace gets flushed
// before mbed_start_application() destroys the stack and jumps
// to the application
log_info("Booting firmware image at 0x%x\n", address);

// Run the application in the primary slot
// Add header size offset to calculate the actual start address of application
mbed_start_application(address);
}
38 changes: 38 additions & 0 deletions bootloader/signing_keys.c
@@ -0,0 +1,38 @@
/* Autogenerated by imgtool.py, do not edit. */
const unsigned char rsa_pub_key[] = {
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
0x00, 0xc1, 0x3c, 0x9a, 0x1b, 0xd5, 0x96, 0x02,
0xdc, 0xdc, 0xc2, 0x5a, 0xf7, 0x31, 0x81, 0x84,
0x46, 0xe6, 0xb5, 0x63, 0x73, 0x51, 0x76, 0xea,
0x94, 0xf7, 0x3d, 0x81, 0xb4, 0x48, 0xa2, 0x9c,
0x00, 0xab, 0x7d, 0x66, 0x9c, 0xcc, 0x84, 0x9c,
0x15, 0x5d, 0x7f, 0x5f, 0x7c, 0x46, 0xb1, 0x6d,
0x8b, 0x5d, 0x47, 0x26, 0x68, 0xff, 0x50, 0xb7,
0x8d, 0x34, 0xa5, 0x25, 0xc6, 0x0f, 0x62, 0xc8,
0x1f, 0xa5, 0x93, 0xcb, 0xc9, 0x21, 0x7e, 0xe6,
0xc2, 0xae, 0x20, 0xc2, 0xaf, 0x85, 0x4f, 0xaa,
0xef, 0xac, 0x16, 0xd8, 0x79, 0xac, 0xc1, 0x02,
0x65, 0x45, 0x23, 0x53, 0xee, 0x7d, 0x8e, 0x8b,
0x87, 0xaa, 0x97, 0x3e, 0xb4, 0xc0, 0xdd, 0xe5,
0xd9, 0xb0, 0xd4, 0x0d, 0x38, 0x67, 0x29, 0x2d,
0xb9, 0xf7, 0xfa, 0x8c, 0x06, 0xd9, 0xb4, 0x29,
0xc2, 0x13, 0x7c, 0xce, 0xcd, 0x2e, 0x48, 0xce,
0x87, 0x0f, 0xb0, 0x61, 0x19, 0x44, 0x71, 0x7c,
0xe9, 0xef, 0x5f, 0x65, 0x16, 0xf9, 0x94, 0xa3,
0x46, 0x17, 0x85, 0xb7, 0x68, 0xb0, 0xc2, 0x9e,
0xe5, 0xd6, 0x56, 0xd6, 0xc8, 0xc6, 0xcc, 0x0b,
0x5f, 0x63, 0xf7, 0x0c, 0x4f, 0xf2, 0xd4, 0xd9,
0xd5, 0x1d, 0x40, 0x5b, 0x6e, 0x73, 0x2f, 0x4d,
0xc7, 0x4a, 0xe5, 0xae, 0x74, 0xaa, 0x35, 0x9a,
0x05, 0xa7, 0x24, 0xd3, 0xba, 0x3a, 0x7c, 0xe9,
0x55, 0x67, 0x35, 0x63, 0xb2, 0x6a, 0x14, 0x6f,
0xfa, 0x5f, 0x1e, 0xc7, 0x71, 0xc9, 0xf7, 0x5a,
0x0b, 0x2c, 0x51, 0xab, 0xdc, 0x11, 0x65, 0x4e,
0xec, 0x10, 0x0e, 0x2e, 0x0e, 0x41, 0x6f, 0x56,
0x64, 0xf5, 0x5c, 0x8f, 0xfa, 0xb4, 0x0b, 0x3b,
0xe0, 0xb0, 0xba, 0x28, 0xb2, 0x48, 0x8c, 0xe0,
0x59, 0xd7, 0x3b, 0xbf, 0x5e, 0x7f, 0x4b, 0xc9,
0x98, 0xdd, 0x03, 0xbd, 0xd2, 0xdc, 0xc8, 0x3e,
0xf1, 0x02, 0x03, 0x01, 0x00, 0x01,
};
const unsigned int rsa_pub_key_len = 270;
25 changes: 25 additions & 0 deletions build_bootloader.sh
@@ -0,0 +1,25 @@
#!/bin/bash

mkdir _tmp > /dev/null 2> /dev/null

# Variables
BOOTLOADER_HEX_SOURCE="$1"
BOOTLOADER_HEX="$2"

if [ -z "$BOOTLOADER_HEX_SOURCE" ]; then
echo "BOOTLOADER_HEX_SOURCE is unset"
BOOTLOADER_HEX_SOURCE="_build/LEKA_V1_2_DEV/bootloader/bootloader.hex"
fi

if [ -z "$BOOTLOADER_HEX" ]; then
echo "BOOTLOADER_HEX is unset"
BOOTLOADER_HEX="_tmp/bootloader.hex"
fi

# Compile bootloader
make deep_clean
make config
make

# Get bootloader binary
cp $BOOTLOADER_HEX_SOURCE $BOOTLOADER_HEX
45 changes: 45 additions & 0 deletions build_update.sh
@@ -0,0 +1,45 @@
#!/bin/bash

mkdir _tmp > /dev/null 2> /dev/null
mkdir _release > /dev/null 2> /dev/null

# Variables
RECOMPILE_APPLICATIONS="$1"

APPLICATION_HEX_SOURCE="$2"
APPLICATION_VERSION="$3"
APPLICATION_HEX="_tmp/application.hex"
APPLICATION_SIGNED_HEX="$4"
APPLICATION_SIGNED_BIN="_release/application-signed.bin"

if [ -z "$APPLICATION_HEX_SOURCE" ]; then
echo "APPLICATION_HEX_SOURCE is unset"
APPLICATION_HEX_SOURCE="_build/LEKA_V1_2_DEV/src/LekaOS.hex"
fi

if [ -z "$APPLICATION_VERSION" ]; then
echo "APPLICATION_VERSION is unset"
APPLICATION_VERSION="1.2.3+4"
fi

if [ -z "$APPLICATION_SIGNED_HEX" ]; then
echo "APPLICATION_SIGNED_HEX is unset"
APPLICATION_SIGNED_HEX="_tmp/application-signed.hex"
fi

# Compile applications
if [ "$RECOMPILE_APPLICATIONS" = "true" ];
then
make deep_clean
make config BUILD_TARGETS_TO_USE_WITH_BOOTLOADER=ON
fi;
make

# Get application binary
cp $APPLICATION_HEX_SOURCE $APPLICATION_HEX

# Sign application with private key
imgtool sign -k signing-keys.pem --align 4 -v $APPLICATION_VERSION --header-size 4096 --pad-header -S 0x180000 $APPLICATION_HEX $APPLICATION_SIGNED_HEX

# Convert in binary
arm-none-eabi-objcopy -I ihex -O binary $APPLICATION_SIGNED_HEX $APPLICATION_SIGNED_BIN
3 changes: 1 addition & 2 deletions cmake/templates/Template_MCUBoot_CMakeLists.txt
Expand Up @@ -3,7 +3,6 @@
# Copyright 2021 APF France handicap
# SPDX-License-Identifier: Apache-2.0

add_compile_definitions(MCUBOOT_BOOTLOADER_BUILD=false)
add_compile_definitions(MCUBOOT_BOOTLOADER_SIZE=0x40000)

add_compile_definitions(MCUBOOT_SCRATCH_SIZE=0x40000)
Expand All @@ -24,7 +23,7 @@ add_compile_definitions(MCUBOOT_SLOT_SIZE=0x200000-MCUBOOT_BOOTLOADER_SIZE-MCUBO
add_compile_definitions(MCUBOOT_VALIDATE_PRIMARY_SLOT=true)

add_compile_definitions(MCUBOOT_READ_GRANULARITY=1)
add_compile_definitions(MCUBOOT_MAX_IMG_SECTORS=256)
add_compile_definitions(MCUBOOT_MAX_IMG_SECTORS=512)

add_subdirectory(${MCUBOOT_DIR}/bootutil)
add_subdirectory(${MCUBOOT_DIR}/mbed)
2 changes: 1 addition & 1 deletion drivers/CoreQSPI/source/CoreQSPI.cpp
Expand Up @@ -10,7 +10,7 @@ void CoreQSPI::setDataTransmissionFormat()
{
auto _command_width = QSPI_CFG_BUS_SINGLE;
auto _address_width = QSPI_CFG_BUS_SINGLE;
auto _address_size = QSPI_CFG_ADDR_SIZE_8;
auto _address_size = QSPI_CFG_ADDR_SIZE_24;
auto _alternate_phase_width = QSPI_CFG_BUS_SINGLE;
qspi_alt_size_t _alternate_phase_size = QSPI_CFG_ALT_SIZE_8;
auto _data_width = QSPI_CFG_BUS_SINGLE;
Expand Down
2 changes: 1 addition & 1 deletion drivers/CoreQSPI/tests/CoreQSPI_test.cpp
Expand Up @@ -29,7 +29,7 @@ TEST(CoreQSPITest, setDataTransmissionFormat)

auto expected_command_width = QSPI_CFG_BUS_SINGLE;
auto expected_address_width = QSPI_CFG_BUS_SINGLE;
auto expected_address_size = QSPI_CFG_ADDR_SIZE_8;
auto expected_address_size = QSPI_CFG_ADDR_SIZE_24;
auto expected_alternate_phase_width = QSPI_CFG_BUS_SINGLE;
auto expected_alternate_phase_size = QSPI_CFG_ALT_SIZE_8;
auto expected_data_width = QSPI_CFG_BUS_SINGLE;
Expand Down
36 changes: 36 additions & 0 deletions generate_firmware.sh
@@ -0,0 +1,36 @@
#!/bin/bash

mkdir _tmp > /dev/null 2> /dev/null
mkdir _release > /dev/null 2> /dev/null

# Variables
RECOMPILE_BOOTLOADER="false"
while getopts r flag
do
case "${flag}" in
r) RECOMPILE_BOOTLOADER="true";;
esac
done

BOOTLOADER_HEX_SOURCE="_build/LEKA_V1_2_DEV/bootloader/bootloader.hex"
BOOTLOADER_HEX="_tmp/bootloader.hex"

APPLICATION_HEX_SOURCE="_build/LEKA_V1_2_DEV/spikes/lk_update_process_app_base/spike_lk_update_process_app_base.hex"
APPLICATION_VERSION="1.2.3+4"
APPLICATION_SIGNED_HEX="_tmp/application-signed.hex"

FIRMWARE_HEX="_tmp/firmwware.hex"
FIRMWARE_RELEASE="_release/firmware.bin"

# Get bootloader
if [ "$RECOMPILE_BOOTLOADER" = "true" ];
then
./build_bootloader.sh $BOOTLOADER_HEX_SOURCE $BOOTLOADER_HEX
fi;

# Get application
./build_update.sh $RECOMPILE_BOOTLOADER $APPLICATION_HEX_SOURCE $APPLICATION_VERSION $APPLICATION_SIGNED_HEX

# Merge bootloader and application
hexmerge.py -o $FIRMWARE_HEX --no-start-addr $BOOTLOADER_HEX $APPLICATION_SIGNED_HEX
arm-none-eabi-objcopy -I ihex -O binary $FIRMWARE_HEX $FIRMWARE_RELEASE

0 comments on commit b1eefc4

Please sign in to comment.