diff options
author | Vernon Mauery <vernon.mauery@linux.intel.com> | 2019-03-25 13:33:03 -0700 |
---|---|---|
committer | Vernon Mauery <vernon.mauery@linux.intel.com> | 2019-05-20 17:27:51 +0000 |
commit | 1554132bc08cf7b22777ae83c3ebd23997a61496 (patch) | |
tree | d3a4dce7977deda17ff4d1b6dfb2eee21b7a65fa /apphandler.cpp | |
parent | 572bac1735aef5587b72a26d760d875908919352 (diff) | |
download | phosphor-host-ipmid-1554132bc08cf7b22777ae83c3ebd23997a61496.tar.gz phosphor-host-ipmid-1554132bc08cf7b22777ae83c3ebd23997a61496.zip |
rewrite Get Device GUID to use new provider API
Modify to use the new provider API. One by one, change calls to
remove any legacy API constructs.
Tested-by: ipmitool 6 8
30 ba 05 cd 7e 9d ac 89 4a 4c 52 ef f3 24 2d 5f
(with matching change from bmcweb:)
curl https://<bmcip>/redfish/v1/Managers/bmc
...
"UUID": "5f2d24f3-ef52-4c4a-89ac-9d7ecd05ba30"
Change-Id: I4cd3b945f76b4fe6c4fcf31d8e1962aaa768828e
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Diffstat (limited to 'apphandler.cpp')
-rw-r--r-- | apphandler.cpp | 150 |
1 files changed, 53 insertions, 97 deletions
diff --git a/apphandler.cpp b/apphandler.cpp index 91bede5..ea40060 100644 --- a/apphandler.cpp +++ b/apphandler.cpp @@ -700,120 +700,75 @@ auto ipmiAppGetSelfTestResults() -> ipmi::RspType<uint8_t, uint8_t> return ipmi::responseSuccess(notImplemented, zero); } -ipmi_ret_t ipmi_app_get_device_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - ipmi_request_t request, - ipmi_response_t response, - ipmi_data_len_t data_len, - ipmi_context_t context) +static constexpr size_t uuidBinaryLength = 16; +static std::array<uint8_t, uuidBinaryLength> rfc4122ToIpmi(std::string rfc4122) { - const char* objname = "/org/openbmc/control/chassis0"; - const char* iface = "org.freedesktop.DBus.Properties"; - const char* chassis_iface = "org.openbmc.control.Chassis"; - sd_bus_message* reply = NULL; - sd_bus_error error = SD_BUS_ERROR_NULL; - int r = 0; - char* uuid = NULL; - char* busname = NULL; - + 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 - - const int resp_size = 16; // Response is 16 hex bytes per IPMI Spec - uint8_t resp_uuid[resp_size]; // Array to hold the formatted response - // Point resp end of array to save in reverse order - int resp_loc = resp_size - 1; - int i = 0; - char* tokptr = NULL; - char* id_octet = NULL; - size_t total_uuid_size = 0; - // 1 byte of resp is built from 2 chars of uuid. - constexpr size_t max_uuid_size = 2 * resp_size; - - // Status code. - ipmi_ret_t rc = IPMI_CC_OK; - *data_len = 0; - - // Call Get properties method with the interface and property name - r = mapper_get_service(bus, objname, &busname); - if (r < 0) - { - log<level::ERR>("Failed to get bus name", entry("BUS=%s", objname), - entry("ERRNO=0x%X", -r)); - goto finish; - } - r = sd_bus_call_method(bus, busname, objname, iface, "Get", &error, &reply, - "ss", chassis_iface, "uuid"); - if (r < 0) - { - log<level::ERR>("Failed to call Get Method", entry("ERRNO=0x%X", -r)); - rc = IPMI_CC_UNSPECIFIED_ERROR; - goto finish; - } - - r = sd_bus_message_read(reply, "v", "s", &uuid); - if (r < 0 || uuid == NULL) + constexpr size_t uuidHexLength = (2 * uuidBinaryLength); + constexpr size_t uuidRfc4122Length = (uuidHexLength + 4); + std::array<uint8_t, uuidBinaryLength> uuid; + if (rfc4122.size() == uuidRfc4122Length) { - log<level::ERR>("Failed to get a response", entry("ERRNO=0x%X", -r)); - rc = IPMI_CC_RESPONSE_ERROR; - goto finish; + rfc4122.erase(std::remove(rfc4122.begin(), rfc4122.end(), '-'), + rfc4122.end()); } - - // Traverse the UUID - // Get the UUID octects separated by dash - id_octet = strtok_r(uuid, "-", &tokptr); - - if (id_octet == NULL) + if (rfc4122.size() != uuidHexLength) { - // Error - log<level::ERR>("Unexpected UUID format", entry("UUID=%s", uuid)); - rc = IPMI_CC_RESPONSE_ERROR; - goto finish; + elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"), + Argument::ARGUMENT_VALUE(rfc4122.c_str())); } - - while (id_octet != NULL) + for (size_t ind = 0; ind < uuidHexLength; ind += 2) { - // Calculate the octet string size since it varies - // Divide it by 2 for the array size since 1 byte is built from 2 chars - int tmp_size = strlen(id_octet) / 2; - - // Check if total UUID size has been exceeded - if ((total_uuid_size += strlen(id_octet)) > max_uuid_size) + char v[3]; + v[0] = rfc4122[ind]; + v[1] = rfc4122[ind + 1]; + v[2] = 0; + size_t err; + long b; + try { - // Error - UUID too long to store - log<level::ERR>("UUID too long", entry("UUID=%s", uuid)); - rc = IPMI_CC_RESPONSE_ERROR; - goto finish; + b = std::stoul(v, &err, 16); } - - for (i = 0; i < tmp_size; i++) + catch (std::exception& e) { - // Holder of the 2 chars that will become a byte - char tmp_array[3] = {0}; - strncpy(tmp_array, id_octet, 2); // 2 chars at a time - - int resp_byte = strtoul(tmp_array, NULL, 16); // Convert to hex byte - // Copy end to first - std::memcpy((void*)&resp_uuid[resp_loc], &resp_byte, 1); - resp_loc--; - id_octet += 2; // Finished with the 2 chars, advance + elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"), + Argument::ARGUMENT_VALUE(rfc4122.c_str())); } - id_octet = strtok_r(NULL, "-", &tokptr); // Get next octet + // check that exactly two ascii bytes were converted + if (err != 2) + { + elog<InvalidArgument>(Argument::ARGUMENT_NAME("rfc4122"), + Argument::ARGUMENT_VALUE(rfc4122.c_str())); + } + uuid[uuidBinaryLength - (ind / 2) - 1] = static_cast<uint8_t>(b); } + return uuid; +} + +auto ipmiAppGetDeviceGuid() + -> ipmi::RspType<std::array<uint8_t, uuidBinaryLength>> +{ + // return a fixed GUID based on /etc/machine-id + // This should match the /redfish/v1/Managers/bmc's UUID data - // Data length - *data_len = resp_size; + // machine specific application ID (for BMC ID) + // generated by systemd-id128 -p new as per man page + static constexpr sd_id128_t bmcUuidAppId = SD_ID128_MAKE( + e0, e1, 73, 76, 64, 61, 47, da, a5, 0c, d0, cc, 64, 12, 45, 78); - // Pack the actual response - std::memcpy(response, &resp_uuid, *data_len); + sd_id128_t bmcUuid; + // create the UUID from /etc/machine-id via the systemd API + sd_id128_get_machine_app_specific(bmcUuidAppId, &bmcUuid); -finish: - sd_bus_error_free(&error); - reply = sd_bus_message_unref(reply); - free(busname); + char bmcUuidCstr[SD_ID128_STRING_MAX]; + std::string systemUuid = sd_id128_to_string(bmcUuid, bmcUuidCstr); - return rc; + std::array<uint8_t, uuidBinaryLength> uuid = rfc4122ToIpmi(systemUuid); + return ipmi::responseSuccess(uuid); } auto ipmiAppGetBtCapabilities() @@ -1339,8 +1294,9 @@ void register_netfn_app_functions() ipmi::Privilege::User, ipmiAppGetSelfTestResults); // <Get Device GUID> - ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_GUID, NULL, - ipmi_app_get_device_guid, PRIVILEGE_USER); + ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnApp, + ipmi::app::cmdGetDeviceGuid, ipmi::Privilege::User, + ipmiAppGetDeviceGuid); // <Set ACPI Power State> ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_ACPI, NULL, |