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) 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 using namespace sdbusplus::xyz::openbmc_project::Logging::server; 461 auto severity = 462 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage( 463 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level:: 464 Error); 465 auto method = bus.new_method_call(LoggingCreate::default_service, 466 LoggingCreate::instance_path, 467 LoggingCreate::interface, "Create"); 468 469 std::map<std::string, std::string> addlData{}; 470 method.append(errorMsg, severity, addlData); 471 bus.call_noreply(method, dbusTimeout); 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, dbusTimeout); 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 return bus.call(method, dbusTimeout).unpack<PropertyValue>(); 560 } 561 562 ObjectValueTree DBusHandler::getManagedObj(const char* service, 563 const char* rootPath) 564 { 565 auto& bus = DBusHandler::getBus(); 566 auto method = bus.new_method_call(service, rootPath, 567 "org.freedesktop.DBus.ObjectManager", 568 "GetManagedObjects"); 569 return bus.call(method).unpack<ObjectValueTree>(); 570 } 571 572 PropertyMap 573 DBusHandler::getDbusPropertiesVariant(const char* serviceName, 574 const char* objPath, 575 const char* dbusInterface) const 576 { 577 auto& bus = DBusHandler::getBus(); 578 auto method = bus.new_method_call(serviceName, objPath, dbusProperties, 579 "GetAll"); 580 method.append(dbusInterface); 581 return bus.call(method, dbusTimeout).unpack<PropertyMap>(); 582 } 583 584 PropertyValue jsonEntryToDbusVal(std::string_view type, 585 const nlohmann::json& value) 586 { 587 PropertyValue propValue{}; 588 if (type == "uint8_t") 589 { 590 propValue = static_cast<uint8_t>(value); 591 } 592 else if (type == "uint16_t") 593 { 594 propValue = static_cast<uint16_t>(value); 595 } 596 else if (type == "uint32_t") 597 { 598 propValue = static_cast<uint32_t>(value); 599 } 600 else if (type == "uint64_t") 601 { 602 propValue = static_cast<uint64_t>(value); 603 } 604 else if (type == "int16_t") 605 { 606 propValue = static_cast<int16_t>(value); 607 } 608 else if (type == "int32_t") 609 { 610 propValue = static_cast<int32_t>(value); 611 } 612 else if (type == "int64_t") 613 { 614 propValue = static_cast<int64_t>(value); 615 } 616 else if (type == "bool") 617 { 618 propValue = static_cast<bool>(value); 619 } 620 else if (type == "double") 621 { 622 propValue = static_cast<double>(value); 623 } 624 else if (type == "string") 625 { 626 propValue = static_cast<std::string>(value); 627 } 628 else 629 { 630 error("Unknown D-Bus property type, TYPE={OTHER_TYPE}", "OTHER_TYPE", 631 type); 632 } 633 634 return propValue; 635 } 636 637 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType, 638 uint16_t entityInstance, uint16_t containerId, 639 uint16_t stateSetId, bool localOrRemote) 640 { 641 uint8_t* pdrData = nullptr; 642 uint32_t pdrSize{}; 643 const pldm_pdr_record* record{}; 644 do 645 { 646 record = pldm_pdr_find_record_by_type(pdrRepo, PLDM_STATE_EFFECTER_PDR, 647 record, &pdrData, &pdrSize); 648 if (record && (localOrRemote ^ pldm_pdr_record_is_remote(record))) 649 { 650 auto pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrData); 651 auto compositeEffecterCount = pdr->composite_effecter_count; 652 auto possible_states_start = pdr->possible_states; 653 654 for (auto effecters = 0x00; effecters < compositeEffecterCount; 655 effecters++) 656 { 657 auto possibleStates = 658 reinterpret_cast<state_effecter_possible_states*>( 659 possible_states_start); 660 auto setId = possibleStates->state_set_id; 661 auto possibleStateSize = possibleStates->possible_states_size; 662 663 if (entityType == pdr->entity_type && 664 entityInstance == pdr->entity_instance && 665 containerId == pdr->container_id && stateSetId == setId) 666 { 667 return pdr->effecter_id; 668 } 669 possible_states_start += possibleStateSize + sizeof(setId) + 670 sizeof(possibleStateSize); 671 } 672 } 673 } while (record); 674 675 return PLDM_INVALID_EFFECTER_ID; 676 } 677 678 int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId, 679 uint8_t sensorOffset, uint8_t eventState, 680 uint8_t previousEventState) 681 { 682 try 683 { 684 auto& bus = DBusHandler::getBus(); 685 auto msg = bus.new_signal("/xyz/openbmc_project/pldm", 686 "xyz.openbmc_project.PLDM.Event", 687 "StateSensorEvent"); 688 msg.append(tid, sensorId, sensorOffset, eventState, previousEventState); 689 690 msg.signal_send(); 691 } 692 catch (const std::exception& e) 693 { 694 error("Error emitting pldm event signal:ERROR={ERR_EXCEP}", "ERR_EXCEP", 695 e.what()); 696 return PLDM_ERROR; 697 } 698 699 return PLDM_SUCCESS; 700 } 701 702 uint16_t findStateSensorId(const pldm_pdr* pdrRepo, uint8_t tid, 703 uint16_t entityType, uint16_t entityInstance, 704 uint16_t containerId, uint16_t stateSetId) 705 { 706 auto pdrs = findStateSensorPDR(tid, entityType, stateSetId, pdrRepo); 707 for (auto pdr : pdrs) 708 { 709 auto sensorPdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdr.data()); 710 auto compositeSensorCount = sensorPdr->composite_sensor_count; 711 auto possible_states_start = sensorPdr->possible_states; 712 713 for (auto sensors = 0x00; sensors < compositeSensorCount; sensors++) 714 { 715 auto possibleStates = 716 reinterpret_cast<state_sensor_possible_states*>( 717 possible_states_start); 718 auto setId = possibleStates->state_set_id; 719 auto possibleStateSize = possibleStates->possible_states_size; 720 if (entityType == sensorPdr->entity_type && 721 entityInstance == sensorPdr->entity_instance && 722 stateSetId == setId && containerId == sensorPdr->container_id) 723 { 724 return sensorPdr->sensor_id; 725 } 726 possible_states_start += possibleStateSize + sizeof(setId) + 727 sizeof(possibleStateSize); 728 } 729 } 730 return PLDM_INVALID_EFFECTER_ID; 731 } 732 733 void printBuffer(bool isTx, const std::vector<uint8_t>& buffer) 734 { 735 if (buffer.empty()) 736 { 737 return; 738 } 739 740 std::cout << (isTx ? "Tx: " : "Rx: "); 741 742 std::ranges::for_each(buffer, [](uint8_t byte) { 743 std::cout << std::format("{:02x} ", byte); 744 }); 745 746 std::cout << std::endl; 747 } 748 749 std::string toString(const struct variable_field& var) 750 { 751 if (var.ptr == nullptr || !var.length) 752 { 753 return ""; 754 } 755 756 std::string str(reinterpret_cast<const char*>(var.ptr), var.length); 757 std::replace_if( 758 str.begin(), str.end(), [](const char& c) { return !isprint(c); }, ' '); 759 return str; 760 } 761 762 std::vector<std::string> split(std::string_view srcStr, std::string_view delim, 763 std::string_view trimStr) 764 { 765 std::vector<std::string> out; 766 size_t start; 767 size_t end = 0; 768 769 while ((start = srcStr.find_first_not_of(delim, end)) != std::string::npos) 770 { 771 end = srcStr.find(delim, start); 772 std::string_view dstStr = srcStr.substr(start, end - start); 773 if (!trimStr.empty()) 774 { 775 dstStr.remove_prefix(dstStr.find_first_not_of(trimStr)); 776 dstStr.remove_suffix(dstStr.size() - 1 - 777 dstStr.find_last_not_of(trimStr)); 778 } 779 780 if (!dstStr.empty()) 781 { 782 out.push_back(std::string(dstStr)); 783 } 784 } 785 786 return out; 787 } 788 789 std::string getCurrentSystemTime() 790 { 791 const auto zonedTime{std::chrono::zoned_time{ 792 std::chrono::current_zone(), std::chrono::system_clock::now()}}; 793 return std::format("{:%F %Z %T}", zonedTime); 794 } 795 796 bool checkForFruPresence(const std::string& objPath) 797 { 798 bool isPresent = false; 799 static constexpr auto presentInterface = 800 "xyz.openbmc_project.Inventory.Item"; 801 static constexpr auto presentProperty = "Present"; 802 try 803 { 804 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( 805 objPath.c_str(), presentProperty, presentInterface); 806 isPresent = std::get<bool>(propVal); 807 } 808 catch (const sdbusplus::exception::SdBusError& e) 809 { 810 error( 811 "Failed to check for FRU presence for {OBJ_PATH} ERROR = {ERR_EXCEP}", 812 "OBJ_PATH", objPath.c_str(), "ERR_EXCEP", e.what()); 813 } 814 return isPresent; 815 } 816 817 bool checkIfLogicalBitSet(const uint16_t& containerId) 818 { 819 return !(containerId & 0x8000); 820 } 821 822 void setFruPresence(const std::string& fruObjPath, bool present) 823 { 824 pldm::utils::PropertyValue value{present}; 825 pldm::utils::DBusMapping dbusMapping; 826 dbusMapping.objectPath = fruObjPath; 827 dbusMapping.interface = "xyz.openbmc_project.Inventory.Item"; 828 dbusMapping.propertyName = "Present"; 829 dbusMapping.propertyType = "bool"; 830 try 831 { 832 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 833 } 834 catch (const std::exception& e) 835 { 836 error( 837 "Failed to set the present property on path: '{PATH}' with {ERROR} ", 838 "PATH", fruObjPath, "ERROR", e); 839 } 840 } 841 842 } // namespace utils 843 } // namespace pldm 844