1 /*
2  * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <soc.h>
9 #include <zephyr/storage/flash_map.h>
10 #include <esp_log.h>
11 #include <stdlib.h>
12 
13 #include <esp32s3/rom/cache.h>
14 #include "esp32s3/dport_access.h"
15 #include "soc/cache_memory.h"
16 #include <soc/dport_reg.h>
17 #include "soc/extmem_reg.h"
18 #include <bootloader_flash_priv.h>
19 
20 #ifdef CONFIG_BOOTLOADER_MCUBOOT
21 
22 #define BOOT_LOG_INF(_fmt, ...) \
23 	ets_printf("[" CONFIG_SOC_SERIES "] [INF] " _fmt "\n\r", ##__VA_ARGS__)
24 
25 #define HDR_ATTR __attribute__((section(".entry_addr"))) __attribute__((used))
26 
27 extern uint32_t _image_irom_start, _image_irom_size, _image_irom_vaddr;
28 extern uint32_t _image_drom_start, _image_drom_size, _image_drom_vaddr;
29 
30 void __start(void);
31 
32 static HDR_ATTR void (*_entry_point)(void) = &__start;
33 
map_rom_segments(void)34 static int map_rom_segments(void)
35 {
36 	int rc = 0;
37 	size_t _partition_offset = FIXED_PARTITION_OFFSET(slot0_partition);
38 	uint32_t _app_irom_start = _partition_offset + (uint32_t)&_image_irom_start;
39 	uint32_t _app_irom_size = (uint32_t)&_image_irom_size;
40 	uint32_t _app_irom_vaddr = (uint32_t)&_image_irom_vaddr;
41 
42 	uint32_t _app_drom_start = _partition_offset + (uint32_t)&_image_drom_start;
43 	uint32_t _app_drom_size = (uint32_t)&_image_drom_size;
44 	uint32_t _app_drom_vaddr = (uint32_t)&_image_drom_vaddr;
45 
46 	uint32_t autoload = Cache_Suspend_DCache();
47 
48 	Cache_Invalidate_DCache_All();
49 
50 	/* Clear the MMU entries that are already set up,
51 	 * so the new app only has the mappings it creates.
52 	 */
53 	for (size_t i = 0; i < FLASH_MMU_TABLE_SIZE; i++) {
54 		FLASH_MMU_TABLE[i] = MMU_TABLE_INVALID_VAL;
55 	}
56 
57 	uint32_t drom_page_count = bootloader_cache_pages_to_map(_app_drom_size, _app_drom_vaddr);
58 
59 	rc |= esp_rom_Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH,
60 				_app_drom_vaddr & MMU_FLASH_MASK,
61 				_app_drom_start & MMU_FLASH_MASK,
62 				64, drom_page_count, 0);
63 
64 	uint32_t irom_page_count = bootloader_cache_pages_to_map(_app_irom_size, _app_irom_vaddr);
65 
66 	rc |= esp_rom_Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH,
67 				_app_irom_vaddr & MMU_FLASH_MASK,
68 				_app_irom_start & MMU_FLASH_MASK,
69 				64, irom_page_count, 0);
70 
71 	REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS);
72 	REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS);
73 
74 	Cache_Resume_DCache(autoload);
75 
76 	/* Show map segments continue using same log format as during MCUboot phase */
77 	BOOT_LOG_INF("DROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map",
78 		_app_drom_start, _app_drom_vaddr, _app_drom_size, _app_drom_size);
79 	BOOT_LOG_INF("IROM segment: paddr=%08Xh, vaddr=%08Xh, size=%05Xh (%6d) map\r\n",
80 		_app_irom_start, _app_irom_vaddr, _app_irom_size, _app_irom_size);
81 	esp_rom_uart_tx_wait_idle(0);
82 
83 	return rc;
84 }
85 #endif /* CONFIG_BOOTLOADER_MCUBOOT */
86 
__start(void)87 void __start(void)
88 {
89 #ifdef CONFIG_BOOTLOADER_MCUBOOT
90 	int err = map_rom_segments();
91 
92 	if (err != 0) {
93 		ets_printf("Failed to setup XIP, aborting\n");
94 		abort();
95 	}
96 #endif
97 	__esp_platform_start();
98 }
99