1# BMC Generic Binary Blob Store via OEM IPMI Blob Transport
2
3Author: Kun Yi (kunyi@google.com, kunyi!)
4
5Created: 2018-12-07
6
7## Problem Description
8Server platform host OS often needs to store and/or access data coupled
9with the machine itself, which in most cases has a 1:1 mapping with the
10motherboard. Traditionally, this is achieved by directly accessing the FRU
11EEPROM, or going through BMC using IPMI FRU commands. However, it may not
12always be viable or desirable due to:
13
14* The FRU data may be programmed by MFG and treated as read-only
15* The FRU data may not be in IPMI FRU format
16* The data to store may not fit in the data types defined in IPMI FRU spec
17* Host may want to store multiple copies in e.g. BMC EEPROM
18
19The BMC generic IPMI blobs binary store, or "binary store" in short, serves a
20simple purpose: provide a read/write/serialize abstraction layer through IPMI
21blobs transport layer to allow users to store binary data on persistent
22locations accessible to the BMC.
23
24Despite its name, the binary blob store cannot be used for everything.
25
26* It is not a host/BMC mailbox. In general, BMC should reserve the space for
27  blob store and not try to write it due to concurrency concerns. It is
28  expected the only accessors are the IPMI blob store commands.
29* It is not a key store. Because the data stored is accessible to IPMI users
30  and is not encrypted in anyway, extra caution should be used. It is not
31  meant for storing data containing any keys or secrets.
32* The data to be stored should not be too large. Since each IPMI packet is
33  limited in size, trying to send an overly large binary is going to take too
34  long, and the overhead of the IPMI transport layer might make it not
35  worthwhile.
36
37## Background and References
38Please read the IPMI Blob protocol design as primer
39[here](https://github.com/openbmc/phosphor-ipmi-blobs/blob/master/README.md).
40
41Under the hood, the binary blobs are stored as a binary [protocol
42buffer](https://github.com/protocolbuffers/protobuf), or "protobuf" in short.
43
44## Requirements
451. BMC image should have `phosphor-ipmi-blobs` installed.
461. The host should know the specific blob base id that it intends to operate on.
47   For this design the discovery operations are limited.
481. The host should only store binary data that is suitable using this transfer
49   mechanism. As mentioned it is not meant for mailbox communication, key store,
50   or large binary data.
51
52## Proposed Design
53This section describes how the handler `phosphor-ipmi-blobs-binarystore`
54defines each handler of the IPMI Blob protocol.
55
56### Blob ID Definition
57
58A "blob id" is a unique string that identifies a blob. Binary Store handler may
59show two kinds of blob ids: "base id" and "file id". They should only contain
60ASCII alphanumerical characters and forward slashes ('/').
61
62A "base id" begins and ends with a forward slash. It is analogous to a Unix
63directory path. The binary store handler will assign each storage location a
64unique base id (See next section for details).
65
66A "file id" begins with a forward slash but must not have a slash at the end,
67and is analogous to a Unix file path. Any file id with a valid base id as its
68longest matching prefix is considered reserved as a binary blob in the storage
69space.
70
71For example, if `/test/` and `/test/blob0` are the initial blob ids, we know
72there is one binary store location with one blob already created. To create a
73new blob named `/test/blob1`, one simply calls open with the id and write/commit
74with the returned session id. Opening invalid ids such as `/foo/bar` or
75`/test/nested/dir` will fail.
76
77### Platform Configuration
78For the binary store handler, a configuration file provides the base id,
79which file and which offset in the file to store the data. Optionally a
80"max\_size" param can be specified to indicate the total size of such binary
81storage should not exceed the limitation. If "max\_size" is specified as -1 or
82not specified, the storage could grow up to what the physical media allows.
83
84```none
85base_id: /bmc_store/
86sysfile_path: /sys/class/i2c-dev/i2c-1/device/1-0050/eeprom
87offset: 256
88max_size: 1024
89```
90[1] Example Configuration
91
92### Binary Store Protobuf Definition
93
94The data is stored as a binary protobuf containing a variable number of binary
95blobs, each having a unique blob\_id string with the base id as a common prefix.
96
97```none
98message BinaryBlob {
99  optional string blob_id = 1;
100  optional bytes data = 2;
101}
102
103message BinaryBlobStore {
104  optional string blob_base_id = 1;
105  repeated BinaryBlob blob = 2;
106  optional uint32 max_size = 3;
107}
108```
109
110Storing data as a protobuf makes the format more flexible and expandable, and
111allows future modifications to the storage format.
112
113### IPMI Blob Transfer Command Primitives
114
115The binary store handler will implement the following primitives:
116
117#### BmcBlobGetCount/BmcBlobEnumerate
118Initially only the base id will appear when enumerating the existing blobs.
119Once a valid binary has successfully been committed, its blob id will appear
120in the list.
121
122#### BmcBlobOpen
123`flags` can be `READ` for read-only access or `READ|WRITE`. `blob_id` can be
124any string with a matching prefix. If there is not already a valid binary
125stored with supplied `blob_id`, the handler treats it as a request to create
126such a blob.
127
128The `session_id` returned should be used by the rest of the session based
129commands to operate on the blob. If there is already an open session, this
130call will fail.
131
132NOTE: the newly created blob is not serialized and stored until `BmcBlobCommit`
133is called.
134
135#### BmcBlobRead
136Returns bytes with the requested offset and size. If there are not enough bytes
137the handler will return the bytes that are available.
138
139Note this operation reads from memory. Make sure the stat is 'COMMITTED' which
140indicates that the memory content matches the data serialized to storage.
141
142#### BmcBlobWrite
143Writes bytes to the requested offset. Return number of bytes written if success,
144zero if failed.
145
146#### BmcBlobCommit
147Store the serialized BinaryBlobStore to associated system file.
148
149#### BmcBlobClose
150Mark the session as closed. Any uncommitted changes to the blob state is lost.
151
152#### BmcBlobDelete
153Delete the binary data associated with `blob_id`.
154Deleting the base\_id (the 'directory' level) will fail harmlessly.
155
156#### BmcBlobStat
157`size` returned equals to length of the `data` bytes in the protobuf.
158`blob_state` will be set with `OPEN_R`, `OPEN_W`, and/or `COMMITTED` as
159appropriate.
160
161#### BmcBlobSessionStat/BmcBlobWriteMeta
162Not supported.
163
164### Example Host Command Flow
165
166#### No binary data yet, write data
1671. `BmcBlobGetCount` followed by `BmcBlobEnumerate`. Since there is
168   no valid blob with binary data stored, BMC handler only populates the
169   `base_id` per platform configuration. e.g. `/bmc_store/`.
1701. `BmcBlobOpen` with `blob_id = /bmc_store/blob0`, BMC honors the
171   request and returns `session_id = 0`.
1721. `BmcBlobWrite` multiple times to write the data into the blob.
1731. `BmcBlobCommit`. BMC writes data into configured path, e.g. to EEPROM.
1741. `BmcBlobClose`
175
176#### Read existing data
1771. `BmcBlobGetCount` followed by `BmcBlobEnumerate` shows `/bmc_store/` and
178   `/bmc_store/blob0`.
1791. `BmcBlobStat` on `/bmc_store/blob0` shows non-zero size and `COMMITTED`
180   state.
1811. `BmcBlobOpen` with `blob_id = /bmc_store/blob0`.
1821. `BmcBlobRead` multiple times to read the data.
1831. `BmcBlobClose`.
184
185## Alternatives Considered
186The first alternative considered was to store the data via IPMI FRU commands;
187as mentioned in the problem description, it is not always viable.
188
189There is a Google OEM I2C-over-IPMI driver that allows the host to read/write
190I2C devices attached to the BMC. In comparison, the blob store approach proposed
191offer more abstraction and is more flexible in where to store the data.
192
193## Impacts
194***Security***:
195As mentioned, the binary store transfer mechanism doesn't offer encryption.
196Entities storing the data through this mechanism should be aware and either
197not to transfer security-critical data, or supply their own security
198mechanism on top.
199
200***BMC performance***:
201Since the handler requires protobuf package, it may increase
202BMC image size if the package wasn't previously installed.
203
204***Host compatibility***:
205If data has been stored using IPMI blob binary store, then the host
206would need a handler that understands the blob transfer
207semantics to read the data.
208
209## Testing
210Where possible mockable interfaces will be used to unit test the logic of the
211code.
212