xref: /openbmc/pldm/fw-update/device_updater.hpp (revision 6fa09e9621b4e8ad3f4ed935a23f665ec9bcfed8)
1 #pragma once
2 
3 #include "common/types.hpp"
4 #include "requester/handler.hpp"
5 #include "requester/request.hpp"
6 
7 #include <sdbusplus/timer.hpp>
8 #include <sdeventplus/event.hpp>
9 #include <sdeventplus/source/event.hpp>
10 
11 #include <fstream>
12 
13 namespace pldm
14 {
15 
16 namespace fw_update
17 {
18 
19 /** @brief Type alias for component update status tracking
20  *         Maps component index to its update completion status (true indicates
21  *         successful completion, false indicates cancellation)
22  */
23 using ComponentUpdateStatusMap = std::map<size_t, bool>;
24 
25 class UpdateManager;
26 
27 /** @class DeviceUpdater
28  *
29  *  DeviceUpdater orchestrates the firmware update of the firmware device and
30  *  updates the UpdateManager about the status once it is complete.
31  */
32 class DeviceUpdater
33 {
34   public:
35     DeviceUpdater() = delete;
36     DeviceUpdater(const DeviceUpdater&) = delete;
37     DeviceUpdater(DeviceUpdater&&) = default;
38     DeviceUpdater& operator=(const DeviceUpdater&) = delete;
39     DeviceUpdater& operator=(DeviceUpdater&&) = delete;
40     ~DeviceUpdater() = default;
41 
42     /** @brief Constructor
43      *
44      *  @param[in] eid - Endpoint ID of the firmware device
45      *  @param[in] package - File stream for firmware update package
46      *  @param[in] fwDeviceIDRecord - FirmwareDeviceIDRecord in the fw update
47      *                                package that matches this firmware device
48      *  @param[in] compImageInfos - Component image information for all the
49      *                              components in the fw update package
50      *  @param[in] compInfo - Component info for the components in this FD
51      *                        derived from GetFirmwareParameters response
52      *  @param[in] maxTransferSize - Maximum size in bytes of the variable
53      *                               payload allowed to be requested by the FD
54      *  @param[in] updateManager - To update the status of fw update of the
55      *                             device
56      */
DeviceUpdater(mctp_eid_t eid,std::ifstream & package,const FirmwareDeviceIDRecord & fwDeviceIDRecord,const ComponentImageInfos & compImageInfos,const ComponentInfo & compInfo,uint32_t maxTransferSize,UpdateManager * updateManager)57     explicit DeviceUpdater(mctp_eid_t eid, std::ifstream& package,
58                            const FirmwareDeviceIDRecord& fwDeviceIDRecord,
59                            const ComponentImageInfos& compImageInfos,
60                            const ComponentInfo& compInfo,
61                            uint32_t maxTransferSize,
62                            UpdateManager* updateManager) :
63         eid(eid), package(package), fwDeviceIDRecord(fwDeviceIDRecord),
64         compImageInfos(compImageInfos), compInfo(compInfo),
65         maxTransferSize(maxTransferSize), updateManager(updateManager)
66     {}
67 
68     /** @brief Start the firmware update flow for the FD
69      *
70      *  To start the update flow RequestUpdate command is sent to the FD.
71      *
72      */
73     void startFwUpdateFlow();
74 
75     /** @brief Handler for RequestUpdate command response
76      *
77      *  The response of the RequestUpdate is processed and if the response
78      *  is success, send PassComponentTable request to FD.
79      *
80      *  @param[in] eid - Remote MCTP endpoint
81      *  @param[in] response - PLDM response message
82      *  @param[in] respMsgLen - Response message length
83      */
84     void requestUpdate(mctp_eid_t eid, const pldm_msg* response,
85                        size_t respMsgLen);
86 
87     /** @brief Handler for PassComponentTable command response
88      *
89      *  The response of the PassComponentTable is processed. If the response
90      *  indicates component can be updated, continue with either a) or b).
91      *
92      *  a. Send PassComponentTable request for the next component if
93      *     applicable
94      *  b. UpdateComponent command to request updating a specific
95      *     firmware component
96      *
97      *  If the response indicates component may be updateable, continue
98      *  based on the policy in DeviceUpdateOptionFlags.
99      *
100      *  @param[in] eid - Remote MCTP endpoint
101      *  @param[in] response - PLDM response message
102      *  @param[in] respMsgLen - Response message length
103      */
104     void passCompTable(mctp_eid_t eid, const pldm_msg* response,
105                        size_t respMsgLen);
106 
107     /** @brief Handler for UpdateComponent command response
108      *
109      *  The response of the UpdateComponent is processed and will wait for
110      *  FD to request the firmware data.
111      *
112      *  @param[in] eid - Remote MCTP endpoint
113      *  @param[in] response - PLDM response message
114      *  @param[in] respMsgLen - Response message length
115      */
116     void updateComponent(mctp_eid_t eid, const pldm_msg* response,
117                          size_t respMsgLen);
118 
119     /** @brief Handler for RequestFirmwareData request
120      *
121      *  @param[in] request - Request message
122      *  @param[in] payload_length - Request message payload length
123      *  @return Response - PLDM Response message
124      */
125     Response requestFwData(const pldm_msg* request, size_t payloadLength);
126 
127     /** @brief Handler for TransferComplete request
128      *
129      *  @param[in] request - Request message
130      *  @param[in] payload_length - Request message payload length
131      *  @return Response - PLDM Response message
132      */
133     Response transferComplete(const pldm_msg* request, size_t payloadLength);
134 
135     /** @brief Handler for VerifyComplete request
136      *
137      *  @param[in] request - Request message
138      *  @param[in] payload_length - Request message payload length
139      *  @return Response - PLDM Response message
140      */
141     Response verifyComplete(const pldm_msg* request, size_t payloadLength);
142 
143     /** @brief Handler for ApplyComplete request
144      *
145      *  @param[in] request - Request message
146      *  @param[in] payload_length - Request message payload length
147      *  @return Response - PLDM Response message
148      */
149     Response applyComplete(const pldm_msg* request, size_t payloadLength);
150 
151     /** @brief Handler for ActivateFirmware command response
152      *
153      *  The response of the ActivateFirmware is processed and will update the
154      *  UpdateManager with the completion of the firmware update.
155      *
156      *  @param[in] eid - Remote MCTP endpoint
157      *  @param[in] response - PLDM response message
158      *  @param[in] respMsgLen - Response message length
159      */
160     void activateFirmware(mctp_eid_t eid, const pldm_msg* response,
161                           size_t respMsgLen);
162     /**
163      * @brief Handler for CancelUpdateComponent command response
164      *
165      * @param[in] eid - Remote MCTP endpoint
166      * @param[in] response - PLDM Response message
167      * @param[in] respMsgLen - Response message length
168      */
169     void cancelUpdateComponent(mctp_eid_t eid, const pldm_msg* response,
170                                size_t respMsgLen);
171 
172   private:
173     /** @brief Send PassComponentTable command request
174      *
175      *  @param[in] compOffset - component offset in compImageInfos
176      */
177     void sendPassCompTableRequest(size_t offset);
178 
179     /** @brief Send UpdateComponent command request
180      *
181      *  @param[in] compOffset - component offset in compImageInfos
182      */
183     void sendUpdateComponentRequest(size_t offset);
184 
185     /** @brief Send ActivateFirmware command request */
186     void sendActivateFirmwareRequest();
187 
188     /**
189      * @brief Send cancel update component request
190      */
191     void sendCancelUpdateComponentRequest();
192 
193     /**
194      * @brief Create a timer to handle RequestFirmwareData timeout (UA_T2)
195      */
196     void createRequestFwDataTimer();
197 
198     /** @brief Endpoint ID of the firmware device */
199     mctp_eid_t eid;
200 
201     /** @brief File stream for firmware update package */
202     std::ifstream& package;
203 
204     /** @brief FirmwareDeviceIDRecord in the fw update package that matches this
205      *         firmware device
206      */
207     const FirmwareDeviceIDRecord& fwDeviceIDRecord;
208 
209     /** @brief Component image information for all the components in the fw
210      *         update package
211      */
212     const ComponentImageInfos& compImageInfos;
213 
214     /** @brief Component info for the components in this FD derived from
215      *         GetFirmwareParameters response
216      */
217     const ComponentInfo& compInfo;
218 
219     /** @brief Maximum size in bytes of the variable payload to be requested by
220      *         the FD via RequestFirmwareData command
221      */
222     uint32_t maxTransferSize;
223 
224     /** @brief To update the status of fw update of the FD */
225     UpdateManager* updateManager;
226 
227     /** @brief Component index is used to track the current component being
228      *         updated if multiple components are applicable for the FD.
229      *         It is also used to keep track of the next component in
230      *         PassComponentTable
231      */
232     size_t componentIndex = 0;
233 
234     /** @brief To send a PLDM request after the current command handling */
235     std::unique_ptr<sdeventplus::source::Defer> pldmRequest;
236 
237     /**
238      * @brief Map to hold component update status. True - success, False -
239      *        cancelled
240      */
241     ComponentUpdateStatusMap componentUpdateStatus;
242 
243     /**
244      * @brief Timeout in seconds for the UA to cancel the component update if no
245      * command is received from the FD during component image transfer stage
246      *
247      */
248     static constexpr int updateTimeoutSeconds = UPDATE_TIMEOUT_SECONDS;
249 
250     /**
251      * @brief Timer to handle RequestFirmwareData timeout(UA_T2)
252      *
253      */
254     std::unique_ptr<sdbusplus::Timer> reqFwDataTimer;
255 };
256 
257 } // namespace fw_update
258 
259 } // namespace pldm
260