xref: /openbmc/phosphor-ipmi-blobs/README.md (revision aceb4baa)
1# Phosphor Blob Transfer Interface
2
3This document describes the commands implementing a generic blob transfer
4interface. This document does not specify how blobs are stored; that is left up
5to blob-specific implementations. Introduction This mechanism supports reading
6and writing from a generic blob store. This mechanism can be leveraged to
7support firmware upgrades,
8
9The interface defined in this document supports:
10
11*   Enumerating blobs
12*   Opening a blob for reading or writing
13*   Writing blob content
14*   Committing a blob
15*   Polling until the blob has been committed
16*   Closing a blob
17*   Reading blob content
18*   Deleting a blob
19
20Some blobs will only support a subset of these operations. For example, firmware
21cannot generally be read, as the firmware file is not persisted on the BMC after
22it has been activated.
23
24This specification supports IPMI as a transport layer. This can be quite slow,
25however; IPMI transport speeds range from 23 kbps to 256 kbps. LPC/P2A ("PCI to
26Aspeed") MMIO bridges are currently unsupported. Blob Identifiers Blobs are
27identified by NULL-terminated C strings. This protocol supports
28implementation-specific blob identifiers; some blobs may have single well-known
29names, while others may be defined only by a prefix, with the client specifying
30the rest of the blob name. For example, "/g/bmc_firmware" may represent a single
31well-known blob that supports BMC firmware updates, whereas "/g/skm/[N]" may
32represent an arbitrary number of SKM keys, with the index specified on the host
33when opening the blob.
34
35Blob identifiers are limited based on the maximum size of the IPMI packet. This
36maximum size is platform-dependent; theoretically a packet could be up to 256
37bytes, but some hardware only supports packets up to 64 bytes.
38
39If an identifier is malformed, e.g. does not have a trailing NUL-byte or is
40otherwise unrecognizable by the BMC, an error is returned.
41
42## Commands
43
44The following details each subcommand in the blob spec. In the following, any
45reference to the command body starts after the 3 bytes of OEM header, the 1-byte
46subcommand code, and (in the cases where the command body is non-empty) a
47two-byte CRC over all data that follows in the body.
48
49All non-empty responses should lead with a two-byte CRC. The CRC algorithm is
50CRC-16-CCITT (poly 0x1021).
51
52All multi-byte values are encoded as little-endian. All structs are assumed
53packed. Success codes are returned via the "completion code" field from the IPMI
54spec.
55
56### BmcBlobGetCount (0)
57
58The `BmcBlobGetCount` command expects to receive an empty body. The BMC will
59return the number of enumerable blobs:
60
61```
62struct BmcBlobCountRx {
63    uint16_t crc16;
64    uint32_t blob_count;
65};
66```
67
68### BmcBlobEnumerate (1)
69
70The `BmcBlobEnumerate` command expects to receive a body of:
71
72```
73struct BmcBlobEnumerateTx {
74    uint16_t crc16;
75    uint32_t blob_idx; /* 0-based index of blob to retrieve. */
76};
77```
78
79The BMC will return the corresponding blob identifier:
80
81```
82struct BmcBlobEnumerateRx {
83    uint16_t crc16;
84    char     blob_id[];
85};
86```
87
88Note that the index for a given blob ID is not expected to be stable across a
89long term. Callers are expected to call `BmcBlobGetCount`, followed by N calls
90to `BmcBlobEnumerate`, to collect all blob IDs. Callers can then call
91`BmcBlobStat` with each blob ID. If this process is interleaved with Open or
92Delete calls that modify the number of enumerable blobs, this operation will be
93subject to concurrent modification issues.
94
95### BmcBlobOpen (2)
96
97The BmcBlobOpen command expects to receive a body of:
98
99```
100struct BmcBlobOpenTx {
101    uint16_t crc16;
102    uint16_t flags;
103    char     blob_id[]; /* Must correspond to a valid blob. */
104};
105```
106
107The flags field allows the caller to specify whether the blob is being opened
108for reading or writing:
109
110```
111enum BmcBlobOpenFlagBits {
112    READ = 0,
113    WRITE = 1,
114    <bits 2-7 reserved>
115    <bits 8-15 given blob-specific definitions>
116};
117```
118
119If the `WRITE` flag is specified, the BMC will mark the specified blob as "open
120for writing". Optional blob-specific behavior: if the blob has been open for
121more than one minute without any activity, the existing session will be torn
122down and the open will succeed. Alternatively, blobs may allow multiple write
123sessions to be active at once.
124
125The BMC allocates a unique session identifier, and internally maps it to the
126blob identifier.
127
128```
129struct BmcBlobOpenRx {
130    uint16_t crc16;
131    uint16_t session_id;
132};
133```
134
135### BmcBlobRead (3)
136
137The BmcBlobRead command is used to read blob data. It expects to receive a body
138of:
139
140```
141struct BmcBlobReadTx {
142    uint16_t crc16;
143    uint16_t session_id; /* Returned from BmcBlobOpen. */
144    uint32_t offset; /* The byte sequence start, 0-based. */
145    uint32_t requested_size; /* The number of bytes requested for reading. */
146};
147```
148
149Blob handlers may require the blob’s "state" to equal `OPEN_R` before reading is
150successful.
151
152```
153struct BmcBlobReadRx {
154    uint16_t crc16;
155    uint8_t  data[];
156};
157```
158
159Immediately following this structure are the bytes being read. The number of
160bytes transferred is the size of the response body less the OEN ("OEM number")
161(3 bytes), sub-command (1 byte), and the structure size (4 bytes). If no bytes
162are transferred, the CRC is still sent.
163
164If the BMC cannot return the number of requested bytes, it simply returns the
165number of bytes available for reading. If the host tries to read at an invalid
166offset or if the host tries to read at the end of the blob, an empty successful
167response is returned; e.g., data is empty.
168
169### BmcBlobWrite (4)
170
171The `BmcBlobWrite` command expects to receive a body of:
172
173```
174struct BmcBlobWriteTx {
175    uint16_t crc16;
176    uint16_t session_id; /* Returned from BmcBlobOpen. */
177    uint32_t offset; /* The byte sequence start, 0-based. */
178    uint8_t  data[];
179};
180```
181
182Immediately following this structure are the bytes to write. The length of the
183entire packet is variable and handled at a higher level, therefore the number of
184bytes to write is the size of the command body less the OEN and sub-command (4
185bytes) and less the structure size (10 bytes). It is assumed that all writes are
186sequential, and begin at offset zero.
187
188On success it will return a success completion code.
189
190### BmcBlobCommit (5)
191
192The `BmcBlobCommit` command expects to receive a body of:
193
194```
195struct BmcBlobCommitTx {
196    uint16_t crc16;
197    uint16_t session_id; /* Returned from BmcBlobOpen. */
198    uint8_t  commit_data_len;
199    uint8_t  commit_data[]; /* Optional blob-specific commit data. */
200};
201```
202
203Each blob defines its own commit behavior. A BMC firmware blob may be verified
204and saved to the filesystem. Commit operations may require additional
205data, which
206would be provided following the structure in the IPMI packet.
207
208The commit operation may exceed the IPMI timeout duration of ~5 seconds
209(implementation dependant). Callers are expected to poll on `BmcBlobSessionStat`
210or `BmcBlobStat` (as appropriate) until committing has finished. To address race
211conditions, blobs should not allow concurrent sessions that modify state.
212
213On success, the BMC returns success completion code.
214
215### BmcBlobClose (6)
216
217The `BmcBlobClose` command must be called after commit-polling has finished,
218regardless of the result. It expects to receive a body of:
219
220```
221struct BmcBlobCloseTx {
222    uint16_t crc16;
223    uint16_t session_id; /* Returned from BmcBlobOpen. */
224};
225```
226
227The BMC marks the specified blob as closed. On success, the BMC returns a
228success completion code.
229
230### BmcBlobDelete (7)
231
232The `BmcBlobDelete` command is used to delete a blob. Not all blobs will support
233deletion. This command expects to receive a body of:
234
235```
236struct BmcBlobDeleteTx {
237    uint16_t crc16;
238    char     blob_id[]; /* Must correspond to a valid blob. */
239};
240```
241
242If the operation is supported, the blob is deleted. On success, the BMC returns
243a success completion code. This command will fail if there are open sessions for
244the blob.
245
246### BmcBlobStat (8)
247
248The `BmcBlobStat` command is used to retrieve statistics about a blob. Not all
249blobs must support this command; this is only useful when blob_id semantics are
250more useful than session IDs. This command expects to receive a body of:
251
252```
253struct BmcBlobStatTx {
254    uint16_t crc16;
255    char     blob_id[]; /* Must correspond to a valid blob. */
256};
257```
258
259The BMC returns the following data:
260
261```
262struct BmcBlobStatRx {
263    uint16_t crc16;
264    uint16_t blob_state;
265    uint32_t size; /* Size in bytes of the blob. */
266    uint8_t  metadata_len;
267    uint8_t  metadata[]; /* Optional blob-specific metadata. */
268};
269```
270
271The blob_state field is a bit field with the following flags:
272
273```
274enum BmcBlobStateFlagBits {
275    OPEN_R = 0,
276    OPEN_W = 1,
277    COMMITTING = 2,
278    COMMITTED = 3,
279    COMMIT_ERROR = 4,
280    <bits 5-7 reserved>
281    <bits 8-15 given blob-specific definitions>
282};
283```
284
285If the state is `COMMITTING`, the blob is not currently available for reading or
286writing. If the state is `COMMITTED`, the blob may be available for reading.
287
288The size field may be zero if the blob does not support reading.
289
290Immediately following this structure are optional blob-specific bytes. The
291number of bytes transferred is the size of the response body less the OEN and
292sub-command and less the structure size. The metadata must fit in a single IPMI
293packet, which has a platform-dependent maximum size. (For reference, Aspeed
294supports 64 bytes max.)
295
296If the blob is open or committed but has been inactive for longer than the
297specified activity timeout, the blob is closed, and blob_status is set to
298`CLOSED` in the response.
299
300### BmcBlobSessionStat (9)
301
302The `BmcBlobSessionStat` command returns the same data as `BmcBlobStat`.
303However, this command operates on sessions, rather than blob IDs. Not all blobs
304must support this command; this is only useful when session semantics are more
305useful than raw blob IDs.
306
307```
308struct BmcBlobSessionStatTx {
309    uint16_t crc16;
310    uint16_t session_id; /* Returned from BmcBlobOpen. */
311};
312```
313
314```
315struct BmcBlobSessionStatRx {
316    uint16_t crc16;
317    uint16_t blob_state;
318    uint32_t size; /* Size in bytes of the blob. */
319    uint8_t  metadata_size;
320    uint8_t  metadata[]; /* Optional blob-specific metadata. */
321};
322```
323
324## Idempotent Commands
325
326The IPMI transport layer is somewhat flaky. Client code must rely on a
327"send-with-retries" strategy to ensure that commands make their way from the
328host to the BMC. Commands can fail if the BMC is busy with other commands.
329
330It is possible that an IPMI command successfully invokes the BMC-side handler,
331but that the response does not successfully make its way back to the host. In
332this case, the host may decide to retry the command. Thus, command handlers
333should be idempotent where possible; duplicate calls should return the same
334value if repeated, while avoiding potentially destructive side-effects.
335
336## Stale Sessions
337
338Each blob type will define an operation for cleansing stale sessions. This could
339involve scrubbing secrets or freeing buffers. A function will be provided that
340will scan over each open session, to determine which if any sessions have been
341open for longer than 10 minutes with no activity. For each session, the
342associated blob type’s cleansing routine will be invoked, and the associated
343session ID will be freed. This function will be invoked from the `BmcBlobOpen`
344command handler, though not more than once every minute.
345