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