summaryrefslogtreecommitdiff
path: root/Documentation
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 /Documentation
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 'Documentation')
-rw-r--r--Documentation/drivers/index.md1
-rw-r--r--Documentation/drivers/smmstorev2.md221
2 files changed, 222 insertions, 0 deletions
diff --git a/Documentation/drivers/index.md b/Documentation/drivers/index.md
index e215c6ab11..508beaf40a 100644
--- a/Documentation/drivers/index.md
+++ b/Documentation/drivers/index.md
@@ -7,3 +7,4 @@ they allow to easily reuse existing code accross platforms.
* [IPMI KCS](ipmi_kcs.md)
* [SMMSTORE](smmstore.md)
* [SoundWire](soundwire.md)
+* [SMMSTOREv2](smmstorev2.md)
diff --git a/Documentation/drivers/smmstorev2.md b/Documentation/drivers/smmstorev2.md
new file mode 100644
index 0000000000..cb79b8b6b8
--- /dev/null
+++ b/Documentation/drivers/smmstorev2.md
@@ -0,0 +1,221 @@
+# SMM based flash storage driver Version 2
+
+This documents the API exposed by the x86 system management based
+storage driver.
+
+## SMMSTOREv2
+
+SMMSTOREv2 is a [SMM] mediated driver to read from, write to and erase
+a predefined region in flash. It can be enabled by setting
+`CONFIG_SMMSTORE=y` and `CONFIG_SMMSTORE_V2=y` in menuconfig.
+
+This can be used by the OS or the payload to implement persistent
+storage to hold for instance configuration data, without needing to
+implement a (platform specific) storage driver in the payload itself.
+
+### Storage size and alignment
+
+SMMSTORE version 2 requires a minimum alignment of 64 KiB, which should
+be supported by all flash chips. Not having to perform read-modify-write
+operations is desired, as it reduces complexity and potential for bugs.
+
+This can be used by a FTW (FaultTolerantWrite) implementation that uses
+at least two regions in an A/B update scheme. The FTW implementation in
+EDK2 uses three different regions in the store:
+
+- The variable store
+- The FTW spare block
+- The FTW working block
+
+All regions must be block-aligned, and the FTW spare size must be larger
+than that of the variable store. FTW working block can be much smaller.
+With 64 KiB as block size, the minimum size of the FTW-enabled store is:
+
+- The variable store: 1 block = 64 KiB
+- The FTW spare block: 2 blocks = 2 * 64 KiB
+- The FTW working block: 1 block = 64 KiB
+
+Therefore, the minimum size for EDK2 FTW is 4 blocks, or 256 KiB.
+
+## API
+
+The API provides read and write access to an unformatted block storage.
+
+### Storage region
+
+By default SMMSTOREv2 will operate on a separate FMAP region called
+`SMMSTORE`. The default generated FMAP will include such a region. On
+systems with a locked FMAP, e.g. in an existing vboot setup with a
+locked RO region, the option exists to add a cbfsfile called `smm_store`
+in the `RW_LEGACY` (if CHROMEOS) or in the `COREBOOT` FMAP regions. It
+is recommended for new builds using a handcrafted FMD that intend to
+make use of SMMSTORE to include a sufficiently large `SMMSTORE` FMAP
+region. It is mandatory to align the `SMMSTORE` region to 64KiB for
+compatibility with the largest flash erase operation.
+
+When a default generated FMAP is used, the size of the FMAP region is
+equal to `CONFIG_SMMSTORE_SIZE`. UEFI payloads expect at least 64 KiB.
+To support a fault tolerant write mechanism, at least a multiple of
+this size is recommended.
+
+### Communication buffer
+
+To prevent malicious ring0 code to access arbitrary memory locations,
+SMMSTOREv2 uses a communication buffer in CBMEM/HOB for all transfers.
+This buffer has to be at least 64 KiB in size and must be installed
+before calling any of the SMMSTORE read or write operations. Usually,
+coreboot will install this buffer to transfer data between ring0 and
+the [SMM] handler.
+
+In order to get the communication buffer address, the payload or OS
+has to read the coreboot table with tag `0x0039`, containing:
+
+```C
+struct lb_smmstorev2 {
+ uint32_t tag;
+ uint32_t size;
+ uint32_t num_blocks; /* Number of writeable blocks in SMM */
+ uint32_t block_size; /* Size of a block in byte. Default: 64 KiB */
+ uint32_t mmap_addr; /* MMIO address of the store for read only access */
+ uint32_t com_buffer; /* Physical address of the communication buffer */
+ uint32_t com_buffer_size; /* Size of the communication buffer in byte */
+ uint8_t apm_cmd; /* The command byte to write to the APM I/O port */
+ uint8_t unused[3]; /* Set to zero */
+};
+```
+
+The absence of this coreboot table entry indicates that there's no
+SMMSTOREv2 support.
+
+### Blocks
+
+The SMMSTOREv2 splits the SMMSTORE FMAP partition into smaller chunks
+called *blocks*. Every block is at least the size of 64KiB to support
+arbitrary NOR flash erase ops. A payload or OS must make no further
+assumptions about the block or communication buffer size.
+
+### Generating the SMI
+
+SMMSTOREv2 is called via an SMI, which is generated via a write to the
+IO port defined in the smi_cmd entry of the FADT ACPI table. `%al`
+contains `APM_CNT_SMMSTORE=0xed` and is written to the smi_cmd IO
+port. `%ah` contains the SMMSTOREv2 command. `%ebx` contains the
+parameter buffer to the SMMSTOREv2 command.
+
+### Return values
+
+If a command succeeds, SMMSTOREv2 will return with
+`SMMSTORE_RET_SUCCESS=0` in `%eax`. On failure SMMSTORE will return
+`SMMSTORE_RET_FAILURE=1`. For unsupported SMMSTORE commands
+`SMMSTORE_REG_UNSUPPORTED=2` is returned.
+
+**NOTE 1**: The caller **must** check the return value and should make
+no assumption on the returned data if `%eax` does not contain
+`SMMSTORE_RET_SUCCESS`.
+
+**NOTE 2**: If the SMI returns without changing `%ax`, it can be assumed
+that the SMMSTOREv2 feature is not installed.
+
+### Calling arguments
+
+SMMSTOREv2 supports 3 subcommands that are passed via `%ah`, the
+additional calling arguments are passed via `%ebx`.
+
+**NOTE**: The size of the struct entries are in the native word size of
+smihandler. This means 32 bits in almost all cases.
+
+#### - SMMSTORE_CMD_INIT = 4
+
+This installs the communication buffer to use and thus enables the
+SMMSTORE handler. This command can only be executed once and is done
+by the firmware. Calling this function at runtime has no effect.
+
+The additional parameter buffer `%ebx` contains a pointer to the
+following struct:
+
+```C
+struct smmstore_params_init {
+ uint32_t com_buffer;
+ uint32_t com_buffer_size;
+} __packed;
+```
+
+INPUT:
+- `com_buffer`: Physical address of the communication buffer (CBMEM)
+- `com_buffer_size`: Size in bytes of the communication buffer
+
+#### - SMMSTORE_CMD_RAW_READ = 5
+
+SMMSTOREv2 allows reading arbitrary data. It is up to the caller to
+initialize the store with meaningful data before using it.
+
+The additional parameter buffer `%ebx` contains a pointer to the
+following struct:
+
+```C
+struct smmstore_params_raw_read {
+ uint32_t bufsize;
+ uint32_t bufoffset;
+ uint32_t block_id;
+} __packed;
+```
+
+INPUT:
+- `bufsize`: Size of data to read within the communication buffer
+- `bufoffset`: Offset within the communication buffer
+- `block_id`: Block to read from
+
+#### - SMMSTORE_CMD_RAW_WRITE = 6
+
+SMMSTOREv2 allows writing arbitrary data. It is up to the caller to
+erase a block before writing it.
+
+The additional parameter buffer `%ebx` contains a pointer to
+the following struct:
+
+```C
+struct smmstore_params_raw_write {
+ uint32_t bufsize;
+ uint32_t bufoffset;
+ uint32_t block_id;
+} __packed;
+```
+
+INPUT:
+- `bufsize`: Size of data to write within the communication buffer
+- `bufoffset`: Offset within the communication buffer
+- `block_id`: Block to write to
+
+#### - SMMSTORE_CMD_RAW_CLEAR = 7
+
+SMMSTOREv2 allows clearing blocks. A cleared block will read as `0xff`.
+By providing multiple blocks the caller can implement a fault tolerant
+write mechanism. It is up to the caller to clear blocks before writing
+to them.
+
+
+```C
+struct smmstore_params_raw_clear {
+ uint32_t block_id;
+} __packed;
+```
+
+INPUT:
+- `block_id`: Block to erase
+
+#### Security
+
+Pointers provided by the payload or OS are checked to not overlap with
+SMM. This protects the SMM handler from being compromised.
+
+As all information is exchanged using the communication buffer and
+coreboot tables, there's no risk that a malicious application capable
+of issuing SMIs could extract arbitrary data or modify the currently
+running kernel.
+
+## External links
+
+* [A Tour Beyond BIOS Implementing UEFI Authenticated Variables in SMM with EDKI](https://software.intel.com/sites/default/files/managed/cf/ea/a_tour_beyond_bios_implementing_uefi_authenticated_variables_in_smm_with_edkii.pdf)
+Note that this differs significantly from coreboot's implementation.
+
+[SMM]: ../security/smm.md