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