blob: 8d0bdccca400866c3ba6acb4feeefcc20d8c1b84 [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;
260 }
261#endif
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200262}
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200263#endif /* STM32MP_SDMMC || STM32MP_EMMC */
Yann Gautier8244e1d2018-10-15 09:36:58 +0200264
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200265#if STM32MP_SPI_NOR
266static void boot_spi_nor(boot_api_context_t *boot_context)
267{
268 int io_result __unused;
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200269
270 io_result = stm32_qspi_init();
271 assert(io_result == 0);
272
273 io_result = register_io_dev_mtd(&spi_dev_con);
274 assert(io_result == 0);
275
276 /* Open connections to device */
277 io_result = io_dev_open(spi_dev_con,
278 (uintptr_t)&spi_nor_dev_spec,
279 &storage_dev_handle);
280 assert(io_result == 0);
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200281}
282#endif /* STM32MP_SPI_NOR */
283
Lionel Debieve402a46b2019-11-04 12:28:15 +0100284#if STM32MP_RAW_NAND
285static void boot_fmc2_nand(boot_api_context_t *boot_context)
286{
287 int io_result __unused;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100288
289 io_result = stm32_fmc2_init();
290 assert(io_result == 0);
291
292 /* Register the IO device on this platform */
293 io_result = register_io_dev_mtd(&nand_dev_con);
294 assert(io_result == 0);
295
296 /* Open connections to device */
297 io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
298 &storage_dev_handle);
299 assert(io_result == 0);
Lionel Debieve402a46b2019-11-04 12:28:15 +0100300}
301#endif /* STM32MP_RAW_NAND */
302
Lionel Debieve186b0462019-09-24 18:30:12 +0200303#if STM32MP_SPI_NAND
304static void boot_spi_nand(boot_api_context_t *boot_context)
305{
306 int io_result __unused;
Lionel Debieve186b0462019-09-24 18:30:12 +0200307
308 io_result = stm32_qspi_init();
309 assert(io_result == 0);
310
311 io_result = register_io_dev_mtd(&spi_dev_con);
312 assert(io_result == 0);
313
314 /* Open connections to device */
315 io_result = io_dev_open(spi_dev_con,
316 (uintptr_t)&spi_nand_dev_spec,
317 &storage_dev_handle);
318 assert(io_result == 0);
Lionel Debieve186b0462019-09-24 18:30:12 +0200319}
320#endif /* STM32MP_SPI_NAND */
321
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200322#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200323static void mmap_io_setup(void)
324{
325 int io_result __unused;
326
327 io_result = register_io_dev_memmap(&memmap_dev_con);
328 assert(io_result == 0);
329
330 io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
331 &storage_dev_handle);
332 assert(io_result == 0);
333}
334
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200335#if STM32MP_UART_PROGRAMMER
336static void stm32cubeprogrammer_uart(void)
337{
338 int ret __unused;
339 boot_api_context_t *boot_context =
340 (boot_api_context_t *)stm32mp_get_boot_ctx_address();
341 uintptr_t uart_base;
342
343 uart_base = get_uart_address(boot_context->boot_interface_instance);
344 ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
345 assert(ret == 0);
346}
347#endif
348
349#if STM32MP_USB_PROGRAMMER
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200350static void stm32cubeprogrammer_usb(void)
351{
352 int ret __unused;
353 struct usb_handle *pdev;
354
355 /* Init USB on platform */
356 pdev = usb_dfu_plat_init();
357
358 ret = stm32cubeprog_usb_load(pdev, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
359 assert(ret == 0);
360}
361#endif
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200362#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
363
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200364
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200365void stm32mp_io_setup(void)
366{
367 int io_result __unused;
368 boot_api_context_t *boot_context =
369 (boot_api_context_t *)stm32mp_get_boot_ctx_address();
Yann Gautierf9d40d52019-01-17 14:41:46 +0100370
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200371 print_boot_device(boot_context);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200372
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200373 if ((boot_context->boot_partition_used_toboot == 1U) ||
374 (boot_context->boot_partition_used_toboot == 2U)) {
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200375 INFO("Boot used partition fsbl%u\n",
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200376 boot_context->boot_partition_used_toboot);
377 }
Yann Gautier8244e1d2018-10-15 09:36:58 +0200378
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200379 io_result = register_io_dev_fip(&fip_dev_con);
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200380 assert(io_result == 0);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200381
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200382 io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
383 &fip_dev_handle);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200384
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200385 switch (boot_context->boot_interface_selected) {
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200386#if STM32MP_SDMMC
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200387 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
388 dmbsy();
389 boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
390 break;
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200391#endif
392#if STM32MP_EMMC
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200393 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
394 dmbsy();
395 boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200396 break;
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200397#endif
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200398#if STM32MP_SPI_NOR
399 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
400 dmbsy();
401 boot_spi_nor(boot_context);
402 break;
403#endif
Lionel Debieve402a46b2019-11-04 12:28:15 +0100404#if STM32MP_RAW_NAND
405 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
406 dmbsy();
407 boot_fmc2_nand(boot_context);
408 break;
409#endif
Lionel Debieve186b0462019-09-24 18:30:12 +0200410#if STM32MP_SPI_NAND
411 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
412 dmbsy();
413 boot_spi_nand(boot_context);
414 break;
415#endif
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200416#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
417#if STM32MP_UART_PROGRAMMER
418 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
419#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200420#if STM32MP_USB_PROGRAMMER
421 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200422#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200423 dmbsy();
424 mmap_io_setup();
425 break;
426#endif
Yann Gautier8244e1d2018-10-15 09:36:58 +0200427
428 default:
429 ERROR("Boot interface %d not supported\n",
430 boot_context->boot_interface_selected);
Yann Gautier4c2b73d2021-06-30 17:04:22 +0200431 panic();
Yann Gautier8244e1d2018-10-15 09:36:58 +0200432 break;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200433 }
434}
435
436int bl2_plat_handle_pre_image_load(unsigned int image_id)
437{
438 static bool gpt_init_done __unused;
439 uint16_t boot_itf = stm32mp_get_boot_itf_selected();
440
441 switch (boot_itf) {
442#if STM32MP_SDMMC || STM32MP_EMMC
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200443 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200444#if STM32MP_EMMC_BOOT
445 if (image_block_spec.offset == STM32MP_EMMC_BOOT_FIP_OFFSET) {
446 break;
447 }
448#endif
449 /* fallthrough */
450 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200451 if (!gpt_init_done) {
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530452/*
453 * With FWU Multi Bank feature enabled, the selection of
454 * the image to boot will be done by fwu_init calling the
455 * platform hook, plat_fwu_set_images_source.
456 */
457#if !PSA_FWU_SUPPORT
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200458 const partition_entry_t *entry;
Lionel Debieve5e111c52022-02-24 18:58:46 +0100459 const struct efi_guid img_type_guid = STM32MP_FIP_GUID;
460 uuid_t img_type_uuid;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200461
Lionel Debieve5e111c52022-02-24 18:58:46 +0100462 guidcpy(&img_type_uuid, &img_type_guid);
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200463 partition_init(GPT_IMAGE_ID);
Lionel Debieve5e111c52022-02-24 18:58:46 +0100464 entry = get_partition_entry_by_type(&img_type_uuid);
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200465 if (entry == NULL) {
Lionel Debieve5e111c52022-02-24 18:58:46 +0100466 entry = get_partition_entry(FIP_IMAGE_NAME);
467 if (entry == NULL) {
468 ERROR("Could NOT find the %s partition!\n",
469 FIP_IMAGE_NAME);
470
471 return -ENOENT;
472 }
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200473 }
474
475 image_block_spec.offset = entry->start;
476 image_block_spec.length = entry->length;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530477#endif
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200478 gpt_init_done = true;
Yann Gautiera3bd8d12021-06-18 11:33:26 +0200479 } else {
480 bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
Yann Gautierc6f77b02022-05-06 09:50:43 +0200481 assert(bl_mem_params != NULL);
Yann Gautiera3bd8d12021-06-18 11:33:26 +0200482
483 mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
484 mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200485 }
486
487 break;
488#endif
489
490#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
491#if STM32MP_RAW_NAND
492 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
493#endif
494#if STM32MP_SPI_NAND
495 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
496#endif
497 image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
498 break;
499#endif
500
501#if STM32MP_SPI_NOR
502 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
503 image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
504 break;
505#endif
506
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200507#if STM32MP_UART_PROGRAMMER
508 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
509 if (image_id == FW_CONFIG_ID) {
510 stm32cubeprogrammer_uart();
511 /* FIP loaded at DWL address */
512 image_block_spec.offset = DWL_BUFFER_BASE;
513 image_block_spec.length = DWL_BUFFER_SIZE;
514 }
515 break;
516#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200517#if STM32MP_USB_PROGRAMMER
518 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
519 if (image_id == FW_CONFIG_ID) {
520 stm32cubeprogrammer_usb();
521 /* FIP loaded at DWL address */
522 image_block_spec.offset = DWL_BUFFER_BASE;
523 image_block_spec.length = DWL_BUFFER_SIZE;
524 }
525 break;
526#endif
527
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200528 default:
529 ERROR("FIP Not found\n");
530 panic();
Yann Gautier8244e1d2018-10-15 09:36:58 +0200531 }
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200532
533 return 0;
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200534}
535
536/*
537 * Return an IO device handle and specification which can be used to access
538 * an image. Use this to enforce platform load policy.
539 */
540int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
541 uintptr_t *image_spec)
542{
543 int rc;
544 const struct plat_io_policy *policy;
545
Yann Gautier29f1f942021-07-13 18:07:41 +0200546 policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200547 rc = policy->check(policy->image_spec);
548 if (rc == 0) {
549 *image_spec = policy->image_spec;
550 *dev_handle = *(policy->dev_handle);
551 }
552
553 return rc;
554}
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530555
556#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
557/*
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100558 * In each boot in non-trial mode, we set the BKP register to
559 * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata.
560 *
561 * As long as the update agent didn't update the "accepted" field in metadata
562 * (i.e. we are in trial mode), we select the new active_index.
563 * To avoid infinite boot loop at trial boot we decrement a BKP register.
564 * If this counter is 0:
565 * - an unexpected TAMPER event raised (that resets the BKP registers to 0)
566 * - a power-off occurs before the update agent was able to update the
567 * "accepted' field
568 * - we already boot FWU_MAX_TRIAL_REBOOT times in trial mode.
569 * we select the previous_active_index.
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530570 */
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100571#define INVALID_BOOT_IDX 0xFFFFFFFF
572
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530573uint32_t plat_fwu_get_boot_idx(void)
574{
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100575 /*
576 * Select boot index and update boot counter only once per boot
577 * even if this function is called several times.
578 */
579 static uint32_t boot_idx = INVALID_BOOT_IDX;
580 const struct fwu_metadata *data;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530581
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100582 data = fwu_get_metadata();
583
584 if (boot_idx == INVALID_BOOT_IDX) {
585 boot_idx = data->active_index;
586 if (fwu_is_trial_run_state()) {
587 if (stm32_get_and_dec_fwu_trial_boot_cnt() == 0U) {
588 WARN("Trial FWU fails %u times\n",
589 FWU_MAX_TRIAL_REBOOT);
590 boot_idx = data->previous_active_index;
591 }
592 } else {
593 stm32_set_max_fwu_trial_boot_cnt();
594 }
595 }
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530596
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100597 return boot_idx;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530598}
599
600static void *stm32_get_image_spec(const uuid_t *img_type_uuid)
601{
602 unsigned int i;
603
604 for (i = 0U; i < MAX_NUMBER_IDS; i++) {
605 if ((guidcmp(&policies[i].img_type_guid, img_type_uuid)) == 0) {
606 return (void *)policies[i].image_spec;
607 }
608 }
609
610 return NULL;
611}
612
613void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
614{
615 unsigned int i;
616 uint32_t boot_idx;
617 const partition_entry_t *entry;
618 const uuid_t *img_type_uuid, *img_uuid;
619 io_block_spec_t *image_spec;
620
621 boot_idx = plat_fwu_get_boot_idx();
622 assert(boot_idx < NR_OF_FW_BANKS);
623
624 for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
625 img_type_uuid = &metadata->img_entry[i].img_type_uuid;
626 image_spec = stm32_get_image_spec(img_type_uuid);
627 if (image_spec == NULL) {
628 ERROR("Unable to get image spec for the image in the metadata\n");
629 panic();
630 }
631
632 img_uuid =
633 &metadata->img_entry[i].img_props[boot_idx].img_uuid;
634
635 entry = get_partition_entry_by_uuid(img_uuid);
636 if (entry == NULL) {
637 ERROR("Unable to find the partition with the uuid mentioned in metadata\n");
638 panic();
639 }
640
641 image_spec->offset = entry->start;
642 image_spec->length = entry->length;
643 }
644}
Sughosh Ganud1f87132021-12-01 16:46:34 +0530645
646static int plat_set_image_source(unsigned int image_id,
647 uintptr_t *handle,
648 uintptr_t *image_spec,
649 const char *part_name)
650{
651 struct plat_io_policy *policy;
652 io_block_spec_t *spec;
653 const partition_entry_t *entry = get_partition_entry(part_name);
654
655 if (entry == NULL) {
656 ERROR("Unable to find the %s partition\n", part_name);
657 return -ENOENT;
658 }
659
660 policy = &policies[image_id];
661
662 spec = (io_block_spec_t *)policy->image_spec;
663 spec->offset = entry->start;
664 spec->length = entry->length;
665
666 *image_spec = policy->image_spec;
667 *handle = *policy->dev_handle;
668
669 return 0;
670}
671
672int plat_fwu_set_metadata_image_source(unsigned int image_id,
673 uintptr_t *handle,
674 uintptr_t *image_spec)
675{
676 char *part_name;
677
678 assert((image_id == FWU_METADATA_IMAGE_ID) ||
679 (image_id == BKUP_FWU_METADATA_IMAGE_ID));
680
681 partition_init(GPT_IMAGE_ID);
682
683 if (image_id == FWU_METADATA_IMAGE_ID) {
684 part_name = METADATA_PART_1;
685 } else {
686 part_name = METADATA_PART_2;
687 }
688
689 return plat_set_image_source(image_id, handle, image_spec,
690 part_name);
691}
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530692#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */