1c9d75b3cSYann Gautier /* 2cddf1bd7SYann Gautier * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. 3c9d75b3cSYann Gautier * 4c9d75b3cSYann Gautier * SPDX-License-Identifier: BSD-3-Clause 5c9d75b3cSYann Gautier */ 6c9d75b3cSYann Gautier 7c9d75b3cSYann Gautier #include <assert.h> 8c9d75b3cSYann Gautier #include <string.h> 9c9d75b3cSYann Gautier 10c9d75b3cSYann Gautier #include <arch_helpers.h> 11c9d75b3cSYann Gautier #include <common/debug.h> 1218b415beSYann Gautier #include <common/desc_image_load.h> 13c9d75b3cSYann Gautier #include <drivers/io/io_block.h> 14c9d75b3cSYann Gautier #include <drivers/io/io_driver.h> 151d204ee4SYann Gautier #include <drivers/io/io_fip.h> 1612e21dfdSLionel Debieve #include <drivers/io/io_mtd.h> 17c9d75b3cSYann Gautier #include <drivers/io/io_storage.h> 18c9d75b3cSYann Gautier #include <drivers/mmc.h> 19c9d75b3cSYann Gautier #include <drivers/partition/partition.h> 2012e21dfdSLionel Debieve #include <drivers/raw_nand.h> 2157044228SLionel Debieve #include <drivers/spi_nand.h> 22b1b218fbSLionel Debieve #include <drivers/spi_nor.h> 23c9d75b3cSYann Gautier #include <drivers/st/io_mmc.h> 2412e21dfdSLionel Debieve #include <drivers/st/stm32_fmc2_nand.h> 2557044228SLionel Debieve #include <drivers/st/stm32_qspi.h> 26c9d75b3cSYann Gautier #include <drivers/st/stm32_sdmmc2.h> 27*d5a84eeaSYann Gautier #include <lib/fconf/fconf.h> 28c9d75b3cSYann Gautier #include <lib/mmio.h> 29c9d75b3cSYann Gautier #include <lib/utils.h> 30c9d75b3cSYann Gautier #include <plat/common/platform.h> 311d204ee4SYann Gautier #include <tools_share/firmware_image_package.h> 321d204ee4SYann Gautier 331d204ee4SYann Gautier #include <platform_def.h> 34*d5a84eeaSYann Gautier #include <stm32mp_fconf_getter.h> 35c9d75b3cSYann Gautier 36c9d75b3cSYann Gautier /* IO devices */ 371d204ee4SYann Gautier uintptr_t fip_dev_handle; 381d204ee4SYann Gautier uintptr_t storage_dev_handle; 39c9d75b3cSYann Gautier 401d204ee4SYann Gautier static const io_dev_connector_t *fip_dev_con; 41c9d75b3cSYann Gautier 4246554b64SNicolas Le Bayon #if STM32MP_SDMMC || STM32MP_EMMC 43cddf1bd7SYann Gautier static struct mmc_device_info mmc_info; 44c9d75b3cSYann Gautier 45c9d75b3cSYann Gautier static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE); 46c9d75b3cSYann Gautier 4718b415beSYann Gautier static io_block_dev_spec_t mmc_block_dev_spec = { 48c9d75b3cSYann Gautier /* It's used as temp buffer in block driver */ 49c9d75b3cSYann Gautier .buffer = { 50c9d75b3cSYann Gautier .offset = (size_t)&block_buffer, 51c9d75b3cSYann Gautier .length = MMC_BLOCK_SIZE, 52c9d75b3cSYann Gautier }, 53c9d75b3cSYann Gautier .ops = { 54c9d75b3cSYann Gautier .read = mmc_read_blocks, 55c9d75b3cSYann Gautier .write = NULL, 56c9d75b3cSYann Gautier }, 57c9d75b3cSYann Gautier .block_size = MMC_BLOCK_SIZE, 58c9d75b3cSYann Gautier }; 59c9d75b3cSYann Gautier 60c9d75b3cSYann Gautier static const io_dev_connector_t *mmc_dev_con; 6146554b64SNicolas Le Bayon #endif /* STM32MP_SDMMC || STM32MP_EMMC */ 62c9d75b3cSYann Gautier 63b1b218fbSLionel Debieve #if STM32MP_SPI_NOR 64b1b218fbSLionel Debieve static io_mtd_dev_spec_t spi_nor_dev_spec = { 65b1b218fbSLionel Debieve .ops = { 66b1b218fbSLionel Debieve .init = spi_nor_init, 67b1b218fbSLionel Debieve .read = spi_nor_read, 68b1b218fbSLionel Debieve }, 69b1b218fbSLionel Debieve }; 70b1b218fbSLionel Debieve #endif 71b1b218fbSLionel Debieve 7212e21dfdSLionel Debieve #if STM32MP_RAW_NAND 7312e21dfdSLionel Debieve static io_mtd_dev_spec_t nand_dev_spec = { 7412e21dfdSLionel Debieve .ops = { 7512e21dfdSLionel Debieve .init = nand_raw_init, 7612e21dfdSLionel Debieve .read = nand_read, 771d204ee4SYann Gautier .seek = nand_seek_bb 7812e21dfdSLionel Debieve }, 7912e21dfdSLionel Debieve }; 8012e21dfdSLionel Debieve 8112e21dfdSLionel Debieve static const io_dev_connector_t *nand_dev_con; 8212e21dfdSLionel Debieve #endif 8312e21dfdSLionel Debieve 8457044228SLionel Debieve #if STM32MP_SPI_NAND 8557044228SLionel Debieve static io_mtd_dev_spec_t spi_nand_dev_spec = { 8657044228SLionel Debieve .ops = { 8757044228SLionel Debieve .init = spi_nand_init, 8857044228SLionel Debieve .read = nand_read, 891d204ee4SYann Gautier .seek = nand_seek_bb 9057044228SLionel Debieve }, 9157044228SLionel Debieve }; 92b1b218fbSLionel Debieve #endif 9357044228SLionel Debieve 94b1b218fbSLionel Debieve #if STM32MP_SPI_NAND || STM32MP_SPI_NOR 9557044228SLionel Debieve static const io_dev_connector_t *spi_dev_con; 9657044228SLionel Debieve #endif 9757044228SLionel Debieve 98*d5a84eeaSYann Gautier io_block_spec_t image_block_spec = { 991d204ee4SYann Gautier .offset = 0U, 1001d204ee4SYann Gautier .length = 0U, 101c9d75b3cSYann Gautier }; 102c9d75b3cSYann Gautier 103*d5a84eeaSYann Gautier int open_fip(const uintptr_t spec) 104c9d75b3cSYann Gautier { 1051d204ee4SYann Gautier return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); 106c9d75b3cSYann Gautier } 107c9d75b3cSYann Gautier 108*d5a84eeaSYann Gautier int open_storage(const uintptr_t spec) 109c9d75b3cSYann Gautier { 110c9d75b3cSYann Gautier return io_dev_init(storage_dev_handle, 0); 111c9d75b3cSYann Gautier } 112c9d75b3cSYann Gautier 113c9d75b3cSYann Gautier static void print_boot_device(boot_api_context_t *boot_context) 114c9d75b3cSYann Gautier { 115c9d75b3cSYann Gautier switch (boot_context->boot_interface_selected) { 116c9d75b3cSYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: 117c9d75b3cSYann Gautier INFO("Using SDMMC\n"); 118c9d75b3cSYann Gautier break; 119c9d75b3cSYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: 120c9d75b3cSYann Gautier INFO("Using EMMC\n"); 121c9d75b3cSYann Gautier break; 122b1b218fbSLionel Debieve case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: 123b1b218fbSLionel Debieve INFO("Using QSPI NOR\n"); 124b1b218fbSLionel Debieve break; 12512e21dfdSLionel Debieve case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: 12612e21dfdSLionel Debieve INFO("Using FMC NAND\n"); 12712e21dfdSLionel Debieve break; 12857044228SLionel Debieve case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: 12957044228SLionel Debieve INFO("Using SPI NAND\n"); 13057044228SLionel Debieve break; 131c9d75b3cSYann Gautier default: 1321d204ee4SYann Gautier ERROR("Boot interface %u not found\n", 1331d204ee4SYann Gautier boot_context->boot_interface_selected); 134c9d75b3cSYann Gautier panic(); 135c9d75b3cSYann Gautier break; 136c9d75b3cSYann Gautier } 137c9d75b3cSYann Gautier 138c9d75b3cSYann Gautier if (boot_context->boot_interface_instance != 0U) { 139c9d75b3cSYann Gautier INFO(" Instance %d\n", boot_context->boot_interface_instance); 140c9d75b3cSYann Gautier } 141c9d75b3cSYann Gautier } 142c9d75b3cSYann Gautier 14346554b64SNicolas Le Bayon #if STM32MP_SDMMC || STM32MP_EMMC 1440b1aa772SYann Gautier static void boot_mmc(enum mmc_device_type mmc_dev_type, 1450b1aa772SYann Gautier uint16_t boot_interface_instance) 146c9d75b3cSYann Gautier { 147c9d75b3cSYann Gautier int io_result __unused; 148c9d75b3cSYann Gautier struct stm32_sdmmc2_params params; 149c9d75b3cSYann Gautier 15042beea8dSYann Gautier zeromem(¶ms, sizeof(struct stm32_sdmmc2_params)); 151c9d75b3cSYann Gautier 152cddf1bd7SYann Gautier mmc_info.mmc_dev_type = mmc_dev_type; 153c9d75b3cSYann Gautier 1540b1aa772SYann Gautier switch (boot_interface_instance) { 155c9d75b3cSYann Gautier case 1: 1563f9c9784SYann Gautier params.reg_base = STM32MP_SDMMC1_BASE; 157c9d75b3cSYann Gautier break; 158c9d75b3cSYann Gautier case 2: 1593f9c9784SYann Gautier params.reg_base = STM32MP_SDMMC2_BASE; 160c9d75b3cSYann Gautier break; 161c9d75b3cSYann Gautier case 3: 1623f9c9784SYann Gautier params.reg_base = STM32MP_SDMMC3_BASE; 163c9d75b3cSYann Gautier break; 164c9d75b3cSYann Gautier default: 165c9d75b3cSYann Gautier WARN("SDMMC instance not found, using default\n"); 1660b1aa772SYann Gautier if (mmc_dev_type == MMC_IS_SD) { 1670b1aa772SYann Gautier params.reg_base = STM32MP_SDMMC1_BASE; 1680b1aa772SYann Gautier } else { 1690b1aa772SYann Gautier params.reg_base = STM32MP_SDMMC2_BASE; 1700b1aa772SYann Gautier } 171c9d75b3cSYann Gautier break; 172c9d75b3cSYann Gautier } 173c9d75b3cSYann Gautier 174cddf1bd7SYann Gautier params.device_info = &mmc_info; 175c9d75b3cSYann Gautier if (stm32_sdmmc2_mmc_init(¶ms) != 0) { 1760b1aa772SYann Gautier ERROR("SDMMC%u init failed\n", boot_interface_instance); 177c9d75b3cSYann Gautier panic(); 178c9d75b3cSYann Gautier } 179c9d75b3cSYann Gautier 180c9d75b3cSYann Gautier /* Open MMC as a block device to read GPT table */ 181c9d75b3cSYann Gautier io_result = register_io_dev_block(&mmc_dev_con); 182c9d75b3cSYann Gautier if (io_result != 0) { 183c9d75b3cSYann Gautier panic(); 184c9d75b3cSYann Gautier } 185c9d75b3cSYann Gautier 1860b1aa772SYann Gautier io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_spec, 187c9d75b3cSYann Gautier &storage_dev_handle); 188c9d75b3cSYann Gautier assert(io_result == 0); 1890b1aa772SYann Gautier } 19046554b64SNicolas Le Bayon #endif /* STM32MP_SDMMC || STM32MP_EMMC */ 1910b1aa772SYann Gautier 192b1b218fbSLionel Debieve #if STM32MP_SPI_NOR 193b1b218fbSLionel Debieve static void boot_spi_nor(boot_api_context_t *boot_context) 194b1b218fbSLionel Debieve { 195b1b218fbSLionel Debieve int io_result __unused; 196b1b218fbSLionel Debieve 197b1b218fbSLionel Debieve io_result = stm32_qspi_init(); 198b1b218fbSLionel Debieve assert(io_result == 0); 199b1b218fbSLionel Debieve 200b1b218fbSLionel Debieve io_result = register_io_dev_mtd(&spi_dev_con); 201b1b218fbSLionel Debieve assert(io_result == 0); 202b1b218fbSLionel Debieve 203b1b218fbSLionel Debieve /* Open connections to device */ 204b1b218fbSLionel Debieve io_result = io_dev_open(spi_dev_con, 205b1b218fbSLionel Debieve (uintptr_t)&spi_nor_dev_spec, 206b1b218fbSLionel Debieve &storage_dev_handle); 207b1b218fbSLionel Debieve assert(io_result == 0); 208b1b218fbSLionel Debieve } 209b1b218fbSLionel Debieve #endif /* STM32MP_SPI_NOR */ 210b1b218fbSLionel Debieve 21112e21dfdSLionel Debieve #if STM32MP_RAW_NAND 21212e21dfdSLionel Debieve static void boot_fmc2_nand(boot_api_context_t *boot_context) 21312e21dfdSLionel Debieve { 21412e21dfdSLionel Debieve int io_result __unused; 21512e21dfdSLionel Debieve 21612e21dfdSLionel Debieve io_result = stm32_fmc2_init(); 21712e21dfdSLionel Debieve assert(io_result == 0); 21812e21dfdSLionel Debieve 21912e21dfdSLionel Debieve /* Register the IO device on this platform */ 22012e21dfdSLionel Debieve io_result = register_io_dev_mtd(&nand_dev_con); 22112e21dfdSLionel Debieve assert(io_result == 0); 22212e21dfdSLionel Debieve 22312e21dfdSLionel Debieve /* Open connections to device */ 22412e21dfdSLionel Debieve io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec, 22512e21dfdSLionel Debieve &storage_dev_handle); 22612e21dfdSLionel Debieve assert(io_result == 0); 22712e21dfdSLionel Debieve } 22812e21dfdSLionel Debieve #endif /* STM32MP_RAW_NAND */ 22912e21dfdSLionel Debieve 23057044228SLionel Debieve #if STM32MP_SPI_NAND 23157044228SLionel Debieve static void boot_spi_nand(boot_api_context_t *boot_context) 23257044228SLionel Debieve { 23357044228SLionel Debieve int io_result __unused; 23457044228SLionel Debieve 23557044228SLionel Debieve io_result = stm32_qspi_init(); 23657044228SLionel Debieve assert(io_result == 0); 23757044228SLionel Debieve 23857044228SLionel Debieve io_result = register_io_dev_mtd(&spi_dev_con); 23957044228SLionel Debieve assert(io_result == 0); 24057044228SLionel Debieve 24157044228SLionel Debieve /* Open connections to device */ 24257044228SLionel Debieve io_result = io_dev_open(spi_dev_con, 24357044228SLionel Debieve (uintptr_t)&spi_nand_dev_spec, 24457044228SLionel Debieve &storage_dev_handle); 24557044228SLionel Debieve assert(io_result == 0); 24657044228SLionel Debieve } 24757044228SLionel Debieve #endif /* STM32MP_SPI_NAND */ 24857044228SLionel Debieve 2490b1aa772SYann Gautier void stm32mp_io_setup(void) 2500b1aa772SYann Gautier { 2510b1aa772SYann Gautier int io_result __unused; 2520b1aa772SYann Gautier boot_api_context_t *boot_context = 2530b1aa772SYann Gautier (boot_api_context_t *)stm32mp_get_boot_ctx_address(); 2540b1aa772SYann Gautier 2550b1aa772SYann Gautier print_boot_device(boot_context); 2560b1aa772SYann Gautier 2570b1aa772SYann Gautier if ((boot_context->boot_partition_used_toboot == 1U) || 2580b1aa772SYann Gautier (boot_context->boot_partition_used_toboot == 2U)) { 2591d204ee4SYann Gautier INFO("Boot used partition fsbl%u\n", 2600b1aa772SYann Gautier boot_context->boot_partition_used_toboot); 2610b1aa772SYann Gautier } 2620b1aa772SYann Gautier 2631d204ee4SYann Gautier io_result = register_io_dev_fip(&fip_dev_con); 2640b1aa772SYann Gautier assert(io_result == 0); 2650b1aa772SYann Gautier 2661d204ee4SYann Gautier io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, 2671d204ee4SYann Gautier &fip_dev_handle); 2680b1aa772SYann Gautier 2690b1aa772SYann Gautier switch (boot_context->boot_interface_selected) { 27046554b64SNicolas Le Bayon #if STM32MP_SDMMC 2710b1aa772SYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: 2720b1aa772SYann Gautier dmbsy(); 2730b1aa772SYann Gautier boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance); 2740b1aa772SYann Gautier break; 27546554b64SNicolas Le Bayon #endif 27646554b64SNicolas Le Bayon #if STM32MP_EMMC 2770b1aa772SYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: 2780b1aa772SYann Gautier dmbsy(); 2790b1aa772SYann Gautier boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance); 280c9d75b3cSYann Gautier break; 28146554b64SNicolas Le Bayon #endif 282b1b218fbSLionel Debieve #if STM32MP_SPI_NOR 283b1b218fbSLionel Debieve case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: 284b1b218fbSLionel Debieve dmbsy(); 285b1b218fbSLionel Debieve boot_spi_nor(boot_context); 286b1b218fbSLionel Debieve break; 287b1b218fbSLionel Debieve #endif 28812e21dfdSLionel Debieve #if STM32MP_RAW_NAND 28912e21dfdSLionel Debieve case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: 29012e21dfdSLionel Debieve dmbsy(); 29112e21dfdSLionel Debieve boot_fmc2_nand(boot_context); 29212e21dfdSLionel Debieve break; 29312e21dfdSLionel Debieve #endif 29457044228SLionel Debieve #if STM32MP_SPI_NAND 29557044228SLionel Debieve case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: 29657044228SLionel Debieve dmbsy(); 29757044228SLionel Debieve boot_spi_nand(boot_context); 29857044228SLionel Debieve break; 29957044228SLionel Debieve #endif 300c9d75b3cSYann Gautier 301c9d75b3cSYann Gautier default: 302c9d75b3cSYann Gautier ERROR("Boot interface %d not supported\n", 303c9d75b3cSYann Gautier boot_context->boot_interface_selected); 30471693a66SYann Gautier panic(); 305c9d75b3cSYann Gautier break; 306c9d75b3cSYann Gautier } 307c9d75b3cSYann Gautier } 308c9d75b3cSYann Gautier 3091d204ee4SYann Gautier int bl2_plat_handle_pre_image_load(unsigned int image_id) 3101d204ee4SYann Gautier { 3111d204ee4SYann Gautier static bool gpt_init_done __unused; 3121d204ee4SYann Gautier uint16_t boot_itf = stm32mp_get_boot_itf_selected(); 3131d204ee4SYann Gautier 3141d204ee4SYann Gautier switch (boot_itf) { 3151d204ee4SYann Gautier #if STM32MP_SDMMC || STM32MP_EMMC 3161d204ee4SYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: 3171d204ee4SYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: 3181d204ee4SYann Gautier if (!gpt_init_done) { 3191d204ee4SYann Gautier const partition_entry_t *entry; 3201d204ee4SYann Gautier 3211d204ee4SYann Gautier partition_init(GPT_IMAGE_ID); 3221d204ee4SYann Gautier entry = get_partition_entry(FIP_IMAGE_NAME); 3231d204ee4SYann Gautier if (entry == NULL) { 3241d204ee4SYann Gautier ERROR("Could NOT find the %s partition!\n", 3251d204ee4SYann Gautier FIP_IMAGE_NAME); 3261d204ee4SYann Gautier return -ENOENT; 3271d204ee4SYann Gautier } 3281d204ee4SYann Gautier 3291d204ee4SYann Gautier image_block_spec.offset = entry->start; 3301d204ee4SYann Gautier image_block_spec.length = entry->length; 3311d204ee4SYann Gautier 3321d204ee4SYann Gautier gpt_init_done = true; 33318b415beSYann Gautier } else { 33418b415beSYann Gautier bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); 33518b415beSYann Gautier 33618b415beSYann Gautier mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base; 33718b415beSYann Gautier mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size; 3381d204ee4SYann Gautier } 3391d204ee4SYann Gautier 3401d204ee4SYann Gautier break; 3411d204ee4SYann Gautier #endif 3421d204ee4SYann Gautier 3431d204ee4SYann Gautier #if STM32MP_RAW_NAND || STM32MP_SPI_NAND 3441d204ee4SYann Gautier #if STM32MP_RAW_NAND 3451d204ee4SYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: 3461d204ee4SYann Gautier #endif 3471d204ee4SYann Gautier #if STM32MP_SPI_NAND 3481d204ee4SYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: 3491d204ee4SYann Gautier #endif 3501d204ee4SYann Gautier image_block_spec.offset = STM32MP_NAND_FIP_OFFSET; 3511d204ee4SYann Gautier break; 3521d204ee4SYann Gautier #endif 3531d204ee4SYann Gautier 3541d204ee4SYann Gautier #if STM32MP_SPI_NOR 3551d204ee4SYann Gautier case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: 3561d204ee4SYann Gautier image_block_spec.offset = STM32MP_NOR_FIP_OFFSET; 3571d204ee4SYann Gautier break; 3581d204ee4SYann Gautier #endif 3591d204ee4SYann Gautier 3601d204ee4SYann Gautier default: 3611d204ee4SYann Gautier ERROR("FIP Not found\n"); 3621d204ee4SYann Gautier panic(); 3631d204ee4SYann Gautier } 3641d204ee4SYann Gautier 3651d204ee4SYann Gautier return 0; 3661d204ee4SYann Gautier } 3671d204ee4SYann Gautier 368c9d75b3cSYann Gautier /* 369c9d75b3cSYann Gautier * Return an IO device handle and specification which can be used to access 370c9d75b3cSYann Gautier * an image. Use this to enforce platform load policy. 371c9d75b3cSYann Gautier */ 372c9d75b3cSYann Gautier int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, 373c9d75b3cSYann Gautier uintptr_t *image_spec) 374c9d75b3cSYann Gautier { 375c9d75b3cSYann Gautier int rc; 376c9d75b3cSYann Gautier const struct plat_io_policy *policy; 377c9d75b3cSYann Gautier 378*d5a84eeaSYann Gautier policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id); 379c9d75b3cSYann Gautier rc = policy->check(policy->image_spec); 380c9d75b3cSYann Gautier if (rc == 0) { 381c9d75b3cSYann Gautier *image_spec = policy->image_spec; 382c9d75b3cSYann Gautier *dev_handle = *(policy->dev_handle); 383c9d75b3cSYann Gautier } 384c9d75b3cSYann Gautier 385c9d75b3cSYann Gautier return rc; 386c9d75b3cSYann Gautier } 387