Skip to content

Commit a1d641d

Browse files
almir-okatogustavonihei
authored andcommitted
espressif:esp32: Add multi image support
Changes on configuration and flash area organization for supporting multi image and implementation for booting on different processors on esp32 Signed-off-by: Almir Okato <almir.okato@espressif.com>
1 parent 20e0209 commit a1d641d

17 files changed

+339
-39
lines changed

boot/espressif/bootloader.conf

+22-2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,33 @@
33
# SPDX-License-Identifier: Apache-2.0
44

55
CONFIG_ESP_BOOTLOADER_SIZE=0xF000
6-
CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS=0x10000
6+
CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS=0x10000
77
CONFIG_ESP_APPLICATION_SIZE=0x100000
8-
CONFIG_ESP_APPLICATION_SECONDARY_START_ADDRESS=0x110000
8+
CONFIG_ESP_IMAGE0_SECONDARY_START_ADDRESS=0x110000
99
CONFIG_ESP_MCUBOOT_WDT_ENABLE=y
1010
CONFIG_ESP_SCRATCH_OFFSET=0x210000
1111
CONFIG_ESP_SCRATCH_SIZE=0x40000
1212

13+
# Enables multi image, if it is not defined, it is assumed
14+
# only one updatable image
15+
# CONFIG_ESP_IMAGE_NUMBER=2
16+
17+
# Enables multi image boot on independent processors
18+
# (main host OS is not responsible for booting the second image)
19+
# Use only with CONFIG_ESP_IMAGE_NUMBER=2
20+
# CONFIG_ESP_MULTI_PROCESSOR_BOOT=y
21+
22+
# Example of values to be used when multi image is enabled
23+
# Notice that the OS layer and update agent must be aware
24+
# of these regions
25+
# CONFIG_ESP_APPLICATION_SIZE=0x50000
26+
# CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS=0x10000
27+
# CONFIG_ESP_IMAGE0_SECONDARY_START_ADDRESS=0x60000
28+
# CONFIG_ESP_IMAGE1_PRIMARY_START_ADDRESS=0xB0000
29+
# CONFIG_ESP_IMAGE1_SECONDARY_START_ADDRESS=0x100000
30+
# CONFIG_ESP_SCRATCH_OFFSET=0x150000
31+
# CONFIG_ESP_SCRATCH_SIZE=0x40000
32+
1333
# CONFIG_ESP_SIGN_EC256=y
1434
# CONFIG_ESP_SIGN_ED25519=n
1535
# CONFIG_ESP_SIGN_RSA=n

