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:
Angus Gratton 2019-06-28 15:38:59 +08:00
commit 265d7dc4e5
12 changed files with 294 additions and 240 deletions

View File

@ -34,7 +34,7 @@ if(NOT BOOTLOADER_BUILD)
${otadata_size} ${blank_otadata_file}) ${otadata_size} ${blank_otadata_file})
add_custom_target(blank_ota_data ALL DEPENDS ${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) set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py)

View File

@ -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 # Do not generate flash file when building bootloader or is in early expansion of the build
if(BOOTLOADER_BUILD) if(BOOTLOADER_BUILD)
return() return()
endif() 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 # Set values used in flash_bootloader_args.in and generate flash file
# for bootloader # for bootloader
esptool_py_flash_project_args(bootloader 0x1000 esptool_py_flash_project_args(bootloader 0x1000
${BOOTLOADER_BUILD_DIR}/bootloader.bin ${BOOTLOADER_BUILD_DIR}/bootloader.bin
FLASH_IN_PROJECT ${flash_bootloader}
FLASH_FILE_TEMPLATE flash_bootloader_args.in) FLASH_FILE_TEMPLATE flash_bootloader_args.in)
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
add_dependencies(bootloader partition_table)

View File

@ -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) if(BOOTLOADER_BUILD)
return() return()
endif() 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 # Glue to build the bootloader subproject binary as an external
# cmake project under this one # cmake project under this one
# #
@ -39,7 +17,25 @@ set(bootloader_binary_files
"${BOOTLOADER_BUILD_DIR}/bootloader.map" "${BOOTLOADER_BUILD_DIR}/bootloader.map"
) )
# These additional files may get generated 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) if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
set(bootloader_binary_files set(bootloader_binary_files
${bootloader_binary_files} ${bootloader_binary_files}
@ -48,21 +44,66 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin" "${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin"
) )
endif() 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(idf_path IDF_PATH)
idf_build_get_property(sdkconfig SDKCONFIG)
idf_build_get_property(idf_target IDF_TARGET) idf_build_get_property(idf_target IDF_TARGET)
idf_build_get_property(sdkconfig SDKCONFIG)
externalproject_add(bootloader externalproject_add(bootloader
# TODO: support overriding the bootloader in COMPONENT_PATHS
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject" SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
BINARY_DIR "${BOOTLOADER_BUILD_DIR}" BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target} CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}
-DPYTHON_DEPS_CHECKED=1 -DPYTHON_DEPS_CHECKED=1
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR} -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 # LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
# the bootloader common component requirements depends on this and # the bootloader common component requirements depends on this and
# config variables are not available before project() call. # config variables are not available before project() call.
@ -70,10 +111,10 @@ if((NOT CONFIG_SECURE_BOOT_ENABLED) OR
INSTALL_COMMAND "" INSTALL_COMMAND ""
BUILD_ALWAYS 1 # no easy way around this... BUILD_ALWAYS 1 # no easy way around this...
BUILD_BYPRODUCTS ${bootloader_binary_files} BUILD_BYPRODUCTS ${bootloader_binary_files}
DEPENDS gen_secure_boot_signing_key
) )
else()
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?") if(CONFIG_SECURE_SIGNED_APPS)
add_dependencies(bootloader gen_secure_boot_keys)
endif() endif()
# this is a hack due to an (annoying) shortcoming in cmake, it can't # this is a hack due to an (annoying) shortcoming in cmake, it can't

View File

@ -29,8 +29,6 @@ project(bootloader)
idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND) idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" 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 ";" " " espsecurepy "${ESPSECUREPY}")
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}") string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}") set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}")
@ -53,7 +51,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_command(OUTPUT "${secure_bootloader_key}" add_custom_command(OUTPUT "${secure_bootloader_key}"
COMMAND ${ESPSECUREPY} digest_private_key COMMAND ${ESPSECUREPY} digest_private_key
--keylen "${key_digest_len}" --keylen "${key_digest_len}"
--keyfile "${secure_boot_signing_key}" --keyfile "${SECURE_BOOT_SIGNING_KEY}"
"${secure_bootloader_key}" "${secure_bootloader_key}"
VERBATIM) VERBATIM)
@ -67,7 +65,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
"\nTo generate one, you can use this command:" "\nTo generate one, you can use this command:"
"\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}" "\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}"
"\nIf a signing key is present, then instead use:" "\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 " "--keylen (192/256) --keyfile KEYFILE "
"${secure_bootloader_key}") "${secure_bootloader_key}")
endif() endif()
@ -78,14 +76,14 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}" COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}" COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin" -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) VERBATIM)
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}") add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
endif() endif()
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) 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
"==============================================================================" "=============================================================================="
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 COMMAND ${CMAKE_COMMAND} -E echo
"* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device" "* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
VERBATIM) VERBATIM)
elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) 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
"==============================================================================" "=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo

View File

