blob: b48a7f6556dc5b39b4bc9cad39c2791b4ce57dc0 [file] [log] [blame]
Tom Josepheea835a2021-10-25 19:30:32 +05301#include "pldm_fw_update_cmd.hpp"
2
3#include "libpldm/firmware_update.h"
4
5#include "common/utils.hpp"
6#include "pldm_cmd_helper.hpp"
7
8namespace pldmtool
9{
10
11namespace fw_update
12{
13
14namespace
15{
16
17using namespace pldmtool::helper;
18
19std::vector<std::unique_ptr<CommandInterface>> commands;
20
21} // namespace
22
23const std::map<uint8_t, std::string> fdStateMachine{
24 {PLDM_FD_STATE_IDLE, "IDLE"},
25 {PLDM_FD_STATE_LEARN_COMPONENTS, "LEARN COMPONENTS"},
26 {PLDM_FD_STATE_READY_XFER, "READY XFER"},
27 {PLDM_FD_STATE_DOWNLOAD, "DOWNLOAD"},
28 {PLDM_FD_STATE_VERIFY, "VERIFY"},
29 {PLDM_FD_STATE_APPLY, "APPLY"},
30 {PLDM_FD_STATE_ACTIVATE, "ACTIVATE"}};
31
32const std::map<uint8_t, const char*> fdAuxState{
33 {PLDM_FD_OPERATION_IN_PROGRESS, "Operation in progress"},
34 {PLDM_FD_OPERATION_SUCCESSFUL, "Operation successful"},
35 {PLDM_FD_OPERATION_FAILED, "Operation Failed"},
36 {PLDM_FD_IDLE_LEARN_COMPONENTS_READ_XFER,
37 "Not applicable in current state"}};
38
39const std::map<uint8_t, const char*> fdAuxStateStatus{
40 {PLDM_FD_AUX_STATE_IN_PROGRESS_OR_SUCCESS,
41 "AuxState is In Progress or Success"},
42 {PLDM_FD_TIMEOUT, "Timeout occurred while performing action"},
43 {PLDM_FD_GENERIC_ERROR, "Generic Error has occured"}};
44
45const std::map<uint8_t, const char*> fdReasonCode{
46 {PLDM_FD_INITIALIZATION, "Initialization of firmware device has occurred"},
47 {PLDM_FD_ACTIVATE_FW, "ActivateFirmware command was received"},
48 {PLDM_FD_CANCEL_UPDATE, "CancelUpdate command was received"},
49 {PLDM_FD_TIMEOUT_LEARN_COMPONENT,
50 "Timeout occurred when in LEARN COMPONENT state"},
51 {PLDM_FD_TIMEOUT_READY_XFER, "Timeout occurred when in READY XFER state"},
52 {PLDM_FD_TIMEOUT_DOWNLOAD, "Timeout occurred when in DOWNLOAD state"},
53 {PLDM_FD_TIMEOUT_VERIFY, "Timeout occurred when in VERIFY state"},
54 {PLDM_FD_TIMEOUT_APPLY, "Timeout occurred when in APPLY state"}};
55
56class GetStatus : public CommandInterface
57{
58 public:
59 ~GetStatus() = default;
60 GetStatus() = delete;
61 GetStatus(const GetStatus&) = delete;
62 GetStatus(GetStatus&&) = default;
63 GetStatus& operator=(const GetStatus&) = delete;
64 GetStatus& operator=(GetStatus&&) = default;
65
66 using CommandInterface::CommandInterface;
67
68 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
69 {
70 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
71 PLDM_GET_STATUS_REQ_BYTES);
72 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
73 auto rc = encode_get_status_req(instanceId, request,
74 PLDM_GET_STATUS_REQ_BYTES);
75 return {rc, requestMsg};
76 }
77
78 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
79 {
80 uint8_t completionCode = 0;
81 uint8_t currentState = 0;
82 uint8_t previousState = 0;
83 uint8_t auxState = 0;
84 uint8_t auxStateStatus = 0;
85 uint8_t progressPercent = 0;
86 uint8_t reasonCode = 0;
87 bitfield32_t updateOptionFlagsEnabled{0};
88
89 auto rc = decode_get_status_resp(
90 responsePtr, payloadLength, &completionCode, &currentState,
91 &previousState, &auxState, &auxStateStatus, &progressPercent,
92 &reasonCode, &updateOptionFlagsEnabled);
93 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS)
94 {
95 std::cerr << "Response Message Error: "
96 << "rc=" << rc << ",cc=" << (int)completionCode << "\n";
97 return;
98 }
99
100 ordered_json data;
101 data["CurrentState"] = fdStateMachine.at(currentState);
102 data["PreviousState"] = fdStateMachine.at(previousState);
103 data["AuxState"] = fdAuxState.at(auxState);
104 if (auxStateStatus >= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_START &&
105 auxStateStatus <= PLDM_FD_VENDOR_DEFINED_STATUS_CODE_END)
106 {
107 data["AuxStateStatus"] = auxStateStatus;
108 }
109 else
110 {
111 data["AuxStateStatus"] = fdAuxStateStatus.at(auxStateStatus);
112 }
113 data["ProgressPercent"] = progressPercent;
114 if (reasonCode >= PLDM_FD_STATUS_VENDOR_DEFINED_MIN &&
115 reasonCode <= PLDM_FD_STATUS_VENDOR_DEFINED_MAX)
116 {
117 data["ReasonCode"] = reasonCode;
118 }
119 else
120 {
121 data["ReasonCode"] = fdReasonCode.at(reasonCode);
122 }
123 data["UpdateOptionFlagsEnabled"] = updateOptionFlagsEnabled.value;
124
125 pldmtool::helper::DisplayInJson(data);
126 }
127};
128
Tom Joseph6f2a2482021-10-27 18:28:16 +0530129const std::map<uint16_t, std::string> componentClassification{
130 {PLDM_COMP_UNKNOWN, "Unknown"},
131 {PLDM_COMP_OTHER, "Other"},
132 {PLDM_COMP_DRIVER, "Driver"},
133 {PLDM_COMP_CONFIGURATION_SOFTWARE, "Configuration Software"},
134 {PLDM_COMP_APPLICATION_SOFTWARE, "Application Software"},
135 {PLDM_COMP_INSTRUMENTATION, "Instrumentation"},
136 {PLDM_COMP_FIRMWARE_OR_BIOS, "Firmware/BIOS"},
137 {PLDM_COMP_DIAGNOSTIC_SOFTWARE, "Diagnostic Software"},
138 {PLDM_COMP_OPERATING_SYSTEM, "Operating System"},
139 {PLDM_COMP_MIDDLEWARE, "Middleware"},
140 {PLDM_COMP_FIRMWARE, "Firmware"},
141 {PLDM_COMP_BIOS_OR_FCODE, "BIOS/FCode"},
142 {PLDM_COMP_SUPPORT_OR_SERVICEPACK, "Support/Service Pack"},
143 {PLDM_COMP_SOFTWARE_BUNDLE, "Software Bundle"},
144 {PLDM_COMP_DOWNSTREAM_DEVICE, "Downstream Device"}};
145
146class GetFwParams : public CommandInterface
147{
148 public:
149 ~GetFwParams() = default;
150 GetFwParams() = delete;
151 GetFwParams(const GetFwParams&) = delete;
152 GetFwParams(GetFwParams&&) = default;
153 GetFwParams& operator=(const GetFwParams&) = delete;
154 GetFwParams& operator=(GetFwParams&&) = default;
155
156 using CommandInterface::CommandInterface;
157
158 std::pair<int, std::vector<uint8_t>> createRequestMsg() override
159 {
160 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
161 PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES);
162 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
163 auto rc = encode_get_firmware_parameters_req(
164 instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, request);
165 return {rc, requestMsg};
166 }
167
168 void parseResponseMsg(pldm_msg* responsePtr, size_t payloadLength) override
169 {
170 pldm_get_firmware_parameters_resp fwParams{};
171 variable_field activeCompImageSetVersion{};
172 variable_field pendingCompImageSetVersion{};
173 variable_field compParameterTable{};
174
175 auto rc = decode_get_firmware_parameters_resp(
176 responsePtr, payloadLength, &fwParams, &activeCompImageSetVersion,
177 &pendingCompImageSetVersion, &compParameterTable);
178 if (rc != PLDM_SUCCESS || fwParams.completion_code != PLDM_SUCCESS)
179 {
180 std::cerr << "Response Message Error: "
181 << "rc=" << rc << ",cc=" << (int)fwParams.completion_code
182 << "\n";
183 return;
184 }
185
186 ordered_json capabilitiesDuringUpdate;
187 if (fwParams.capabilities_during_update.bits.bit0)
188 {
189 capabilitiesDuringUpdate
190 ["Component Update Failure Recovery Capability"] =
191 "Device will not revert to previous component image upon failure, timeout or cancellation of the transfer.";
192 }
193 else
194 {
195 capabilitiesDuringUpdate
196 ["Component Update Failure Recovery Capability"] =
197 "Device will revert to previous component image upon failure, timeout or cancellation of the transfer.";
198 }
199
200 if (fwParams.capabilities_during_update.bits.bit1)
201 {
202 capabilitiesDuringUpdate["Component Update Failure Retry Capability"] =
203 "Device will not be able to update component again unless it exits update mode and the UA sends a new Request Update command.";
204 }
205 else
206 {
207 capabilitiesDuringUpdate["Component Update Failure Retry Capability"] =
208 " Device can have component updated again without exiting update mode and restarting transfer via RequestUpdate command.";
209 }
210
211 if (fwParams.capabilities_during_update.bits.bit2)
212 {
213 capabilitiesDuringUpdate["Firmware Device Partial Updates"] =
214 "Firmware Device can support a partial update, whereby a package which contains a component image set that is a subset of all components currently residing on the FD, can be transferred.";
215 }
216 else
217 {
218 capabilitiesDuringUpdate["Firmware Device Partial Updates"] =
219 "Firmware Device cannot accept a partial update and all components present on the FD shall be updated.";
220 }
221
222 if (fwParams.capabilities_during_update.bits.bit3)
223 {
224 capabilitiesDuringUpdate
225 ["Firmware Device Host Functionality during Firmware Update"] =
226 "Device will not revert to previous component image upon failure, timeout or cancellation of the transfer";
227 }
228 else
229 {
230 capabilitiesDuringUpdate
231 ["Firmware Device Host Functionality during Firmware Update"] =
232 "Device will revert to previous component image upon failure, timeout or cancellation of the transfer";
233 }
234
235 if (fwParams.capabilities_during_update.bits.bit4)
236 {
237 capabilitiesDuringUpdate["Firmware Device Update Mode Restrictions"] =
238 "Firmware device unable to enter update mode if host OS environment is active.";
239 }
240 else
241 {
242 capabilitiesDuringUpdate
243 ["Firmware Device Update Mode Restrictions"] =
244 "No host OS environment restriction for update mode";
245 }
246
247 ordered_json data;
248 data["CapabilitiesDuringUpdate"] = capabilitiesDuringUpdate;
249 data["ComponentCount"] = static_cast<uint16_t>(fwParams.comp_count);
250 data["ActiveComponentImageSetVersionString"] =
251 pldm::utils::toString(activeCompImageSetVersion);
252 data["PendingComponentImageSetVersionString"] =
253 pldm::utils::toString(pendingCompImageSetVersion);
254
255 auto compParamPtr = compParameterTable.ptr;
256 auto compParamTableLen = compParameterTable.length;
257 pldm_component_parameter_entry compEntry{};
258 variable_field activeCompVerStr{};
259 variable_field pendingCompVerStr{};
260 ordered_json compDataEntries;
261
262 while (fwParams.comp_count-- && (compParamTableLen > 0))
263 {
264 ordered_json compData;
265 auto rc = decode_get_firmware_parameters_resp_comp_entry(
266 compParamPtr, compParamTableLen, &compEntry, &activeCompVerStr,
267 &pendingCompVerStr);
268 if (rc)
269 {
270 std::cerr
271 << "Decoding component parameter table entry failed, RC="
272 << rc << "\n";
273 return;
274 }
275
276 if (componentClassification.contains(compEntry.comp_classification))
277 {
278 compData["ComponentClassification"] =
279 componentClassification.at(compEntry.comp_classification);
280 }
281 else
282 {
283 compData["ComponentClassification"] =
284 static_cast<uint16_t>(compEntry.comp_classification);
285 }
286 compData["ComponentIdentifier"] =
287 static_cast<uint16_t>(compEntry.comp_identifier);
288 compData["ComponentClassificationIndex"] =
289 static_cast<uint8_t>(compEntry.comp_classification_index);
290 compData["ActiveComponentComparisonStamp"] =
291 static_cast<uint32_t>(compEntry.active_comp_comparison_stamp);
292
293 // ActiveComponentReleaseData
294 std::array<uint8_t, 8> noReleaseData{0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00};
296 if (std::equal(noReleaseData.begin(), noReleaseData.end(),
297 compEntry.active_comp_release_date))
298 {
299 compData["ActiveComponentReleaseDate"] = "";
300 }
301 else
302 {
303 std::string activeComponentReleaseDate(
304 reinterpret_cast<const char*>(
305 compEntry.active_comp_release_date),
306 sizeof(compEntry.active_comp_release_date));
307 compData["ActiveComponentReleaseDate"] =
308 activeComponentReleaseDate;
309 }
310
311 compData["PendingComponentComparisonStamp"] =
312 static_cast<uint32_t>(compEntry.pending_comp_comparison_stamp);
313
314 // PendingComponentReleaseData
315 if (std::equal(noReleaseData.begin(), noReleaseData.end(),
316 compEntry.pending_comp_release_date))
317 {
318 compData["PendingComponentReleaseDate"] = "";
319 }
320 else
321 {
322 std::string pendingComponentReleaseDate(
323 reinterpret_cast<const char*>(
324 compEntry.pending_comp_release_date),
325 sizeof(compEntry.pending_comp_release_date));
326 compData["PendingComponentReleaseDate"] =
327 pendingComponentReleaseDate;
328 }
329
330 // ComponentActivationMethods
331 ordered_json componentActivationMethods;
332 if (compEntry.comp_activation_methods.bits.bit0)
333 {
334 componentActivationMethods.push_back("Automatic");
335 }
336 else if (compEntry.comp_activation_methods.bits.bit1)
337 {
338 componentActivationMethods.push_back("Self-Contained");
339 }
340 else if (compEntry.comp_activation_methods.bits.bit2)
341 {
342 componentActivationMethods.push_back("Medium-specific reset");
343 }
344 else if (compEntry.comp_activation_methods.bits.bit3)
345 {
346 componentActivationMethods.push_back("System reboot");
347 }
348 else if (compEntry.comp_activation_methods.bits.bit4)
349 {
350 componentActivationMethods.push_back("DC power cycel");
351 }
352 else if (compEntry.comp_activation_methods.bits.bit5)
353 {
354 componentActivationMethods.push_back("AC power cycle");
355 }
356 compData["ComponentActivationMethods"] = componentActivationMethods;
357
358 // CapabilitiesDuringUpdate
359 ordered_json compCapabilitiesDuringUpdate;
360 if (compEntry.capabilities_during_update.bits.bit0)
361 {
362 compCapabilitiesDuringUpdate
363 ["Firmware Device apply state functionality"] =
364 "Firmware Device performs an auto-apply during transfer phase and apply step will be completed immediately.";
365 }
366 else
367 {
368 compCapabilitiesDuringUpdate
369 ["Firmware Device apply state functionality"] =
370 " Firmware Device will execute an operation during the APPLY state which will include migrating the new component image to its final non-volatile storage destination.";
371 }
372 compData["CapabilitiesDuringUpdate"] = compCapabilitiesDuringUpdate;
373
374 compData["ActiveComponentVersionString"] =
375 pldm::utils::toString(activeCompVerStr);
376 compData["PendingComponentVersionString"] =
377 pldm::utils::toString(pendingCompVerStr);
378
379 compParamPtr += sizeof(pldm_component_parameter_entry) +
380 activeCompVerStr.length + pendingCompVerStr.length;
381 compParamTableLen -= sizeof(pldm_component_parameter_entry) +
382 activeCompVerStr.length +
383 pendingCompVerStr.length;
384 compDataEntries.push_back(compData);
385 }
386 data["ComponentParameterEntries"] = compDataEntries;
387
388 pldmtool::helper::DisplayInJson(data);
389 }
390};
391
Tom Josepheea835a2021-10-25 19:30:32 +0530392void registerCommand(CLI::App& app)
393{
394 auto fwUpdate =
395 app.add_subcommand("fw_update", "firmware update type commands");
396 fwUpdate->require_subcommand(1);
397
398 auto getStatus = fwUpdate->add_subcommand("GetStatus", "Status of the FD");
399 commands.push_back(
400 std::make_unique<GetStatus>("fw_update", "GetStatus", getStatus));
Tom Joseph6f2a2482021-10-27 18:28:16 +0530401
402 auto getFwParams = fwUpdate->add_subcommand(
403 "GetFwParams", "To get the component details of the FD");
404 commands.push_back(
405 std::make_unique<GetFwParams>("fw_update", "GetFwParams", getFwParams));
Tom Josepheea835a2021-10-25 19:30:32 +0530406}
407
408} // namespace fw_update
409
410} // namespace pldmtool