]> granicus.if.org Git - esp-idf/commitdiff
CMake : Secure Boot support added
authorAnurag Kar <anurag.kar@espressif.com>
Fri, 19 Oct 2018 19:02:55 +0000 (00:32 +0530)
committerAnurag Kar <anurag.kar@espressif.com>
Tue, 6 Nov 2018 11:39:55 +0000 (17:09 +0530)
12 files changed:
components/bootloader/project_include.cmake
components/bootloader/subproject/CMakeLists.txt
components/bootloader_support/CMakeLists.txt
components/esptool_py/CMakeLists.txt
components/esptool_py/flash_bootloader_args.in
components/esptool_py/flash_project_args.in
components/esptool_py/flasher_args.json.in
components/esptool_py/project_include.cmake
components/partition_table/CMakeLists.txt
components/partition_table/project_include.cmake
tools/cmake/utilities.cmake
tools/idf.py

index d59689820d6c5b2de087f94edbdf1ecc2e19b75a..54799088cd43f5c50996a4ffbb0501d631d09de8 100644 (file)
@@ -1,3 +1,24 @@
+# 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_PATH}")
+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()
+
 if(BOOTLOADER_BUILD)
     return()  # don't keep recursing!
 endif()
@@ -13,16 +34,34 @@ set(bootloader_binary_files
     "${bootloader_build_dir}/bootloader.map"
     )
 
