xref: /openbmc/docs/designs/psu-firmware-update.md (revision 11d810db6a7f1c374bd1f480470a70c185cf78ac)
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