| From 6f408c969d32d489acd5e65589e2d6af5677cdd1 Mon Sep 17 00:00:00 2001 |
| From: Simon Glass <sjg@chromium.org> |
| Date: Wed, 18 Dec 2019 11:15:07 -0700 |
| Subject: [PATCH] WIP: hook into emuvariable to sync data with coreboot smm |
| store |
| |
| Change-Id: I7f443b9f36612f79787e1b4b1075176a91107686 |
| Signed-off-by: Patrick Georgi <pgeorgi@google.com> |
| --- |
| .../Variable/EmuRuntimeDxe/EmuVariable.c | 157 ++++++++++++++++++ |
| 1 file changed, 157 insertions(+) |
| |
| diff --git a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c |
| index 6dee2b6add4..45ac02b142c 100644 |
| --- a/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c |
| +++ b/MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariable.c |
| @@ -14,8 +14,53 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. |
|
|
| **/
|
|
|
| +#include <Library/UefiRuntimeServicesTableLib.h>
|
| #include "Variable.h"
|
|
|
| +
|
| +EFI_EVENT mVirtualAddressChangeEvent2 = NULL;
|
| +int storeInitialized = 0;
|
| +VOID *rt_buffer;
|
| +UINTN rt_buffer_phys;
|
| +
|
| +/*
|
| + * calls into SMM with the given cmd and subcmd in eax, and arg in ebx
|
| + *
|
| + * static inline because the resulting assembly is often smaller than
|
| + * the call sequence due to constant folding.
|
| + */
|
| +static inline UINT32 call_smm(UINT8 cmd, UINT8 subcmd, UINT32 arg) {
|
| + UINT32 res = 0;
|
| + __asm__ __volatile__ (
|
| + "outb %b0, $0xb2"
|
| + : "=a" (res)
|
| + : "a" ((subcmd << 8) | cmd), "b" (arg)
|
| + : "memory");
|
| + return res;
|
| +}
|
| +
|
| +#define SMMSTORE_APM_CNT 0xed
|
| +
|
| +#define SMMSTORE_RET_SUCCESS 0
|
| +#define SMMSTORE_RET_FAILURE 1
|
| +#define SMMSTORE_RET_UNSUPPORTED 2
|
| +
|
| +#define SMMSTORE_CMD_CLEAR 1
|
| +#define SMMSTORE_CMD_READ 2
|
| +#define SMMSTORE_CMD_APPEND 3
|
| +
|
| +struct smmstore_params_read {
|
| + UINT32 buf;
|
| + UINT32 bufsize;
|
| +};
|
| +
|
| +struct smmstore_params_append {
|
| + UINT32 key;
|
| + UINT32 keysize;
|
| + UINT32 val;
|
| + UINT32 valsize;
|
| +};
|
| +
|
| ///
|
| /// Don't use module globals after the SetVirtualAddress map is signaled
|
| ///
|
| @@ -1044,6 +1089,33 @@ UpdateVariable ( |
| DataSize
|
| );
|
|
|
| + if (storeInitialized && ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0)) {
|
| +
|
| + /* TODO: add hook for logging nv changes here */
|
| +
|
| + int keysize = sizeof (EFI_GUID) + VarNameSize;
|
| + int valsize = DataSize;
|
| +
|
| + struct smmstore_params_append *data = rt_buffer;
|
| + void *keydata = rt_buffer + sizeof(*data);
|
| + void *valdata = keydata + keysize;
|
| + data->key = (UINT32)(UINTN)rt_buffer_phys + sizeof(*data);
|
| + data->keysize = keysize;
|
| + data->val = data->key + keysize;
|
| + data->valsize = valsize;
|
| +
|
| + CopyMem (keydata, VendorGuid, sizeof (EFI_GUID));
|
| + CopyMem (keydata + sizeof (EFI_GUID), VariableName, VarNameSize);
|
| + CopyMem (valdata, Data, DataSize);
|
| +
|
| + call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_APPEND, (UINT32)rt_buffer_phys);
|
| + /* call into SMM through EFI_ISA_IO_PROTOCOL to write to 0xb2:
|
| + * set registers (how?)
|
| + * UINT8 Data = ...;
|
| + * IsaIo->Io.Write (IsaIo, EfiIsaIoWidthUInt8, 0xb2, 1, &Data);
|
| + */
|
| + }
|
| +
|
| //
|
| // Mark the old variable as deleted
|
| //
|
| @@ -1769,6 +1841,19 @@ InitializeVariableStore ( |
| return EFI_SUCCESS;
|
| }
|
|
|
| +VOID
|
| +EFIAPI
|
| +EmuVariableAddressChangeEvent (
|
| + IN EFI_EVENT Event,
|
| + IN VOID *Context
|
| + )
|
| +{
|
| + //
|
| + // Converts a pointer for runtime memory management to a new virtual address.
|
| + //
|
| + EfiConvertPointer (0x0, (VOID **) &rt_buffer);
|
| +}
|
| +
|
| /**
|
| Initializes variable store area for non-volatile and volatile variable.
|
|
|
| @@ -1816,5 +1901,77 @@ VariableCommonInitialize ( |
| //
|
| Status = InitializeVariableStore (FALSE);
|
|
|
| + /* TODO: add hook for filling nv store from log here */
|
| + const int bufsize = 64 * 1024;
|
| + rt_buffer = AllocateRuntimePool (bufsize);
|
| +
|
| + /* needed later for the 32bit 1:1 mapped SMM interface */
|
| + rt_buffer_phys = (UINTN)rt_buffer;
|
| + ASSERT(rt_buffer_phys <= 0x100000000 - bufsize);
|
| +
|
| + Status = gBS->CreateEventEx (
|
| + EVT_NOTIFY_SIGNAL,
|
| + TPL_NOTIFY,
|
| + EmuVariableAddressChangeEvent,
|
| + NULL,
|
| + &gEfiEventVirtualAddressChangeGuid,
|
| + &mVirtualAddressChangeEvent2
|
| + );
|
| + ASSERT_EFI_ERROR (Status);
|
| +
|
| + /* read store */
|
| + /* we're still phys mapped here, so no magic necessary */
|
| + UINT8 buf[0x10000];
|
| + ASSERT((UINTN)buf <= 0x100000000 - sizeof(buf));
|
| + struct smmstore_params_read read_cmd = {
|
| + .buf = (UINT32)(UINTN)&buf,
|
| + .bufsize = sizeof(buf),
|
| + };
|
| + ASSERT((UINTN)&read_cmd <= 0x100000000 - sizeof(read_cmd));
|
| + call_smm(SMMSTORE_APM_CNT, SMMSTORE_CMD_READ, (UINT32)(UINTN)&read_cmd);
|
| +
|
| + DEBUG ((DEBUG_WARN, "Initialize buffer from 0x%x bytes of flash\n", read_cmd.bufsize));
|
| + int i = 0;
|
| + while (i < read_cmd.bufsize) {
|
| + // assume native endian
|
| + UINT32 keysz = ((UINT32 *)(buf + i))[0];
|
| + if (keysz == 0xffffffff)
|
| + break; // no more entries
|
| + UINTN valsz = ((UINT32 *)(buf + i))[1];
|
| +
|
| + if (i + keysz + valsz + 1 > read_cmd.bufsize)
|
| + break;
|
| + // TODO: check if entry is properly terminated
|
| +
|
| + DEBUG ((DEBUG_WARN, "Found variable: key size: 0x%x, val size: %x\n", keysz, valsz));
|
| + if (keysz > sizeof (EFI_GUID)) {
|
| + CHAR16 *varname = (CHAR16 *)(buf + i + 8 + sizeof (EFI_GUID));
|
| + EFI_GUID *guid = (EFI_GUID *)(buf + i + 8);
|
| + VOID *data = (VOID *)(buf + i + 8 + keysz);
|
| +
|
| + DEBUG ((DEBUG_WARN, "Fetching variable: %s\n", varname));
|
| + DEBUG ((DEBUG_WARN, "buf: %p, buf+i: %p, guid: %p, varname: %p, data: %p\n", buf, buf + i, guid, varname, data));
|
| + VARIABLE_POINTER_TRACK Variable;
|
| + FindVariable (varname, guid, &Variable, (VARIABLE_GLOBAL *)mVariableModuleGlobal);
|
| +
|
| + DEBUG ((DEBUG_WARN, "Updating variable: %s\n", varname));
|
| + UpdateVariable (
|
| + varname,
|
| + guid,
|
| + data,
|
| + valsz,
|
| + // all of these variables are nv
|
| + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
| + &Variable
|
| + );
|
| + }
|
| + DEBUG ((DEBUG_WARN, "Added variable: 0x%x, val size: %x\n", keysz, valsz));
|
| + // no UEFI variable since it's at most the GUID part, so skip
|
| + i += 8 + keysz + valsz + 1;
|
| + i = (i + 3) & ~3;
|
| + }
|
| +
|
| + storeInitialized = 1;
|
| +
|
| return Status;
|
| }
|
| -- |
| 2.24.1.735.g03f4e72817-goog |
| |