1# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD 2# 3# SPDX-License-Identifier: Apache-2.0 4 5cmake_minimum_required(VERSION 3.13) 6cmake_policy(SET CMP0109 NEW) 7 8include(${CMAKE_CURRENT_LIST_DIR}/tools/utils.cmake) 9 10if (NOT DEFINED MCUBOOT_TARGET) 11 message(FATAL_ERROR "MCUBOOT_TARGET not defined. Please pass -DMCUBOOT_TARGET flag.") 12endif() 13 14add_definitions(-DMCUBOOT_TARGET=${MCUBOOT_TARGET}) 15add_definitions(-D__ESPRESSIF__=1) 16 17if ("${MCUBOOT_TARGET}" STREQUAL "esp32" OR 18 "${MCUBOOT_TARGET}" STREQUAL "esp32s2" OR 19 "${MCUBOOT_TARGET}" STREQUAL "esp32s3") 20 set(MCUBOOT_ARCH "xtensa") 21elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c3" OR 22 "${MCUBOOT_TARGET}" STREQUAL "esp32c6" OR 23 "${MCUBOOT_TARGET}" STREQUAL "esp32c2" OR 24 "${MCUBOOT_TARGET}" STREQUAL "esp32h2") 25 set(MCUBOOT_ARCH "riscv") 26endif() 27 28if (NOT DEFINED CMAKE_TOOLCHAIN_FILE) 29 if (DEFINED TOOLCHAIN_BIN_DIR) 30 message("CMAKE_TOOLCHAIN_FILE not defined, searching for toolchain compiler in TOOLCHAIN_BIN_DIR: ${TOOLCHAIN_BIN_DIR}") 31 set(CMAKE_SYSTEM_NAME Generic) 32 33 file(GLOB C_COMPILER_BIN "${TOOLCHAIN_BIN_DIR}/*${MCUBOOT_ARCH}*elf-gcc") 34 if (NOT C_COMPILER_BIN) 35 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") 36 endif() 37 set(CMAKE_C_COMPILER ${C_COMPILER_BIN}) 38 set(CMAKE_ASM_COMPILER ${C_COMPILER_BIN}) 39 message("C compiler found: ${CMAKE_C_COMPILER}") 40 41 file(GLOB CXX_COMPILER_BIN "${TOOLCHAIN_BIN_DIR}/*${MCUBOOT_ARCH}*elf-g++") 42 if (NOT CXX_COMPILER_BIN) 43 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") 44 endif() 45 set(CMAKE_CXX_COMPILER ${CXX_COMPILER_BIN}) 46 message("CXX compiler found: ${CMAKE_CXX_COMPILER}") 47 else() 48 # Set toolchain file that expect the same toolchain as IDF sets on PATH 49 set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/tools/toolchain-${MCUBOOT_TARGET}.cmake) 50 message("No user-defined toolchain, setting default toolchain file: ${CMAKE_TOOLCHAIN_FILE}") 51 endif() 52 53 # This flag is needed when redefining a different compiler toolchain at this point 54 # on CMakeLists, the reason is that CMake does a compiler testing prior to building 55 # that may fail due to cross-compilation 56 set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") 57else() 58 message("CMAKE_TOOLCHAIN_FILE: ${CMAKE_TOOLCHAIN_FILE}") 59endif() 60 61project(mcuboot_${MCUBOOT_TARGET}) 62 63# Set the minimum revision for each supported chip 64if ("${MCUBOOT_TARGET}" STREQUAL "esp32") 65 set(ESP_MIN_REVISION 3) 66elseif("${MCUBOOT_TARGET}" STREQUAL "esp32s2") 67 set(ESP_MIN_REVISION 0) 68elseif("${MCUBOOT_TARGET}" STREQUAL "esp32s3") 69 set(ESP_MIN_REVISION 0) 70elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c3") 71 set(ESP_MIN_REVISION 3) 72elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c6") 73 set(ESP_MIN_REVISION 0) 74elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c2") 75 set(ESP_MIN_REVISION 0) 76elseif("${MCUBOOT_TARGET}" STREQUAL "esp32h2") 77 set(ESP_MIN_REVISION 0) 78else() 79 message(FATAL_ERROR "Unsupported target ${MCUBOOT_TARGET}") 80endif() 81 82if (NOT DEFINED ESP_HAL_PATH) 83 if (DEFINED ENV{ESP_HAL_PATH}) 84 set(ESP_HAL_PATH $ENV{ESP_HAL_PATH}) 85 else() 86 message(WARNING "ESP_HAL_PATH not defined, checking if IDF_PATH exists.") 87 if (DEFINED ENV{IDF_PATH}) 88 set(ESP_HAL_PATH $ENV{IDF_PATH}) 89 message("IDF installation found in the system, using IDF_PATH as ESP_HAL_PATH.") 90 else () 91 message(FATAL_ERROR "Please set -DESP_HAL_PATH parameter or define ESP_HAL_PATH environment variable.") 92 endif() 93 endif() 94endif() 95 96execute_process( 97 COMMAND git describe --tags 98 WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} 99 OUTPUT_VARIABLE MCUBOOT_VER 100 OUTPUT_STRIP_TRAILING_WHITESPACE 101 ) 102add_definitions(-DMCUBOOT_VER=\"${MCUBOOT_VER}\") 103 104if (NOT DEFINED MCUBOOT_CONFIG_FILE) 105 set(MCUBOOT_CONFIG_FILE "${CMAKE_CURRENT_LIST_DIR}/port/${MCUBOOT_TARGET}/bootloader.conf") 106endif() 107 108string(REPLACE " " ";" MCUBOOT_CONFIG_FILE_LIST "${MCUBOOT_CONFIG_FILE}") 109foreach(CONFIG_FILE ${MCUBOOT_CONFIG_FILE_LIST}) 110 if (NOT EXISTS "${CONFIG_FILE}") 111 message(FATAL_ERROR "MCUboot configuration file does not exist at ${CONFIG_FILE}") 112 endif() 113 parse_and_set_config_file(${CONFIG_FILE}) 114endforeach() 115 116set(APP_NAME mcuboot_${MCUBOOT_TARGET}) 117set(APP_EXECUTABLE ${APP_NAME}.elf) 118 119set(MCUBOOT_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..) 120set(BOOTUTIL_DIR ${MCUBOOT_ROOT_DIR}/boot/bootutil) 121set(BOOT_SERIAL_DIR ${MCUBOOT_ROOT_DIR}/boot/boot_serial) 122set(ZCBOR_DIR ${MCUBOOT_ROOT_DIR}/boot/zcbor) 123set(ESPRESSIF_PORT_DIR ${CMAKE_CURRENT_LIST_DIR}) 124 125# Find imgtool. 126# Go with an explicitly installed imgtool first, falling 127# back to mcuboot/scripts/imgtool.py. 128find_program(IMGTOOL_COMMAND 129 NAMES imgtool imgtool.py 130 ) 131if ("${IMGTOOL_COMMAND}" MATCHES "IMGTOOL_COMMAND-NOTFOUND") 132 set(imgtool_path "${MCUBOOT_ROOT_DIR}/scripts/imgtool.py") 133else() 134 set(imgtool_path "${IMGTOOL_COMMAND}") 135endif() 136 137# Find installed esptool, if not found falls to IDF's 138find_program(ESPTOOL_COMMAND 139 NAMES esptool esptool.py 140 ) 141if ("${ESPTOOL_COMMAND}" MATCHES "ESPTOOL_COMMAND-NOTFOUND") 142 if (DEFINED ENV{IDF_PATH}) 143 set(esptool_path "${IDF_PATH}/components/esptool_py/esptool/esptool.py") 144 else() 145 message(FATAL_ERROR "esptool.py not found. Please install it using \'pip install esptool\'.") 146 endif() 147else() 148 set(esptool_path "${ESPTOOL_COMMAND}") 149endif() 150 151# Flash frequency parameter for esptool.py, for more information, check `esptool.py -h` 152if (NOT DEFINED ESP_FLASH_FREQ) 153 if ("${MCUBOOT_TARGET}" STREQUAL "esp32" OR 154 "${MCUBOOT_TARGET}" STREQUAL "esp32s2" OR 155 "${MCUBOOT_TARGET}" STREQUAL "esp32s3" OR 156 "${MCUBOOT_TARGET}" STREQUAL "esp32c3" OR 157 "${MCUBOOT_TARGET}" STREQUAL "esp32c6") 158 set(ESP_FLASH_FREQ "40m") 159 elseif("${MCUBOOT_TARGET}" STREQUAL "esp32c2") 160 set(ESP_FLASH_FREQ "60m") 161 elseif("${MCUBOOT_TARGET}" STREQUAL "esp32h2") 162 set(ESP_FLASH_FREQ "24m") 163 endif() 164endif() 165 166# Flash mode parameter for esptool.py, for more information, check `esptool.py -h` 167if (NOT DEFINED ESP_FLASH_MODE) 168 set(ESP_FLASH_MODE "dio") 169endif() 170 171# Serial baud rate parameter for esptool.py flash use, for more information, check `esptool.py -h` 172if (NOT DEFINED ESP_BAUD_RATE) 173 set(ESP_BAUD_RATE 115200) 174endif() 175 176if (DEFINED CONFIG_ESP_SIGN_RSA) 177 include(${CMAKE_CURRENT_LIST_DIR}/include/crypto_config/rsa.cmake) 178elseif (DEFINED CONFIG_ESP_SIGN_EC256) 179 include(${CMAKE_CURRENT_LIST_DIR}/include/crypto_config/ec256.cmake) 180elseif (DEFINED CONFIG_ESP_SIGN_ED25519) 181 include(${CMAKE_CURRENT_LIST_DIR}/include/crypto_config/ed25519.cmake) 182else() 183 # No signature verification 184 set(TINYCRYPT_DIR ${MCUBOOT_ROOT_DIR}/ext/tinycrypt/lib) 185 set(CRYPTO_INC 186 ${TINYCRYPT_DIR}/include 187 ) 188 set(crypto_srcs 189 ${TINYCRYPT_DIR}/source/sha256.c 190 ${TINYCRYPT_DIR}/source/utils.c 191 ) 192endif() 193 194if(DEFINED CONFIG_ESP_SIGN_KEY_FILE) 195 if(IS_ABSOLUTE ${CONFIG_ESP_SIGN_KEY_FILE}) 196 set(KEY_FILE ${CONFIG_ESP_SIGN_KEY_FILE}) 197 else() 198 set(KEY_FILE ${MCUBOOT_ROOT_DIR}/${CONFIG_ESP_SIGN_KEY_FILE}) 199 endif() 200 message("MCUBoot bootloader key file: ${KEY_FILE}") 201 202 set(GENERATED_PUBKEY ${CMAKE_CURRENT_BINARY_DIR}/autogen-pubkey.c) 203 add_custom_command( 204 OUTPUT ${GENERATED_PUBKEY} 205 COMMAND 206 ${imgtool_path} 207 getpub 208 -k 209 ${KEY_FILE} 210 > ${GENERATED_PUBKEY} 211 DEPENDS ${KEY_FILE} 212 ) 213 list(APPEND crypto_srcs ${GENERATED_PUBKEY}) 214endif() 215 216set(bootutil_srcs 217 ${BOOTUTIL_DIR}/src/boot_record.c 218 ${BOOTUTIL_DIR}/src/bootutil_misc.c 219 ${BOOTUTIL_DIR}/src/bootutil_public.c 220 ${BOOTUTIL_DIR}/src/caps.c 221 ${BOOTUTIL_DIR}/src/encrypted.c 222 ${BOOTUTIL_DIR}/src/fault_injection_hardening.c 223 ${BOOTUTIL_DIR}/src/fault_injection_hardening_delay_rng_mbedtls.c 224 ${BOOTUTIL_DIR}/src/image_ecdsa.c 225 ${BOOTUTIL_DIR}/src/image_ed25519.c 226 ${BOOTUTIL_DIR}/src/image_rsa.c 227 ${BOOTUTIL_DIR}/src/image_validate.c 228 ${BOOTUTIL_DIR}/src/loader.c 229 ${BOOTUTIL_DIR}/src/swap_misc.c 230 ${BOOTUTIL_DIR}/src/swap_move.c 231 ${BOOTUTIL_DIR}/src/swap_scratch.c 232 ${BOOTUTIL_DIR}/src/tlv.c 233 ) 234set(bootutil_paths) 235 236set(CFLAGS 237 "-Wno-frame-address" 238 "-Wall" 239 "-Wextra" 240 "-W" 241 "-Wdeclaration-after-statement" 242 "-Wwrite-strings" 243 "-Wlogical-op" 244 "-Wshadow" 245 "-ffunction-sections" 246 "-fdata-sections" 247 "-fstrict-volatile-bitfields" 248 "-Werror=all" 249 "-Wno-error=unused-function" 250 "-Wno-error=unused-but-set-variable" 251 "-Wno-error=unused-variable" 252 "-Wno-error=deprecated-declarations" 253 "-Wno-unused-parameter" 254 "-Wno-sign-compare" 255 "-ggdb" 256 "-Os" 257 "-D_GNU_SOURCE" 258 "-std=gnu17" 259 "-Wno-old-style-declaration" 260 "-Wno-implicit-int" 261 "-Wno-declaration-after-statement" 262 ) 263 264set(LDFLAGS 265 "-nostdlib" 266 "-Wno-frame-address" 267 "-Wl,--cref" 268 "-Wl,--Map=${APP_NAME}.map" 269 "-fno-rtti" 270 "-fno-lto" 271 "-Wl,--gc-sections" 272 "-Wl,--undefined=uxTopUsedPriority" 273 "-lm" 274 "-lgcc" 275 "-lgcov" 276 ) 277 278if ("${MCUBOOT_ARCH}" STREQUAL "xtensa") 279 list(APPEND CFLAGS 280 "-mlongcalls" 281 ) 282 list(APPEND LDFLAGS 283 "-mlongcalls" 284 ) 285endif() 286 287add_subdirectory(hal) 288add_executable( 289 ${APP_EXECUTABLE} 290 ${CMAKE_CURRENT_LIST_DIR}/main.c 291 ) 292 293target_compile_options( 294 ${APP_EXECUTABLE} 295 PUBLIC 296 ${CFLAGS} 297 ) 298 299set(port_srcs 300 ${CMAKE_CURRENT_LIST_DIR}/port/esp_mcuboot.c 301 ${CMAKE_CURRENT_LIST_DIR}/port/esp_loader.c 302 ${CMAKE_CURRENT_LIST_DIR}/os.c 303 ) 304 305if(CONFIG_ESP_MCUBOOT_SERIAL) 306 set(MBEDTLS_DIR "${MCUBOOT_ROOT_DIR}/ext/mbedtls") 307 308 list(APPEND bootutil_srcs 309 ${BOOT_SERIAL_DIR}/src/boot_serial.c 310 ${BOOT_SERIAL_DIR}/src/zcbor_bulk.c 311 ${ZCBOR_DIR}/src/zcbor_decode.c 312 ${ZCBOR_DIR}/src/zcbor_encode.c 313 ${ZCBOR_DIR}/src/zcbor_common.c 314 ) 315 list(APPEND bootutil_paths 316 ${ZCBOR_DIR}/include 317 ) 318 list(APPEND port_srcs 319 ${CMAKE_CURRENT_LIST_DIR}/port/${MCUBOOT_TARGET}/serial_adapter.c 320 ${MBEDTLS_DIR}/library/base64.c 321 ) 322 list(APPEND CRYPTO_INC 323 ${MBEDTLS_DIR}/include 324 ) 325endif() 326 327target_sources( 328 ${APP_EXECUTABLE} 329 PUBLIC 330 ${bootutil_srcs} 331 ${crypto_srcs} 332 ${port_srcs} 333 ) 334 335target_include_directories( 336 ${APP_EXECUTABLE} 337 PUBLIC 338 ${BOOTUTIL_DIR}/include 339 ${BOOTUTIL_DIR}/src 340 ${BOOT_SERIAL_DIR}/include 341 ${CRYPTO_INC} 342 ${CMAKE_CURRENT_LIST_DIR}/include 343 ${bootutil_paths} 344 ) 345 346set(ld_input ${CMAKE_CURRENT_LIST_DIR}/port/${MCUBOOT_TARGET}/ld/bootloader.ld) 347set(ld_output ${CMAKE_CURRENT_BINARY_DIR}/ld/bootloader.ld) 348 349file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/ld") 350 351get_directory_property(configs COMPILE_DEFINITIONS) 352foreach(c ${configs}) 353 list(APPEND conf_defines "-D${c}") 354endforeach() 355 356# Preprocess linker script 357add_custom_command( 358 TARGET ${APP_EXECUTABLE} PRE_LINK 359 COMMAND ${CMAKE_C_COMPILER} -x c -E -P -o ${ld_output} ${conf_defines} ${ld_input} 360 MAIN_DEPENDENCY ${ld_input} 361 COMMENT "Preprocessing bootloader.ld linker script..." 362 ) 363 364target_link_libraries( 365 ${APP_EXECUTABLE} 366 PUBLIC 367 -T${ld_output} 368 ${LDFLAGS} 369 ) 370 371target_link_libraries( 372 ${APP_EXECUTABLE} 373 PUBLIC 374 hal 375 ) 376 377# This step uses esptool.py for generating the final bootloader binary in 378# Espressif compatible format. 379# Note: Both binary generation and flash steps still have some default arguments 380add_custom_command(TARGET ${APP_EXECUTABLE} POST_BUILD 381 COMMAND 382 ${esptool_path} 383 --chip ${MCUBOOT_TARGET} elf2image --min-rev ${ESP_MIN_REVISION} 384 --flash_mode ${ESP_FLASH_MODE} --flash_freq ${ESP_FLASH_FREQ} --flash_size ${CONFIG_ESP_FLASH_SIZE} 385 -o ${APP_NAME}.bin ${APP_NAME}.elf 386 ) 387 388if (DEFINED MCUBOOT_FLASH_PORT) 389 set(FLASH_PORT ${MCUBOOT_FLASH_PORT}) 390else() 391 # Defaults to the first USB serial port 392 set(FLASH_PORT "/dev/ttyUSB0") 393endif() 394 395if (NOT EXISTS "${FLASH_PORT}") 396 message(WARNING "Could not open ${FLASH_PORT}, serial port does not exist") 397endif() 398 399add_custom_target(flash DEPENDS ${APP_NAME}.bin) 400add_custom_command(TARGET flash 401 USES_TERMINAL 402 COMMAND 403 ${esptool_path} 404 -p ${FLASH_PORT} -b ${ESP_BAUD_RATE} --before default_reset --after no_reset 405 --chip ${MCUBOOT_TARGET} write_flash 406 --flash_mode ${ESP_FLASH_MODE} --flash_size ${CONFIG_ESP_FLASH_SIZE} 407 --flash_freq ${ESP_FLASH_FREQ} ${CONFIG_ESP_BOOTLOADER_OFFSET} 408 ${APP_NAME}.bin 409 ) 410