1 #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 
8 namespace pldmtool
9 {
10 
11 namespace fw_update
12 {
13 
14 namespace
15 {
16 
17 using namespace pldmtool::helper;
18 
19 std::vector<std::unique_ptr<CommandInterface>> commands;
20 
21 } // namespace
22 
23 const 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 
32 const 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 
39 const 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 
45 const 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 
56 class 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 
129 void registerCommand(CLI::App& app)
130 {
131     auto fwUpdate =
132         app.add_subcommand("fw_update", "firmware update type commands");
133     fwUpdate->require_subcommand(1);
134 
135     auto getStatus = fwUpdate->add_subcommand("GetStatus", "Status of the FD");
136     commands.push_back(
137         std::make_unique<GetStatus>("fw_update", "GetStatus", getStatus));
138 }
139 
140 } // namespace fw_update
141 
142 } // namespace pldmtool