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