1f8da32adSTom Joseph #include "guid.hpp" 2f8da32adSTom Joseph 34f09eaeeSWilliam A. Kennington III #include <ipmid/api.h> 49e801a2bSVernon Mauery #include <mapper.h> 59e801a2bSVernon Mauery 6*94b0d134SXie Ning #include <ipmid/utils.hpp> 7*94b0d134SXie Ning #include <phosphor-logging/elog-errors.hpp> 87b7f25f7SGeorge Liu #include <phosphor-logging/lg2.hpp> 9*94b0d134SXie Ning #include <xyz/openbmc_project/Common/error.hpp> 10bc8958feSGeorge Liu 11f8da32adSTom Joseph #include <sstream> 12f8da32adSTom Joseph #include <string> 13f8da32adSTom Joseph 14fc37e59eSVernon Mauery using namespace phosphor::logging; 15*94b0d134SXie Ning using namespace sdbusplus::xyz::openbmc_project::Common::Error; 16fc37e59eSVernon Mauery 1783029cb8STom Joseph namespace cache 1883029cb8STom Joseph { 1983029cb8STom Joseph 2083029cb8STom Joseph command::Guid guid; 21*94b0d134SXie Ning std::string guidObjService = ""; 22*94b0d134SXie Ning std::string guidObjPath = ""; 2383029cb8STom Joseph 2483029cb8STom Joseph } // namespace cache 2583029cb8STom Joseph 26f8da32adSTom Joseph namespace command 27f8da32adSTom Joseph { 28f8da32adSTom Joseph 2983029cb8STom Joseph std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr); 3083029cb8STom Joseph 31*94b0d134SXie Ning static constexpr auto propInterface = "xyz.openbmc_project.Common.UUID"; 32*94b0d134SXie Ning static constexpr auto uuidProperty = "UUID"; 33*94b0d134SXie Ning static constexpr auto subtreePath = "/xyz/openbmc_project/inventory/"; 34*94b0d134SXie Ning 35*94b0d134SXie Ning void getUIDObjectInfo() 36*94b0d134SXie Ning { 37*94b0d134SXie Ning sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()}; 38*94b0d134SXie Ning ipmi::DbusObjectInfo bmcObject; 39*94b0d134SXie Ning try 40*94b0d134SXie Ning { 41*94b0d134SXie Ning // Get the Inventory object implementing BMC interface 42*94b0d134SXie Ning bmcObject = ipmi::getDbusObject(bus, propInterface, subtreePath); 43*94b0d134SXie Ning } 44*94b0d134SXie Ning catch (const sdbusplus::exception_t& e) 45*94b0d134SXie Ning { 46*94b0d134SXie Ning lg2::error("Failed in reading BMC UUID property: {ERROR}", "ERROR", e); 47*94b0d134SXie Ning return; 48*94b0d134SXie Ning } 49*94b0d134SXie Ning 50*94b0d134SXie Ning cache::guidObjService = bmcObject.second; 51*94b0d134SXie Ning cache::guidObjPath = bmcObject.first; 52*94b0d134SXie Ning return; 53*94b0d134SXie Ning } 54*94b0d134SXie Ning 55*94b0d134SXie Ning static void rfcToGuid(std::string rfc4122, Guid& uuid) 56*94b0d134SXie Ning { 57*94b0d134SXie Ning using Argument = xyz::openbmc_project::Common::InvalidArgument; 58*94b0d134SXie Ning // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 59*94b0d134SXie Ning // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte 60*94b0d134SXie Ning // order 61*94b0d134SXie Ning // Ex: 0x2332fc2c40e66298e511f2782395a361 62*94b0d134SXie Ning constexpr size_t uuidHexLength = (2 * BMC_GUID_LEN); 63*94b0d134SXie Ning constexpr size_t uuidRfc4122Length = (uuidHexLength + 4); 64*94b0d134SXie Ning 65*94b0d134SXie Ning if (rfc4122.size() == uuidRfc4122Length) 66*94b0d134SXie Ning { 67*94b0d134SXie Ning rfc4122.erase(std::remove(rfc4122.begin(), rfc4122.end(), '-'), 68*94b0d134SXie Ning rfc4122.end()); 69*94b0d134SXie Ning } 70*94b0d134SXie Ning if (rfc4122.size() != uuidHexLength) 71*94b0d134SXie Ning { 72*94b0d134SXie Ning elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"), 73*94b0d134SXie Ning Argument::ARGUMENT_VALUE(rfc4122.c_str())); 74*94b0d134SXie Ning } 75*94b0d134SXie Ning for (size_t ind = 0; ind < uuidHexLength; ind += 2) 76*94b0d134SXie Ning { 77*94b0d134SXie Ning long b; 78*94b0d134SXie Ning try 79*94b0d134SXie Ning { 80*94b0d134SXie Ning b = std::stoul(rfc4122.substr(ind, 2), nullptr, 16); 81*94b0d134SXie Ning } 82*94b0d134SXie Ning catch (const std::exception& e) 83*94b0d134SXie Ning { 84*94b0d134SXie Ning elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"), 85*94b0d134SXie Ning Argument::ARGUMENT_VALUE(rfc4122.c_str())); 86*94b0d134SXie Ning } 87*94b0d134SXie Ning 88*94b0d134SXie Ning uuid[BMC_GUID_LEN - (ind / 2) - 1] = static_cast<uint8_t>(b); 89*94b0d134SXie Ning } 90*94b0d134SXie Ning return; 91*94b0d134SXie Ning } 9283029cb8STom Joseph 9383029cb8STom Joseph Guid getSystemGUID() 94f8da32adSTom Joseph { 95f8da32adSTom Joseph // Canned System GUID for QEMU where the Chassis DBUS object is not 96f8da32adSTom Joseph // populated 9783029cb8STom Joseph Guid guid = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 9883029cb8STom Joseph 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10}; 99f8da32adSTom Joseph 100*94b0d134SXie Ning sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()}; 101f8da32adSTom Joseph 102*94b0d134SXie Ning ipmi::Value propValue; 103*94b0d134SXie Ning try 104f8da32adSTom Joseph { 105*94b0d134SXie Ning // Read UUID property value from bmcObject 106*94b0d134SXie Ning // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 107*94b0d134SXie Ning propValue = ipmi::getDbusProperty(bus, cache::guidObjService, 108*94b0d134SXie Ning cache::guidObjPath, propInterface, 109*94b0d134SXie Ning uuidProperty); 110*94b0d134SXie Ning } 111*94b0d134SXie Ning catch (const sdbusplus::exception_t& e) 112f8da32adSTom Joseph { 113*94b0d134SXie Ning lg2::error("Failed in reading BMC UUID property: {ERROR}", "ERROR", e); 114*94b0d134SXie Ning return guid; 115f8da32adSTom Joseph } 116f8da32adSTom Joseph 117*94b0d134SXie Ning std::string rfc4122Uuid = std::get<std::string>(propValue); 118*94b0d134SXie Ning try 119f8da32adSTom Joseph { 120*94b0d134SXie Ning // convert to IPMI format 121*94b0d134SXie Ning rfcToGuid(rfc4122Uuid, guid); 122f8da32adSTom Joseph } 123*94b0d134SXie Ning catch (const InvalidArgument& e) 124f8da32adSTom Joseph { 125*94b0d134SXie Ning lg2::error("Failed in parsing BMC UUID property: {VALUE}", "VALUE", 126*94b0d134SXie Ning rfc4122Uuid.c_str()); 127*94b0d134SXie Ning return guid; 128f8da32adSTom Joseph } 129f8da32adSTom Joseph 130f8da32adSTom Joseph return guid; 131f8da32adSTom Joseph } 132f8da32adSTom Joseph 13383029cb8STom Joseph void registerGUIDChangeCallback() 13483029cb8STom Joseph { 13583029cb8STom Joseph if (matchPtr == nullptr) 13683029cb8STom Joseph { 13783029cb8STom Joseph using namespace sdbusplus::bus::match::rules; 1380a59062cSPatrick Williams sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()}; 13983029cb8STom Joseph 14083029cb8STom Joseph matchPtr = std::make_unique<sdbusplus::bus::match_t>( 141*94b0d134SXie Ning bus, propertiesChanged(cache::guidObjPath, propInterface), 1420a59062cSPatrick Williams [](sdbusplus::message_t&) { cache::guid = getSystemGUID(); }); 14383029cb8STom Joseph } 14483029cb8STom Joseph } 14583029cb8STom Joseph 146f8da32adSTom Joseph } // namespace command 147