@ -19,40 +19,6 @@ if(BOOTLOADER_BUILD)
"src/${IDF_TARGET}/flash_encrypt.c" "src/${IDF_TARGET}/flash_encrypt.c"
"src/${IDF_TARGET}/secure_boot_signatures.c" "src/${IDF_TARGET}/secure_boot_signatures.c"
"src/${IDF_TARGET}/secure_boot.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() else()
list(APPEND srcs list(APPEND srcs
"src/idf/bootloader_sha.c" "src/idf/bootloader_sha.c"
@ -67,5 +33,33 @@ idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}" INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS "${priv_include_dirs}" PRIV_INCLUDE_DIRS "${priv_include_dirs}"
REQUIRES "${requires}" REQUIRES "${requires}"
PRIV_REQUIRES "${priv_requires}" PRIV_REQUIRES "${priv_requires}")
EMBED_FILES "${embed_files}")
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()

View File

@ -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} 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_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) esptool_py_flash_project_args(phy ${phy_partition_offset} ${phy_init_data_bin} FLASH_IN_PROJECT)
endif() endif()

View File

@ -1,6 +1,7 @@
idf_component_register(REQUIRES bootloader) idf_component_register(REQUIRES bootloader)
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS}") if(NOT BOOTLOADER_BUILD)
string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_FLASH_OPTIONS}")
set(ESPTOOLPY_FLASH_PROJECT_OPTIONS set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
"${ESPTOOLPY_FLASH_PROJECT_OPTIONS}" "${ESPTOOLPY_FLASH_PROJECT_OPTIONS}"
) )
@ -20,7 +21,6 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2
file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_project_args file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/flash_project_args
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2) INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_project_args.in2)
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
configure_file(${COMPONENT_DIR}/flash_encrypted_project_args.in configure_file(${COMPONENT_DIR}/flash_encrypted_project_args.in
${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in) ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in)
@ -31,7 +31,6 @@ if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2) INPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_encrypted_project_args.in2)
endif() endif()
configure_file(${COMPONENT_DIR}/flasher_args.json.in configure_file(${COMPONENT_DIR}/flasher_args.json.in
${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in) ${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in)
@ -48,3 +47,26 @@ set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in" "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in"
"${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2" "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json.in2"
"${CMAKE_BINARY_DIR}/flasher_args.json") "${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()

View File

@ -31,7 +31,7 @@ else()
set(ESPTOOLPY_COMPRESSED_OPT -u) set(ESPTOOLPY_COMPRESSED_OPT -u)
endif() endif()
set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS set(ESPTOOLPY_FLASH_OPTIONS
--flash_mode ${ESPFLASHMODE} --flash_mode ${ESPFLASHMODE}
--flash_freq ${ESPFLASHFREQ} --flash_freq ${ESPFLASHFREQ}
--flash_size ${ESPFLASHSIZE} --flash_size ${ESPFLASHSIZE}
@ -40,19 +40,18 @@ set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
# String for printing flash command # String for printing flash command
string(REPLACE ";" " " ESPTOOLPY_WRITE_FLASH_STR string(REPLACE ";" " " ESPTOOLPY_WRITE_FLASH_STR
"${ESPTOOLPY} --port (PORT) --baud (BAUD) --before ${ESPTOOLPY_BEFORE} --after ${ESPTOOLPY_AFTER} " "${ESPTOOLPY} --port (PORT) --baud (BAUD) --before ${ESPTOOLPY_BEFORE} --after ${ESPTOOLPY_AFTER} "
"write_flash ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} ${ESPTOOLPY_EXTRA_FLASH_OPTIONS} ${ESPTOOLPY_COMPRESSED_OPT}") "write_flash ${ESPTOOLPY_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()
if(NOT BOOTLOADER_BUILD) if(NOT BOOTLOADER_BUILD)
set(ESPTOOLPY_ELF2IMAGE_OPTIONS --elf-sha256-offset 0xb0) set(ESPTOOLPY_ELF2IMAGE_OPTIONS --elf-sha256-offset 0xb0)
endif() 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) if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT)
# Set ESPFLASHSIZE to 'detect' *after* elf2image options are generated, # Set ESPFLASHSIZE to 'detect' *after* elf2image options are generated,
# as elf2image can't have 'detect' as an option... # 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 'app.bin' target - generates with elf2image
# #
add_custom_command(OUTPUT "${build_dir}/.bin_timestamp" 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}" -o "${build_dir}/${unsigned_project_binary}" "${elf}"
COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${unsigned_project_binary}" 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" COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/${unsigned_project_binary}" > "${build_dir}/.bin_timestamp"
@ -87,9 +86,15 @@ add_custom_command(OUTPUT "${build_dir}/.bin_timestamp"
) )
add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp") add_custom_target(gen_project_binary DEPENDS "${build_dir}/.bin_timestamp")
if(NOT BOOTLOADER_BUILD AND set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${build_dir}/${unsigned_project_binary}"
)
add_custom_target(app ALL DEPENDS gen_project_binary)
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 # 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" add_custom_command(OUTPUT "${build_dir}/.signed_bin_timestamp"
COMMAND ${ESPSECUREPY} sign_data --keyfile ${secure_boot_signing_key} COMMAND ${ESPSECUREPY} sign_data --keyfile ${secure_boot_signing_key}
@ -103,25 +108,21 @@ if(NOT BOOTLOADER_BUILD AND
) )
add_custom_target(gen_signed_project_binary DEPENDS "${build_dir}/.signed_bin_timestamp") add_custom_target(gen_signed_project_binary DEPENDS "${build_dir}/.signed_bin_timestamp")
add_dependencies(gen_project_binary gen_signed_project_binary) add_dependencies(gen_project_binary gen_signed_project_binary)
endif()
if(NOT BOOTLOADER_BUILD) set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
add_custom_target(app ALL DEPENDS gen_project_binary) APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${build_dir}/${PROJECT_BIN}"
)
else() else()
add_custom_target(bootloader ALL DEPENDS gen_project_binary) string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
endif()
if(NOT BOOTLOADER_BUILD AND
CONFIG_SECURE_BOOT_ENABLED AND
NOT CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
add_custom_command(TARGET app POST_BUILD add_custom_command(TARGET app POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo
"App built but not signed. Sign app before flashing" "App built but not signed. Sign app before flashing"
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo
"\t${ESPSECUREPY} sign_data --keyfile KEYFILE ${build_dir}/${elf_bin}" "\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/${PROJECT_BIN}"
VERBATIM) VERBATIM)
endif() endif()
endif()
# #
# Add 'flash' target - not all build systems can run this directly # Add 'flash' target - not all build systems can run this directly
@ -142,7 +143,6 @@ endfunction()
esptool_py_custom_target(flash project "app;partition_table;bootloader") esptool_py_custom_target(flash project "app;partition_table;bootloader")
esptool_py_custom_target(app-flash app "app") esptool_py_custom_target(app-flash app "app")
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
esptool_py_custom_target(encrypted-flash encrypted_project "app;partition_table;bootloader") esptool_py_custom_target(encrypted-flash encrypted_project "app;partition_table;bootloader")

View File

@ -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" DEPENDS ${partition_csv} "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py"
VERBATIM) 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}) if(EXISTS ${partition_csv})
add_custom_target(partition_table ALL DEPENDS "${build_dir}/partition_table/${final_partition_bin}") add_custom_target(partition_table ALL DEPENDS "${build_dir}/partition_table/${final_partition_bin}")
else() else()
@ -64,29 +51,29 @@ else()
"Either change partition table in menuconfig or create this input file.") "Either change partition table in menuconfig or create this input file.")
endif() endif()
if(CONFIG_SECURE_BOOT_ENABLED AND # Add signing steps
NOT CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) 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}")
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 add_custom_command(TARGET partition_table POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo
"Partition table built but not signed. Sign partition data before flashing:" "Partition table built but not signed. Sign partition data before flashing:"
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo
"\t${ESPSECUREPY} sign_data --keyfile KEYFILE ${CMAKE_CURRENT_BINARY_DIR}/${final_partition_bin}" "\t${espsecurepy} sign_data --keyfile KEYFILE ${build_dir}/partition_table/${final_partition_bin}"
VERBATIM) VERBATIM)
endif() endif()
# 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)
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 # Use global properties ESPTOOL_WRITE_FLASH_ARGS to pass this info to build
# the list of esptool write arguments for flashing # the list of esptool write arguments for flashing
set_property(GLOBAL APPEND_STRING PROPERTY 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} esptool_py_flash_project_args(partition_table ${PARTITION_TABLE_OFFSET}
${build_dir}/partition_table/partition-table.bin FLASH_IN_PROJECT) ${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()

View File

@ -2,8 +2,6 @@
The following features are not yet supported with the CMake-based build system: The following features are not yet supported with the CMake-based build system:
- Eclipse IDE Documentation - Eclipse IDE Documentation
- Secure Boot
- Flash Encryption
Support for these features will be available before CMake becomes the default build system. Support for these features will be available before CMake becomes the default build system.

View File

@ -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" 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" 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" print_status "All tests completed"
if [ -n "${FAILURES}" ]; then if [ -n "${FAILURES}" ]; then
echo "Some failures were detected:" echo "Some failures were detected:"

View File

@ -201,9 +201,15 @@ function(fail_at_build_time target_name message_line0)
foreach(message_line ${ARGN}) foreach(message_line ${ARGN})
set(message_lines ${message_lines} COMMAND ${CMAKE_COMMAND} -E echo "${message_line}") set(message_lines ${message_lines} COMMAND ${CMAKE_COMMAND} -E echo "${message_line}")
endforeach() 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 add_custom_target(${target_name} ALL
${message_lines} ${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 COMMAND ${CMAKE_COMMAND} -P ${idf_path}/tools/cmake/scripts/fail.cmake
VERBATIM) VERBATIM)
endfunction() endfunction()