Page 1 of 1

OTA firmware update in second stage bootloader with custom bootloader

Posted: Wed Jan 10, 2024 6:46 am
by suraj02
Hi there,
I would like to write custom bootloader code to perform an OTA firmware upgrade over wifi in the second bootloader step. My code to initialize wifi during the bootloader stage was unsuccessful due to several issues. The cause for my error was found
here: https://esp32.com/viewtopic.php?t=27605 .

So, at the second stage bootloader, how can I upgrade the firmware over the air using wifi?
Could someone help explain the proper procedure to me?

bootloader_start.c code:
  1. #include <stdbool.h>
  2. #include "sdkconfig.h"
  3. #include "esp_log.h"
  4. #include "bootloader_init.h"
  5. #include "bootloader_utility.h"
  6. #include "bootloader_common.h"
  7.  
  8. #include "esp_wifi.h"
  9. #include "esp_event.h"
  10. #include "esp_log.h"
  11. #include "nvs_flash.h"
  12. #include "esp_netif.h"
  13. #include "protocol_examples_common.h"
  14.  
  15. static const char* TAG = "boot";
  16.  
  17. static int select_partition_number(bootloader_state_t *bs);
  18.  
  19. void __attribute__((noreturn)) call_start_cpu0(void)
  20. {
  21.     // 1. Hardware initialization
  22.     if (bootloader_init() != ESP_OK) {
  23.         bootloader_reset();
  24.     }
  25.  
  26. #ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
  27.     bootloader_utility_load_boot_image_from_deep_sleep();
  28.  
  29. #endif
  30.  
  31.  
  32.  //Wi-Fi Initialization
  33.     nvs_flash_init();
  34.     esp_netif_init();
  35.     esp_event_loop_create_default();
  36.     example_connect();
  37.  
  38.     // 2. Select the number of boot partition
  39.     bootloader_state_t bs = {0};
  40.     select_partition_number(&bs);
  41.     int boot_index = FACTORY_INDEX;
  42.     // Print boot index
  43.     ESP_LOGI(TAG, "Boot Index: %d", boot_index);
  44.     if (boot_index == INVALID_INDEX) {
  45.         bootloader_reset();
  46.     }
  47.  
  48.     // 2.1 Print a custom message!
  49.     esp_rom_printf("[%s] %s\n", TAG, CONFIG_EXAMPLE_BOOTLOADER_WELCOME_MESSAGE);
  50.  
  51.     // 3. Load the app image for booting
  52.     bootloader_utility_load_boot_image(&bs, boot_index);
  53. }
  54.  
  55. // Select the number of boot partition
  56. static int select_partition_number(bootloader_state_t *bs)
  57. {
  58.     // 1. Load partition table
  59.     if (!bootloader_utility_load_partition_table(bs)) {
  60.         ESP_LOGE(TAG, "load partition table error!");
  61.         return INVALID_INDEX;
  62.     }
  63.  
  64.     // 2. Select the number of boot partition
  65.     return bootloader_utility_get_selected_boot_partition(bs);
  66. }
  67.  
  68. // Return global reent struct if any newlib functions are linked to bootloader
  69. struct _reent *__getreent(void)
  70. {
  71.     return _GLOBAL_REENT;
  72. }
CMakeLists.txt:
  1. idf_component_register(SRCS "bootloader_start.c"
  2.                     INCLUDE_DIRS "."
  3.                     REQUIRES bootloader bootloader_support nvs_flash esp_wifi freertos esp_system protocol_examples_common)
  4.  
  5. idf_build_get_property(target IDF_TARGET)
  6. # Use the linker script files from the actual bootloader
  7. set(scripts "${IDF_PATH}/components/bootloader/subproject/main/ld/${target}/bootloader.ld"
  8.             "${IDF_PATH}/components/bootloader/subproject/main/ld/${target}/bootloader.rom.ld")
  9.  
  10. target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")
