// Copyright 2021 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "util.hpp" #include #include #include #include #include #include #include #include #include #include #include #include namespace google { namespace ipmi { namespace fs = std::filesystem; using namespace phosphor::logging; using InternalFailure = sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; nlohmann::json parseConfig(const std::string& file) { std::ifstream jsonFile(file); if (!jsonFile.is_open()) { log("Entity association JSON file not found"); elog(); } auto data = nlohmann::json::parse(jsonFile, nullptr, false); if (data.is_discarded()) { log("Entity association JSON parser failure"); elog(); } return data; } std::string readPropertyFile(const std::string& fileName) { std::ifstream ifs(fileName); std::string contents; if (!ifs.is_open()) { auto msg = std::string("Unable to open file ") + fileName.c_str(); log(msg.c_str()); } else { if (ifs >> contents) { // If the last character is a null terminator; remove it. if (!contents.empty()) { const char& back = contents.back(); if (back == '\0') contents.pop_back(); } return contents; } else { stdplus::print(stderr, "Unable to read file {}.\n", fileName); } } return ""; } std::vector> buildPcieMap() { std::vector> pcie_i2c_map; // Build a vector with i2c bus to pcie slot mapping. // Iterate through all the devices under "/sys/bus/i2c/devices". for (const auto& i2c_dev : fs::directory_iterator("/sys/bus/i2c/devices")) { std::string i2c_dev_path = i2c_dev.path(); std::smatch i2c_dev_string_number; std::regex e("(i2c-)(\\d+)"); // Check if the device has "i2c-" in its path. if (std::regex_search(i2c_dev_path, i2c_dev_string_number, e)) { // Check if the i2c device has "pcie-slot" file under "of-node" dir. std::string pcie_slot_path = i2c_dev_path + "/of_node/pcie-slot"; std::string pcie_slot; // Read the "pcie-slot" name from the "pcie-slot" file. pcie_slot = readPropertyFile(pcie_slot_path); if (pcie_slot.empty()) { continue; } std::string pcie_slot_name; std::string pcie_slot_full_path; // Append the "pcie-slot" name to dts base. pcie_slot_full_path.append("/proc/device-tree"); pcie_slot_full_path.append(pcie_slot); // Read the "label" which contains the pcie slot name. pcie_slot_full_path.append("/label"); pcie_slot_name = readPropertyFile(pcie_slot_full_path); if (pcie_slot_name.empty()) { continue; } // Get the i2c bus number from the i2c device path. std::uint32_t i2c_bus_number = i2c_dev_string_number[2].matched ? std::stoi(i2c_dev_string_number[2]) : 0; // Store the i2c bus number and the pcie slot name in the vector. pcie_i2c_map.push_back( std::make_tuple(i2c_bus_number, pcie_slot_name)); } } return pcie_i2c_map; } } // namespace ipmi } // namespace google