Page 1 of 2

Partition table update on secure device

Posted: Wed Feb 23, 2022 10:23 am
by erikha
Hello,

I have a problem with updating the partition table over-the-air.

Information:
ESP32-WROOM-32E
Using esp-idf v4.2
Secure boot v1 enabled, one-time flashable
Encrypted some partitions in NVS

When I update the partition table of a non-secure device over-the-air it works like a charm, but when performing the same update to a secure device, the device is bricked because it boot loops. I suspect the boot digest is the problem here, because this digest isn't updated when the partition table is updated.

A solution would be to be able to re-calculate the digest from the application code when the partition table is updated. Is this possible? Or is something else the problem?

Thank you for your help.

Kind regards,
erikha

Re: Partition table update on secure device

Posted: Wed Feb 23, 2022 3:45 pm
by WiFive
Are you sure the partition table of both devices is at the same address? Usually size of secure bootloader means partition table has to be moved. Do you have the boot log?

Re: Partition table update on secure device

Posted: Wed Feb 23, 2022 4:22 pm
by erikha
The bootloader is flashed with start address 0x1000 and the partition table at 0x10000 on both devices.

The boot log:

Code: Select all

rst:0x3 (SW_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:11376
ho 0 tail 12 room 4
load:0x40078000,len:20240
load:0x40080400,len:6712
entry 0x40080778
I (146) boot: Chip Revision: 1
I (68) boot: ESP-IDF v3.3.4 2nd stage bootloader
I (68) boot: compile time 13:07:11
I (68) boot: Enabling RNG early entropy source...
I (73) boot: SPI Speed      : 40MHz
I (77) boot: SPI Mode       : DIO
I (81) boot: SPI Flash Size : 8MB
E (85) flash_parts: partition 0 invalid magic number 0x4088
E (91) boot: Failed to verify partition table
E (96) boot: load partition table error!
ets Jun  8 2016 00:22:57

Re: Partition table update on secure device

Posted: Thu Feb 24, 2022 3:23 am
by WiFive
The digest is fine because the 2nd stage bootloader is running. The error is "invalid magic number 0x4088" for the partition table. Are you also using flash encryption and how do you write the new bootloader to flash?

Re: Partition table update on secure device

Posted: Thu Feb 24, 2022 4:07 pm
by erikha
Okay, good to know the digest is fine.

Yes, I have flash encryption enabled.

I don't write a new bootloader. The process:

- Flash device with secure bootloader A, partion table A and application A
- Boot device for first time and flash gets encrypted
- Device shipped to customer
- I want to update partition table
- Send application B OTA
- Application B boots and detects partition table A
- Application B start replacing partion table A with partition table B
- Device reboots and enters a bootloop

Is there something I did wrong or did I forget something?

Re: Partition table update on secure device

Posted: Fri Feb 25, 2022 3:52 am
by WiFive
Sorry I meant how do you write the new partition table. Show code.

Re: Partition table update on secure device

Posted: Fri Feb 25, 2022 12:59 pm
by erikha
The binairy of the partion table is embedded in the application binairy that's doing the partion table update. The code:

Code: Select all

extern const unsigned char partition_table_bin_start[] asm("_binary_partition_table_bin_start");
extern const unsigned char partition_table_bin_end[]   asm("_binary_partition_table_bin_end");
static const char *PARTITION_TABLE_UPDATE_TAG = "PartitionTableUpdate";

#define APPLIANCE_UPDATE_PARTITION_TYPE     0x40
#define APPLIANCE_UPDATE_PARTITION_NAME     "appliance_update"
#define PARTITION_TABLE_SECTOR_SIZE         0x1000
#define EXPECTED_PARTITION_TABLE_SIZE       (partition_table_bin_end - partition_table_bin_start)

bool PartitionTableIsUpdateNeeded(void)
{
    return (NULL == esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, NULL));
}

void PartitionTablePerformUpdate(void)
{
    ESP_LOGI(PARTITION_TABLE_UPDATE_TAG, "Updating Partition Table...");
    const esp_partition_t* pApplianceUpdatePartition = esp_partition_find_first(APPLIANCE_UPDATE_PARTITION_TYPE, ESP_PARTITION_SUBTYPE_ANY, APPLIANCE_UPDATE_PARTITION_NAME);
    isl_assert(pApplianceUpdatePartition);
    esp_partition_erase_range(pApplianceUpdatePartition, 0, pApplianceUpdatePartition->size);
    unsigned char* pBuffer = heap_caps_calloc(EXPECTED_PARTITION_TABLE_SIZE, sizeof(unsigned char), MALLOC_CAP_8BIT);
    isl_assert(pBuffer);
    esp_err_t flashOperationStatus = ESP_OK;
    do
    {
        if ((flashOperationStatus = esp_flash_erase_region(esp_flash_default_chip, ESP_PARTITION_TABLE_OFFSET, PARTITION_TABLE_SECTOR_SIZE)) != ESP_OK)
        {
            ESP_LOGE(PARTITION_TABLE_UPDATE_TAG, "esp_flash_erase_region failed with code %d", flashOperationStatus);
        }
        else if ((flashOperationStatus = esp_flash_write(esp_flash_default_chip, partition_table_bin_start, ESP_PARTITION_TABLE_OFFSET, EXPECTED_PARTITION_TABLE_SIZE)) != ESP_OK)
        {
            ESP_LOGE(PARTITION_TABLE_UPDATE_TAG, "esp_flash_write failed with code %d", flashOperationStatus);
        }
        else if ((flashOperationStatus = esp_flash_read(esp_flash_default_chip, pBuffer, ESP_PARTITION_TABLE_OFFSET, EXPECTED_PARTITION_TABLE_SIZE)) != ESP_OK)
        {
            ESP_LOGE(PARTITION_TABLE_UPDATE_TAG, "esp_flash_read failed with code %d", flashOperationStatus);
        }
    } while (memcmp(pBuffer, partition_table_bin_start, EXPECTED_PARTITION_TABLE_SIZE) != 0);
    heap_caps_free(pBuffer);
    ESP_LOGI(PARTITION_TABLE_UPDATE_TAG, "Partition Table Updated");
    esp_restart();
}

To be clear: this update process works perfect when secure boot and flash encrytion are NOT enabled.

Re: Partition table update on secure device

Posted: Fri Feb 25, 2022 4:31 pm
by WiFive
You have to use esp_flash_write_encrypted when encryption is on

Re: Partition table update on secure device

Posted: Fri Feb 25, 2022 6:08 pm
by erikha
Okay, thank you!

Is it also possible to use the esp_write_partition() function? If I understand the docs correctly, this function allows to write to both encrypted and unencrypted partitions.

Re: Partition table update on secure device

Posted: Fri Feb 25, 2022 6:11 pm
by erikha
And another question: is it possible to save the device that suffers the bootloop? or is it bricked?