From c2f6f35b3a23a8c598dc0f13f7248f3567d8aaa2 Mon Sep 17 00:00:00 2001 From: Karthikeyan Ramasubramanian Date: Fri, 10 Sep 2021 12:03:30 -0600 Subject: [PATCH] soc/amd/common/psp_verstage: Introduce boot device driver PSP verstage can access the boot device either in Programmed I/O mode or DMA mode. Introduce a boot device driver and use the appropriate mode based on the SoC support. BUG=b:194990811 TEST=Build and boot to OS in Guybrush. Change-Id: I8ca5290156199548916852e48f4e11de7cb886fb Signed-off-by: Karthikeyan Ramasubramanian Reviewed-on: https://review.coreboot.org/c/coreboot/+/57563 Reviewed-by: Raul Rangel Tested-by: build bot (Jenkins) --- src/soc/amd/common/Kconfig.common | 1 + src/soc/amd/common/psp_verstage/Kconfig | 7 ++ src/soc/amd/common/psp_verstage/Makefile.inc | 1 + src/soc/amd/common/psp_verstage/boot_dev.c | 85 +++++++++++++++++++ .../amd/common/psp_verstage/psp_verstage.c | 24 ++---- 5 files changed, 102 insertions(+), 16 deletions(-) create mode 100644 src/soc/amd/common/psp_verstage/Kconfig create mode 100644 src/soc/amd/common/psp_verstage/boot_dev.c diff --git a/src/soc/amd/common/Kconfig.common b/src/soc/amd/common/Kconfig.common index d6f9d01784..5a84f2fdda 100644 --- a/src/soc/amd/common/Kconfig.common +++ b/src/soc/amd/common/Kconfig.common @@ -8,5 +8,6 @@ if SOC_AMD_COMMON source "src/soc/amd/common/block/*/Kconfig" source "src/soc/amd/common/fsp/Kconfig" source "src/soc/amd/common/pi/Kconfig" +source "src/soc/amd/common/psp_verstage/Kconfig" endif # SOC_AMD_COMMON diff --git a/src/soc/amd/common/psp_verstage/Kconfig b/src/soc/amd/common/psp_verstage/Kconfig new file mode 100644 index 0000000000..834abaaa5f --- /dev/null +++ b/src/soc/amd/common/psp_verstage/Kconfig @@ -0,0 +1,7 @@ +config PSP_VERSTAGE_CCP_DMA + bool + default n + help + Configure PSP Verstage to use Crypto Co-processor (CCP) DMA while + accessing the boot device. Select it on platforms which supports + using CCP DMA to access the boot device. diff --git a/src/soc/amd/common/psp_verstage/Makefile.inc b/src/soc/amd/common/psp_verstage/Makefile.inc index a913a5ba56..fb82ef4869 100644 --- a/src/soc/amd/common/psp_verstage/Makefile.inc +++ b/src/soc/amd/common/psp_verstage/Makefile.inc @@ -7,6 +7,7 @@ CPPFLAGS_common += -I$(VBOOT_SOURCE)/firmware/2lib/include/ # This size should match the size in the linker script. CFLAGS_arm += -Wstack-usage=40960 +verstage-y += boot_dev.c verstage-y += delay.c verstage-y += fch.c verstage-y += pmutil.c diff --git a/src/soc/amd/common/psp_verstage/boot_dev.c b/src/soc/amd/common/psp_verstage/boot_dev.c new file mode 100644 index 0000000000..5b25d59624 --- /dev/null +++ b/src/soc/amd/common/psp_verstage/boot_dev.c @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "psp_verstage.h" + +#include +#include +#include +#include +#include +#include + +#define DEST_BUF_ALIGNMENT 16 + +static void *boot_dev_mmap(const struct region_device *rd, size_t offset, size_t size __unused) +{ + const struct mem_region_device *mdev; + + mdev = container_of(rd, __typeof__(*mdev), rdev); + + return &(mdev->base[offset]); +} + +static int boot_dev_munmap(const struct region_device *rd __unused, void *mapping __unused) +{ + return 0; +} + +static ssize_t boot_dev_dma_readat(const struct region_device *rd, void *dest, + size_t offset, size_t size) +{ + size_t memcpy_size = ALIGN_UP((uintptr_t)dest, DEST_BUF_ALIGNMENT) - (uintptr_t)dest; + const struct mem_region_device *mdev = container_of(rd, __typeof__(*mdev), rdev); + int ret; + + if (memcpy_size > size) + 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); + + dest = ((char *)dest + memcpy_size); + offset += memcpy_size; + size -= memcpy_size; + if (!size) + return memcpy_size; + + ret = svc_ccp_dma((uint32_t)offset, dest, (uint32_t)size); + if (ret != BL_OK) { + printk(BIOS_ERR, "%s: Failed dest:%p offset:%zu size:%zu ret:%d\n", + __func__, dest, offset, size, ret); + return -1; + } + + return size + memcpy_size; +} + +static ssize_t boot_dev_readat(const struct region_device *rd, void *dest, + size_t offset, size_t size) +{ + const struct mem_region_device *mdev = container_of(rd, __typeof__(*mdev), rdev); + + if (CONFIG(PSP_VERSTAGE_CCP_DMA)) + return boot_dev_dma_readat(rd, dest, offset, size); + + memcpy(dest, &(mdev->base[offset]), size); + return size; +} + +const struct region_device_ops boot_dev_rdev_ro_ops = { + .mmap = boot_dev_mmap, + .munmap = boot_dev_munmap, + .readat = boot_dev_readat, +}; + +static struct mem_region_device boot_dev = { + .rdev = REGION_DEV_INIT(&boot_dev_rdev_ro_ops, 0, CONFIG_ROM_SIZE), +}; + +const struct region_device *boot_device_ro(void) +{ + if (!boot_dev.base) + boot_dev.base = (void *)map_spi_rom(); + return &boot_dev.rdev; +} diff --git a/src/soc/amd/common/psp_verstage/psp_verstage.c b/src/soc/amd/common/psp_verstage/psp_verstage.c index 5c59c4f4e4..7c37355594 100644 --- a/src/soc/amd/common/psp_verstage/psp_verstage.c +++ b/src/soc/amd/common/psp_verstage/psp_verstage.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -20,8 +21,6 @@ #include extern char _bss_start, _bss_end; -static struct mem_region_device boot_dev = - MEM_REGION_DEV_RO_INIT(NULL, CONFIG_ROM_SIZE); void __weak verstage_mainboard_early_init(void) {} void __weak verstage_mainboard_init(void) {} @@ -82,6 +81,7 @@ static uint32_t update_boot_region(struct vb2_context *ctx) uint32_t *psp_dir_in_spi, *bios_dir_in_spi; const char *fname; void *amdfw_location; + void *boot_dev_base = rdev_mmap_full(boot_device_ro()); /* Continue booting from RO */ if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) { @@ -109,9 +109,9 @@ static uint32_t update_boot_region(struct vb2_context *ctx) psp_dir_addr = ef_table->psp_table; 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)boot_dev_base); bios_dir_in_spi = (uint32_t *)((bios_dir_addr & SPI_ADDR_MASK) + - (uint32_t)boot_dev.base); + (uint32_t)boot_dev_base); if (*psp_dir_in_spi != PSP_COOKIE) { printk(BIOS_ERR, "Error: PSP Directory address is not correct.\n"); return POSTCODE_PSP_COOKIE_MISMATCH_ERROR; @@ -200,6 +200,7 @@ void Main(void) { uint32_t retval; struct vb2_context *ctx = NULL; + void *boot_dev_base; /* * Do not use printk() before console_init() @@ -259,8 +260,9 @@ void Main(void) post_code(POSTCODE_UNMAP_SPI_ROM); - if (boot_dev.base) { - if (svc_unmap_spi_rom((void *)boot_dev.base)) + 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"); } @@ -273,16 +275,6 @@ void Main(void) svc_exit(retval); } -const struct region_device *boot_device_ro(void) -{ - uintptr_t *addr; - - addr = map_spi_rom(); - mem_region_device_ro_init(&boot_dev, (void *)addr, CONFIG_ROM_SIZE); - - return &boot_dev.rdev; -} - /* * The stage_entry function is not used directly, but stage_entry() is marked as an entry * point in arm/arch/header.h, so if stage_entry() isn't present and calling Main(), all