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