blob: 13416ae8a72f26f29483c2882d7c7d6ccd7a01a2 [file] [log] [blame]
Patrick Williams2544b412022-10-04 08:41:06 -05001extern "C"
2{
Jayanth Othayoth4d779b22021-06-03 05:45:13 -05003#include <libpdbg.h>
4}
5
6#include "fapi_data_process.hpp"
7
8#include <attributes_info.H>
Jayanth Othayoth417b88e2021-11-17 00:28:09 -06009#include <libphal.H>
10#include <phal_exception.H>
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050011
Patrick Williams2544b412022-10-04 08:41:06 -050012#include <phosphor-logging/elog.hpp>
13
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050014#include <algorithm>
15#include <cstdlib>
16#include <cstring>
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -050017#include <format>
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050018#include <iomanip>
19#include <list>
20#include <map>
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050021#include <sstream>
22#include <string>
23
24namespace openpower
25{
26namespace pels
27{
28namespace phal
29{
30
31using namespace phosphor::logging;
Jayanth Othayoth417b88e2021-11-17 00:28:09 -060032using namespace openpower::phal::exception;
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050033
34/**
35 * Used to pass buffer to pdbg callback api to get required target
36 * data (attributes) based on given data (attribute).
37 */
38struct TargetInfo
39{
40 ATTR_PHYS_BIN_PATH_Type physBinPath;
41 ATTR_LOCATION_CODE_Type locationCode;
42 ATTR_PHYS_DEV_PATH_Type physDevPath;
43 ATTR_MRU_ID_Type mruId;
44
45 bool deconfigure;
46
47 TargetInfo()
48 {
49 memset(&physBinPath, '\0', sizeof(physBinPath));
50 memset(&locationCode, '\0', sizeof(locationCode));
51 memset(&physDevPath, '\0', sizeof(physDevPath));
52 mruId = 0;
53 deconfigure = false;
54 }
55};
56
57/**
58 * Used to return in callback function which are used to get
59 * physical path value and it binary format value.
60 *
61 * The value for constexpr defined based on pdbg_target_traverse function usage.
62 */
63constexpr int continueTgtTraversal = 0;
64constexpr int requireAttrFound = 1;
65constexpr int requireAttrNotFound = 2;
66
67/**
68 * @brief Used to get target location code from phal device tree
69 *
70 * @param[in] target current device tree target
71 * @param[out] appPrivData used for accessing|storing from|to application
72 *
73 * @return 0 to continue traverse, non-zero to stop traverse
74 */
75int pdbgCallbackToGetTgtReqAttrsVal(struct pdbg_target* target,
76 void* appPrivData)
77{
Jayanth Othayoth417b88e2021-11-17 00:28:09 -060078 using namespace openpower::phal::pdbg;
79
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050080 TargetInfo* targetInfo = static_cast<TargetInfo*>(appPrivData);
81
82 ATTR_PHYS_BIN_PATH_Type physBinPath;
83 /**
84 * TODO: Issue: phal/pdata#16
85 * Should not use direct pdbg api to read attribute. Need to use DT_GET_PROP
86 * macro for bmc app's and this will call libdt-api api but, it will print
87 * "pdbg_target_get_attribute failed" trace if attribute is not found and
88 * this callback will call recursively by using pdbg_target_traverse() until
89 * find expected attribute based on return code from this callback. Because,
90 * need to do target iteration to get actual attribute (ATTR_PHYS_BIN_PATH)
91 * value when device tree target info doesn't know to read attribute from
92 * device tree. So, Due to this error trace user will get confusion while
93 * looking traces. Hence using pdbg api to avoid trace until libdt-api
94 * provides log level setup.
95 */
96 if (!pdbg_target_get_attribute(
97 target, "ATTR_PHYS_BIN_PATH",
98 std::stoi(dtAttr::fapi2::ATTR_PHYS_BIN_PATH_Spec),
99 dtAttr::fapi2::ATTR_PHYS_BIN_PATH_ElementCount, physBinPath))
100 {
101 return continueTgtTraversal;
102 }
103
104 if (std::memcmp(physBinPath, targetInfo->physBinPath,
105 sizeof(physBinPath)) != 0)
106 {
107 return continueTgtTraversal;
108 }
109
Jayanth Othayoth363ac762021-11-17 00:38:24 -0600110 // Found Target, now collect the required attributes associated to the
111 // target. Incase of any attribute read failure, initialize the data with
112 // default value.
113
Jayanth Othayoth417b88e2021-11-17 00:28:09 -0600114 try
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500115 {
Jayanth Othayoth417b88e2021-11-17 00:28:09 -0600116 // Get location code information
117 openpower::phal::pdbg::getLocationCode(target,
118 targetInfo->locationCode);
119 }
120 catch (const std::exception& e)
121 {
122 // log message and continue with default data
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500123 log<level::ERR>(std::format("getLocationCode({}): Exception({})",
Jayanth Othayoth417b88e2021-11-17 00:28:09 -0600124 pdbg_target_path(target), e.what())
125 .c_str());
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500126 }
127
128 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, target, targetInfo->physDevPath))
129 {
Jayanth Othayoth363ac762021-11-17 00:38:24 -0600130 log<level::ERR>(
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500131 std::format("Could not read({}) PHYS_DEV_PATH attribute",
Jayanth Othayoth363ac762021-11-17 00:38:24 -0600132 pdbg_target_path(target))
133 .c_str());
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500134 }
135
136 if (DT_GET_PROP(ATTR_MRU_ID, target, targetInfo->mruId))
137 {
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500138 log<level::ERR>(std::format("Could not read({}) ATTR_MRU_ID attribute",
Jayanth Othayoth363ac762021-11-17 00:38:24 -0600139 pdbg_target_path(target))
140 .c_str());
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500141 }
142
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500143 return requireAttrFound;
144}
145
146/**
147 * @brief Used to get target info (attributes data)
148 *
149 * To get target required attributes value using another attribute value
150 * ("PHYS_BIN_PATH" which is present in same target attributes list) by using
151 * "ipdbg_target_traverse" api because, here we have attribute value only and
152 * doesn't have respective device tree target info to get required attributes
153 * values from it attributes list.
154 *
155 * @param[in] physBinPath to pass PHYS_BIN_PATH value
156 * @param[out] targetInfo to pas buufer to fill with required attributes
157 *
158 * @return true on success otherwise false
159 */
160bool getTgtReqAttrsVal(const std::vector<uint8_t>& physBinPath,
161 TargetInfo& targetInfo)
162{
163 std::memcpy(&targetInfo.physBinPath, physBinPath.data(),
164 sizeof(targetInfo.physBinPath));
165
166 int ret = pdbg_target_traverse(NULL, pdbgCallbackToGetTgtReqAttrsVal,
167 &targetInfo);
168 if (ret == 0)
169 {
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500170 std::string fmt;
171 for (auto value : targetInfo.physBinPath)
172 {
173 fmt += std::format("{:02X} ", value);
174 }
175
176 log<level::ERR>(std::format("Given ATTR_PHYS_BIN_PATH value {} "
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500177 "not found in phal device tree",
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500178 fmt)
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500179 .c_str());
180 return false;
181 }
182 else if (ret == requireAttrNotFound)
183 {
184 return false;
185 }
186
187 return true;
188}
189
190/**
191 * @brief GET PEL priority from pHAL priority
192 *
193 * The pHAL callout priority is in different format than PEL format
194 * so, this api is used to return current phal supported priority into
195 * PEL expected format.
196 *
197 * @param[in] phalPriority used to pass phal priority format string
198 *
199 * @return pel priority format string else empty if failure
200 *
201 * @note For "NONE" returning "L" (LOW)
202 */
203static std::string getPelPriority(const std::string& phalPriority)
204{
205 const std::map<std::string, std::string> priorityMap = {
206 {"HIGH", "H"}, {"MEDIUM", "M"}, {"LOW", "L"}, {"NONE", "L"}};
207
208 auto it = priorityMap.find(phalPriority);
209 if (it == priorityMap.end())
210 {
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500211 log<level::ERR>(std::format("Unsupported phal priority({}) is given "
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500212 "to get pel priority format",
213 phalPriority)
214 .c_str());
215 return "H";
216 }
217
218 return it->second;
219}
220
rajerpp1f928c4a2021-11-27 05:55:21 -0600221/**
222 * @brief addPlanarCallout
223 *
224 * This function will add a json for planar callout in the input json list.
225 * The caller can pass this json list into createErrorPEL to apply the callout.
226 *
227 * @param[in,out] jsonCalloutDataList - json list where callout json will be
228 * emplaced
229 * @param[in] priority - string indicating priority.
230 */
231static void addPlanarCallout(json& jsonCalloutDataList,
232 const std::string& priority)
233{
234 json jsonCalloutData;
235
236 // Inventory path for planar
237 jsonCalloutData["InventoryPath"] =
238 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
239 jsonCalloutData["Deconfigured"] = false;
240 jsonCalloutData["Guarded"] = false;
241 jsonCalloutData["Priority"] = priority;
242
243 jsonCalloutDataList.emplace_back(jsonCalloutData);
244}
245
Jayanth Othayothe98777d2022-06-30 04:11:07 -0500246/**
247 * @brief processClockInfoErrorHelper
248 *
249 * Creates informational PEL for spare clock failure
250 *
251 * @param[in] ffdc FFDC data capturd by the HWP
252 * @param[out] pelJSONFmtCalloutDataList used to store collected callout
253 * data into pel expected format
254 * @param[out] ffdcUserData used to store additional ffdc user data to
255 * provided by the SBE FFDC packet.
256 *
257 * @return NULL
258 *
259 **/
260void processClockInfoErrorHelper(const FFDC& ffdc,
261 json& pelJSONFmtCalloutDataList,
262 FFDCData& ffdcUserData)
263{
264 log<level::INFO>(
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500265 std::format("processClockInfoErrorHelper: FFDC Message[{}]",
Jayanth Othayothe98777d2022-06-30 04:11:07 -0500266 ffdc.message)
267 .c_str());
268
269 // Adding hardware procedures return code details
270 ffdcUserData.emplace_back("HWP_RC", ffdc.hwp_errorinfo.rc);
271 ffdcUserData.emplace_back("HWP_RC_DESC", ffdc.hwp_errorinfo.rc_desc);
272
273 // Adding hardware procedures required ffdc data for debug
274 for_each(ffdc.hwp_errorinfo.ffdcs_data.cbegin(),
275 ffdc.hwp_errorinfo.ffdcs_data.cend(),
276 [&ffdcUserData](
277 const std::pair<std::string, std::string>& ele) -> void {
278 std::string keyWithPrefix("HWP_FFDC_");
279 keyWithPrefix.append(ele.first);
280
281 ffdcUserData.emplace_back(keyWithPrefix, ele.second);
282 });
283 // get clock position information
284 auto clk_pos = 0xFF; // Invalid position.
285 for (auto& hwCallout : ffdc.hwp_errorinfo.hwcallouts)
286 {
287 if ((hwCallout.hwid == "PROC_REF_CLOCK") ||
288 (hwCallout.hwid == "PCI_REF_CLOCK"))
289 {
290 clk_pos = hwCallout.clkPos;
291 break;
292 }
293 }
294 // Adding CDG (Only deconfigure) targets details
295 for_each(ffdc.hwp_errorinfo.cdg_targets.begin(),
296 ffdc.hwp_errorinfo.cdg_targets.end(),
297 [&ffdcUserData, &pelJSONFmtCalloutDataList,
298 clk_pos](const CDG_Target& cdg_tgt) -> void {
299 json jsonCalloutData;
300 std::string pelPriority = "H";
301 jsonCalloutData["Priority"] = pelPriority; // Not used
Patrick Williams2544b412022-10-04 08:41:06 -0500302 jsonCalloutData["SymbolicFRU"] = "REFCLK" +
303 std::to_string(clk_pos);
Jayanth Othayothe98777d2022-06-30 04:11:07 -0500304 jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
305 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
306 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
307 });
308}
309
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500310void convertFAPItoPELformat(FFDC& ffdc, json& pelJSONFmtCalloutDataList,
311 FFDCData& ffdcUserData)
312{
Jayanth Othayothe98777d2022-06-30 04:11:07 -0500313 if (ffdc.ffdc_type == FFDC_TYPE_SPARE_CLOCK_INFO)
314 {
315 processClockInfoErrorHelper(ffdc, pelJSONFmtCalloutDataList,
316 ffdcUserData);
317 return;
318 }
319
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500320 if (ffdc.ffdc_type == FFDC_TYPE_HWP)
321 {
322 // Adding hardware procedures return code details
323 ffdcUserData.emplace_back("HWP_RC", ffdc.hwp_errorinfo.rc);
324 ffdcUserData.emplace_back("HWP_RC_DESC", ffdc.hwp_errorinfo.rc_desc);
325
326 // Adding hardware procedures required ffdc data for debug
327 for_each(
328 ffdc.hwp_errorinfo.ffdcs_data.begin(),
329 ffdc.hwp_errorinfo.ffdcs_data.end(),
330 [&ffdcUserData](std::pair<std::string, std::string>& ele) -> void {
331 std::string keyWithPrefix("HWP_FFDC_");
332 keyWithPrefix.append(ele.first);
333
334 ffdcUserData.emplace_back(keyWithPrefix, ele.second);
335 });
336
337 // Adding hardware callout details
338 int calloutCount = 0;
339 for_each(
340 ffdc.hwp_errorinfo.hwcallouts.begin(),
341 ffdc.hwp_errorinfo.hwcallouts.end(),
342 [&ffdcUserData, &calloutCount,
343 &pelJSONFmtCalloutDataList](const HWCallout& hwCallout) -> void {
344 calloutCount++;
345 std::stringstream keyPrefix;
346 keyPrefix << "HWP_HW_CO_" << std::setfill('0') << std::setw(2)
347 << calloutCount << "_";
348
349 ffdcUserData.emplace_back(
350 std::string(keyPrefix.str()).append("HW_ID"),
351 hwCallout.hwid);
352
353 ffdcUserData.emplace_back(
354 std::string(keyPrefix.str()).append("PRIORITY"),
355 hwCallout.callout_priority);
356
357 phal::TargetInfo targetInfo;
358 phal::getTgtReqAttrsVal(hwCallout.target_entity_path,
359 targetInfo);
360
361 std::string locationCode = std::string(targetInfo.locationCode);
362 ffdcUserData.emplace_back(
363 std::string(keyPrefix.str()).append("LOC_CODE"),
364 locationCode);
365
366 std::string physPath = std::string(targetInfo.physDevPath);
367 ffdcUserData.emplace_back(
368 std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);
369
370 ffdcUserData.emplace_back(
371 std::string(keyPrefix.str()).append("CLK_POS"),
372 std::to_string(hwCallout.clkPos));
rajerpp1f928c4a2021-11-27 05:55:21 -0600373
374 ffdcUserData.emplace_back(
375 std::string(keyPrefix.str()).append("CALLOUT_PLANAR"),
376 (hwCallout.isPlanarCallout == true ? "true" : "false"));
377
378 std::string pelPriority =
379 getPelPriority(hwCallout.callout_priority);
380
381 if (hwCallout.isPlanarCallout)
382 {
383 addPlanarCallout(pelJSONFmtCalloutDataList, pelPriority);
384 }
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500385 });
386
387 // Adding CDG (callout, deconfigure and guard) targets details
388 calloutCount = 0;
389 for_each(
390 ffdc.hwp_errorinfo.cdg_targets.begin(),
391 ffdc.hwp_errorinfo.cdg_targets.end(),
392 [&ffdcUserData, &calloutCount,
393 &pelJSONFmtCalloutDataList](const CDG_Target& cdg_tgt) -> void {
394 calloutCount++;
395 std::stringstream keyPrefix;
396 keyPrefix << "HWP_CDG_TGT_" << std::setfill('0') << std::setw(2)
397 << calloutCount << "_";
398
399 phal::TargetInfo targetInfo;
400 targetInfo.deconfigure = cdg_tgt.deconfigure;
401
402 phal::getTgtReqAttrsVal(cdg_tgt.target_entity_path, targetInfo);
403
404 std::string locationCode = std::string(targetInfo.locationCode);
405 ffdcUserData.emplace_back(
406 std::string(keyPrefix.str()).append("LOC_CODE"),
407 locationCode);
408 std::string physPath = std::string(targetInfo.physDevPath);
409 ffdcUserData.emplace_back(
410 std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);
411
412 ffdcUserData.emplace_back(
413 std::string(keyPrefix.str()).append("CO_REQ"),
414 (cdg_tgt.callout == true ? "true" : "false"));
415
416 ffdcUserData.emplace_back(
417 std::string(keyPrefix.str()).append("CO_PRIORITY"),
418 cdg_tgt.callout_priority);
419
420 ffdcUserData.emplace_back(
421 std::string(keyPrefix.str()).append("DECONF_REQ"),
422 (cdg_tgt.deconfigure == true ? "true" : "false"));
423
424 ffdcUserData.emplace_back(
425 std::string(keyPrefix.str()).append("GUARD_REQ"),
426 (cdg_tgt.guard == true ? "true" : "false"));
427
428 ffdcUserData.emplace_back(
429 std::string(keyPrefix.str()).append("GUARD_TYPE"),
430 cdg_tgt.guard_type);
431
432 json jsonCalloutData;
433 jsonCalloutData["LocationCode"] = locationCode;
434 std::string pelPriority =
435 getPelPriority(cdg_tgt.callout_priority);
436 jsonCalloutData["Priority"] = pelPriority;
437
438 if (targetInfo.mruId != 0)
439 {
440 jsonCalloutData["MRUs"] = json::array({
441 {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
442 });
443 }
444 jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
445 jsonCalloutData["Guarded"] = cdg_tgt.guard;
Jayanth Othayoth95205eb2021-11-08 06:21:30 -0600446 jsonCalloutData["GuardType"] = cdg_tgt.guard_type;
447 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500448
449 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
450 });
Jayanth Othayoth9368b712021-11-17 01:03:42 -0600451
452 // Adding procedure callout
453 calloutCount = 0;
454 for_each(ffdc.hwp_errorinfo.procedures_callout.begin(),
455 ffdc.hwp_errorinfo.procedures_callout.end(),
456 [&ffdcUserData, &calloutCount, &pelJSONFmtCalloutDataList](
457 const ProcedureCallout& procCallout) -> void {
458 calloutCount++;
459 std::stringstream keyPrefix;
460 keyPrefix << "HWP_PROC_CO_" << std::setfill('0')
461 << std::setw(2) << calloutCount << "_";
462 ffdcUserData.emplace_back(
463 std::string(keyPrefix.str()).append("PRIORITY"),
464 procCallout.callout_priority);
465 ffdcUserData.emplace_back(
466 std::string(keyPrefix.str()).append("MAINT_PROCEDURE"),
467 procCallout.proc_callout);
468 json jsonCalloutData;
469 jsonCalloutData["Procedure"] = procCallout.proc_callout;
470 std::string pelPriority =
471 getPelPriority(procCallout.callout_priority);
472 jsonCalloutData["Priority"] = pelPriority;
473 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
474 });
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500475 }
476 else if ((ffdc.ffdc_type != FFDC_TYPE_NONE) &&
477 (ffdc.ffdc_type != FFDC_TYPE_UNSUPPORTED))
478 {
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500479 log<level::ERR>(std::format("Unsupported phal FFDC type to create PEL. "
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500480 "MSG: {}",
481 ffdc.message)
482 .c_str());
483 }
484}
485
486} // namespace phal
487} // namespace pels
488} // namespace openpower