blob: a8ddb46288be65505ed93fd2bb4687e7b2dc1542 [file] [log] [blame]
Tom Joseph75356c12021-06-20 03:52:40 -07001#include "inventory_manager.hpp"
2
Tom Joseph75356c12021-06-20 03:52:40 -07003#include "common/utils.hpp"
4#include "xyz/openbmc_project/Software/Version/server.hpp"
5
George Liuc453e162022-12-21 17:16:23 +08006#include <libpldm/firmware_update.h>
7
Tom Joseph75356c12021-06-20 03:52:40 -07008#include <functional>
9
10namespace pldm
11{
12
13namespace fw_update
14{
15
16void InventoryManager::discoverFDs(const std::vector<mctp_eid_t>& eids)
17{
18 for (const auto& eid : eids)
19 {
20 auto instanceId = requester.getInstanceId(eid);
21 Request requestMsg(sizeof(pldm_msg_hdr) +
22 PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES);
23 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
24 auto rc = encode_query_device_identifiers_req(
25 instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, request);
26 if (rc)
27 {
28 requester.markFree(eid, instanceId);
29 std::cerr << "encode_query_device_identifiers_req failed, EID="
30 << unsigned(eid) << ", RC=" << rc << "\n";
31 continue;
32 }
33
34 rc = handler.registerRequest(
35 eid, instanceId, PLDM_FWUP, PLDM_QUERY_DEVICE_IDENTIFIERS,
36 std::move(requestMsg),
37 std::move(std::bind_front(&InventoryManager::queryDeviceIdentifiers,
38 this)));
39 if (rc)
40 {
41 std::cerr << "Failed to send QueryDeviceIdentifiers request, EID="
42 << unsigned(eid) << ", RC=" << rc << "\n ";
43 }
44 }
45}
46
47void InventoryManager::queryDeviceIdentifiers(mctp_eid_t eid,
48 const pldm_msg* response,
49 size_t respMsgLen)
50{
51 if (response == nullptr || !respMsgLen)
52 {
53 std::cerr << "No response received for QueryDeviceIdentifiers, EID="
54 << unsigned(eid) << "\n";
55 return;
56 }
57
58 uint8_t completionCode = PLDM_SUCCESS;
59 uint32_t deviceIdentifiersLen = 0;
60 uint8_t descriptorCount = 0;
61 uint8_t* descriptorPtr = nullptr;
62
63 auto rc = decode_query_device_identifiers_resp(
64 response, respMsgLen, &completionCode, &deviceIdentifiersLen,
65 &descriptorCount, &descriptorPtr);
66 if (rc)
67 {
68 std::cerr << "Decoding QueryDeviceIdentifiers response failed, EID="
69 << unsigned(eid) << ", RC=" << rc << "\n";
70 return;
71 }
72
73 if (completionCode)
74 {
75 std::cerr << "QueryDeviceIdentifiers response failed with error "
76 "completion code, EID="
77 << unsigned(eid) << ", CC=" << unsigned(completionCode)
78 << "\n";
79 return;
80 }
81
82 Descriptors descriptors{};
83 while (descriptorCount-- && (deviceIdentifiersLen > 0))
84 {
85 uint16_t descriptorType = 0;
86 variable_field descriptorData{};
87
88 rc = decode_descriptor_type_length_value(
89 descriptorPtr, deviceIdentifiersLen, &descriptorType,
90 &descriptorData);
91 if (rc)
92 {
93 std::cerr
94 << "Decoding descriptor type, length and value failed, EID="
95 << unsigned(eid) << ", RC=" << rc << "\n ";
96 return;
97 }
98
99 if (descriptorType != PLDM_FWUP_VENDOR_DEFINED)
100 {
101 std::vector<uint8_t> descData(
102 descriptorData.ptr, descriptorData.ptr + descriptorData.length);
103 descriptors.emplace(descriptorType, std::move(descData));
104 }
105 else
106 {
107 uint8_t descriptorTitleStrType = 0;
108 variable_field descriptorTitleStr{};
109 variable_field vendorDefinedDescriptorData{};
110
111 rc = decode_vendor_defined_descriptor_value(
112 descriptorData.ptr, descriptorData.length,
113 &descriptorTitleStrType, &descriptorTitleStr,
114 &vendorDefinedDescriptorData);
115 if (rc)
116 {
117 std::cerr
118 << "Decoding Vendor-defined descriptor value failed, EID="
119 << unsigned(eid) << ", RC=" << rc << "\n ";
120 return;
121 }
122
123 auto vendorDefinedDescriptorTitleStr =
124 utils::toString(descriptorTitleStr);
125 std::vector<uint8_t> vendorDescData(
126 vendorDefinedDescriptorData.ptr,
127 vendorDefinedDescriptorData.ptr +
128 vendorDefinedDescriptorData.length);
129 descriptors.emplace(descriptorType,
130 std::make_tuple(vendorDefinedDescriptorTitleStr,
131 vendorDescData));
132 }
133 auto nextDescriptorOffset =
134 sizeof(pldm_descriptor_tlv().descriptor_type) +
135 sizeof(pldm_descriptor_tlv().descriptor_length) +
136 descriptorData.length;
137 descriptorPtr += nextDescriptorOffset;
138 deviceIdentifiersLen -= nextDescriptorOffset;
139 }
140
141 descriptorMap.emplace(eid, std::move(descriptors));
142
143 // Send GetFirmwareParameters request
144 sendGetFirmwareParametersRequest(eid);
145}
146
147void InventoryManager::sendGetFirmwareParametersRequest(mctp_eid_t eid)
148{
149 auto instanceId = requester.getInstanceId(eid);
150 Request requestMsg(sizeof(pldm_msg_hdr) +
151 PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES);
152 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
153 auto rc = encode_get_firmware_parameters_req(
154 instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, request);
155 if (rc)
156 {
157 requester.markFree(eid, instanceId);
158 std::cerr << "encode_get_firmware_parameters_req failed, EID="
159 << unsigned(eid) << ", RC=" << rc << "\n";
160 return;
161 }
162
163 rc = handler.registerRequest(
164 eid, instanceId, PLDM_FWUP, PLDM_GET_FIRMWARE_PARAMETERS,
165 std::move(requestMsg),
166 std::move(
167 std::bind_front(&InventoryManager::getFirmwareParameters, this)));
168 if (rc)
169 {
170 std::cerr << "Failed to send GetFirmwareParameters request, EID="
171 << unsigned(eid) << ", RC=" << rc << "\n ";
172 }
173}
174
175void InventoryManager::getFirmwareParameters(mctp_eid_t eid,
176 const pldm_msg* response,
177 size_t respMsgLen)
178{
179 if (response == nullptr || !respMsgLen)
180 {
181 std::cerr << "No response received for GetFirmwareParameters, EID="
182 << unsigned(eid) << "\n";
183 descriptorMap.erase(eid);
184 return;
185 }
186
187 pldm_get_firmware_parameters_resp fwParams{};
188 variable_field activeCompImageSetVerStr{};
189 variable_field pendingCompImageSetVerStr{};
190 variable_field compParamTable{};
191
192 auto rc = decode_get_firmware_parameters_resp(
193 response, respMsgLen, &fwParams, &activeCompImageSetVerStr,
194 &pendingCompImageSetVerStr, &compParamTable);
195 if (rc)
196 {
197 std::cerr << "Decoding GetFirmwareParameters response failed, EID="
198 << unsigned(eid) << ", RC=" << rc << "\n";
199 return;
200 }
201
202 if (fwParams.completion_code)
203 {
204 std::cerr << "GetFirmwareParameters response failed with error "
205 "completion code, EID="
206 << unsigned(eid)
207 << ", CC=" << unsigned(fwParams.completion_code) << "\n";
208 return;
209 }
210
211 auto compParamPtr = compParamTable.ptr;
212 auto compParamTableLen = compParamTable.length;
213 pldm_component_parameter_entry compEntry{};
214 variable_field activeCompVerStr{};
215 variable_field pendingCompVerStr{};
216
217 ComponentInfo componentInfo{};
218 while (fwParams.comp_count-- && (compParamTableLen > 0))
219 {
220 auto rc = decode_get_firmware_parameters_resp_comp_entry(
221 compParamPtr, compParamTableLen, &compEntry, &activeCompVerStr,
222 &pendingCompVerStr);
223 if (rc)
224 {
225 std::cerr << "Decoding component parameter table entry failed, EID="
226 << unsigned(eid) << ", RC=" << rc << "\n";
227 return;
228 }
229
230 auto compClassification = compEntry.comp_classification;
231 auto compIdentifier = compEntry.comp_identifier;
232 componentInfo.emplace(
233 std::make_pair(compClassification, compIdentifier),
234 compEntry.comp_classification_index);
235 compParamPtr += sizeof(pldm_component_parameter_entry) +
236 activeCompVerStr.length + pendingCompVerStr.length;
237 compParamTableLen -= sizeof(pldm_component_parameter_entry) +
238 activeCompVerStr.length + pendingCompVerStr.length;
239 }
240 componentInfoMap.emplace(eid, std::move(componentInfo));
241}
242
243} // namespace fw_update
244
245} // namespace pldm