diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager')
5 files changed, 1005 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0001-Improve-initialization-of-I2C-sensors.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0001-Improve-initialization-of-I2C-sensors.patch new file mode 100644 index 000000000..e47111c56 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0001-Improve-initialization-of-I2C-sensors.patch @@ -0,0 +1,493 @@ +From a85d4c9cf702965593ec771e57a975e30d1d5853 Mon Sep 17 00:00:00 2001 +From: Johnathan Mantey <johnathanx.mantey@intel.com> +Date: Tue, 13 Oct 2020 15:00:51 -0700 +Subject: [PATCH] Improve initialization of I2C sensors + +After an AC cycle validation has witnessed some systems sensors are +missing. As Entity Manager begins the process of scanning for +sesnsors, and creating the hardware monitoring nodes, there are +occassionally some failures to correctly create the node. This +manifests itself by the 'dd' kernel driver emitting an -EBUSY error +message. Unfortunately the 'dd' driver also eats the error code, and +continues. This is by design. + +This commit modifies how the nodes are initialized. The steps taken: +1. Determine if the node is already present +2. Create the node if it is not +3. Set a timer, to give the kernel time to create the node +4. For those sensors that create a "hwmon" subdir, search for that +directory after the timer elapses. +5. If the subdir is not present, delete the device, and try again by +initiating another timer. +6. Continue until the subdir exists, or a retry count expires. + +Tested: +Ran AC cycles via a script. +After each cycle, wait for the SUT to DC on, and arrive at the EFI +Shell> propmt. +Issue "ipmitool sensor list", capturing the results +Search the list for all of the sensors that have been reported as +missing after AC cycles. + +Change-Id: I118df674162677d66e7d211b089430fce384086b +Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com> +--- + include/devices.hpp | 167 +++++++++++++++++++++----------------- + src/Overlay.cpp | 192 ++++++++++++++++++++++++++++++++++---------- + 2 files changed, 243 insertions(+), 116 deletions(-) + +diff --git a/include/devices.hpp b/include/devices.hpp +index 50fbe63..2e299a0 100644 +--- a/include/devices.hpp ++++ b/include/devices.hpp +@@ -31,107 +31,130 @@ struct CmpStr + + struct ExportTemplate + { +- ExportTemplate(const char* params, const char* dev) : +- parameters(params), device(dev){}; ++ ExportTemplate(const char* params, const char* dev, const char* constructor, ++ const char* destructor, bool createsHWMon) : ++ parameters(params), ++ devicePath(dev), add(constructor), remove(destructor), ++ createsHWMon(createsHWMon){}; + const char* parameters; +- const char* device; ++ const char* devicePath; ++ const char* add; ++ const char* remove; ++ bool createsHWMon; + }; + + const boost::container::flat_map<const char*, ExportTemplate, CmpStr> + exportTemplates{ + {{"EEPROM_24C02", + ExportTemplate("24c02 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ "/sys/bus/i2c/devices/i2c-$Bus/new_device", ++ "new_device", "delete_device", false)}, + {"EEPROM_24C64", + ExportTemplate("24c64 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"ADM1266", +- ExportTemplate("adm1266 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ "/sys/bus/i2c/devices/i2c-$Bus/new_device", ++ "new_device", "delete_device", false)}, ++ {"24C02", ++ ExportTemplate("24c02 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, ++ {"24C64", ++ ExportTemplate("24c64 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, ++ {"ADM1266", ExportTemplate("adm1266 $Address", ++ "/sys/bus/i2c/devices/i2c-$Bus/new_device", ++ "new_device", "delete_device", false)}, + {"ADM1272", +- ExportTemplate("adm1272 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"EEPROM", ExportTemplate("eeprom $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("adm1272 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, ++ {"EEPROM", ++ ExportTemplate("eeprom $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, + {"EMC1412", +- ExportTemplate("emc1412 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("emc1412 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"EMC1413", +- ExportTemplate("emc1413 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("emc1413 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"EMC1414", +- ExportTemplate("emc1414 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"Gpio", ExportTemplate("$Index", "/sys/class/gpio/export")}, +- {"INA230", ExportTemplate("ina230 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("emc1414 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, ++ {"Gpio", ExportTemplate("$Index", "/sys/class/gpio", "export", ++ "unexport", false)}, ++ {"INA230", ++ ExportTemplate("ina230 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"ISL68137", +- ExportTemplate("isl68137 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("isl68137 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"ISL68223", +- ExportTemplate("isl68223 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("isl68223 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"ISL69243", +- ExportTemplate("isl69243 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("isl69243 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"MAX16601", +- ExportTemplate("max16601 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max16601 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"MAX20710", +- ExportTemplate("max20710 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max20710 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"MAX20730", +- ExportTemplate("max20730 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max20730 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"MAX20734", +- ExportTemplate("max20734 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max20734 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"MAX20796", +- ExportTemplate("max20796 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max20796 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"MAX31725", +- ExportTemplate("max31725 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max31725 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"MAX31730", +- ExportTemplate("max31730 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"MAX34440", +- ExportTemplate("max34440 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max31730 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, ++ {"MAX34440", ExportTemplate("max34440 $Address", ++ "/sys/bus/i2c/devices/i2c-$Bus/new_device", ++ "new_device", "delete_device", true)}, + {"MAX34451", +- ExportTemplate("max34451 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max34451 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"MAX6654", +- ExportTemplate("max6654 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("max6654 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"PCA9543Mux", +- ExportTemplate("pca9543 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("pca9543 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, + {"PCA9544Mux", +- ExportTemplate("pca9544 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("pca9544 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, + {"PCA9545Mux", +- ExportTemplate("pca9545 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("pca9545 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, + {"PCA9546Mux", +- ExportTemplate("pca9546 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("pca9546 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, + {"PCA9547Mux", +- ExportTemplate("pca9547 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"SBTSI", ExportTemplate("sbtsi $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"pmbus", ExportTemplate("pmbus $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"TMP112", ExportTemplate("tmp112 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"TMP175", ExportTemplate("tmp175 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"TMP421", ExportTemplate("tmp421 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, +- {"TMP441", ExportTemplate("tmp441 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}, ++ ExportTemplate("pca9547 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", false)}, ++ {"SBTSI", ++ ExportTemplate("sbtsi $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, ++ {"pmbus", ++ ExportTemplate("pmbus $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, ++ {"TMP112", ++ ExportTemplate("tmp112 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, ++ {"TMP175", ++ ExportTemplate("tmp175 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, ++ {"TMP421", ++ ExportTemplate("tmp421 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, ++ {"TMP441", ++ ExportTemplate("tmp441 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}, + {"TMP75", +- ExportTemplate("tmp75 $Address", +- "/sys/bus/i2c/devices/i2c-$Bus/new_device")}}}; ++ ExportTemplate("tmp75 $Address", "/sys/bus/i2c/devices/i2c-$Bus", ++ "new_device", "delete_device", true)}}}; + } // namespace devices +diff --git a/src/Overlay.cpp b/src/Overlay.cpp +index cb6ed10..7a3089e 100644 +--- a/src/Overlay.cpp ++++ b/src/Overlay.cpp +@@ -21,6 +21,8 @@ + #include "devices.hpp" + + #include <boost/algorithm/string/predicate.hpp> ++#include <boost/asio/io_context.hpp> ++#include <boost/asio/steady_timer.hpp> + #include <boost/container/flat_map.hpp> + #include <boost/container/flat_set.hpp> + #include <boost/process/child.hpp> +@@ -32,6 +34,8 @@ + #include <regex> + #include <string> + ++extern boost::asio::io_context io; ++ + constexpr const char* OUTPUT_DIR = "/tmp/overlays"; + constexpr const char* TEMPLATE_CHAR = "$"; + constexpr const char* HEX_FORMAT_STR = "0x"; +@@ -113,16 +117,149 @@ void linkMux(const std::string& muxName, size_t busIndex, size_t address, + } + } + ++static int deleteDevice(const std::string& devicePath, ++ std::shared_ptr<uint64_t> address, ++ const std::string& destructor) ++{ ++ if (!address) ++ { ++ return -1; ++ } ++ std::filesystem::path deviceDestructor(devicePath); ++ deviceDestructor /= destructor; ++ std::ofstream deviceFile(deviceDestructor); ++ if (!deviceFile.good()) ++ { ++ std::cerr << "Error writing " << deviceDestructor << "\n"; ++ return -1; ++ } ++ deviceFile << std::to_string(*address); ++ deviceFile.close(); ++ return 0; ++} ++ ++static int createDevice(const std::string& devicePath, ++ const std::string& parameters, ++ const std::string& constructor) ++{ ++ std::filesystem::path deviceConstructor(devicePath); ++ deviceConstructor /= constructor; ++ std::ofstream deviceFile(deviceConstructor); ++ if (!deviceFile.good()) ++ { ++ std::cerr << "Error writing " << deviceConstructor << "\n"; ++ return -1; ++ } ++ deviceFile << parameters; ++ deviceFile.close(); ++ ++ return 0; ++} ++ ++static bool deviceIsCreated(const std::string& devicePath, ++ std::shared_ptr<uint64_t> bus, ++ std::shared_ptr<uint64_t> address, ++ const bool retrying) ++{ ++ // Prevent the device from being created a second time. ++ if (bus && address) ++ { ++ std::ostringstream hex; ++ hex << std::hex << *address; ++ std::string addressHex = hex.str(); ++ std::string busStr = std::to_string(*bus); ++ ++ if (std::filesystem::is_directory(devicePath)) ++ { ++ for (const auto& path : ++ std::filesystem::directory_iterator(devicePath)) ++ { ++ if (!std::filesystem::is_directory(path)) ++ { ++ continue; ++ } ++ ++ const std::string& directoryName = path.path().filename(); ++ if (boost::starts_with(directoryName, busStr) && ++ boost::ends_with(directoryName, addressHex)) ++ { ++ if (retrying) ++ { ++ // subsequent attempts should find the hwmon subdir. ++ std::filesystem::path hwmonDir(devicePath); ++ hwmonDir /= directoryName; ++ hwmonDir /= "hwmon"; ++ bool dirFound = ++ (std::filesystem::is_directory(hwmonDir)); ++ return dirFound; ++ } ++ else ++ { ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ } ++ return false; ++} ++ ++constexpr size_t totalBuildDeviceRetries = 5; ++static int buildDevice(const std::string& devicePath, ++ const std::string& parameters, ++ std::shared_ptr<uint64_t> bus, ++ std::shared_ptr<uint64_t> address, ++ const std::string& constructor, ++ const std::string& destructor, const bool createsHWMon, ++ const size_t retries = totalBuildDeviceRetries) ++{ ++ bool tryAgain = false; ++ if (!retries) ++ { ++ return -1; ++ } ++ ++ if (!deviceIsCreated(devicePath, bus, address, false)) ++ { ++ createDevice(devicePath, parameters, constructor); ++ tryAgain = true; ++ } ++ else if (createsHWMon && !deviceIsCreated(devicePath, bus, address, true)) ++ { ++ // device is present, hwmon subdir missing ++ deleteDevice(devicePath, address, destructor); ++ tryAgain = true; ++ } ++ ++ if (tryAgain) ++ { ++ std::shared_ptr<boost::asio::steady_timer> createTimer = ++ std::make_shared<boost::asio::steady_timer>(io); ++ createTimer->expires_after(std::chrono::milliseconds(500)); ++ createTimer->async_wait([createTimer, devicePath, parameters, bus, ++ address, constructor, destructor, createsHWMon, ++ retries](const boost::system::error_code&) { ++ buildDevice(devicePath, parameters, bus, address, constructor, ++ destructor, createsHWMon, retries - 1); ++ }); ++ } ++ return 0; ++} ++ + void exportDevice(const std::string& type, + const devices::ExportTemplate& exportTemplate, + const nlohmann::json& configuration) + { + + std::string parameters = exportTemplate.parameters; +- std::string device = exportTemplate.device; ++ std::string devicePath = exportTemplate.devicePath; ++ std::string constructor = exportTemplate.add; ++ std::string destructor = exportTemplate.remove; ++ bool createsHWMon = exportTemplate.createsHWMon; + std::string name = "unknown"; +- const uint64_t* bus = nullptr; +- const uint64_t* address = nullptr; ++ std::shared_ptr<uint64_t> bus = nullptr; ++ std::shared_ptr<uint64_t> address = nullptr; + const nlohmann::json::array_t* channels = nullptr; + + for (auto keyPair = configuration.begin(); keyPair != configuration.end(); +@@ -144,11 +281,13 @@ void exportDevice(const std::string& type, + + if (keyPair.key() == "Bus") + { +- bus = keyPair.value().get_ptr<const uint64_t*>(); ++ bus = std::make_shared<uint64_t>( ++ *keyPair.value().get_ptr<const uint64_t*>()); + } + else if (keyPair.key() == "Address") + { +- address = keyPair.value().get_ptr<const uint64_t*>(); ++ address = std::make_shared<uint64_t>( ++ *keyPair.value().get_ptr<const uint64_t*>()); + } + else if (keyPair.key() == "ChannelNames") + { +@@ -157,49 +296,14 @@ void exportDevice(const std::string& type, + } + boost::replace_all(parameters, TEMPLATE_CHAR + keyPair.key(), + subsituteString); +- boost::replace_all(device, TEMPLATE_CHAR + keyPair.key(), ++ boost::replace_all(devicePath, TEMPLATE_CHAR + keyPair.key(), + subsituteString); + } + +- // if we found bus and address we can attempt to prevent errors +- if (bus != nullptr && address != nullptr) +- { +- std::ostringstream hex; +- hex << std::hex << *address; +- const std::string& addressHex = hex.str(); +- std::string busStr = std::to_string(*bus); ++ int err = buildDevice(devicePath, parameters, bus, address, constructor, ++ destructor, createsHWMon); + +- std::filesystem::path devicePath(device); +- std::filesystem::path parentPath = devicePath.parent_path(); +- if (std::filesystem::is_directory(parentPath)) +- { +- for (const auto& path : +- std::filesystem::directory_iterator(parentPath)) +- { +- if (!std::filesystem::is_directory(path)) +- { +- continue; +- } +- +- const std::string& directoryName = path.path().filename(); +- if (boost::starts_with(directoryName, busStr) && +- boost::ends_with(directoryName, addressHex)) +- { +- return; // already exported +- } +- } +- } +- } +- +- std::ofstream deviceFile(device); +- if (!deviceFile.good()) +- { +- std::cerr << "Error writing " << device << "\n"; +- return; +- } +- deviceFile << parameters; +- deviceFile.close(); +- if (boost::ends_with(type, "Mux") && bus && address && channels) ++ if (!err && boost::ends_with(type, "Mux") && bus && address && channels) + { + linkMux(name, static_cast<size_t>(*bus), static_cast<size_t>(*address), + *channels); +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0002-Entity-manager-Add-support-to-update-assetTag.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0002-Entity-manager-Add-support-to-update-assetTag.patch new file mode 100644 index 000000000..0fea3e8a0 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0002-Entity-manager-Add-support-to-update-assetTag.patch @@ -0,0 +1,176 @@ +From 0941036f4206d74bfc3d3e505a5d269fb39c48ff Mon Sep 17 00:00:00 2001 +From: mansijos <mansi.joshi@intel.com> +Date: Tue, 6 Apr 2021 02:12:56 +0530 +Subject: [PATCH] Entity-manager: Add support to update assetTag + +Asset tag is an updateable property from User level interface like +Redfish. User-level interface will update Asset tag in entity-manager, +which will further update the needed FRU interface property exposed. + +Tested: +Successfully updated in assetTag interface as well as in fru interface +while using set-property and using redfish as well. +The new value is preserved after BMC resets. + +Change-Id: If7fbfd8325488280f500ab0e2c8b38475813cc3f +Signed-off-by: mansijos <mansi.joshi@intel.com> +--- + src/EntityManager.cpp | 95 +++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 91 insertions(+), 4 deletions(-) + +diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp +index 490c0f5..139ba9a 100644 +--- a/src/EntityManager.cpp ++++ b/src/EntityManager.cpp +@@ -48,9 +48,19 @@ constexpr const char* lastConfiguration = "/tmp/configuration/last.json"; + constexpr const char* currentConfiguration = "/var/configuration/system.json"; + constexpr const char* globalSchema = "global.json"; + constexpr const int32_t maxMapperDepth = 0; ++constexpr const char* foundObject = "FoundProbe"; + + constexpr const bool debug = false; + ++ ++ ++using foundProbeData = std::map<std::string, std::string>; ++static foundProbeData foundData; ++static std::map<std::string, foundProbeData> mapFoundData; ++ ++constexpr const char* fruConn = "xyz.openbmc_project.FruDevice"; ++constexpr const char* fruIntf = "xyz.openbmc_project.FruDevice"; ++ + struct CmpStr + { + bool operator()(const char* a, const char* b) const +@@ -577,6 +587,43 @@ void addArrayToDbus(const std::string& name, const nlohmann::json& array, + } + } + ++template <typename PropertyType> ++bool persistAssetTag(const PropertyType& newVal, ++ const std::string& jsonPointerString) ++{ ++ std::size_t found = jsonPointerString.find_last_of("/\\"); ++ std::string jsonPointerPath = jsonPointerString.substr(0, found); ++ ++ auto it = mapFoundData.find(jsonPointerPath); ++ if (it == mapFoundData.end()) ++ { ++ std::cerr << "Error in finding jsonPointerPath in mapFoundData" ++ << "\n"; ++ return false; ++ } ++ ++ foundProbeData& tmpMap = it->second; ++ auto foundPath = tmpMap.find("foundPath"); ++ if (foundPath == tmpMap.end()) ++ { ++ std::cerr << "No prob object data is avaliable in foundProbeData" ++ << "\n"; ++ return false; ++ } ++ ++ systemBus->async_method_call( ++ [](const boost::system::error_code& ec) { ++ if (ec) ++ { ++ std::cerr << "Error setting AssetTag in FRU interface " << ec ++ << "\n"; ++ } ++ }, ++ fruConn, foundPath->second, "org.freedesktop.DBus.Properties", "Set", ++ fruIntf, "PRODUCT_ASSET_TAG", std::variant<PropertyType>(newVal)); ++ return true; ++} ++ + template <typename PropertyType> + void addProperty(const std::string& propertyName, const PropertyType& value, + sdbusplus::asio::dbus_interface* iface, +@@ -591,9 +638,18 @@ void addProperty(const std::string& propertyName, const PropertyType& value, + } + iface->register_property( + propertyName, value, +- [&systemConfiguration, ++ [propertyName, &systemConfiguration, + jsonPointerString{std::string(jsonPointerString)}]( + const PropertyType& newVal, PropertyType& val) { ++ if (propertyName == "AssetTag") ++ { ++ if (!persistAssetTag(newVal, jsonPointerString)) ++ { ++ std::cerr << "error setting AssetTag in FRU interface\n"; ++ return -1; ++ } ++ } ++ + val = newVal; + if (!setJsonFromPointer(jsonPointerString, val, + systemConfiguration)) +@@ -993,6 +1049,9 @@ void postToDbus(const nlohmann::json& newConfiguration, + populateInterfaceFromJson(systemConfiguration, jsonPointerPath, + boardIface, boardValues, objServer); + jsonPointerPath += "/"; ++ ++ std::string foundPath; ++ + // iterate through board properties + for (auto& boardField : boardValues.items()) + { +@@ -1002,9 +1061,28 @@ void postToDbus(const nlohmann::json& newConfiguration, + createInterface(objServer, boardName, boardField.key(), + boardKeyOrig); + +- populateInterfaceFromJson(systemConfiguration, +- jsonPointerPath + boardField.key(), +- iface, boardField.value(), objServer); ++ if (boardField.key() == "FoundProbe") ++ { ++ foundPath = boardField.value()["Path"]; ++ } ++ if (boardField.key() == ++ "xyz.openbmc_project.Inventory.Decorator.AssetTag") ++ { ++ foundData["foundPath"] = foundPath; ++ mapFoundData[jsonPointerPath + boardField.key()] = ++ foundData; ++ ++ populateInterfaceFromJson( ++ systemConfiguration, jsonPointerPath + boardField.key(), ++ iface, boardField.value(), objServer, ++ sdbusplus::asio::PropertyPermission::readWrite); ++ } ++ else ++ { ++ populateInterfaceFromJson( ++ systemConfiguration, jsonPointerPath + boardField.key(), ++ iface, boardField.value(), objServer); ++ } + } + } + +@@ -1362,6 +1440,11 @@ void PerformScan::run() + { + continue; // non-numeric replacement + } ++ ++ nlohmann::json recordVal = *recordPtr; ++ // Save the dbus path info of the device ++ recordVal[foundObject]["Path"] = std::get<1>(*itr); ++ + usedNames.insert(nameIt.value()); + auto usedIt = std::find(indexes.begin(), + indexes.end(), index); +@@ -1439,6 +1522,10 @@ void PerformScan::run() + } + } + ++ // Save the dbus path info of the device ++ record[foundObject]["Path"] = ++ std::get<1>(foundDeviceAndPath); ++ + if (replaceStr) + { + std::cerr << "Duplicates found, replacing " +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0003-Add-logs-to-fwVersionIsSame.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0003-Add-logs-to-fwVersionIsSame.patch new file mode 100644 index 000000000..94af67967 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0003-Add-logs-to-fwVersionIsSame.patch @@ -0,0 +1,56 @@ +From 28525b56161e1b659e85e85c33fc00dc397758aa Mon Sep 17 00:00:00 2001 +From: Helen Huang <he.huang@intel.com> +Date: Mon, 19 Apr 2021 16:06:15 +0800 +Subject: [PATCH] Add logs to fwVersionIsSame() + +Add logs to fwVersionIsSame() to indicate whether the firmware +version is changed or not. + +Tested: +Logs are printed as expected when firmware updating and BMC rebooting. + +Log of rebooting: +The firmware version is similiar as the last boot, +Hash value of versionFile is:3336889560 + +Log of Firmware update: +The firmware version is changed since the last boot, +hash value of current versionFile is:3336889560, +hash value of versionFile of last boot is:834871226 + +Change-Id: I5306917329d2e2e015af58cad1e9c59881f0b217 +Signed-off-by: Helen Huang <he.huang@intel.com> +--- + include/Utils.hpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/include/Utils.hpp b/include/Utils.hpp +index 657af92..8238807 100644 +--- a/include/Utils.hpp ++++ b/include/Utils.hpp +@@ -116,13 +116,22 @@ inline bool fwVersionIsSame(void) + + if (expectedHash == hashString) + { ++ std::cout << "The firmware version is similiar as the last boot, " ++ "hash value of versionFile is:" ++ << hashString.c_str() << "\n"; + return true; + } ++ std::cout << "The firmware version is changed since the last boot, hash " ++ "value of current versionFile is:" ++ << expectedHash.c_str() ++ << ", hash value of versionFile of last boot is:" ++ << hashString.c_str() << "\n"; + hashFile.close(); + } + + std::ofstream output(versionHashFile); + output << expectedHash; ++ + return false; + } + +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0004-Adding-MUX-and-Drives-present-in-HSBP-in-json-config.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0004-Adding-MUX-and-Drives-present-in-HSBP-in-json-config.patch new file mode 100644 index 000000000..4f6679dde --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0004-Adding-MUX-and-Drives-present-in-HSBP-in-json-config.patch @@ -0,0 +1,149 @@ +From 95a1f9e5f65d35adc3cf8d3b3095d92b63c17f85 Mon Sep 17 00:00:00 2001 +From: AKSHAY RAVEENDRAN K <akshay.raveendran.k@intel.com> +Date: Sun, 20 Jun 2021 18:22:34 +0000 +Subject: [PATCH] Add MUX and Drives present in HSBP in json configuration + +Added Mux addresses for all 3 HSBP configuration and the drive +names to be exposed via entity manager when the HSBP is connected + +Added board instance to separate each HSBP board. + +Tested: +After this addition, detected the MUXes in entity manager +tree as well as in /dev/i2c-mux location. Also able to detect +the drive address. + +Change-Id: Ic07e3880cf5b6f8a47ee7b8f1f98e12042765da8 +Signed-off-by: AKSHAY RAVEENDRAN K <akshay.raveendran.k@intel.com> + +--- + configurations/F2U8X25 HSBP.json | 78 ++++++++++++++++++++++++++++++-- + 1 file changed, 75 insertions(+), 3 deletions(-) + +diff --git a/configurations/F2U8X25 HSBP.json b/configurations/F2U8X25 HSBP.json +index c6c7678..e2eedfa 100644 +--- a/configurations/F2U8X25 HSBP.json ++++ b/configurations/F2U8X25 HSBP.json +@@ -7,6 +7,30 @@ + "Name": "F2U8X25 HSBP1 FRU", + "Type": "EEPROM" + }, ++ { ++ "Address": "0x70", ++ "Bus": "$bus", ++ "ChannelNames": [ ++ "Drive_1", ++ "Drive_2", ++ "Drive_3", ++ "Drive_4" ++ ], ++ "Name": "Drive Mux 1", ++ "Type": "PCA9546Mux" ++ }, ++ { ++ "Address": "0x74", ++ "Bus": "$bus", ++ "ChannelNames": [ ++ "Drive_5", ++ "Drive_6", ++ "Drive_7", ++ "Drive_8" ++ ], ++ "Name": "Drive Mux 2", ++ "Type": "PCA9546Mux" ++ }, + { + "Address": "0x48", + "Bus": "$bus", +@@ -40,7 +64,7 @@ + "Type": "TMP75" + } + ], +- "Name": "F2U8X25 HSBP", ++ "Name": "F2U8X25 HSBP 1", + "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'F2U8X25PCIHSBP', 'ADDRESS': 80})", + "Type": "Board", + "xyz.openbmc_project.Inventory.Decorator.Asset": { +@@ -58,6 +82,30 @@ + "Name": "F2U8X25 HSBP2 FRU", + "Type": "EEPROM" + }, ++ { ++ "Address": "0x73", ++ "Bus": "$bus", ++ "ChannelNames": [ ++ "Drive_9", ++ "Drive_10", ++ "Drive_11", ++ "Drive_12" ++ ], ++ "Name": "Drive Mux 3", ++ "Type": "PCA9546Mux" ++ }, ++ { ++ "Address": "0x77", ++ "Bus": "$bus", ++ "ChannelNames": [ ++ "Drive_13", ++ "Drive_14", ++ "Drive_15", ++ "Drive_16" ++ ], ++ "Name": "Drive Mux 4", ++ "Type": "PCA9546Mux" ++ }, + { + "Address": "0x4B", + "Bus": "$bus", +@@ -91,7 +139,7 @@ + "Type": "TMP75" + } + ], +- "Name": "F2U8X25 HSBP", ++ "Name": "F2U8X25 HSBP 2", + "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'F2U8X25PCIHSBP', 'ADDRESS': 83})", + "Type": "Board", + "xyz.openbmc_project.Inventory.Decorator.Asset": { +@@ -109,6 +157,30 @@ + "Name": "F2U8X25 HSBP3 FRU", + "Type": "EEPROM" + }, ++ { ++ "Address": "0x72", ++ "Bus": "$bus", ++ "ChannelNames": [ ++ "Drive_17", ++ "Drive_18", ++ "Drive_19", ++ "Drive_20" ++ ], ++ "Name": "Drive Mux 5", ++ "Type": "PCA9546Mux" ++ }, ++ { ++ "Address": "0x76", ++ "Bus": "$bus", ++ "ChannelNames": [ ++ "Drive_21", ++ "Drive_22", ++ "Drive_23", ++ "Drive_24" ++ ], ++ "Name": "Drive Mux 6", ++ "Type": "PCA9546Mux" ++ }, + { + "Address": "0x4A", + "Bus": "$bus", +@@ -142,7 +214,7 @@ + "Type": "TMP75" + } + ], +- "Name": "F2U8X25 HSBP", ++ "Name": "F2U8X25 HSBP 3", + "Probe": "xyz.openbmc_project.FruDevice({'BOARD_PRODUCT_NAME': 'F2U8X25PCIHSBP', 'ADDRESS': 82})", + "Type": "Board", + "xyz.openbmc_project.Inventory.Decorator.Asset": { +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0005-Allow-MUX-idle-state-to-be-configured-as-DISCONNECT.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0005-Allow-MUX-idle-state-to-be-configured-as-DISCONNECT.patch new file mode 100644 index 000000000..ac0995614 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/configuration/entity-manager/0005-Allow-MUX-idle-state-to-be-configured-as-DISCONNECT.patch @@ -0,0 +1,131 @@ +From aada39602a21e83d7e8c39c39fb8c5c32122863c Mon Sep 17 00:00:00 2001 +From: AKSHAY RAVEENDRAN K <akshay.raveendran.k@intel.com> +Date: Thu, 2 Sep 2021 11:11:40 +0000 +Subject: [PATCH] Allow MUX idle state to be configured as DISCONNECT + +The existing Linux behavior is to leave the Mux status as it is after +an operation. In HSBP and in other places we have more than one MUX +parallel in same root bus. The existing behavior will result in reading +multiple buses of different MUXes at the same time and causes bad read. +In this fix, we can configure "MuxIdleMode" as "Disconnect" in +configuration file as shown below + +{ + "Address": "0x70", + "Bus": "$bus", + "ChannelNames": [ + "Drive_1", + "Drive_2", + "Drive_3", + "Drive_4" + ], + "MuxIdleMode": "Disconnect", + "Name": "Drive Mux 1", + "Type": "PCA9546Mux" + +Tested: +Set the MUX idle mode to Disconnect in MUXes present in HSBP board and +only one channel is read at a time. + +Change-Id: I6d29cd3be350682c386bd3072e76b930a7d45587 +Signed-off-by: AKSHAY RAVEENDRAN K <akshay.raveendran.k@intel.com> +--- + src/Overlay.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 52 insertions(+), 3 deletions(-) + +diff --git a/src/Overlay.cpp b/src/Overlay.cpp +index 4454423..2843c31 100644 +--- a/src/Overlay.cpp ++++ b/src/Overlay.cpp +@@ -38,11 +38,46 @@ constexpr const char* outputDir = "/tmp/overlays"; + constexpr const char* templateChar = "$"; + constexpr const char* i2CDevsDir = "/sys/bus/i2c/devices"; + constexpr const char* muxSymlinkDir = "/dev/i2c-mux"; ++constexpr const char* idleModeAsIs = "-1"; ++constexpr const char* idleModeDisconnect = "-2"; + + constexpr const bool debug = false; + + std::regex illegalNameRegex("[^A-Za-z0-9_]"); + ++void setIdleMode(const std::string& muxName, size_t busIndex, size_t address, ++ const std::string& idleMode) ++{ ++ std::error_code ec; ++ ++ std::ostringstream hexAddress; ++ hexAddress << std::hex << std::setfill('0') << std::setw(4) << address; ++ ++ std::filesystem::path idlePath(i2CDevsDir); ++ idlePath /= ++ std::to_string(busIndex) + "-" + hexAddress.str() + "/idle_state"; ++ ++ std::string modeData = ++ (idleMode == "Disconnect") ? idleModeDisconnect : idleModeAsIs; ++ ++ if (debug) ++ { ++ std::cerr << "Setting " << muxName << " idle state to " << modeData ++ << " in " << idlePath << "\n"; ++ } ++ ++ std::ofstream idleFile(idlePath); ++ if (!idleFile.good()) ++ { ++ std::cerr << "Can't set idle mode in " << idlePath << " for " << muxName ++ << "\n"; ++ } ++ else ++ { ++ idleFile << modeData; ++ } ++} ++ + // helper function to make json types into string + std::string jsonToString(const nlohmann::json& in) + { +@@ -285,6 +320,7 @@ void exportDevice(const std::string& type, + std::shared_ptr<uint64_t> bus = nullptr; + std::shared_ptr<uint64_t> address = nullptr; + const nlohmann::json::array_t* channels = nullptr; ++ std::string idleMode; + + for (auto keyPair = configuration.begin(); keyPair != configuration.end(); + keyPair++) +@@ -318,6 +354,11 @@ void exportDevice(const std::string& type, + channels = + keyPair.value().get_ptr<const nlohmann::json::array_t*>(); + } ++ else if (keyPair.key() == "MuxIdleMode") ++ { ++ idleMode = keyPair.value().get<std::string>(); ++ } ++ + boost::replace_all(parameters, templateChar + keyPair.key(), + subsituteString); + boost::replace_all(devicePath, templateChar + keyPair.key(), +@@ -327,10 +368,18 @@ void exportDevice(const std::string& type, + int err = buildDevice(devicePath, parameters, bus, address, constructor, + destructor, createsHWMon); + +- if (!err && boost::ends_with(type, "Mux") && bus && address && channels) ++ if (!err && boost::ends_with(type, "Mux") && bus && address) + { +- linkMux(name, static_cast<size_t>(*bus), static_cast<size_t>(*address), +- *channels); ++ if (channels) ++ { ++ linkMux(name, static_cast<size_t>(*bus), ++ static_cast<size_t>(*address), *channels); ++ } ++ if (!idleMode.empty()) ++ { ++ setIdleMode(name, static_cast<size_t>(*bus), ++ static_cast<size_t>(*address), idleMode); ++ } + } + } + +-- +2.17.1 + |