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