summaryrefslogtreecommitdiffstats
path: root/Documentation/drivers/smmstore.md
blob: ecf937b1d0927a933397b457733e790c49520a7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# SMM based flash storage driver

This documents the API exposed by the x86 system management based
storage driver.

## SMMSTORE

SMMSTORE 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` 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.

The API provides append-only semantics for key/value pairs.

## API

### Storage region

By default SMMSTORE 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 recommended to
align the `SMMSTORE` region to 64KiB for the largest flash erase
op compatibility.

When a default generated FMAP is used the size of the FMAP region
is equal to `CONFIG_SMMSTORE_SIZE`. UEFI payloads expect at least
64KiB. Given that the current implementation lacks a way to rewrite
key-value pairs at least a multiple of this is recommended.

### generating the SMI

SMMSTORE 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 SMMSTORE command. `%ebx` contains the
parameter buffer to the SMMSTORE command.

### Return values

If a command succeeds, SMMSTORE will return with
`SMMSTORE_RET_SUCCESS=0` on `%eax`. On failure SMMSTORE will return
`SMMSTORE_RET_FAILURE=1`. For unsupported SMMSTORE commands
`SMMSTORE_REG_UNSUPPORTED=2` is returned.

**NOTE1**: The caller **must** check the return value and should make
no assumption on the returned data if `%eax` does not contain
`SMMSTORE_RET_SUCCESS`.

**NOTE2**: If the SMI returns without changing `%ax` assume that the
SMMSTORE feature is not installed.

### Calling arguments

SMMSTORE 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_CLEAR = 1

This clears the `SMMSTORE` storage region. The argument in `%ebx` is
unused.

#### - SMMSTORE_CMD_READ = 2

The additional parameter buffer `%ebx` contains a pointer to
the following struct:

```C
struct smmstore_params_read {
	void *buf;
	ssize_t bufsize;
};
```

INPUT:
- `buf`: is a pointer to where the data needs to be read
- `bufsize`: is the size of the buffer

OUTPUT:
- `buf`
- `bufsize`: returns the amount of data that has actually been read.

#### - SMMSTORE_CMD_APPEND = 3

SMMSTORE takes a key-value approach to appending data. key-value pairs
are never updated, they are always appended. It is up to the caller to
walk through the key-value pairs after reading SMMSTORE to find the
latest one.

The additional parameter buffer `%ebx` contains a pointer to
the following struct:

```C
struct smmstore_params_append {
	void *key;
	size_t keysize;
	void *val;
	size_t valsize;
};
```

INPUT:
- `key`: pointer to the key data
- `keysize`: size of the key data
- `val`: pointer to the value data
- `valsize`: size of the value data

## 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, this differs significantly from coreboot's implementation.