diff options
author | Patrick Rudolph <patrick.rudolph@9elements.com> | 2020-04-17 16:16:49 +0200 |
---|---|---|
committer | Michał Żygowski <michal.zygowski@3mdeb.com> | 2020-10-22 12:29:47 +0000 |
commit | bc744f5893fc4d53275ed26dd8d968011c6a09c1 (patch) | |
tree | fb283c9d57431020405a5404db04b425428f7709 /src/drivers/smmstore/smi.c | |
parent | a693fa06cd32da8239f820d833bb7a1bf55bf351 (diff) |
drivers/smmstore: Implement SMMSTORE version 2
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 <patrick.rudolph@9elements.com>
Signed-off-by: Christian Walter <christian.walter@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/40520
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Michał Żygowski <michal.zygowski@3mdeb.com>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Diffstat (limited to 'src/drivers/smmstore/smi.c')
-rw-r--r-- | src/drivers/smmstore/smi.c | 81 |
1 files changed, 78 insertions, 3 deletions
diff --git a/src/drivers/smmstore/smi.c b/src/drivers/smmstore/smi.c index b21423e90e..b90338c619 100644 --- a/src/drivers/smmstore/smi.c +++ b/src/drivers/smmstore/smi.c @@ -23,8 +23,7 @@ static int range_check(void *start, size_t size) return 0; } -/* Param is usually EBX, ret in EAX */ -uint32_t smmstore_exec(uint8_t command, void *param) +static uint32_t smmstorev1_exec(uint8_t command, void *param) { uint32_t ret = SMMSTORE_RET_FAILURE; @@ -66,13 +65,89 @@ uint32_t smmstore_exec(uint8_t command, void *param) ret = SMMSTORE_RET_SUCCESS; break; } + default: + printk(BIOS_DEBUG, + "Unknown SMM store v1 command: 0x%02x\n", command); + ret = SMMSTORE_RET_UNSUPPORTED; + break; + } + return ret; +} + +static uint32_t smmstorev2_exec(uint8_t command, void *param) +{ + uint32_t ret = SMMSTORE_RET_FAILURE; + + switch (command) { + case SMMSTORE_CMD_INIT: { + printk(BIOS_DEBUG, "Init SMM store\n"); + struct smmstore_params_init *params = param; + + if (range_check(params, sizeof(*params)) != 0) + break; + + void *buf = (void *)(uintptr_t)params->com_buffer; + + if (range_check(buf, params->com_buffer_size) != 0) + break; + + if (smmstore_init(buf, params->com_buffer_size) == 0) + ret = SMMSTORE_RET_SUCCESS; + break; + } + case SMMSTORE_CMD_RAW_READ: { + printk(BIOS_DEBUG, "Raw read from SMM store, param = %p\n", param); + struct smmstore_params_raw_read *params = param; + + if (range_check(params, sizeof(*params)) != 0) + break; + + if (smmstore_rawread_region(params->block_id, params->bufoffset, + params->bufsize) == 0) + ret = SMMSTORE_RET_SUCCESS; + break; + } + case SMMSTORE_CMD_RAW_WRITE: { + printk(BIOS_DEBUG, "Raw write to SMM store, param = %p\n", param); + struct smmstore_params_raw_write *params = param; + + if (range_check(params, sizeof(*params)) != 0) + break; + + if (smmstore_rawwrite_region(params->block_id, params->bufoffset, + params->bufsize) == 0) + ret = SMMSTORE_RET_SUCCESS; + break; + } + case SMMSTORE_CMD_RAW_CLEAR: { + printk(BIOS_DEBUG, "Raw clear SMM store, param = %p\n", param); + struct smmstore_params_raw_clear *params = param; + + if (range_check(params, sizeof(*params)) != 0) + break; + + if (smmstore_rawclear_region(params->block_id) == 0) + ret = SMMSTORE_RET_SUCCESS; + break; + } default: printk(BIOS_DEBUG, - "Unknown SMM store command: 0x%02x\n", command); + "Unknown SMM store v2 command: 0x%02x\n", command); ret = SMMSTORE_RET_UNSUPPORTED; break; } return ret; } + +uint32_t smmstore_exec(uint8_t command, void *param) +{ + if (!param) + return SMMSTORE_RET_FAILURE; + + if (CONFIG(SMMSTORE_V2)) + return smmstorev2_exec(command, param); + else + return smmstorev1_exec(command, param); +} |