Files
esp-idf/components/bootloader_support/src/bootloader_utility_tee.c

261 lines
9.8 KiB
C
Raw Normal View History

/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdint.h>
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_rom_sys.h"
#include "esp_rom_crc.h"
#include "hal/efuse_hal.h"
#include "esp_image_format.h"
#include "bootloader_config.h"
#include "bootloader_flash_priv.h"
#include "bootloader_utility.h"
#include "bootloader_utility_tee.h"
#include "esp_tee_ota_utils.h"
#include "sdkconfig.h"
static const char *TAG = "boot_tee";
static esp_err_t write_tee_otadata_sector(esp_tee_ota_select_entry_t *tee_otadata, uint32_t offset)
{
if (tee_otadata == NULL) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = bootloader_flash_erase_sector(offset / FLASH_SECTOR_SIZE);
if (err == ESP_OK) {
bool write_encrypted = false;
#if !CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
write_encrypted = efuse_hal_flash_encryption_enabled();
#endif
err = bootloader_flash_write(offset, tee_otadata, sizeof(esp_tee_ota_select_entry_t), write_encrypted);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to write otadata sector, 0x%x", err);
}
}
return err;
}
static esp_err_t read_tee_otadata(const esp_partition_pos_t *tee_ota_info, esp_tee_ota_select_entry_t *two_otadata)
{
if (tee_ota_info == NULL || two_otadata == NULL || tee_ota_info->offset == 0) {
return ESP_ERR_INVALID_ARG;
}
if (tee_ota_info->size < 2 * FLASH_SECTOR_SIZE) {
return ESP_ERR_INVALID_SIZE;
}
ESP_LOGV(TAG, "TEE OTA data offset 0x%"PRIx32, tee_ota_info->offset);
const esp_tee_ota_select_entry_t *ota_select_map = bootloader_mmap(tee_ota_info->offset, tee_ota_info->size);
if (!ota_select_map) {
ESP_LOGE(TAG, "bootloader_mmap(0x%"PRIx32", 0x%"PRIx32") failed", tee_ota_info->offset, tee_ota_info->size);
return ESP_FAIL;
}
memcpy(&two_otadata[0], (uint8_t *)ota_select_map, sizeof(esp_tee_ota_select_entry_t));
memcpy(&two_otadata[1], (uint8_t *)ota_select_map + FLASH_SECTOR_SIZE, sizeof(esp_tee_ota_select_entry_t));
bootloader_munmap(ota_select_map);
return ESP_OK;
}
static esp_err_t write_tee_otadata(esp_tee_ota_select_entry_t *tee_otadata, const esp_partition_pos_t *tee_ota_info)
{
esp_err_t err = write_tee_otadata_sector(tee_otadata, tee_ota_info->offset);
if (err == ESP_OK) {
err = write_tee_otadata_sector(tee_otadata, tee_ota_info->offset + FLASH_SECTOR_SIZE);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to update otadata sector, 0x%x", err);
}
}
return err;
}
static esp_err_t get_valid_tee_otadata(const esp_partition_pos_t *tee_ota_info, esp_tee_ota_select_entry_t *tee_otadata)
{
esp_tee_ota_select_entry_t two_otadata[2] = {0};
if (read_tee_otadata(tee_ota_info, two_otadata) != ESP_OK) {
return ESP_ERR_NOT_FOUND;
}
esp_tee_ota_select_entry_t blank_otadata;
memset(&blank_otadata, 0xff, sizeof(esp_tee_ota_select_entry_t));
// Check if the contents of both the otadata sectors match
bool sectors_match = (memcmp(&two_otadata[0], &two_otadata[1], sizeof(esp_tee_ota_select_entry_t)) == 0);
if (sectors_match) {
if (memcmp(&two_otadata[0], &blank_otadata, sizeof(esp_tee_ota_select_entry_t)) != 0) {
uint32_t crc = esp_rom_crc32_le(0, (uint8_t const *)two_otadata, (sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t)));
if (two_otadata[0].magic != TEE_OTADATA_MAGIC || crc != two_otadata[0].crc) {
ESP_LOGE(TAG, "TEE otadata[0] magic or CRC verification failed");
return ESP_FAIL;
}
}
memcpy(tee_otadata, &two_otadata[0], sizeof(esp_tee_ota_select_entry_t));
ESP_LOGV(TAG, "Both tee_otadata sectors are the same");
} else {
uint32_t crc_otadata0 = esp_rom_crc32_le(0, (uint8_t const *)&two_otadata[0], (sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t)));
uint32_t crc_otadata1 = esp_rom_crc32_le(0, (uint8_t const *)&two_otadata[1], (sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t)));
if (crc_otadata0 == two_otadata[0].crc) {
ESP_LOGV(TAG, "Second tee_otadata sector is invalid - copying contents from first sector");
// Copy contents of first tee_otadata sector into second
write_tee_otadata_sector(&two_otadata[0], tee_ota_info->offset + FLASH_SECTOR_SIZE);
memcpy(tee_otadata, &two_otadata[0], sizeof(esp_tee_ota_select_entry_t));
} else if (crc_otadata1 == two_otadata[1].crc) {
ESP_LOGV(TAG, "First tee_otadata sector is invalid - copying contents from second sector");
// Copy contents of second tee_otadata sector into first
write_tee_otadata_sector(&two_otadata[1], tee_ota_info->offset);
memcpy(tee_otadata, &two_otadata[1], sizeof(esp_tee_ota_select_entry_t));
} else {
ESP_LOGE(TAG, "Both tee_otadata sectors are invalid!");
abort();
}
}
return ESP_OK;
}
static esp_err_t update_tee_otadata(const esp_partition_pos_t *tee_ota_info, uint8_t boot_partition, uint8_t ota_state)
{
esp_tee_ota_select_entry_t otadata = {
.magic = TEE_OTADATA_MAGIC,
.boot_partition = boot_partition,
.ota_state = ota_state,
};
otadata.crc = esp_rom_crc32_le(0, (uint8_t const *)&otadata, (sizeof(esp_tee_ota_select_entry_t) - sizeof(uint32_t)));
return write_tee_otadata(&otadata, tee_ota_info);
}
int bootloader_utility_tee_get_boot_partition(const esp_partition_pos_t *tee_ota_info)
{
esp_tee_ota_select_entry_t otadata = {}, blank_otadata;
const int default_tee_app_slot = PART_SUBTYPE_TEE_0;
esp_err_t err = get_valid_tee_otadata(tee_ota_info, &otadata);
if (err == ESP_ERR_NOT_FOUND) {
ESP_LOGV(TAG, "otadata partition not found, booting from first partition");
return default_tee_app_slot;
}
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to get valid otadata, 0x%x", err);
return -1;
}
memset(&blank_otadata, 0xff, sizeof(esp_tee_ota_select_entry_t));
if (!memcmp(&blank_otadata, &otadata, sizeof(esp_tee_ota_select_entry_t))) {
ESP_LOGV(TAG, "otadata partition empty, booting from first partition");
/* NOTE: The first TEE partition will always be valid as it is flashed manually */
if (update_tee_otadata(tee_ota_info, default_tee_app_slot, ESP_TEE_OTA_IMG_VALID) != ESP_OK) {
ESP_LOGW(TAG, "Failed to setup TEE otadata as per the first partition!");
}
return default_tee_app_slot;
}
int boot_partition = 0;
#if BOOTLOADER_BUILD
switch(otadata.ota_state) {
case ESP_TEE_OTA_IMG_NEW:
ESP_LOGD(TAG, "TEE otadata - Current image state: NEW");
boot_partition = otadata.boot_partition;
if (update_tee_otadata(tee_ota_info, otadata.boot_partition, ESP_TEE_OTA_IMG_PENDING_VERIFY) != ESP_OK) {
return -1;
}
break;
case ESP_TEE_OTA_IMG_UNDEFINED:
case ESP_TEE_OTA_IMG_PENDING_VERIFY:
ESP_LOGD(TAG, "TEE otadata - Current image state: PENDING_VERIFY/UNDEFINED");
boot_partition = (otadata.boot_partition == PART_SUBTYPE_TEE_0) ? PART_SUBTYPE_TEE_1 : PART_SUBTYPE_TEE_0;
if (update_tee_otadata(tee_ota_info, boot_partition, ESP_TEE_OTA_IMG_INVALID) != ESP_OK) {
return -1;
}
break;
case ESP_TEE_OTA_IMG_INVALID:
ESP_LOGD(TAG, "TEE otadata - Current image state: INVALID");
bootloader_reset();
break;
case ESP_TEE_OTA_IMG_VALID:
ESP_LOGD(TAG, "TEE otadata - Current image state: VALID");
boot_partition = otadata.boot_partition;
break;
break;
default:
break;
}
#else
boot_partition = otadata.boot_partition;
#endif
return boot_partition;
}
esp_err_t bootloader_utility_tee_set_boot_partition(const esp_partition_pos_t *tee_ota_info, const esp_partition_info_t *tee_try_part)
{
if (tee_ota_info == NULL || tee_try_part == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (tee_try_part->subtype != PART_SUBTYPE_TEE_0 && tee_try_part->subtype != PART_SUBTYPE_TEE_1) {
return ESP_ERR_INVALID_ARG;
}
esp_image_metadata_t data = {};
if (esp_image_verify(ESP_IMAGE_VERIFY, &tee_try_part->pos, &data) != ESP_OK) {
return ESP_ERR_IMAGE_INVALID;
}
return update_tee_otadata(tee_ota_info, tee_try_part->subtype, ESP_TEE_OTA_IMG_NEW);
}
int bootloader_utility_tee_get_next_update_partition(const esp_partition_pos_t *tee_ota_info)
{
esp_tee_ota_select_entry_t otadata = {}, blank_otadata;
const int default_tee_next_app_slot = PART_SUBTYPE_TEE_1;
esp_err_t err = get_valid_tee_otadata(tee_ota_info, &otadata);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to get valid otadata, 0x%x", err);
return -1;
}
memset(&blank_otadata, 0xff, sizeof(esp_tee_ota_select_entry_t));
if (!memcmp(&blank_otadata, &otadata, sizeof(esp_tee_ota_select_entry_t))) {
return default_tee_next_app_slot;
}
return (otadata.boot_partition == PART_SUBTYPE_TEE_0) ? PART_SUBTYPE_TEE_1 : PART_SUBTYPE_TEE_0;
}
esp_err_t bootloader_utility_tee_mark_app_valid_and_cancel_rollback(const esp_partition_pos_t *tee_ota_info)
{
esp_tee_ota_select_entry_t two_otadata[2];
esp_err_t err = read_tee_otadata(tee_ota_info, two_otadata);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch TEE otadata!");
return err;
}
if (two_otadata[0].ota_state == ESP_TEE_OTA_IMG_VALID) {
ESP_LOGD(TAG, "TEE otadata - Current image already has been marked VALID");
return ESP_ERR_INVALID_STATE;
}
int tee_app_slot = bootloader_utility_tee_get_boot_partition(tee_ota_info);
return update_tee_otadata(tee_ota_info, (uint8_t)tee_app_slot, ESP_TEE_OTA_IMG_VALID);
}