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 GetSubTreePathsResponse DBusHandler::getSubTreePaths( 452 const std::string& objectPath, int depth, 453 const std::vector<std::string>& ifaceList) const 454 { 455 std::vector<std::string> paths; 456 auto& bus = pldm::utils::DBusHandler::getBus(); 457 auto method = bus.new_method_call( 458 ObjectMapper::default_service, ObjectMapper::instance_path, 459 ObjectMapper::interface, "GetSubTreePaths"); 460 method.append(objectPath, depth, ifaceList); 461 auto reply = bus.call(method, dbusTimeout); 462 463 reply.read(paths); 464 return paths; 465 } 466 467 void reportError(const char* errorMsg) 468 { 469 auto& bus = pldm::utils::DBusHandler::getBus(); 470 471 try 472 { 473 using LoggingCreate = 474 sdbusplus::client::xyz::openbmc_project::logging::Create<>; 475 476 using namespace sdbusplus::xyz::openbmc_project::Logging::server; 477 auto severity = 478 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage( 479 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level:: 480 Error); 481 auto method = bus.new_method_call(LoggingCreate::default_service, 482 LoggingCreate::instance_path, 483 LoggingCreate::interface, "Create"); 484 485 std::map<std::string, std::string> addlData{}; 486 method.append(errorMsg, severity, addlData); 487 bus.call_noreply(method, dbusTimeout); 488 } 489 catch (const std::exception& e) 490 { 491 error( 492 "failed to make a d-bus call to create error log, ERROR={ERR_EXCEP}", 493 "ERR_EXCEP", e.what()); 494 } 495 } 496 497 void DBusHandler::setDbusProperty(const DBusMapping& dBusMap, 498 const PropertyValue& value) const 499 { 500 auto setDbusValue = [&dBusMap, this](const auto& variant) { 501 auto& bus = getBus(); 502 auto service = getService(dBusMap.objectPath.c_str(), 503 dBusMap.interface.c_str()); 504 auto method = bus.new_method_call( 505 service.c_str(), dBusMap.objectPath.c_str(), dbusProperties, "Set"); 506 method.append(dBusMap.interface.c_str(), dBusMap.propertyName.c_str(), 507 variant); 508 bus.call_noreply(method, dbusTimeout); 509 }; 510 511 if (dBusMap.propertyType == "uint8_t") 512 { 513 std::variant<uint8_t> v = std::get<uint8_t>(value); 514 setDbusValue(v); 515 } 516 else if (dBusMap.propertyType == "bool") 517 { 518 std::variant<bool> v = std::get<bool>(value); 519 setDbusValue(v); 520 } 521 else if (dBusMap.propertyType == "int16_t") 522 { 523 std::variant<int16_t> v = std::get<int16_t>(value); 524 setDbusValue(v); 525 } 526 else if (dBusMap.propertyType == "uint16_t") 527 { 528 std::variant<uint16_t> v = std::get<uint16_t>(value); 529 setDbusValue(v); 530 } 531 else if (dBusMap.propertyType == "int32_t") 532 { 533 std::variant<int32_t> v = std::get<int32_t>(value); 534 setDbusValue(v); 535 } 536 else if (dBusMap.propertyType == "uint32_t") 537 { 538 std::variant<uint32_t> v = std::get<uint32_t>(value); 539 setDbusValue(v); 540 } 541 else if (dBusMap.propertyType == "int64_t") 542 { 543 std::variant<int64_t> v = std::get<int64_t>(value); 544 setDbusValue(v); 545 } 546 else if (dBusMap.propertyType == "uint64_t") 547 { 548 std::variant<uint64_t> v = std::get<uint64_t>(value); 549 setDbusValue(v); 550 } 551 else if (dBusMap.propertyType == "double") 552 { 553 std::variant<double> v = std::get<double>(value); 554 setDbusValue(v); 555 } 556 else if (dBusMap.propertyType == "string") 557 { 558 std::variant<std::string> v = std::get<std::string>(value); 559 setDbusValue(v); 560 } 561 else 562 { 563 throw std::invalid_argument("UnSpported Dbus Type"); 564 } 565 } 566 567 PropertyValue DBusHandler::getDbusPropertyVariant( 568 const char* objPath, const char* dbusProp, const char* dbusInterface) const 569 { 570 auto& bus = DBusHandler::getBus(); 571 auto service = getService(objPath, dbusInterface); 572 auto method = bus.new_method_call(service.c_str(), objPath, dbusProperties, 573 "Get"); 574 method.append(dbusInterface, dbusProp); 575 return bus.call(method, dbusTimeout).unpack<PropertyValue>(); 576 } 577 578 ObjectValueTree DBusHandler::getManagedObj(const char* service, 579 const char* rootPath) 580 { 581 auto& bus = DBusHandler::getBus(); 582 auto method = bus.new_method_call(service, rootPath, 583 "org.freedesktop.DBus.ObjectManager", 584 "GetManagedObjects"); 585 return bus.call(method).unpack<ObjectValueTree>(); 586 } 587 588 PropertyMap 589 DBusHandler::getDbusPropertiesVariant(const char* serviceName, 590 const char* objPath, 591 const char* dbusInterface) const 592 { 593 auto& bus = DBusHandler::getBus(); 594 auto method = bus.new_method_call(serviceName, objPath, dbusProperties, 595 "GetAll"); 596 method.append(dbusInterface); 597 return bus.call(method, dbusTimeout).unpack<PropertyMap>(); 598 } 599 600 PropertyValue jsonEntryToDbusVal(std::string_view type, 601 const nlohmann::json& value) 602 { 603 PropertyValue propValue{}; 604 if (type == "uint8_t") 605 { 606 propValue = static_cast<uint8_t>(value); 607 } 608 else if (type == "uint16_t") 609 { 610 propValue = static_cast<uint16_t>(value); 611 } 612 else if (type == "uint32_t") 613 { 614 propValue = static_cast<uint32_t>(value); 615 } 616 else if (type == "uint64_t") 617 { 618 propValue = static_cast<uint64_t>(value); 619 } 620 else if (type == "int16_t") 621 { 622 propValue = static_cast<int16_t>(value); 623 } 624 else if (type == "int32_t") 625 { 626 propValue = static_cast<int32_t>(value); 627 } 628 else if (type == "int64_t") 629 { 630 propValue = static_cast<int64_t>(value); 631 } 632 else if (type == "bool") 633 { 634 propValue = static_cast<bool>(value); 635 } 636 else if (type == "double") 637 { 638 propValue = static_cast<double>(value); 639 } 640 else if (type == "string") 641 { 642 propValue = static_cast<std::string>(value); 643 } 644 else 645 { 646 error("Unknown D-Bus property type, TYPE={OTHER_TYPE}", "OTHER_TYPE", 647 type); 648 } 649 650 return propValue; 651 } 652 653 uint16_t findStateEffecterId(const pldm_pdr* pdrRepo, uint16_t entityType, 654 uint16_t entityInstance, uint16_t containerId, 655 uint16_t stateSetId, bool localOrRemote) 656 { 657 uint8_t* pdrData = nullptr; 658 uint32_t pdrSize{}; 659 const pldm_pdr_record* record{}; 660 do 661 { 662 record = pldm_pdr_find_record_by_type(pdrRepo, PLDM_STATE_EFFECTER_PDR, 663 record, &pdrData, &pdrSize); 664 if (record && (localOrRemote ^ pldm_pdr_record_is_remote(record))) 665 { 666 auto pdr = reinterpret_cast<pldm_state_effecter_pdr*>(pdrData); 667 auto compositeEffecterCount = pdr->composite_effecter_count; 668 auto possible_states_start = pdr->possible_states; 669 670 for (auto effecters = 0x00; effecters < compositeEffecterCount; 671 effecters++) 672 { 673 auto possibleStates = 674 reinterpret_cast<state_effecter_possible_states*>( 675 possible_states_start); 676 auto setId = possibleStates->state_set_id; 677 auto possibleStateSize = possibleStates->possible_states_size; 678 679 if (entityType == pdr->entity_type && 680 entityInstance == pdr->entity_instance && 681 containerId == pdr->container_id && stateSetId == setId) 682 { 683 return pdr->effecter_id; 684 } 685 possible_states_start += possibleStateSize + sizeof(setId) + 686 sizeof(possibleStateSize); 687 } 688 } 689 } while (record); 690 691 return PLDM_INVALID_EFFECTER_ID; 692 } 693 694 int emitStateSensorEventSignal(uint8_t tid, uint16_t sensorId, 695 uint8_t sensorOffset, uint8_t eventState, 696 uint8_t previousEventState) 697 { 698 try 699 { 700 auto& bus = DBusHandler::getBus(); 701 auto msg = bus.new_signal("/xyz/openbmc_project/pldm", 702 "xyz.openbmc_project.PLDM.Event", 703 "StateSensorEvent"); 704 msg.append(tid, sensorId, sensorOffset, eventState, previousEventState); 705 706 msg.signal_send(); 707 } 708 catch (const std::exception& e) 709 { 710 error("Error emitting pldm event signal:ERROR={ERR_EXCEP}", "ERR_EXCEP", 711 e.what()); 712 return PLDM_ERROR; 713 } 714 715 return PLDM_SUCCESS; 716 } 717 718 uint16_t findStateSensorId(const pldm_pdr* pdrRepo, uint8_t tid, 719 uint16_t entityType, uint16_t entityInstance, 720 uint16_t containerId, uint16_t stateSetId) 721 { 722 auto pdrs = findStateSensorPDR(tid, entityType, stateSetId, pdrRepo); 723 for (auto pdr : pdrs) 724 { 725 auto sensorPdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdr.data()); 726 auto compositeSensorCount = sensorPdr->composite_sensor_count; 727 auto possible_states_start = sensorPdr->possible_states; 728 729 for (auto sensors = 0x00; sensors < compositeSensorCount; sensors++) 730 { 731 auto possibleStates = 732 reinterpret_cast<state_sensor_possible_states*>( 733 possible_states_start); 734 auto setId = possibleStates->state_set_id; 735 auto possibleStateSize = possibleStates->possible_states_size; 736 if (entityType == sensorPdr->entity_type && 737 entityInstance == sensorPdr->entity_instance && 738 stateSetId == setId && containerId == sensorPdr->container_id) 739 { 740 return sensorPdr->sensor_id; 741 } 742 possible_states_start += possibleStateSize + sizeof(setId) + 743 sizeof(possibleStateSize); 744 } 745 } 746 return PLDM_INVALID_EFFECTER_ID; 747 } 748 749 void printBuffer(bool isTx, const std::vector<uint8_t>& buffer) 750 { 751 if (buffer.empty()) 752 { 753 return; 754 } 755 756 std::cout << (isTx ? "Tx: " : "Rx: "); 757 758 std::ranges::for_each(buffer, [](uint8_t byte) { 759 std::cout << std::format("{:02x} ", byte); 760 }); 761 762 std::cout << std::endl; 763 } 764 765 std::string toString(const struct variable_field& var) 766 { 767 if (var.ptr == nullptr || !var.length) 768 { 769 return ""; 770 } 771 772 std::string str(reinterpret_cast<const char*>(var.ptr), var.length); 773 std::replace_if( 774 str.begin(), str.end(), [](const char& c) { return !isprint(c); }, ' '); 775 return str; 776 } 777 778 std::vector<std::string> split(std::string_view srcStr, std::string_view delim, 779 std::string_view trimStr) 780 { 781 std::vector<std::string> out; 782 size_t start; 783 size_t end = 0; 784 785 while ((start = srcStr.find_first_not_of(delim, end)) != std::string::npos) 786 { 787 end = srcStr.find(delim, start); 788 std::string_view dstStr = srcStr.substr(start, end - start); 789 if (!trimStr.empty()) 790 { 791 dstStr.remove_prefix(dstStr.find_first_not_of(trimStr)); 792 dstStr.remove_suffix(dstStr.size() - 1 - 793 dstStr.find_last_not_of(trimStr)); 794 } 795 796 if (!dstStr.empty()) 797 { 798 out.push_back(std::string(dstStr)); 799 } 800 } 801 802 return out; 803 } 804 805 std::string getCurrentSystemTime() 806 { 807 const auto zonedTime{std::chrono::zoned_time{ 808 std::chrono::current_zone(), std::chrono::system_clock::now()}}; 809 return std::format("{:%F %Z %T}", zonedTime); 810 } 811 812 bool checkForFruPresence(const std::string& objPath) 813 { 814 bool isPresent = false; 815 static constexpr auto presentInterface = 816 "xyz.openbmc_project.Inventory.Item"; 817 static constexpr auto presentProperty = "Present"; 818 try 819 { 820 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( 821 objPath.c_str(), presentProperty, presentInterface); 822 isPresent = std::get<bool>(propVal); 823 } 824 catch (const sdbusplus::exception::SdBusError& e) 825 { 826 error( 827 "Failed to check for FRU presence for {OBJ_PATH} ERROR = {ERR_EXCEP}", 828 "OBJ_PATH", objPath.c_str(), "ERR_EXCEP", e.what()); 829 } 830 return isPresent; 831 } 832 833 bool checkIfLogicalBitSet(const uint16_t& containerId) 834 { 835 return !(containerId & 0x8000); 836 } 837 838 void setFruPresence(const std::string& fruObjPath, bool present) 839 { 840 pldm::utils::PropertyValue value{present}; 841 pldm::utils::DBusMapping dbusMapping; 842 dbusMapping.objectPath = fruObjPath; 843 dbusMapping.interface = "xyz.openbmc_project.Inventory.Item"; 844 dbusMapping.propertyName = "Present"; 845 dbusMapping.propertyType = "bool"; 846 try 847 { 848 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 849 } 850 catch (const std::exception& e) 851 { 852 error( 853 "Failed to set the present property on path: '{PATH}' with {ERROR} ", 854 "PATH", fruObjPath, "ERROR", e); 855 } 856 } 857 858 } // namespace utils 859 } // namespace pldm 860