1*11d810dbSLei YU# PSU firmware update 2*11d810dbSLei YU 3*11d810dbSLei YUAuthor: 4*11d810dbSLei YU Lei YU <mine260309@gmail.com> <LeiYU> 5*11d810dbSLei YU 6*11d810dbSLei YUPrimary assignee: 7*11d810dbSLei YU None 8*11d810dbSLei YU 9*11d810dbSLei YUOther contributors: 10*11d810dbSLei YU Su Xiao <suxiao@inspur.com> 11*11d810dbSLei YU Derek Howard <derekh@us.ibm.com> 12*11d810dbSLei YU 13*11d810dbSLei YUCreated: 14*11d810dbSLei YU 2019-06-03 15*11d810dbSLei YU 16*11d810dbSLei YU 17*11d810dbSLei YU## Problem Description 18*11d810dbSLei YU 19*11d810dbSLei YUThere is no support in OpenBMC to update the firmware for PSUs. 20*11d810dbSLei YU 21*11d810dbSLei YU 22*11d810dbSLei YU## Background and References 23*11d810dbSLei YU 24*11d810dbSLei YUIn OpenBMC, there is an existing interface for [software update][1]. 25*11d810dbSLei YU 26*11d810dbSLei YUThe update process consists of: 27*11d810dbSLei YU1. Uploading an image to the BMC; 28*11d810dbSLei YU2. Processing the image to check the version and purpose of the image; 29*11d810dbSLei YU3. Verifying and activating the image. 30*11d810dbSLei YU 31*11d810dbSLei YUCurrently, BMC and BIOS firmware update are supported: 32*11d810dbSLei YU* [phosphor-bmc-code-mgmt][2] implements BMC code update, and it supports all 33*11d810dbSLei YU the above 3 processes. 34*11d810dbSLei YU* [openpower-pnor-code-mgmt][3] implements BIOS code update, and it only 35*11d810dbSLei YU implements "verifying and activating" the image. It shares the function of 36*11d810dbSLei YU the above 1 & 2 processes. 37*11d810dbSLei YU* Both of the above use the same [Software DBus interface][1]. 38*11d810dbSLei YU 39*11d810dbSLei YUFor PSU firmware update, it is preferred to re-use the same function for the 40*11d810dbSLei YUabove 1 & 2. 41*11d810dbSLei YU 42*11d810dbSLei YU 43*11d810dbSLei YU## Requirements 44*11d810dbSLei YU 45*11d810dbSLei YUThe PSU firmware shall be updated in the below cases: 46*11d810dbSLei YU1. The user manually invokes the APIs to do the update; 47*11d810dbSLei YU2. After BMC code update and if there is a newer PSU image in the BMC's 48*11d810dbSLei YU filesystem, BMC shall update the PSU firmware; 49*11d810dbSLei YU3. When a PSU is replaced and the version is older than the one in BMC's 50*11d810dbSLei YU filesystem, BMC shall update the PSU firmware. 51*11d810dbSLei YU4. There are cases that a system could use different models of PSUs, and thus 52*11d810dbSLei YU different PSU firmware images need to be supported. 53*11d810dbSLei YU 54*11d810dbSLei YUFor some PSUs, it is risky to do PSU code update while the host is running to 55*11d810dbSLei YUavoid power loss. This shall be handled by PSU vendor-specific tools, but not 56*11d810dbSLei YUin the generic framework. 57*11d810dbSLei YU 58*11d810dbSLei YUNote: The "vendor-specific" referred below is the PSU vendor-specific. 59*11d810dbSLei YU 60*11d810dbSLei YUSo the below checks are optional and expected to be handled by vendor-specific 61*11d810dbSLei YUtool: 62*11d810dbSLei YU1. If the host is powered off; 63*11d810dbSLei YU2. If the redundant PSUs are all connected; 64*11d810dbSLei YU3. If the AC input and DC standby output is OK on all the PSUs; 65*11d810dbSLei YU 66*11d810dbSLei YU 67*11d810dbSLei YU## Proposed Design 68*11d810dbSLei YU 69*11d810dbSLei YUAs described in the above requirements, there are different cases where the 70*11d810dbSLei YUPSU firmware is updated: 71*11d810dbSLei YU* When the APIs are invoked; 72*11d810dbSLei YU* When a new version is updated together with BMC code update; 73*11d810dbSLei YU* When a PSU is replaced with an old version of the firmware. 74*11d810dbSLei YU 75*11d810dbSLei YU### Update by API 76*11d810dbSLei YU 77*11d810dbSLei YUThis method is usually used by users who manually update PSU firmware. 78*11d810dbSLei YU 79*11d810dbSLei YUIt will re-use the current interfaces to upload, verify, and activate the 80*11d810dbSLei YUimage. 81*11d810dbSLei YU 82*11d810dbSLei YU1. The "Version" interface needs to be extended: 83*11d810dbSLei YU * Add a new [VersionPurpose][4] for PSU; 84*11d810dbSLei YU * Re-use the existing `ExtendedVersion` as an additional string for 85*11d810dbSLei YU vendor-specific purpose, e.g. to indicate the PSU model. 86*11d810dbSLei YU2. Re-use the existing functions implemented by [phosphor-bmc-code-mgmt][2] for 87*11d810dbSLei YU uploading and processing the image. 88*11d810dbSLei YU * The PSU update image shall be a tarball that consists of a MANIFEST, 89*11d810dbSLei YU images, and signatures. 90*11d810dbSLei YU * When the PSU image is uploaded and processed, a `VersionObject` shall be 91*11d810dbSLei YU created to indicate the version and its purpose. 92*11d810dbSLei YU3. There will be a new service that implements the [Activation][5] interface to 93*11d810dbSLei YU update the PSU firmware. 94*11d810dbSLei YU * The service will be started by default when BMC starts; 95*11d810dbSLei YU * On start, the service will check the PSU's existing firmware and create 96*11d810dbSLei YU the `Version` and `Activation` interfaces. 97*11d810dbSLei YU * The service shall watch the interface added on 98*11d810dbSLei YU `/xyz/openbmc_project/Software`. 99*11d810dbSLei YU * When a new object with PSU `VersionPurpose` is added, the service will 100*11d810dbSLei YU verify the signature of the image; 101*11d810dbSLei YU * The service shall check the `ExtendedVersion` to make sure the image 102*11d810dbSLei YU matches the PSU model. 103*11d810dbSLei YU * The service will have a configuration file to describe the PSU model and 104*11d810dbSLei YU its related vendor-specific tools. 105*11d810dbSLei YU * The service will find the matched vendor-specific tool to perform the code 106*11d810dbSLei YU update. 107*11d810dbSLei YU For example, if a vendor specific tool `foo` is configured in 108*11d810dbSLei YU `psu-update@foo.service` which executes `foo psu.bin`, the service will 109*11d810dbSLei YU find the `psu-update@foo.service` and start it by systemd, which performs 110*11d810dbSLei YU the update. 111*11d810dbSLei YU * When the PSU code update is completed, an informational event log shall be 112*11d810dbSLei YU created. 113*11d810dbSLei YU * When the PSU code update is completed, the image, MANIFEST, and optionally 114*11d810dbSLei YU the signature will be saved to a pre-defined directory in read-write 115*11d810dbSLei YU filesystem for future use, in case a new PSU with old firmware is plugged. 116*11d810dbSLei YU4. The vendor-specific tool shall run all the checks it needs to be run, before 117*11d810dbSLei YU and after the PSU update, and return a status to the above service to 118*11d810dbSLei YU indicate the result. 119*11d810dbSLei YU5. When the vendor-specific tool returns errors, the PSU update will be aborted 120*11d810dbSLei YU and an error event log shall be created. 121*11d810dbSLei YU6. During the update, the service shall set the related sensors to 122*11d810dbSLei YU non-functional, and when the update is done, it shall set the related 123*11d810dbSLei YU sensors back to functional. 124*11d810dbSLei YU 125*11d810dbSLei YU### Update by new BMC image 126*11d810dbSLei YU 127*11d810dbSLei YUWhen BMC is updated and a new version of PSU firmware is included, it shall be 128*11d810dbSLei YUupdated to the PSU. 129*11d810dbSLei YUThis will be done by the same service described above. 130*11d810dbSLei YU 131*11d810dbSLei YU1. On start, the service will check the PSU image, model and version in its 132*11d810dbSLei YU filesystem, compare with the ones in PSU hardware and decide if PSU firmware 133*11d810dbSLei YU update shall be performed. 134*11d810dbSLei YU2. There could be two places containing the PSU images: 135*11d810dbSLei YU * The pre-defined directory in read-only filesystem, which is part of BMC 136*11d810dbSLei YU image. 137*11d810dbSLei YU * The other pre-defined directory in read-write filesystem, which is the 138*11d810dbSLei YU location for the saved PSU images by API update. 139*11d810dbSLei YU Both places shall be checked and a newer version will be selected to compare 140*11d810dbSLei YU with the PSU hardware. 141*11d810dbSLei YU3. If PSU update is needed, the service will find the matched vendor-specific 142*11d810dbSLei YU tool to perform the code update. 143*11d810dbSLei YU4. The following process will be the same as [Update by API]. 144*11d810dbSLei YU 145*11d810dbSLei YU### Update on replaced PSU 146*11d810dbSLei YU 147*11d810dbSLei YUWhen a PSU is replaced, and the firmware version is older than the one in BMC 148*11d810dbSLei YUfilesystem, it shall be updated. 149*11d810dbSLei YUThis will be done by the same service described above. 150*11d810dbSLei YU 151*11d810dbSLei YU1. On start, the service will subscribe to the PropertiesChanged signal to 152*11d810dbSLei YU the PSU object path to monitor the PSU presence status. 153*11d810dbSLei YU (Or maybe subscribe the InterfacesAdded/Removed signal?) 154*11d810dbSLei YU2. When a PSU's presence status is changed from false to true (or the 155*11d810dbSLei YU InterfacesAdded event occurs), the service will check the new PSU's model, 156*11d810dbSLei YU firmware version to decide if the firmware needs to be updated. 157*11d810dbSLei YU3. If yes, the service will find the matched vendor-specific tool to perform 158*11d810dbSLei YU the code update. 159*11d810dbSLei YU4. The following process will be the same as [Update by API]. 160*11d810dbSLei YU 161*11d810dbSLei YU## Alternatives Considered 162*11d810dbSLei YU 163*11d810dbSLei YU### General implementation 164*11d810dbSLei YU 165*11d810dbSLei YUThe PSU firmware update could be implemented by separated recipes that only 166*11d810dbSLei YUcall vendor-specific tools. 167*11d810dbSLei YUIt will be a bit simpler but loses the unified interface provided by OpenBMC's 168*11d810dbSLei YUexisting [software update interface][1], and thus it will become difficult to 169*11d810dbSLei YUuse a standard API to the PSU firmware update. 170*11d810dbSLei YU 171*11d810dbSLei YU### VersionPurpose 172*11d810dbSLei YUIt is possible to re-use the `VersionPurpose.Other` to represent the PSU 173*11d810dbSLei YUimage's version purpose. 174*11d810dbSLei YUBut that requires additional information about the image, otherwise, there is 175*11d810dbSLei YUno way to tell if the image is for PSU, or CPLD, or other peripherals. 176*11d810dbSLei YUA new `VersionPurpose.PSU` is more specific and makes it easier to implement 177*11d810dbSLei YUand friendly for the user. 178*11d810dbSLei YU 179*11d810dbSLei YU### Additional string 180*11d810dbSLei YUThe design proposal uses `ExtendedVersion` as the additional string for 181*11d810dbSLei YUvendor-specific purpose, e.g. to indicate the PSU model, so the implementation 182*11d810dbSLei YUcould check and compare if the image matches the PSU model. 183*11d810dbSLei YUIt is possible to make it optional or remove this additional string, then the 184*11d810dbSLei YUimplementation will not verify if the image matches the PSU. It could be OK if 185*11d810dbSLei YUwe trust the user who is uploading the correct image, especially the image 186*11d810dbSLei YUshall be signed. 187*11d810dbSLei YUBut it is always risky in case the image does not match the PSU, and cause 188*11d810dbSLei YUunintended damage if the incorrect PSU firmware is updated. 189*11d810dbSLei YU 190*11d810dbSLei YU 191*11d810dbSLei YU## Impacts 192*11d810dbSLei YU 193*11d810dbSLei YUThis design only introduces a new `VersionPurpose` enum into the dbus 194*11d810dbSLei YUinterfaces. 195*11d810dbSLei YUThe newly introduced PSU firmware update service will be a new service that 196*11d810dbSLei YUimplements existing [Activation][5] interface. 197*11d810dbSLei YUThere will be new configuration files for the service to: 198*11d810dbSLei YU* Link the vendor specific tool with PSU models. 199*11d810dbSLei YU* Get the sensors related to the PSU. 200*11d810dbSLei YU* etc. 201*11d810dbSLei YU 202*11d810dbSLei YUSo the impacts are minimal to existing systems. 203*11d810dbSLei YU 204*11d810dbSLei YU 205*11d810dbSLei YU## Testing 206*11d810dbSLei YU 207*11d810dbSLei YUIt requires the manual tests to verify the PSU code update process. 208*11d810dbSLei YU* Verify the PSU code update is done on all PSUs successfully; 209*11d810dbSLei YU* Verify the PSU code update will fail if the vendor-specific tool fails on 210*11d810dbSLei YU pre-condition check, of fails on updating PSU. 211*11d810dbSLei YU* Verify the PSU code update is performed after a new BMC image is updated 212*11d810dbSLei YU containing a new version of PSU firmware. 213*11d810dbSLei YU* Verify the PSU code update is performed after a PSU with old firmware is 214*11d810dbSLei YU plugged in. 215*11d810dbSLei YU 216*11d810dbSLei YU 217*11d810dbSLei YU[1]: https://github.com/openbmc/phosphor-dbus-interfaces/tree/master/xyz/openbmc_project/Software 218*11d810dbSLei YU[2]: https://github.com/openbmc/phosphor-bmc-code-mgmt/ 219*11d810dbSLei YU[3]: https://github.com/openbmc/openpower-pnor-code-mgmt/ 220*11d810dbSLei YU[4]: https://github.com/openbmc/phosphor-dbus-interfaces/blob/57b878d048f929643276f1bf7fdf750abc4bde8b/xyz/openbmc_project/Software/Version.interface.yaml#L14 221*11d810dbSLei YU[5]: https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml 222*11d810dbSLei YU 223