blob: 3550e1f099825fcc68c0e2fc4d861fdcdd58a361 [file] [log] [blame]
Jayanth Othayoth4d779b22021-06-03 05:45:13 -05001extern "C" {
2#include <libpdbg.h>
3}
4
5#include "fapi_data_process.hpp"
6
7#include <attributes_info.H>
8#include <fmt/format.h>
9
10#include <algorithm>
11#include <cstdlib>
12#include <cstring>
13#include <iomanip>
14#include <list>
15#include <map>
16#include <phosphor-logging/elog.hpp>
17#include <sstream>
18#include <string>
19
20namespace openpower
21{
22namespace pels
23{
24namespace phal
25{
26
27using namespace phosphor::logging;
28
29/**
30 * Used to pass buffer to pdbg callback api to get required target
31 * data (attributes) based on given data (attribute).
32 */
33struct TargetInfo
34{
35 ATTR_PHYS_BIN_PATH_Type physBinPath;
36 ATTR_LOCATION_CODE_Type locationCode;
37 ATTR_PHYS_DEV_PATH_Type physDevPath;
38 ATTR_MRU_ID_Type mruId;
39
40 bool deconfigure;
41
42 TargetInfo()
43 {
44 memset(&physBinPath, '\0', sizeof(physBinPath));
45 memset(&locationCode, '\0', sizeof(locationCode));
46 memset(&physDevPath, '\0', sizeof(physDevPath));
47 mruId = 0;
48 deconfigure = false;
49 }
50};
51
52/**
53 * Used to return in callback function which are used to get
54 * physical path value and it binary format value.
55 *
56 * The value for constexpr defined based on pdbg_target_traverse function usage.
57 */
58constexpr int continueTgtTraversal = 0;
59constexpr int requireAttrFound = 1;
60constexpr int requireAttrNotFound = 2;
61
62/**
63 * @brief Used to get target location code from phal device tree
64 *
65 * @param[in] target current device tree target
66 * @param[out] appPrivData used for accessing|storing from|to application
67 *
68 * @return 0 to continue traverse, non-zero to stop traverse
69 */
70int pdbgCallbackToGetTgtReqAttrsVal(struct pdbg_target* target,
71 void* appPrivData)
72{
73 TargetInfo* targetInfo = static_cast<TargetInfo*>(appPrivData);
74
75 ATTR_PHYS_BIN_PATH_Type physBinPath;
76 /**
77 * TODO: Issue: phal/pdata#16
78 * Should not use direct pdbg api to read attribute. Need to use DT_GET_PROP
79 * macro for bmc app's and this will call libdt-api api but, it will print
80 * "pdbg_target_get_attribute failed" trace if attribute is not found and
81 * this callback will call recursively by using pdbg_target_traverse() until
82 * find expected attribute based on return code from this callback. Because,
83 * need to do target iteration to get actual attribute (ATTR_PHYS_BIN_PATH)
84 * value when device tree target info doesn't know to read attribute from
85 * device tree. So, Due to this error trace user will get confusion while
86 * looking traces. Hence using pdbg api to avoid trace until libdt-api
87 * provides log level setup.
88 */
89 if (!pdbg_target_get_attribute(
90 target, "ATTR_PHYS_BIN_PATH",
91 std::stoi(dtAttr::fapi2::ATTR_PHYS_BIN_PATH_Spec),
92 dtAttr::fapi2::ATTR_PHYS_BIN_PATH_ElementCount, physBinPath))
93 {
94 return continueTgtTraversal;
95 }
96
97 if (std::memcmp(physBinPath, targetInfo->physBinPath,
98 sizeof(physBinPath)) != 0)
99 {
100 return continueTgtTraversal;
101 }
102
103 if (DT_GET_PROP(ATTR_LOCATION_CODE, target, targetInfo->locationCode))
104 {
105 log<level::ERR>("Could not read LOCATION_CODE attribute");
106 return requireAttrNotFound;
107 }
108
109 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, target, targetInfo->physDevPath))
110 {
111 log<level::ERR>("Could not read PHYS_DEV_PATH attribute");
112 return requireAttrNotFound;
113 }
114
115 if (DT_GET_PROP(ATTR_MRU_ID, target, targetInfo->mruId))
116 {
117 log<level::ERR>("Could not read MRU_ID attribute");
118 return requireAttrNotFound;
119 }
120
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500121 return requireAttrFound;
122}
123
124/**
125 * @brief Used to get target info (attributes data)
126 *
127 * To get target required attributes value using another attribute value
128 * ("PHYS_BIN_PATH" which is present in same target attributes list) by using
129 * "ipdbg_target_traverse" api because, here we have attribute value only and
130 * doesn't have respective device tree target info to get required attributes
131 * values from it attributes list.
132 *
133 * @param[in] physBinPath to pass PHYS_BIN_PATH value
134 * @param[out] targetInfo to pas buufer to fill with required attributes
135 *
136 * @return true on success otherwise false
137 */
138bool getTgtReqAttrsVal(const std::vector<uint8_t>& physBinPath,
139 TargetInfo& targetInfo)
140{
141 std::memcpy(&targetInfo.physBinPath, physBinPath.data(),
142 sizeof(targetInfo.physBinPath));
143
144 int ret = pdbg_target_traverse(NULL, pdbgCallbackToGetTgtReqAttrsVal,
145 &targetInfo);
146 if (ret == 0)
147 {
148 log<level::ERR>(fmt::format("Given ATTR_PHYS_BIN_PATH value({}) "
149 "not found in phal device tree",
150 targetInfo.physBinPath)
151 .c_str());
152 return false;
153 }
154 else if (ret == requireAttrNotFound)
155 {
156 return false;
157 }
158
159 return true;
160}
161
162/**
163 * @brief GET PEL priority from pHAL priority
164 *
165 * The pHAL callout priority is in different format than PEL format
166 * so, this api is used to return current phal supported priority into
167 * PEL expected format.
168 *
169 * @param[in] phalPriority used to pass phal priority format string
170 *
171 * @return pel priority format string else empty if failure
172 *
173 * @note For "NONE" returning "L" (LOW)
174 */
175static std::string getPelPriority(const std::string& phalPriority)
176{
177 const std::map<std::string, std::string> priorityMap = {
178 {"HIGH", "H"}, {"MEDIUM", "M"}, {"LOW", "L"}, {"NONE", "L"}};
179
180 auto it = priorityMap.find(phalPriority);
181 if (it == priorityMap.end())
182 {
183 log<level::ERR>(fmt::format("Unsupported phal priority({}) is given "
184 "to get pel priority format",
185 phalPriority)
186 .c_str());
187 return "H";
188 }
189
190 return it->second;
191}
192
193void convertFAPItoPELformat(FFDC& ffdc, json& pelJSONFmtCalloutDataList,
194 FFDCData& ffdcUserData)
195{
196 if (ffdc.ffdc_type == FFDC_TYPE_HWP)
197 {
198 // Adding hardware procedures return code details
199 ffdcUserData.emplace_back("HWP_RC", ffdc.hwp_errorinfo.rc);
200 ffdcUserData.emplace_back("HWP_RC_DESC", ffdc.hwp_errorinfo.rc_desc);
201
202 // Adding hardware procedures required ffdc data for debug
203 for_each(
204 ffdc.hwp_errorinfo.ffdcs_data.begin(),
205 ffdc.hwp_errorinfo.ffdcs_data.end(),
206 [&ffdcUserData](std::pair<std::string, std::string>& ele) -> void {
207 std::string keyWithPrefix("HWP_FFDC_");
208 keyWithPrefix.append(ele.first);
209
210 ffdcUserData.emplace_back(keyWithPrefix, ele.second);
211 });
212
213 // Adding hardware callout details
214 int calloutCount = 0;
215 for_each(
216 ffdc.hwp_errorinfo.hwcallouts.begin(),
217 ffdc.hwp_errorinfo.hwcallouts.end(),
218 [&ffdcUserData, &calloutCount,
219 &pelJSONFmtCalloutDataList](const HWCallout& hwCallout) -> void {
220 calloutCount++;
221 std::stringstream keyPrefix;
222 keyPrefix << "HWP_HW_CO_" << std::setfill('0') << std::setw(2)
223 << calloutCount << "_";
224
225 ffdcUserData.emplace_back(
226 std::string(keyPrefix.str()).append("HW_ID"),
227 hwCallout.hwid);
228
229 ffdcUserData.emplace_back(
230 std::string(keyPrefix.str()).append("PRIORITY"),
231 hwCallout.callout_priority);
232
233 phal::TargetInfo targetInfo;
234 phal::getTgtReqAttrsVal(hwCallout.target_entity_path,
235 targetInfo);
236
237 std::string locationCode = std::string(targetInfo.locationCode);
238 ffdcUserData.emplace_back(
239 std::string(keyPrefix.str()).append("LOC_CODE"),
240 locationCode);
241
242 std::string physPath = std::string(targetInfo.physDevPath);
243 ffdcUserData.emplace_back(
244 std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);
245
246 ffdcUserData.emplace_back(
247 std::string(keyPrefix.str()).append("CLK_POS"),
248 std::to_string(hwCallout.clkPos));
249
250 json jsonCalloutData;
251 jsonCalloutData["LocationCode"] = locationCode;
252 std::string pelPriority =
253 getPelPriority(hwCallout.callout_priority);
254 jsonCalloutData["Priority"] = pelPriority;
255
256 if (targetInfo.mruId != 0)
257 {
258 jsonCalloutData["MRUs"] = json::array({
259 {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
260 });
261 }
262
263 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
264 });
265
266 // Adding CDG (callout, deconfigure and guard) targets details
267 calloutCount = 0;
268 for_each(
269 ffdc.hwp_errorinfo.cdg_targets.begin(),
270 ffdc.hwp_errorinfo.cdg_targets.end(),
271 [&ffdcUserData, &calloutCount,
272 &pelJSONFmtCalloutDataList](const CDG_Target& cdg_tgt) -> void {
273 calloutCount++;
274 std::stringstream keyPrefix;
275 keyPrefix << "HWP_CDG_TGT_" << std::setfill('0') << std::setw(2)
276 << calloutCount << "_";
277
278 phal::TargetInfo targetInfo;
279 targetInfo.deconfigure = cdg_tgt.deconfigure;
280
281 phal::getTgtReqAttrsVal(cdg_tgt.target_entity_path, targetInfo);
282
283 std::string locationCode = std::string(targetInfo.locationCode);
284 ffdcUserData.emplace_back(
285 std::string(keyPrefix.str()).append("LOC_CODE"),
286 locationCode);
287 std::string physPath = std::string(targetInfo.physDevPath);
288 ffdcUserData.emplace_back(
289 std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);
290
291 ffdcUserData.emplace_back(
292 std::string(keyPrefix.str()).append("CO_REQ"),
293 (cdg_tgt.callout == true ? "true" : "false"));
294
295 ffdcUserData.emplace_back(
296 std::string(keyPrefix.str()).append("CO_PRIORITY"),
297 cdg_tgt.callout_priority);
298
299 ffdcUserData.emplace_back(
300 std::string(keyPrefix.str()).append("DECONF_REQ"),
301 (cdg_tgt.deconfigure == true ? "true" : "false"));
302
303 ffdcUserData.emplace_back(
304 std::string(keyPrefix.str()).append("GUARD_REQ"),
305 (cdg_tgt.guard == true ? "true" : "false"));
306
307 ffdcUserData.emplace_back(
308 std::string(keyPrefix.str()).append("GUARD_TYPE"),
309 cdg_tgt.guard_type);
310
311 json jsonCalloutData;
312 jsonCalloutData["LocationCode"] = locationCode;
313 std::string pelPriority =
314 getPelPriority(cdg_tgt.callout_priority);
315 jsonCalloutData["Priority"] = pelPriority;
316
317 if (targetInfo.mruId != 0)
318 {
319 jsonCalloutData["MRUs"] = json::array({
320 {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
321 });
322 }
323 jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
324 jsonCalloutData["Guarded"] = cdg_tgt.guard;
Jayanth Othayoth95205eb2021-11-08 06:21:30 -0600325 jsonCalloutData["GuardType"] = cdg_tgt.guard_type;
326 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500327
328 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
329 });
330 }
331 else if ((ffdc.ffdc_type != FFDC_TYPE_NONE) &&
332 (ffdc.ffdc_type != FFDC_TYPE_UNSUPPORTED))
333 {
334 log<level::ERR>(fmt::format("Unsupported phal FFDC type to create PEL. "
335 "MSG: {}",
336 ffdc.message)
337 .c_str());
338 }
339}
340
341} // namespace phal
342} // namespace pels
343} // namespace openpower