| # SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD |
| # |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| cmake_minimum_required(VERSION 3.13) |
| cmake_policy(SET CMP0109 NEW) |
| |
| include(${CMAKE_CURRENT_LIST_DIR}/tools/utils.cmake) |
| |
| if (NOT DEFINED MCUBOOT_TARGET) |
| message(FATAL_ERROR "MCUBOOT_TARGET not defined. Please pass -DMCUBOOT_TARGET flag.") |
| endif() |
| |
| add_definitions(-DMCUBOOT_TARGET=${MCUBOOT_TARGET}) |
| add_definitions(-D__ESPRESSIF__=1) |
| |
| if ("${MCUBOOT_TARGET}" STREQUAL "esp32" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32s2" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32s3") |
| set(MCUBOOT_ARCH "xtensa") |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c3" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32c6" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32c2" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32h2") |
| set(MCUBOOT_ARCH "riscv") |
| endif() |
| |
| if (NOT DEFINED CMAKE_TOOLCHAIN_FILE) |
| if (DEFINED TOOLCHAIN_BIN_DIR) |
| message("CMAKE_TOOLCHAIN_FILE not defined, searching for toolchain compiler in TOOLCHAIN_BIN_DIR: ${TOOLCHAIN_BIN_DIR}") |
| set(CMAKE_SYSTEM_NAME Generic) |
| |
| file(GLOB C_COMPILER_BIN "${TOOLCHAIN_BIN_DIR}/*${MCUBOOT_ARCH}*elf-gcc") |
| if (NOT C_COMPILER_BIN) |
| message(FATAL_ERROR "No C compiler found. Please ensure that TOOLCHAIN_BIN_DIR directory contains a set of C compiling tools compatible with the target") |
| endif() |
| set(CMAKE_C_COMPILER ${C_COMPILER_BIN}) |
| set(CMAKE_ASM_COMPILER ${C_COMPILER_BIN}) |
| message("C compiler found: ${CMAKE_C_COMPILER}") |
| |
| file(GLOB CXX_COMPILER_BIN "${TOOLCHAIN_BIN_DIR}/*${MCUBOOT_ARCH}*elf-g++") |
| if (NOT CXX_COMPILER_BIN) |
| message(FATAL_ERROR "No C++ compiler found. Please ensure that TOOLCHAIN_BIN_DIR directory contains a set of C++ compiling tools compatible with the target") |
| endif() |
| set(CMAKE_CXX_COMPILER ${CXX_COMPILER_BIN}) |
| message("CXX compiler found: ${CMAKE_CXX_COMPILER}") |
| else() |
| # Set toolchain file that expect the same toolchain as IDF sets on PATH |
| set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/tools/toolchain-${MCUBOOT_TARGET}.cmake) |
| message("No user-defined toolchain, setting default toolchain file: ${CMAKE_TOOLCHAIN_FILE}") |
| endif() |
| |
| # This flag is needed when redefining a different compiler toolchain at this point |
| # on CMakeLists, the reason is that CMake does a compiler testing prior to building |
| # that may fail due to cross-compilation |
| set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") |
| else() |
| message("CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}") |
| endif() |
| |
| project(mcuboot_${MCUBOOT_TARGET}) |
| |
| # Set the minimum revision for each supported chip |
| if ("${MCUBOOT_TARGET}" STREQUAL "esp32") |
| set(ESP_MIN_REVISION 3) |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32s2") |
| set(ESP_MIN_REVISION 0) |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32s3") |
| set(ESP_MIN_REVISION 0) |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c3") |
| set(ESP_MIN_REVISION 3) |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c6") |
| set(ESP_MIN_REVISION 0) |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c2") |
| set(ESP_MIN_REVISION 0) |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32h2") |
| set(ESP_MIN_REVISION 0) |
| else() |
| message(FATAL_ERROR "Unsupported target ${MCUBOOT_TARGET}") |
| endif() |
| |
| if (NOT DEFINED ESP_HAL_PATH) |
| if (DEFINED ENV{ESP_HAL_PATH}) |
| set(ESP_HAL_PATH $ENV{ESP_HAL_PATH}) |
| else() |
| message(WARNING "ESP_HAL_PATH not defined, checking if IDF_PATH exists.") |
| if (DEFINED ENV{IDF_PATH}) |
| set(ESP_HAL_PATH $ENV{IDF_PATH}) |
| message("IDF installation found in the system, using IDF_PATH as ESP_HAL_PATH.") |
| else () |
| message(FATAL_ERROR "Please set -DESP_HAL_PATH parameter or define ESP_HAL_PATH environment variable.") |
| endif() |
| endif() |
| endif() |
| |
| execute_process( |
| COMMAND git describe --tags |
| WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} |
| OUTPUT_VARIABLE MCUBOOT_VER |
| OUTPUT_STRIP_TRAILING_WHITESPACE |
| ) |
| add_definitions(-DMCUBOOT_VER=\"${MCUBOOT_VER}\") |
| |
| if (NOT DEFINED MCUBOOT_CONFIG_FILE) |
| set(MCUBOOT_CONFIG_FILE "${CMAKE_CURRENT_LIST_DIR}/port/${MCUBOOT_TARGET}/bootloader.conf") |
| endif() |
| |
| string(REPLACE " " ";" MCUBOOT_CONFIG_FILE_LIST "${MCUBOOT_CONFIG_FILE}") |
| foreach(CONFIG_FILE ${MCUBOOT_CONFIG_FILE_LIST}) |
| if (NOT EXISTS "${CONFIG_FILE}") |
| message(FATAL_ERROR "MCUboot configuration file does not exist at ${CONFIG_FILE}") |
| endif() |
| parse_and_set_config_file(${CONFIG_FILE}) |
| endforeach() |
| |
| set(APP_NAME mcuboot_${MCUBOOT_TARGET}) |
| set(APP_EXECUTABLE ${APP_NAME}.elf) |
| |
| set(MCUBOOT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) |
| set(BOOTUTIL_DIR ${MCUBOOT_ROOT_DIR}/boot/bootutil) |
| set(BOOT_SERIAL_DIR ${MCUBOOT_ROOT_DIR}/boot/boot_serial) |
| set(ZCBOR_DIR ${MCUBOOT_ROOT_DIR}/boot/zcbor) |
| set(ESPRESSIF_PORT_DIR ${CMAKE_CURRENT_LIST_DIR}) |
| |
| # Find imgtool. |
| # Go with an explicitly installed imgtool first, falling |
| # back to mcuboot/scripts/imgtool.py. |
| find_program(IMGTOOL_COMMAND |
| NAMES imgtool imgtool.py |
| ) |
| if ("${IMGTOOL_COMMAND}" MATCHES "IMGTOOL_COMMAND-NOTFOUND") |
| set(imgtool_path "${MCUBOOT_ROOT_DIR}/scripts/imgtool.py") |
| else() |
| set(imgtool_path "${IMGTOOL_COMMAND}") |
| endif() |
| |
| # Find installed esptool, if not found falls to IDF's |
| find_program(ESPTOOL_COMMAND |
| NAMES esptool esptool.py |
| ) |
| if ("${ESPTOOL_COMMAND}" MATCHES "ESPTOOL_COMMAND-NOTFOUND") |
| if (DEFINED ENV{IDF_PATH}) |
| set(esptool_path "${IDF_PATH}/components/esptool_py/esptool/esptool.py") |
| else() |
| message(FATAL_ERROR "esptool.py not found. Please install it using \'pip install esptool\'.") |
| endif() |
| else() |
| set(esptool_path "${ESPTOOL_COMMAND}") |
| endif() |
| |
| # Flash frequency parameter for esptool.py, for more information, check `esptool.py -h` |
| if (NOT DEFINED ESP_FLASH_FREQ) |
| if ("${MCUBOOT_TARGET}" STREQUAL "esp32" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32s2" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32s3" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32c3" OR |
| "${MCUBOOT_TARGET}" STREQUAL "esp32c6") |
| set(ESP_FLASH_FREQ "40m") |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c2") |
| set(ESP_FLASH_FREQ "60m") |
| elseif("${MCUBOOT_TARGET}" STREQUAL "esp32h2") |
| set(ESP_FLASH_FREQ "24m") |
| endif() |
| endif() |
| |
| # Flash mode parameter for esptool.py, for more information, check `esptool.py -h` |
| if (NOT DEFINED ESP_FLASH_MODE) |
| set(ESP_FLASH_MODE "dio") |
| endif() |
| |
| # Serial baud rate parameter for esptool.py flash use, for more information, check `esptool.py -h` |
| if (NOT DEFINED ESP_BAUD_RATE) |
| set(ESP_BAUD_RATE 115200) |
| endif() |
| |
| if (DEFINED CONFIG_ESP_SIGN_RSA) |
| include(${CMAKE_CURRENT_LIST_DIR}/include/crypto_config/rsa.cmake) |
| elseif (DEFINED CONFIG_ESP_SIGN_EC256) |
| include(${CMAKE_CURRENT_LIST_DIR}/include/crypto_config/ec256.cmake) |
| elseif (DEFINED CONFIG_ESP_SIGN_ED25519) |
| include(${CMAKE_CURRENT_LIST_DIR}/include/crypto_config/ed25519.cmake) |
| else() |
| # No signature verification |
| set(TINYCRYPT_DIR ${MCUBOOT_ROOT_DIR}/ext/tinycrypt/lib) |
| set(CRYPTO_INC |
| ${TINYCRYPT_DIR}/include |
| ) |
| set(crypto_srcs |
| ${TINYCRYPT_DIR}/source/sha256.c |
| ${TINYCRYPT_DIR}/source/utils.c |
| ) |
| endif() |
| |
| if(DEFINED CONFIG_ESP_SIGN_KEY_FILE) |
| if(IS_ABSOLUTE ${CONFIG_ESP_SIGN_KEY_FILE}) |
| set(KEY_FILE ${CONFIG_ESP_SIGN_KEY_FILE}) |
| else() |
| set(KEY_FILE ${MCUBOOT_ROOT_DIR}/${CONFIG_ESP_SIGN_KEY_FILE}) |
| endif() |
| message("MCUBoot bootloader key file: ${KEY_FILE}") |
| |
| set(GENERATED_PUBKEY ${CMAKE_CURRENT_BINARY_DIR}/autogen-pubkey.c) |
| add_custom_command( |
| OUTPUT ${GENERATED_PUBKEY} |
| COMMAND |
| ${imgtool_path} |
| getpub |
| -k |
| ${KEY_FILE} |
| > ${GENERATED_PUBKEY} |
| DEPENDS ${KEY_FILE} |
| ) |
| list(APPEND crypto_srcs ${GENERATED_PUBKEY}) |
| endif() |
| |
| set(bootutil_srcs |
| ${BOOTUTIL_DIR}/src/boot_record.c |
| ${BOOTUTIL_DIR}/src/bootutil_misc.c |
| ${BOOTUTIL_DIR}/src/bootutil_public.c |
| ${BOOTUTIL_DIR}/src/caps.c |
| ${BOOTUTIL_DIR}/src/encrypted.c |
| ${BOOTUTIL_DIR}/src/fault_injection_hardening.c |
| ${BOOTUTIL_DIR}/src/fault_injection_hardening_delay_rng_mbedtls.c |
| ${BOOTUTIL_DIR}/src/image_ecdsa.c |
| ${BOOTUTIL_DIR}/src/image_ed25519.c |
| ${BOOTUTIL_DIR}/src/image_rsa.c |
| ${BOOTUTIL_DIR}/src/image_validate.c |
| ${BOOTUTIL_DIR}/src/loader.c |
| ${BOOTUTIL_DIR}/src/swap_misc.c |
| ${BOOTUTIL_DIR}/src/swap_move.c |
| ${BOOTUTIL_DIR}/src/swap_scratch.c |
| ${BOOTUTIL_DIR}/src/tlv.c |
| ) |
| set(bootutil_paths) |
| |
| set(CFLAGS |
| "-Wno-frame-address" |
| "-Wall" |
| "-Wextra" |
| "-W" |
| "-Wdeclaration-after-statement" |
| "-Wwrite-strings" |
| "-Wlogical-op" |
| "-Wshadow" |
| "-ffunction-sections" |
| "-fdata-sections" |
| "-fstrict-volatile-bitfields" |
| "-Werror=all" |
| "-Wno-error=unused-function" |
| "-Wno-error=unused-but-set-variable" |
| "-Wno-error=unused-variable" |
| "-Wno-error=deprecated-declarations" |
| "-Wno-unused-parameter" |
| "-Wno-sign-compare" |
| "-ggdb" |
| "-Os" |
| "-D_GNU_SOURCE" |
| "-std=gnu17" |
| "-Wno-old-style-declaration" |
| "-Wno-implicit-int" |
| "-Wno-declaration-after-statement" |
| ) |
| |
| set(LDFLAGS |
| "-nostdlib" |
| "-Wno-frame-address" |
| "-Wl,--cref" |
| "-Wl,--Map=${APP_NAME}.map" |
| "-fno-rtti" |
| "-fno-lto" |
| "-Wl,--gc-sections" |
| "-Wl,--undefined=uxTopUsedPriority" |
| "-lm" |
| "-lgcc" |
| "-lgcov" |
| ) |
| |
| if ("${MCUBOOT_ARCH}" STREQUAL "xtensa") |
| list(APPEND CFLAGS |
| "-mlongcalls" |
| ) |
| list(APPEND LDFLAGS |
| "-mlongcalls" |
| ) |
| endif() |
| |
| add_subdirectory(hal) |
| add_executable( |
| ${APP_EXECUTABLE} |
| ${CMAKE_CURRENT_LIST_DIR}/main.c |
| ) |
| |
| target_compile_options( |
| ${APP_EXECUTABLE} |
| PUBLIC |
| ${CFLAGS} |
| ) |
| |
| set(port_srcs |
| ${CMAKE_CURRENT_LIST_DIR}/port/esp_mcuboot.c |
| ${CMAKE_CURRENT_LIST_DIR}/port/esp_loader.c |
| ${CMAKE_CURRENT_LIST_DIR}/os.c |
| ) |
| |
| if(CONFIG_ESP_MCUBOOT_SERIAL) |
| set(MBEDTLS_DIR "${MCUBOOT_ROOT_DIR}/ext/mbedtls") |
| |
| list(APPEND bootutil_srcs |
| ${BOOT_SERIAL_DIR}/src/boot_serial.c |
| ${BOOT_SERIAL_DIR}/src/zcbor_bulk.c |
| ${ZCBOR_DIR}/src/zcbor_decode.c |
| ${ZCBOR_DIR}/src/zcbor_encode.c |
| ${ZCBOR_DIR}/src/zcbor_common.c |
| ) |
| list(APPEND bootutil_paths |
| ${ZCBOR_DIR}/include |
| ) |
| list(APPEND port_srcs |
| ${CMAKE_CURRENT_LIST_DIR}/port/${MCUBOOT_TARGET}/serial_adapter.c |
| ${MBEDTLS_DIR}/library/base64.c |
| ) |
| list(APPEND CRYPTO_INC |
| ${MBEDTLS_DIR}/include |
| ) |
| endif() |
| |
| target_sources( |
| ${APP_EXECUTABLE} |
| PUBLIC |
| ${bootutil_srcs} |
| ${crypto_srcs} |
| ${port_srcs} |
| ) |
| |
| target_include_directories( |
| ${APP_EXECUTABLE} |
| PUBLIC |
| ${BOOTUTIL_DIR}/include |
| ${BOOTUTIL_DIR}/src |
| ${BOOT_SERIAL_DIR}/include |
| ${CRYPTO_INC} |
| ${CMAKE_CURRENT_LIST_DIR}/include |
| ${bootutil_paths} |
| ) |
| |
| set(ld_input ${CMAKE_CURRENT_LIST_DIR}/port/${MCUBOOT_TARGET}/ld/bootloader.ld) |
| set(ld_output ${CMAKE_CURRENT_BINARY_DIR}/ld/bootloader.ld) |
| |
| file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/ld") |
| |
| get_directory_property(configs COMPILE_DEFINITIONS) |
| foreach(c ${configs}) |
| list(APPEND conf_defines "-D${c}") |
| endforeach() |
| |
| # Preprocess linker script |
| add_custom_command( |
| TARGET ${APP_EXECUTABLE} PRE_LINK |
| COMMAND ${CMAKE_C_COMPILER} -x c -E -P -o ${ld_output} ${conf_defines} ${ld_input} |
| MAIN_DEPENDENCY ${ld_input} |
| COMMENT "Preprocessing bootloader.ld linker script..." |
| ) |
| |
| target_link_libraries( |
| ${APP_EXECUTABLE} |
| PUBLIC |
| -T${ld_output} |
| ${LDFLAGS} |
| ) |
| |
| target_link_libraries( |
| ${APP_EXECUTABLE} |
| PUBLIC |
| hal |
| ) |
| |
| # This step uses esptool.py for generating the final bootloader binary in |
| # Espressif compatible format. |
| # Note: Both binary generation and flash steps still have some default arguments |
| add_custom_command(TARGET ${APP_EXECUTABLE} POST_BUILD |
| COMMAND |
| ${esptool_path} |
| --chip ${MCUBOOT_TARGET} elf2image --min-rev ${ESP_MIN_REVISION} |
| --flash_mode ${ESP_FLASH_MODE} --flash_freq ${ESP_FLASH_FREQ} --flash_size ${CONFIG_ESP_FLASH_SIZE} |
| -o ${APP_NAME}.bin ${APP_NAME}.elf |
| ) |
| |
| if (DEFINED MCUBOOT_FLASH_PORT) |
| set(FLASH_PORT ${MCUBOOT_FLASH_PORT}) |
| else() |
| # Defaults to the first USB serial port |
| set(FLASH_PORT "/dev/ttyUSB0") |
| endif() |
| |
| if (NOT EXISTS "${FLASH_PORT}") |
| message(WARNING "Could not open ${FLASH_PORT}, serial port does not exist") |
| endif() |
| |
| add_custom_target(flash DEPENDS ${APP_NAME}.bin) |
| add_custom_command(TARGET flash |
| USES_TERMINAL |
| COMMAND |
| ${esptool_path} |
| -p ${FLASH_PORT} -b ${ESP_BAUD_RATE} --before default_reset --after no_reset |
| --chip ${MCUBOOT_TARGET} write_flash |
| --flash_mode ${ESP_FLASH_MODE} --flash_size ${CONFIG_ESP_FLASH_SIZE} |
| --flash_freq ${ESP_FLASH_FREQ} ${CONFIG_ESP_BOOTLOADER_OFFSET} |
| ${APP_NAME}.bin |
| ) |