1 #pragma once
2 
3 #include <filesystem>
4 #include <nlohmann/json.hpp>
5 #include <string>
6 #include <tuple>
7 #include <vector>
8 
9 /**
10  * @file device_callouts.hpp
11  *
12  * @brief Looks up FRU callouts, which are D-Bus inventory paths,
13  * in JSON for device sysfs paths.
14  *
15  * The code will extract the search keys from the sysfs path to
16  * use to look up the callout list in the JSON.  The callouts will
17  * be sorted by priority as defined in th PEL spec.
18  *
19  * The JSON is normally generated from the MRW, and contains
20  * sections for the following types of callouts:
21  *   * I2C  (also based on bus/addr as well as the path)
22  *   * FSI
23  *   * FSI-I2C
24  *   * FSI-SPI
25  *
26  * The JSON looks like:
27  *
28  * "I2C":
29  *   "<bus>":
30  *     "<address>":
31  *       "Callouts": [
32  *          {
33  *             "LocationCode": "<location code>",
34  *             "Name": "<inventory path>",
35  *             "Priority": "<priority=H/M/L>",
36  *             "MRU": "<optional MRU name>"
37  *          },
38  *          ...
39  *       ],
40  *       "Dest": "<destination MRW target>"
41  *
42  * "FSI":
43  *   "<fsi link>":
44  *     "Callouts": [
45  *            ...
46  *     ],
47  *     "Dest": "<destination MRW target>"
48  *
49  * "FSI-I2C":
50  *    "<fsi link>":
51  *      "<bus>":
52  *        "<address>":
53  *            "Callouts": [
54  *                   ...
55  *             ],
56  *            "Dest": "<destination MRW target>"
57  *
58  * "FSI-SPI":
59  *    "<fsi link>":
60  *      "<bus>":
61  *         "Callouts": [
62  *                ...
63  *         ],
64  *         "Dest": "<destination MRW target>"
65  *
66  */
67 
68 namespace openpower::pels::device_callouts
69 {
70 
71 /**
72  * @brief Represents a callout in the device JSON.
73  *
74  * The debug field will only be filled in for the first
75  * callout in the list of them and contains additional
76  * information about what happened when looking up the
77  * callouts that is meant to aid in debug.
78  */
79 struct Callout
80 {
81     std::string priority;
82     std::string locationCode;
83     std::string name;
84     std::string mru;
85     std::string debug;
86 };
87 
88 /**
89  * @brief Looks up the callouts in a JSON File to add to a PEL
90  *        for when the path between the BMC and the device specified
91  *        by the passed in device path needs to be called out.
92  *
93  * The path is the path used to access the device in sysfs.  It
94  * can be either a directory path or a file path.
95  *
96  * @param[in] devPath - The device path
97  * @param[in] compatibleList - The list of compatible names for this
98  *                             system.
99  * @return std::vector<Callout> - The list of callouts
100  */
101 std::vector<Callout>
102     getCallouts(const std::string& devPath,
103                 const std::vector<std::string>& compatibleList);
104 
105 /**
106  * @brief Looks up the callouts to add to a PEL for when the path
107  *        between the BMC and the device specified by the passed in
108  *        I2C bus and address needs to be called out.
109  *
110  * @param[in] i2cBus - The I2C bus
111  * @param[in] i2cAddress - The I2C address
112  * @param[in] compatibleList - The list of compatible names for this
113  *                             system.
114  * @return std::vector<Callout> - The list of callouts
115  */
116 std::vector<Callout>
117     getI2CCallouts(size_t i2cBus, uint8_t i2cAddress,
118                    const std::vector<std::string>& compatibleList);
119 
120 namespace util
121 {
122 
123 /**
124  * @brief The different callout path types
125  */
126 enum class CalloutType
127 {
128     i2c,
129     fsi,
130     fsii2c,
131     fsispi,
132     unknown
133 };
134 
135 /**
136  * @brief Returns the path to the JSON file to look up callouts in.
137  *
138  * @param[in] compatibleList - The list of compatible names for this
139  *                             system.
140  *
141  * @return path - The path to the file.
142  */
143 std::filesystem::path
144     getJSONFilename(const std::vector<std::string>& compatibleList);
145 
146 /**
147  * @brief Looks up the callouts in the JSON using the I2C keys.
148  *
149  * @param[in] i2cBus - The I2C bus
150  * @param[in] i2cAddress - The I2C address
151  * @param[in] calloutJSON - The JSON containing the callouts
152  *
153  * @return std::vector<Callout> - The callouts
154  */
155 std::vector<device_callouts::Callout>
156     calloutI2C(size_t i2CBus, uint8_t i2cAddress,
157                const nlohmann::json& calloutJSON);
158 
159 /**
160  * @brief Determines the type of the path (FSI, I2C, etc) based
161  *        on tokens in the device path.
162  *
163  * @param[in] devPath - The device path
164  *
165  * @return CalloutType - The callout type
166  */
167 CalloutType getCalloutType(const std::string& devPath);
168 
169 /**
170  * @brief Pulls the fields out of the I2C device path to use as search keys
171  *        in the JSON.
172  *
173  * The keys are the I2C bus and address.
174  *
175  * @param[in] devPath - The device path
176  *
177  * @return std::tuple<size_t, uint8_t> - The I2C bus and address keys
178  */
179 std::tuple<size_t, uint8_t> getI2CSearchKeys(const std::string& devPath);
180 
181 /**
182  * @brief Pulls the fields out of the FSI device path to use as search keys
183  *        in the JSON.
184  *
185  * The key is the FSI link.  For multi-hop paths, the links are
186  * separated by '-'s, like "0-1-2".
187  *
188  * @param[in] devPath - The device path
189  *
190  * @return std::string - The FSI links key
191  */
192 std::string getFSISearchKeys(const std::string& devPath);
193 
194 /**
195  * @brief Pulls the fields out of the FSI-I2C device path to use as
196  *        search keys in the JSON.
197  *
198  * The keys are the FSI link string and the  I2C bus and address.
199  *
200  * @param[in] devPath - The device path
201  *
202  * @return std::tuple<std::string, std::tuple<size_t, uint8_t>>
203  *         - The FSI links key along with the I2C bus/address.
204  */
205 std::tuple<std::string, std::tuple<size_t, uint8_t>>
206     getFSII2CSearchKeys(const std::string& devPath);
207 
208 /**
209  * @brief Pulls the fields out of the SPI device path to use as search keys
210  *        in the JSON.
211  *
212  * The key is the SPI bus number.
213  *
214  * @param[in] devPath - The device path
215  *
216  * @return size_t - The SPI bus key
217  */
218 size_t getSPISearchKeys(const std::string& devPath);
219 
220 /**
221  * @brief Pulls the fields out of the FSI-SPI device path to use as
222  *        search keys in the JSON.
223  *
224  * The keys are the FSI link string and the SPI bus number.
225  *
226  * @param[in] devPath - The device path
227  *
228  * @return std::tuple<std::string, size_t>
229  *         - The FSI links key along with the SPI bus number.
230  */
231 std::tuple<std::string, size_t> getFSISPISearchKeys(const std::string& devPath);
232 
233 } // namespace util
234 } // namespace openpower::pels::device_callouts
235