diff options
Diffstat (limited to 'apphandler.cpp')
-rw-r--r-- | apphandler.cpp | 146 |
1 files changed, 111 insertions, 35 deletions
diff --git a/apphandler.cpp b/apphandler.cpp index e370f0c..6564181 100644 --- a/apphandler.cpp +++ b/apphandler.cpp @@ -24,6 +24,8 @@ #include <phosphor-logging/log.hpp> #include <phosphor-logging/elog-errors.hpp> #include "xyz/openbmc_project/Common/error.hpp" +#include "xyz/openbmc_project/Software/Version/server.hpp" +#include "xyz/openbmc_project/Software/Activation/server.hpp" extern sd_bus *bus; @@ -32,10 +34,21 @@ constexpr auto bmc_guid_interface = "xyz.openbmc_project.Common.UUID"; constexpr auto bmc_guid_property = "UUID"; constexpr auto bmc_guid_len = 16; +static constexpr auto redundancyIntf = + "xyz.openbmc_project.Software.RedundancyPriority"; +static constexpr auto versionIntf = + "xyz.openbmc_project.Software.Version"; +static constexpr auto activationIntf = + "xyz.openbmc_project.Software.Activation"; +static constexpr auto softwareRoot = "/xyz/openbmc_project/software"; + void register_netfn_app_functions() __attribute__((constructor)); using namespace phosphor::logging; using namespace sdbusplus::xyz::openbmc_project::Common::Error; +using Version = sdbusplus::xyz::openbmc_project::Software::server::Version; +using Activation = + sdbusplus::xyz::openbmc_project::Software::server::Activation; namespace fs = std::experimental::filesystem; // Offset in get device id command. @@ -51,6 +64,82 @@ typedef struct uint8_t aux[4]; }__attribute__((packed)) ipmi_device_id_t; +/** + * @brief Returns the Version info from primary s/w object + * + * Get the Version info from the active s/w object which is having high + * "Priority" value(a smaller number is a higher priority) and "Purpose" + * is "BMC" from the list of all s/w objects those are implementing + * RedundancyPriority interface from the given softwareRoot path. + * + * @return On success returns the Version info from primary s/w object. + * + */ +std::string getActiveSoftwareVersionInfo() +{ + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + + std::string revision{}; + auto objectTree = ipmi::getAllDbusObjects(bus, softwareRoot, redundancyIntf, + ""); + if (objectTree.empty()) + { + log<level::ERR>("No Obj has implemented the s/w redundancy interface", + entry("INTERFACE=%s", redundancyIntf)); + elog<InternalFailure>(); + } + + auto objectFound = false; + for (auto& softObject : objectTree) + { + auto service = ipmi::getService(bus, redundancyIntf, softObject.first); + auto objValueTree = ipmi::getManagedObjects(bus, service, softwareRoot); + + auto minPriority = 0xFF; + for (const auto& objIter : objValueTree) + { + try + { + auto& intfMap = objIter.second; + auto& redundancyPriorityProps = intfMap.at(redundancyIntf); + auto& versionProps = intfMap.at(versionIntf); + auto& activationProps = intfMap.at(activationIntf); + auto priority = + redundancyPriorityProps.at("Priority").get<uint8_t>(); + auto purpose = versionProps.at("Purpose").get<std::string>(); + auto activation = + activationProps.at("Activation").get<std::string>(); + auto version = versionProps.at("Version").get<std::string>(); + if ((Version::convertVersionPurposeFromString(purpose) == + Version::VersionPurpose::BMC) && + (Activation::convertActivationsFromString(activation) == + Activation::Activations::Active)) + { + if (priority < minPriority) + { + minPriority = priority; + objectFound = true; + revision = std::move(version); + } + } + } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + } + } + } + + if (!objectFound) + { + log<level::ERR>("Could not found an BMC software Object"); + elog<InternalFailure>(); + } + + return revision; +} + + ipmi_ret_t ipmi_app_set_acpi_power_state(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) @@ -162,12 +251,7 @@ ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_data_len_t data_len, ipmi_context_t context) { ipmi_ret_t rc = IPMI_CC_OK; - const char *objname = - "/org/openbmc/inventory/system/chassis/motherboard/bmc"; - const char *iface = "org.openbmc.InventoryItem"; - char *ver = NULL; - char *busname = NULL; - int r; + int r = -1; rev_t rev = {0}; static ipmi_device_id_t dev_id{}; static bool dev_id_initialized = false; @@ -178,33 +262,27 @@ ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd, if (!dev_id_initialized) { - // Firmware revision is already implemented, - // so get it from appropriate position. - r = mapper_get_service(bus, objname, &busname); - if (r < 0) { - fprintf(stderr, "Failed to get %s bus name: %s\n", - objname, strerror(-r)); - goto finish; + try + { + auto version = getActiveSoftwareVersionInfo(); + r = convert_version(version.c_str(), &rev); } - r = sd_bus_get_property_string(bus,busname,objname,iface,"version", - NULL, &ver); - if ( r < 0 ) { - fprintf(stderr, "Failed to obtain version property: %s\n", - strerror(-r)); - } else { - r = convert_version(ver, &rev); - if( r >= 0 ) { - // bit7 identifies if the device is available - // 0=normal operation - // 1=device firmware, SDR update, - // or self-initialization in progress. - // our SDR is normal working condition, so mask: - dev_id.fw[0] = 0x7F & rev.major; - - rev.minor = (rev.minor > 99 ? 99 : rev.minor); - dev_id.fw[1] = rev.minor % 10 + (rev.minor / 10) * 16; - memcpy(&dev_id.aux, rev.d, 4); - } + catch (const std::exception& e) + { + log<level::ERR>(e.what()); + } + + if( r >= 0 ) { + // bit7 identifies if the device is available + // 0=normal operation + // 1=device firmware, SDR update, + // or self-initialization in progress. + // our SDR is normal working condition, so mask: + dev_id.fw[0] = 0x7F & rev.major; + + rev.minor = (rev.minor > 99 ? 99 : rev.minor); + dev_id.fw[1] = rev.minor % 10 + (rev.minor / 10) * 16; + memcpy(&dev_id.aux, rev.d, 4); } // IPMI Spec version 2.0 @@ -247,9 +325,7 @@ ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd, // Pack the actual response memcpy(response, &dev_id, *data_len); -finish: - free(busname); - free(ver); + return rc; } |