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