From bc744f5893fc4d53275ed26dd8d968011c6a09c1 Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Fri, 17 Apr 2020 16:16:49 +0200 Subject: drivers/smmstore: Implement SMMSTORE version 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SMMSTORE version 2 is a complete redesign of the current driver. It is not backwards-compatible with version 1, and only one version can be used at a time. Key features: * Uses a fixed communication buffer instead of writing to arbitrary memory addresses provided by untrusted ring0 code. * Gives the caller full control over the used data format. * Splits the store into smaller chunks to allow fault tolerant updates. * Doesn't provide feedback about the actual read/written bytes, just returns error or success in registers. * Returns an error if the requested operation would overflow the communication buffer. Separate the SMMSTORE into 64 KiB blocks that can individually be read/written/erased. To be used by payloads that implement a FaultTolerant Variable store like TianoCore. The implementation has been tested against EDK2 master. An example EDK2 implementation can be found here: https://github.com/9elements/edk2-1/commit/eb1127744a3a5d5c8ac4e8eb76f07e79c736dbe2 Change-Id: I25e49d184135710f3e6dd1ad3bed95de950fe057 Signed-off-by: Patrick Rudolph Signed-off-by: Christian Walter Reviewed-on: https://review.coreboot.org/c/coreboot/+/40520 Tested-by: build bot (Jenkins) Reviewed-by: Michał Żygowski Reviewed-by: Matt DeVillier --- src/drivers/smmstore/ramstage.c | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 src/drivers/smmstore/ramstage.c (limited to 'src/drivers/smmstore/ramstage.c') diff --git a/src/drivers/smmstore/ramstage.c b/src/drivers/smmstore/ramstage.c new file mode 100644 index 0000000000..ef80e221bc --- /dev/null +++ b/src/drivers/smmstore/ramstage.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct smmstore_params_info info; + +void lb_smmstorev2(struct lb_header *header) +{ + struct lb_record *rec; + struct lb_smmstorev2 *store; + const struct cbmem_entry *e; + + e = cbmem_entry_find(CBMEM_ID_SMM_COMBUFFER); + if (!e) + return; + + rec = lb_new_record(header); + store = (struct lb_smmstorev2 *)rec; + + store->tag = LB_TAG_SMMSTOREV2; + store->size = sizeof(*store); + store->com_buffer = (uintptr_t)cbmem_entry_start(e); + store->com_buffer_size = cbmem_entry_size(e); + store->mmap_addr = info.mmap_addr; + store->num_blocks = info.num_blocks; + store->block_size = info.block_size; + store->apm_cmd = APM_CNT_SMMSTORE; +} + +static void init_store(void *unused) +{ + struct smmstore_params_init args; + uint32_t eax = ~0; + uint32_t ebx; + + if (smmstore_get_info(&info) < 0) { + printk(BIOS_INFO, "SMMSTORE: Failed to get meta data\n"); + return; + } + + void *ptr = cbmem_add(CBMEM_ID_SMM_COMBUFFER, info.block_size); + if (!ptr) { + printk(BIOS_ERR, "SMMSTORE: Failed to add com buffer\n"); + return; + } + + args.com_buffer = (uintptr_t)ptr; + args.com_buffer_size = info.block_size; + ebx = (uintptr_t)&args; + + printk(BIOS_INFO, "SMMSTORE: Setting up SMI handler\n"); + + /* Issue SMI using APM to update the com buffer and to lock the SMMSTORE */ + __asm__ __volatile__ ( + "outb %%al, %%dx" + : "=a" (eax) + : "a" ((SMMSTORE_CMD_INIT << 8) | APM_CNT_SMMSTORE), + "b" (ebx), + "d" (APM_CNT) + : "memory"); + + if (eax != SMMSTORE_RET_SUCCESS) { + printk(BIOS_ERR, "SMMSTORE: Failed to install com buffer\n"); + return; + } +} + +/* The SMI APM handler is installed at DEV_INIT phase */ +BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, init_store, NULL); -- cgit v1.2.3