-externalproject_add(bootloader
-    # TODO: support overriding the bootloader in COMPONENT_PATHS
-    SOURCE_DIR "${IDF_PATH}/components/bootloader/subproject"
-    BINARY_DIR "${bootloader_build_dir}"
-    CMAKE_ARGS  -DSDKCONFIG=${SDKCONFIG} -DIDF_PATH=${IDF_PATH} -DEXTRA_COMPONENT_DIRS=${COMPONENT_DIRS}
-                -DTESTS_ALL=0 -DTEST_COMPONENTS=""
-    INSTALL_COMMAND ""
-    BUILD_ALWAYS 1  # no easy way around this...
-    BUILD_BYPRODUCTS ${bootloader_binary_files}
-    )
+# 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"
+        )
+endif()
+
+if((NOT CONFIG_SECURE_BOOT_ENABLED) OR
+    CONFIG_SECURE_BOOTLOADER_REFLASHABLE OR
+    CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
+    externalproject_add(bootloader
+        # TODO: support overriding the bootloader in COMPONENT_PATHS
+        SOURCE_DIR "${IDF_PATH}/components/bootloader/subproject"
+        BINARY_DIR "${bootloader_build_dir}"
+        CMAKE_ARGS  -DSDKCONFIG=${SDKCONFIG} -DIDF_PATH=${IDF_PATH} -DEXTRA_COMPONENT_DIRS=${COMPONENT_DIRS}
+                    -DTESTS_ALL=0 -DTEST_COMPONENTS=""
+                    -DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}
+        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?")
+endif()
 
 # this is a hack due to an (annoying) shortcoming in cmake, it can't
 # extend the 'clean' target to the external project
index 6d3c44c44976d4a8837c09c94a4636093be5d652..2d75c0a4dfab34120f6a74de22b98d3db1c14e60 100644 (file)
@@ -26,3 +26,104 @@ target_linker_script(bootloader.elf
 target_linker_script(bootloader.elf ${ESP32_BOOTLOADER_LINKER_SCRIPTS})
 
 target_link_libraries(bootloader.elf gcc)
+
+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}")
+
+if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
+    if(CONFIG_SECURE_BOOTLOADER_KEY_ENCODING_192BIT)
+        set(key_digest_len 192)
+    else()
+        set(key_digest_len 256)
+    endif()
+
+    get_filename_component(bootloader_digest_bin
+        "bootloader-reflash-digest.bin"
+        ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
+
+    get_filename_component(secure_bootloader_key
+        "secure-bootloader-key-${key_digest_len}.bin"
+        ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
+
+    add_custom_command(OUTPUT "${secure_bootloader_key}"
+        COMMAND ${ESPSECUREPY} digest_private_key
+            --keylen "${key_digest_len}"
+            --keyfile "${secure_boot_signing_key}"
+            "${secure_bootloader_key}"
+        VERBATIM)
+
+    if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
+        add_custom_target(gen_secure_bootloader_key ALL DEPENDS "${secure_bootloader_key}")
+    else()
+        if(NOT EXISTS "${secure_bootloader_key}")
+            message(FATAL_ERROR
+                "No pre-generated key for a reflashable secure bootloader is available, "
+                "due to signing configuration."
+                "\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 "
+                "--keylen (192/256) --keyfile KEYFILE "
+                "${secure_bootloader_key}")
+        endif()
+        add_custom_target(gen_secure_bootloader_key)
+    endif()
+
+    add_custom_command(OUTPUT "${bootloader_digest_bin}"
+        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"
+        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
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "=============================================================================="
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "One-time flash command is:"
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
+        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
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "=============================================================================="
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "Bootloader built and secure digest generated."
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "Secure boot enabled, so bootloader not flashed automatically."
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "Burn secure boot key to efuse using:"
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "\t${espefusepy} burn_key secure_boot ${secure_bootloader_key}"
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "First time flash command is:"
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "=============================================================================="
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "To reflash the bootloader after initial flash:"
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "\t${esptoolpy_write_flash} 0x0 ${bootloader_digest_bin}"
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "=============================================================================="
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "* After first boot, only re-flashes of this kind (with same key) will be accepted."
+        COMMAND ${CMAKE_COMMAND} -E echo
+            "* Not recommended to re-use the same secure boot keyfile on multiple production devices."
+        DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
+        VERBATIM)
+endif()
index cdb086abfa4266d5f81f3173e482f857af4ff84c..088040f16fd902af31c681a982283c27286e2e18 100644 (file)
@@ -17,6 +17,40 @@ if(${BOOTLOADER_BUILD})
     set(COMPONENT_REQUIRES)
     set(COMPONENT_PRIV_REQUIRES spi_flash micro-ecc)
     list(APPEND COMPONENT_SRCS "src/bootloader_init.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(COMPONENT_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()
     set(COMPONENT_ADD_INCLUDEDIRS "include")
     set(COMPONENT_PRIV_INCLUDEDIRS "include_bootloader")
index 690763934ed15ee7680b22dcc3bdec7d36659125..05293be3748ddfa9108d3e692c29e42af60a05ef 100644 (file)
@@ -1,5 +1,14 @@
 register_config_only_component()
 
+string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS}")
+set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
+    "${ESPTOOLPY_FLASH_PROJECT_OPTIONS} ${BOOTLOADER_OFFSET} bootloader/bootloader.bin"
+    )
+
+if(CONFIG_SECURE_BOOT_ENABLED)
+    set(ESPTOOLPY_FLASH_PROJECT_OPTIONS "")
+endif()
+
 # Generate pre-canned flasher args files suitable for passing to esptool.py
 foreach(part project app bootloader partition_table)
     configure_file(
index ac19a6d81199806d293cf2e517559096f61146b8..cd7b7766d3f963e32e89efcbddbea826cbff5b9f 100644 (file)
@@ -1,4 +1,4 @@
 --flash_mode ${ESPFLASHMODE}
 --flash_size ${ESPFLASHSIZE}
 --flash_freq ${ESPFLASHFREQ}
-0x1000 bootloader/bootloader.bin
+${BOOTLOADER_OFFSET} bootloader/bootloader.bin
index c09bc08fbd0e584ce84cebf4ca4cf961600ac774..18ee9ab2c506500e6c56917bc39e8961bd9d1692 100644 (file)
@@ -1,7 +1,4 @@
---flash_mode ${ESPFLASHMODE}
---flash_size ${ESPFLASHSIZE}
---flash_freq ${ESPFLASHFREQ}
-0x1000 bootloader/bootloader.bin
+${ESPTOOLPY_FLASH_PROJECT_OPTIONS}
 ${PARTITION_TABLE_OFFSET} partition_table/partition-table.bin
 ${PHY_PARTITION_OFFSET} ${PHY_PARTITION_BIN_FILE}
 ${OTADATA_PARTITION_OFFSET} ${BLANK_OTADATA_FILE}
index 6a4128f1336c5d2996fb5a5eef8a2eaa1c3cc907..bc0e5e3409d81c2ee626d2cde2e10ec23a02dfd1 100644 (file)
@@ -3,18 +3,22 @@
                            "--flash_size", "${ESPFLASHSIZE}",
                            "--flash_freq", "${ESPFLASHFREQ}" ],
     "flash_files" : {
-        "0x1000" : "bootloader/bootloader.bin",
+        "${BOOTLOADER_OFFSET}" : "bootloader/bootloader.bin",
         "${PARTITION_TABLE_OFFSET}" : "partition_table/partition-table.bin",
         "${PHY_PARTITION_OFFSET}" : "${PHY_PARTITION_BIN_FILE}",
         "${OTADATA_PARTITION_OFFSET}" : "${BLANK_OTADATA_FILE}",
         "${APP_PARTITION_OFFSET}" : "${PROJECT_NAME}.bin"
     },
-    "bootloader" :      { "offset" : "0x1000",
+    "bootloader" :      { "offset" : "${BOOTLOADER_OFFSET}",
                           "file" : "bootloader/bootloader.bin" },
     "partition_table" : { "offset" : "${PARTITION_TABLE_OFFSET}",
                           "file" : "partition_table/partition-table.bin" },
     "otadata" : { "offset" : "${OTADATA_PARTITION_OFFSET}",
                   "file" : "${BLANK_OTADATA_FILE}" },
     "app" :             { "offset" : "${APP_PARTITION_OFFSET}",
-                          "file" : "${PROJECT_NAME}.bin" }
+                          "file" : "${PROJECT_NAME}.bin" },
+    "extra_esptool_args" : {
+        "after"  : "${ESPTOOLPY_AFTER}",
+        "before" : "${ESPTOOLPY_BEFORE}"
+    }
 }
index e39b09485631a8563e1b473f3e64984efa0e7933..7ab07f5b826341c01608f148ac4dd343653d56ec 100644 (file)
@@ -1,14 +1,34 @@
 # Set some global esptool.py variables
 #
 # Many of these are read when generating flash_app_args & flash_project_args
-set(ESPTOOLPY "${PYTHON}" "${CMAKE_CURRENT_LIST_DIR}/esptool/esptool.py" --chip esp32)
-set(ESPSECUREPY "${PYTHON}" "${CMAKE_CURRENT_LIST_DIR}/esptool/espsecure.py")
+set(ESPTOOLPY "${CMAKE_CURRENT_LIST_DIR}/esptool/esptool.py" --chip esp32)
+set(ESPSECUREPY "${CMAKE_CURRENT_LIST_DIR}/esptool/espsecure.py")
+set(ESPEFUSEPY "${CMAKE_CURRENT_LIST_DIR}/esptool/espefuse.py")
 
 set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE})
 set(ESPFLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ})
 set(ESPFLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE})
 
