diff options
-rw-r--r-- | src/soc/amd/common/psp_verstage/boot_dev.c | 51 | ||||
-rw-r--r-- | src/soc/amd/common/psp_verstage/fch.c | 9 | ||||
-rw-r--r-- | src/soc/amd/common/psp_verstage/include/psp_verstage.h | 6 | ||||
-rw-r--r-- | src/soc/amd/common/psp_verstage/psp_verstage.c | 39 |
4 files changed, 75 insertions, 30 deletions
diff --git a/src/soc/amd/common/psp_verstage/boot_dev.c b/src/soc/amd/common/psp_verstage/boot_dev.c index 4ee78b8349..c129479059 100644 --- a/src/soc/amd/common/psp_verstage/boot_dev.c +++ b/src/soc/amd/common/psp_verstage/boot_dev.c @@ -11,22 +11,51 @@ #define DEST_BUF_ALIGNMENT 16 -static void *boot_dev_mmap(const struct region_device *rd, size_t offset, - size_t size __always_unused) +static uint32_t active_map_count; + +static void *boot_dev_mmap(const struct region_device *rd, size_t offset, size_t size) { const struct mem_region_device *mdev; + void *mapping = NULL; + uint32_t ret; mdev = container_of(rd, __typeof__(*mdev), rdev); - return &(mdev->base[offset]); + if (mdev->base) { + if ((ret = svc_map_spi_rom(&mdev->base[offset], size, (void **)&mapping)) + != BL_OK) + printk(BIOS_ERR, "Failed(%d) to map SPI ROM offset: %zu, size: %zu\n", + ret, offset, size); + else + active_map_count++; + } + + return mapping; } -static int boot_dev_munmap(const struct region_device *rd __always_unused, - void *mapping __always_unused) +static int boot_dev_munmap(const struct region_device *rd, void *mapping) { + uint32_t ret; + + active_map_count--; + if ((ret = svc_unmap_spi_rom(mapping)) != BL_OK) + printk(BIOS_ERR, "Failed(%d) to unmap SPI ROM mapping %p\n", ret, mapping); return 0; } +static ssize_t boot_dev_mmap_readat(const struct region_device *rd, void *dest, + size_t offset, size_t size) +{ + void *mapping = boot_dev_mmap(rd, offset, size); + + if (!mapping) + return -1; + + memcpy(dest, mapping, size); + boot_dev_munmap(rd, mapping); + return size; +} + static ssize_t boot_dev_dma_readat(const struct region_device *rd, void *dest, size_t offset, size_t size) { @@ -38,8 +67,8 @@ static ssize_t boot_dev_dma_readat(const struct region_device *rd, void *dest, memcpy_size = size; /* Alignment requirement is only on dest buffer for CCP DMA. So do a memcpy until the destination buffer alignment requirement is met. */ - if (memcpy_size) - memcpy(dest, &(mdev->base[offset]), memcpy_size); + if (memcpy_size && boot_dev_mmap_readat(rd, dest, offset, memcpy_size) != memcpy_size) + return -1; dest = ((char *)dest + memcpy_size); offset += memcpy_size; @@ -65,8 +94,7 @@ static ssize_t boot_dev_readat(const struct region_device *rd, void *dest, if (CONFIG(PSP_VERSTAGE_CCP_DMA)) return boot_dev_dma_readat(rd, dest, offset, size); - memcpy(dest, &(mdev->base[offset]), size); - return size; + return boot_dev_mmap_readat(rd, dest, offset, size); } const struct region_device_ops boot_dev_rdev_ro_ops = { @@ -85,3 +113,8 @@ const struct region_device *boot_device_ro(void) boot_dev.base = (void *)map_spi_rom(); return &boot_dev.rdev; } + +uint32_t boot_dev_get_active_map_count(void) +{ + return active_map_count; +} diff --git a/src/soc/amd/common/psp_verstage/fch.c b/src/soc/amd/common/psp_verstage/fch.c index 7f850fd149..0517545f16 100644 --- a/src/soc/amd/common/psp_verstage/fch.c +++ b/src/soc/amd/common/psp_verstage/fch.c @@ -90,19 +90,14 @@ static struct { {"AOAC", {FCH_IO_DEVICE_AOAC}, aoac_set_bar}, }; -uintptr_t *map_spi_rom(void) +void *map_spi_rom(void) { - uintptr_t *addr = NULL; struct spirom_info spi = {0}; if (svc_get_spi_rom_info(&spi)) printk(BIOS_DEBUG, "Error getting SPI ROM info.\n"); - if (spi.SpiBiosSmnBase != 0) - if (svc_map_spi_rom(spi.SpiBiosSmnBase, CONFIG_ROM_SIZE, (void **)&addr)) - printk(BIOS_DEBUG, "Error mapping SPI ROM to address.\n"); - - return addr; + return spi.SpiBiosSmnBase; } static uint32_t map_fch_devices(void) diff --git a/src/soc/amd/common/psp_verstage/include/psp_verstage.h b/src/soc/amd/common/psp_verstage/include/psp_verstage.h index c3240fab56..6c5d4c0acf 100644 --- a/src/soc/amd/common/psp_verstage/include/psp_verstage.h +++ b/src/soc/amd/common/psp_verstage/include/psp_verstage.h @@ -38,7 +38,7 @@ #define POSTCODE_CMOS_RECOVERY 0xCA #define POSTCODE_EARLY_INIT_ERROR 0xCB #define POSTCODE_INIT_TPM_FAILED 0xCC - +#define POSTCODE_MAP_SPI_ROM_FAILED 0xCD #define POSTCODE_UNMAP_SPI_ROM 0xF0 #define POSTCODE_UNMAP_FCH_DEVICES 0xF1 @@ -57,7 +57,7 @@ void verstage_soc_aoac_init(void); void verstage_soc_espi_init(void); void verstage_soc_i2c_init(void); void verstage_soc_spi_init(void); -uintptr_t *map_spi_rom(void); +void *map_spi_rom(void); uint32_t update_psp_bios_dir(uint32_t *psp_dir_offset, uint32_t *bios_dir_offset); uint32_t save_uapp_data(void *address, uint32_t size); @@ -72,4 +72,6 @@ void report_prev_boot_status_to_vboot(void); void report_hsp_secure_state(void); +uint32_t boot_dev_get_active_map_count(void); + #endif /* PSP_VERSTAGE_H */ diff --git a/src/soc/amd/common/psp_verstage/psp_verstage.c b/src/soc/amd/common/psp_verstage/psp_verstage.c index e5b0277ba9..dfea43d6c9 100644 --- a/src/soc/amd/common/psp_verstage/psp_verstage.c +++ b/src/soc/amd/common/psp_verstage/psp_verstage.c @@ -10,6 +10,7 @@ #include <commonlib/region.h> #include <console/console.h> #include <fmap.h> +#include <fmap_config.h> #include <pc80/mc146818rtc.h> #include <soc/iomap.h> #include <soc/psp_transfer.h> @@ -74,7 +75,8 @@ static uint32_t update_boot_region(struct vb2_context *ctx) const char *fname; const char *hash_fname; void *amdfw_location; - void *boot_dev_base = rdev_mmap_full(boot_device_ro()); + void *map_base = NULL; + size_t map_offset; /* Continue booting from RO */ if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) { @@ -85,36 +87,53 @@ static uint32_t update_boot_region(struct vb2_context *ctx) if (vboot_is_firmware_slot_a(ctx)) { fname = "apu/amdfw_a"; hash_fname = "apu/amdfw_a_hash"; + map_offset = FMAP_SECTION_FW_MAIN_A_START - FMAP_SECTION_FLASH_START; + map_base = rdev_mmap(boot_device_ro(), map_offset, FMAP_SECTION_FW_MAIN_A_SIZE); } else { fname = "apu/amdfw_b"; hash_fname = "apu/amdfw_b_hash"; + map_offset = FMAP_SECTION_FW_MAIN_B_START - FMAP_SECTION_FLASH_START; + map_base = rdev_mmap(boot_device_ro(), map_offset, FMAP_SECTION_FW_MAIN_B_SIZE); + } + + if (!map_base) { + printk(BIOS_ERR, "Failed to map RW FW_MAIN section.\n"); + return POSTCODE_MAP_SPI_ROM_FAILED; } amdfw_location = cbfs_map(fname, NULL); if (!amdfw_location) { printk(BIOS_ERR, "AMD Firmware table not found.\n"); + rdev_munmap(boot_device_ro(), map_base); return POSTCODE_AMD_FW_MISSING; } + ef_table = (struct embedded_firmware *)amdfw_location; if (ef_table->signature != EMBEDDED_FW_SIGNATURE) { printk(BIOS_ERR, "ROMSIG address is not correct.\n"); + cbfs_unmap(amdfw_location); + rdev_munmap(boot_device_ro(), map_base); return POSTCODE_ROMSIG_MISMATCH_ERROR; } psp_dir_addr = ef_table->new_psp_directory; bios_dir_addr = get_bios_dir_addr(ef_table); psp_dir_in_spi = (uint32_t *)((psp_dir_addr & SPI_ADDR_MASK) + - (uint32_t)boot_dev_base); + (uint32_t)map_base - map_offset); if (*psp_dir_in_spi != PSP_COOKIE) { printk(BIOS_ERR, "PSP Directory address is not correct.\n"); + cbfs_unmap(amdfw_location); + rdev_munmap(boot_device_ro(), map_base); return POSTCODE_PSP_COOKIE_MISMATCH_ERROR; } if (bios_dir_addr) { bios_dir_in_spi = (uint32_t *)((bios_dir_addr & SPI_ADDR_MASK) + - (uint32_t)boot_dev_base); + (uint32_t)map_base - map_offset); if (*bios_dir_in_spi != BHD_COOKIE) { printk(BIOS_ERR, "BIOS Directory address is not correct.\n"); + cbfs_unmap(amdfw_location); + rdev_munmap(boot_device_ro(), map_base); return POSTCODE_BHD_COOKIE_MISMATCH_ERROR; } } @@ -128,12 +147,16 @@ static uint32_t update_boot_region(struct vb2_context *ctx) if (update_psp_bios_dir(&psp_dir_addr, &bios_dir_addr)) { printk(BIOS_ERR, "Updated BIOS Directory could not be set.\n"); + cbfs_unmap(amdfw_location); + rdev_munmap(boot_device_ro(), map_base); return POSTCODE_UPDATE_PSP_BIOS_DIR_ERROR; } if (CONFIG(SEPARATE_SIGNED_PSPFW)) update_psp_fw_hash_table(hash_fname); + cbfs_unmap(amdfw_location); + rdev_munmap(boot_device_ro(), map_base); return 0; } @@ -208,7 +231,6 @@ void Main(void) { uint32_t retval; struct vb2_context *ctx = NULL; - void *boot_dev_base; uint32_t bootmode; /* @@ -324,14 +346,7 @@ void Main(void) if (retval) reboot_into_recovery(ctx, retval); - - post_code(POSTCODE_UNMAP_SPI_ROM); - boot_dev_base = rdev_mmap_full(boot_device_ro()); - if (boot_dev_base) { - if (svc_unmap_spi_rom((void *)boot_dev_base)) - printk(BIOS_ERR, "Error unmapping SPI rom\n"); - } - + assert(!boot_dev_get_active_map_count()); post_code(POSTCODE_UNMAP_FCH_DEVICES); unmap_fch_devices(); |