xref: /openbmc/phosphor-ipmi-flash/README.md (revision 8b58856f)
1# Secure Flash Update Mechanism
2
3This document describes the OpenBmc software implementing the secure flash
4update mechanism.
5
6## Introduction
7
8This supports two methods of providing the image to stage. You can send the
9file over IPMI packets, which is a very slow process. A 32-MiB image can take
10~3 hours to send via this method.  This can be done in <1 minutes via the PCI
11bridge, or just a few minutes via LPC depending on the size of the mapped area.
12
13This is implemented in the Google OEM number space: **11129**.
14This is also implemented under the Firmware netfn.
15
16It is command: **127**
17
18The OpenBmc tool, not yet upstreamed, supports this approach.
19
20The image must be signed via the production or development keys, the former
21being required for production builds. The image itself and the image signature
22are separately sent to the BMC for verification. The verification package
23source is beyond the scope of this design.
24
25Basically the IPMI OEM handler receives the image in one fashion or another and
26then triggers the `verify_image` service. Then, the user polls until the result
27is reported. This is because the image verification process can exceed 10
28seconds.
29
30### Using Legacy Images
31
32The image flashing mechanism itself is the initramfs stage during reboot. It
33will check for files named "`image-*`" and flash them appropriately for each
34name to section. The IPMI command creates a file `/run/initramfs/bmc-image` and
35writes the contents there. It was found that writing it in /tmp could cause OOM
36errors moving it on low memory systems, whereas renaming a file within the same
37folder seems to only update the directory inode's contents.
38
39### Using UBI
40
41The staging file path can be controlled via software configuration.  The image
42is assumed to be the tarball contents and is written into `/tmp/{tarball_name}.gz`
43
44TODO: Flesh out the UBI approach.
45
46## Primary Implementation Approaches
47
48To determine if the bridge sequence is supported you can send the
49`FlashRequestRegion` subcommand and see if it returns success with an address.
50However, for the sake of sanity, there is also a `FlashVersion` subcommand
51that'll return the version of the protocol.
52
53### Data over IPMI Sequence
54
55If you're updating the image entirely over IPMI, then you should expect to send
56the following sequence of commands:
57
581.  `FlashStartTransfer`
591.  `FlashDataBlock` (for each piece of the image)
601.  `FlashDataFinish`
611.  `FlashStartHash`
621.  `FlashHashData` (for each piece of the hash)
631.  `FlashHashFinish`
641.  `FlashDataVerify`
651.  `FlashVerifyCheck` (repeatedly until it results with 3-5s sleeps)
66
67### Data over Bridge Sequence
68
69If you're using some region to send the image and hash, you should expect to
70send the following sequences of commands:
71
721.  `FlashStartTransfer`
731.  `FlashMapRegionLpc`(if necessary)
741.  `FlashRequestRegion`
751.  `FlashDataExtBlock` (for each piece of the image)
761.  `FlashDataFinish`
771.  `FlashStartHash`
781.  `FlashHashExtData` (for each piece of the hash)
791.  `FlashHashFinish`
801.  `FlashDataVerify`
811.  `FlashVerifyCheck` (repeatedly until it results with 3-5s sleeps)
82
83## Bridge Options
84
85### P2A
86
87The PCI-to-AHB bridge is only available on some systems, and provides a 64-KiB
88region that can be pointed anywhere in BMC memory space.
89
90It is controlled by two PCIe MMIO addresses that are based on BAR1. Further
91specifics can be found in the ASPEED data sheet. However, the way it works in
92this instance is that the BMC has configured a region of physical memory it
93plans to use as this buffer region. The BMC returns the address to host program
94so it can configure the PCIe MMIO registers properly for that address.
95
96As an example, a 64-KiB region a platform can use for this
97approach is the last 64-KiB of the VGA reserved region: `0x47ff0000`.
98
99### LPC
100
101Like the P2A mechanism, the BMC must have already allocated a memory region
102with a platform-defined size. This region is mapped to LPC space at the request
103of the host, which also specifies the LPC address and region size in the
104mapping request subcommand. The host can then read the _actual_ LPC address at
105which the BMC was able to map, checking that it's usable.
106
107### USB
108
109As future work, USB should be considered an option for staging the image to be
110copied to the BMC.
111
112## Commands
113
114The following details each subcommand with which you'll lead the body of the
115command. Unlike some designs, the responses don't necessarily include the
116corresponding sub-command, partially because this protocol is meant to be used
117by one user at a time and trying to use otherwise can have negative effects and
118is not supported.
119
120In the following, any reference to the command body starts after the 3 bytes of
121OEM header, and the 1-byte subcommand.
122
123*This will now also go after the firmware function.*
124
125### FlashStartTransfer (0)
126
127The FlashStartTransfer command expects to receive a body of:
128
129```
130struct StartTx
131{
132    uint32_t length; /* Maximum image length is 4GiB */
133};
134```
135
136However, this data is presently ignored.
137
138This command will first close out and abort any previous attempt at updating
139the flash.
140
141On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
142portion.
143
144### FlashDataBlock (1)
145
146This command expects to receive a body of:
147
148```
149struct ChunkHdr
150{
151    uint32_t offset; /* The byte sequence start, (0 based). */
152};
153```
154
155However, this data is presently ignored.
156
157Immediately following this structure are the bytes to write. The length of the
158entire packet is variable and handled at a higher level, therefore the number
159of bytes to write is the size of the command body less the sub-command (1 byte)
160and less the structure size (4 bytes).
161
162On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
163portion.
164
165### FlashDataFinish (2)
166
167This command expects the body to be empty.
168
169On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
170portion.
171
172### FlashStartHash (3)
173
174The FlashStartHash command expects to receive a body of:
175
176```
177struct StartTx
178{
179    uint32_t length; /* Maximum image length is 4GiB */
180};
181```
182
183This is used! But it's only checked to see that it's non-zero.
184
185On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
186portion.
187
188### FlashHashData (4)
189
190This command expects to receive a body of:
191
192```
193struct ChunkHdr
194{
195    uint32_t offset; /* The byte sequence start, (0 based). */
196};
197```
198
199However, this data is presently ignored.
200
201Immediately following this structure are the bytes to write. The length of the
202entire packet is variable and handled at a higher level, therefore the number
203of bytes to write is the size of the command body less the sub-command (1 byte)
204and less the structure size (4 bytes).
205
206On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
207portion.
208
209### FlashHashFinish (5)
210
211This command expects the body to be empty.
212
213On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
214portion.
215
216### FlashDataVerify (6)
217
218This command expects the body to be empty.
219
220This will start the `verify_image` systemd service.
221
222On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
223portion.
224
225### FlashAbort (7)
226
227This command expects the body to be empty.
228
229This command deletes any temporary files or flash image, hashes, etc.
230
231On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
232portion.
233
234### FlashVerifyCheck (8)
235
236This command expects the body to be empty.
237
238This command opens the verification result file and checks to see if it
239contains: "`running`", "`success`" or "`failed`". This then packs that as a 1
240byte of result of:
241
242```
243enum VerifyCheckResponses
244{
245    VerifyRunning = 0x00,
246    VerifySuccess = 0x01,
247    VerifyFailed  = 0x02,
248    VerifyOther   = 0x03,
249};
250```
251
252### FlashVersion (9)
253
254This command expects the body to be empty.
255
256Returns 16-bit version sequence (little endian), in the body, after the 3-byte
257OEM portion.
258
259### FlashRequestRegion (10)
260
261Should **_return type string "LPC" or "P2A"_** but does not yet.  We need to
262add this into another command, such as **_FlashRegionSupportedType_**
263
264returns 32-bit address (little endian) of either the BMC's memory buffer in BAR
265space (P2A bridge) or in LPC FW space (LPC bridge).
266
267### FlashDataExtBlock (11)
268
269This command expects to receive:
270
271```
272struct ExtChunkHdr
273{
274    uint32_t length; /* Length of the data queued (little endian). */
275};
276```
277
278A design limitation of this is that it expects to be able to copy and write the
279data before the IPMI command times out, which should be completely possible.
280
281On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
282portion.
283
284### FlashHashExtData (12)
285
286This command expects to receive:
287
288```
289struct ExtChunkHdr
290{
291    uint32_t length; /* Length of the data queued (little endian). */
292};
293```
294
295A design limitation of this is that it expects to be able to copy and write the
296data before the IPMI command times out, which should be completely possible.
297
298On success it will return 1 byte of `0x00`, in the body, after the 3-byte OEM
299portion.
300
301### FlashMapRegionLpc (13)
302
303This command maps a chunk (size specified by host) of the BMC memory into LPC
304space at a specified address. It expects to receive:
305
306```
307struct LpcRegion
308{
309    uint32_t address; /* Host LPC address where the chunk is to be mapped. */
310    uint32_t length; /* Size of the chunk to be mapped. */
311};
312```
313
314The command will return 1 byte in the response body with value:
315
316*   0x00 on success (1 byte)
317*   0x16 (EINVAL) if the BMC is not expecting an LPC bridge (1 byte)
318*   0x1B (EFBIG) if the length argument is larger than the BMC can map at the
319    requested address, followed by a 32-bit "length" payload representing the
320    maximal buffer size that BMC can map. (5 bytes)
321
322After a success map to LPC space, the host can use FlashRequestRegion to read
323the LPC address of the chunk mapped, which should match that requested.
324