-set(ESPTOOLPY_SERIAL "${ESPTOOLPY}" --port "${ESPPORT}" --baud ${ESPBAUD})
+set(ESPTOOLPY_BEFORE "${CONFIG_ESPTOOLPY_BEFORE}")
+set(ESPTOOLPY_AFTER  "${CONFIG_ESPTOOLPY_AFTER}")
+
+if(CONFIG_SECURE_BOOT_ENABLED OR CONFIG_FLASH_ENCRYPTION_ENABLED)
+    # If security enabled then override post flash option
+    set(ESPTOOLPY_AFTER "no_reset")
+endif()
+
+set(ESPTOOLPY_SERIAL "${ESPTOOLPY}"
+    --port "${ESPPORT}"
+    --baud ${ESPBAUD}
+    --before "${ESPTOOLPY_BEFORE}"
+    --after "${ESPTOOLPY_AFTER}"
+    )
+
+if(CONFIG_ESPTOOLPY_COMPRESSED)
+    set(ESPTOOLPY_COMPRESSED_OPT -z)
+else()
+    set(ESPTOOLPY_COMPRESSED_OPT -u)
+endif()
 
 set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
     --flash_mode ${ESPFLASHMODE}
@@ -16,6 +36,18 @@ set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS
     --flash_size ${ESPFLASHSIZE}
     )
 
+# 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()
+
 if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT)
     # Set ESPFLASHSIZE to 'detect' *after* elf2image options are generated,
     # as elf2image can't have 'detect' as an option...
@@ -28,15 +60,50 @@ if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION)
     set(PHY_PARTITION_BIN_FILE "esp32/phy_init_data.bin")
 endif()
 
+if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES AND NOT BOOTLOADER_BUILD)
+    set(unsigned_project_binary "${PROJECT_NAME}-unsigned.bin")
+else()
+    set(unsigned_project_binary "${PROJECT_NAME}.bin")
+endif()
+
 #
 # Add 'app.bin' target - generates with elf2image
 #
