diff options
-rw-r--r-- | apphandler.cpp | 128 | ||||
-rw-r--r-- | docs/configuration.md | 24 |
2 files changed, 93 insertions, 59 deletions
diff --git a/apphandler.cpp b/apphandler.cpp index 048219e..4b00065 100644 --- a/apphandler.cpp +++ b/apphandler.cpp @@ -3,9 +3,11 @@ #include "app/watchdog.hpp" #include "host-ipmid/ipmid-api.h" #include "ipmid.hpp" +#include "nlohmann/json.hpp" #include "types.hpp" #include "utils.hpp" +#include <fstream> #include <stdio.h> #include <stdint.h> #include <systemd/sd-bus.h> @@ -59,7 +61,6 @@ ipmi_ret_t ipmi_app_set_acpi_power_state(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return rc; } - typedef struct { char major; @@ -164,73 +165,82 @@ ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd, char *busname = NULL; int r; rev_t rev = {0}; - ipmi_device_id_t dev_id{}; + static ipmi_device_id_t dev_id{}; + static bool dev_id_initialized = false; + const char* filename = "/usr/share/ipmi-providers/dev_id.json"; // Data length *data_len = sizeof(dev_id); - // From IPMI spec, controller that have different application commands, or different - // definitions of OEM fields, are expected to have different Device ID values. - // Set to 0 now. + 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; + } + 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); + } + } - // Device Revision is set to 0 now. - // Bit7 identifies if device provide Device SDRs, obmc don't have SDR,we use ipmi to - // simulate SDR, hence the value: - dev_id.revision = 0x80; + // IPMI Spec version 2.0 + dev_id.ipmi_ver = 2; - // 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; - } - 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); + std::ifstream dev_id_file(filename); + if (dev_id_file.is_open()) + { + auto data = nlohmann::json::parse(dev_id_file, nullptr, false); + if (!data.is_discarded()) + { + dev_id.id = data.value("id", 0); + dev_id.revision = data.value("revision", 0); + dev_id.addn_dev_support = data.value("addn_dev_support", 0); + dev_id.manuf_id[2] = data.value("manuf_id", 0) >> 16; + dev_id.manuf_id[1] = data.value("manuf_id", 0) >> 8; + dev_id.manuf_id[0] = data.value("manuf_id", 0); + dev_id.prod_id[1] = data.value("prod_id", 0) >> 8; + dev_id.prod_id[0] = data.value("prod_id", 0); + dev_id.aux[3] = data.value("aux", 0) >> 24; + dev_id.aux[2] = data.value("aux", 0) >> 16; + dev_id.aux[1] = data.value("aux", 0) >> 8; + dev_id.aux[0] = data.value("aux", 0); + + //Don't read the file every time if successful + dev_id_initialized = true; + } + else + { + log<level::ERR>("Device ID JSON parser failure"); + rc = IPMI_CC_UNSPECIFIED_ERROR; + } + } + else + { + log<level::ERR>("Device ID file not found"); + rc = IPMI_CC_UNSPECIFIED_ERROR; } } - // IPMI Spec version 2.0 - dev_id.ipmi_ver = 2; - - // Additional device Support. - // List the 'logical device' commands and functions that the controller supports - // that are in addition to the mandatory IPM and Application commands. - // [7] Chassis Device (device functions as chassis device per ICMB spec.) - // [6] Bridge (device responds to Bridge NetFn commands) - // [5] IPMB Event Generator - // [4] IPMB Event Receiver - // [3] FRU Inventory Device - // [2] SEL Device - // [1] SDR Repository Device - // [0] Sensor Device - // We support FRU/SEL/Sensor now: - dev_id.addn_dev_support = 0x8D; - - // This value is the IANA number assigned to "IBM Platform Firmware - // Division", which is also used by our service processor. We may want - // a different number or at least a different version? - dev_id.manuf_id[0] = 0x41; - dev_id.manuf_id[1] = 0xA7; - dev_id.manuf_id[2] = 0x00; - - // Witherspoon's product ID is hardcoded to 4F42(ASCII 'OB'). - // TODO: openbmc/openbmc#495 - dev_id.prod_id[0] = 0x4F; - dev_id.prod_id[1] = 0x42; - // Pack the actual response memcpy(response, &dev_id, *data_len); finish: diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..61caaf1 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,24 @@ +#Device ID Configuration# + +There is a default dev_id.json file provided by +meta-phosphor/common/recipes-phosphor/ipmi/phosphor-ipmi-host.bb + +Any target can override the default json file by providing a +phosphor-ipmi-host.bbappend with an ODM or platform customizable configuration. + +For a specific example, see: +[Witherspoon](https://github.com/openbmc/openbmc/blob/master/ +meta-openbmc-machines/meta-openpower/meta-ibm/meta-witherspoon/ +recipes-phosphor/ipmi/phosphor-ipmi-host.bbappend) + +The JSON format for get_device_id: + + {"id": 0, "revision": 0, "addn_dev_support": 0, + "manuf_id": 0, "prod_id": 0, "aux": 0} + + +Each value in this JSON object should be an integer. The file is placed in +/usr/share/ipmi-providers/ by Yocto, and will be parsed upon the first call to +get_device_id. The data is then cached for future use. If you change the data +at runtime, simply restart the service to see the new data fetched by a call to +get_device_id. |