| #include "guid.hpp" |
| |
| #include <ipmid/api.h> |
| #include <mapper.h> |
| |
| #include <ipmid/utils.hpp> |
| #include <phosphor-logging/elog-errors.hpp> |
| #include <phosphor-logging/lg2.hpp> |
| #include <xyz/openbmc_project/Common/error.hpp> |
| |
| #include <sstream> |
| #include <string> |
| |
| using namespace phosphor::logging; |
| using namespace sdbusplus::xyz::openbmc_project::Common::Error; |
| |
| namespace cache |
| { |
| |
| command::Guid guid; |
| std::string guidObjService = ""; |
| std::string guidObjPath = ""; |
| |
| } // namespace cache |
| |
| namespace command |
| { |
| |
| std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr); |
| |
| static constexpr auto propInterface = "xyz.openbmc_project.Common.UUID"; |
| static constexpr auto uuidProperty = "UUID"; |
| static constexpr auto subtreePath = "/xyz/openbmc_project/inventory/"; |
| |
| void getUIDObjectInfo() |
| { |
| sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()}; |
| ipmi::DbusObjectInfo bmcObject; |
| try |
| { |
| // Get the Inventory object implementing BMC interface |
| bmcObject = ipmi::getDbusObject(bus, propInterface, subtreePath); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| lg2::error("Failed in reading BMC UUID property: {ERROR}", "ERROR", e); |
| return; |
| } |
| |
| cache::guidObjService = bmcObject.second; |
| cache::guidObjPath = bmcObject.first; |
| return; |
| } |
| |
| static void rfcToGuid(std::string rfc4122, Guid& uuid) |
| { |
| using Argument = xyz::openbmc_project::Common::InvalidArgument; |
| // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 |
| // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte |
| // order |
| // Ex: 0x2332fc2c40e66298e511f2782395a361 |
| constexpr size_t uuidHexLength = (2 * BMC_GUID_LEN); |
| constexpr size_t uuidRfc4122Length = (uuidHexLength + 4); |
| |
| if (rfc4122.size() == uuidRfc4122Length) |
| { |
| rfc4122.erase(std::remove(rfc4122.begin(), rfc4122.end(), '-'), |
| rfc4122.end()); |
| } |
| if (rfc4122.size() != uuidHexLength) |
| { |
| elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"), |
| Argument::ARGUMENT_VALUE(rfc4122.c_str())); |
| } |
| for (size_t ind = 0; ind < uuidHexLength; ind += 2) |
| { |
| long b; |
| try |
| { |
| b = std::stoul(rfc4122.substr(ind, 2), nullptr, 16); |
| } |
| catch (const std::exception& e) |
| { |
| elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"), |
| Argument::ARGUMENT_VALUE(rfc4122.c_str())); |
| } |
| |
| uuid[BMC_GUID_LEN - (ind / 2) - 1] = static_cast<uint8_t>(b); |
| } |
| return; |
| } |
| |
| Guid getSystemGUID() |
| { |
| // Canned System GUID for QEMU where the Chassis DBUS object is not |
| // populated |
| Guid guid = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, |
| 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10}; |
| |
| sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()}; |
| |
| ipmi::Value propValue; |
| try |
| { |
| // Read UUID property value from bmcObject |
| // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 |
| propValue = ipmi::getDbusProperty(bus, cache::guidObjService, |
| cache::guidObjPath, propInterface, |
| uuidProperty); |
| } |
| catch (const sdbusplus::exception_t& e) |
| { |
| lg2::error("Failed in reading BMC UUID property: {ERROR}", "ERROR", e); |
| return guid; |
| } |
| |
| std::string rfc4122Uuid = std::get<std::string>(propValue); |
| try |
| { |
| // convert to IPMI format |
| rfcToGuid(rfc4122Uuid, guid); |
| } |
| catch (const InvalidArgument& e) |
| { |
| lg2::error("Failed in parsing BMC UUID property: {VALUE}", "VALUE", |
| rfc4122Uuid.c_str()); |
| return guid; |
| } |
| |
| return guid; |
| } |
| |
| void registerGUIDChangeCallback() |
| { |
| if (matchPtr == nullptr) |
| { |
| using namespace sdbusplus::bus::match::rules; |
| sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()}; |
| |
| matchPtr = std::make_unique<sdbusplus::bus::match_t>( |
| bus, propertiesChanged(cache::guidObjPath, propInterface), |
| [](sdbusplus::message_t&) { cache::guid = getSystemGUID(); }); |
| } |
| } |
| |
| } // namespace command |