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