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