mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/fix_secure_boot_support' into 'master'
Fixes to secure boot support in CMake See merge request idf/esp-idf!4977
This commit is contained in:
commit
265d7dc4e5
@ -34,7 +34,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
${otadata_size} ${blank_otadata_file})
|
||||
|
||||
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
|
||||
add_dependencies(app blank_ota_data)
|
||||
add_dependencies(flash blank_ota_data)
|
||||
|
||||
set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py)
|
||||
|
||||
|
@ -1,13 +1,21 @@
|
||||
idf_component_register()
|
||||
idf_component_register(PRIV_REQUIRES partition_table)
|
||||
|
||||
# Do not generate flash file when building bootloader or is in early expansion of the build
|
||||
if(BOOTLOADER_BUILD)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash`
|
||||
if(NOT CONFIG_SECURE_BOOT_ENABLED)
|
||||
set(flash_bootloader FLASH_IN_PROJECT)
|
||||
endif()
|
||||
|
||||
# Set values used in flash_bootloader_args.in and generate flash file
|
||||
# for bootloader
|
||||
esptool_py_flash_project_args(bootloader 0x1000
|
||||
${BOOTLOADER_BUILD_DIR}/bootloader.bin
|
||||
FLASH_IN_PROJECT
|
||||
FLASH_FILE_TEMPLATE flash_bootloader_args.in)
|
||||
${flash_bootloader}
|
||||
FLASH_FILE_TEMPLATE flash_bootloader_args.in)
|
||||
|
||||
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
|
||||
add_dependencies(bootloader partition_table)
|
||||
|
@ -1,32 +1,10 @@
|
||||
# Do not generate flash file when building bootloader or is in early expansion of the build
|
||||
set(BOOTLOADER_OFFSET 0x1000)
|
||||
|
||||
# Do not generate flash file when building bootloader
|
||||
if(BOOTLOADER_BUILD)
|
||||
return()
|
||||
endif()
|
||||
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
|
||||
# This is for tracking the top level project path
|
||||
if(BOOTLOADER_BUILD)
|
||||
set(main_project_path "${CMAKE_BINARY_DIR}/../..")
|
||||
else()
|
||||
set(main_project_path "${project_dir}")
|
||||
endif()
|
||||
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${CONFIG_SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${main_project_path}")
|
||||
if(NOT EXISTS ${secure_boot_signing_key})
|
||||
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that
|
||||
# fails the build. fail_at_build_time also touches CMakeCache.txt to cause a cmake run next time
|
||||
# (to pick up a new signing key if one exists, etc.)
|
||||
fail_at_build_time(gen_secure_boot_signing_key
|
||||
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
|
||||
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_signing_key)
|
||||
endif()
|
||||
|
||||
|
||||
# Glue to build the bootloader subproject binary as an external
|
||||
# cmake project under this one
|
||||
#
|
||||
@ -39,41 +17,104 @@ set(bootloader_binary_files
|
||||
"${BOOTLOADER_BUILD_DIR}/bootloader.map"
|
||||
)
|
||||
|
||||
# These additional files may get generated
|
||||
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
set(bootloader_binary_files
|
||||
${bootloader_binary_files}
|
||||
"${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin"
|
||||
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin"
|
||||
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin"
|
||||
)
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
|
||||
# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens
|
||||
# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES.
|
||||
# For both cases, the user either sets binaries to be signed during build or not
|
||||
# using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
|
||||
#
|
||||
# Regardless, pass the main project's keys (signing/verification) to the bootloader subproject
|
||||
# via config.
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
add_custom_target(gen_secure_boot_keys)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_ENABLED)
|
||||
# Check that the configuration is sane
|
||||
if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR
|
||||
(NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH))
|
||||
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
set(bootloader_binary_files
|
||||
${bootloader_binary_files}
|
||||
"${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin"
|
||||
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin"
|
||||
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Since keys are usually given relative to main project dir, get the absolute paths to the keys
|
||||
# for use by the bootloader subproject. Replace the values in config with these absolute paths,
|
||||
# so that bootloader subproject does not need to assume main project dir to obtain path to the keys.
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${CONFIG_SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
|
||||
if(NOT EXISTS ${secure_boot_signing_key})
|
||||
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that
|
||||
# fails the build. fail_at_build_time causes a cmake run next time
|
||||
# (to pick up a new signing key if one exists, etc.)
|
||||
fail_at_build_time(gen_secure_boot_signing_key
|
||||
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
|
||||
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_signing_key)
|
||||
endif()
|
||||
|
||||
set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components
|
||||
set(sign_key_arg "-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}")
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
|
||||
else()
|
||||
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${CONFIG_SECURE_BOOT_VERIFICATION_KEY}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
|
||||
if(NOT EXISTS ${secure_boot_verification_key})
|
||||
# If the verification key is not found, create a phony gen_secure_boot_verification_key target that
|
||||
# fails the build. fail_at_build_time causes a cmake run next time
|
||||
# (to pick up a new verification key if one exists, etc.)
|
||||
fail_at_build_time(gen_secure_boot_verification_key
|
||||
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
|
||||
"\tThis can be extracted from the private signing key."
|
||||
"\tSee docs/security/secure-boot.rst for details.")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_verification_key)
|
||||
endif()
|
||||
|
||||
set(ver_key_arg "-DSECURE_BOOT_VERIFICATION_KEY=${secure_boot_verification_key}")
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_verification_key)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if((NOT CONFIG_SECURE_BOOT_ENABLED) OR
|
||||
CONFIG_SECURE_BOOTLOADER_REFLASHABLE OR
|
||||
CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
idf_build_get_property(sdkconfig SDKCONFIG)
|
||||
idf_build_get_property(idf_target IDF_TARGET)
|
||||
externalproject_add(bootloader
|
||||
# TODO: support overriding the bootloader in COMPONENT_PATHS
|
||||
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
|
||||
BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
|
||||
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
|
||||
-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}
|
||||
-DPYTHON_DEPS_CHECKED=1
|
||||
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
|
||||
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
|
||||
# the bootloader common component requirements depends on this and
|
||||
# config variables are not available before project() call.
|
||||
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS 1 # no easy way around this...
|
||||
BUILD_BYPRODUCTS ${bootloader_binary_files}
|
||||
DEPENDS gen_secure_boot_signing_key
|
||||
)
|
||||
else()
|
||||
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?")
|
||||
idf_build_get_property(idf_path IDF_PATH)
|
||||
idf_build_get_property(idf_target IDF_TARGET)
|
||||
idf_build_get_property(sdkconfig SDKCONFIG)
|
||||
|
||||
externalproject_add(bootloader
|
||||
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
|
||||
BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
|
||||
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
|
||||
-DPYTHON_DEPS_CHECKED=1
|
||||
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
|
||||
${sign_key_arg} ${ver_key_arg}
|
||||
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
|
||||
# the bootloader common component requirements depends on this and
|
||||
# config variables are not available before project() call.
|
||||
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_ALWAYS 1 # no easy way around this...
|
||||
BUILD_BYPRODUCTS ${bootloader_binary_files}
|
||||
)
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
add_dependencies(bootloader gen_secure_boot_keys)
|
||||
endif()
|
||||
|
||||
# this is a hack due to an (annoying) shortcoming in cmake, it can't
|
||||
|
@ -29,8 +29,6 @@ project(bootloader)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND)
|
||||
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
|
||||
|
||||
set(secure_boot_signing_key ${SECURE_BOOT_SIGNING_KEY})
|
||||
|
||||
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
|
||||
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
|
||||
set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}")
|
||||
@ -53,7 +51,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
add_custom_command(OUTPUT "${secure_bootloader_key}"
|
||||
COMMAND ${ESPSECUREPY} digest_private_key
|
||||
--keylen "${key_digest_len}"
|
||||
--keyfile "${secure_boot_signing_key}"
|
||||
--keyfile "${SECURE_BOOT_SIGNING_KEY}"
|
||||
"${secure_bootloader_key}"
|
||||
VERBATIM)
|
||||
|
||||
@ -67,7 +65,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
"\nTo generate one, you can use this command:"
|
||||
"\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}"
|
||||
"\nIf a signing key is present, then instead use:"
|
||||
"\n\t${ESPSECUREPY} digest_private_key "
|
||||
"\n\t${espsecurepy} digest_private_key "
|
||||
"--keylen (192/256) --keyfile KEYFILE "
|
||||
"${secure_bootloader_key}")
|
||||
endif()
|
||||
@ -78,14 +76,14 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
|
||||
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
|
||||
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
DEPENDS gen_secure_bootloader_key "${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
DEPENDS gen_secure_bootloader_key gen_project_binary
|
||||
VERBATIM)
|
||||
|
||||
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
|
||||
add_custom_command(TARGET bootloader POST_BUILD
|
||||
add_custom_command(TARGET bootloader.elf POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
@ -97,9 +95,8 @@ if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
|
||||
VERBATIM)
|
||||
|
||||
elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
add_custom_command(TARGET bootloader POST_BUILD
|
||||
add_custom_command(TARGET bootloader.elf POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
|
@ -19,40 +19,6 @@ if(BOOTLOADER_BUILD)
|
||||
"src/${IDF_TARGET}/flash_encrypt.c"
|
||||
"src/${IDF_TARGET}/secure_boot_signatures.c"
|
||||
"src/${IDF_TARGET}/secure_boot.c")
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
get_filename_component(secure_boot_verification_key
|
||||
"signature_verification_key.bin"
|
||||
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
add_custom_command(OUTPUT "${secure_boot_verification_key}"
|
||||
COMMAND ${ESPSECUREPY}
|
||||
extract_public_key --keyfile "${secure_boot_signing_key}"
|
||||
"${secure_boot_verification_key}"
|
||||
DEPENDS gen_secure_boot_signing_key
|
||||
VERBATIM)
|
||||
else()
|
||||
get_filename_component(orig_secure_boot_verification_key
|
||||
"${CONFIG_SECURE_BOOT_VERIFICATION_KEY}"
|
||||
ABSOLUTE BASE_DIR "${main_project_path}")
|
||||
if(NOT EXISTS ${orig_secure_boot_verification_key})
|
||||
message(FATAL_ERROR
|
||||
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
|
||||
"\nThis can be extracted from the private signing key."
|
||||
"\nSee docs/security/secure-boot.rst for details.")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT "${secure_boot_verification_key}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy "${orig_secure_boot_verification_key}"
|
||||
"${secure_boot_verification_key}"
|
||||
DEPENDS "${orig_secure_boot_verification_key}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
set(embed_files "${secure_boot_verification_key}")
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${secure_boot_verification_key}")
|
||||
endif()
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"src/idf/bootloader_sha.c"
|
||||
@ -67,5 +33,33 @@ idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
REQUIRES "${requires}"
|
||||
PRIV_REQUIRES "${priv_requires}"
|
||||
EMBED_FILES "${embed_files}")
|
||||
PRIV_REQUIRES "${priv_requires}")
|
||||
|
||||
if(BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
|
||||
# Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed
|
||||
# in the library.
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# We generate the key from the signing key. The signing key is passed from the main project.
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${SECURE_BOOT_SIGNING_KEY}"
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
get_filename_component(secure_boot_verification_key
|
||||
"signature_verification_key.bin"
|
||||
ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_custom_command(OUTPUT "${secure_boot_verification_key}"
|
||||
COMMAND ${ESPSECUREPY}
|
||||
extract_public_key --keyfile "${secure_boot_signing_key}"
|
||||
"${secure_boot_verification_key}"
|
||||
VERBATIM)
|
||||
else()
|
||||
# We expect to 'inherit' the verification key passed from main project.
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${SECURE_BOOT_VERIFICATION_KEY}
|
||||
ABSOLUTE BASE_DIR "${project_dir}")
|
||||
endif()
|
||||
|
||||
target_add_binary_data(${COMPONENT_LIB} "${secure_boot_verification_key}" "BINARY")
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${secure_boot_verification_key}")
|
||||
endif()
|
||||
|
@ -53,7 +53,7 @@ if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION)
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary phy_init_data.obj ${phy_init_data_bin}
|
||||
)
|
||||
add_custom_target(phy_init_data ALL DEPENDS ${phy_init_data_bin})
|
||||
add_dependencies(app phy_init_data)
|
||||
add_dependencies(flash phy_init_data)
|
||||
|
||||
esptool_py_flash_project_args(phy ${phy_partition_offset} ${phy_init_data_bin} FLASH_IN_PROJECT)
|
||||
endif()
|
||||
|
@ -1,50 +1,72 @@
|
||||
idf_component_register(REQUIRES bootloader)
|
||||
|
||||
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS}")
|
||||
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
|
||||
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
|
||||
)
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_FLASH_OPTIONS}")
|
||||
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
|
||||
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
|
||||
)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_ENABLED)
|
||||
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS "")
|
||||
if(CONFIG_SECURE_BOOT_ENABLED)
|
||||
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS "")
|
||||
endif()
|
||||
|
||||
# Generate the flash project args and the flasher args json file using the accumulated values
|
||||
# from esptool_py_flash_project_args calls. The file is first configured using configure_file() for all variable values,
|
||||
# and then generated using file(GENERATE... for generator expressions.
|
||||
configure_file(${COMPONENT_DIR}/flash_project_args.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in)
|
||||
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in)
|
||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_project_args
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2)
|
||||
|
||||
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
|
||||
configure_file(${COMPONENT_DIR}/flash_encrypted_project_args.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
|
||||
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
|
||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_encrypted_project_args
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2)
|
||||
endif()
|
||||
|
||||
configure_file(${COMPONENT_DIR}/flasher_args.json.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
|
||||
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
|
||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flasher_args.json
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2)
|
||||
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2"
|
||||
"${CMAKE_BINARY_DIR}/flash_project_args"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2"
|
||||
"${CMAKE_BINARY_DIR}/flasher_args.json")
|
||||
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset")
|
||||
esptool_py_flash_project_args(app ${app_partition_offset} ${build_dir}/${PROJECT_BIN} FLASH_IN_PROJECT)
|
||||
|
||||
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in "--encrypt ${app_partition_offset} ${PROJECT_BIN}")
|
||||
esptool_py_flash_project_args(encrypted_app ${app_partition_offset} ${build_dir}/${PROJECT_BIN}
|
||||
FLASH_FILE_TEMPLATE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in)
|
||||
endif()
|
||||
|
||||
add_dependencies(flash partition_table)
|
||||
|
||||
# If anti-rollback option is set then factory partition should not be in Partition Table.
|
||||
# In this case, should be used the partition table with two ota app without the factory.
|
||||
partition_table_get_partition_info(factory_offset "--partition-type app --partition-subtype factory" "offset")
|
||||
if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND factory_offset)
|
||||
fail_at_build_time(check_table_contents
|
||||
"ERROR: Anti-rollback option is enabled. Partition table should consist of two ota app without factory partition.")
|
||||
add_dependencies(app check_table_contents)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Generate the flash project args and the flasher args json file using the accumulated values
|
||||
# from esptool_py_flash_project_args calls. The file is first configured using configure_file() for all variable values,
|
||||
# and then generated using file(GENERATE... for generator expressions.
|
||||
configure_file(${COMPONENT_DIR}/flash_project_args.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in)
|
||||
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in)
|
||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_project_args
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2)
|
||||
|
||||
|
||||
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
|
||||
configure_file(${COMPONENT_DIR}/flash_encrypted_project_args.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
|
||||
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
|
||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_encrypted_project_args
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2)
|
||||
endif()
|
||||
|
||||
|
||||
configure_file(${COMPONENT_DIR}/flasher_args.json.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
|
||||
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
|
||||
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flasher_args.json
|
||||
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2)
|
||||
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2"
|
||||
"${CMAKE_BINARY_DIR}/flash_project_args"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2"
|
||||
"${CMAKE_BINARY_DIR}/flasher_args.json")
|
||||
|
@ -31,7 +31,7 @@ else()
|
||||
set(ESPTOOLPY_COMPRESSED_OPT -u)
|
||||
endif()
|
||||
|
||||
set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
|
||||
set(ESPTOOLPY_FLASH_OPTIONS
|
||||
--flash_mode ${ESPFLASHMODE}
|
||||
--flash_freq ${ESPFLASHFREQ}
|
||||
--flash_size ${ESPFLASHSIZE}
|
||||
@ -40,19 +40,18 @@ set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
|
||||
# String for printing flash command
|
||||
string(REPLACE ";" " " ESPTOOLPY_WRITE_FLASH_STR
|
||||
"${ESPTOOLPY} --port (PORT) --baud (BAUD) --before ${ESPTOOLPY_BEFORE} --after ${ESPTOOLPY_AFTER} "
|
||||
"write_flash ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} ${ESPTOOLPY_EXTRA_FLASH_OPTIONS} ${ESPTOOLPY_COMPRESSED_OPT}")
|
||||
|
||||
if(CONFIG_SECURE_BOOT_ENABLED AND
|
||||
NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION AND
|
||||
NOT BOOTLOADER_BUILD)
|
||||
set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
|
||||
${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} --secure-pad)
|
||||
endif()
|
||||
"write_flash ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_EXTRA_FLASH_OPTIONS} ${ESPTOOLPY_COMPRESSED_OPT}")
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
set(ESPTOOLPY_ELF2IMAGE_OPTIONS --elf-sha256-offset 0xb0)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT_ENABLED AND
|
||||
NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION
|
||||
AND NOT BOOTLOADER_BUILD)
|
||||
set(ESPTOOLPY_ELF2IMAGE_OPTIONS ${ESPTOOLPY_ELF2IMAGE_OPTIONS} --secure-pad)
|
||||
endif()
|
||||
|
||||
if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT)
|
||||
# Set ESPFLASHSIZE to 'detect' *after* elf2image options are generated,
|
||||
# as elf2image can't have 'detect' as an option...
|
||||
@ -76,7 +75,7 @@ set(PROJECT_BIN "${elf_name}.bin")
|
||||
# Add 'app.bin' target - generates with elf2image
|
||||
#
|
||||
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
||||
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
|
||||
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
|
||||
-o "${build_dir}/${unsigned_project_binary}" "${elf}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${unsigned_project_binary}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${unsigned_project_binary}" > "${build_dir}/.bin_timestamp"
|
||||
@ -87,40 +86,42 @@ add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
|
||||
)
|
||||
add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp")
|
||||
|
||||
if(NOT BOOTLOADER_BUILD AND
|
||||
CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${build_dir}/${unsigned_project_binary}"
|
||||
)
|
||||
|
||||
# for locally signed secure boot image, add a signing step to get from unsigned app to signed app
|
||||
add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp"
|
||||
COMMAND ${ESPSECUREPY} sign_data --keyfile ${secure_boot_signing_key}
|
||||
-o "${build_dir}/${PROJECT_BIN}" "${build_dir}/${unsigned_project_binary}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
|
||||
"from ${build_dir}/${unsigned_project_binary}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${PROJECT_BIN}" > "${build_dir}/.signed_bin_timestamp"
|
||||
DEPENDS "${build_dir}/.bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Generating signed binary image"
|
||||
)
|
||||
add_custom_target(gen_signed_project_binary DEPENDS "${build_dir}/.signed_bin_timestamp")
|
||||
add_dependencies(gen_project_binary gen_signed_project_binary)
|
||||
endif()
|
||||
add_custom_target(app ALL DEPENDS gen_project_binary)
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
add_custom_target(app ALL DEPENDS gen_project_binary)
|
||||
else()
|
||||
add_custom_target(bootloader ALL DEPENDS gen_project_binary)
|
||||
endif()
|
||||
if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
# for locally signed secure boot image, add a signing step to get from unsigned app to signed app
|
||||
add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp"
|
||||
COMMAND ${ESPSECUREPY} sign_data --keyfile ${secure_boot_signing_key}
|
||||
-o "${build_dir}/${PROJECT_BIN}" "${build_dir}/${unsigned_project_binary}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
|
||||
"from ${build_dir}/${unsigned_project_binary}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${PROJECT_BIN}" > "${build_dir}/.signed_bin_timestamp"
|
||||
DEPENDS "${build_dir}/.bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Generating signed binary image"
|
||||
)
|
||||
add_custom_target(gen_signed_project_binary DEPENDS "${build_dir}/.signed_bin_timestamp")
|
||||
add_dependencies(gen_project_binary gen_signed_project_binary)
|
||||
|
||||
|
||||
if(NOT BOOTLOADER_BUILD AND
|
||||
CONFIG_SECURE_BOOT_ENABLED AND
|
||||
NOT CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
add_custom_command(TARGET app POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"App built but not signed. Sign app before flashing"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${ESPSECUREPY} sign_data --keyfile KEYFILE ${build_dir}/${elf_bin}"
|
||||
VERBATIM)
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${build_dir}/${PROJECT_BIN}"
|
||||
)
|
||||
else()
|
||||
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
|
||||
add_custom_command(TARGET app POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"App built but not signed. Sign app before flashing"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/${PROJECT_BIN}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#
|
||||
@ -142,7 +143,6 @@ endfunction()
|
||||
|
||||
esptool_py_custom_target(flash project "app;partition_table;bootloader")
|
||||
esptool_py_custom_target(app-flash app "app")
|
||||
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
|
||||
|
||||
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
|
||||
esptool_py_custom_target(encrypted-flash encrypted_project "app;partition_table;bootloader")
|
||||
|
@ -40,19 +40,6 @@ add_custom_command(OUTPUT "${build_dir}/partition_table/${unsigned_partition_bin
|
||||
DEPENDS ${partition_csv} "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py"
|
||||
VERBATIM)
|
||||
|
||||
# Add signing steps
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
add_custom_target(gen_unsigned_partition_bin ALL DEPENDS
|
||||
"${build_dir}/partition_table/${unsigned_partition_bin}")
|
||||
|
||||
add_custom_command(OUTPUT "${build_dir}/partition_table/${final_partition_bin}"
|
||||
COMMAND ${ESPSECUREPY} sign_data --keyfile "${secure_boot_signing_key}"
|
||||
-o "${build_dir}/partition_table/${final_partition_bin}"
|
||||
"${build_dir}/partition_table/${unsigned_partition_bin}"
|
||||
DEPENDS "${build_dir}/partition_table/${unsigned_partition_bin}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
if(EXISTS ${partition_csv})
|
||||
add_custom_target(partition_table ALL DEPENDS "${build_dir}/partition_table/${final_partition_bin}")
|
||||
else()
|
||||
@ -64,29 +51,29 @@ else()
|
||||
"Either change partition table in menuconfig or create this input file.")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT_ENABLED AND
|
||||
NOT CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
add_custom_command(TARGET partition_table POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Partition table built but not signed. Sign partition data before flashing:"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${ESPSECUREPY} sign_data --keyfile KEYFILE ${CMAKE_CURRENT_BINARY_DIR}/${final_partition_bin}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
# Add signing steps
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
add_custom_target(gen_unsigned_partition_bin ALL DEPENDS
|
||||
"${build_dir}/partition_table/${unsigned_partition_bin}")
|
||||
|
||||
# If anti-rollback option is set then factory partition should not be in Partition Table.
|
||||
# In this case, should be used the partition table with two ota app without the factory.
|
||||
partition_table_get_partition_info(factory_offset "--partition-type app --partition-subtype factory" "offset")
|
||||
if(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK AND factory_offset)
|
||||
fail_at_build_time(check_table_contents
|
||||
"ERROR: Anti-rollback option is enabled. Partition table should consist of two ota app without factory partition.")
|
||||
add_dependencies(bootloader check_table_contents)
|
||||
add_dependencies(app check_table_contents)
|
||||
add_custom_command(OUTPUT "${build_dir}/partition_table/${final_partition_bin}"
|
||||
COMMAND ${ESPSECUREPY} sign_data --keyfile "${SECURE_BOOT_SIGNING_KEY}"
|
||||
-o "${build_dir}/partition_table/${final_partition_bin}"
|
||||
"${build_dir}/partition_table/${unsigned_partition_bin}"
|
||||
DEPENDS "${build_dir}/partition_table/${unsigned_partition_bin}"
|
||||
VERBATIM)
|
||||
else()
|
||||
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
|
||||
add_custom_command(TARGET partition_table POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Partition table built but not signed. Sign partition data before flashing:"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/partition_table/${final_partition_bin}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_dependencies(bootloader partition_table)
|
||||
add_dependencies(app partition_table)
|
||||
|
||||
# Use global properties ESPTOOL_WRITE_FLASH_ARGS to pass this info to build
|
||||
# the list of esptool write arguments for flashing
|
||||
set_property(GLOBAL APPEND_STRING PROPERTY
|
||||
@ -95,13 +82,3 @@ set_property(GLOBAL APPEND_STRING PROPERTY
|
||||
|
||||
esptool_py_flash_project_args(partition_table ${PARTITION_TABLE_OFFSET}
|
||||
${build_dir}/partition_table/partition-table.bin FLASH_IN_PROJECT)
|
||||
|
||||
partition_table_get_partition_info(app_partition_offset "--partition-boot-default" "offset")
|
||||
esptool_py_flash_project_args(app ${app_partition_offset} ${build_dir}/${PROJECT_BIN} FLASH_IN_PROJECT)
|
||||
|
||||
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in "--encrypt ${app_partition_offset} ${PROJECT_BIN}")
|
||||
esptool_py_flash_project_args(encrypted_app ${app_partition_offset} ${build_dir}/${PROJECT_BIN}
|
||||
FLASH_FILE_TEMPLATE ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_app_args.in)
|
||||
endif()
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
The following features are not yet supported with the CMake-based build system:
|
||||
|
||||
- Eclipse IDE Documentation
|
||||
- Secure Boot
|
||||
- Flash Encryption
|
||||
|
||||
Support for these features will be available before CMake becomes the default build system.
|
||||
|
||||
|
@ -488,6 +488,17 @@ endmenu\n" >> ${IDF_PATH}/Kconfig;
|
||||
print_status "Can set -D twice: globally and for subcommand, only if values are the same"
|
||||
idf.py -DAAA=BBB -DCCC=EEE build -DAAA=BBB -DCCC=EEE || failure "It should be allowed to set -D twice (globally and for subcommand) if values are the same"
|
||||
|
||||
print_status "Fail on build time works"
|
||||
clean_build_dir
|
||||
cp CMakeLists.txt CMakeLists.txt.bak
|
||||
printf "\nif(NOT EXISTS \"\${CMAKE_CURRENT_LIST_DIR}/hello.txt\") \nfail_at_build_time(test_file \"hello.txt does not exists\") \nendif()" >> CMakeLists.txt
|
||||
! idf.py build || failure "Build should fail if requirements are not satisfied"
|
||||
touch hello.txt
|
||||
idf.py build || failure "Build succeeds once requirements are satisfied"
|
||||
rm -rf hello.txt CMakeLists.txt
|
||||
mv CMakeLists.txt.bak CMakeLists.txt
|
||||
rm -rf CMakeLists.txt.bak
|
||||
|
||||
print_status "All tests completed"
|
||||
if [ -n "${FAILURES}" ]; then
|
||||
echo "Some failures were detected:"
|
||||
|
@ -201,9 +201,15 @@ function(fail_at_build_time target_name message_line0)
|
||||
foreach(message_line ${ARGN})
|
||||
set(message_lines ${message_lines} COMMAND ${CMAKE_COMMAND} -E echo "${message_line}")
|
||||
endforeach()
|
||||
# Generate a timestamp file that gets included. When deleted on build, this forces CMake
|
||||
# to rerun.
|
||||
string(RANDOM filename)
|
||||
set(filename "${CMAKE_CURRENT_BINARY_DIR}/${filename}.cmake")
|
||||
file(WRITE "${filename}" "")
|
||||
include("${filename}")
|
||||
add_custom_target(${target_name} ALL
|
||||
${message_lines}
|
||||
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/CMakeCache.txt"
|
||||
COMMAND ${CMAKE_COMMAND} -E remove "${filename}"
|
||||
COMMAND ${CMAKE_COMMAND} -P ${idf_path}/tools/cmake/scripts/fail.cmake
|
||||
VERBATIM)
|
||||
endfunction()
|
||||
|
Loading…
x
Reference in New Issue
Block a user