Skip to content
Permalink
Browse files

WIP: hook into emuvariable to sync data with coreboot smm store

changed: buffer size from 64k to 256k

Change-Id: I7f443b9f36612f79787e1b4b1075176a91107686
Signed-off-by: Patrick Georgi <pgeorgi@google.com>
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
  • Loading branch information...
MattDevo committed Aug 24, 2018
1 parent a81000a commit c792dbf1bd692bb95781a79d5d2d886a4933bc77
Showing with 157 additions and 0 deletions.
  1. +157 −0 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[0x40000];
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;
}

0 comments on commit c792dbf

Please sign in to comment.
You can’t perform that action at this time.