aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/smmstore/smi.c
diff options
context:
space:
mode:
authorPatrick Rudolph <patrick.rudolph@9elements.com>2020-04-17 16:16:49 +0200
committerMichał Żygowski <michal.zygowski@3mdeb.com>2020-10-22 12:29:47 +0000
commitbc744f5893fc4d53275ed26dd8d968011c6a09c1 (patch)
treefb283c9d57431020405a5404db04b425428f7709 /src/drivers/smmstore/smi.c
parenta693fa06cd32da8239f820d833bb7a1bf55bf351 (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.c81
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);
+}