-add_custom_command(OUTPUT "${PROJECT_NAME}.bin"
-    COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} -o "${PROJECT_NAME}.bin" "${PROJECT_NAME}.elf"
+add_custom_command(OUTPUT "${unsigned_project_binary}"
+    COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS}
+        -o "${unsigned_project_binary}" "${PROJECT_NAME}.elf"
     DEPENDS ${PROJECT_NAME}.elf
     VERBATIM
     )
-add_custom_target(app ALL DEPENDS "${PROJECT_NAME}.bin")
+
+if(NOT BOOTLOADER_BUILD AND
+    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_target(gen_unsigned_project_binary ALL DEPENDS "${unsigned_project_binary}")
+    add_custom_command(OUTPUT "${PROJECT_NAME}.bin"
+        COMMAND ${ESPSECUREPY} sign_data --keyfile ${secure_boot_signing_key}
+            -o "${PROJECT_NAME}.bin" "${unsigned_project_binary}"
+        DEPENDS gen_unsigned_project_binary
+        VERBATIM
+        )
+endif()
+
+if(NOT BOOTLOADER_BUILD)
+    add_custom_target(app ALL DEPENDS "${PROJECT_NAME}.bin")
+else()
+    add_custom_target(bootloader ALL DEPENDS "${PROJECT_NAME}.bin")
+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
+        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 ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.bin"
+        VERBATIM)
+endif()
 
 #
 # Add 'flash' target - not all build systems can run this directly
index 443a5ad6e339aaa0c400583c8423155f5c19a2f7..fc2ecf7ad2a7348527a5bd7a131ccda0f21ef262 100644 (file)
@@ -22,40 +22,48 @@ if(CONFIG_ESPTOOLPY_FLASHSIZE)
     set(flashsize_opt --flash-size ${CONFIG_ESPTOOLPY_FLASHSIZE})
 endif()
 
+if(CONFIG_SECURE_BOOT_ENABLED AND NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION)
+    set(partition_secure_opt --secure)
+else()
+    set(partition_secure_opt "")
+endif()
+
 add_custom_command(OUTPUT "${unsigned_partition_bin}"
-    COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py" -q --offset ${PARTITION_TABLE_OFFSET} ${md5_opt} ${flashsize_opt}
-    ${partition_csv} ${unsigned_partition_bin}
+    COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py"
+        -q --offset ${PARTITION_TABLE_OFFSET} ${md5_opt} ${flashsize_opt}
+        ${partition_secure_opt} ${partition_csv} ${unsigned_partition_bin}
     DEPENDS ${partition_csv} "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py"
     VERBATIM)
 
 # Add signing steps
 if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
-    get_filename_component(secure_boot_signing_key
-        "${CONFIG_SECURE_BOOT_SIGNING_KEY}"
-        ABSOLUTE BASE_DIR "${PROJECT_PATH}")
-
+    add_custom_target(gen_unsigned_partition_bin ALL DEPENDS "${unsigned_partition_bin}")
     add_custom_command(OUTPUT "${final_partition_bin}"
-        COMMAND "${PYTHON}" "${ESPSECUREPY}" sign_data --keyfile "${secure_boot_signing_key}"
-        -o "${final_partition_bin}" "${unsigned_partition_bin}"
-        DEPENDS "${unsigned_partition_bin}"
+        COMMAND ${ESPSECUREPY} sign_data --keyfile "${secure_boot_signing_key}"
+            -o "${final_partition_bin}" "${unsigned_partition_bin}"
+        DEPENDS gen_unsigned_partition_bin gen_secure_boot_signing_key
         VERBATIM)
-
 endif()
 
 if(EXISTS ${partition_csv})
     add_custom_target(partition_table ALL DEPENDS "${final_partition_bin}")
 else()
