diff --git a/configs/config.pcengines_apu2_drtm_payload b/configs/config.pcengines_apu2_drtm_payload new file mode 100644 index 00000000000..e05bb3c6b55 --- /dev/null +++ b/configs/config.pcengines_apu2_drtm_payload @@ -0,0 +1,51 @@ +CONFIG_LOCALVERSION="v0.9.1" +CONFIG_OPTION_BACKEND_NONE=y +CONFIG_VENDOR_PCENGINES=y +CONFIG_VBOOT=y +CONFIG_PXE_ROM_ID="8086,157b" +CONFIG_CONSOLE_CBMEM_BUFFER_SIZE=0x100000 +CONFIG_EDK2_BOOT_TIMEOUT=6 +CONFIG_TPM_MEASURED_BOOT=y +CONFIG_EDK2_BOOTSPLASH_FILE="3rdparty/dasharo-blobs/dasharo/bootsplash.bmp" +CONFIG_LAUNCH_DRTM_PAYLOAD=y +CONFIG_UDK_202005_BINDING=y +CONFIG_NO_GFX_INIT=y +CONFIG_DRIVERS_EFI_VARIABLE_STORE=y +CONFIG_TPM2=y +CONFIG_BOOTMEDIA_LOCK_CHIP=y +CONFIG_BOOTMEDIA_LOCK_WPRO_VBOOT_RO=y +CONFIG_BOOTMEDIA_LOCK_IN_VERSTAGE=y +CONFIG_BOOTMEDIA_SPI_LOCK_PIN=y +CONFIG_DEFAULT_CONSOLE_LOGLEVEL_1=y +# CONFIG_CONSOLE_USE_LOGLEVEL_PREFIX is not set +# CONFIG_CONSOLE_USE_ANSI_ESCAPES is not set +CONFIG_PAYLOAD_EDK2=y +CONFIG_EDK2_USE_EDK2_PLATFORMS=y +CONFIG_EDK2_PLATFORMS_REPOSITORY="https://github.com/Dasharo/edk2-platforms" +CONFIG_EDK2_PLATFORMS_TAG_OR_REV="1002a59639f111a2f8178b77d1f5fde0ea8d976f" +CONFIG_EDK2_CBMEM_LOGGING=y +CONFIG_EDK2_HAVE_EFI_SHELL=y +# CONFIG_EDK2_PS2_SUPPORT is not set +CONFIG_EDK2_SERIAL_SUPPORT=y +CONFIG_BUILD_IPXE=y +CONFIG_IPXE_ADD_SCRIPT=y +CONFIG_IPXE_SCRIPT="3rdparty/dasharo-blobs/dasharo/dasharo.ipxe" +CONFIG_IPXE_CUSTOM_BUILD_ID="0123456789" +CONFIG_DASHARO=y +CONFIG_EDK2_ENABLE_IPXE=y +# CONFIG_EDK2_SECURE_BOOT_DEFAULT_ENABLE is not set +CONFIG_EDK2_SATA_PASSWORD=y +CONFIG_EDK2_OPAL_PASSWORD=y +CONFIG_EDK2_SETUP_PASSWORD=y +CONFIG_EDK2_PERFORMANCE_MEASUREMENT_ENABLE=y +CONFIG_EDK2_DASHARO_SYSTEM_FEATURES=y +CONFIG_EDK2_DASHARO_SECURITY_OPTIONS=y +CONFIG_EDK2_DASHARO_USB_CONFIG=y +CONFIG_EDK2_DASHARO_NETWORK_CONFIG=y +CONFIG_EDK2_DASHARO_CHIPSET_CONFIG=y +CONFIG_EDK2_DASHARO_SERIAL_REDIRECTION_DEFAULT_ENABLE=y +CONFIG_EDK2_HAVE_2ND_UART=y +CONFIG_EDK2_BOOT_MENU_KEY=0x0014 +CONFIG_EDK2_SETUP_MENU_KEY=0x0008 +CONFIG_EDK2_DISABLE_OPTION_ROMS=y +CONFIG_EDK2_CREATE_PREINSTALLED_BOOT_OPTIONS=y diff --git a/payloads/external/.gitignore b/payloads/external/.gitignore index c9efcffd032..a5f0f6ef598 100644 --- a/payloads/external/.gitignore +++ b/payloads/external/.gitignore @@ -10,3 +10,4 @@ Memtest86Plus/memtest86plus/ iPXE/ipxe/ skiboot/skiboot skiboot/build +skl/secure-kernel-loader/ diff --git a/payloads/external/Makefile.mk b/payloads/external/Makefile.mk index 3b8770833de..8d95b301031 100644 --- a/payloads/external/Makefile.mk +++ b/payloads/external/Makefile.mk @@ -578,3 +578,16 @@ doom.wad-file := $(strip $(CONFIG_COREDOOM_WAD_FILE)) doom.wad-type := raw doom.wad-compression := $(CBFS_SECONDARY_PAYLOAD_COMPRESS_FLAG) endif + +# SKL + +payloads/external/skl/secure-kernel-loader/skl.bin: + $(MAKE) -C payloads/external/skl CC="$(HOSTCC)" \ + CONFIG_SKL_REPOSITORY=$(CONFIG_SKL_REPOSITORY) \ + CONFIG_SKL_TAG_OR_REV=$(CONFIG_SKL_TAG_OR_REV) + +cbfs-files-$(CONFIG_LAUNCH_DRTM_PAYLOAD) += $(CONFIG_CBFS_PREFIX)/drtm_payload +$(CONFIG_CBFS_PREFIX)/drtm_payload-file := payloads/external/skl/secure-kernel-loader/skl.bin +$(CONFIG_CBFS_PREFIX)/drtm_payload-type := raw +$(CONFIG_CBFS_PREFIX)/drtm_payload-compression := $(CBFS_PAYLOAD_COMPRESS_FLAG) +$(CONFIG_CBFS_PREFIX)/drtm_payload-options := $(ADDITIONAL_PAYLOAD_CONFIG) diff --git a/payloads/external/skl/Makefile b/payloads/external/skl/Makefile new file mode 100644 index 00000000000..042302af3b4 --- /dev/null +++ b/payloads/external/skl/Makefile @@ -0,0 +1,34 @@ +## SPDX-License-Identifier: GPL-2.0-only +project_git_repo=$(CONFIG_SKL_REPOSITORY) +project_dir=secure-kernel-loader + +all: skl + +checkout: + if [ ! -d "$(project_dir)" ]; then \ + git clone --recurse-submodules "$(project_git_repo)" -j5; \ + fi + cd "$(project_dir)"; \ + if ! git rev-parse --verify -q $(CONFIG_SKL_TAG_OR_REV)^{object} >/dev/null; then \ + echo " $(CONFIG_SKL_TAG_OR_REV) is not a valid git reference"; \ + exit 1;\ + fi; \ + if git status --ignore-submodules=dirty | grep -q "nothing to commit, working tree clean"; then \ + echo " Checking out secure-kernel-loader $(CONFIG_SKL_TAG_OR_REV)"; \ + git checkout --detach $(CONFIG_SKL_TAG_OR_REV) -f; \ + else \ + echo " Working directory not clean; will not overwrite"; \ + fi; \ + git submodule update --init --checkout + + +skl: checkout + $(MAKE) -C $(project_dir) DEBUG=y + +clean: + test -d $(project_dir) && $(MAKE) -C $(project_dir) clean || exit 0 + +distclean: + rm -rf $(project_dir) + +.PHONY: checkout skl clean distclean diff --git a/src/soc/amd/common/Kconfig.common b/src/soc/amd/common/Kconfig.common index 2070b817913..1d10778e1e3 100644 --- a/src/soc/amd/common/Kconfig.common +++ b/src/soc/amd/common/Kconfig.common @@ -11,6 +11,7 @@ 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" +source "src/soc/amd/common/skl/Kconfig" config APCB_BLOBS_DIR string "Mainboard blobs path" diff --git a/src/soc/amd/common/Makefile.mk b/src/soc/amd/common/Makefile.mk index b3c1499a3fe..51535b26366 100644 --- a/src/soc/amd/common/Makefile.mk +++ b/src/soc/amd/common/Makefile.mk @@ -4,6 +4,7 @@ subdirs-y += block subdirs-y += fsp subdirs-y += pi subdirs-y += vboot +subdirs-$(CONFIG_LAUNCH_DRTM_PAYLOAD) += skl CPPFLAGS_common += -I$(src)/soc/amd/common/vboot/include diff --git a/src/soc/amd/common/skl/Kconfig b/src/soc/amd/common/skl/Kconfig new file mode 100644 index 00000000000..3d44022bfdb --- /dev/null +++ b/src/soc/amd/common/skl/Kconfig @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config LAUNCH_DRTM_PAYLOAD + bool "Launch DRTM payload before the real one" + default n + depends on MEMORY_MAPPED_TPM && ARCH_RAMSTAGE_X86_32 + help + Launch DRTM payload before the real one. This makes it possible to + put root of trust in hardware for platforms that don't support SRTM. + +if LAUNCH_DRTM_PAYLOAD + +config SKL_REPOSITORY + string "URL to git repository for secure-kernel-loader" + default "https://github.com/TrenchBoot/secure-kernel-loader.git" + help + TODO + +config SKL_TAG_OR_REV + string "Insert a commit's SHA-1 or a branch name" + default "de1899007d038eeacf5edb8e63c0f0a4b3e265c4" + help + The commit's SHA-1 or branch name of the revision to use. This must exist in + SKL_REPOSITORY, and in the case of a branch name, prefixed with origin i.e. + "origin/skl-loader-amdsl-v11" + +endif # LAUNCH_DRTM_PAYLOAD diff --git a/src/soc/amd/common/skl/Makefile.mk b/src/soc/amd/common/skl/Makefile.mk new file mode 100644 index 00000000000..52f2db01c7e --- /dev/null +++ b/src/soc/amd/common/skl/Makefile.mk @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + +ramstage-$(CONFIG_LAUNCH_DRTM_PAYLOAD) += skinit.c + +CPPFLAGS_common += -I$(src)/soc/amd/common/skl/include/ diff --git a/src/soc/amd/common/skl/include/slrt.h b/src/soc/amd/common/skl/include/slrt.h new file mode 100644 index 00000000000..ddd2e6dcda2 --- /dev/null +++ b/src/soc/amd/common/skl/include/slrt.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef __SLRT_H__ +#define __SLRT_H__ + +#include + +/* SLR Table header values */ +#define SLR_TABLE_MAGIC 0x4452544d +#define SLR_TABLE_REVISION 1 + +/* Current revisions for the policy and UEFI config */ +#define SLR_POLICY_REVISION 1 +#define SLR_UEFI_CONFIG_REVISION 1 + +/* SLR defined architectures */ +#define SLR_INTEL_TXT 1 +#define SLR_AMD_SKINIT 2 + +/* SLR defined bootloaders */ +#define SLR_BOOTLOADER_INVALID 0 +#define SLR_BOOTLOADER_GRUB 1 + +/* Log formats */ +#define SLR_DRTM_TPM12_LOG 1 +#define SLR_DRTM_TPM20_LOG 2 + +/* Array Lengths */ +#define TPM_EVENT_INFO_LENGTH 32 + +/* Tags */ +#define SLR_ENTRY_INVALID 0x0000 +#define SLR_ENTRY_DL_INFO 0x0001 +#define SLR_ENTRY_LOG_INFO 0x0002 +#define SLR_ENTRY_ENTRY_POLICY 0x0003 +#define SLR_ENTRY_INTEL_INFO 0x0004 +#define SLR_ENTRY_AMD_INFO 0x0005 +#define SLR_ENTRY_ARM_INFO 0x0006 +#define SLR_ENTRY_UEFI_INFO 0x0007 +#define SLR_ENTRY_UEFI_CONFIG 0x0008 +#define SLR_ENTRY_END 0xffff + +/* + * sl_header as given by AMD + */ +struct sl_header { + u16 skl_entry_point; + u16 skl_measured_size; + u8 reserved[62]; + u16 skl_info_offset; + u16 bootloader_data_offset; +} __packed; + +/* + * Common SLRT Table Header + */ +struct slr_entry_hdr { + u32 tag; + u32 size; +} __packed; + +/* + * Primary Secure Launch Resource Table Header + */ +struct slr_table { + u32 magic; + u16 revision; + u16 architecture; + u32 size; + u32 max_size; + /* Not really a flex array, don't use it that way! */ + struct slr_entry_hdr entries[]; +} __packed; + +/* + * Boot loader context + */ +struct slr_bl_context { + u16 bootloader; + u16 reserved[3]; + u64 context; +} __packed; + +/* + * DRTM Dynamic Launch Configuration + */ +struct slr_entry_dl_info { + struct slr_entry_hdr hdr; + u64 dce_size; + u64 dce_base; + u64 dlme_size; + u64 dlme_base; + u64 dlme_entry; /* Offset from dlme_base */ + struct slr_bl_context bl_context; + u64 dl_handler; +} __packed; + +/* + * TPM Log Information + */ +struct slr_entry_log_info { + struct slr_entry_hdr hdr; + u16 format; + u16 reserved; + u32 size; + u64 addr; +} __packed; + +/* + * AMD SKINIT Info table + */ +struct slr_entry_amd_info { + struct slr_entry_hdr hdr; + u64 next; + u32 type; + u32 len; + u64 slrt_size; + u64 slrt_base; + u64 boot_params_base; + u16 psp_version; + u16 reserved[3]; +} __packed; + +static inline void *next_entry(void* t) +{ + void *x = t + ((struct slr_entry_hdr*)t)->size; + return x; +} + +#endif /* __SLRT_H__ */ diff --git a/src/soc/amd/common/skl/skinit.c b/src/soc/amd/common/skl/skinit.c new file mode 100644 index 00000000000..b7a2379a51d --- /dev/null +++ b/src/soc/amd/common/skl/skinit.c @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static uintptr_t payload_start, payload_size; + +/* For CBFS_TYPE_SELF (Simple Elf), prog->start and prog->size are not set so obtain it differently. */ +void platform_segment_loaded(uintptr_t start, size_t size, int flags) +{ + /* FIXME: need to differentiate between payload and other loaded segments */ + if (/*payload_start != 0 || payload_size != 0 || */flags != SEG_FINAL) + die("ELF payload must have only one loadable segment for DRTM!\n"); + + payload_start = start; + payload_size = size; +} + +void platform_prog_run(struct prog *prog) +{ + void *skl = NULL; + uint16_t bootloader_data_offset; + struct slr_table *slrt; + struct slr_entry_dl_info *dl_info; + struct slr_entry_amd_info *amd_info; + struct slr_entry_log_info *log_info; + struct slr_entry_hdr *end; + const struct cbmem_entry *ce; + + /* + * Check if we're on 32b platform. + * TODO: add support for 64b? + */ + _Static_assert(sizeof(skl) == 4); + + /* + * APs have to be in wait-for-SIPI state for at least 1000 cycles before + * SKINIT. Send INIT now and assume that loading SKL from CBFS is long + * enough. + */ + lapic_send_ipi_others(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_MT_INIT); + + skl = memalign(64*KiB, 64*KiB); + if (!skl) + die("Could not reserve memory for DRTM\n"); + + memset(slrt, 0, 64*KiB - (skl - (void *)slrt)); + + if (!cbfs_load(CONFIG_CBFS_PREFIX "/drtm_payload", skl, 64*KiB)) + die("Could not load DRTM payload\n"); + + bootloader_data_offset = ((struct sl_header *)skl)->bootloader_data_offset; + slrt = (struct slr_table *)(skl + bootloader_data_offset); + + slrt->magic = SLR_TABLE_MAGIC; + slrt->revision = SLR_TABLE_REVISION; + slrt->architecture = SLR_AMD_SKINIT; + slrt->size = sizeof(*slrt); + slrt->max_size = 64*KiB - bootloader_data_offset; + + dl_info = (struct slr_entry_dl_info *)slrt->entries; + dl_info->hdr.tag = SLR_ENTRY_DL_INFO; + dl_info->hdr.size = sizeof(struct slr_entry_dl_info); + dl_info->dlme_base = payload_start; + dl_info->dlme_size = payload_size; + dl_info->dlme_entry = (uint32_t)prog->entry - payload_start; + dl_info->bl_context.bootloader = SLR_BOOTLOADER_GRUB; // TODO: BOOTLOADER_COREBOOT? + slrt->size += dl_info->hdr.size; + + amd_info = next_entry(dl_info); + amd_info->hdr.tag = SLR_ENTRY_AMD_INFO; + amd_info->hdr.size = sizeof(*amd_info); + slrt->size += amd_info->hdr.size; + + log_info = next_entry(amd_info); + log_info->hdr.tag = SLR_ENTRY_LOG_INFO; + log_info->hdr.size = sizeof(*log_info); + slrt->size += log_info->hdr.size; + ce = cbmem_entry_find(CBMEM_ID_TPM2_TCG_LOG); + if (ce) { + log_info->addr = (uintptr_t)cbmem_entry_start(ce); + log_info->size = cbmem_entry_size(ce); + log_info->format = SLR_DRTM_TPM20_LOG; // TODO: Support 1.2? + } else + printk(BIOS_ERR, "Could not find TPM2 CBMEM Entry\n"); + + end = next_entry(log_info); + end->tag = SLR_ENTRY_END; + end->size = sizeof(struct slr_entry_hdr); + slrt->size += end->size; + + /* TODO: DRTM TPM event log and SKL hash(es) */ + + msr_t msr; + + msr = rdmsr(SMM_BASE_MSR); + printk(BIOS_DEBUG, "SMM_BASE_MSR = %#8.8x%8.8x\n", msr.hi, msr.lo); + + msr = rdmsr(SMM_ADDR_MSR); + printk(BIOS_DEBUG, "SMM_ADDR_MSR = %#8.8x%8.8x\n", msr.hi, msr.lo); + + msr = rdmsr(SMM_MASK_MSR); + printk(BIOS_DEBUG, "SMM_MASK_MSR = %#8.8x%8.8x\n", msr.hi, msr.lo); + + msr = rdmsr(HWCR_MSR); + printk(BIOS_DEBUG, "HWCR_MSR = %#8.8x%8.8x\n", msr.hi, msr.lo); + + asm volatile ("skinit" :: "a"(skl)); +}