blob: 95e4d127b1dda7364f52903fca6cfdc327d5d3d3 [file] [log] [blame]
Willy Tua2056e92021-10-10 13:36:16 -07001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Patrick Ventureab650002019-03-16 09:08:47 -070015#include "util.hpp"
16
Patrick Williams444b5ea2023-05-19 13:56:42 -050017#include <nlohmann/json.hpp>
18#include <phosphor-logging/elog-errors.hpp>
19#include <xyz/openbmc_project/Common/error.hpp>
20
Patrick Venture3fb74292019-03-16 11:32:16 -070021#include <cstdint>
Patrick Venture8d5c9ce2019-03-16 11:20:12 -070022#include <cstdio>
Patrick Venture3fb74292019-03-16 11:32:16 -070023#include <filesystem>
Patrick Ventureab650002019-03-16 09:08:47 -070024#include <fstream>
Patrick Venture3fb74292019-03-16 11:32:16 -070025#include <regex>
Patrick Ventureab650002019-03-16 09:08:47 -070026#include <string>
Patrick Venture3fb74292019-03-16 11:32:16 -070027#include <tuple>
28#include <vector>
Patrick Ventureab650002019-03-16 09:08:47 -070029
30namespace google
31{
32namespace ipmi
33{
Patrick Venture3fb74292019-03-16 11:32:16 -070034namespace fs = std::filesystem;
Patrick Ventureab650002019-03-16 09:08:47 -070035using namespace phosphor::logging;
36using InternalFailure =
37 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
38
39nlohmann::json parseConfig(const std::string& file)
40{
41 std::ifstream jsonFile(file);
42 if (!jsonFile.is_open())
43 {
44 log<level::ERR>("Entity association JSON file not found");
45 elog<InternalFailure>();
46 }
47
48 auto data = nlohmann::json::parse(jsonFile, nullptr, false);
49 if (data.is_discarded())
50 {
51 log<level::ERR>("Entity association JSON parser failure");
52 elog<InternalFailure>();
53 }
54
55 return data;
56}
57
Patrick Venture8d5c9ce2019-03-16 11:20:12 -070058std::string readPropertyFile(const std::string& fileName)
59{
60 std::ifstream ifs(fileName);
61 std::string contents;
62
63 if (!ifs.is_open())
64 {
Yunyun Lin86598512022-02-11 10:41:56 -080065 auto msg = std::string("Unable to open file ") + fileName.c_str();
66 log<level::DEBUG>(msg.c_str());
Patrick Venture8d5c9ce2019-03-16 11:20:12 -070067 }
68 else
69 {
70 if (ifs >> contents)
71 {
72 // If the last character is a null terminator; remove it.
73 if (!contents.empty())
74 {
Patrick Williams444b5ea2023-05-19 13:56:42 -050075 const char& back = contents.back();
Patrick Venture8d5c9ce2019-03-16 11:20:12 -070076 if (back == '\0')
77 contents.pop_back();
78 }
79
80 return contents;
81 }
82 else
83 {
84 std::fprintf(stderr, "Unable to read file %s.\n", fileName.c_str());
85 }
86 }
87
88 return "";
89}
90
Patrick Venture3fb74292019-03-16 11:32:16 -070091std::vector<std::tuple<std::uint32_t, std::string>> buildPcieMap()
92{
93 std::vector<std::tuple<std::uint32_t, std::string>> pcie_i2c_map;
94
95 // Build a vector with i2c bus to pcie slot mapping.
96 // Iterate through all the devices under "/sys/bus/i2c/devices".
97 for (const auto& i2c_dev : fs::directory_iterator("/sys/bus/i2c/devices"))
98 {
99 std::string i2c_dev_path = i2c_dev.path();
100 std::smatch i2c_dev_string_number;
101 std::regex e("(i2c-)(\\d+)");
102
103 // Check if the device has "i2c-" in its path.
104 if (std::regex_search(i2c_dev_path, i2c_dev_string_number, e))
105 {
106 // Check if the i2c device has "pcie-slot" file under "of-node" dir.
107 std::string pcie_slot_path = i2c_dev_path + "/of_node/pcie-slot";
108 std::string pcie_slot;
109
110 // Read the "pcie-slot" name from the "pcie-slot" file.
111 pcie_slot = readPropertyFile(pcie_slot_path);
112 if (pcie_slot.empty())
113 {
114 continue;
115 }
116 std::string pcie_slot_name;
117 std::string pcie_slot_full_path;
118
119 // Append the "pcie-slot" name to dts base.
120 pcie_slot_full_path.append("/proc/device-tree");
121 pcie_slot_full_path.append(pcie_slot);
122
123 // Read the "label" which contains the pcie slot name.
124 pcie_slot_full_path.append("/label");
125 pcie_slot_name = readPropertyFile(pcie_slot_full_path);
126
127 if (pcie_slot_name.empty())
128 {
129 continue;
130 }
131
132 // Get the i2c bus number from the i2c device path.
133 std::uint32_t i2c_bus_number =
134 i2c_dev_string_number[2].matched
135 ? std::stoi(i2c_dev_string_number[2])
136 : 0;
137 // Store the i2c bus number and the pcie slot name in the vector.
138 pcie_i2c_map.push_back(
139 std::make_tuple(i2c_bus_number, pcie_slot_name));
140 }
141 }
142
143 return pcie_i2c_map;
144}
145
Patrick Ventureab650002019-03-16 09:08:47 -0700146} // namespace ipmi
147} // namespace google