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