mirror of
https://github.com/apache/nuttx.git
synced 2026-08-26 20:00:42 +00:00
xtensa/esp32: Implement board_boot_image for mcuboot/nxboot support
This commit adds the board_boot_image() implementation for ESP32, enabling support for MCUboot and nxboot bootloaders. It includes parsing the image header and setting up the necessary MMU mappings. Signed-off-by: Aviral Garg <aviral.garg.2023@gmail.com>
This commit is contained in:
parent
e83606732d
commit
ac40b2129f
4 changed files with 620 additions and 503 deletions
|
|
@ -33,8 +33,7 @@
|
|||
|
||||
/* OTA image operation code */
|
||||
|
||||
enum ota_img_ctrl
|
||||
{
|
||||
enum ota_img_ctrl {
|
||||
OTA_IMG_GET_BOOT = 0xe1,
|
||||
OTA_IMG_SET_BOOT = 0xe2,
|
||||
OTA_IMG_SET_ENCRYPTED = 0xe3,
|
||||
|
|
@ -43,15 +42,15 @@ enum ota_img_ctrl
|
|||
OTA_IMG_GET_SUBTYPE = 0xe6,
|
||||
OTA_IMG_INVALIDATE_BOOT = 0xe7,
|
||||
OTA_IMG_IS_MAPPED_AS_TEXT = 0xe8,
|
||||
OTA_IMG_GET_OFFSET = 0xe9,
|
||||
};
|
||||
|
||||
/* 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,
|
||||
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
|
||||
};
|
||||
|
||||
|
|
@ -72,7 +71,7 @@ enum ota_img_bootseq
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32_partition_read_decrypt(const char *label, size_t offset,
|
||||
void *buf, size_t size);
|
||||
int esp32_partition_read_decrypt(const char *label, size_t offset, void *buf,
|
||||
size_t size);
|
||||
|
||||
#endif /* __ARCH_XTENSA_INCLUDE_ESP32_PARTITION_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -178,6 +178,8 @@ ifeq ($(CONFIG_ETC_ROMFS),y)
|
|||
RCSRCS = etc/init.d/rc.sysinit etc/init.d/rcS
|
||||
endif
|
||||
|
||||
CSRCS += esp32_boot_image.c
|
||||
|
||||
DEPPATH += --dep-path src
|
||||
VPATH += :src
|
||||
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)src
|
||||
|
|
|
|||
230
boards/xtensa/esp32/common/src/esp32_boot_image.c
Normal file
230
boards/xtensa/esp32/common/src/esp32_boot_image.c
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/****************************************************************************
|
||||
* boards/xtensa/esp32/common/src/esp32_boot_image.c
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <debug.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <arch/esp32/partition.h>
|
||||
#include <nuttx/board.h>
|
||||
#include <nuttx/cache.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "esp_app_format.h"
|
||||
#include "esp_loader.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define ESP32_APP_IMAGE_MAGIC 0xE9
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct esp32_boot_loader_args_s {
|
||||
uint32_t entry_addr;
|
||||
uint32_t drom_addr;
|
||||
uint32_t drom_vaddr;
|
||||
uint32_t drom_size;
|
||||
uint32_t irom_addr;
|
||||
uint32_t irom_vaddr;
|
||||
uint32_t irom_size;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void IRAM_ATTR esp32_boot_loader_stub(void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32_boot_loader_stub
|
||||
*
|
||||
* Description:
|
||||
* This function resides in IRAM and is responsible for switching MMU
|
||||
* mappings and jumping to the new application.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void IRAM_ATTR esp32_boot_loader_stub(void *arg) {
|
||||
struct esp32_boot_loader_args_s *args =
|
||||
(struct esp32_boot_loader_args_s *)arg;
|
||||
void (*entry_point)(void) = (void (*)(void))args->entry_addr;
|
||||
|
||||
/* Disable interrupts */
|
||||
|
||||
up_irq_disable();
|
||||
|
||||
/* Disable cache */
|
||||
|
||||
#ifdef CONFIG_ARCH_CHIP_ESP32
|
||||
cache_read_disable(0);
|
||||
cache_flush(0);
|
||||
#else
|
||||
cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL);
|
||||
#endif
|
||||
|
||||
/* Map new segments */
|
||||
|
||||
map_rom_segments(args->drom_addr, args->drom_vaddr, args->drom_size,
|
||||
args->irom_addr, args->irom_vaddr, args->irom_size);
|
||||
|
||||
/* Jump to entry point */
|
||||
|
||||
entry_point();
|
||||
|
||||
/* Should never reach here */
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: board_boot_image
|
||||
*
|
||||
* Description:
|
||||
* Boot a new application image.
|
||||
*
|
||||
* Input Parameters:
|
||||
* path - Path to the image file/partition
|
||||
* hdr_size - Size of the image header (unused for ESP32)
|
||||
*
|
||||
* Returned Value:
|
||||
* Does not return on success; returns error code on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int board_boot_image(FAR const char *path, uint32_t hdr_size) {
|
||||
int fd;
|
||||
int ret;
|
||||
uint32_t offset;
|
||||
esp_image_header_t image_header;
|
||||
esp_image_segment_header_t segment_hdr;
|
||||
struct esp32_boot_loader_args_s args = {0};
|
||||
uint32_t current_offset;
|
||||
int i;
|
||||
|
||||
/* Check for legacy format (not supported) */
|
||||
|
||||
#ifdef CONFIG_ESP32_APP_FORMAT_LEGACY
|
||||
ferr("ERROR: Legacy format not supported for board_boot_image\n");
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
|
||||
/* Open the image file */
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ferr("ERROR: Failed to open %s: %d\n", path, errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* Get partition offset */
|
||||
|
||||
ret = ioctl(fd, OTA_IMG_GET_OFFSET, (unsigned long)&offset);
|
||||
if (ret < 0) {
|
||||
ferr("ERROR: Failed to get partition offset: %d\n", errno);
|
||||
close(fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* Read image header */
|
||||
|
||||
ret = read(fd, &image_header, sizeof(esp_image_header_t));
|
||||
if (ret != sizeof(esp_image_header_t)) {
|
||||
ferr("ERROR: Failed to read image header: %d\n", errno);
|
||||
close(fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (image_header.magic != ESP32_APP_IMAGE_MAGIC) {
|
||||
ferr("ERROR: Invalid image magic: 0x%02x\n", image_header.magic);
|
||||
close(fd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
args.entry_addr = image_header.entry_addr;
|
||||
current_offset = sizeof(esp_image_header_t);
|
||||
|
||||
/* Parse segments */
|
||||
|
||||
for (i = 0; i < image_header.segment_count; i++) {
|
||||
ret = read(fd, &segment_hdr, sizeof(esp_image_segment_header_t));
|
||||
if (ret != sizeof(esp_image_segment_header_t)) {
|
||||
ferr("ERROR: Failed to read segment header: %d\n", errno);
|
||||
close(fd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* Check for IROM/DROM segments */
|
||||
|
||||
if (segment_hdr.load_addr >= 0x3f400000 &&
|
||||
segment_hdr.load_addr < 0x3f800000) /* DROM */
|
||||
{
|
||||
args.drom_addr =
|
||||
offset + current_offset + sizeof(esp_image_segment_header_t);
|
||||
args.drom_vaddr = segment_hdr.load_addr;
|
||||
args.drom_size = segment_hdr.data_len;
|
||||
} else if (segment_hdr.load_addr >= 0x400d0000 &&
|
||||
segment_hdr.load_addr < 0x40400000) /* IROM */
|
||||
{
|
||||
args.irom_addr =
|
||||
offset + current_offset + sizeof(esp_image_segment_header_t);
|
||||
args.irom_vaddr = segment_hdr.load_addr;
|
||||
args.irom_size = segment_hdr.data_len;
|
||||
}
|
||||
|
||||
current_offset += sizeof(esp_image_segment_header_t) + segment_hdr.data_len;
|
||||
|
||||
/* Advance file pointer to next segment */
|
||||
|
||||
lseek(fd, segment_hdr.data_len, SEEK_CUR);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
finfo("Booting image: entry=0x%08" PRIx32 ", drom=0x%08" PRIx32
|
||||
" (0x%08" PRIx32 "), irom=0x%08" PRIx32 " (0x%08" PRIx32 ")\n",
|
||||
args.entry_addr, args.drom_vaddr, args.drom_size, args.irom_vaddr,
|
||||
args.irom_size);
|
||||
|
||||
/* Invoke IRAM loader stub */
|
||||
|
||||
esp32_boot_loader_stub(&args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue