diff options
22 files changed, 1125 insertions, 107 deletions
diff --git a/src/soc/amd/picasso/Kconfig b/src/soc/amd/picasso/Kconfig index fd2a2053fb..5872a6fd98 100644 --- a/src/soc/amd/picasso/Kconfig +++ b/src/soc/amd/picasso/Kconfig @@ -10,7 +10,7 @@ if SOC_AMD_PICASSO config CPU_SPECIFIC_OPTIONS def_bool y select ARCH_BOOTBLOCK_X86_32 - select ARCH_VERSTAGE_X86_32 + select ARCH_VERSTAGE_X86_32 if !VBOOT_STARTS_BEFORE_BOOTBLOCK select ARCH_ROMSTAGE_X86_32 select ARCH_RAMSTAGE_X86_32 select RESET_VECTOR_IN_RAM @@ -473,6 +473,16 @@ config PSP_BOOTLOADER_FILE Note that this option may conflict with the whitelist file if a different PSP bootloader binary is specified. +config PSP_SHAREDMEM_SIZE + hex "Maximum size of shared memory area" + default 0x3000 if VBOOT + default 0x0 + help + Sets the maximum size for the PSP to pass the vboot workbuf and + any logs or timestamps back to coreboot. This will be copied + into main memory by the PSP and will be available when the x86 is + started. + config PSP_UNLOCK_SECURE_DEBUG bool "Unlock secure debug" default n @@ -481,4 +491,17 @@ config PSP_UNLOCK_SECURE_DEBUG endmenu + +config VBOOT + select VBOOT_VBNV_CMOS + select VBOOT_VBNV_CMOS_BACKUP_TO_FLASH if ! VBOOT_STARTS_BEFORE_BOOTBLOCK + +config VBOOT_STARTS_BEFORE_BOOTBLOCK + def_bool n + depends on VBOOT + select ARCH_VERSTAGE_ARMV7 + help + Runs verstage on the PSP. Only available on + certain Chrome OS branded parts from AMD. + endif # SOC_AMD_PICASSO diff --git a/src/soc/amd/picasso/Makefile.inc b/src/soc/amd/picasso/Makefile.inc index 39269e9fe2..9ea770c86c 100644 --- a/src/soc/amd/picasso/Makefile.inc +++ b/src/soc/amd/picasso/Makefile.inc @@ -9,6 +9,7 @@ subdirs-y += ../../../cpu/x86/cache subdirs-y += ../../../cpu/x86/mtrr subdirs-y += ../../../cpu/x86/pae subdirs-y += ../../../cpu/x86/smm +subdirs-$(CONFIG_VBOOT_STARTS_BEFORE_BOOTBLOCK) += psp_verstage bootblock-y += bootblock/pre_c.S bootblock-y += bootblock/bootblock.c @@ -21,11 +22,13 @@ bootblock-y += tsc_freq.c bootblock-y += gpio.c bootblock-y += smi_util.c bootblock-y += config.c +bootblock-y += ../../../arch/x86/memmove.c romstage-y += i2c.c romstage-y += romstage.c romstage-y += gpio.c romstage-y += pmutil.c +romstage-y += reset.c romstage-y += memmap.c romstage-y += uart.c romstage-$(CONFIG_PICASSO_CONSOLE_UART) += uart_console.c @@ -37,14 +40,15 @@ romstage-y += psp.c romstage-y += config.c romstage-y += mrc_cache.c -verstage-y += gpio.c verstage-y += i2c.c verstage-y += pmutil.c verstage-y += config.c verstage-y += aoac.c -verstage-y += uart.c -verstage-$(CONFIG_PICASSO_CONSOLE_UART) += uart_console.c -verstage-y += tsc_freq.c +verstage_x86-y += gpio.c +verstage_x86-y += uart.c +verstage_x86-$(CONFIG_PICASSO_CONSOLE_UART) += uart_console.c +verstage_x86-y += tsc_freq.c +verstage_x86-y += reset.c ramstage-y += i2c.c ramstage-y += chip.c @@ -58,6 +62,7 @@ ramstage-y += gpio.c ramstage-y += aoac.c ramstage-y += southbridge.c ramstage-y += pmutil.c +ramstage-y += reset.c ramstage-y += acp.c ramstage-y += sata.c ramstage-y += memmap.c @@ -75,8 +80,6 @@ ramstage-y += config.c ramstage-y += update_microcode.c ramstage-y += graphics.c -all-y += reset.c - smm-y += smihandler.c smm-y += smi_util.c smm-y += tsc_freq.c diff --git a/src/soc/amd/picasso/chip.h b/src/soc/amd/picasso/chip.h index 1dbe3d9dd4..205733a604 100644 --- a/src/soc/amd/picasso/chip.h +++ b/src/soc/amd/picasso/chip.h @@ -12,7 +12,7 @@ #include <soc/iomap.h> #include <soc/southbridge.h> #include <acpi/acpi_device.h> -#include <arch/smp/mpspec.h> +#include <arch/x86/include/arch/smp/mpspec.h> /* point from top level */ /* USB 2.0 PHY Parameters diff --git a/src/soc/amd/picasso/memlayout.ld b/src/soc/amd/picasso/memlayout.ld index 6f43ba18af..6f5d4cf82f 100644 --- a/src/soc/amd/picasso/memlayout.ld +++ b/src/soc/amd/picasso/memlayout.ld @@ -1,101 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -#include <memlayout.h> -#include <arch/header.ld> - -#define EARLY_RESERVED_DRAM_START(addr) SYMBOL(early_reserved_dram, addr) -#define EARLY_RESERVED_DRAM_END(addr) SYMBOL(eearly_reserved_dram, addr) - -#define PSP_SHAREDMEM_DRAM_START(addr) SYMBOL(psp_sharedmem_dram, addr) -#define PSP_SHAREDMEM_DRAM_END(addr) SYMBOL(epsp_sharedmem_dram, addr) - -/* - * - * +--------------------------------+ - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * reserved_dram_end +--------------------------------+ - * | | - * | verstage (if reqd) | - * | (VERSTAGE_SIZE) | - * +--------------------------------+ VERSTAGE_ADDR - * | | - * | FSP-M | - * | (FSP_M_SIZE) | - * +--------------------------------+ FSP_M_ADDR - * | |X86_RESET_VECTOR = ROMSTAGE_ADDR + ROMSTAGE_SIZE - 0x10 - * | romstage | - * | (ROMSTAGE_SIZE) | - * +--------------------------------+ ROMSTAGE_ADDR - * | bootblock | - * | (C_ENV_BOOTBLOCK_SIZE) | - * +--------------------------------+ BOOTBLOCK_ADDR - * | Unused hole | - * +--------------------------------+ - * | FMAP cache (FMAP_SIZE) | - * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + PRERAM_CBMEM_CONSOLE_SIZE + 0x200 - * | Early Timestamp region (512B) | - * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + PRERAM_CBMEM_CONSOLE_SIZE - * | Preram CBMEM console | - * | (PRERAM_CBMEM_CONSOLE_SIZE) | - * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE - * | PSP shared (vboot workbuf) | - * | (PSP_SHAREDMEM_SIZE) | - * +--------------------------------+ PSP_SHAREDMEM_BASE - * | APOB (64KiB) | - * +--------------------------------+ PSP_APOB_DRAM_ADDRESS - * | Early BSP stack | - * | (EARLYRAM_BSP_STACK_SIZE) | - * reserved_dram_start +--------------------------------+ EARLY_RESERVED_DRAM_BASE - * | DRAM | - * +--------------------------------+ 0x100000 - * | Option ROM | - * +--------------------------------+ 0xc0000 - * | Legacy VGA | - * +--------------------------------+ 0xa0000 - * | DRAM | - * +--------------------------------+ 0x0 - */ -SECTIONS -{ - DRAM_START(0x0) - - EARLY_RESERVED_DRAM_START(CONFIG_EARLY_RESERVED_DRAM_BASE) - - EARLYRAM_STACK(., CONFIG_EARLYRAM_BSP_STACK_SIZE) - REGION(apob, CONFIG_PSP_APOB_DRAM_ADDRESS, 64K, 1) - -#if CONFIG(VBOOT) - PSP_SHAREDMEM_DRAM_START(CONFIG_PSP_SHAREDMEM_BASE) - VBOOT2_WORK(., VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE) - PSP_SHAREDMEM_DRAM_END(CONFIG_PSP_SHAREDMEM_BASE + CONFIG_PSP_SHAREDMEM_SIZE) -#endif - - PRERAM_CBMEM_CONSOLE(., CONFIG_PRERAM_CBMEM_CONSOLE_SIZE) - TIMESTAMP(., 0x200) - FMAP_CACHE(., FMAP_SIZE) - - _ = ASSERT((CONFIG_BOOTBLOCK_ADDR + CONFIG_C_ENV_BOOTBLOCK_SIZE - 0x10) == CONFIG_X86_RESET_VECTOR, "Reset vector should be -0x10 from end of bootblock"); - _ = ASSERT(CONFIG_BOOTBLOCK_ADDR == ((CONFIG_BOOTBLOCK_ADDR + 0xFFFF) & 0xFFFF0000), "Bootblock must be 16 bit aligned"); - BOOTBLOCK(CONFIG_BOOTBLOCK_ADDR, CONFIG_C_ENV_BOOTBLOCK_SIZE) - ROMSTAGE(CONFIG_ROMSTAGE_ADDR, CONFIG_ROMSTAGE_SIZE) - REGION(fspm, CONFIG_FSP_M_ADDR, CONFIG_FSP_M_SIZE, 1) -#if CONFIG(VBOOT_SEPARATE_VERSTAGE) - VERSTAGE(CONFIG_VERSTAGE_ADDR, CONFIG_VERSTAGE_SIZE) -#endif - - EARLY_RESERVED_DRAM_END(.) - - RAMSTAGE(CONFIG_RAMBASE, 8M) -} - -#if ENV_BOOTBLOCK -/* Bootblock specific scripts which provide more SECTION directives. */ -#include <cpu/x86/16bit/entry16.ld> -#include <cpu/x86/16bit/reset16.ld> -#endif /* ENV_BOOTBLOCK */ +#if ENV_SEPARATE_VERSTAGE && CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK) + #include "memlayout_psp_verstage.ld" +#else + #include "memlayout_x86.ld" +#endif /* ENV_SEPARATE_VERSTAGE && CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK) */ diff --git a/src/soc/amd/picasso/memlayout_psp_verstage.ld b/src/soc/amd/picasso/memlayout_psp_verstage.ld new file mode 100644 index 0000000000..d2b409c850 --- /dev/null +++ b/src/soc/amd/picasso/memlayout_psp_verstage.ld @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <memlayout.h> + +/* + * Start of available space is 0x15000 and this is where the + * header for the user app (verstage) must be mapped. + * Size is 0x28000 bytes + */ +#define PSP_SRAM_START 0x15000 +#define PSP_SRAM_SIZE 160K + +#define VERSTAGE_START 0x15000 +#define VERSTAGE_SIZE 60K +#define VBOOT_WORK_START VERSTAGE_START + VERSTAGE_SIZE +#define VBOOT_WORK_SIZE 12K +#define FMAP_CACHE_SIZE 2K + +/* + * The temp stack can be made much smaller if needed - even 256 bytes + * should be sufficient. This is just for the function mapping the + * actual stack. + */ +#define PSP_VERSTAGE_TEMP_STACK_START 0x39000 +#define PSP_VERSTAGE_TEMP_STACK_SIZE 4K + +/* + * The top of the stack must be 4k aligned, so set the bottom as 4k aligned + * and make the size a multiple of 4k + */ +#define PSP_VERSTAGE_STACK_START 0x3B000 +#define PSP_VERSTAGE_STACK_SIZE 8K + +ENTRY(_psp_vs_start) +SECTIONS +{ + SRAM_START(PSP_SRAM_START) + _verstage = .; + + .text : { *(PSP_HEADER_DATA) } + .text : { *(.text._psp_vs_start) } + .text : { *(.text.Main) } + .text : { *(.text*) } + .rodata : { *(.rodata*) } + + .data : { *(.data*) } + .data : { *(PSP_FOOTER_DATA) } + + _bss_start = .; + .bss : { *(.bss*) } + _bss_end = .; + + _everstage = _verstage + VERSTAGE_SIZE; + + REGION(vboot2_work, VBOOT_WORK_START, VBOOT_WORK_SIZE, 64) + + FMAP_CACHE(., FMAP_SIZE) + + PSP_VERSTAGE_TEMP_STACK_END = (PSP_VERSTAGE_TEMP_STACK_START + PSP_VERSTAGE_TEMP_STACK_SIZE ); + + REGION(stack, PSP_VERSTAGE_STACK_START, PSP_VERSTAGE_STACK_SIZE, 64) + PSP_VERSTAGE_STACK_BASE = _stack; + PSP_VERSTAGE_STACK_END = _estack; + SRAM_END(PSP_SRAM_START + PSP_SRAM_SIZE) +} diff --git a/src/soc/amd/picasso/memlayout_x86.ld b/src/soc/amd/picasso/memlayout_x86.ld new file mode 100644 index 0000000000..6f43ba18af --- /dev/null +++ b/src/soc/amd/picasso/memlayout_x86.ld @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <memlayout.h> +#include <arch/header.ld> + +#define EARLY_RESERVED_DRAM_START(addr) SYMBOL(early_reserved_dram, addr) +#define EARLY_RESERVED_DRAM_END(addr) SYMBOL(eearly_reserved_dram, addr) + +#define PSP_SHAREDMEM_DRAM_START(addr) SYMBOL(psp_sharedmem_dram, addr) +#define PSP_SHAREDMEM_DRAM_END(addr) SYMBOL(epsp_sharedmem_dram, addr) + +/* + * + * +--------------------------------+ + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * reserved_dram_end +--------------------------------+ + * | | + * | verstage (if reqd) | + * | (VERSTAGE_SIZE) | + * +--------------------------------+ VERSTAGE_ADDR + * | | + * | FSP-M | + * | (FSP_M_SIZE) | + * +--------------------------------+ FSP_M_ADDR + * | |X86_RESET_VECTOR = ROMSTAGE_ADDR + ROMSTAGE_SIZE - 0x10 + * | romstage | + * | (ROMSTAGE_SIZE) | + * +--------------------------------+ ROMSTAGE_ADDR + * | bootblock | + * | (C_ENV_BOOTBLOCK_SIZE) | + * +--------------------------------+ BOOTBLOCK_ADDR + * | Unused hole | + * +--------------------------------+ + * | FMAP cache (FMAP_SIZE) | + * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + PRERAM_CBMEM_CONSOLE_SIZE + 0x200 + * | Early Timestamp region (512B) | + * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + PRERAM_CBMEM_CONSOLE_SIZE + * | Preram CBMEM console | + * | (PRERAM_CBMEM_CONSOLE_SIZE) | + * +--------------------------------+ PSP_SHAREDMEM_BASE + PSP_SHAREDMEM_SIZE + * | PSP shared (vboot workbuf) | + * | (PSP_SHAREDMEM_SIZE) | + * +--------------------------------+ PSP_SHAREDMEM_BASE + * | APOB (64KiB) | + * +--------------------------------+ PSP_APOB_DRAM_ADDRESS + * | Early BSP stack | + * | (EARLYRAM_BSP_STACK_SIZE) | + * reserved_dram_start +--------------------------------+ EARLY_RESERVED_DRAM_BASE + * | DRAM | + * +--------------------------------+ 0x100000 + * | Option ROM | + * +--------------------------------+ 0xc0000 + * | Legacy VGA | + * +--------------------------------+ 0xa0000 + * | DRAM | + * +--------------------------------+ 0x0 + */ +SECTIONS +{ + DRAM_START(0x0) + + EARLY_RESERVED_DRAM_START(CONFIG_EARLY_RESERVED_DRAM_BASE) + + EARLYRAM_STACK(., CONFIG_EARLYRAM_BSP_STACK_SIZE) + REGION(apob, CONFIG_PSP_APOB_DRAM_ADDRESS, 64K, 1) + +#if CONFIG(VBOOT) + PSP_SHAREDMEM_DRAM_START(CONFIG_PSP_SHAREDMEM_BASE) + VBOOT2_WORK(., VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE) + PSP_SHAREDMEM_DRAM_END(CONFIG_PSP_SHAREDMEM_BASE + CONFIG_PSP_SHAREDMEM_SIZE) +#endif + + PRERAM_CBMEM_CONSOLE(., CONFIG_PRERAM_CBMEM_CONSOLE_SIZE) + TIMESTAMP(., 0x200) + FMAP_CACHE(., FMAP_SIZE) + + _ = ASSERT((CONFIG_BOOTBLOCK_ADDR + CONFIG_C_ENV_BOOTBLOCK_SIZE - 0x10) == CONFIG_X86_RESET_VECTOR, "Reset vector should be -0x10 from end of bootblock"); + _ = ASSERT(CONFIG_BOOTBLOCK_ADDR == ((CONFIG_BOOTBLOCK_ADDR + 0xFFFF) & 0xFFFF0000), "Bootblock must be 16 bit aligned"); + BOOTBLOCK(CONFIG_BOOTBLOCK_ADDR, CONFIG_C_ENV_BOOTBLOCK_SIZE) + ROMSTAGE(CONFIG_ROMSTAGE_ADDR, CONFIG_ROMSTAGE_SIZE) + REGION(fspm, CONFIG_FSP_M_ADDR, CONFIG_FSP_M_SIZE, 1) +#if CONFIG(VBOOT_SEPARATE_VERSTAGE) + VERSTAGE(CONFIG_VERSTAGE_ADDR, CONFIG_VERSTAGE_SIZE) +#endif + + EARLY_RESERVED_DRAM_END(.) + + RAMSTAGE(CONFIG_RAMBASE, 8M) +} + +#if ENV_BOOTBLOCK +/* Bootblock specific scripts which provide more SECTION directives. */ +#include <cpu/x86/16bit/entry16.ld> +#include <cpu/x86/16bit/reset16.ld> +#endif /* ENV_BOOTBLOCK */ diff --git a/src/soc/amd/picasso/psp_verstage/Makefile.inc b/src/soc/amd/picasso/psp_verstage/Makefile.inc new file mode 100644 index 0000000000..320b704716 --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/Makefile.inc @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only + +verstage-generic-ccopts += -I$(src)/soc/amd/picasso/psp_verstage/include +verstage-generic-ccopts += -I$(src)/vendorcode/amd/fsp/picasso/include +CPPFLAGS_common += -I$(VBOOT_SOURCE)/firmware/2lib/include/ + +verstage-y += delay.c +verstage-y += fch.c +verstage-y += pmutil.c +verstage-y += post.c +verstage-y += printk.c +verstage-y += psp_verstage.c +verstage-y += psp.c +verstage-y += reset.c +verstage-y += svc.c +verstage-y += timer.c +verstage-y += timestamp.c +verstage-y += vboot_crypto.c + +verstage-y += $(top)/src/vendorcode/amd/fsp/picasso/bl_uapp/bl_uapp_startup.S +verstage-y += $(top)/src/vendorcode/amd/fsp/picasso/bl_uapp/bl_uapp_end.S + +$(obj)/psp_verstage.bin: $(objcbfs)/verstage.elf + $(OBJCOPY_verstage) -O binary $^ $@ diff --git a/src/soc/amd/picasso/psp_verstage/delay.c b/src/soc/amd/picasso/psp_verstage/delay.c new file mode 100644 index 0000000000..ff62524503 --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/delay.c @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bl_uapp/bl_syscall_public.h> +#include <delay.h> +#include <stdint.h> + +void udelay(uint32_t usecs) +{ + svc_delay_in_usec(usecs); +} diff --git a/src/soc/amd/picasso/psp_verstage/fch.c b/src/soc/amd/picasso/psp_verstage/fch.c new file mode 100644 index 0000000000..9059c9e160 --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/fch.c @@ -0,0 +1,159 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "psp_verstage.h" + +#include <amdblocks/acpimmio.h> +#include <amdblocks/espi.h> +#include <arch/exception.h> +#include <arch/hlt.h> +#include <arch/io.h> +#include <bl_uapp/bl_errorcodes_public.h> +#include <bl_uapp/bl_syscall_public.h> +#include <console/console.h> +#include <delay.h> +#include <soc/i2c.h> +#include <soc/southbridge.h> +#include <stdint.h> +#include <timestamp.h> + +static void i2c3_set_bar(void *bar) +{ + i2c_set_bar(3, (uintptr_t)bar); +} + +static void i2c2_set_bar(void *bar) +{ + i2c_set_bar(2, (uintptr_t)bar); +} + +static void espi_set_bar(void *bar) +{ + espi_update_static_bar((uintptr_t)bar); +} + +static void iomux_set_bar(void *bar) +{ + acpimmio_iomux = bar; +} + +static void misc_set_bar(void *bar) +{ + acpimmio_misc = bar; +} + +static void gpio_set_bar(void *bar) +{ + acpimmio_gpio0 = bar; +} + +static uintptr_t io_bar; + +static void io_set_bar(void *bar) +{ + io_bar = (uintptr_t)bar; +} + +u8 io_read8(u16 reg) +{ + return read8((void *)(io_bar + reg)); +} + +void io_write8(u16 reg, u8 value) +{ + write8((void *)(io_bar + reg), value); +} + +static struct { + const char *name; + struct { + FCH_IO_DEVICE device; + uint32_t arg0; + } args; + void (*set_bar)(void *bar); + void *_bar; +} bar_map[] = { + {"IOMUX", {FCH_IO_DEVICE_IOMUX}, iomux_set_bar}, + {"MISC", {FCH_IO_DEVICE_MISC}, misc_set_bar}, + {"GPIO", {FCH_IO_DEVICE_GPIO}, gpio_set_bar}, + {"IO", {FCH_IO_DEVICE_IOPORT}, io_set_bar}, + {"eSPI", {FCH_IO_DEVICE_ESPI}, espi_set_bar}, + {"I2C2", {FCH_IO_DEVICE_I2C, 2}, i2c2_set_bar}, + {"I2C3", {FCH_IO_DEVICE_I2C, 3}, i2c3_set_bar}, +}; + +uintptr_t *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; +} + +void sb_enable_legacy_io(void) +{ + pm_io_write32(PM_DECODE_EN, pm_io_read32(PM_DECODE_EN) | LEGACY_IO_EN); +} + +static uint32_t map_fch_devices(void) +{ + void *bar; + uint32_t err; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(bar_map); ++i) { + err = svc_map_fch_dev(bar_map[i].args.device, bar_map[i].args.arg0, 0, &bar); + if (err) { + printk(BIOS_ERR, "Failed to map %s: %u\n", bar_map[i].name, err); + return err; + } + + bar_map[i]._bar = bar; + bar_map[i].set_bar(bar); + } + + return BL_UAPP_OK; +} + +uint32_t unmap_fch_devices(void) +{ + void *bar; + uint32_t err, rtn = BL_UAPP_OK; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(bar_map); ++i) { + bar = bar_map[i]._bar; + if (!bar) + continue; + + err = svc_unmap_fch_dev(bar_map[i].args.device, bar); + if (err) { + printk(BIOS_ERR, "Failed to unmap %s: %u\n", bar_map[i].name, err); + rtn = err; + } else { + bar_map[i]._bar = NULL; + bar_map[i].set_bar(NULL); + } + } + + return rtn; +} + +uint32_t verstage_soc_early_init(void) +{ + return map_fch_devices(); +} + +void verstage_soc_init(void) +{ + if (CONFIG(SOC_AMD_COMMON_BLOCK_USE_ESPI)) { + espi_setup(); + espi_configure_decodes(); + } +} diff --git a/src/soc/amd/picasso/psp_verstage/include/arch/io.h b/src/soc/amd/picasso/psp_verstage/include/arch/io.h new file mode 100644 index 0000000000..efa128b25c --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/include/arch/io.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __ARCH_IO_H__ +#define __ARCH_IO_H__ + +#include <stdint.h> + +u8 io_read8(u16 reg); +void io_write8(u16 reg, u8 value); + +static inline void outb(uint8_t value, uint16_t port) +{ + io_write8(port, value); +} + +static inline uint8_t inb(uint16_t port) +{ + return io_read8(port); +} + +#endif diff --git a/src/soc/amd/picasso/psp_verstage/pmutil.c b/src/soc/amd/picasso/psp_verstage/pmutil.c new file mode 100644 index 0000000000..ddaf54d470 --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/pmutil.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bl_uapp/bl_syscall_public.h> +#include <bootmode.h> +#include <console/console.h> +#include <stdint.h> + +int platform_is_resuming(void) +{ + uint32_t bootmode = 0; + if (svc_get_boot_mode(&bootmode)) { + printk(BIOS_ERR, "Error getting boot mode. Assuming no resume.\n"); + return 0; + } + + if (bootmode == PSP_BOOT_MODE_S3_RESUME || bootmode == PSP_BOOT_MODE_S0i3_RESUME) + return 1; + + return 0; +} diff --git a/src/soc/amd/picasso/psp_verstage/post.c b/src/soc/amd/picasso/psp_verstage/post.c new file mode 100644 index 0000000000..5b429c912b --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/post.c @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bl_uapp/bl_syscall_public.h> +#include <console/console.h> +#include <post.h> + +void arch_post_code(u8 value) +{ + if (CONFIG(POST_IO) && CONFIG_POST_IO_PORT == 0x80) + svc_write_postcode(value); +} diff --git a/src/soc/amd/picasso/psp_verstage/printk.c b/src/soc/amd/picasso/psp_verstage/printk.c new file mode 100644 index 0000000000..2252d44262 --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/printk.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bl_uapp/bl_syscall_public.h> +#include <console/console.h> +#include <console/streams.h> +#include <stdarg.h> +#include <stdint.h> + +void console_hw_init(void) +{ + // Nothing to init for svc_debug_print +} + +int do_printk(int msg_level, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = do_vprintk(msg_level, fmt, args); + va_end(args); + + return i; +} + +int do_vprintk(int msg_level, const char *fmt, va_list args) +{ + int i, log_this; + char buf[256]; + + log_this = console_log_level(msg_level); + if (log_this < CONSOLE_LOG_FAST) + return 0; + + i = vsnprintf(buf, sizeof(buf), fmt, args); + svc_debug_print(buf); + return i; +} diff --git a/src/soc/amd/picasso/psp_verstage/psp.c b/src/soc/amd/picasso/psp_verstage/psp.c new file mode 100644 index 0000000000..7f24b20384 --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/psp.c @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <smp/node.h> + +int boot_cpu(void) +{ + return 1; +} diff --git a/src/soc/amd/picasso/psp_verstage/psp_verstage.c b/src/soc/amd/picasso/psp_verstage/psp_verstage.c new file mode 100644 index 0000000000..bac05481f6 --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/psp_verstage.c @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "psp_verstage.h" + +#include <bl_uapp/bl_syscall_public.h> +#include <boot_device.h> +#include <console/console.h> +#include <security/vboot/misc.h> +#include <security/vboot/symbols.h> +#include <security/vboot/vboot_common.h> +#include <arch/stages.h> +#include <stdarg.h> +#include <stdio.h> + +#define RUN_PSP_SVC_TESTS 0 + +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) {} + +static void reboot_into_recovery(struct vb2_context *ctx, uint32_t subcode) +{ + subcode += PSP_VBOOT_ERROR_SUBCODE; + svc_write_postcode(subcode); + + vb2api_fail(ctx, VB2_RECOVERY_RO_UNSPECIFIED, (int)subcode); + vboot_save_data(ctx); + + svc_debug_print("Rebooting into recovery\n"); + vboot_reboot(); +} + +/* + * Tell the PSP where to load the rest of the firmware from + */ +static uint32_t update_boot_region(struct vb2_context *ctx) +{ + struct psp_ef_table *ef_table; + uint32_t psp_dir_addr, bios_dir_addr; + uint32_t *psp_dir_in_spi, *bios_dir_in_spi; + + /* Continue booting from RO */ + if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) { + printk(BIOS_ERR, "In recovery mode. Staying in RO.\n"); + return 0; + } + + if (vboot_is_firmware_slot_a(ctx)) { + printk(BIOS_SPEW, "Using FMAP RW_A region.\n"); + ef_table = (struct psp_ef_table *)((CONFIG_PICASSO_FW_A_POSITION & + SPI_ADDR_MASK) + (uint32_t)boot_dev.base); + } else { + printk(BIOS_SPEW, "Using FMAP RW_B region.\n"); + ef_table = (struct psp_ef_table *)((CONFIG_PICASSO_FW_B_POSITION & + SPI_ADDR_MASK) + (uint32_t)boot_dev.base); + } + + if (ef_table->signature != EMBEDDED_FW_SIGNATURE) { + printk(BIOS_ERR, "Error: ROMSIG address is not correct.\n"); + return POSTCODE_ROMSIG_MISMATCH_ERROR; + } + + psp_dir_addr = ef_table->psp_table; + bios_dir_addr = ef_table->bios1_entry; + psp_dir_in_spi = (uint32_t *)((psp_dir_addr & SPI_ADDR_MASK) + + (uint32_t)boot_dev.base); + bios_dir_in_spi = (uint32_t *)((bios_dir_addr & SPI_ADDR_MASK) + + (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; + } + if (*bios_dir_in_spi != BDT1_COOKIE) { + printk(BIOS_ERR, "Error: BIOS Directory address is not correct.\n"); + return POSTCODE_BDT1_COOKIE_MISMATCH_ERROR; + } + + if (svc_update_psp_bios_dir((void *)&psp_dir_addr, + (void *)&bios_dir_addr, DIR_OFFSET_SET)) { + printk(BIOS_ERR, "Error: Updated BIOS Directory could not be set.\n"); + return POSTCODE_UPDATE_PSP_BIOS_DIR_ERROR; + } + + return 0; +} + +/* + * Save workbuf (and soon memory console and timestamps) to the bootloader to pass + * back to coreboot. + */ +static uint32_t save_buffers(struct vb2_context **ctx) +{ + uint32_t retval; + uint32_t buffer_size = DEFAULT_WORKBUF_TRANSFER_SIZE; + uint32_t max_buffer_size; + + /* + * This should never fail, but if it does, we should still try to + * save the buffer. If that fails, then we should go to recovery mode. + */ + if (svc_get_max_workbuf_size(&max_buffer_size)) { + post_code(POSTCODE_DEFAULT_BUFFER_SIZE_NOTICE); + printk(BIOS_NOTICE, "Notice: using default transfer buffer size.\n"); + max_buffer_size = DEFAULT_WORKBUF_TRANSFER_SIZE; + } + printk(BIOS_DEBUG, "\nMaximum buffer size: %d bytes\n", max_buffer_size); + + retval = vb2api_relocate(_vboot2_work, _vboot2_work, buffer_size, ctx); + if (retval != VB2_SUCCESS) { + printk(BIOS_ERR, "Error shrinking workbuf. Error code %#x\n", retval); + buffer_size = VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE; + post_code(POSTCODE_WORKBUF_RESIZE_WARNING); + } + + if (buffer_size > max_buffer_size) { + printk(BIOS_ERR, "Error: Workbuf is larger than max buffer size.\n"); + post_code(POSTCODE_WORKBUF_BUFFER_SIZE_ERROR); + return POSTCODE_WORKBUF_BUFFER_SIZE_ERROR; + } + + retval = svc_save_uapp_data(UAPP_COPYBUF_CHROME_WORKBUF, (void *)_vboot2_work, + buffer_size); + if (retval) { + printk(BIOS_ERR, "Error: Could not save workbuf. Error code 0x%08x\n", + retval); + return POSTCODE_WORKBUF_SAVE_ERROR; + } + + return 0; +} + +void Main(void) +{ + uint32_t retval; + struct vb2_context *ctx = NULL; + + /* + * Do not use printk() before console_init() + * Do not use post_code() before verstage_mainboard_init() + */ + svc_write_postcode(POSTCODE_ENTERED_PSP_VERSTAGE); + svc_debug_print("Entering verstage on PSP\n"); + memset(&_bss_start, '\0', &_bss_end - &_bss_start); + + svc_write_postcode(POSTCODE_CONSOLE_INIT); + console_init(); + + svc_write_postcode(POSTCODE_EARLY_INIT); + retval = verstage_soc_early_init(); + if (retval) { + svc_debug_print("verstage_soc_early_init failed\n"); + reboot_into_recovery(NULL, retval); + } + svc_debug_print("calling verstage_mainboard_early_init\n"); + + verstage_mainboard_early_init(); + + svc_write_postcode(POSTCODE_LATE_INIT); + sb_enable_legacy_io(); + verstage_soc_init(); + verstage_mainboard_init(); + + post_code(POSTCODE_VERSTAGE_MAIN); + + verstage_main(); + + post_code(POSTCODE_SAVE_BUFFERS); + retval = save_buffers(&ctx); + if (retval) + goto err; + + post_code(POSTCODE_UPDATE_BOOT_REGION); + retval = update_boot_region(ctx); + if (retval) + goto err; + + post_code(POSTCODE_UNMAP_SPI_ROM); + if (boot_dev.base) { + if (svc_unmap_spi_rom((void *)boot_dev.base)) + printk(BIOS_ERR, "Error unmapping SPI rom\n"); + } + + post_code(POSTCODE_UNMAP_FCH_DEVICES); + unmap_fch_devices(); + + post_code(POSTCODE_LEAVING_VERSTAGE); + + printk(BIOS_DEBUG, "Leaving verstage on PSP\n"); + svc_exit(retval); + +err: + reboot_into_recovery(ctx, 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 + * the verstage code gets dropped by the linker. Slightly hacky, but mostly harmless. + */ +void stage_entry(uintptr_t stage_arg) +{ + Main(); +} diff --git a/src/soc/amd/picasso/psp_verstage/psp_verstage.h b/src/soc/amd/picasso/psp_verstage/psp_verstage.h new file mode 100644 index 0000000000..6fe5c7a13d --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/psp_verstage.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef PSP_VERSTAGE_H +#define PSP_VERSTAGE_H + +#include <stdint.h> + +#define EMBEDDED_FW_SIGNATURE 0x55aa55aa +#define PSP_COOKIE 0x50535024 /* 'PSP$' */ +#define BDT1_COOKIE 0x44484224 /* 'DHB$ */ + +#define PSP_VBOOT_ERROR_SUBCODE 0x0D5D0000 + +#define POSTCODE_ENTERED_PSP_VERSTAGE 0x00 +#define POSTCODE_CONSOLE_INIT 0x01 +#define POSTCODE_EARLY_INIT 0x02 +#define POSTCODE_LATE_INIT 0x03 +#define POSTCODE_VERSTAGE_MAIN 0x04 + +#define POSTCODE_SAVE_BUFFERS 0x0F +#define POSTCODE_UPDATE_BOOT_REGION 0x0F + +#define POSTCODE_DEFAULT_BUFFER_SIZE_NOTICE 0xC0 +#define POSTCODE_WORKBUF_RESIZE_WARNING 0xC1 +#define POSTCODE_WORKBUF_SAVE_ERROR 0xC2 +#define POSTCODE_WORKBUF_BUFFER_SIZE_ERROR 0xC3 +#define POSTCODE_ROMSIG_MISMATCH_ERROR 0xC4 +#define POSTCODE_PSP_COOKIE_MISMATCH_ERROR 0xC5 +#define POSTCODE_BDT1_COOKIE_MISMATCH_ERROR 0xC6 +#define POSTCODE_UPDATE_PSP_BIOS_DIR_ERROR 0xC7 + +#define POSTCODE_UNMAP_SPI_ROM 0xF0 +#define POSTCODE_UNMAP_FCH_DEVICES 0xF1 +#define POSTCODE_LEAVING_VERSTAGE 0xF2 + +#define SPI_ADDR_MASK 0x00ffffff +#define DEFAULT_WORKBUF_TRANSFER_SIZE (8 * KiB) + +struct psp_ef_table { + uint32_t signature; /* 0x55aa55aa */ + uint32_t reserved0[4]; + uint32_t psp_table; + uint32_t bios0_entry; + uint32_t bios1_entry; + uint32_t bios2_entry; +} __attribute__((packed, aligned(16))); + +void test_svc_calls(void); +uint32_t unmap_fch_devices(void); +uint32_t verstage_soc_early_init(void); +void verstage_soc_init(void); +uintptr_t *map_spi_rom(void); +void sb_enable_legacy_io(void); + +#endif /* PSP_VERSTAGE_H */ diff --git a/src/soc/amd/picasso/psp_verstage/reset.c b/src/soc/amd/picasso/psp_verstage/reset.c new file mode 100644 index 0000000000..5619e457ae --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/reset.c @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bl_uapp/bl_syscall_public.h> +#include <console/console.h> +#include <reset.h> +#include <stdint.h> + + +void do_board_reset(void) +{ + printk(BIOS_ERR, "Resetting the board now.\n"); + svc_reset_system(RESET_TYPE_COLD); +} diff --git a/src/soc/amd/picasso/psp_verstage/svc.c b/src/soc/amd/picasso/psp_verstage/svc.c new file mode 100644 index 0000000000..149e3e2b2b --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/svc.c @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include "svc.h" + +#include <assert.h> +#include <bl_uapp/bl_syscall_public.h> +#include <stddef.h> + +void svc_exit(uint32_t status) +{ + uint32_t unused = 0; + SVC_CALL0(SVC_EXIT, unused); +} + +uint32_t svc_map_user_stack(void *start_addr, void *end_addr, void *stack_va) +{ + uint32_t retval = 0; + SVC_CALL3(SVC_MAP_USER_STACK, (uint32_t)start_addr, + (uint32_t)end_addr, stack_va, retval); + return retval; +} + +void svc_debug_print(const char *string) +{ + uint32_t unused = 0; + SVC_CALL1(SVC_DEBUG_PRINT, (uint32_t)string, unused); +} + +void svc_debug_print_ex(uint32_t dword0, + uint32_t dword1, uint32_t dword2, uint32_t dword3) +{ + uint32_t unused = 0; + SVC_CALL4(SVC_DEBUG_PRINT_EX, dword0, dword1, dword2, dword3, unused); +} + +uint32_t svc_wait_10ns_multiple(uint32_t multiple) +{ + uint32_t retval = 0; + SVC_CALL1(SVC_WAIT_10NS_MULTIPLE, multiple, retval); + return retval; +} + +uint32_t svc_get_boot_mode(uint32_t *boot_mode) +{ + uint32_t retval = 0; + SVC_CALL1(SVC_GET_BOOT_MODE, boot_mode, retval); + return retval; +} + +void svc_delay_in_usec(uint32_t delay) +{ + uint32_t unused = 0; + SVC_CALL1(SVC_DELAY_IN_MICRO_SECONDS, delay, unused); +} + +uint32_t svc_get_spi_rom_info(SPIROM_INFO *spi_rom_info) +{ + uint32_t retval = 0; + SVC_CALL1(SVC_GET_SPI_INFO, (uint32_t)spi_rom_info, retval); + return retval; +} + +uint32_t svc_map_fch_dev(FCH_IO_DEVICE io_device, + uint32_t arg1, uint32_t arg2, void **io_device_axi_addr) +{ + uint32_t retval = 0; + assert(io_device < FCH_IO_DEVICE_END); + SVC_CALL4(SVC_MAP_FCH_IO_DEVICE, io_device, arg1, arg2, + (uint32_t)io_device_axi_addr, retval); + return retval; +} + +uint32_t svc_unmap_fch_dev(FCH_IO_DEVICE io_device, void *io_device_axi_addr) +{ + uint32_t retval = 0; + assert(io_device < FCH_IO_DEVICE_END); + SVC_CALL2(SVC_UNMAP_FCH_IO_DEVICE, (uint32_t)io_device, + (uint32_t)io_device_axi_addr, retval); + return retval; +} + +uint32_t svc_map_spi_rom(void *spi_rom_addr, + uint32_t size, void **spi_rom_axi_addr) +{ + uint32_t retval = 0; + SVC_CALL3(SVC_MAP_SPIROM_DEVICE, spi_rom_addr, size, + (uint32_t)spi_rom_axi_addr, retval); + return retval; +} + +uint32_t svc_unmap_spi_rom(void *spi_rom_addr) +{ + uint32_t retval = 0; + SVC_CALL1(SVC_UNMAP_SPIROM_DEVICE, (uint32_t)spi_rom_addr, retval); + return retval; +} + +uint32_t svc_update_psp_bios_dir(uint32_t *psp_dir_offset, + uint32_t *bios_dir_offset, DIR_OFFSET_OPERATION operation) +{ + uint32_t retval = 0; + assert(operation < DIR_OFFSET_OPERATION_MAX); + SVC_CALL3(SVC_UPDATE_PSP_BIOS_DIR, (uint32_t)psp_dir_offset, + (uint32_t)bios_dir_offset, operation, retval); + return retval; +} + +uint32_t svc_save_uapp_data(UAPP_COPYBUF type, void *address, + uint32_t size) +{ + uint32_t retval = 0; + assert(type < UAPP_COPYBUF_MAX); + SVC_CALL3(SVC_COPY_DATA_FROM_UAPP, type, (uint32_t)address, size, retval); + return retval; +} + +uint32_t svc_read_timer_val(PSP_TIMER_TYPE type, uint64_t *counter_value) +{ + unsigned int retval = 0; + assert(type < PSP_TIMER_TYPE_MAX); + SVC_CALL2(SVC_READ_TIMER_VAL, type, counter_value, retval); + return retval; +} + +uint32_t svc_reset_system(RESET_TYPE reset_type) +{ + unsigned int retval = 0; + assert(reset_type < RESET_TYPE_MAX); + SVC_CALL1(SVC_RESET_SYSTEM, reset_type, retval); + return retval; +} + +uint32_t svc_write_postcode(uint32_t postcode) +{ + uint32_t retval = 0; + SVC_CALL1(SVC_WRITE_POSTCODE, postcode, retval); + return retval; +} + +uint32_t svc_get_max_workbuf_size(uint32_t *size) +{ + uint32_t retval = 0; + SVC_CALL1(SVC_GET_MAX_WORKBUF_SIZE, size, retval); + return retval; +} + +uint32_t svc_crypto_sha(SHA_GENERIC_DATA *sha_op, SHA_OPERATION_MODE sha_mode) +{ + uint32_t retval = 0; + SVC_CALL2(SVC_SHA, sha_op, sha_mode, retval); + return retval; +} diff --git a/src/soc/amd/picasso/psp_verstage/svc.h b/src/soc/amd/picasso/psp_verstage/svc.h new file mode 100644 index 0000000000..03bae066e0 --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/svc.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef PSP_VERSTAGE_SVC_H +#define PSP_VERSTAGE_SVC_H + +#define SVC_CALL4(SVC_ID, R0, R1, R2, R3, Ret) \ + __asm__ __volatile__ ( \ + "mov r0, %[reg0]\n\t" \ + "mov r1, %[reg1]\n\t" \ + "mov r2, %[reg2]\n\t" \ + "mov r3, %[reg3]\n\t" \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "i" (SVC_ID), [reg0] "r" (R0), [reg1] "r" (R1), [reg2] "r" (R2), \ + [reg3] "r" (R3) /* input(s) */ \ + : "r0", "r1", "r2", "r3", "memory", "cc" /* list of clobbered registers */); + +#define SVC_CALL3(SVC_ID, R0, R1, R2, Ret) \ + __asm__ __volatile__ ( \ + "mov r0, %[reg0]\n\t" \ + "mov r1, %[reg1]\n\t" \ + "mov r2, %[reg2]\n\t" \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "i" (SVC_ID), [reg0] "r" (R0), [reg1] "r" (R1), [reg2] "r" (R2) \ + : "r0", "r1", "r2", "memory", "cc" /* list of clobbered registers */); + +#define SVC_CALL2(SVC_ID, R0, R1, Ret) \ + __asm__ __volatile__ ( \ + "mov r0, %[reg0]\n\t" \ + "mov r1, %[reg1]\n\t" \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "i" (SVC_ID), [reg0] "r" (R0), [reg1] "r" (R1)/* input(s) */ \ + : "r0", "r1", "memory", "cc" /* list of clobbered registers */); + +#define SVC_CALL1(SVC_ID, R0, Ret) \ + __asm__ __volatile__ ( \ + "mov r0, %[reg0]\n\t" \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "i" (SVC_ID), [reg0] "r" (R0) /* input(s) */ \ + : "r0", "memory", "cc" /* list of clobbered registers */); + +#define SVC_CALL0(SVC_ID, Ret) \ + __asm__ __volatile__ ( \ + "svc %[id]\n\t" \ + "mov %[result], r0\n\t" \ + : [result] "=r" (Ret) /* output */ \ + : [id] "I" (SVC_ID) /* input(s) */ \ + : "memory", "cc" /* list of clobbered registers */); + +#endif /* PSP_VERSTAGE_SVC_H */ diff --git a/src/soc/amd/picasso/psp_verstage/timer.c b/src/soc/amd/picasso/psp_verstage/timer.c new file mode 100644 index 0000000000..04728baf0c --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/timer.c @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <bl_uapp/bl_syscall_public.h> +#include <stdint.h> +#include <timer.h> + +void timer_monotonic_get(struct mono_time *mt) +{ + /* Chrono timer is based on a 25MHz clock */ + uint64_t clk; + + svc_read_timer_val(PSP_TIMER_TYPE_CHRONO, &clk); + + mt->microseconds = clk / 25; +} diff --git a/src/soc/amd/picasso/psp_verstage/timestamp.c b/src/soc/amd/picasso/psp_verstage/timestamp.c new file mode 100644 index 0000000000..b3b8f75f7e --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/timestamp.c @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <timestamp.h> + +/* Stubs */ +void timestamp_add_now(enum timestamp_id id) +{ +} + +void timestamp_add(enum timestamp_id id, uint64_t ts) +{ +} + +uint64_t timestamp_get(void) +{ + return 0; +} diff --git a/src/soc/amd/picasso/psp_verstage/vboot_crypto.c b/src/soc/amd/picasso/psp_verstage/vboot_crypto.c new file mode 100644 index 0000000000..c010eb626b --- /dev/null +++ b/src/soc/amd/picasso/psp_verstage/vboot_crypto.c @@ -0,0 +1,104 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <2crypto.h> +#include <2return_codes.h> +#include <bl_uapp/bl_syscall_public.h> +#include <commonlib/bsd/helpers.h> +#include <console/console.h> +#include "psp_verstage.h" +#include <stddef.h> +#include <string.h> +#include <vb2_api.h> + +static struct SHA_GENERIC_DATA_T sha_op; +static uint32_t sha_op_size_remaining; +static uint8_t __attribute__((aligned(32))) sha_hash[64]; + +vb2_error_t vb2ex_hwcrypto_digest_init(enum vb2_hash_algorithm hash_alg, uint32_t data_size) +{ + printk(BIOS_DEBUG, "Calculating hash of %d bytes\n", data_size); + + sha_op_size_remaining = data_size; + + if (hash_alg == VB2_HASH_SHA256) { + sha_op.SHAType = SHA_TYPE_256; + sha_op.DigestLen = 32; + } else if (hash_alg == VB2_HASH_SHA512) { + sha_op.SHAType = SHA_TYPE_512; + sha_op.DigestLen = 64; + } else { + printk(BIOS_INFO, "Unsupported hash_alg %d!\n", hash_alg); + return VB2_ERROR_EX_HWCRYPTO_UNSUPPORTED; + } + + /* Set init flag for first operation */ + sha_op.Init = 1; + + /* Clear eom flag until last operation */ + sha_op.Eom = 0; + + /* Need documentation on this b:157610147 */ + sha_op.DataMemType = 2; + + sha_op.Digest = sha_hash; + + sha_op.IntermediateDigest = NULL; + + sha_op.IntermediateMsgLen = 0; + + return VB2_SUCCESS; +} + +vb2_error_t vb2ex_hwcrypto_digest_extend(const uint8_t *buf, uint32_t size) +{ + uint32_t retval; + sha_op.Data = (uint8_t *) buf; + + if (!sha_op_size_remaining) { + printk(BIOS_ERR, "ERROR: got more data than expected.\n"); + return VB2_ERROR_UNKNOWN; + } + + while (size) { + sha_op.DataLen = size; + + sha_op_size_remaining -= sha_op.DataLen; + + /* Set eom flag for final operation */ + if (sha_op_size_remaining == 0) + sha_op.Eom = 1; + + retval = svc_crypto_sha(&sha_op, SHA_GENERIC); + if (retval) { + printk(BIOS_ERR, "ERROR: HW crypto failed - errorcode: %#x\n", + retval); + return VB2_ERROR_UNKNOWN; + } + + /* Clear init flag after first operation */ + if (sha_op.Init == 1) + sha_op.Init = 0; + + size -= sha_op.DataLen; + } + + return VB2_SUCCESS; +} + +/* Copy the hash back to verstage */ +vb2_error_t vb2ex_hwcrypto_digest_finalize(uint8_t *digest, uint32_t digest_size) +{ + if (sha_op.Eom == 0) { + printk(BIOS_ERR, "ERROR: Got less data than expected.\n"); + return VB2_ERROR_UNKNOWN; + } + + if (digest_size != sha_op.DigestLen) { + printk(BIOS_ERR, "ERROR: Digest size does not match expected length.\n"); + return VB2_ERROR_UNKNOWN; + } + + memcpy(digest, sha_hash, digest_size); + + return VB2_SUCCESS; +} |