You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
I have searched the issue tracker for a similar issue and not found a similar issue.
IDF version.
5.0.7
Espressif SoC revision.
esp32s3
Operating System used.
Windows
How did you build your project?
Command line with Make
If you are using Windows, please specify command line type.
CMD
Development Kit.
esp32s3
Power Supply used.
USB
What is the expected behavior?
I am trying to implement a memory protection functionally for my project. I have several partitions: SSBL, factory and application. During normal operation the code first goes into SSBL than boots the factory/application.
What is the actual behavior?
It works like that, but when I try to implement the PMS functionality to select partitions and set access control for each of them, I can't boot any partition following SSBL. The memory protection algorithm is located in my SSBL.
Steps to reproduce.
This is my SSBL code:
/*
We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.
The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.
We do have a stack, so we can do the initialization in C. /
void attribute((noreturn)) call_start_cpu0(void)
{
tReprogFlag pReprogFlag = (tReprogFlag*) REPROGRAMMING_STRUCT_BASE_ADDR;
esp_image_metadata_t img_meta;
uint32_t calculatedCrcValue = 0;
bool noMainApp = false;
bool verifiedFAC = false;
bool verifiedOTA[2] = {false, false};
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
// If this boot is a wake up from the deep sleep then go to the short way,
// try to load the application which worked before deep sleep.
// It skips a lot of checks due to it was done before (while first boot).
bootloader_utility_load_boot_image_from_deep_sleep();
// If it is not successful try to load an application as usual.
#endif
/* 2. Select the number of boot partition */
bootloader_state_t bs = {0};
/* 2.1 Load partition table */
if (!bootloader_utility_load_partition_table(&bs)) {
ESP_LOGE(TAG, "load partition table error!");
bootloader_reset();
}
/* 3. Verify factory image checksum */
verifiedFAC = (esp_image_verify(ESP_IMAGE_VERIFY_SILENT, &bs.factory, &img_meta) == ESP_OK);
ESP_LOGI(TAG, "Image FCTRY verified: %d", verifiedFAC);
ESP_LOGI(TAG, "Should never arrive here!");
/* 4. Evaluate BootFlag */
calculatedCrcValue = esp_rom_crc32_le(REPROGRAMMING_STRUCT_CRC_INIT, (uint8_t const *)pReprogFlag, REPROG_FLAG_CRC_DATA_LEN);
ESP_LOGD(TAG, "calculated CRC: 0x%08X", calculatedCrcValue);
ESP_LOGD(TAG, "reprFlCrc: 0x%08X", pReprogFlag->reprFlCrc);
ESP_LOGD(TAG, "pReprogFlag addr: 0x%08X", pReprogFlag);
ESP_LOGD(TAG, "magicNum: 0x%08X", pReprogFlag->magicNum);
ESP_LOGD(TAG, "reprogFlag: 0x%08X", pReprogFlag->reprogFlag);
ESP_LOGD(TAG, "resetReasonFlag: 0x%08lX", pReprogFlag->resetReasonFlag);
bool bootAppl = false;
if (pReprogFlag->reprFlCrc == calculatedCrcValue) {
ESP_LOGI(TAG, "The CRC of Reprogramming flag structure valid!");
switch(pReprogFlag->reprogFlag)
{
case REPROGRAMMING_FLAG_APPL:
ESP_LOGI(TAG, "APPL start is requested.");
bootAppl = true;
break;
default:
ESP_LOGI(TAG, "Default boot image to factory.");
/* load KSC2N Factory */
break;
}
}
else {
/* Boot application start flag is invalid. Proceed first to factory */
ESP_LOGW(TAG, "The CRC of Reprogramming flag structure is invalid.");
/* Try to boot into application, if factory is not verified. */
bootAppl = (verifiedFAC == false);
}
int bootIndex = FACTORY_INDEX;
if (bootAppl) {
/* Verfiy OTA image checksums */
verifiedOTA[0] = (esp_image_verify(ESP_IMAGE_VERIFY_SILENT, &bs.ota[0], &img_meta) == ESP_OK);
ESP_LOGI(TAG, "Image OTA[0] verified: %d", verifiedOTA[0]);
verifiedOTA[1] = (esp_image_verify(ESP_IMAGE_VERIFY_SILENT, &bs.ota[1], &img_meta) == ESP_OK);
ESP_LOGI(TAG, "Image OTA[1] verified: %d", verifiedOTA[1]);
/* Select boot index for available applications. */
bootIndex = select_boot_index(&bs, verifiedOTA);
/* If factory is selected, no applicaiton is available */
if (bootIndex == FACTORY_INDEX) {
noMainApp = true;
}
}
ESP_LOGI(TAG, "Should never arrive here2!");
if ((bootIndex == FACTORY_INDEX) && (!verifiedFAC)) {
ESP_LOGE(TAG, "Factory image is invalid. No bootable image found.");
bootloader_halt();
}
/* 6. Reset reprogFlag for next boot (because a reset should always first boot factory and then go to main) */
pReprogFlag->magicNum = REPROGRAMMING_STRUCT_MAGIC_NUM;
pReprogFlag->reprogFlag = REPROGRAMMING_FLAG_FCTRY;
pReprogFlag->resetReasonFlag = (noMainApp) ? REPROGRAMMING_REASON_NO_APP : REPROGRAMMING_REASON_RESERVED;
calculatedCrcValue = esp_rom_crc32_le(REPROGRAMMING_STRUCT_CRC_INIT, (uint8_t const *)pReprogFlag, REPROG_FLAG_CRC_DATA_LEN);
pReprogFlag->reprFlCrc = calculatedCrcValue;
ESP_LOGI(TAG, "Reset Reprogramming flag");
ESP_LOGD(TAG, "calculated CRC: 0x%08X", calculatedCrcValue);
ESP_LOGD(TAG, "reprFlCrc: 0x%08X", pReprogFlag->reprFlCrc);
ESP_LOGD(TAG, "pReprogFlag addr: 0x%08X", pReprogFlag);
ESP_LOGD(TAG, "magicNum: 0x%08X", pReprogFlag->magicNum);
ESP_LOGD(TAG, "reprogFlag: 0x%08X", pReprogFlag->reprogFlag);
ESP_LOGD(TAG, "resetReasonFlag: 0x%08lX", pReprogFlag->resetReasonFlag);
/*** MEMORY PROTECTION ***/
hal_mem_protect_enable(bootIndex);
/*** MEMORY PROTECTION ***/
/* 7. Load the app image for booting */
ESP_LOGI(TAG, "Try to load image: %d (-1: factory | 0/1: main app)", bootIndex);
bootloader_utility_load_boot_image(&bs, bootIndex);
}
My hal driver for PMS:
/**
(c) Maschinenfabrik Bernard Krone GmbH, Spelle. All rights reserved.
// Constants for Active OTA Selection
#define OTA_0_ACTIVE 0
#define OTA_1_ACTIVE 1
/*************************/
/***************** Local types /
//
// Enum for Memory Regions
enum {
SSBL = 0,
OTA_0,
OTA_1,
FACTORY,
PROD,
NUM_REGIONS // Total number of regions
};
// Memory map structure
typedef struct {
uint32_t start_address; // Starting address of the memory region
uint32_t size; // Size of the memory region
} memory_region_t;
/*********************/
/***************** Local variables /
//
// Configures the Flash memory protection
void hal_mem_protect_enable(int active_ota) {
// Iterate through all memory regions
for (int i = 0; i < NUM_REGIONS; i++) {
if(i == OTA_0 || i == OTA_1 || i == FACTORY) {
// Configure the start address and size
REG_WRITE(FLASH_ACE_ADDR_REG(counter), memory_regions[counter].start_address); // Set base address
REG_WRITE(FLASH_ACE_SIZE_REG(counter), memory_regions[counter].size); // Set size
ESP_LOGE("PCU", "FLASH ACE ADDR REG: %X, start address: %X", FLASH_ACE_ADDR_REG(counter), memory_regions[counter].start_address);
ESP_LOGE("PCU", "FLASH ACE SIZE REG: %X, size: %X", FLASH_ACE_SIZE_REG(counter), memory_regions[counter].size);
// Set the access control attributes for Secure, Non-Secure, and SPI1
uint32_t attr = ATTR_FULL_ACCESS;//ATTR_SPI1_READ_ONLY | ATTR_NON_SECURE_READ_ONLY | ATTR_SECURE_READ_ONLY;
REG_WRITE(FLASH_ACE_ATTR_REG(counter), attr); // Set attributes
ESP_LOGE("PCU", "FLASH ACE ATTR REG: %X, attr: %X", FLASH_ACE_ATTR_REG(counter), attr);
uint32_t value = REG_READ(FLASH_ACE_ADDR_REG(counter));
ESP_LOGE("PCU", "read FLASH ACE ADDR REG: %X", value);
value = REG_READ(FLASH_ACE_SIZE_REG(counter));
ESP_LOGE("PCU", "read FLASH ACE SIZE REG: %X", value);
value = REG_READ(FLASH_ACE_ATTR_REG(counter));
ESP_LOGE("PCU", "read FLASH ACE ATTR REG: %X", value);
}
counter++;
}
ESP_LOGE("PCU", "Flash memory regions configured with full access for Secure, Non-Secure, and SPI1.");
}
// Enables full access for either SSBL or Factory region
void enable_full_access(int region) {
if (region != SSBL && region != FACTORY) {
ESP_LOGE("PCU", "Invalid region specified. Only SSBL or Factory can be set to full access.");
return;
}
// Enable full access for the specified region
uint32_t full_access_attr = ATTR_FULL_ACCESS; // Full access for all
REG_WRITE(FLASH_ACE_ATTR_REG(region), full_access_attr);
ESP_LOGI("PCU", "Full access enabled for region %s.",
(region == SSBL) ? "SSBL" : "Factory");
}
//
/ Local function definitions **************/
/*************/
#ifdef __cplusplus
} /* end of extern "C" */
#endif
You can see that I have selected the partitions starting addresses, their size and the access control.
Even if set the access control is set to full access, I can't boot my bootloader or application. Please take a look at the logs.
Debug Logs.
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0x29 (SPI_FAST_FLASH_BOOT)
Saved PC:0x403cdf3a
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3980,len:0x216c
load:0x403c9700,len:0x1344
load:0x403cc700,len:0x33fc
entry 0x403c99e0
W (27) boot.esp32s3: eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!
I (43) boot: ESP-IDF v5.0.7-dirty 2nd stage bootloader
I (44) boot: compile time 15:48:58
I (44) boot: Multicore bootloader
I (46) boot: chip revision: v0.1
I (50) qio_mode: Enabling default flash chip QIO
I (55) boot.esp32s3: Boot SPI Speed : 80MHz
I (60) boot.esp32s3: SPI Mode : QIO
I (65) boot.esp32s3: SPI Flash Size : 16MB
I (70) boot: Enabling RNG early entropy source...
I (75) boot: Partition Table:
I (79) boot: ## Label Usage Type ST Offset Length
I (86) boot: 0 otadata OTA data 01 00 0000d000 00002000
I (93) boot: 1 reserved WiFi data 01 02 0000f000 00001000
I (101) boot: 2 ota_0 OTA app 00 10 00010000 00300000
I (108) boot: 3 ota_1 OTA app 00 11 00310000 00300000
I (116) boot: 4 factory factory app 00 00 00610000 00100000
I (124) boot: 5 prod Unknown data 01 ff 00710000 00001000
I (131) boot: 6 reserved1 Unknown data 01 ff 00711000 00002000
I (139) boot: 7 safeNVrb0 Unknown data 01 ff 00713000 00010000
I (146) boot: 8 safeNVrb1 Unknown data 01 ff 00723000 00010000
I (154) boot: 9 safeNVrb2 Unknown data 01 ff 00733000 00010000
I (161) boot: 10 config WiFi data 01 02 00743000 00046000
I (169) boot: 11 shared WiFi data 01 02 00789000 00003000
I (176) boot: 12 appl WiFi data 01 02 0078c000 00008000
I (184) boot: 13 coredump Unknown data 01 03 00794000 00040000
I (192) boot: 14 log Unknown data 01 ff 007d4000 00040000
I (199) boot: 15 fifo Unknown data 01 ff 00814000 00100000
I (207) boot: 16 diagtool2 Unknown data 01 ff 00914000 006ea000
I (214) boot: End of partition table
I (321) SSBL: Image FCTRY verified: 1
I (321) SSBL: Should never arrive here!
I (321) SSBL: The CRC of Reprogramming flag structure valid!
I (325) SSBL: Default boot image to factory.
I (329) SSBL: Should never arrive here2!
I (334) SSBL: Reset Reprogramming flag
E (339) PCU: FLASH ACE ADDR REG: 6002603C, start address: 20000
E (345) PCU: FLASH ACE SIZE REG: 6002604C, size: 2D
E (351) PCU: FLASH ACE ATTR REG: 6002602C, attr: FF
E (356) PCU: read FLASH ACE ADDR REG: 20000
E (361) PCU: read FLASH ACE SIZE REG: 2D
E (366) PCU: read FLASH ACE ATTR REG: FF
E (370) PCU: FLASH ACE ADDR REG: 60026040, start address: 312000
E (377) PCU: FLASH ACE SIZE REG: 60026050, size: 2D
E (383) PCU: FLASH ACE ATTR REG: 60026030, attr: FF
E (388) PCU: read FLASH ACE ADDR REG: 312000
E (393) PCU: read FLASH ACE SIZE REG: 2D
E (398) PCU: read FLASH ACE ATTR REG: FF
E (402) PCU: FLASH ACE ADDR REG: 60026044, start address: 620000
E (409) PCU: FLASH ACE SIZE REG: 60026054, size: F
E (414) PCU: FLASH ACE ATTR REG: 60026034, attr: FF
E (420) PCU: read FLASH ACE ADDR REG: 620000
E (425) PCU: read FLASH ACE SIZE REG: F
E (429) PCU: read FLASH ACE ATTR REG: FF
E (434) PCU: Flash memory regions configured with full access for Secure, Non-Secure, and SPI1.
I (443) SSBL: Try to load image: -1 (-1: factory | 0/1: main app)
I (450) esp_image: segment 0: paddr=00610020 vaddr=3c070020 size=2a618h (173592) map
E (480) esp_image: invalid segment length 0xfeebdaed
E (481) boot: Factory app partition is not bootable
I (481) esp_image: segment 0: paddr=00010020 vaddr=3c1b0020 size=7ffe8h (524264) map
E (549) esp_image: invalid segment length 0xfeebdaed
E (549) boot: OTA app partition slot 0 is not bootable
E (549) esp_image: image at 0x310000 has invalid magic byte (nothing flashed here?)
E (557) boot: OTA app partition slot 1 is not bootable
E (563) boot: No bootable app partitions in the partition table
The whole idea was to implement memory protection that while I am in one partition in the code, to disable unwanted access to the other partitions. Perhaps, I am doing something wrong during the configuration of the PMS or perhaps, this functionality is not applicable for my use case.
Also, because some of the segments I want to protect are shorter than 64k, which is the shortest segment fraction, I was wondering whether I can have overlapping memory segments in terms of PMS?
The text was updated successfully, but these errors were encountered:
Can you confirm that start address and size of the all the flash partitions are 64Kb aligned? From the code snippet it looks like SSBL partition size is not (it’s 48KB).
All the partition size defined are in numbers (SSBL_SIZE = 1, ….) and same is configured in FLASH_ACE_n_SIZE register. Can you please confirm it? If this is the case, it will be invalid configuration.
Are you configuring all the valid permission for Secure World? I think entire code will be executing in secure world, it is not switching to Non-secure world.
Are you configuring and enabling the interrupt for access violation for external memory (Section 15.6.3 in TRM)? If not, can you read control and addr registers (0x88 and 0x8c), to find the location and type of access violation?
Answers checklist.
IDF version.
5.0.7
Espressif SoC revision.
esp32s3
Operating System used.
Windows
How did you build your project?
Command line with Make
If you are using Windows, please specify command line type.
CMD
Development Kit.
esp32s3
Power Supply used.
USB
What is the expected behavior?
I am trying to implement a memory protection functionally for my project. I have several partitions: SSBL, factory and application. During normal operation the code first goes into SSBL than boots the factory/application.
What is the actual behavior?
It works like that, but when I try to implement the PMS functionality to select partitions and set access control for each of them, I can't boot any partition following SSBL. The memory protection algorithm is located in my SSBL.
Steps to reproduce.
This is my SSBL code:
/*
We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.
The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.
We do have a stack, so we can do the initialization in C.
/
void attribute((noreturn)) call_start_cpu0(void)
{
tReprogFlag pReprogFlag = (tReprogFlag*) REPROGRAMMING_STRUCT_BASE_ADDR;
esp_image_metadata_t img_meta;
uint32_t calculatedCrcValue = 0;
bool noMainApp = false;
bool verifiedFAC = false;
bool verifiedOTA[2] = {false, false};
/* 1. Hardware initialization */
if (bootloader_init() != ESP_OK) {
bootloader_reset();
}
#ifdef CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
// If this boot is a wake up from the deep sleep then go to the short way,
// try to load the application which worked before deep sleep.
// It skips a lot of checks due to it was done before (while first boot).
bootloader_utility_load_boot_image_from_deep_sleep();
// If it is not successful try to load an application as usual.
#endif
}
My hal driver for PMS:
/**
*/
#ifdef __cplusplus
extern "C"
{
#endif
//
/***************** Inclusions **************************/
//
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "esp_log.h"
#include "HAL_MEM_PROTECT.h"
/************************/
/***************** Local Macros /
//
//write value to register
#define REG_WRITE(_r, _v) do {
(*(volatile uint32_t *)(_r)) = (_v);
} while(0)
//read value from register
#define REG_READ(_r) ({
(*(volatile uint32_t *)(_r));
})
// Correct SYSCON Base Address for Flash
#define SYSCON_BASE 0x60026000
// Flash ACE Registers
#define FLASH_ACE_ATTR_REG(n) (SYSCON_BASE + 0x0028 + (4 * (n))) // Flash ACE Permission Config Register
#define FLASH_ACE_ADDR_REG(n) (SYSCON_BASE + 0x0038 + (4 * (n))) // Flash ACE Starting Address Config Register
#define FLASH_ACE_SIZE_REG(n) (SYSCON_BASE + 0x0048 + (4 * (n))) // Flash ACE Length Config Register
// Define Access Control Attributes (Readable Names for Bits)
#define ATTR_SECURE_READ_ONLY (0b010 << 0) // Secure World: Read-only (W=0, R=1, X=1)
#define ATTR_NON_SECURE_READ_ONLY (0b010 << 3) // Non-Secure World: Read-only (W=0, R=1, X=1)
#define ATTR_SPI1_READ_ONLY (0b01 << 6) // SPI1: Read-only (W=0, R=1)
#define ATTR_FULL_ACCESS (0b11111111) // Full Access (W=1, R=1, X=1)
/*************************/
/***************** Local types /
//
// Memory Map Configuration Macros
#define SSBL_START_ADDR 0x00000000
#define SSBL_SIZE 1 // (48 * 1024) // 48KB
#define OTA_0_START_ADDR 0x00020000
#define OTA_0_SIZE 45 // (3072 * 1024) // 3072KB
#define OTA_1_START_ADDR 0x0312000
#define OTA_1_SIZE 45 // (3072 * 1024) // 3072KB
#define FACTORY_START_ADDR 0x00620000
#define FACTORY_SIZE 15 // (1024 * 1024) // 1024KB
#define PROD_START_ADDR 0x00710000
#define PROD_SIZE 1 // (4 * 1024) // 4KB
// Constants for Active OTA Selection
#define OTA_0_ACTIVE 0
#define OTA_1_ACTIVE 1
/*************************/
/***************** Local types /
//
// Enum for Memory Regions
enum {
SSBL = 0,
OTA_0,
OTA_1,
FACTORY,
PROD,
NUM_REGIONS // Total number of regions
};
// Memory map structure
typedef struct {
uint32_t start_address; // Starting address of the memory region
uint32_t size; // Size of the memory region
} memory_region_t;
/*********************/
/***************** Local variables /
//
// Memory regions defined using macros
const memory_region_t memory_regions[NUM_REGIONS] = {
{SSBL_START_ADDR, SSBL_SIZE}, // SSBL
{OTA_0_START_ADDR, OTA_0_SIZE}, // OTA_0
{OTA_1_START_ADDR, OTA_1_SIZE}, // OTA_1
{FACTORY_START_ADDR, FACTORY_SIZE}, // Factory
{PROD_START_ADDR, PROD_SIZE} // Prod
};
uint8_t counter = 0;
//
/ Local function declarations /
//
//
/***************** Interface functions *****************/
//
// Configures the Flash memory protection
void hal_mem_protect_enable(int active_ota) {
// Iterate through all memory regions
for (int i = 0; i < NUM_REGIONS; i++) {
}
// Enables full access for either SSBL or Factory region
void enable_full_access(int region) {
if (region != SSBL && region != FACTORY) {
ESP_LOGE("PCU", "Invalid region specified. Only SSBL or Factory can be set to full access.");
return;
}
}
//
/ Local function definitions **************/
/*************/
#ifdef __cplusplus
} /* end of extern "C" */
#endif
You can see that I have selected the partitions starting addresses, their size and the access control.
Even if set the access control is set to full access, I can't boot my bootloader or application. Please take a look at the logs.
Debug Logs.
More Information.
I followed the specifications specified in section 15.5 in this document: https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf
The whole idea was to implement memory protection that while I am in one partition in the code, to disable unwanted access to the other partitions. Perhaps, I am doing something wrong during the configuration of the PMS or perhaps, this functionality is not applicable for my use case.
Also, because some of the segments I want to protect are shorter than 64k, which is the shortest segment fraction, I was wondering whether I can have overlapping memory segments in terms of PMS?
The text was updated successfully, but these errors were encountered: