blob: 49f6465ad3223303d460e4e89c8131a878587099 [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 Gautierac22dd52021-03-22 14:22:14 +0100224 params.device_info = &mmc_info;
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200225 if (stm32_sdmmc2_mmc_init(&params) != 0) {
226 ERROR("SDMMC%u init failed\n", boot_interface_instance);
227 panic();
228 }
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200229
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200230 /* Open MMC as a block device to read FIP */
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200231 io_result = register_io_dev_block(&mmc_dev_con);
232 if (io_result != 0) {
233 panic();
234 }
Yann Gautier8244e1d2018-10-15 09:36:58 +0200235
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200236 io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec,
237 &storage_dev_handle);
238 assert(io_result == 0);
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200239
240#if STM32MP_EMMC_BOOT
241 if (mmc_dev_type == MMC_IS_EMMC) {
242 io_result = mmc_part_switch_current_boot();
243 assert(io_result == 0);
244
245 if (get_boot_part_fip_header() != TOC_HEADER_NAME) {
246 WARN("%s: Can't find FIP header on eMMC boot partition. Trying GPT\n",
247 __func__);
248 io_result = mmc_part_switch_user();
249 assert(io_result == 0);
250 return;
251 }
252
253 VERBOSE("%s: FIP header found on eMMC boot partition\n",
254 __func__);
255 image_block_spec.offset = STM32MP_EMMC_BOOT_FIP_OFFSET;
256 }
257#endif
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200258}
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200259#endif /* STM32MP_SDMMC || STM32MP_EMMC */
Yann Gautier8244e1d2018-10-15 09:36:58 +0200260
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200261#if STM32MP_SPI_NOR
262static void boot_spi_nor(boot_api_context_t *boot_context)
263{
264 int io_result __unused;
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200265
266 io_result = stm32_qspi_init();
267 assert(io_result == 0);
268
269 io_result = register_io_dev_mtd(&spi_dev_con);
270 assert(io_result == 0);
271
272 /* Open connections to device */
273 io_result = io_dev_open(spi_dev_con,
274 (uintptr_t)&spi_nor_dev_spec,
275 &storage_dev_handle);
276 assert(io_result == 0);
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200277}
278#endif /* STM32MP_SPI_NOR */
279
Lionel Debieve402a46b2019-11-04 12:28:15 +0100280#if STM32MP_RAW_NAND
281static void boot_fmc2_nand(boot_api_context_t *boot_context)
282{
283 int io_result __unused;
Lionel Debieve402a46b2019-11-04 12:28:15 +0100284
285 io_result = stm32_fmc2_init();
286 assert(io_result == 0);
287
288 /* Register the IO device on this platform */
289 io_result = register_io_dev_mtd(&nand_dev_con);
290 assert(io_result == 0);
291
292 /* Open connections to device */
293 io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
294 &storage_dev_handle);
295 assert(io_result == 0);
Lionel Debieve402a46b2019-11-04 12:28:15 +0100296}
297#endif /* STM32MP_RAW_NAND */
298
Lionel Debieve186b0462019-09-24 18:30:12 +0200299#if STM32MP_SPI_NAND
300static void boot_spi_nand(boot_api_context_t *boot_context)
301{
302 int io_result __unused;
Lionel Debieve186b0462019-09-24 18:30:12 +0200303
304 io_result = stm32_qspi_init();
305 assert(io_result == 0);
306
307 io_result = register_io_dev_mtd(&spi_dev_con);
308 assert(io_result == 0);
309
310 /* Open connections to device */
311 io_result = io_dev_open(spi_dev_con,
312 (uintptr_t)&spi_nand_dev_spec,
313 &storage_dev_handle);
314 assert(io_result == 0);
Lionel Debieve186b0462019-09-24 18:30:12 +0200315}
316#endif /* STM32MP_SPI_NAND */
317
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200318#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200319static void mmap_io_setup(void)
320{
321 int io_result __unused;
322
323 io_result = register_io_dev_memmap(&memmap_dev_con);
324 assert(io_result == 0);
325
326 io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
327 &storage_dev_handle);
328 assert(io_result == 0);
329}
330
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200331#if STM32MP_UART_PROGRAMMER
332static void stm32cubeprogrammer_uart(void)
333{
334 int ret __unused;
335 boot_api_context_t *boot_context =
336 (boot_api_context_t *)stm32mp_get_boot_ctx_address();
337 uintptr_t uart_base;
338
339 uart_base = get_uart_address(boot_context->boot_interface_instance);
340 ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
341 assert(ret == 0);
342}
343#endif
344
345#if STM32MP_USB_PROGRAMMER
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200346static void stm32cubeprogrammer_usb(void)
347{
348 int ret __unused;
349 struct usb_handle *pdev;
350
351 /* Init USB on platform */
352 pdev = usb_dfu_plat_init();
353
354 ret = stm32cubeprog_usb_load(pdev, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
355 assert(ret == 0);
356}
357#endif
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200358#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
359
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200360
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200361void stm32mp_io_setup(void)
362{
363 int io_result __unused;
364 boot_api_context_t *boot_context =
365 (boot_api_context_t *)stm32mp_get_boot_ctx_address();
Yann Gautierf9d40d52019-01-17 14:41:46 +0100366
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200367 print_boot_device(boot_context);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200368
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200369 if ((boot_context->boot_partition_used_toboot == 1U) ||
370 (boot_context->boot_partition_used_toboot == 2U)) {
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200371 INFO("Boot used partition fsbl%u\n",
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200372 boot_context->boot_partition_used_toboot);
373 }
Yann Gautier8244e1d2018-10-15 09:36:58 +0200374
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200375 io_result = register_io_dev_fip(&fip_dev_con);
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200376 assert(io_result == 0);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200377
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200378 io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
379 &fip_dev_handle);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200380
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200381 switch (boot_context->boot_interface_selected) {
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200382#if STM32MP_SDMMC
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200383 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
384 dmbsy();
385 boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
386 break;
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200387#endif
388#if STM32MP_EMMC
Yann Gautiereae3fbf2019-04-23 13:34:03 +0200389 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
390 dmbsy();
391 boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
Yann Gautier8244e1d2018-10-15 09:36:58 +0200392 break;
Nicolas Le Bayon3f42cad2019-09-03 09:52:05 +0200393#endif
Lionel Debievecb0dbc42019-09-25 09:11:31 +0200394#if STM32MP_SPI_NOR
395 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
396 dmbsy();
397 boot_spi_nor(boot_context);
398 break;
399#endif
Lionel Debieve402a46b2019-11-04 12:28:15 +0100400#if STM32MP_RAW_NAND
401 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
402 dmbsy();
403 boot_fmc2_nand(boot_context);
404 break;
405#endif
Lionel Debieve186b0462019-09-24 18:30:12 +0200406#if STM32MP_SPI_NAND
407 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
408 dmbsy();
409 boot_spi_nand(boot_context);
410 break;
411#endif
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200412#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
413#if STM32MP_UART_PROGRAMMER
414 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
415#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200416#if STM32MP_USB_PROGRAMMER
417 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200418#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200419 dmbsy();
420 mmap_io_setup();
421 break;
422#endif
Yann Gautier8244e1d2018-10-15 09:36:58 +0200423
424 default:
425 ERROR("Boot interface %d not supported\n",
426 boot_context->boot_interface_selected);
Yann Gautier4c2b73d2021-06-30 17:04:22 +0200427 panic();
Yann Gautier8244e1d2018-10-15 09:36:58 +0200428 break;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200429 }
430}
431
432int bl2_plat_handle_pre_image_load(unsigned int image_id)
433{
434 static bool gpt_init_done __unused;
435 uint16_t boot_itf = stm32mp_get_boot_itf_selected();
436
437 switch (boot_itf) {
438#if STM32MP_SDMMC || STM32MP_EMMC
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200439 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
Ahmad Fatoumbd685282022-05-19 07:42:33 +0200440#if STM32MP_EMMC_BOOT
441 if (image_block_spec.offset == STM32MP_EMMC_BOOT_FIP_OFFSET) {
442 break;
443 }
444#endif
445 /* fallthrough */
446 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200447 if (!gpt_init_done) {
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530448/*
449 * With FWU Multi Bank feature enabled, the selection of
450 * the image to boot will be done by fwu_init calling the
451 * platform hook, plat_fwu_set_images_source.
452 */
453#if !PSA_FWU_SUPPORT
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200454 const partition_entry_t *entry;
Lionel Debieve5e111c52022-02-24 18:58:46 +0100455 const struct efi_guid img_type_guid = STM32MP_FIP_GUID;
456 uuid_t img_type_uuid;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200457
Lionel Debieve5e111c52022-02-24 18:58:46 +0100458 guidcpy(&img_type_uuid, &img_type_guid);
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200459 partition_init(GPT_IMAGE_ID);
Lionel Debieve5e111c52022-02-24 18:58:46 +0100460 entry = get_partition_entry_by_type(&img_type_uuid);
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200461 if (entry == NULL) {
Lionel Debieve5e111c52022-02-24 18:58:46 +0100462 entry = get_partition_entry(FIP_IMAGE_NAME);
463 if (entry == NULL) {
464 ERROR("Could NOT find the %s partition!\n",
465 FIP_IMAGE_NAME);
466
467 return -ENOENT;
468 }
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200469 }
470
471 image_block_spec.offset = entry->start;
472 image_block_spec.length = entry->length;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530473#endif
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200474 gpt_init_done = true;
Yann Gautiera3bd8d12021-06-18 11:33:26 +0200475 } else {
476 bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
Yann Gautierc6f77b02022-05-06 09:50:43 +0200477 assert(bl_mem_params != NULL);
Yann Gautiera3bd8d12021-06-18 11:33:26 +0200478
479 mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
480 mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200481 }
482
483 break;
484#endif
485
486#if STM32MP_RAW_NAND || STM32MP_SPI_NAND
487#if STM32MP_RAW_NAND
488 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
489#endif
490#if STM32MP_SPI_NAND
491 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI:
492#endif
493 image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
494 break;
495#endif
496
497#if STM32MP_SPI_NOR
498 case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI:
499 image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
500 break;
501#endif
502
Patrick Delaunaye50571b2021-10-28 13:48:52 +0200503#if STM32MP_UART_PROGRAMMER
504 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
505 if (image_id == FW_CONFIG_ID) {
506 stm32cubeprogrammer_uart();
507 /* FIP loaded at DWL address */
508 image_block_spec.offset = DWL_BUFFER_BASE;
509 image_block_spec.length = DWL_BUFFER_SIZE;
510 }
511 break;
512#endif
Patrick Delaunay9c5ee782021-07-06 14:07:56 +0200513#if STM32MP_USB_PROGRAMMER
514 case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
515 if (image_id == FW_CONFIG_ID) {
516 stm32cubeprogrammer_usb();
517 /* FIP loaded at DWL address */
518 image_block_spec.offset = DWL_BUFFER_BASE;
519 image_block_spec.length = DWL_BUFFER_SIZE;
520 }
521 break;
522#endif
523
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200524 default:
525 ERROR("FIP Not found\n");
526 panic();
Yann Gautier8244e1d2018-10-15 09:36:58 +0200527 }
Yann Gautier0ed7b2a2021-05-19 18:48:16 +0200528
529 return 0;
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200530}
531
532/*
533 * Return an IO device handle and specification which can be used to access
534 * an image. Use this to enforce platform load policy.
535 */
536int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
537 uintptr_t *image_spec)
538{
539 int rc;
540 const struct plat_io_policy *policy;
541
Yann Gautier29f1f942021-07-13 18:07:41 +0200542 policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
Yann Gautier4b0c72a2018-07-16 10:54:09 +0200543 rc = policy->check(policy->image_spec);
544 if (rc == 0) {
545 *image_spec = policy->image_spec;
546 *dev_handle = *(policy->dev_handle);
547 }
548
549 return rc;
550}
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530551
552#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
553/*
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100554 * In each boot in non-trial mode, we set the BKP register to
555 * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata.
556 *
557 * As long as the update agent didn't update the "accepted" field in metadata
558 * (i.e. we are in trial mode), we select the new active_index.
559 * To avoid infinite boot loop at trial boot we decrement a BKP register.
560 * If this counter is 0:
561 * - an unexpected TAMPER event raised (that resets the BKP registers to 0)
562 * - a power-off occurs before the update agent was able to update the
563 * "accepted' field
564 * - we already boot FWU_MAX_TRIAL_REBOOT times in trial mode.
565 * we select the previous_active_index.
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530566 */
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100567#define INVALID_BOOT_IDX 0xFFFFFFFF
568
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530569uint32_t plat_fwu_get_boot_idx(void)
570{
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100571 /*
572 * Select boot index and update boot counter only once per boot
573 * even if this function is called several times.
574 */
575 static uint32_t boot_idx = INVALID_BOOT_IDX;
576 const struct fwu_metadata *data;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530577
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100578 data = fwu_get_metadata();
579
580 if (boot_idx == INVALID_BOOT_IDX) {
581 boot_idx = data->active_index;
582 if (fwu_is_trial_run_state()) {
583 if (stm32_get_and_dec_fwu_trial_boot_cnt() == 0U) {
584 WARN("Trial FWU fails %u times\n",
585 FWU_MAX_TRIAL_REBOOT);
586 boot_idx = data->previous_active_index;
587 }
588 } else {
589 stm32_set_max_fwu_trial_boot_cnt();
590 }
591 }
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530592
Nicolas Toromanoff5a937cd2022-02-07 10:12:04 +0100593 return boot_idx;
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530594}
595
596static void *stm32_get_image_spec(const uuid_t *img_type_uuid)
597{
598 unsigned int i;
599
600 for (i = 0U; i < MAX_NUMBER_IDS; i++) {
601 if ((guidcmp(&policies[i].img_type_guid, img_type_uuid)) == 0) {
602 return (void *)policies[i].image_spec;
603 }
604 }
605
606 return NULL;
607}
608
609void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
610{
611 unsigned int i;
612 uint32_t boot_idx;
613 const partition_entry_t *entry;
614 const uuid_t *img_type_uuid, *img_uuid;
615 io_block_spec_t *image_spec;
616
617 boot_idx = plat_fwu_get_boot_idx();
618 assert(boot_idx < NR_OF_FW_BANKS);
619
620 for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
621 img_type_uuid = &metadata->img_entry[i].img_type_uuid;
622 image_spec = stm32_get_image_spec(img_type_uuid);
623 if (image_spec == NULL) {
624 ERROR("Unable to get image spec for the image in the metadata\n");
625 panic();
626 }
627
628 img_uuid =
629 &metadata->img_entry[i].img_props[boot_idx].img_uuid;
630
631 entry = get_partition_entry_by_uuid(img_uuid);
632 if (entry == NULL) {
633 ERROR("Unable to find the partition with the uuid mentioned in metadata\n");
634 panic();
635 }
636
637 image_spec->offset = entry->start;
638 image_spec->length = entry->length;
639 }
640}
Sughosh Ganud1f87132021-12-01 16:46:34 +0530641
642static int plat_set_image_source(unsigned int image_id,
643 uintptr_t *handle,
644 uintptr_t *image_spec,
645 const char *part_name)
646{
647 struct plat_io_policy *policy;
648 io_block_spec_t *spec;
649 const partition_entry_t *entry = get_partition_entry(part_name);
650
651 if (entry == NULL) {
652 ERROR("Unable to find the %s partition\n", part_name);
653 return -ENOENT;
654 }
655
656 policy = &policies[image_id];
657
658 spec = (io_block_spec_t *)policy->image_spec;
659 spec->offset = entry->start;
660 spec->length = entry->length;
661
662 *image_spec = policy->image_spec;
663 *handle = *policy->dev_handle;
664
665 return 0;
666}
667
668int plat_fwu_set_metadata_image_source(unsigned int image_id,
669 uintptr_t *handle,
670 uintptr_t *image_spec)
671{
672 char *part_name;
673
674 assert((image_id == FWU_METADATA_IMAGE_ID) ||
675 (image_id == BKUP_FWU_METADATA_IMAGE_ID));
676
677 partition_init(GPT_IMAGE_ID);
678
679 if (image_id == FWU_METADATA_IMAGE_ID) {
680 part_name = METADATA_PART_1;
681 } else {
682 part_name = METADATA_PART_2;
683 }
684
685 return plat_set_image_source(image_id, handle, image_spec,
686 part_name);
687}
Sughosh Ganub721f8a2021-12-01 16:45:11 +0530688#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */