From 3f2d6a08910dbd03932820e8edf2ef0ca82ebef7 Mon Sep 17 00:00:00 2001 From: suda-morris <362953310@qq.com> Date: Tue, 16 Apr 2019 17:01:31 +0800 Subject: [PATCH] make bootloader_support depend on IDF_TARGET 1. move chip-specific code(e.g. encryption) into IDF_TARGET directory 2. splict app-only code to idf directory which won't be compiled into bootloader --- components/bootloader_support/CMakeLists.txt | 14 +-- components/bootloader_support/component.mk | 6 ++ .../include_bootloader/bootloader_sha.h | 23 ----- .../include_bootloader/bootloader_utility.h | 24 ++++++ .../src/bootloader_utility.c | 18 ++++ .../src/{ => esp32}/bootloader_sha.c | 74 ++-------------- .../src/{ => esp32}/flash_encrypt.c | 0 .../src/{ => esp32}/secure_boot.c | 4 - .../src/esp32/secure_boot_signatures.c | 86 +++++++++++++++++++ .../bootloader_support/src/esp_image_format.c | 2 +- .../src/idf/bootloader_sha.c | 53 ++++++++++++ .../src/{ => idf}/secure_boot_signatures.c | 37 ++------ 12 files changed, 208 insertions(+), 133 deletions(-) rename components/bootloader_support/src/{ => esp32}/bootloader_sha.c (66%) rename components/bootloader_support/src/{ => esp32}/flash_encrypt.c (100%) rename components/bootloader_support/src/{ => esp32}/secure_boot.c (99%) create mode 100644 components/bootloader_support/src/esp32/secure_boot_signatures.c create mode 100644 components/bootloader_support/src/idf/bootloader_sha.c rename components/bootloader_support/src/{ => idf}/secure_boot_signatures.c (79%) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index 244dad5de..2cf543cbb 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -2,20 +2,20 @@ set(COMPONENT_SRCS "src/bootloader_clock.c" "src/bootloader_common.c" "src/bootloader_flash.c" "src/bootloader_random.c" - "src/bootloader_sha.c" "src/bootloader_utility.c" "src/esp_image_format.c" - "src/flash_encrypt.c" "src/flash_partitions.c" - "src/flash_qio_mode.c" - "src/secure_boot.c" - "src/secure_boot_signatures.c") + "src/flash_qio_mode.c") if(${BOOTLOADER_BUILD}) set(COMPONENT_ADD_INCLUDEDIRS "include include_bootloader") set(COMPONENT_REQUIRES) set(COMPONENT_PRIV_REQUIRES spi_flash micro-ecc efuse) - list(APPEND COMPONENT_SRCS "src/bootloader_init.c") + list(APPEND COMPONENT_SRCS "src/bootloader_init.c" + "src/${IDF_TARGET}/bootloader_sha.c" + "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 @@ -51,6 +51,8 @@ if(${BOOTLOADER_BUILD}) "${secure_boot_verification_key}") endif() else() + list(APPEND COMPONENT_SRCS "src/idf/bootloader_sha.c" + "src/idf/secure_boot_signatures.c") set(COMPONENT_ADD_INCLUDEDIRS "include") set(COMPONENT_PRIV_INCLUDEDIRS "include_bootloader") set(COMPONENT_REQUIRES) diff --git a/components/bootloader_support/component.mk b/components/bootloader_support/component.mk index ecf26bd89..202e35769 100644 --- a/components/bootloader_support/component.mk +++ b/components/bootloader_support/component.mk @@ -9,6 +9,12 @@ endif COMPONENT_SRCDIRS := src +ifndef IS_BOOTLOADER_BUILD +COMPONENT_SRCDIRS += src/idf # idf sub-directory contains platform agnostic IDF versions +else +COMPONENT_SRCDIRS += src/$(IDF_TARGET) # one sub-dir per chip +endif + ifndef IS_BOOTLOADER_BUILD COMPONENT_OBJEXCLUDE := src/bootloader_init.o endif diff --git a/components/bootloader_support/include_bootloader/bootloader_sha.h b/components/bootloader_support/include_bootloader/bootloader_sha.h index 89c2efad1..3bfefb9f5 100644 --- a/components/bootloader_support/include_bootloader/bootloader_sha.h +++ b/components/bootloader_support/include_bootloader/bootloader_sha.h @@ -31,26 +31,3 @@ bootloader_sha256_handle_t bootloader_sha256_start(); void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len); void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest); - -/** - * @brief Converts an array to a printable string. - * - * This function is useful for printing SHA-256 digest. - * \code{c} - * // Example of using. image_hash will be printed - * #define HASH_LEN 32 // SHA-256 digest length - * ... - * char hash_print[HASH_LEN * 2 + 1]; - * hash_print[HASH_LEN * 2] = 0; - * bootloader_sha256_hex_to_str(hash_print, image_hash, HASH_LEN); - * ESP_LOGI(TAG, %s", hash_print); - * \endcode - - * @param[out] out_str Output string - * @param[in] in_array_hex Pointer to input array - * @param[in] len Length of input array - * - * @return ESP_OK: Successful - * ESP_ERR_INVALID_ARG: Error in the passed arguments - */ -esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len); diff --git a/components/bootloader_support/include_bootloader/bootloader_utility.h b/components/bootloader_support/include_bootloader/bootloader_utility.h index 31213a016..84d0cb48f 100644 --- a/components/bootloader_support/include_bootloader/bootloader_utility.h +++ b/components/bootloader_support/include_bootloader/bootloader_utility.h @@ -13,6 +13,7 @@ // limitations under the License. #pragma once +#include "bootloader_config.h" #include "esp_image_format.h" /** @@ -62,3 +63,26 @@ __attribute__((noreturn)) void bootloader_utility_load_boot_image(const bootload * It is not recommended to call this function from an app (if called, the app will abort). */ __attribute__((noreturn)) void bootloader_reset(void); + +/** + * @brief Converts an array to a printable string. + * + * This function is useful for printing SHA-256 digest. + * \code{c} + * // Example of using. image_hash will be printed + * #define HASH_LEN 32 // SHA-256 digest length + * ... + * char hash_print[HASH_LEN * 2 + 1]; + * hash_print[HASH_LEN * 2] = 0; + * bootloader_sha256_hex_to_str(hash_print, image_hash, HASH_LEN); + * ESP_LOGI(TAG, %s", hash_print); + * \endcode + + * @param[out] out_str Output string + * @param[in] in_array_hex Pointer to input array + * @param[in] len Length of input array + * + * @return ESP_OK: Successful + * ESP_ERR_INVALID_ARG: Error in the passed arguments + */ +esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len); diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 863eaa098..8a5a501bf 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -702,3 +702,21 @@ void bootloader_reset(void) abort(); /* This function should really not be called from application code */ #endif } + +esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len) +{ + if (out_str == NULL || in_array_hex == NULL || len == 0) { + return ESP_ERR_INVALID_ARG; + } + for (int i = 0; i < len; i++) { + for (int shift = 0; shift < 2; shift++) { + uint8_t nibble = (in_array_hex[i] >> (shift ? 0 : 4)) & 0x0F; + if (nibble < 10) { + out_str[i * 2 + shift] = '0' + nibble; + } else { + out_str[i * 2 + shift] = 'a' + nibble - 10; + } + } + } + return ESP_OK; +} diff --git a/components/bootloader_support/src/bootloader_sha.c b/components/bootloader_support/src/esp32/bootloader_sha.c similarity index 66% rename from components/bootloader_support/src/bootloader_sha.c rename to components/bootloader_support/src/esp32/bootloader_sha.c index 0ae1fd4a8..646a8d35a 100644 --- a/components/bootloader_support/src/bootloader_sha.c +++ b/components/bootloader_support/src/esp32/bootloader_sha.c @@ -16,59 +16,17 @@ #include #include #include - -#ifndef BOOTLOADER_BUILD -// App version is a wrapper around mbedTLS SHA API -#include - -bootloader_sha256_handle_t bootloader_sha256_start() -{ - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)malloc(sizeof(mbedtls_sha256_context)); - if (!ctx) { - return NULL; - } - mbedtls_sha256_init(ctx); - int ret = mbedtls_sha256_starts_ret(ctx, false); - if (ret != 0) { - return NULL; - } - return ctx; -} - -void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len) -{ - assert(handle != NULL); - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - int ret = mbedtls_sha256_update_ret(ctx, data, data_len); - assert(ret == 0); -} - -void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) -{ - assert(handle != NULL); - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - if (digest != NULL) { - int ret = mbedtls_sha256_finish_ret(ctx, digest); - assert(ret == 0); - } - mbedtls_sha256_free(ctx); - free(handle); -} - -#else // Bootloader version - #include "esp32/rom/sha.h" #include "soc/dport_reg.h" #include "soc/hwcrypto_reg.h" - #include "esp32/rom/ets_sys.h" // TO REMOVE static uint32_t words_hashed; // Words per SHA256 block -static const size_t BLOCK_WORDS = (64/sizeof(uint32_t)); +static const size_t BLOCK_WORDS = (64 / sizeof(uint32_t)); // Words in final SHA256 digest -static const size_t DIGEST_WORDS = (32/sizeof(uint32_t)); +static const size_t DIGEST_WORDS = (32 / sizeof(uint32_t)); bootloader_sha256_handle_t bootloader_sha256_start() { @@ -95,7 +53,7 @@ void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, copy_words = MIN(word_len, copy_words); // Wait for SHA engine idle - while(REG_READ(SHA_256_BUSY_REG) != 0) { } + while (REG_READ(SHA_256_BUSY_REG) != 0) { } // Copy to memory block //ets_printf("block_count %d copy_words %d\n", block_count, copy_words); @@ -148,7 +106,7 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest bootloader_sha256_data(handle, padding, pad_bytes); - assert(words_hashed % BLOCK_WORDS == 60/4); // 32-bits left in block + assert(words_hashed % BLOCK_WORDS == 60 / 4); // 32-bits left in block // Calculate 32-bit length for final 32 bits of data uint32_t bit_count = __builtin_bswap32( data_words * 32 ); @@ -156,9 +114,9 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest assert(words_hashed % BLOCK_WORDS == 0); - while(REG_READ(SHA_256_BUSY_REG) == 1) { } + while (REG_READ(SHA_256_BUSY_REG) == 1) { } REG_WRITE(SHA_256_LOAD_REG, 1); - while(REG_READ(SHA_256_BUSY_REG) == 1) { } + while (REG_READ(SHA_256_BUSY_REG) == 1) { } uint32_t *digest_words = (uint32_t *)digest; uint32_t *sha_text_reg = (uint32_t *)(SHA_TEXT_BASE); @@ -167,23 +125,3 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest } asm volatile ("memw"); } - -#endif - -esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len) -{ - if (out_str == NULL || in_array_hex == NULL || len == 0) { - return ESP_ERR_INVALID_ARG; - } - for (int i = 0; i < len; i++) { - for (int shift = 0; shift < 2; shift++) { - uint8_t nibble = (in_array_hex[i] >> (shift ? 0 : 4)) & 0x0F; - if (nibble < 10) { - out_str[i*2+shift] = '0' + nibble; - } else { - out_str[i*2+shift] = 'a' + nibble - 10; - } - } - } - return ESP_OK; -} diff --git a/components/bootloader_support/src/flash_encrypt.c b/components/bootloader_support/src/esp32/flash_encrypt.c similarity index 100% rename from components/bootloader_support/src/flash_encrypt.c rename to components/bootloader_support/src/esp32/flash_encrypt.c diff --git a/components/bootloader_support/src/secure_boot.c b/components/bootloader_support/src/esp32/secure_boot.c similarity index 99% rename from components/bootloader_support/src/secure_boot.c rename to components/bootloader_support/src/esp32/secure_boot.c index b60a67427..5de905e3b 100644 --- a/components/bootloader_support/src/secure_boot.c +++ b/components/bootloader_support/src/esp32/secure_boot.c @@ -40,8 +40,6 @@ * from the bootloader code. */ -#ifdef BOOTLOADER_BUILD - static const char* TAG = "secure_boot"; /** @@ -233,5 +231,3 @@ esp_err_t esp_secure_boot_permanently_enable(void) return ESP_ERR_INVALID_STATE; } } - -#endif // #ifdef BOOTLOADER_BUILD diff --git a/components/bootloader_support/src/esp32/secure_boot_signatures.c b/components/bootloader_support/src/esp32/secure_boot_signatures.c new file mode 100644 index 000000000..3642b309d --- /dev/null +++ b/components/bootloader_support/src/esp32/secure_boot_signatures.c @@ -0,0 +1,86 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "sdkconfig.h" + +#include "bootloader_flash.h" +#include "bootloader_sha.h" +#include "esp_log.h" +#include "esp_image_format.h" +#include "esp_secure_boot.h" +#include "esp32/rom/sha.h" +#include "uECC.h" + +typedef SHA_CTX sha_context; + +static const char *TAG = "secure_boot"; + +extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start"); +extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end"); + +#define SIGNATURE_VERIFICATION_KEYLEN 64 + +#define DIGEST_LEN 32 + +esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) +{ + uint8_t digest[DIGEST_LEN]; + const uint8_t *data; + const esp_secure_boot_sig_block_t *sigblock; + + ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); + + data = bootloader_mmap(src_addr, length + sizeof(esp_secure_boot_sig_block_t)); + if (data == NULL) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length + sizeof(esp_secure_boot_sig_block_t)); + return ESP_FAIL; + } + + // Calculate digest of main image + bootloader_sha256_handle_t handle = bootloader_sha256_start(); + bootloader_sha256_data(handle, data, length); + bootloader_sha256_finish(handle, digest); + + // Map the signature block and verify the signature + sigblock = (const esp_secure_boot_sig_block_t *)(data + length); + esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest); + bootloader_munmap(data); + return err; +} + +esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest) +{ + ptrdiff_t keylen; + + keylen = signature_verification_key_end - signature_verification_key_start; + if (keylen != SIGNATURE_VERIFICATION_KEYLEN) { + ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen); + return ESP_FAIL; + } + + if (sig_block->version != 0) { + ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version); + return ESP_FAIL; + } + + ESP_LOGD(TAG, "Verifying secure boot signature"); + + bool is_valid; + is_valid = uECC_verify(signature_verification_key_start, + image_digest, + DIGEST_LEN, + sig_block->signature, + uECC_secp256r1()); + ESP_LOGD(TAG, "Verification result %d", is_valid); + return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID; +} diff --git a/components/bootloader_support/src/esp_image_format.c b/components/bootloader_support/src/esp_image_format.c index b6245a22e..77af08c3c 100644 --- a/components/bootloader_support/src/esp_image_format.c +++ b/components/bootloader_support/src/esp_image_format.c @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include #include diff --git a/components/bootloader_support/src/idf/bootloader_sha.c b/components/bootloader_support/src/idf/bootloader_sha.c new file mode 100644 index 000000000..7dc4f7429 --- /dev/null +++ b/components/bootloader_support/src/idf/bootloader_sha.c @@ -0,0 +1,53 @@ +// Copyright 2017 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "bootloader_sha.h" +#include +#include +#include +#include +#include + +bootloader_sha256_handle_t bootloader_sha256_start() +{ + mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)malloc(sizeof(mbedtls_sha256_context)); + if (!ctx) { + return NULL; + } + mbedtls_sha256_init(ctx); + int ret = mbedtls_sha256_starts_ret(ctx, false); + if (ret != 0) { + return NULL; + } + return ctx; +} + +void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len) +{ + assert(handle != NULL); + mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; + int ret = mbedtls_sha256_update_ret(ctx, data, data_len); + assert(ret == 0); +} + +void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) +{ + assert(handle != NULL); + mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; + if (digest != NULL) { + int ret = mbedtls_sha256_finish_ret(ctx, digest); + assert(ret == 0); + } + mbedtls_sha256_free(ctx); + free(handle); +} diff --git a/components/bootloader_support/src/secure_boot_signatures.c b/components/bootloader_support/src/idf/secure_boot_signatures.c similarity index 79% rename from components/bootloader_support/src/secure_boot_signatures.c rename to components/bootloader_support/src/idf/secure_boot_signatures.c index e28e8a272..14e8faea5 100644 --- a/components/bootloader_support/src/secure_boot_signatures.c +++ b/components/bootloader_support/src/idf/secure_boot_signatures.c @@ -18,17 +18,10 @@ #include "esp_log.h" #include "esp_image_format.h" #include "esp_secure_boot.h" - -#ifdef BOOTLOADER_BUILD -#include "esp32/rom/sha.h" -#include "uECC.h" -typedef SHA_CTX sha_context; -#else #include "mbedtls/sha256.h" #include "mbedtls/x509.h" -#endif -static const char* TAG = "secure_boot"; +static const char *TAG = "secure_boot"; extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start"); extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end"); @@ -46,20 +39,13 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); data = bootloader_mmap(src_addr, length + sizeof(esp_secure_boot_sig_block_t)); - if(data == NULL) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(esp_secure_boot_sig_block_t)); + if (data == NULL) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length + sizeof(esp_secure_boot_sig_block_t)); return ESP_FAIL; } // Calculate digest of main image -#ifdef BOOTLOADER_BUILD - bootloader_sha256_handle_t handle = bootloader_sha256_start(); - bootloader_sha256_data(handle, data, length); - bootloader_sha256_finish(handle, digest); -#else - /* Use thread-safe mbedTLS version */ mbedtls_sha256_ret(data, length, digest, 0); -#endif // Map the signature block and verify the signature sigblock = (const esp_secure_boot_sig_block_t *)(data + length); @@ -73,7 +59,7 @@ esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block ptrdiff_t keylen; keylen = signature_verification_key_end - signature_verification_key_start; - if(keylen != SIGNATURE_VERIFICATION_KEYLEN) { + if (keylen != SIGNATURE_VERIFICATION_KEYLEN) { ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen); return ESP_FAIL; } @@ -85,16 +71,6 @@ esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block ESP_LOGD(TAG, "Verifying secure boot signature"); -#ifdef BOOTLOADER_BUILD - bool is_valid; - is_valid = uECC_verify(signature_verification_key_start, - image_digest, - DIGEST_LEN, - sig_block->signature, - uECC_secp256r1()); - ESP_LOGD(TAG, "Verification result %d", is_valid); - return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID; -#else /* BOOTLOADER_BUILD */ int ret; mbedtls_mpi r, s; @@ -102,7 +78,7 @@ esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block mbedtls_mpi_init(&s); /* Extract r and s components from RAW ECDSA signature of 64 bytes */ - #define ECDSA_INTEGER_LEN 32 +#define ECDSA_INTEGER_LEN 32 ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN); if (ret != 0) { ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret); @@ -122,7 +98,7 @@ esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block mbedtls_ecp_group_load(&ecdsa_context.grp, MBEDTLS_ECP_DP_SECP256R1); size_t plen = mbedtls_mpi_size(&ecdsa_context.grp.P); - if (keylen != 2*plen) { + if (keylen != 2 * plen) { ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen); ret = ESP_FAIL; goto cleanup; @@ -141,5 +117,4 @@ cleanup: mbedtls_mpi_free(&s); mbedtls_ecdsa_free(&ecdsa_context); return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID; -#endif /* !BOOTLOADER_BUILD */ }