blob: 72225848bc5f9fbe04c12697294cb72eb6fb3ce7 [file] [log] [blame]
Yann Gautier4b0c72a2018-07-16 10:54:09 +02001/*
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +01002 * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
Yann Gautier4b0c72a2018-07-16 10:54:09 +02003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Yann Gautier4b0c72a2018-07-16 10:54:09 +02007#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008#include <string.h>
9
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <arch_helpers.h>
11#include <common/debug.h>
Yann Gautiera3bd8d12021-06-18 11:33:26 +020012#include <common/desc_image_load.h>
Sughosh Ganub721f8a2021-12-01 16:45:11 +053013#include <drivers/fwu/fwu.h>
14#include <drivers/fwu/fwu_metadata.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000015#include <drivers/io/io_block.h>
16#include <drivers/io/io_driver.h>
Yann Gautier0ed7b2a2021-05-19 18:48:16 +020017#include <drivers/io/io_fip.h>
Patrick Delaunay9c5ee782021-07-06 14:07:56 +020018#include <drivers/io/io_memmap.h>
Lionel Debieve402a46b2019-11-04 12:28:15 +010019#include <drivers/io/io_mtd.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000020#include <drivers/io/io_storage.h>
21#include <drivers/mmc.h>
Sughosh Ganub721f8a2021-12-01 16:45:11 +053022#include <drivers/partition/efi.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000023#include <drivers/partition/partition.h>
Lionel Debieve402a46b2019-11-04 12:28:15 +010024#include <drivers/raw_nand.h>
Lionel Debieve186b0462019-09-24 18:30:12 +020025#include <drivers/spi_nand.h>
Lionel Debievecb0dbc42019-09-25 09:11:31 +020026#include <drivers/spi_nor.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000027#include <drivers/st/io_mmc.h>
Lionel Debieve402a46b2019-11-04 12:28:15 +010028#include <drivers/st/stm32_fmc2_nand.h>
Lionel Debieve186b0462019-09-24 18:30:12 +020029#include <drivers/st/stm32_qspi.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000030#include <drivers/st/stm32_sdmmc2.h>
Patrick Delaunay9c5ee782021-07-06 14:07:56 +020031#include <drivers/usb_device.h>
Yann Gautier29f1f942021-07-13 18:07:41 +020032#include <lib/fconf/fconf.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000033#include <lib/mmio.h>
34#include <lib/utils.h>
35#include <plat/common/platform.h>
Yann Gautier0ed7b2a2021-05-19 18:48:16 +020036#include <tools_share/firmware_image_package.h>
37
38#include <platform_def.h>
Patrick Delaunay9c5ee782021-07-06 14:07:56 +020039#include <stm32cubeprogrammer.h>
Lionel Debieve5e111c52022-02-24 18:58:46 +010040#include <stm32mp_efi.h>
Yann Gautier29f1f942021-07-13 18:07:41 +020041#include <stm32mp_fconf_getter.h>
Yann Gautier8636a5f2022-05-06 15:27:32 +020042#include <stm32mp_io_storage.h>
Patrick Delaunay9c5ee782021-07-06 14:07:56 +020043#include <usb_dfu.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000044
Yann Gautier4b0c72a2018-07-16 10:54:09 +020045/* IO devices */
Yann Gautier0ed7b2a2021-05-19 18:48:16 +020046uintptr_t fip_dev_handle;
47uintptr_t storage_dev_handle;
Yann Gautier4b0c72a2018-07-16 10:54:09 +020048
Yann Gautier0ed7b2a2021-05-19 18:48:16 +020049static const io_dev_connector_t *fip_dev_con;
Yann Gautier8244e1d2018-10-15 09:36:58 +020050
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +020051#if STM32MP_SDMMC || STM32MP_EMMC
Yann Gautierac22dd52021-03-22 14:22:14 +010052static struct mmc_device_info mmc_info;
Yann Gautier8244e1d2018-10-15 09:36:58 +020053
Yann Gautierf9af3bc2018-11-09 15:57:18 +010054static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
Yann Gautier8244e1d2018-10-15 09:36:58 +020055
Yann Gautiera3bd8d12021-06-18 11:33:26 +020056static io_block_dev_spec_t mmc_block_dev_spec = {
Yann Gautier8244e1d2018-10-15 09:36:58 +020057 /* It's used as temp buffer in block driver */
58 .buffer = {
59 .offset = (size_t)&block_buffer,
60 .length = MMC_BLOCK_SIZE,
61 },
62 .ops = {
63 .read = mmc_read_blocks,
64 .write = NULL,
65 },
66 .block_size = MMC_BLOCK_SIZE,
67};
Vyacheslav Yurkove43a0802021-06-04 10:10:51 +020068
Yann Gautier8244e1d2018-10-15 09:36:58 +020069static const io_dev_connector_t *mmc_dev_con;
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +020070#endif /* STM32MP_SDMMC || STM32MP_EMMC */
Yann Gautier8244e1d2018-10-15 09:36:58 +020071
Lionel Debievecb0dbc42019-09-25 09:11:31 +020072#if STM32MP_SPI_NOR
73static io_mtd_dev_spec_t spi_nor_dev_spec = {
74 .ops = {
75 .init = spi_nor_init,
76 .read = spi_nor_read,
77 },
78};
79#endif
80
Lionel Debieve402a46b2019-11-04 12:28:15 +010081#if STM32MP_RAW_NAND
82static io_mtd_dev_spec_t nand_dev_spec = {
83 .ops = {
84 .init = nand_raw_init,
85 .read = nand_read,
Yann Gautier0ed7b2a2021-05-19 18:48:16 +020086 .seek = nand_seek_bb
Lionel Debieve402a46b2019-11-04 12:28:15 +010087 },
88};
89
90static const io_dev_connector_t *nand_dev_con;
91#endif
92
Lionel Debieve186b0462019-09-24 18:30:12 +020093#if STM32MP_SPI_NAND
94static io_mtd_dev_spec_t spi_nand_dev_spec = {
95 .ops = {
96 .init = spi_nand_init,
97 .read = nand_read,
Yann Gautier0ed7b2a2021-05-19 18:48:16 +020098 .seek = nand_seek_bb
Lionel Debieve186b0462019-09-24 18:30:12 +020099 },
100};
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200101#endif
Lionel Debieve186b0462019-09-24 18:30:12 +0200102
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200103#if STM32MP_SPI_NAND || STM32MP_SPI_NOR
Lionel Debieve186b0462019-09-24 18:30:12 +0200104static const io_dev_connector_t *spi_dev_con;
105#endif
106
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200107#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200108static const io_dev_connector_t *memmap_dev_con;
109#endif
110
Yann Gautier29f1f942021-07-13 18:07:41 +0200111io_block_spec_t image_block_spec = {
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200112 .offset = 0U,
113 .length = 0U,
114};
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200115
Yann Gautier29f1f942021-07-13 18:07:41 +0200116int open_fip(const uintptr_t spec)
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200117{
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200118 return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200119}
Yann Gautier8244e1d2018-10-15 09:36:58 +0200120
Yann Gautier29f1f942021-07-13 18:07:41 +0200121int open_storage(const uintptr_t spec)
Yann Gautier8244e1d2018-10-15 09:36:58 +0200122{
123 return io_dev_init(storage_dev_handle, 0);
124}
Vyacheslav Yurkove43a0802021-06-04 10:10:51 +0200125
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200126#if STM32MP_EMMC_BOOT
127static uint32_t get_boot_part_fip_header(void)
128{
129 io_block_spec_t emmc_boot_fip_block_spec = {
130 .offset = STM32MP_EMMC_BOOT_FIP_OFFSET,
131 .length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
132 };
133 uint32_t magic = 0U;
134 int io_result;
135 size_t bytes_read;
136 uintptr_t fip_hdr_handle;
137
138 io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_fip_block_spec,
139 &fip_hdr_handle);
140 assert(io_result == 0);
141
142 io_result = io_read(fip_hdr_handle, (uintptr_t)&magic, sizeof(magic),
143 &bytes_read);
144 if ((io_result != 0) || (bytes_read != sizeof(magic))) {
145 panic();
146 }
147
148 io_close(fip_hdr_handle);
149
150 VERBOSE("%s: eMMC boot magic at offset 256K: %08x\n",
151 __func__, magic);
152
153 return magic;
154}
155#endif
156
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200157static void print_boot_device(boot_api_context_t *boot_context)
158{
159 switch (boot_context->boot_interface_selected) {
160 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
161 INFO("Using SDMMC\n");
162 break;
163 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
164 INFO("Using EMMC\n");
165 break;
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200166 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
167 INFO("Using QSPI NOR\n");
168 break;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100169 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
170 INFO("Using FMC NAND\n");
171 break;
Lionel Debieve186b0462019-09-24 18:30:12 +0200172 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
173 INFO("Using SPI NAND\n");
174 break;
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200175 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
176 INFO("Using UART\n");
177 break;
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200178 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
179 INFO("Using USB\n");
180 break;
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200181 default:
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200182 ERROR("Boot interface %u not found\n",
183 boot_context->boot_interface_selected);
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200184 panic();
185 break;
186 }
187
188 if (boot_context->boot_interface_instance != 0U) {
189 INFO(" Instance %d\n", boot_context->boot_interface_instance);
190 }
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200191}
192
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200193#if STM32MP_SDMMC || STM32MP_EMMC
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200194static void boot_mmc(enum mmc_device_type mmc_dev_type,
195 uint16_t boot_interface_instance)
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200196{
197 int io_result __unused;
Yann Gautier8244e1d2018-10-15 09:36:58 +0200198 struct stm32_sdmmc2_params params;
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200199
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200200 zeromem(&params, sizeof(struct stm32_sdmmc2_params));
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200201
Yann Gautierac22dd52021-03-22 14:22:14 +0100202 mmc_info.mmc_dev_type = mmc_dev_type;
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200203
204 switch (boot_interface_instance) {
205 case 1:
206 params.reg_base = STM32MP_SDMMC1_BASE;
207 break;
208 case 2:
209 params.reg_base = STM32MP_SDMMC2_BASE;
210 break;
211 case 3:
212 params.reg_base = STM32MP_SDMMC3_BASE;
213 break;
214 default:
215 WARN("SDMMC instance not found, using default\n");
216 if (mmc_dev_type == MMC_IS_SD) {
217 params.reg_base = STM32MP_SDMMC1_BASE;
218 } else {
219 params.reg_base = STM32MP_SDMMC2_BASE;
220 }
221 break;
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200222 }
223
Yann Gautierb218faa2019-08-14 16:44:48 +0200224 if (mmc_dev_type != MMC_IS_EMMC) {
225 params.flags = MMC_FLAG_SD_CMD6;
226 }
227
Yann Gautierac22dd52021-03-22 14:22:14 +0100228 params.device_info = &mmc_info;
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200229 if (stm32_sdmmc2_mmc_init(&params) != 0) {
230 ERROR("SDMMC%u init failed\n", boot_interface_instance);
231 panic();
232 }
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200233
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200234 /* Open MMC as a block device to read FIP */
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200235 io_result = register_io_dev_block(&mmc_dev_con);
236 if (io_result != 0) {
237 panic();
238 }
Yann Gautier8244e1d2018-10-15 09:36:58 +0200239
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200240 io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
241 &storage_dev_handle);
242 assert(io_result == 0);
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200243
244#if STM32MP_EMMC_BOOT
245 if (mmc_dev_type == MMC_IS_EMMC) {
246 io_result = mmc_part_switch_current_boot();
247 assert(io_result == 0);
248
249 if (get_boot_part_fip_header() != TOC_HEADER_NAME) {
250 WARN("%s: Can't find FIP header on eMMC boot partition. Trying GPT\n",
251 __func__);
252 io_result = mmc_part_switch_user();
253 assert(io_result == 0);
254 return;
255 }
256
257 VERBOSE("%s: FIP header found on eMMC boot partition\n",
258 __func__);
259 image_block_spec.offset = STM32MP_EMMC_BOOT_FIP_OFFSET;
Yann Gautier637cd9e2022-09-02 08:36:40 +0200260 image_block_spec.length = mmc_boot_part_size() - STM32MP_EMMC_BOOT_FIP_OFFSET;
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200261 }
262#endif
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200263}
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200264#endif /* STM32MP_SDMMC || STM32MP_EMMC */
Yann Gautier8244e1d2018-10-15 09:36:58 +0200265
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200266#if STM32MP_SPI_NOR
267static void boot_spi_nor(boot_api_context_t *boot_context)
268{
269 int io_result __unused;
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200270
271 io_result = stm32_qspi_init();
272 assert(io_result == 0);
273
274 io_result = register_io_dev_mtd(&spi_dev_con);
275 assert(io_result == 0);
276
277 /* Open connections to device */
278 io_result = io_dev_open(spi_dev_con,
279 (uintptr_t)&spi_nor_dev_spec,
280 &storage_dev_handle);
281 assert(io_result == 0);
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200282}
283#endif /* STM32MP_SPI_NOR */
284
Lionel Debieve402a46b2019-11-04 12:28:15 +0100285#if STM32MP_RAW_NAND
286static void boot_fmc2_nand(boot_api_context_t *boot_context)
287{
288 int io_result __unused;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100289
290 io_result = stm32_fmc2_init();
291 assert(io_result == 0);
292
293 /* Register the IO device on this platform */
294 io_result = register_io_dev_mtd(&nand_dev_con);
295 assert(io_result == 0);
296
297 /* Open connections to device */
298 io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
299 &storage_dev_handle);
300 assert(io_result == 0);
Lionel Debieve402a46b2019-11-04 12:28:15 +0100301}
302#endif /* STM32MP_RAW_NAND */
303
Lionel Debieve186b0462019-09-24 18:30:12 +0200304#if STM32MP_SPI_NAND
305static void boot_spi_nand(boot_api_context_t *boot_context)
306{
307 int io_result __unused;
Lionel Debieve186b0462019-09-24 18:30:12 +0200308
309 io_result = stm32_qspi_init();
310 assert(io_result == 0);
311
312 io_result = register_io_dev_mtd(&spi_dev_con);
313 assert(io_result == 0);
314
315 /* Open connections to device */
316 io_result = io_dev_open(spi_dev_con,
317 (uintptr_t)&spi_nand_dev_spec,
318 &storage_dev_handle);
319 assert(io_result == 0);
Lionel Debieve186b0462019-09-24 18:30:12 +0200320}
321#endif /* STM32MP_SPI_NAND */
322
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200323#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200324static void mmap_io_setup(void)
325{
326 int io_result __unused;
327
328 io_result = register_io_dev_memmap(&memmap_dev_con);
329 assert(io_result == 0);
330
331 io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
332 &storage_dev_handle);
333 assert(io_result == 0);
334}
335
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200336#if STM32MP_UART_PROGRAMMER
337static void stm32cubeprogrammer_uart(void)
338{
339 int ret __unused;
340 boot_api_context_t *boot_context =
341 (boot_api_context_t *)stm32mp_get_boot_ctx_address();
342 uintptr_t uart_base;
343
344 uart_base = get_uart_address(boot_context->boot_interface_instance);
345 ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
346 assert(ret == 0);
347}
348#endif
349
350#if STM32MP_USB_PROGRAMMER
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200351static void stm32cubeprogrammer_usb(void)
352{
353 int ret __unused;
354 struct usb_handle *pdev;
355
356 /* Init USB on platform */
357 pdev = usb_dfu_plat_init();
358
359 ret = stm32cubeprog_usb_load(pdev, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
360 assert(ret == 0);
361}
362#endif
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200363#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
364
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200365
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200366void stm32mp_io_setup(void)
367{
368 int io_result __unused;
369 boot_api_context_t *boot_context =
370 (boot_api_context_t *)stm32mp_get_boot_ctx_address();
Yann Gautierf9d40d52019-01-17 14:41:46 +0100371
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200372 print_boot_device(boot_context);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200373
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200374 if ((boot_context->boot_partition_used_toboot == 1U) ||
375 (boot_context->boot_partition_used_toboot == 2U)) {
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200376 INFO("Boot used partition fsbl%u\n",
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200377 boot_context->boot_partition_used_toboot);
378 }
Yann Gautier8244e1d2018-10-15 09:36:58 +0200379
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200380 io_result = register_io_dev_fip(&fip_dev_con);
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200381 assert(io_result == 0);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200382
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200383 io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
384 &fip_dev_handle);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200385
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200386 switch (boot_context->boot_interface_selected) {
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200387#if STM32MP_SDMMC
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200388 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
389 dmbsy();
390 boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
391 break;
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200392#endif
393#if STM32MP_EMMC
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200394 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
395 dmbsy();
396 boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200397 break;
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200398#endif
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200399#if STM32MP_SPI_NOR
400 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
401 dmbsy();
402 boot_spi_nor(boot_context);
403 break;
404#endif
Lionel Debieve402a46b2019-11-04 12:28:15 +0100405#if STM32MP_RAW_NAND
406 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
407 dmbsy();
408 boot_fmc2_nand(boot_context);
409 break;
410#endif
Lionel Debieve186b0462019-09-24 18:30:12 +0200411#if STM32MP_SPI_NAND
412 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
413 dmbsy();
414 boot_spi_nand(boot_context);
415 break;
416#endif
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200417#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
418#if STM32MP_UART_PROGRAMMER
419 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
420#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200421#if STM32MP_USB_PROGRAMMER
422 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200423#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200424 dmbsy();
425 mmap_io_setup();
426 break;
427#endif
Yann Gautier8244e1d2018-10-15 09:36:58 +0200428
429 default:
430 ERROR("Boot interface %d not supported\n",
431 boot_context->boot_interface_selected);
Yann Gautier4c2b73d2021-06-30 17:04:22 +0200432 panic();
Yann Gautier8244e1d2018-10-15 09:36:58 +0200433 break;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200434 }
435}
436
437int bl2_plat_handle_pre_image_load(unsigned int image_id)
438{
439 static bool gpt_init_done __unused;
440 uint16_t boot_itf = stm32mp_get_boot_itf_selected();
441
442 switch (boot_itf) {
443#if STM32MP_SDMMC || STM32MP_EMMC
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200444 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200445#if STM32MP_EMMC_BOOT
446 if (image_block_spec.offset == STM32MP_EMMC_BOOT_FIP_OFFSET) {
447 break;
448 }
449#endif
450 /* fallthrough */
451 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200452 if (!gpt_init_done) {
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530453/*
454 * With FWU Multi Bank feature enabled, the selection of
455 * the image to boot will be done by fwu_init calling the
456 * platform hook, plat_fwu_set_images_source.
457 */
458#if !PSA_FWU_SUPPORT
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200459 const partition_entry_t *entry;
Lionel Debieve5e111c52022-02-24 18:58:46 +0100460 const struct efi_guid img_type_guid = STM32MP_FIP_GUID;
461 uuid_t img_type_uuid;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200462
Lionel Debieve5e111c52022-02-24 18:58:46 +0100463 guidcpy(&img_type_uuid, &img_type_guid);
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200464 partition_init(GPT_IMAGE_ID);
Lionel Debieve5e111c52022-02-24 18:58:46 +0100465 entry = get_partition_entry_by_type(&img_type_uuid);
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200466 if (entry == NULL) {
Lionel Debieve5e111c52022-02-24 18:58:46 +0100467 entry = get_partition_entry(FIP_IMAGE_NAME);
468 if (entry == NULL) {
469 ERROR("Could NOT find the %s partition!\n",
470 FIP_IMAGE_NAME);
471
472 return -ENOENT;
473 }
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200474 }
475
476 image_block_spec.offset = entry->start;
477 image_block_spec.length = entry->length;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530478#endif
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200479 gpt_init_done = true;
Yann Gautiera3bd8d12021-06-18 11:33:26 +0200480 } else {
481 bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
Yann Gautierc6f77b02022-05-06 09:50:43 +0200482 assert(bl_mem_params != NULL);
Yann Gautiera3bd8d12021-06-18 11:33:26 +0200483
484 mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
485 mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200486 }
487
488 break;
489#endif
490
491#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
492#if STM32MP_RAW_NAND
493 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
494#endif
495#if STM32MP_SPI_NAND
496 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
497#endif
498 image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
499 break;
500#endif
501
502#if STM32MP_SPI_NOR
503 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
504 image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
505 break;
506#endif
507
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200508#if STM32MP_UART_PROGRAMMER
509 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
510 if (image_id == FW_CONFIG_ID) {
511 stm32cubeprogrammer_uart();
512 /* FIP loaded at DWL address */
513 image_block_spec.offset = DWL_BUFFER_BASE;
514 image_block_spec.length = DWL_BUFFER_SIZE;
515 }
516 break;
517#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200518#if STM32MP_USB_PROGRAMMER
519 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
520 if (image_id == FW_CONFIG_ID) {
521 stm32cubeprogrammer_usb();
522 /* FIP loaded at DWL address */
523 image_block_spec.offset = DWL_BUFFER_BASE;
524 image_block_spec.length = DWL_BUFFER_SIZE;
525 }
526 break;
527#endif
528
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200529 default:
530 ERROR("FIP Not found\n");
531 panic();
Yann Gautier8244e1d2018-10-15 09:36:58 +0200532 }
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200533
534 return 0;
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200535}
536
537/*
538 * Return an IO device handle and specification which can be used to access
539 * an image. Use this to enforce platform load policy.
540 */
541int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
542 uintptr_t *image_spec)
543{
544 int rc;
545 const struct plat_io_policy *policy;
546
Yann Gautier29f1f942021-07-13 18:07:41 +0200547 policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200548 rc = policy->check(policy->image_spec);
549 if (rc == 0) {
550 *image_spec = policy->image_spec;
551 *dev_handle = *(policy->dev_handle);
552 }
553
554 return rc;
555}
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530556
557#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
558/*
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100559 * In each boot in non-trial mode, we set the BKP register to
560 * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata.
561 *
562 * As long as the update agent didn't update the "accepted" field in metadata
563 * (i.e. we are in trial mode), we select the new active_index.
564 * To avoid infinite boot loop at trial boot we decrement a BKP register.
565 * If this counter is 0:
566 * - an unexpected TAMPER event raised (that resets the BKP registers to 0)
567 * - a power-off occurs before the update agent was able to update the
568 * "accepted' field
569 * - we already boot FWU_MAX_TRIAL_REBOOT times in trial mode.
570 * we select the previous_active_index.
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530571 */
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100572#define INVALID_BOOT_IDX 0xFFFFFFFF
573
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530574uint32_t plat_fwu_get_boot_idx(void)
575{
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100576 /*
577 * Select boot index and update boot counter only once per boot
578 * even if this function is called several times.
579 */
580 static uint32_t boot_idx = INVALID_BOOT_IDX;
581 const struct fwu_metadata *data;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530582
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100583 data = fwu_get_metadata();
584
585 if (boot_idx == INVALID_BOOT_IDX) {
586 boot_idx = data->active_index;
587 if (fwu_is_trial_run_state()) {
588 if (stm32_get_and_dec_fwu_trial_boot_cnt() == 0U) {
589 WARN("Trial FWU fails %u times\n",
590 FWU_MAX_TRIAL_REBOOT);
591 boot_idx = data->previous_active_index;
592 }
593 } else {
594 stm32_set_max_fwu_trial_boot_cnt();
595 }
596 }
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530597
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100598 return boot_idx;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530599}
600
601static void *stm32_get_image_spec(const uuid_t *img_type_uuid)
602{
603 unsigned int i;
604
605 for (i = 0U; i < MAX_NUMBER_IDS; i++) {
606 if ((guidcmp(&policies[i].img_type_guid, img_type_uuid)) == 0) {
607 return (void *)policies[i].image_spec;
608 }
609 }
610
611 return NULL;
612}
613
614void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
615{
616 unsigned int i;
617 uint32_t boot_idx;
618 const partition_entry_t *entry;
619 const uuid_t *img_type_uuid, *img_uuid;
620 io_block_spec_t *image_spec;
621
622 boot_idx = plat_fwu_get_boot_idx();
623 assert(boot_idx < NR_OF_FW_BANKS);
624
625 for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
626 img_type_uuid = &metadata->img_entry[i].img_type_uuid;
627 image_spec = stm32_get_image_spec(img_type_uuid);
628 if (image_spec == NULL) {
629 ERROR("Unable to get image spec for the image in the metadata\n");
630 panic();
631 }
632
633 img_uuid =
634 &metadata->img_entry[i].img_props[boot_idx].img_uuid;
635
636 entry = get_partition_entry_by_uuid(img_uuid);
637 if (entry == NULL) {
638 ERROR("Unable to find the partition with the uuid mentioned in metadata\n");
639 panic();
640 }
641
642 image_spec->offset = entry->start;
643 image_spec->length = entry->length;
644 }
645}
Sughosh Ganud1f87132021-12-01 16:46:34 +0530646
647static int plat_set_image_source(unsigned int image_id,
648 uintptr_t *handle,
649 uintptr_t *image_spec,
650 const char *part_name)
651{
652 struct plat_io_policy *policy;
653 io_block_spec_t *spec;
654 const partition_entry_t *entry = get_partition_entry(part_name);
655
656 if (entry == NULL) {
657 ERROR("Unable to find the %s partition\n", part_name);
658 return -ENOENT;
659 }
660
661 policy = &policies[image_id];
662
663 spec = (io_block_spec_t *)policy->image_spec;
664 spec->offset = entry->start;
665 spec->length = entry->length;
666
667 *image_spec = policy->image_spec;
668 *handle = *policy->dev_handle;
669
670 return 0;
671}
672
673int plat_fwu_set_metadata_image_source(unsigned int image_id,
674 uintptr_t *handle,
675 uintptr_t *image_spec)
676{
677 char *part_name;
678
679 assert((image_id == FWU_METADATA_IMAGE_ID) ||
680 (image_id == BKUP_FWU_METADATA_IMAGE_ID));
681
682 partition_init(GPT_IMAGE_ID);
683
684 if (image_id == FWU_METADATA_IMAGE_ID) {
685 part_name = METADATA_PART_1;
686 } else {
687 part_name = METADATA_PART_2;
688 }
689
690 return plat_set_image_source(image_id, handle, image_spec,
691 part_name);
692}
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530693#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */