CMakeLists.txt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. cmake_minimum_required(VERSION 3.16)
  2. if(NOT SDKCONFIG)
  3. message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed "
  4. "in by the parent build process.")
  5. endif()
  6. if(NOT IDF_PATH)
  7. message(FATAL_ERROR "Bootloader subproject expects the IDF_PATH variable to be passed "
  8. "in by the parent build process.")
  9. endif()
  10. if(NOT IDF_TARGET)
  11. message(FATAL_ERROR "Bootloader subproject expects the IDF_TARGET variable to be passed "
  12. "in by the parent build process.")
  13. endif()
  14. # A number of these components are implemented as config-only when built in the bootloader
  15. set(COMPONENTS
  16. bootloader
  17. esptool_py
  18. esp_hw_support
  19. esp_system
  20. freertos
  21. hal
  22. partition_table
  23. soc
  24. bootloader_support
  25. log
  26. spi_flash
  27. micro-ecc
  28. main
  29. efuse
  30. esp_system
  31. newlib)
  32. # Make EXTRA_COMPONENT_DIRS variable to point to the bootloader_components directory
  33. # of the project being compiled
  34. set(PROJECT_EXTRA_COMPONENTS "${PROJECT_SOURCE_DIR}/bootloader_components")
  35. if(EXISTS ${PROJECT_EXTRA_COMPONENTS})
  36. list(APPEND EXTRA_COMPONENT_DIRS "${PROJECT_EXTRA_COMPONENTS}")
  37. endif()
  38. if(IGNORE_EXTRA_COMPONENT)
  39. # Prefix all entries of the list with ${PROJECT_EXTRA_COMPONENTS} absolute path
  40. list(TRANSFORM IGNORE_EXTRA_COMPONENT
  41. PREPEND "${PROJECT_EXTRA_COMPONENTS}/"
  42. OUTPUT_VARIABLE EXTRA_COMPONENT_EXCLUDE_DIRS)
  43. endif()
  44. # Consider each directory in the project's bootloader_components as a component to be compiled
  45. file(GLOB proj_components RELATIVE ${PROJECT_EXTRA_COMPONENTS} ${PROJECT_EXTRA_COMPONENTS}/*)
  46. foreach(component ${proj_components})
  47. # Only directories are considered components
  48. if(IS_DIRECTORY "${PROJECT_EXTRA_COMPONENTS}/${component}" AND NOT ${component} IN_LIST IGNORE_EXTRA_COMPONENT)
  49. list(APPEND COMPONENTS ${component})
  50. endif()
  51. endforeach()
  52. set(BOOTLOADER_BUILD 1)
  53. include("${IDF_PATH}/tools/cmake/project.cmake")
  54. set(common_req log esp_rom esp_common esp_hw_support newlib)
  55. idf_build_set_property(EXTRA_COMPONENT_EXCLUDE_DIRS "${EXTRA_COMPONENT_EXCLUDE_DIRS}")
  56. idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}")
  57. idf_build_set_property(__OUTPUT_SDKCONFIG 0)
  58. project(bootloader)
  59. idf_build_set_property(COMPILE_DEFINITIONS "BOOTLOADER_BUILD=1" APPEND)
  60. idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
  61. idf_component_get_property(main_args esptool_py FLASH_ARGS)
  62. idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
  63. # String for printing flash command
  64. string(REPLACE ";" " " esptoolpy_write_flash
  65. "${ESPTOOLPY} --port=(PORT) --baud=(BAUD) ${main_args} "
  66. "write_flash ${sub_args}")
  67. string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
  68. string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
  69. # Suppress warning: "Manually-specified variables were not used by the project: SECURE_BOOT_SIGNING_KEY"
  70. set(ignore_signing_key "${SECURE_BOOT_SIGNING_KEY}")
  71. if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
  72. if(CONFIG_SECURE_BOOTLOADER_KEY_ENCODING_192BIT)
  73. set(key_digest_len 192)
  74. else()
  75. set(key_digest_len 256)
  76. endif()
  77. get_filename_component(bootloader_digest_bin
  78. "bootloader-reflash-digest.bin"
  79. ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
  80. get_filename_component(secure_bootloader_key
  81. "secure-bootloader-key-${key_digest_len}.bin"
  82. ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
  83. add_custom_command(OUTPUT "${secure_bootloader_key}"
  84. COMMAND ${ESPSECUREPY} digest_private_key
  85. --keylen "${key_digest_len}"
  86. --keyfile "${SECURE_BOOT_SIGNING_KEY}"
  87. "${secure_bootloader_key}"
  88. VERBATIM)
  89. if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
  90. add_custom_target(gen_secure_bootloader_key ALL DEPENDS "${secure_bootloader_key}")
  91. else()
  92. if(NOT EXISTS "${secure_bootloader_key}")
  93. message(FATAL_ERROR
  94. "No pre-generated key for a reflashable secure bootloader is available, "
  95. "due to signing configuration."
  96. "\nTo generate one, you can use this command:"
  97. "\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}"
  98. "\nIf a signing key is present, then instead use:"
  99. "\n\t${espsecurepy} digest_private_key "
  100. "--keylen (192/256) --keyfile KEYFILE "
  101. "${secure_bootloader_key}")
  102. endif()
  103. add_custom_target(gen_secure_bootloader_key)
  104. endif()
  105. add_custom_command(OUTPUT "${bootloader_digest_bin}"
  106. COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
  107. COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
  108. -o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
  109. MAIN_DEPENDENCY "${CMAKE_BINARY_DIR}/.bin_timestamp"
  110. DEPENDS gen_secure_bootloader_key gen_project_binary
  111. VERBATIM)
  112. add_custom_target(gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
  113. endif()
  114. if(CONFIG_SECURE_BOOT_V2_ENABLED)
  115. if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
  116. get_filename_component(secure_boot_signing_key
  117. "${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}")
  118. if(NOT EXISTS "${secure_boot_signing_key}")
  119. message(FATAL_ERROR
  120. "Secure Boot Signing Key Not found."
  121. "\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
  122. "\nTo generate one, you can use this command:"
  123. "\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}")
  124. endif()
  125. set(bootloader_unsigned_bin "bootloader-unsigned.bin")
  126. add_custom_command(OUTPUT ".signed_bin_timestamp"
  127. COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
  128. "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
  129. COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}"
  130. -o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
  131. COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
  132. "from ${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
  133. COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
  134. > "${CMAKE_BINARY_DIR}/.signed_bin_timestamp"
  135. DEPENDS "${build_dir}/.bin_timestamp"
  136. VERBATIM
  137. COMMENT "Generated the signed Bootloader")
  138. else()
  139. add_custom_command(OUTPUT ".signed_bin_timestamp"
  140. VERBATIM
  141. COMMENT "Bootloader generated but not signed")
  142. endif()
  143. add_custom_target(gen_signed_bootloader ALL DEPENDS "${build_dir}/.signed_bin_timestamp")
  144. endif()
  145. if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
  146. add_custom_command(TARGET bootloader.elf POST_BUILD
  147. COMMAND ${CMAKE_COMMAND} -E echo
  148. "=============================================================================="
  149. COMMAND ${CMAKE_COMMAND} -E echo
  150. "Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
  151. COMMAND ${CMAKE_COMMAND} -E echo
  152. "One-time flash command is:"
  153. COMMAND ${CMAKE_COMMAND} -E echo
  154. "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
  155. COMMAND ${CMAKE_COMMAND} -E echo
  156. "* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
  157. VERBATIM)
  158. elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
  159. add_custom_command(TARGET bootloader.elf POST_BUILD
  160. COMMAND ${CMAKE_COMMAND} -E echo
  161. "=============================================================================="
  162. COMMAND ${CMAKE_COMMAND} -E echo
  163. "Bootloader built and secure digest generated."
  164. COMMAND ${CMAKE_COMMAND} -E echo
  165. "Secure boot enabled, so bootloader not flashed automatically."
  166. COMMAND ${CMAKE_COMMAND} -E echo
  167. "Burn secure boot key to efuse using:"
  168. COMMAND ${CMAKE_COMMAND} -E echo
  169. "\t${espefusepy} burn_key secure_boot_v1 ${secure_bootloader_key}"
  170. COMMAND ${CMAKE_COMMAND} -E echo
  171. "First time flash command is:"
  172. COMMAND ${CMAKE_COMMAND} -E echo
  173. "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
  174. COMMAND ${CMAKE_COMMAND} -E echo
  175. "=============================================================================="
  176. COMMAND ${CMAKE_COMMAND} -E echo
  177. "To reflash the bootloader after initial flash:"
  178. COMMAND ${CMAKE_COMMAND} -E echo
  179. "\t${esptoolpy_write_flash} 0x0 ${bootloader_digest_bin}"
  180. COMMAND ${CMAKE_COMMAND} -E echo
  181. "=============================================================================="
  182. COMMAND ${CMAKE_COMMAND} -E echo
  183. "* After first boot, only re-flashes of this kind (with same key) will be accepted."
  184. COMMAND ${CMAKE_COMMAND} -E echo
  185. "* Not recommended to re-use the same secure boot keyfile on multiple production devices."
  186. DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
  187. VERBATIM)
  188. elseif(
  189. CONFIG_SECURE_BOOT_V2_ENABLED AND
  190. (CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS GREATER 1) AND
  191. NOT CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT
  192. )
  193. add_custom_command(TARGET bootloader.elf POST_BUILD
  194. COMMAND ${CMAKE_COMMAND} -E echo
  195. "=============================================================================="
  196. COMMAND ${CMAKE_COMMAND} -E echo
  197. "Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
  198. COMMAND ${CMAKE_COMMAND} -E echo
  199. "To sign the bootloader with additional private keys."
  200. COMMAND ${CMAKE_COMMAND} -E echo
  201. "\t${espsecurepy} sign_data -k secure_boot_signing_key2.pem -v 2 \
  202. --append_signatures -o signed_bootloader.bin build/bootloader/bootloader.bin"
  203. COMMAND ${CMAKE_COMMAND} -E echo
  204. "Secure boot enabled, so bootloader not flashed automatically."
  205. COMMAND ${CMAKE_COMMAND} -E echo
  206. "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
  207. COMMAND ${CMAKE_COMMAND} -E echo
  208. "=============================================================================="
  209. DEPENDS gen_signed_bootloader
  210. VERBATIM)
  211. elseif(CONFIG_SECURE_BOOT_V2_ENABLED AND NOT CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT)
  212. add_custom_command(TARGET bootloader.elf POST_BUILD
  213. COMMAND ${CMAKE_COMMAND} -E echo
  214. "=============================================================================="
  215. COMMAND ${CMAKE_COMMAND} -E echo
  216. "Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
  217. COMMAND ${CMAKE_COMMAND} -E echo
  218. "Secure boot enabled, so bootloader not flashed automatically."
  219. COMMAND ${CMAKE_COMMAND} -E echo
  220. "\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
  221. COMMAND ${CMAKE_COMMAND} -E echo
  222. "=============================================================================="
  223. DEPENDS gen_signed_bootloader
  224. VERBATIM)
  225. endif()