diff --git a/arch/xtensa/include/esp32/partition.h b/arch/xtensa/include/esp32/partition.h new file mode 100644 index 0000000000000..20a8c21bb061a --- /dev/null +++ b/arch/xtensa/include/esp32/partition.h @@ -0,0 +1,78 @@ +/**************************************************************************** + * arch/xtensa/include/esp32/partition.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_XTENSA_INCLUDE_ESP32_PARTITION_H +#define __ARCH_XTENSA_INCLUDE_ESP32_PARTITION_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* OTA image operation code */ + +enum ota_img_ctrl +{ + OTA_IMG_GET_BOOT = 0xe1, + OTA_IMG_SET_BOOT = 0xe2, + OTA_IMG_SET_ENCRYPTED = 0xe3, + OTA_IMG_GET_ENCRYPTED = 0xe4, + OTA_IMG_GET_TYPE = 0xe5, + OTA_IMG_GET_SUBTYPE = 0xe6, + OTA_IMG_INVALIDATE_BOOT = 0xe7, + OTA_IMG_IS_MAPPED_AS_TEXT = 0xe8, +}; + +/* OTA image boot sequency */ + +enum ota_img_bootseq +{ + OTA_IMG_BOOT_FACTORY = 0, + OTA_IMG_BOOT_OTA_0 = 1, + OTA_IMG_BOOT_OTA_1 = 2, + OTA_IMG_BOOT_SEQ_MAX +}; + +/**************************************************************************** + * Name: esp32_partition_read_decrypt + * + * Description: + * Read data from SPI Flash at designated address. (with decryption) + * + * Input Parameters: + * label - Partition label + * offset - Offset in SPI Flash + * buf - Data buffer pointer + * size - Data number + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +int esp32_partition_read_decrypt(const char *label, size_t offset, + void *buf, size_t size); + +#endif /* __ARCH_XTENSA_INCLUDE_ESP32_PARTITION_H */ diff --git a/arch/xtensa/src/esp32/esp32_partition.c b/arch/xtensa/src/esp32/esp32_partition.c index d8fe975888de7..397eba66adc99 100644 --- a/arch/xtensa/src/esp32/esp32_partition.c +++ b/arch/xtensa/src/esp32/esp32_partition.c @@ -35,6 +35,7 @@ #include "esp32_spiflash.h" #include "esp32_partition.h" +#include "arch/esp32/partition.h" /**************************************************************************** * Pre-processor Definitions @@ -86,18 +87,6 @@ * Private Types ****************************************************************************/ -/* OTA image operation code */ - -enum ota_img_ctrl -{ - OTA_IMG_GET_BOOT = 0xe1, - OTA_IMG_SET_BOOT = 0xe2, - OTA_IMG_SET_ENCRYPTED = 0xe3, - OTA_IMG_GET_ENCRYPTED = 0xe4, - OTA_IMG_GET_TYPE = 0xe5, - OTA_IMG_GET_SUBTYPE = 0xe6 -}; - /* OTA image state */ enum ota_img_state @@ -143,16 +132,6 @@ enum ota_img_state OTA_IMG_UNDEFINED = 0xffffffff, }; -/* OTA image boot sequency */ - -enum ota_img_bootseq -{ - OTA_IMG_BOOT_FACTORY = 0, - OTA_IMG_BOOT_OTA_0 = 1, - OTA_IMG_BOOT_OTA_1 = 2, - OTA_IMG_BOOT_SEQ_MAX -}; - /* Partition information data */ struct partition_info_priv @@ -346,6 +325,12 @@ static int ota_set_bootseq(struct mtd_dev_priv *dev, int num) ferr("ERROR: Failed to get boot sequence error=%d\n", ret); return ret; } + else if (ret == num) + { + /* the requested num is already set as next boot partition */ + + return OK; + } else if (ret == OTA_IMG_BOOT_FACTORY) { next_seq = 1; @@ -419,6 +404,81 @@ static int ota_set_bootseq(struct mtd_dev_priv *dev, int num) return OK; } +/**************************************************************************** + * Name: ota_invalidate_bootseq + * + * Description: + * Invalidate boot sequence by deleting the corresponding otadata + * + * Input Parameters: + * dev - Partition private MTD data + * num - boot sequence buffer + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +static int ota_invalidate_bootseq(struct mtd_dev_priv *dev, int num) +{ + int ret; + uint32_t sec; + finfo("INFO: num=%d\n", num); + switch (num) + { + case OTA_IMG_BOOT_OTA_0: + case OTA_IMG_BOOT_OTA_1: + sec = num - OTA_IMG_BOOT_OTA_0; + ret = MTD_ERASE(dev->mtd_part, sec, 1); + if (ret != 1) + { + ferr("ERROR: Failed to erase OTA%d data error=%d\n", sec, ret); + return -EIO; + } + + break; + default: + ferr("ERROR: num=%d is error\n", num); + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Name: is_currently_mapped_as_text + * + * Description: + * Check if the MTD partition is mapped as text + * + * Input Parameters: + * dev - Partition private MTD data + * mapped - true if mapped, false if not + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +static int is_currently_mapped_as_text(struct mtd_dev_priv *dev, + bool *mapped) +{ + uint32_t currently_mapped_address; + + if (mapped == NULL) + { + ferr("ERROR: Invalid argument.\n"); + return -EINVAL; + } + + currently_mapped_address = esp32_get_flash_address_mapped_as_text(); + + *mapped = ((dev->offset <= currently_mapped_address) && + (currently_mapped_address < dev->offset + dev->size)); + + return OK; +} + /**************************************************************************** * Name: esp32_part_erase * @@ -621,6 +681,28 @@ static int esp32_part_ioctl(struct mtd_dev_s *dev, int cmd, break; case OTA_IMG_GET_SUBTYPE: *(int *)arg = mtd_priv->subtype; + break; + case OTA_IMG_INVALIDATE_BOOT: + { + ret = ota_invalidate_bootseq(mtd_priv, arg); + if (ret < 0) + { + ferr("ERROR: Failed to invalidate boot img\n"); + } + } + + break; + case OTA_IMG_IS_MAPPED_AS_TEXT: + { + bool *mapped = (bool *)arg; + + ret = is_currently_mapped_as_text(mtd_priv, mapped); + if (ret < 0) + { + ferr("ERROR: Failed to check partition is mapped as text\n"); + } + } + break; default: { @@ -956,6 +1038,56 @@ int esp32_partition_read(const char *label, size_t offset, void *buf, return OK; } +/**************************************************************************** + * Name: esp32_partition_read_decrypt + * + * Description: + * Read data from SPI Flash at designated address. (with decryption) + * + * Input Parameters: + * label - Partition label + * offset - Offset in SPI Flash + * buf - Data buffer pointer + * size - Data number + * + * Returned Value: + * 0 if success or a negative value if fail. + * + ****************************************************************************/ + +int esp32_partition_read_decrypt(const char *label, size_t offset, void *buf, + size_t size) +{ + int ret; + int partion_offset; + DEBUGASSERT(label != NULL && buf != NULL); + struct mtd_dev_s *mtd; + + partion_offset = partition_get_offset(label, strlen(label)); + if (partion_offset < 0) + { + ferr("ERROR: Failed to get partition: %s offset\n", label); + return partion_offset; + } + + mtd = esp32_spiflash_encrypt_get_mtd(); + if (!mtd) + { + ferr("ERROR: Failed to get SPI flash MTD\n"); + return -ENOSYS; + } + + ret = MTD_READ(mtd, partion_offset + offset, + size, (uint8_t *)buf); + if (ret != size) + { + ferr("ERROR: Failed to get read data from MTD\n"); + return -EIO; + } + + return OK; +} + /**************************************************************************** * Name: esp32_partition_write * diff --git a/arch/xtensa/src/esp32/esp32_spiflash.c b/arch/xtensa/src/esp32/esp32_spiflash.c index 8b8b563eb7d62..d5caa16d9bf63 100644 --- a/arch/xtensa/src/esp32/esp32_spiflash.c +++ b/arch/xtensa/src/esp32/esp32_spiflash.c @@ -2757,4 +2757,26 @@ bool esp32_flash_encryption_enabled(void) return enabled; } +/**************************************************************************** + * Name: esp32_get_flash_address_mapped_as_text + * + * Description: + * Get flash address which is currently mapped as text + * + * Input Parameters: + * None + * + * Returned Value: + * flash address which is currently mapped as text + * + ****************************************************************************/ + +uint32_t esp32_get_flash_address_mapped_as_text(void) +{ + uint32_t i = MMU_ADDR2PAGE((uint32_t)&_stext - SOC_IROM_MASK_LOW) + + IROM0_PAGES_START; + return (PRO_MMU_TABLE[i] & DPORT_MMU_ADDRESS_MASK) + * SPI_FLASH_MMU_PAGE_SIZE; +} + #endif /* CONFIG_ESP32_SPIFLASH */ diff --git a/arch/xtensa/src/esp32/esp32_spiflash.h b/arch/xtensa/src/esp32/esp32_spiflash.h index a885294a8d4e7..67e9dbe2e8782 100644 --- a/arch/xtensa/src/esp32/esp32_spiflash.h +++ b/arch/xtensa/src/esp32/esp32_spiflash.h @@ -158,6 +158,22 @@ struct mtd_dev_s *esp32_spiflash_encrypt_get_mtd(void); bool esp32_flash_encryption_enabled(void); +/**************************************************************************** + * Name: esp32_get_flash_address_mapped_as_text + * + * Description: + * Get flash address which is currently mapped as text + * + * Input Parameters: + * None + * + * Returned Value: + * flash address which is currently mapped as text + * + ****************************************************************************/ + +uint32_t esp32_get_flash_address_mapped_as_text(void); + #ifdef __cplusplus } #endif