boot/espressif/hal/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ set(hal_srcs
5656
${src_dir}/flash_encrypt.c
5757
${src_dir}/${MCUBOOT_TARGET}/bootloader_init.c
5858
${esp_idf_dir}/components/hal/mpu_hal.c
59+
${esp_idf_dir}/components/hal/soc_hal.c
5960
${esp_idf_dir}/components/bootloader_support/src/bootloader_common_loader.c
6061
${esp_idf_dir}/components/bootloader_support/src/bootloader_console_loader.c
6162
${esp_idf_dir}/components/bootloader_support/src/bootloader_flash.c
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#include <stdint.h>
10+
11+
void appcpu_start(uint32_t entry_addr);

boot/espressif/hal/include/esp32/esp32.cmake

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ list(APPEND hal_srcs
1010
${esp_idf_dir}/components/efuse/src/esp_efuse_api_key_esp32.c
1111
)
1212

13+
if (DEFINED CONFIG_ESP_MULTI_PROCESSOR_BOOT)
14+
list(APPEND hal_srcs
15+
${src_dir}/${MCUBOOT_TARGET}/app_cpu_start.c
16+
)
17+
endif()
18+
1319
list(APPEND LINKER_SCRIPTS
1420
-T${esp_idf_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.newlib-funcs.ld
1521
-T${esp_idf_dir}/components/esp_rom/${MCUBOOT_TARGET}/ld/${MCUBOOT_TARGET}.rom.eco3.ld

boot/espressif/hal/include/mcuboot_config/mcuboot_config.h

+4
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,11 @@
9898

9999
/* Default number of separately updateable images; change in case of
100100
* multiple images. */
101+
#if defined(CONFIG_ESP_IMAGE_NUMBER)
102+
#define MCUBOOT_IMAGE_NUMBER CONFIG_ESP_IMAGE_NUMBER
103+
#else
101104
#define MCUBOOT_IMAGE_NUMBER 1
105+
#endif
102106

103107
/*
104108
* Logging
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "app_cpu_start.h"
8+
9+
#include "soc/dport_reg.h"
10+
#include "soc/gpio_periph.h"
11+
#include "soc/rtc_periph.h"
12+
#include "soc/rtc_cntl_reg.h"
13+
#include "esp32/rom/cache.h"
14+
#include "esp32/rom/uart.h"
15+
#include "esp_cpu.h"
16+
#include "esp_log.h"
17+
18+
static const char *TAG = "app_cpu_start";
19+
20+
void appcpu_start(uint32_t entry_addr)
21+
{
22+
ESP_LOGI(TAG, "Starting APPCPU");
23+
24+
Cache_Flush(1);
25+
Cache_Read_Enable(1);
26+
27+
esp_cpu_unstall(1);
28+
29+
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
30+
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL);
31+
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
32+
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
33+
34+
ets_set_appcpu_boot_addr(entry_addr);
35+
ets_delay_us(10000);
36+
uart_tx_wait_idle(0);
37+
ESP_LOGI(TAG, "APPCPU start sequence complete");
38+
}

boot/espressif/hal/src/flash_encrypt.c

+19-4
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
234234
* This will need changes when implementing multi-slot support
235235
*/
236236
ESP_LOGI(TAG, "Encrypting remaining flash...");
237-
uint32_t region_addr = CONFIG_ESP_APPLICATION_SECONDARY_START_ADDRESS;
237+
uint32_t region_addr = CONFIG_ESP_IMAGE0_SECONDARY_START_ADDRESS;
238238
size_t region_size = CONFIG_ESP_APPLICATION_SIZE;
239239
err = esp_flash_encrypt_region(region_addr, region_size);
240240
if (err != ESP_OK) {
@@ -247,6 +247,21 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
247247
return err;
248248
}
249249

250+
#if defined(CONFIG_ESP_IMAGE_NUMBER) && (CONFIG_ESP_IMAGE_NUMBER == 2)
251+
region_addr = CONFIG_ESP_IMAGE1_PRIMARY_START_ADDRESS;
252+
region_size = CONFIG_ESP_APPLICATION_SIZE;
253+
err = esp_flash_encrypt_region(region_addr, region_size);
254+
if (err != ESP_OK) {
255+
return err;
256+
}
257+
region_addr = CONFIG_ESP_IMAGE1_SECONDARY_START_ADDRESS;
258+
region_size = CONFIG_ESP_APPLICATION_SIZE;
259+
err = esp_flash_encrypt_region(region_addr, region_size);
260+
if (err != ESP_OK) {
261+
return err;
262+
}
263+
#endif
264+
250265
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
251266
// Go straight to max, permanently enabled
252267
ESP_LOGI(TAG, "Setting CRYPT_CNT for permanent encryption");
@@ -309,20 +324,20 @@ static esp_err_t encrypt_primary_slot(void)
309324
/* Check if the slot is plaintext or encrypted, 0x20 offset is for skipping
310325
* MCUboot header
311326
*/
312-
err = bootloader_flash_read(CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS + 0x20,
327+
err = bootloader_flash_read(CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS + 0x20,
313328
&img_header, sizeof(esp_image_load_header_t), true);
314329
if (err != ESP_OK) {
315330
ESP_LOGE(TAG, "Failed to read slot img header");
316331
return err;
317332
} else {
318-
err = verify_img_header(CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS,
333+
err = verify_img_header(CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS,
319334
&img_header, true);
320335
}
321336

322337
if (err == ESP_OK) {
323338
ESP_LOGI(TAG, "Encrypting primary slot...");
324339

325-
err = esp_flash_encrypt_region(CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS,
340+
err = esp_flash_encrypt_region(CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS,
326341
CONFIG_ESP_APPLICATION_SIZE);
327342
if (err != ESP_OK) {
328343
ESP_LOGE(TAG, "Failed to encrypt slot in place: 0x%x", err);

boot/espressif/include/esp_loader.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66

77
#pragma once
88

9-
void esp_app_image_load(int slot, unsigned int hdr_offset);
9+
void esp_app_image_load(int image_index, int slot, unsigned int hdr_offset, unsigned int *entry_addr);

boot/espressif/include/sysflash/sysflash.h

+33-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
#pragma once
8+
9+
#include <mcuboot_config/mcuboot_config.h>
10+
711
//! A user-defined identifier for different storage mediums
812
//! (i.e internal flash, external NOR flash, eMMC, etc)
913
#define FLASH_DEVICE_INTERNAL_FLASH 0
@@ -12,14 +16,35 @@
1216
//! there is not slot
1317
#define FLASH_SLOT_DOES_NOT_EXIST 255
1418

15-
//! NB: MCUboot expects this define to exist but it's only used
16-
//! if MCUBOOT_SWAP_USING_SCRATCH=1 is set
17-
#define FLASH_AREA_IMAGE_SCRATCH FLASH_SLOT_DOES_NOT_EXIST
18-
1919
//! The slot we will use to track the bootloader allocation
2020
#define FLASH_AREA_BOOTLOADER 0
2121

22-
//! A mapping to primary and secondary/upgrade slot
23-
//! given an image_index. We'll plan to use
24-
#define FLASH_AREA_IMAGE_PRIMARY(i) ((i == 0) ? 1 : 255)
25-
#define FLASH_AREA_IMAGE_SECONDARY(i) ((i == 0) ? 2 : 255)
22+
#define FLASH_AREA_IMAGE_0_PRIMARY 1
23+
#define FLASH_AREA_IMAGE_0_SECONDARY 2
24+
#define FLASH_AREA_IMAGE_SCRATCH 3
25+
#define FLASH_AREA_IMAGE_1_PRIMARY 4
26+
#define FLASH_AREA_IMAGE_1_SECONDARY 5
27+
28+
#if (MCUBOOT_IMAGE_NUMBER == 1)
29+
#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? \
30+
FLASH_AREA_IMAGE_0_PRIMARY : \
31+
FLASH_SLOT_DOES_NOT_EXIST)
32+
#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? \
33+
FLASH_AREA_IMAGE_0_SECONDARY : \
34+
FLASH_SLOT_DOES_NOT_EXIST)
35+
36+
#elif (MCUBOOT_IMAGE_NUMBER == 2)
37+
#define FLASH_AREA_IMAGE_PRIMARY(x) (((x) == 0) ? \
38+
FLASH_AREA_IMAGE_0_PRIMARY : \
39+
((x) == 1) ? \
40+
FLASH_AREA_IMAGE_1_PRIMARY : \
41+
FLASH_SLOT_DOES_NOT_EXIST)
42+
#define FLASH_AREA_IMAGE_SECONDARY(x) (((x) == 0) ? \
43+
FLASH_AREA_IMAGE_0_SECONDARY : \
44+
((x) == 1) ? \
45+
FLASH_AREA_IMAGE_1_SECONDARY : \
46+
FLASH_SLOT_DOES_NOT_EXIST)
47+
48+
#else
49+
#warning "Image slot and flash area mapping is not defined"
50+
#endif

boot/espressif/main.c

+65-3
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,74 @@
2222
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
2323
#include "esp_flash_encrypt.h"
2424
#endif
25+
#ifdef CONFIG_ESP_MULTI_PROCESSOR_BOOT
26+
#include "app_cpu_start.h"
27+
#endif
2528

2629
#include "esp_loader.h"
2730
#include "os/os_malloc.h"
2831

32+
#define IMAGE_INDEX_0 0
33+
#define IMAGE_INDEX_1 1
34+
35+
#define PRIMARY_SLOT 0
36+
#define SECONDARY_SLOT 1
37+
2938
#ifdef CONFIG_SECURE_BOOT
3039
extern esp_err_t check_and_generate_secure_boot_keys(void);
3140
#endif
3241

3342
void do_boot(struct boot_rsp *rsp)
3443
{
44+
unsigned int entry_addr;
3545
BOOT_LOG_INF("br_image_off = 0x%x", rsp->br_image_off);
3646
BOOT_LOG_INF("ih_hdr_size = 0x%x", rsp->br_hdr->ih_hdr_size);
37-
int slot = (rsp->br_image_off == CONFIG_ESP_APPLICATION_PRIMARY_START_ADDRESS) ? 0 : 1;
38-
esp_app_image_load(slot, rsp->br_hdr->ih_hdr_size);
47+
int slot = (rsp->br_image_off == CONFIG_ESP_IMAGE0_PRIMARY_START_ADDRESS) ? PRIMARY_SLOT : SECONDARY_SLOT;
48+
esp_app_image_load(IMAGE_INDEX_0, slot, rsp->br_hdr->ih_hdr_size, &entry_addr);
49+
((void (*)(void))entry_addr)(); /* Call to application entry address should not return */
50+
FIH_PANIC; /* It should not get here */
51+
}
52+
53+
#ifdef CONFIG_ESP_MULTI_PROCESSOR_BOOT
54+
int read_image_header(uint32_t img_index, uint32_t slot, struct image_header *img_header)
55+
{
56+
const struct flash_area *fap;
57+
int area_id;
58+
int rc = 0;
59+
60+
area_id = flash_area_id_from_multi_image_slot(img_index, slot);
61+
rc = flash_area_open(area_id, &fap);
62+
if (rc != 0) {
63+
rc = BOOT_EFLASH;
64+
goto done;
65+
}
66+
67+
if (flash_area_read(fap, 0, img_header, sizeof(struct image_header))) {
68+
rc = BOOT_EFLASH;
69+
goto done;
70+
}
71+
72+
BOOT_LOG_INF("Image offset = 0x%x", fap->fa_off);
73+
BOOT_LOG_INF("Image header size = 0x%x", img_header->ih_hdr_size);
74+
75+
done:
76+
flash_area_close(fap);
77+
return rc;
78+
}
79+
80+
void do_boot_appcpu(uint32_t img_index, uint32_t slot)
81+
{
82+
unsigned int entry_addr;
83+
struct image_header img_header;
84+
85+
if (read_image_header(img_index, slot, &img_header) != 0) {
86+
FIH_PANIC;
87+
}
88+
89+
esp_app_image_load(img_index, slot, img_header.ih_hdr_size, &entry_addr);
90+
appcpu_start(entry_addr);
3991
}
92+
#endif
4093

4194
int main()
4295
{
@@ -97,8 +150,10 @@ int main()
97150
* 2) MCUboot validates the application images and prepares the booting process.
98151
*/
99152

153+
/* MCUboot's boot_go validates and checks all images for update and returns
154+
* the load information for booting the main image
155+
*/
100156
FIH_CALL(boot_go, fih_rc, &rsp);
101-
102157
if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
103158
BOOT_LOG_ERR("Unable to find bootable image");
104159
#ifdef CONFIG_SECURE_BOOT
@@ -165,6 +220,13 @@ int main()
165220
BOOT_LOG_INF("Disabling RNG early entropy source...");
166221
bootloader_random_disable();
167222

223+
#ifdef CONFIG_ESP_MULTI_PROCESSOR_BOOT
224+
/* Multi image independent boot
225+
* Boot on the second processor happens before the image0 boot
226+
*/
227+
do_boot_appcpu(IMAGE_INDEX_1, PRIMARY_SLOT);
228+
#endif
229+
168230
do_boot(&rsp);
169231

170232
while(1);

boot/espressif/port/esp_loader.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include "esp_loader.h"
2828
#include "flash_map_backend/flash_map_backend.h"
2929

30-
3130
static int load_segment(const struct flash_area *fap, uint32_t data_addr, uint32_t data_len, uint32_t load_addr)
3231
{
3332
const uint32_t *data = (const uint32_t *)bootloader_mmap((fap->fa_off + data_addr), data_len);
@@ -40,18 +39,20 @@ static int load_segment(const struct flash_area *fap, uint32_t data_addr, uint32
4039
return 0;
4140
}
4241

43-
void esp_app_image_load(int slot, unsigned int hdr_offset)
42+
void esp_app_image_load(int image_index, int slot, unsigned int hdr_offset, unsigned int *entry_addr)
4443
{
4544
const struct flash_area *fap;
4645
int area_id;
4746
int rc;
4847

49-
area_id = flash_area_id_from_image_slot(slot);
48+
area_id = flash_area_id_from_multi_image_slot(image_index, slot);
5049
rc = flash_area_open(area_id, &fap);
5150
if (rc != 0) {
5251
BOOT_LOG_ERR("%s: flash_area_open failed with %d", __func__, rc);
5352
}
5453

54+
BOOT_LOG_INF("Loading image %d - slot %d from flash, area id: %d", image_index, slot, area_id);
55+
5556
const uint32_t *data = (const uint32_t *)bootloader_mmap((fap->fa_off + hdr_offset), sizeof(esp_image_load_header_t));
5657
esp_image_load_header_t load_header = {0};
5758
memcpy((void *)&load_header, data, sizeof(esp_image_load_header_t));
@@ -85,7 +86,7 @@ void esp_app_image_load(int slot, unsigned int hdr_offset)
8586

8687
BOOT_LOG_INF("start=0x%x", load_header.entry_addr);
8788
uart_tx_wait_idle(0);
88-
void *start = (void *) load_header.entry_addr;
89-
((void (*)(void))start)(); /* Call to application entry address should not return */
90-
FIH_PANIC;
89+
90+
assert(entry_addr != NULL);
91+
*entry_addr = load_header.entry_addr;
9192
}

0 commit comments

Comments
 (0)