1# In-Band Update of BMC Firmware (and others) using OEM IPMI Blob Transport
2
3Author: Patrick Venture <venture!>
4
5Primary assignee: Patrick Venture
6
7Created: 2018-10-18
8
9## Problem Description
10
11The BMC needs a mechanism for receiving a new firmware image from the host
12through a variety of mechanisms. This can best be served with one protocol into
13which multiple approaches can be routed.
14
15## Background and References
16
17BMC hardware provides at a minimum some interface for sending and receiving IPMI
18messages. This hardware may also provide regions that can be memory mapped for
19higher speed communication between the BMC and the host. Certain infrastructures
20do not provide network access to the BMC, therefore it is required to provide an
21update mechanism that can be done in-band between the host and the BMC.
22
23In-band here refers to a communications channel that is directly connected
24between the host and BMC.
25
261.  Serial
271.  IPMI over LPC
281.  IPMI over i2c
291.  LPC Memory-Mapped Region
301.  P2A bridge
31
32## Primer
33
34Please read the IPMI BLOB protocol design as primer
35[here](https://github.com/openbmc/phosphor-ipmi-blobs/blob/master/README.md).
36
37## Requirements
38
39The following statements are reflective of the initial requirements.
40
41*   Any update mechanism must provide support for UBI tarballs and legacy
42    (static layout) flash images. Leveraging the BLOB protocol allows a system
43    to provide support for any image type simply by implementing a mechanism for
44    handling it.
45
46*   Any update mechanism must allow for triggering an image verification step
47    before the image is used.
48
49*   Any update mechanism must allow implementing the data staging via different
50    in-band mechanisms.
51
52*   Any update mechanism must provide a handshake or equivalent protocol for
53    coordinating the data transfer. For instance, whether the BMC should enable
54    the P2A bridge and what region to use or whether to turn on the LPC memory
55    map bridge.
56
57*   Any update mechanism must attempt to maintain security, insomuch as not
58    leaving a memory region open by default. For example, before starting the
59    verification step, access to the staged firmware image must not be still
60    accessible from the host.
61
62## Proposed Design
63
64OpenBMC supports a BLOB protocol that provides primitives. These primitives
65allow a variety of different "handlers" to exist that implement those primitives
66for specific "blobs." A blob in this context is a file path that is strictly
67unique.
68
69Sending the firmware image over the BLOB protocol will be done via routing the
70[phosphor-ipmi-flash design](https://github.com/openbmc/phosphor-ipmi-flash/blob/master/README.md)
71through a BLOB handler. This is meant to supplant `phosphor-ipmi-flash`'s
72current approach to centralize on one flexible handler.
73
74### Sequencing Control
75
76To enforce sequencing control, the design requires that only one blob be open at
77a time. If the verification blob is open, the other blobs cannot be opened, and
78likewise if a client has a data blob open, the verification blob cannot be
79opened.
80
81### Defining Blobs
82
83The BLOB protocol allows a handler to specify a list of blob ids. This list will
84be leveraged to specify whether the platform supports either the legacy (static
85layout) or the UBI mechanism, or both. The flags provided to the open command
86identify the mechanism selected by the client-side. The stat command will return
87the list of supported mechanisms for the blob.
88
89The blob ids for the mechanisms will be as follows:
90
91Flash Blob Id    | Type
92---------------- | -------------
93`/flash/image`   | Static Layout
94`/flash/tarball` | UBI
95`/flash/bios`    | Host BIOS image
96
97The flash handler will determine what commands it should expect to receive and
98responses it will return given the blob opened, based on the flags provided to
99open.
100
101The flash handler will only allow one of the above blobs to be opened for a
102sequence of commands, such that you cannot open `/flash/image` and then open
103`/flash/bios` without completing (or later aborting) the first update process
104started.
105
106The following blob ids are defined for storing the hash for the image:
107
108Hash Blob     | Id Mechanism
109------------- | --------------------
110`/flash/hash` | Whichever flash blob was opened
111
112The flash handler will only allow one open file at a time, such that if the host
113attempts to send a firmware image down over IPMI BlockTransfer, it won't allow
114the host to start a PCI send until the BlockTransfer file is closed.
115
116There is only one hash "file" mechanism. The exact hash used will only be
117important to your verification service. The value provided will be written to a
118known place.
119
120When a transfer is active, it'll create a blob_id of `/flash/active/image` and
121`/flash/active/hash`.
122
123#### Verification Blob
124
125The following blob id is defined once the image or hash upload has started. Its
126purpose is to trigger and monitor the firmware verification process. Therefore,
127the BmcBlobOpen command will fail until both the hash and image file are closed.
128Further on the ideal command sequence below.
129
130Trigger Blob    | Note
131--------------- | ------------------------
132`/flash/verify` | Verify Trigger Mechanism
133
134When the verification file is closed, if verification was completed
135successfully, it'll add an update blob id, defined below.
136
137The verification process used is not defined by this design.
138
139#### Update Blob
140
141The update blob id is available once `/flash/verify` is closed with a valid image
142or tarball. The update blob needs to be opened and commit() called on that blob
143id to trigger the update mechanism.
144
145The update process can be checked periodically by calling stat() on the update
146blob id.
147
148Update Blob     | Note
149--------------- | ------------------------
150`/flash/update` | Trigger Update Mechanism
151
152The update process used is not defined by this design.
153
154#### Cleanup Blob
155
156The cleanup blob id is always present.  The goal of this blob is to handle
157deletion of update artifacts on failure, or success.  It can be implemented to
158do any manner of cleanup required, but for systems under memory pressure, it is
159a convenient cleanup mechanism.
160
161The cleanup blob has no state or knowledge and is meant to provide a simple
162system cleanup mechanism.  This could also be accomplished by warm rebooting
163the BMC.  The cleanup blob will delete a list of files.  The cleanup blob has
164no state recognition for the update process, and therefore can interfere with
165an update process.  The host tool will only use it on failure cases.  Any other
166tool developed should respect this and not employ it unless the goal is to
167cleanup artifacts.
168
169To trigger the cleanup, simply open the blob, commit, and close.  It has no
170knowledge of the update process.  This simplification is done through the
171design of a convenience mechanism instead of a required mechanism.
172
173Cleanup Blob     | Note
174---------------- | -------------------------
175`/flash/cleanup` | Trigger Cleanup Mechanism
176
177### Caching Images
178
179Similarly to the OEM IPMI Flash protocol, the flash image will be staged in a
180compile-time configured location.
181
182Other mechanisms can readily be added by adding more blob ids or flags to the
183handler.
184
185### Commands
186
187The update mechanism will expect a specific sequence of commands depending on
188the transport mechanism selected. Some mechanisms require a handshake.
189
190#### BlockTransfer Sequence
191
1921.  Open (for Image or tarball)
1931.  Write
1941.  Close
1951.  Open (`/flash/hash`)
1961.  Write
1971.  Close
1981.  Open (`/flash/verify`)
1991.  Commit
2001.  SessionStat (to read back verification status)
2011.  Close
2021.  Open (`/flash/update`)
2031.  Commit
2041.  SessionStat (to read back update status)
2051.  Close
206
207#### P2A Sequence
208
2091.  Open (for Image or tarball)
2101.  SessionStat (P2A Region for P2A mapping)
2111.  Write
2121.  Close
2131.  Open (`/flash/hash`)
2141.  SessionStat (P2A Region)
2151.  Write
2161.  Close
2171.  Open (`/flash/verify`)
2181.  Commit
2191.  SessionStat (to read back verification status)
2201.  Close
2211.  Open (`/flash/update`)
2221.  Commit
2231.  SessionStat (to read back update status)
2241.  Close
225
226#### LPC Sequence
227
2281.  Open (for image or tarball)
2291.  WriteMeta (specify region information from host for LPC)
2301.  SessionStat (verify the contents from the above)
2311.  Write
2321.  Close
2331.  Open (`/flash/hash`)
2341.  WriteMeta (LPC Region)
2351.  SessionStat (verify LPC config)
2361.  Write
2371.  Close
2381.  Open (`/flash/verify`)
2391.  Commit
2401.  SessionStat (to read back verification status)
2411.  Close
2421.  Open (`/flash/update`)
2431.  Commit
2441.  SessionStat (to read back update status)
2451.  Close
246
247### Stale Images
248
249If an image update process is started but goes stale there are multiple
250mechanisms in place to ensure cleanup. If a session is left open after the blob
251timeout period it'll be closed. Because expiration is not the same action as
252closing, the cache will be flushed and any staged pieces deleted.
253
254The image itself, in legacy (static layout) mode will be placed and named in
255such a way that it will disappear if the BMC reboots. In the UBI case, the file
256will be stored in `/tmp` and deleted accordingly.
257
258At any point during the upload process, one can abort by closing the open blobs
259and deleting them by name.
260
261### Blob Primitives
262
263The update mechanism will implement the Blob primitives as follows.
264
265#### BmcBlobOpen
266
267The blob open primitive allows supplying blob specific flags. These flags are
268used for specifying the transport mechanism. To obtain the list of supported
269mechanisms on a platform, see the `Stat` command below.
270
271```
272enum OpenFlags
273{
274    read = (1 << 0),
275    write = (1 << 1),
276};
277
278/* These bits start in the blob specific range of the flags. */
279enum FirmwareUpdateFlags
280{
281    bt = (1 << 8),   /* Expect to send contents over IPMI BlockTransfer. */
282    p2a = (1 << 9),  /* Expect to send contents over P2A bridge. */
283    lpc = (1 << 10), /* Expect to send contents over LPC bridge. */
284};
285```
286
287An open request must specify that it is opening for writing and one transport
288mechanism, otherwise it is rejected. If the request is also set for reading,
289this is not rejected but currently provides no additional value.
290
291Once opened a new file will appear in the blob_id list (for both the image and
292hash) indicating they are in progress. The name will be `flash/active/image` and
293`flash/active/hash` which has no meaning beyond representing the current update
294in progress. Closing the file does not delete the staged images. Only delete
295will.
296
297***Note*** The active image blob_ids cannot be opened. This can be reconsidered
298later.
299
300#### BmcBlobRead
301
302This will initially not perform any function and will return success with 0
303bytes.
304
305#### BmcBlobWrite
306
307The write command's contents will depend on the transport mechanism. This
308command must not return until it has copied the data out of the mapped region
309into either a staging buffer or written down to a staging file. How the command
310reads from the mapped region is beyond the scope of this design.
311
312##### If BT
313
314The data section of the payload is only data.
315
316##### If P2A
317
318The data section of the payload is the following structure:
319
320```
321struct ExtChunkHdr
322{
323    uint32_t length; /* Length of the data queued (little endian). */
324};
325```
326
327##### If LPC
328
329The data section of the payload is the following structure:
330
331```
332struct ExtChunkHdr
333{
334    uint32_t length; /* Length of the data queued (little endian). */
335};
336```
337
338#### BmcBlobCommit
339
340If this command is called on the session of the firmware image itself, nothing
341will happen at present. It will return a no-op success.
342
343If this command is called on the session for the hash image, nothing will happen
344at present. It will return a no-op success.
345
346If this command is called on the session for the verify blob id, it'll trigger a
347systemd service `verify_image.service` to attempt to verify the image. Before
348doing this, if the transport mechanism is not IPMI BT, it'll shut down the
349mechanism used for transport preventing the host from updating anything.
350
351When this is started, only the BmcBlobSessionStat command will respond. Details
352on that response are below under BmcBlobSessionStat.
353
354#### BmcBlobClose
355
356Close must be called on the firmware image and the hash file before opening the
357verify blob.
358
359If the `verify_image.service` returned success, closing the verify file will
360have a specific behavior depending on the update. If it's UBI, it'll perform the
361install. If it's legacy (static layout), it'll do nothing. The verify_image
362service in the legacy case is responsible for placing the file in the correct
363staging position. A BMC warm reset command will initiate the firmware update
364process.
365
366If the image verification fails, it will automatically delete any files
367associated with the update.
368
369***Note:*** During development testing, a developer will want to upload files
370that are not signed. Therefore, an additional bit will be added to the flags to
371change this behavior.
372
373#### BmcBlobDelete
374
375Aborts any update that's in progress:
376
3771.  Stops the verify_image.service if started.
3781.  Deletes any staged files.
379
380In the event the update is already in progress, such as the tarball mechanism is
381used and in the middle of updating the files, it cannot be aborted.
382
383#### BmcBlobStat
384
385Blob stat on a blob_id (not SessionStat) will return the capabilities of the
386blob_id handler.
387
388```
389struct BmcBlobStatRx {
390    uint16_t crc16;
391    /* This will have the bits set from the FirmwareUpdateFlags enum. */
392    uint16_t blob_state;
393    uint32_t size; /* 0 - it's set to zero when there's no session */
394    uint8_t  metadata_len; /* 0 */
395};
396```
397
398#### BmcBlobSessionStat
399
400If called pre-commit, it'll return the following information:
401
402```
403struct BmcBlobStatRx {
404    uint16_t crc16;
405    uint16_t blob_state; /* OpenFlags::write | (one of the interfaces) */
406    uint32_t size; /* Size in bytes so far written */
407    uint8_t  metadata_len; /* 0. */
408};
409```
410
411If it's called and the data transport mechanism is P2A, it'll return a 32-bit
412address for use to configure the P2A region as part of the metadata portion of
413the `BmcBlobStatRx`.
414
415```
416struct BmcBlobStatRx {
417    uint16_t crc16;
418    uint16_t blob_state; /* OpenFlags::write | (one of the interfaces) */
419    uint32_t size; /* Size in bytes so far written */
420    uint8_t  metadata_len = sizeof(struct P2ARegion);
421    struct P2ARegion {
422        uint32_t address;
423    };
424};
425```
426
427If called post-commit on the verify file session, it'll return:
428
429```
430struct BmcBlobStatRx {
431    uint16_t crc16;
432    uint16_t blob_state; /* OPEN_W | (one of the interfaces) */
433    uint32_t size; /* Size in bytes so far written */
434    uint8_t  metadata_len; /* 1. */
435    uint8_t  verify_response; /* one byte from the below enum */
436};
437
438enum VerifyCheckResponses
439{
440    VerifyRunning = 0x00,
441    VerifySuccess = 0x01,
442    VerifyFailed  = 0x02,
443    VerifyOther   = 0x03,
444};
445```
446
447If called post-commit on the update file session, it'll return:
448
449```
450struct BmcBlobStatRx {
451    uint16_t crc16;
452    uint16_t blob_state; /* OPEN_W | (one of the interfaces) */
453    uint32_t size; /* Size in bytes so far written */
454    uint8_t  metadata_len; /* 1. */
455    uint8_t  update_response; /* one by from the below enum */
456};
457
458enum UpdateStatus
459{
460    UpdateRunning = 0x00,
461    UpdateSuccessful = 0x01,
462    UpdateFailed = 0x02,
463    UpdateStatusUnknown = 0x03
464};
465```
466
467The `UpdateStatus` and `VerifyCheckResponses` are currently identical, but this
468may change over time.
469
470#### BmcBlobWriteMeta
471
472The write metadata command is meant to allow the host to provide specific
473configuration data to the BMC for the in-band update. Currently that is only
474aimed at LPC which needs to be told the memory address so it can configure the
475window.
476
477The write meta command's blob will be this structure:
478
479```
480struct LpcRegion
481{
482    uint32_t address; /* Host LPC address where the chunk is to be mapped. */
483    uint32_t length; /* Size of the chunk to be mapped. */
484};
485```
486
487## Alternatives Considered
488
489There is currently another implementation in-use by Google that leverages the
490same mechanisms, however, it's not as flexible because every command is a custom
491piece. Mapping it into blobs primitives allows for easier future modification
492while maintaining backwards compatibility (without simply adding a separate OEM
493library to handle a new process, etc).
494
495## Impacts
496
497This impacts security because it can leverage the memory mapped windows. There
498is not an expected performance impact, as the blob handler existing only
499generates a couple extra entries during the blob enumerate command's response.
500
501## Testing
502
503Where possible (nearly everywhere), mockable interfaces will be used such that
504the entire process has individual unit-tests that verify flags are checked, as
505well as states and sequences.
506
507### Scenarios
508
509#### Sending an image with a bad hash
510
511A required functional test is one whereby an image is sent down to the BMC,
512however the signature is invalid for that image. The expected result is that the
513verification step will return failure and the files will be deleted from the BMC
514without user intervention.
515
516#### Sending an image with a good hash
517
518A required functional test is one whereby an image is sent down to the BMC with
519a valid signature. The expected result is that the verification step will return
520success.
521
522## Configuration
523
524See the configuration section of
525[Secure Flash Update Mechanism](https://github.com/openbmc/phosphor-ipmi-flash/blob/master/README.md)
526