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