blob: de6fe1f396be3dd76837d99bd022f8170f74f71f [file] [log] [blame]
Deepak Kodihalli70e8db02019-10-21 00:59:46 -05001#include "fru.hpp"
2
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05003#include "common/utils.hpp"
Deepak Kodihalli70e8db02019-10-21 00:59:46 -05004
George Liuc453e162022-12-21 17:16:23 +08005#include <libpldm/entity.h>
6#include <libpldm/utils.h>
Deepak Kodihalli70e8db02019-10-21 00:59:46 -05007#include <systemd/sd-journal.h>
8
Riya Dixit49cfb132023-03-02 04:26:53 -06009#include <phosphor-logging/lg2.hpp>
Deepak Kodihalli70e8db02019-10-21 00:59:46 -050010#include <sdbusplus/bus.hpp>
Deepak Kodihalli70e8db02019-10-21 00:59:46 -050011
George Liu5bfb0dc2021-05-01 14:28:41 +080012#include <optional>
George Liu6492f522020-06-16 10:34:05 +080013#include <set>
George Liu5bfb0dc2021-05-01 14:28:41 +080014#include <stack>
George Liu077fea22020-04-08 16:47:14 +080015
Riya Dixit49cfb132023-03-02 04:26:53 -060016PHOSPHOR_LOG2_USING;
17
Deepak Kodihalli70e8db02019-10-21 00:59:46 -050018namespace pldm
19{
Deepak Kodihalli70e8db02019-10-21 00:59:46 -050020namespace responder
21{
George Liu5bfb0dc2021-05-01 14:28:41 +080022
23constexpr auto root = "/xyz/openbmc_project/inventory/";
24
25std::optional<pldm_entity>
26 FruImpl::getEntityByObjectPath(const dbus::InterfaceMap& intfMaps)
27{
28 for (const auto& intfMap : intfMaps)
29 {
30 try
31 {
32 pldm_entity entity{};
33 entity.entity_type = parser.getEntityType(intfMap.first);
34 return entity;
35 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -050036 catch (const std::exception&)
George Liu5bfb0dc2021-05-01 14:28:41 +080037 {
38 continue;
39 }
40 }
41
42 return std::nullopt;
43}
44
45void FruImpl::updateAssociationTree(const dbus::ObjectValueTree& objects,
46 const std::string& path)
47{
48 if (path.find(root) == std::string::npos)
49 {
50 return;
51 }
52
53 std::stack<std::string> tmpObjPaths{};
54 tmpObjPaths.emplace(path);
55
56 auto obj = pldm::utils::findParent(path);
57 while ((obj + '/') != root)
58 {
59 tmpObjPaths.emplace(obj);
60 obj = pldm::utils::findParent(obj);
61 }
62
63 std::stack<std::string> tmpObj = tmpObjPaths;
64 while (!tmpObj.empty())
65 {
66 std::string s = tmpObj.top();
George Liu5bfb0dc2021-05-01 14:28:41 +080067 tmpObj.pop();
68 }
69 // Update pldm entity to assocition tree
70 std::string prePath = tmpObjPaths.top();
71 while (!tmpObjPaths.empty())
72 {
73 std::string currPath = tmpObjPaths.top();
74 tmpObjPaths.pop();
75
76 do
77 {
78 if (objToEntityNode.contains(currPath))
79 {
80 pldm_entity node =
81 pldm_entity_extract(objToEntityNode.at(currPath));
Manojkiran Eda8e715ae2021-07-04 21:46:43 +053082 if (pldm_entity_association_tree_find_with_locality(
83 entityTree, &node, false))
George Liu5bfb0dc2021-05-01 14:28:41 +080084 {
85 break;
86 }
87 }
88 else
89 {
90 if (!objects.contains(currPath))
91 {
92 break;
93 }
94
95 auto entityPtr = getEntityByObjectPath(objects.at(currPath));
96 if (!entityPtr)
97 {
98 break;
99 }
100
101 pldm_entity entity = *entityPtr;
102
103 for (auto& it : objToEntityNode)
104 {
105 pldm_entity node = pldm_entity_extract(it.second);
106 if (node.entity_type == entity.entity_type)
107 {
108 entity.entity_instance_num = node.entity_instance_num +
109 1;
110 break;
111 }
112 }
113
114 if (currPath == prePath)
115 {
Manojkiran Eda8e715ae2021-07-04 21:46:43 +0530116 auto node = pldm_entity_association_tree_add_entity(
George Liu5bfb0dc2021-05-01 14:28:41 +0800117 entityTree, &entity, 0xFFFF, nullptr,
Manojkiran Eda8e715ae2021-07-04 21:46:43 +0530118 PLDM_ENTITY_ASSOCIAION_PHYSICAL, false, true, 0xFFFF);
George Liu5bfb0dc2021-05-01 14:28:41 +0800119 objToEntityNode[currPath] = node;
120 }
121 else
122 {
123 if (objToEntityNode.contains(prePath))
124 {
Manojkiran Eda8e715ae2021-07-04 21:46:43 +0530125 auto node = pldm_entity_association_tree_add_entity(
George Liu5bfb0dc2021-05-01 14:28:41 +0800126 entityTree, &entity, 0xFFFF,
127 objToEntityNode[prePath],
Manojkiran Eda8e715ae2021-07-04 21:46:43 +0530128 PLDM_ENTITY_ASSOCIAION_PHYSICAL, false, true,
129 0xFFFF);
George Liu5bfb0dc2021-05-01 14:28:41 +0800130 objToEntityNode[currPath] = node;
131 }
132 }
133 }
134 } while (0);
135
136 prePath = currPath;
137 }
138}
139
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530140void FruImpl::buildFRUTable()
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500141{
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530142 if (isBuilt)
143 {
144 return;
145 }
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500146
Tom Josephf0076332020-02-06 10:18:50 +0530147 fru_parser::DBusLookupInfo dbusInfo;
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500148 // Read the all the inventory D-Bus objects
149 auto& bus = pldm::utils::DBusHandler::getBus();
150 dbus::ObjectValueTree objects;
151
152 try
153 {
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530154 dbusInfo = parser.inventoryLookup();
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500155 auto method = bus.new_method_call(
156 std::get<0>(dbusInfo).c_str(), std::get<1>(dbusInfo).c_str(),
157 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500158 auto reply = bus.call(method, dbusTimeout);
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500159 reply.read(objects);
160 }
161 catch (const std::exception& e)
162 {
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500163 error("Failed building FRU table due to inventory lookup: {ERROR}",
164 "ERROR", e);
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500165 return;
166 }
167
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500168 auto itemIntfsLookup = std::get<2>(dbusInfo);
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500169
170 for (const auto& object : objects)
171 {
172 const auto& interfaces = object.second;
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500173 for (const auto& interface : interfaces)
174 {
175 if (itemIntfsLookup.find(interface.first) != itemIntfsLookup.end())
176 {
Kamalkumar Patel2a103ef2024-02-14 02:58:08 -0600177 // checking fru present property is available or not.
178 if (!pldm::utils::checkForFruPresence(object.first.str))
179 {
180 continue;
181 }
182
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500183 // An exception will be thrown by getRecordInfo, if the item
184 // D-Bus interface name specified in FRU_Master.json does
185 // not have corresponding config jsons
186 try
187 {
George Liu5bfb0dc2021-05-01 14:28:41 +0800188 updateAssociationTree(objects, object.first.str);
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500189 pldm_entity entity{};
George Liu5bfb0dc2021-05-01 14:28:41 +0800190 if (objToEntityNode.contains(object.first.str))
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500191 {
George Liu5bfb0dc2021-05-01 14:28:41 +0800192 pldm_entity_node* node =
193 objToEntityNode.at(object.first.str);
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500194
George Liu5bfb0dc2021-05-01 14:28:41 +0800195 entity = pldm_entity_extract(node);
196 }
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500197
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530198 auto recordInfos = parser.getRecordInfo(interface.first);
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500199 populateRecords(interfaces, recordInfos, entity);
George Liuc4ea6a92020-07-14 15:48:44 +0800200
201 associatedEntityMap.emplace(object.first, entity);
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500202 break;
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500203 }
204 catch (const std::exception& e)
205 {
Riya Dixit797f3382023-08-22 22:27:51 -0500206 error(
Riya Dixit49cfb132023-03-02 04:26:53 -0600207 "Config JSONs missing for the item interface type, interface = {INTF}",
208 "INTF", interface.first);
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500209 break;
210 }
211 }
212 }
213 }
214
Andrew Jefferyb0ba34d2023-07-17 17:47:16 +0930215 int rc = pldm_entity_association_pdr_add_check(entityTree, pdrRepo, false,
216 TERMINUS_HANDLE);
217 if (rc < 0)
218 {
219 // pldm_entity_assocation_pdr_add() assert()ed on failure
220 error("Failed to add PLDM entity association PDR: {LIBPLDM_ERROR}",
221 "LIBPLDM_ERROR", rc);
222 throw std::runtime_error("Failed to add PLDM entity association PDR");
223 }
224
Sampa Misrac073a202021-05-08 10:56:05 -0500225 // save a copy of bmc's entity association tree
226 pldm_entity_association_tree_copy_root(entityTree, bmcEntityTree);
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500227
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530228 isBuilt = true;
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500229}
Pavithra Barithaya47180ac2020-10-28 02:12:05 -0500230std::string FruImpl::populatefwVersion()
231{
232 static constexpr auto fwFunctionalObjPath =
233 "/xyz/openbmc_project/software/functional";
234 auto& bus = pldm::utils::DBusHandler::getBus();
235 std::string currentBmcVersion;
236 try
237 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500238 auto method = bus.new_method_call(pldm::utils::mapperService,
239 fwFunctionalObjPath,
240 pldm::utils::dbusProperties, "Get");
Pavithra Barithaya47180ac2020-10-28 02:12:05 -0500241 method.append("xyz.openbmc_project.Association", "endpoints");
242 std::variant<std::vector<std::string>> paths;
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500243 auto reply = bus.call(method, dbusTimeout);
Pavithra Barithaya47180ac2020-10-28 02:12:05 -0500244 reply.read(paths);
245 auto fwRunningVersion = std::get<std::vector<std::string>>(paths)[0];
246 constexpr auto versionIntf = "xyz.openbmc_project.Software.Version";
247 auto version = pldm::utils::DBusHandler().getDbusPropertyVariant(
248 fwRunningVersion.c_str(), "Version", versionIntf);
249 currentBmcVersion = std::get<std::string>(version);
250 }
251 catch (const std::exception& e)
252 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600253 error("failed to make a d-bus call Asociation, ERROR= {ERR_EXCEP}",
254 "ERR_EXCEP", e.what());
Pavithra Barithaya47180ac2020-10-28 02:12:05 -0500255 return {};
256 }
257 return currentBmcVersion;
258}
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500259void FruImpl::populateRecords(
260 const pldm::responder::dbus::InterfaceMap& interfaces,
Deepak Kodihalli3cd61812020-03-10 06:38:45 -0500261 const fru_parser::FruRecordInfos& recordInfos, const pldm_entity& entity)
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500262{
263 // recordSetIdentifier for the FRU will be set when the first record gets
264 // added for the FRU
265 uint16_t recordSetIdentifier = 0;
266 auto numRecsCount = numRecs;
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600267 static uint32_t bmc_record_handle = 0;
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500268
Patrick Williams6da4f912023-05-10 07:50:53 -0500269 for (const auto& [recType, encType, fieldInfos] : recordInfos)
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500270 {
271 std::vector<uint8_t> tlvs;
272 uint8_t numFRUFields = 0;
Patrick Williams6da4f912023-05-10 07:50:53 -0500273 for (const auto& [intf, prop, propType, fieldTypeNum] : fieldInfos)
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500274 {
275 try
276 {
Pavithra Barithaya47180ac2020-10-28 02:12:05 -0500277 pldm::responder::dbus::Value propValue;
Manojkiran Eda2b7c1bf2021-09-09 12:26:00 +0530278
279 // Assuming that 0 container Id is assigned to the System (as
280 // that should be the top most container as per dbus hierarchy)
281 if (entity.entity_container_id == 0 && prop == "Version")
Pavithra Barithaya47180ac2020-10-28 02:12:05 -0500282 {
283 propValue = populatefwVersion();
284 }
285 else
286 {
287 propValue = interfaces.at(intf).at(prop);
288 }
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500289 if (propType == "bytearray")
290 {
291 auto byteArray = std::get<std::vector<uint8_t>>(propValue);
292 if (!byteArray.size())
293 {
294 continue;
295 }
296
297 numFRUFields++;
298 tlvs.emplace_back(fieldTypeNum);
299 tlvs.emplace_back(byteArray.size());
300 std::move(std::begin(byteArray), std::end(byteArray),
301 std::back_inserter(tlvs));
302 }
303 else if (propType == "string")
304 {
305 auto str = std::get<std::string>(propValue);
306 if (!str.size())
307 {
308 continue;
309 }
310
311 numFRUFields++;
312 tlvs.emplace_back(fieldTypeNum);
313 tlvs.emplace_back(str.size());
314 std::move(std::begin(str), std::end(str),
315 std::back_inserter(tlvs));
316 }
317 }
Kamalkumar Patel58cbcaf2023-10-06 03:48:25 -0500318 catch (const std::out_of_range&)
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500319 {
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500320 continue;
321 }
322 }
323
324 if (tlvs.size())
325 {
326 if (numRecs == numRecsCount)
327 {
328 recordSetIdentifier = nextRSI();
Pavithra Barithaya4f2538a2021-03-05 07:32:15 -0600329 bmc_record_handle = nextRecordHandle();
Andrew Jeffery2e248e82023-07-03 17:23:24 +0930330 int rc = pldm_pdr_add_fru_record_set_check(
Manojkiran Edacc5f1582021-09-29 17:03:06 +0530331 pdrRepo, TERMINUS_HANDLE, recordSetIdentifier,
332 entity.entity_type, entity.entity_instance_num,
Andrew Jeffery2e248e82023-07-03 17:23:24 +0930333 entity.entity_container_id, &bmc_record_handle);
334 if (rc)
335 {
336 // pldm_pdr_add_fru_record_set() assert()ed on failure
337 throw std::runtime_error(
338 "Failed to add PDR FRU record set");
339 }
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500340 }
341 auto curSize = table.size();
342 table.resize(curSize + recHeaderSize + tlvs.size());
343 encode_fru_record(table.data(), table.size(), &curSize,
344 recordSetIdentifier, recType, numFRUFields,
345 encType, tlvs.data(), tlvs.size());
346 numRecs++;
347 }
348 }
349}
350
Pavithra Barithaya9e6631e2024-01-22 00:46:32 -0600351std::vector<uint8_t> FruImpl::tableResize()
352{
353 std::vector<uint8_t> tempTable;
354
355 if (table.size())
356 {
357 std::copy(table.begin(), table.end(), std::back_inserter(tempTable));
358 padBytes = pldm::utils::getNumPadBytes(table.size());
359 tempTable.resize(tempTable.size() + padBytes, 0);
360 }
361 return tempTable;
362}
363
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500364void FruImpl::getFRUTable(Response& response)
365{
366 auto hdrSize = response.size();
Pavithra Barithaya9e6631e2024-01-22 00:46:32 -0600367 std::vector<uint8_t> tempTable;
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500368
Pavithra Barithaya9e6631e2024-01-22 00:46:32 -0600369 if (table.size())
370 {
371 tempTable = tableResize();
372 checksum = crc32(tempTable.data(), tempTable.size());
373 }
374 response.resize(hdrSize + tempTable.size() + sizeof(checksum), 0);
375 std::copy(tempTable.begin(), tempTable.end(), response.begin() + hdrSize);
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500376
377 // Copy the checksum to response data
Pavithra Barithaya9e6631e2024-01-22 00:46:32 -0600378 auto iter = response.begin() + hdrSize + tempTable.size();
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500379 std::copy_n(reinterpret_cast<const uint8_t*>(&checksum), sizeof(checksum),
380 iter);
381}
382
Pavithra Barithaya9e6631e2024-01-22 00:46:32 -0600383void FruImpl::getFRURecordTableMetadata()
384{
385 std::vector<uint8_t> tempTable;
386 if (table.size())
387 {
388 tempTable = tableResize();
389 checksum = crc32(tempTable.data(), tempTable.size());
390 }
391}
392
John Wang9e82ad12020-06-12 10:53:32 +0800393int FruImpl::getFRURecordByOption(std::vector<uint8_t>& fruData,
394 uint16_t /* fruTableHandle */,
395 uint16_t recordSetIdentifer,
396 uint8_t recordType, uint8_t fieldType)
397{
Manojkiran Eda31a78442021-09-12 15:18:25 +0530398 using sum = uint32_t;
399
John Wang9e82ad12020-06-12 10:53:32 +0800400 // FRU table is built lazily, build if not done.
401 buildFRUTable();
402
403 /* 7 is sizeof(checksum,4) + padBytesMax(3)
404 * We can not know size of the record table got by options in advance, but
405 * it must be less than the source table. So it's safe to use sizeof the
406 * source table + 7 as the buffer length
407 */
408 size_t recordTableSize = table.size() - padBytes + 7;
409 fruData.resize(recordTableSize, 0);
410
Andrew Jeffery663783b2023-07-03 12:58:14 +0930411 int rc = get_fru_record_by_option_check(
412 table.data(), table.size() - padBytes, fruData.data(), &recordTableSize,
413 recordSetIdentifer, recordType, fieldType);
John Wang9e82ad12020-06-12 10:53:32 +0800414
Andrew Jeffery663783b2023-07-03 12:58:14 +0930415 if (rc != PLDM_SUCCESS || recordTableSize == 0)
John Wang9e82ad12020-06-12 10:53:32 +0800416 {
417 return PLDM_FRU_DATA_STRUCTURE_TABLE_UNAVAILABLE;
418 }
419
Sridevi Ramesheefe49b2022-06-27 11:51:02 -0500420 auto pads = pldm::utils::getNumPadBytes(recordTableSize);
Manojkiran Eda31a78442021-09-12 15:18:25 +0530421 crc32(fruData.data(), recordTableSize + pads);
John Wang9e82ad12020-06-12 10:53:32 +0800422
423 auto iter = fruData.begin() + recordTableSize + pads;
424 std::copy_n(reinterpret_cast<const uint8_t*>(&checksum), sizeof(checksum),
425 iter);
426 fruData.resize(recordTableSize + pads + sizeof(sum));
427
428 return PLDM_SUCCESS;
429}
430
Pavithra Barithayaa410c652021-07-22 01:32:47 -0500431int FruImpl::setFRUTable(const std::vector<uint8_t>& fruData)
432{
433 auto record =
434 reinterpret_cast<const pldm_fru_record_data_format*>(fruData.data());
435 if (record)
436 {
437 if (oemFruHandler && record->record_type == PLDM_FRU_RECORD_TYPE_OEM)
438 {
439 auto rc = oemFruHandler->processOEMFRUTable(fruData);
440 if (!rc)
441 {
442 return PLDM_SUCCESS;
443 }
444 }
445 }
446 return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
447}
448
Deepak Kodihallie60c5822019-10-23 03:26:15 -0500449namespace fru
450{
Deepak Kodihallie60c5822019-10-23 03:26:15 -0500451Response Handler::getFRURecordTableMetadata(const pldm_msg* request,
452 size_t /*payloadLength*/)
453{
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530454 // FRU table is built lazily, build if not done.
455 buildFRUTable();
456
Deepak Kodihallie60c5822019-10-23 03:26:15 -0500457 constexpr uint8_t major = 0x01;
458 constexpr uint8_t minor = 0x00;
459 constexpr uint32_t maxSize = 0xFFFFFFFF;
460
461 Response response(sizeof(pldm_msg_hdr) +
462 PLDM_GET_FRU_RECORD_TABLE_METADATA_RESP_BYTES,
463 0);
464 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
465
Pavithra Barithaya9e6631e2024-01-22 00:46:32 -0600466 impl.getFRURecordTableMetadata();
467
Deepak Kodihallie60c5822019-10-23 03:26:15 -0500468 auto rc = encode_get_fru_record_table_metadata_resp(
469 request->hdr.instance_id, PLDM_SUCCESS, major, minor, maxSize,
470 impl.size(), impl.numRSI(), impl.numRecords(), impl.checkSum(),
471 responsePtr);
472 if (rc != PLDM_SUCCESS)
473 {
474 return ccOnlyResponse(request, rc);
475 }
476
477 return response;
478}
479
480Response Handler::getFRURecordTable(const pldm_msg* request,
481 size_t payloadLength)
482{
Tom Joseph33e9c7e2020-06-11 22:09:52 +0530483 // FRU table is built lazily, build if not done.
484 buildFRUTable();
485
Deepak Kodihallie60c5822019-10-23 03:26:15 -0500486 if (payloadLength != PLDM_GET_FRU_RECORD_TABLE_REQ_BYTES)
487 {
488 return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
489 }
490
491 Response response(
492 sizeof(pldm_msg_hdr) + PLDM_GET_FRU_RECORD_TABLE_MIN_RESP_BYTES, 0);
493 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
494
Patrick Williams6da4f912023-05-10 07:50:53 -0500495 auto rc = encode_get_fru_record_table_resp(request->hdr.instance_id,
496 PLDM_SUCCESS, 0,
497 PLDM_START_AND_END, responsePtr);
Deepak Kodihallie60c5822019-10-23 03:26:15 -0500498 if (rc != PLDM_SUCCESS)
499 {
500 return ccOnlyResponse(request, rc);
501 }
502
503 impl.getFRUTable(response);
504
505 return response;
506}
507
John Wang9e82ad12020-06-12 10:53:32 +0800508Response Handler::getFRURecordByOption(const pldm_msg* request,
509 size_t payloadLength)
510{
511 if (payloadLength != sizeof(pldm_get_fru_record_by_option_req))
512 {
513 return ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
514 }
515
516 uint32_t retDataTransferHandle{};
517 uint16_t retFruTableHandle{};
518 uint16_t retRecordSetIdentifier{};
519 uint8_t retRecordType{};
520 uint8_t retFieldType{};
521 uint8_t retTransferOpFlag{};
522
523 auto rc = decode_get_fru_record_by_option_req(
524 request, payloadLength, &retDataTransferHandle, &retFruTableHandle,
525 &retRecordSetIdentifier, &retRecordType, &retFieldType,
526 &retTransferOpFlag);
527
528 if (rc != PLDM_SUCCESS)
529 {
530 return ccOnlyResponse(request, rc);
531 }
532
533 std::vector<uint8_t> fruData;
534 rc = impl.getFRURecordByOption(fruData, retFruTableHandle,
535 retRecordSetIdentifier, retRecordType,
536 retFieldType);
537 if (rc != PLDM_SUCCESS)
538 {
539 return ccOnlyResponse(request, rc);
540 }
541
Patrick Williams6da4f912023-05-10 07:50:53 -0500542 auto respPayloadLength = PLDM_GET_FRU_RECORD_BY_OPTION_MIN_RESP_BYTES +
543 fruData.size();
John Wang9e82ad12020-06-12 10:53:32 +0800544 Response response(sizeof(pldm_msg_hdr) + respPayloadLength, 0);
545 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
546
547 rc = encode_get_fru_record_by_option_resp(
548 request->hdr.instance_id, PLDM_SUCCESS, 0, PLDM_START_AND_END,
549 fruData.data(), fruData.size(), responsePtr, respPayloadLength);
550
551 if (rc != PLDM_SUCCESS)
552 {
553 return ccOnlyResponse(request, rc);
554 }
555
556 return response;
557}
558
Pavithra Barithayaa410c652021-07-22 01:32:47 -0500559Response Handler::setFRURecordTable(const pldm_msg* request,
560 size_t payloadLength)
561{
562 uint32_t transferHandle{};
563 uint8_t transferOpFlag{};
564 struct variable_field fruData;
565
566 auto rc = decode_set_fru_record_table_req(
567 request, payloadLength, &transferHandle, &transferOpFlag, &fruData);
568
569 if (rc != PLDM_SUCCESS)
570 {
571 return ccOnlyResponse(request, rc);
572 }
573
574 Table table(fruData.ptr, fruData.ptr + fruData.length);
575 rc = impl.setFRUTable(table);
576 if (rc != PLDM_SUCCESS)
577 {
578 return ccOnlyResponse(request, rc);
579 }
580
581 Response response(sizeof(pldm_msg_hdr) +
582 PLDM_SET_FRU_RECORD_TABLE_RESP_BYTES);
583 struct pldm_msg* responsePtr = reinterpret_cast<pldm_msg*>(response.data());
584
585 rc = encode_set_fru_record_table_resp(
586 request->hdr.instance_id, PLDM_SUCCESS, 0 /* nextDataTransferHandle */,
587 response.size() - sizeof(pldm_msg_hdr), responsePtr);
588
589 if (rc != PLDM_SUCCESS)
590 {
591 return ccOnlyResponse(request, rc);
592 }
593
594 return response;
595}
596
Deepak Kodihallie60c5822019-10-23 03:26:15 -0500597} // namespace fru
598
Deepak Kodihalli70e8db02019-10-21 00:59:46 -0500599} // namespace responder
600
601} // namespace pldm