From 5d99b0ff4e516865421839667f7ab9a6d1726b94 Mon Sep 17 00:00:00 2001 From: nuttxs Date: Wed, 19 Feb 2025 11:55:26 +0800 Subject: [PATCH] arch/esp32_partition: add some partition operation interfaces for esp32 Relocate the enum ota_img_ctrl_e and ota_img_bootseq_e to a directory visible to the application. Inspect if the MTD partition (factory/ota_0/ota_1) is mapped as text. Adding an ioctl interface ota_invalidate_bootseq() to the ESP32 partitions, by deleting the corresponding otadata, makes the boot sequence (ota_0/1) invalid. --- arch/xtensa/include/esp32/partition.h | 58 +++++++++++ arch/xtensa/src/esp32/esp32_partition.c | 126 +++++++++++++++++++----- arch/xtensa/src/esp32/esp32_spiflash.c | 22 +++++ arch/xtensa/src/esp32/esp32_spiflash.h | 16 +++ 4 files changed, 200 insertions(+), 22 deletions(-) create mode 100644 arch/xtensa/include/esp32/partition.h diff --git a/arch/xtensa/include/esp32/partition.h b/arch/xtensa/include/esp32/partition.h new file mode 100644 index 0000000000000..da9f53d0cfe8a --- /dev/null +++ b/arch/xtensa/include/esp32/partition.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * 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 +}; + +#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..94b94d1783529 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: { 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