error logs:
Executing action: all (aliases: build)
Running ninja in directory /home/suraj/trial/newf/bootloader_override/build
Executing "ninja all"...
[12/659] Performing build step for 'bootloader'
FAILED: bootloader-prefix/src/bootloader-stamp/bootloader-build bootloader/bootloader.elf bootloader/bootloader.bin bootloader/bootloader.map /home/suraj/trial/newf/bootloader_override/build/bootloader-prefix/src/bootloader-stamp/bootloader-build /home/suraj/trial/newf/bootloader_override/build/bootloader/bootloader.elf /home/suraj/trial/newf/bootloader_override/build/bootloader/bootloader.bin /home/suraj/trial/newf/bootloader_override/build/bootloader/bootloader.map
cd /home/suraj/trial/newf/bootloader_override/build/bootloader && /usr/bin/cmake --build .
[1/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/camellia.c.obj
[2/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chachapoly.c.obj
[3/483] Building C object esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_mbedtls.c.obj
FAILED: esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_mbedtls.c.obj
/home/suraj/.espressif/tools/xtensa-esp32s3-elf/esp-2021r2-patch5-8.4.0/xtensa-esp32s3-elf/bin/xtensa-esp32s3-elf-gcc -DCONFIG_ECC -DCONFIG_IEEE80211W -DCONFIG_SHA256 -DCONFIG_WNM -DCONFIG_WPA3_SAE -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DEAP_FAST -DEAP_MSCHAPv2 -DEAP_PEAP -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DESP32_WORKAROUND -DESPRESSIF_USE -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\" -DUSE_WPA2_TASK -DUSE_WPS_TASK -D__ets__ -I/home/suraj/trial/newf/bootloader_override/build/bootloader/config -I/home/suraj/esp/esp-idf/components/wpa_supplicant/include -I/home/suraj/esp/esp-idf/components/wpa_supplicant/port/include -I/home/suraj/esp/esp-idf/components/wpa_supplicant/esp_supplicant/include -I/home/suraj/esp/esp-idf/components/wpa_supplicant/src -I/home/suraj/esp/esp-idf/components/wpa_supplicant/src/utils -I/home/suraj/esp/esp-idf/components/wpa_supplicant/esp_supplicant/src -I/home/suraj/esp/esp-idf/components/log/include -I/home/suraj/esp/esp-idf/components/esp_rom/include -I/home/suraj/esp/esp-idf/components/esp_rom/include/esp32s3 -I/home/suraj/esp/esp-idf/components/esp_rom/esp32s3 -I/home/suraj/esp/esp-idf/components/esp_common/include -I/home/suraj/esp/esp-idf/components/esp_hw_support/include -I/home/suraj/esp/esp-idf/components/esp_hw_support/include/soc -I/home/suraj/esp/esp-idf/components/esp_hw_support/include/soc/esp32s3 -I/home/suraj/esp/esp-idf/components/esp_hw_support/port/esp32s3/. -I/home/suraj/esp/esp-idf/components/esp_hw_support/port/esp32s3/private_include -I/home/suraj/esp/esp-idf/components/hal/esp32s3/include -I/home/suraj/esp/esp-idf/components/hal/include -I/home/suraj/esp/esp-idf/components/hal/platform_port/include -I/home/suraj/esp/esp-idf/components/newlib/platform_include -I/home/suraj/esp/esp-idf/components/xtensa/include -I/home/suraj/esp/esp-idf/components/xtensa/esp32s3/include -I/home/suraj/esp/esp-idf/components/soc/include -I/home/suraj/esp/esp-idf/components/soc/esp32s3/. -I/home/suraj/esp/esp-idf/components/soc/esp32s3/include -I/home/suraj/esp/esp-idf/components/mbedtls/port/include -I/home/suraj/esp/esp-idf/components/mbedtls/mbedtls/include -I/home/suraj/esp/esp-idf/components/mbedtls/esp_crt_bundle/include -I/home/suraj/esp/esp-idf/components/lwip/include/apps -I/home/suraj/esp/esp-idf/components/lwip/include/apps/sntp -I/home/suraj/esp/esp-idf/components/lwip/lwip/src/include -I/home/suraj/esp/esp-idf/components/lwip/port/esp32/include -I/home/suraj/esp/esp-idf/components/lwip/port/esp32/include/arch -I/home/suraj/esp/esp-idf/components/vfs/include -I/home/suraj/esp/esp-idf/components/esp_wifi/include -I/home/suraj/esp/esp-idf/components/esp_event/include -I/home/suraj/esp/esp-idf/components/esp_netif/include -I/home/suraj/esp/esp-idf/components/esp_eth/include -I/home/suraj/esp/esp-idf/components/tcpip_adapter/include -I/home/suraj/esp/esp-idf/components/esp_phy/include -I/home/suraj/esp/esp-idf/components/esp_phy/esp32s3/include -I/home/suraj/esp/esp-idf/components/driver/include -I/home/suraj/esp/esp-idf/components/driver/esp32s3/include -I/home/suraj/esp/esp-idf/components/esp_pm/include -I/home/suraj/esp/esp-idf/components/esp_ringbuf/include -I/home/suraj/esp/esp-idf/components/esp_timer/include -mlongcalls -ffunction-sections -fdata-sections -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wextra -Wno-unused-parameter -Wno-sign-compare -ggdb -Os -freorder-blocks -fmacro-prefix-map=/home/suraj/esp/esp-idf/components/bootloader/subproject=. -fmacro-prefix-map=/home/suraj/esp/esp-idf=IDF -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -fno-stack-protector -std=gnu99 -Wno-old-style-declaration -D_GNU_SOURCE -DIDF_VER=\"v4.4.3-dirty\" -DESP_PLATFORM -DBOOTLOADER_BUILD=1 -Wno-strict-aliasing -Wno-write-strings -MD -MT esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_mbedtls.c.obj -MF esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_mbedtls.c.obj.d -o esp-idf/wpa_supplicant/CMakeFiles/__idf_wpa_supplicant.dir/src/crypto/crypto_mbedtls.c.obj -c /home/suraj/esp/esp-idf/components/wpa_supplicant/src/crypto/crypto_mbedtls.c
/home/suraj/esp/esp-idf/components/wpa_supplicant/src/crypto/crypto_mbedtls.c:8:10: fatal error: esp_system.h: No such file or directory
#include "esp_system.h"
^~~~~~~~~~~~~~
compilation terminated.
[4/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/chacha20.c.obj
[5/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cmac.c.obj
[6/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/des.c.obj
[7/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ccm.c.obj
[8/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher_wrap.c.obj
[9/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/constant_time.c.obj
[10/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/dhm.c.obj
[11/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/ctr_drbg.c.obj
[12/483] Building C object esp-idf/mbedtls/mbedtls/library/CMakeFiles/mbedcrypto.dir/cipher.c.obj
ninja: build stopped: subcommand failed.
[21/659] Building C object esp-idf/lwip/CMakeFiles/__idf_lwip.dir/lwip/src/core/ipv4/dhcp.c.obj
ninja: build stopped: subcommand failed.
ninja failed with exit code 1

Re: OTA firmware update in second stage bootloader with custom bootloader

Posted: Thu Jan 11, 2024 2:12 am
by ESP_Sprite
You cannot do that in the 2nd bootloader: you don't have access to e.g. FreeRTOS and the 2nd stage bootloader cannot be large enough to contain the entire WiFi/TCP-IP stack. Rather, you should boot into some application (e.g. on the factory partition) to do WiFi-related stuff.

Re: OTA firmware update in second stage bootloader with custom bootloader

Posted: Sat Jan 13, 2024 1:07 pm
by suraj02
Okay. Thank you for your help.