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 <kramasub@google.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/57563 Reviewed-by: Raul Rangel <rrangel@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
f0d9c1212c
commit
c2f6f35b3a
|
@ -8,5 +8,6 @@ if SOC_AMD_COMMON
|
||||||
source "src/soc/amd/common/block/*/Kconfig"
|
source "src/soc/amd/common/block/*/Kconfig"
|
||||||
source "src/soc/amd/common/fsp/Kconfig"
|
source "src/soc/amd/common/fsp/Kconfig"
|
||||||
source "src/soc/amd/common/pi/Kconfig"
|
source "src/soc/amd/common/pi/Kconfig"
|
||||||
|
source "src/soc/amd/common/psp_verstage/Kconfig"
|
||||||
|
|
||||||
endif # SOC_AMD_COMMON
|
endif # SOC_AMD_COMMON
|
||||||
|
|
|
@ -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.
|
|
@ -7,6 +7,7 @@ CPPFLAGS_common += -I$(VBOOT_SOURCE)/firmware/2lib/include/
|
||||||
# This size should match the size in the linker script.
|
# This size should match the size in the linker script.
|
||||||
CFLAGS_arm += -Wstack-usage=40960
|
CFLAGS_arm += -Wstack-usage=40960
|
||||||
|
|
||||||
|
verstage-y += boot_dev.c
|
||||||
verstage-y += delay.c
|
verstage-y += delay.c
|
||||||
verstage-y += fch.c
|
verstage-y += fch.c
|
||||||
verstage-y += pmutil.c
|
verstage-y += pmutil.c
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
|
#include "psp_verstage.h"
|
||||||
|
|
||||||
|
#include <bl_uapp/bl_errorcodes_public.h>
|
||||||
|
#include <bl_uapp/bl_syscall_public.h>
|
||||||
|
#include <boot_device.h>
|
||||||
|
#include <commonlib/region.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
#include <bl_uapp/bl_syscall_public.h>
|
#include <bl_uapp/bl_syscall_public.h>
|
||||||
#include <boot_device.h>
|
#include <boot_device.h>
|
||||||
#include <cbfs.h>
|
#include <cbfs.h>
|
||||||
|
#include <commonlib/region.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <fmap.h>
|
#include <fmap.h>
|
||||||
#include <pc80/mc146818rtc.h>
|
#include <pc80/mc146818rtc.h>
|
||||||
|
@ -20,8 +21,6 @@
|
||||||
#include <timestamp.h>
|
#include <timestamp.h>
|
||||||
|
|
||||||
extern char _bss_start, _bss_end;
|
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_early_init(void) {}
|
||||||
void __weak verstage_mainboard_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;
|
uint32_t *psp_dir_in_spi, *bios_dir_in_spi;
|
||||||
const char *fname;
|
const char *fname;
|
||||||
void *amdfw_location;
|
void *amdfw_location;
|
||||||
|
void *boot_dev_base = rdev_mmap_full(boot_device_ro());
|
||||||
|
|
||||||
/* Continue booting from RO */
|
/* Continue booting from RO */
|
||||||
if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
|
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;
|
psp_dir_addr = ef_table->psp_table;
|
||||||
bios_dir_addr = get_bios_dir_addr(ef_table);
|
bios_dir_addr = get_bios_dir_addr(ef_table);
|
||||||
psp_dir_in_spi = (uint32_t *)((psp_dir_addr & SPI_ADDR_MASK) +
|
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) +
|
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) {
|
if (*psp_dir_in_spi != PSP_COOKIE) {
|
||||||
printk(BIOS_ERR, "Error: PSP Directory address is not correct.\n");
|
printk(BIOS_ERR, "Error: PSP Directory address is not correct.\n");
|
||||||
return POSTCODE_PSP_COOKIE_MISMATCH_ERROR;
|
return POSTCODE_PSP_COOKIE_MISMATCH_ERROR;
|
||||||
|
@ -200,6 +200,7 @@ void Main(void)
|
||||||
{
|
{
|
||||||
uint32_t retval;
|
uint32_t retval;
|
||||||
struct vb2_context *ctx = NULL;
|
struct vb2_context *ctx = NULL;
|
||||||
|
void *boot_dev_base;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not use printk() before console_init()
|
* Do not use printk() before console_init()
|
||||||
|
@ -259,8 +260,9 @@ void Main(void)
|
||||||
|
|
||||||
|
|
||||||
post_code(POSTCODE_UNMAP_SPI_ROM);
|
post_code(POSTCODE_UNMAP_SPI_ROM);
|
||||||
if (boot_dev.base) {
|
boot_dev_base = rdev_mmap_full(boot_device_ro());
|
||||||
if (svc_unmap_spi_rom((void *)boot_dev.base))
|
if (boot_dev_base) {
|
||||||
|
if (svc_unmap_spi_rom((void *)boot_dev_base))
|
||||||
printk(BIOS_ERR, "Error unmapping SPI rom\n");
|
printk(BIOS_ERR, "Error unmapping SPI rom\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,16 +275,6 @@ void Main(void)
|
||||||
svc_exit(retval);
|
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
|
* 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
|
* point in arm/arch/header.h, so if stage_entry() isn't present and calling Main(), all
|
||||||
|
|
Loading…
Reference in New Issue