xref: /openbmc/phosphor-net-ipmid/command/guid.cpp (revision 94b0d134c0b8f0230e7d74c8ac34ebeea5ba91e1)
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