-    # This is a bit of a hack: If the partition input CSV is not found, create a phony partition_table target that
-    # fails the build. Have it also touch CMakeCache.txt to cause a cmake run next time
+    # If the partition input CSV is not found, create a phony partition_table 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 CSV if one exists, etc.)
-    #
-    # This is because partition CSV is required at CMake runtime (to generate metadata files with flashing data, etc) but we can't
-    # fail the build if it is not found, because the "menuconfig" target may be required to fix the problem. CMAKE_CONFIGURE_DEPENDS
-    # only works for files which exist at CMake runtime.
-    add_custom_target(partition_table ALL
-        COMMAND ${CMAKE_COMMAND} -E echo "Partition table CSV ${partition_csv} does not exist. Either change partition table in menuconfig or create this input file."
-        COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/CMakeCache.txt"
-        COMMAND ${CMAKE_COMMAND} -P ${IDF_PATH}/tools/cmake/scripts/fail.cmake)
+    fail_at_build_time(partition_table
+        "Partition table CSV ${partition_csv} does not exist."
+        "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_dependencies(bootloader partition_table)
index 01442647229ac30a5e350af7090b65bc1fa38044..0d168c7bd679fc37ea41874b3f33e624ebc3b415 100644 (file)
@@ -56,3 +56,5 @@ get_partition_info(OTADATA_PARTITION_OFFSET "--type data --subtype ota --offset"
 get_partition_info(OTADATA_PARTITION_SIZE "--type data --subtype ota --size")
 
 endif()
+
+set(BOOTLOADER_OFFSET 0x1000)
index bfe10c090f42173e94509fd38baab6c1418af3e0..8abeef89a9a0879b059da2766a6a7a6edc33c64a 100644 (file)
@@ -114,8 +114,9 @@ function(target_add_binary_data target embed_file embed_type)
         -D "FILE_TYPE=${embed_type}"
         -P "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake"
         MAIN_DEPENDENCY "${embed_file}"
-        DEPENDENCIES "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake"
-        WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
+        DEPENDS "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake"
+        WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
+        VERBATIM)
 
     set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${embed_srcfile}")
 
@@ -188,4 +189,25 @@ function(add_prefix var prefix)
         list(APPEND newlist "${prefix}${elm}")
     endforeach()
     set(${var} "${newlist}" PARENT_SCOPE)
-endfunction()
\ No newline at end of file
+endfunction()
+
+# fail_at_build_time
+#
+# Creates a phony target which fails the build and touches CMakeCache.txt to cause a cmake run next time.
+#
+# This is used when a missing file is required at CMake runtime, but we can't fail the build if it is not found,
+# because the "menuconfig" target may be required to fix the problem.
+#
+# We cannot use CMAKE_CONFIGURE_DEPENDS instead because it only works for files which exist at CMake runtime.
+#
+function(fail_at_build_time target_name message_line0)
+    set(message_lines COMMAND ${CMAKE_COMMAND} -E echo "${message_line0}")
+    foreach(message_line ${ARGN})
+        set(message_lines ${message_lines} COMMAND ${CMAKE_COMMAND} -E echo "${message_line}")
+    endforeach()
+    add_custom_target(${target_name} ALL
+        ${message_lines}
+        COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/CMakeCache.txt"
+        COMMAND ${CMAKE_COMMAND} -P ${IDF_PATH}/tools/cmake/scripts/fail.cmake
+        VERBATIM)
+endfunction()
index 716bbf50bb73a0395263e66e5d0cd8be58acdf57..830ff9713379e0cf41e04990e014203d5bec4dcc 100755 (executable)
@@ -244,6 +244,12 @@ def _get_esptool_args(args):
     result = [ PYTHON, esptool_path ]
     result += [ "-p", args.port ]
     result += [ "-b", str(args.baud) ]
+
+    with open(os.path.join(args.build_dir, "flasher_args.json")) as f:
+        flasher_args = json.load(f)
+
+    extra_esptool_args = flasher_args["extra_esptool_args"]
+    result += [ "--after", extra_esptool_args["after"] ]
     return result
 
 def flash(action, args):
@@ -360,10 +366,11 @@ def print_closing_message(args):
             for o,f in flash_items:
                 cmd += o + " " + flasher_path(f) + " "
 
-        print("%s -p %s -b %s write_flash %s" % (
+        print("%s -p %s -b %s --after %s write_flash %s" % (
             os.path.relpath("%s/components/esptool_py/esptool/esptool.py" % os.environ["IDF_PATH"]),
             args.port or "(PORT)",
             args.baud,
+            flasher_args["extra_esptool_args"]["after"],
             cmd.strip()))
         print("or run 'idf.py -p %s %s'" % (args.port or "(PORT)", key + "-flash" if key != "project" else "flash",))