1 #include "utils.hpp" 2 3 #include <libpldm/pdr.h> 4 #include <libpldm/pldm_types.h> 5 #include <linux/mctp.h> 6 7 #include <phosphor-logging/lg2.hpp> 8 #include <xyz/openbmc_project/Common/error.hpp> 9 #include <xyz/openbmc_project/Logging/Create/client.hpp> 10 #include <xyz/openbmc_project/ObjectMapper/client.hpp> 11 12 #include <algorithm> 13 #include <array> 14 #include <cctype> 15 #include <ctime> 16 #include <fstream> 17 #include <iostream> 18 #include <map> 19 #include <stdexcept> 20 #include <string> 21 #include <vector> 22 23 PHOSPHOR_LOG2_USING; 24 25 namespace pldm 26 { 27 namespace utils 28 { 29 30 using ObjectMapper = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>; 31 32 constexpr const char* MCTP_INTERFACE_CC = "au.com.codeconstruct.MCTP.Endpoint1"; 33 constexpr const char* MCTP_ENDPOINT_RECOVER_METHOD = "Recover"; 34 35 std::vector<std::vector<uint8_t>> findStateEffecterPDR( 36 uint8_t /*tid*/, uint16_t entityID, uint16_t stateSetId, 37 const pldm_pdr* repo) 38 { 39 uint8_t* outData = nullptr; 40 uint32_t size{}; 41 const pldm_pdr_record* record{}; 42 std::vector<std::vector<uint8_t>> pdrs; 43 try 44 { 45 do 46 { 47 record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_EFFECTER_PDR, 48 record, &outData, &size); 49 if (record) 50 { 51 auto pdr = new (outData) pldm_state_effecter_pdr; 52 auto compositeEffecterCount = pdr->composite_effecter_count; 53 auto possible_states_start = pdr->possible_states; 54 55 for (auto effecters = 0x00; effecters < compositeEffecterCount; 56 effecters++) 57 { 58 auto possibleStates = new (possible_states_start) 59 state_effecter_possible_states; 60 auto setId = possibleStates->state_set_id; 61 auto possibleStateSize = 62 possibleStates->possible_states_size; 63 64 if (pdr->entity_type == entityID && setId == stateSetId) 65 { 66 std::vector<uint8_t> effecter_pdr(&outData[0], 67 &outData[size]); 68 pdrs.emplace_back(std::move(effecter_pdr)); 69 break; 70 } 71 possible_states_start += possibleStateSize + sizeof(setId) + 72 sizeof(possibleStateSize); 73 } 74 } 75 76 } while (record); 77 } 78 catch (const std::exception& e) 79 { 80 error("Failed to obtain a record, error - {ERROR}", "ERROR", e); 81 } 82 83 return pdrs; 84 } 85 86 std::vector<std::vector<uint8_t>> findStateSensorPDR( 87 uint8_t /*tid*/, uint16_t entityID, uint16_t stateSetId, 88 const pldm_pdr* repo) 89 { 90 uint8_t* outData = nullptr; 91 uint32_t size{}; 92 const pldm_pdr_record* record{}; 93 std::vector<std::vector<uint8_t>> pdrs; 94 try 95 { 96 do 97 { 98 record = pldm_pdr_find_record_by_type(repo, PLDM_STATE_SENSOR_PDR, 99 record, &outData, &size); 100 if (record) 101 { 102 auto pdr = new (outData) pldm_state_sensor_pdr; 103 auto compositeSensorCount = pdr->composite_sensor_count; 104 auto possible_states_start = pdr->possible_states; 105 106 for (auto sensors = 0x00; sensors < compositeSensorCount; 107 sensors++) 108 { 109 auto possibleStates = new (possible_states_start) 110 state_sensor_possible_states; 111 auto setId = possibleStates->state_set_id; 112 auto possibleStateSize = 113 possibleStates->possible_states_size; 114 115 if (pdr->entity_type == entityID && setId == stateSetId) 116 { 117 std::vector<uint8_t> sensor_pdr(&outData[0], 118 &outData[size]); 119 pdrs.emplace_back(std::move(sensor_pdr)); 120 break; 121 } 122 possible_states_start += possibleStateSize + sizeof(setId) + 123 sizeof(possibleStateSize); 124 } 125 } 126 127 } while (record); 128 } 129 catch (const std::exception& e) 130 { 131 error( 132 "Failed to obtain a record with entity ID '{ENTITYID}', error - {ERROR}", 133 "ENTITYID", entityID, "ERROR", e); 134 } 135 136 return pdrs; 137 } 138 139 uint8_t readHostEID() 140 { 141 uint8_t eid{}; 142 std::ifstream eidFile{HOST_EID_PATH}; 143 if (!eidFile.good()) 144 { 145 error("Failed to open remote terminus EID file at path '{PATH}'", 146 "PATH", static_cast<std::string>(HOST_EID_PATH)); 147 } 148 else 149 { 150 std::string eidStr; 151 eidFile >> eidStr; 152 if (!eidStr.empty()) 153 { 154 eid = atoi(eidStr.c_str()); 155 } 156 else 157 { 158 error("Remote terminus EID file was empty"); 159 } 160 } 161 162 return eid; 163 } 164 165 bool isValidEID(eid mctpEid) 166 { 167 if (mctpEid == MCTP_ADDR_NULL || mctpEid < MCTP_START_VALID_EID || 168 mctpEid == MCTP_ADDR_ANY) 169 { 170 return false; 171 } 172 173 return true; 174 } 175 176 uint8_t getNumPadBytes(uint32_t data) 177 { 178 uint8_t pad; 179 pad = ((data % 4) ? (4 - data % 4) : 0); 180 return pad; 181 } // end getNumPadBytes 182 183 bool uintToDate(uint64_t data, uint16_t* year, uint8_t* month, uint8_t* day, 184 uint8_t* hour, uint8_t* min, uint8_t* sec) 185 { 186 constexpr uint64_t max_data = 29991231115959; 187 constexpr uint64_t min_data = 19700101000000; 188 if (data < min_data || data > max_data) 189 { 190 return false; 191 } 192 193 *year = data / 10000000000; 194 data = data % 10000000000; 195 *month = data / 100000000; 196 data = data % 100000000; 197 *day = data / 1000000; 198 data = data % 1000000; 199 *hour = data / 10000; 200 data = data % 10000; 201 *min = data / 100; 202 *sec = data % 100; 203 204 return true; 205 } 206 207 std::optional<std::vector<set_effecter_state_field>> parseEffecterData( 208 const std::vector<uint8_t>& effecterData, uint8_t effecterCount) 209 { 210 std::vector<set_effecter_state_field> stateField; 211 212 if (effecterData.size() != effecterCount * 2) 213 { 214 return std::nullopt; 215 } 216 217 for (uint8_t i = 0; i < effecterCount; ++i) 218 { 219 uint8_t set_request = effecterData[i * 2] == PLDM_REQUEST_SET 220 ? PLDM_REQUEST_SET 221 : PLDM_NO_CHANGE; 222 set_effecter_state_field filed{set_request, effecterData[i * 2 + 1]}; 223 stateField.emplace_back(std::move(filed)); 224 } 225 226 return std::make_optional(std::move(stateField)); 227 } 228 229 std::string DBusHandler::getService(const char* path, 230 const char* interface) const 231 { 232 using DbusInterfaceList = std::vector<std::string>; 233 std::map<std::string, std::vector<std::string>> mapperResponse; 234 auto& bus = DBusHandler::getBus(); 235 236 auto mapper = bus.new_method_call(ObjectMapper::default_service, 237 ObjectMapper::instance_path, 238 ObjectMapper::interface, "GetObject"); 239 240 if (interface) 241 { 242 mapper.append(path, DbusInterfaceList({interface})); 243 } 244 else 245 { 246 mapper.append(path, DbusInterfaceList({})); 247 } 248 249 auto mapperResponseMsg = bus.call(mapper, dbusTimeout); 250 mapperResponseMsg.read(mapperResponse); 251 return mapperResponse.begin()->first; 252 } 253 254 GetSubTreeResponse DBusHandler::getSubtree( 255 const std::string& searchPath, int depth, 256 const std::vector<std::string>& ifaceList) const 257 { 258 auto& bus = pldm::utils::DBusHandler::getBus(); 259 auto method = bus.new_method_call(ObjectMapper::default_service, 260 ObjectMapper::instance_path, 261 ObjectMapper::interface, "GetSubTree"); 262 method.append(searchPath, depth, ifaceList); 263 auto reply = bus.call(method, dbusTimeout); 264 GetSubTreeResponse response; 265 reply.read(response); 266 return response; 267 } 268 269 GetSubTreePathsResponse DBusHandler::getSubTreePaths( 270 const std::string& objectPath, int depth, 271 const std::vector<std::string>& ifaceList) const 272 { 273 std::vector<std::string> paths; 274 auto& bus = pldm::utils::DBusHandler::getBus(); 275 auto method = bus.new_method_call( 276 ObjectMapper::default_service, ObjectMapper::instance_path, 277 ObjectMapper::interface, "GetSubTreePaths"); 278 method.append(objectPath, depth, ifaceList); 279 auto reply = bus.call(method, dbusTimeout); 280 281 reply.read(paths); 282 return paths; 283 } 284 285 GetAncestorsResponse DBusHandler::getAncestors( 286 const std::string& path, const std::vector<std::string>& ifaceList) const 287 { 288 auto& bus = pldm::utils::DBusHandler::getBus(); 289 auto method = bus.new_method_call(ObjectMapper::default_service, 290 ObjectMapper::instance_path, 291 ObjectMapper::interface, "GetAncestors"); 292 method.append(path, ifaceList); 293 auto reply = bus.call(method, dbusTimeout); 294 GetAncestorsResponse response; 295 reply.read(response); 296 return response; 297 } 298 299 void reportError(const char* errorMsg) 300 { 301 auto& bus = pldm::utils::DBusHandler::getBus(); 302 using LoggingCreate = 303 sdbusplus::client::xyz::openbmc_project::logging::Create<>; 304 try 305 { 306 using namespace sdbusplus::xyz::openbmc_project::Logging::server; 307 auto severity = 308 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage( 309 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level:: 310 Error); 311 auto method = bus.new_method_call(LoggingCreate::default_service, 312 LoggingCreate::instance_path, 313 LoggingCreate::interface, "Create"); 314 315 std::map<std::string, std::string> addlData{}; 316 method.append(errorMsg, severity, addlData); 317 bus.call_noreply(method, dbusTimeout); 318 } 319 catch (const std::exception& e) 320 { 321 error( 322 "Failed to do dbus call for creating error log for '{ERRMSG}' at path '{PATH}' and interface '{INTERFACE}', error - {ERROR}", 323 "ERRMSG", errorMsg, "PATH", LoggingCreate::instance_path, 324 "INTERFACE", LoggingCreate::interface, "ERROR", e); 325 } 326 } 327 328 void DBusHandler::setDbusProperty(const DBusMapping& dBusMap, 329 const PropertyValue& value) const 330 { 331 auto setDbusValue = [&dBusMap, this](const auto& variant) { 332 auto& bus = getBus(); 333 auto service = 334 getService(dBusMap.objectPath.c_str(), dBusMap.interface.c_str()); 335 auto method = bus.new_method_call( 336 service.c_str(), dBusMap.objectPath.c_str(), dbusProperties, "Set"); 337 method.append(dBusMap.interface.c_str(), dBusMap.propertyName.c_str(), 338 variant); 339 bus.call_noreply(method, dbusTimeout); 340 }; 341 342 if (dBusMap.propertyType == "uint8_t") 343 { 344 std::variant<uint8_t> v = std::get<uint8_t>(value); 345 setDbusValue(v); 346 } 347 else if (dBusMap.propertyType == "bool") 348 { 349 std::variant<bool> v = std::get<bool>(value); 350 setDbusValue(v); 351 } 352 else if (dBusMap.propertyType == "int16_t") 353 { 354 std::variant<int16_t> v = std::get<int16_t>(value); 355 setDbusValue(v); 356 } 357 else if (dBusMap.propertyType == "uint16_t") 358 { 359 std::variant<uint16_t> v = std::get<uint16_t>(value); 360 setDbusValue(v); 361 } 362 else if (dBusMap.propertyType == "int32_t") 363 { 364 std::variant<int32_t> v = std::get<int32_t>(value); 365 setDbusValue(v); 366 } 367 else if (dBusMap.propertyType == "uint32_t") 368 { 369 std::variant<uint32_t> v = std::get<uint32_t>(value); 370 setDbusValue(v); 371 } 372 else if (dBusMap.propertyType == "int64_t") 373 { 374 std::variant<int64_t> v = std::get<int64_t>(value); 375 setDbusValue(v); 376 } 377 else if (dBusMap.propertyType == "uint64_t") 378 { 379 std::variant<uint64_t> v = std::get<uint64_t>(value); 380 setDbusValue(v); 381 } 382 else if (dBusMap.propertyType == "double") 383 { 384 std::variant<double> v = std::get<double>(value); 385 setDbusValue(v); 386 } 387 else if (dBusMap.propertyType == "string") 388 { 389 std::variant<std::string> v = std::get<std::string>(value); 390 setDbusValue(v); 391 } 392 else 393 { 394 error("Unsupported property type '{TYPE}'", "TYPE", 395 dBusMap.propertyType); 396 throw std::invalid_argument("UnSupported Dbus Type"); 397 } 398 } 399 400 PropertyValue DBusHandler::getDbusPropertyVariant( 401 const char* objPath, const char* dbusProp, const char* dbusInterface) const 402 { 403 auto& bus = DBusHandler::getBus(); 404 auto service = getService(objPath, dbusInterface); 405 auto method = 406 bus.new_method_call(service.c_str(), objPath, dbusProperties, "Get"); 407 method.append(dbusInterface, dbusProp); 408 return bus.call(method, dbusTimeout).unpack<PropertyValue>(); 409 } 410 411 ObjectValueTree DBusHandler::getManagedObj(const char* service, 412 const char* rootPath) 413 { 414 auto& bus = DBusHandler::getBus(); 415 auto method = bus.new_method_call(service, rootPath, 416 "org.freedesktop.DBus.ObjectManager", 417 "GetManagedObjects"); 418 return bus.call(method).unpack<ObjectValueTree>(); 419 } 420 421 PropertyMap DBusHandler::getDbusPropertiesVariant( 422 const char* serviceName, const char* objPath, 423 const char* dbusInterface) const 424 { 425 auto& bus = DBusHandler::getBus(); 426 auto method = 427 bus.new_method_call(serviceName, objPath, dbusProperties, "GetAll"); 428 method.append(dbusInterface); 429 return bus.call(method, dbusTimeout).unpack<PropertyMap>(); 430 } 431 432 PropertyValue jsonEntryToDbusVal(std::string_view type, 433 const nlohmann::json& value) 434 { 435 PropertyValue propValue{}; 436 if (type == "uint8_t") 437 { 438 propValue = static_cast<uint8_t>(value); 439 } 440 else if (type == "uint16_t") 441 { 442 propValue = static_cast<uint16_t>(value); 443 } 444 else if (type == "uint32_t") 445 { 446 propValue = static_cast<uint32_t>(value); 447 } 448 else if (type == "uint64_t") 449 { 450 propValue = static_cast<uint64_t>(value); 451 } 452 else if (type == "int16_t") 453 { 454 propValue = static_cast<int16_t>(value); 455 } 456 else if (type == "int32_t") 457 { 458 propValue = static_cast<int32_t>(value); 459 } 460 else if (type == "int64_t") 461 { 462 propValue = static_cast<int64_t>(value); 463 } 464 else if (type == "bool") 465 { 466 propValue = static_cast<bool>(value); 467 } 468 else if (type == "double") 469 { 470 propValue = static_cast<double>(value); 471 } 472 else if (type == "string") 473 { 474 propValue = static_cast<std::string>(value); 475 } 476 else 477 { 478 error("Unknown D-Bus property type '{TYPE}'", "TYPE", type); 479 } 480 481 return propValue; 482 } 483 484 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType, 485 uint16_t entityInstance, uint16_t containerId, 486 uint16_t stateSetId, bool localOrRemote) 487 { 488 uint8_t* pdrData = nullptr; 489 uint32_t pdrSize{}; 490 const pldm_pdr_record* record{}; 491 do 492 { 493 record = pldm_pdr_find_record_by_type(pdrRepo, PLDM_STATE_EFFECTER_PDR, 494 record, &pdrData, &pdrSize); 495 if (record && (localOrRemote ^ pldm_pdr_record_is_remote(record))) 496 { 497 auto pdr = new (pdrData) pldm_state_effecter_pdr; 498 auto compositeEffecterCount = pdr->composite_effecter_count; 499 auto possible_states_start = pdr->possible_states; 500 501 for (auto effecters = 0x00; effecters < compositeEffecterCount; 502 effecters++) 503 { 504 auto possibleStates = new (possible_states_start) 505 state_effecter_possible_states; 506 auto setId = possibleStates->state_set_id; 507 auto possibleStateSize = possibleStates->possible_states_size; 508 509 if (entityType == pdr->entity_type && 510 entityInstance == pdr->entity_instance && 511 containerId == pdr->container_id && stateSetId == setId) 512 { 513 return pdr->effecter_id; 514 } 515 possible_states_start += possibleStateSize + sizeof(setId) + 516 sizeof(possibleStateSize); 517 } 518 } 519 } while (record); 520 521 return PLDM_INVALID_EFFECTER_ID; 522 } 523 524 int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId, 525 uint8_t sensorOffset, uint8_t eventState, 526 uint8_t previousEventState) 527 { 528 try 529 { 530 auto& bus = DBusHandler::getBus(); 531 auto msg = bus.new_signal("/xyz/openbmc_project/pldm", 532 "xyz.openbmc_project.PLDM.Event", 533 "StateSensorEvent"); 534 msg.append(tid, sensorId, sensorOffset, eventState, previousEventState); 535 536 msg.signal_send(); 537 } 538 catch (const std::exception& e) 539 { 540 error("Failed to emit pldm event signal, error - {ERROR}", "ERROR", e); 541 return PLDM_ERROR; 542 } 543 544 return PLDM_SUCCESS; 545 } 546 547 void recoverMctpEndpoint(const std::string& endpointObjPath) 548 { 549 auto& bus = DBusHandler::getBus(); 550 try 551 { 552 std::string service = DBusHandler().getService(endpointObjPath.c_str(), 553 MCTP_INTERFACE_CC); 554 555 auto method = bus.new_method_call( 556 service.c_str(), endpointObjPath.c_str(), MCTP_INTERFACE_CC, 557 MCTP_ENDPOINT_RECOVER_METHOD); 558 bus.call_noreply(method, dbusTimeout); 559 } 560 catch (const std::exception& e) 561 { 562 error( 563 "failed to make a D-Bus call to recover MCTP Endpoint, ERROR {ERR_EXCEP}", 564 "ERR_EXCEP", e); 565 } 566 } 567 568 uint16_t findStateSensorId(const pldm_pdr* pdrRepo, uint8_t tid, 569 uint16_t entityType, uint16_t entityInstance, 570 uint16_t containerId, uint16_t stateSetId) 571 { 572 auto pdrs = findStateSensorPDR(tid, entityType, stateSetId, pdrRepo); 573 for (auto pdr : pdrs) 574 { 575 auto sensorPdr = new (pdr.data()) pldm_state_sensor_pdr; 576 auto compositeSensorCount = sensorPdr->composite_sensor_count; 577 auto possible_states_start = sensorPdr->possible_states; 578 579 for (auto sensors = 0x00; sensors < compositeSensorCount; sensors++) 580 { 581 auto possibleStates = new (possible_states_start) 582 state_sensor_possible_states; 583 auto setId = possibleStates->state_set_id; 584 auto possibleStateSize = possibleStates->possible_states_size; 585 if (entityType == sensorPdr->entity_type && 586 entityInstance == sensorPdr->entity_instance && 587 stateSetId == setId && containerId == sensorPdr->container_id) 588 { 589 return sensorPdr->sensor_id; 590 } 591 possible_states_start += 592 possibleStateSize + sizeof(setId) + sizeof(possibleStateSize); 593 } 594 } 595 return PLDM_INVALID_EFFECTER_ID; 596 } 597 598 void printBuffer(bool isTx, const std::vector<uint8_t>& buffer) 599 { 600 if (buffer.empty()) 601 { 602 return; 603 } 604 605 std::cout << (isTx ? "Tx: " : "Rx: "); 606 607 std::ranges::for_each(buffer, [](uint8_t byte) { 608 std::cout << std::format("{:02x} ", byte); 609 }); 610 611 std::cout << std::endl; 612 } 613 614 std::string toString(const struct variable_field& var) 615 { 616 if (var.ptr == nullptr || !var.length) 617 { 618 return ""; 619 } 620 621 std::string str(reinterpret_cast<const char*>(var.ptr), var.length); 622 std::replace_if( 623 str.begin(), str.end(), [](const char& c) { return !isprint(c); }, ' '); 624 return str; 625 } 626 627 std::vector<std::string> split(std::string_view srcStr, std::string_view delim, 628 std::string_view trimStr) 629 { 630 std::vector<std::string> out; 631 size_t start; 632 size_t end = 0; 633 634 while ((start = srcStr.find_first_not_of(delim, end)) != std::string::npos) 635 { 636 end = srcStr.find(delim, start); 637 std::string_view dstStr = srcStr.substr(start, end - start); 638 if (!trimStr.empty()) 639 { 640 dstStr.remove_prefix(dstStr.find_first_not_of(trimStr)); 641 dstStr.remove_suffix( 642 dstStr.size() - 1 - dstStr.find_last_not_of(trimStr)); 643 } 644 645 if (!dstStr.empty()) 646 { 647 out.push_back(std::string(dstStr)); 648 } 649 } 650 651 return out; 652 } 653 654 std::string getCurrentSystemTime() 655 { 656 const auto zonedTime{std::chrono::zoned_time{ 657 std::chrono::current_zone(), std::chrono::system_clock::now()}}; 658 return std::format("{:%F %Z %T}", zonedTime); 659 } 660 661 bool checkForFruPresence(const std::string& objPath) 662 { 663 bool isPresent = false; 664 static constexpr auto presentInterface = 665 "xyz.openbmc_project.Inventory.Item"; 666 static constexpr auto presentProperty = "Present"; 667 try 668 { 669 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( 670 objPath.c_str(), presentProperty, presentInterface); 671 isPresent = std::get<bool>(propVal); 672 } 673 catch (const sdbusplus::exception::SdBusError& e) 674 { 675 error("Failed to check for FRU presence at {PATH}, error - {ERROR}", 676 "PATH", objPath, "ERROR", e); 677 } 678 return isPresent; 679 } 680 681 bool checkIfLogicalBitSet(const uint16_t& containerId) 682 { 683 return !(containerId & 0x8000); 684 } 685 686 void setFruPresence(const std::string& fruObjPath, bool present) 687 { 688 pldm::utils::PropertyValue value{present}; 689 pldm::utils::DBusMapping dbusMapping; 690 dbusMapping.objectPath = fruObjPath; 691 dbusMapping.interface = "xyz.openbmc_project.Inventory.Item"; 692 dbusMapping.propertyName = "Present"; 693 dbusMapping.propertyType = "bool"; 694 try 695 { 696 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 697 } 698 catch (const std::exception& e) 699 { 700 error( 701 "Failed to set the present property on path '{PATH}', error - {ERROR}.", 702 "PATH", fruObjPath, "ERROR", e); 703 } 704 } 705 706 std::string_view trimNameForDbus(std::string& name) 707 { 708 std::replace(name.begin(), name.end(), ' ', '_'); 709 auto nullTerminatorPos = name.find('\0'); 710 if (nullTerminatorPos != std::string::npos) 711 { 712 name.erase(nullTerminatorPos); 713 } 714 return name; 715 } 716 717 bool dbusPropValuesToDouble(const std::string_view& type, 718 const pldm::utils::PropertyValue& value, 719 double* doubleValue) 720 { 721 if (!dbusValueNumericTypeNames.contains(type)) 722 { 723 return false; 724 } 725 726 if (!doubleValue) 727 { 728 return false; 729 } 730 731 try 732 { 733 if (type == "uint8_t") 734 { 735 *doubleValue = static_cast<double>(std::get<uint8_t>(value)); 736 } 737 else if (type == "int16_t") 738 { 739 *doubleValue = static_cast<double>(std::get<int16_t>(value)); 740 } 741 else if (type == "uint16_t") 742 { 743 *doubleValue = static_cast<double>(std::get<uint16_t>(value)); 744 } 745 else if (type == "int32_t") 746 { 747 *doubleValue = static_cast<double>(std::get<int32_t>(value)); 748 } 749 else if (type == "uint32_t") 750 { 751 *doubleValue = static_cast<double>(std::get<uint32_t>(value)); 752 } 753 else if (type == "int64_t") 754 { 755 *doubleValue = static_cast<double>(std::get<int64_t>(value)); 756 } 757 else if (type == "uint64_t") 758 { 759 *doubleValue = static_cast<double>(std::get<uint64_t>(value)); 760 } 761 else if (type == "double") 762 { 763 *doubleValue = static_cast<double>(std::get<double>(value)); 764 } 765 else 766 { 767 return false; 768 } 769 } 770 catch (const std::exception& e) 771 { 772 return false; 773 } 774 775 return true; 776 } 777 778 std::optional<std::string> fruFieldValuestring(const uint8_t* value, 779 const uint8_t& length) 780 { 781 if (!value || !length) 782 { 783 lg2::error("Fru data to string invalid data."); 784 return std::nullopt; 785 } 786 787 return std::string(reinterpret_cast<const char*>(value), length); 788 } 789 790 std::optional<uint32_t> fruFieldParserU32(const uint8_t* value, 791 const uint8_t& length) 792 { 793 if (!value || length != sizeof(uint32_t)) 794 { 795 lg2::error("Fru data to u32 invalid data."); 796 return std::nullopt; 797 } 798 799 uint32_t ret; 800 std::memcpy(&ret, value, length); 801 return ret; 802 } 803 804 } // namespace utils 805 } // namespace pldm 806