blob: 27348853d04f9c545b05e1e4bbf4b4fe94cb9fb4 [file] [log] [blame]
Zane Shelleye90b85d2021-12-17 17:24:49 -06001//------------------------------------------------------------------------------
2// IMPORTANT:
3// This file will be built in CI test and should work out-of-the-box in CI test
4// with use of the fake device tree. Any functions that require addition support
5// to simulate in CI test should be put in `pdbg_no_sim.cpp`.
6//------------------------------------------------------------------------------
7
Zane Shelley171a2e02020-11-13 13:56:13 -06008#include <assert.h>
Zane Shelleye4bfb472021-08-10 12:47:32 -05009#include <config.h>
Zane Shelley171a2e02020-11-13 13:56:13 -060010
Zane Shelley7ae9c8c2020-12-02 20:10:31 -060011#include <hei_main.hpp>
Caleb Palmer626270a2022-02-21 11:05:08 -060012#include <nlohmann/json.hpp>
13#include <util/dbus.hpp>
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060014#include <util/pdbg.hpp>
Zane Shelley171a2e02020-11-13 13:56:13 -060015#include <util/trace.hpp>
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060016
Caleb Palmer626270a2022-02-21 11:05:08 -060017#include <filesystem>
18#include <fstream>
19#include <string>
20
Zane Shelley3a851082021-03-23 16:45:28 -050021#ifdef CONFIG_PHAL_API
Zane Shelleye4bfb472021-08-10 12:47:32 -050022#include <attributes_info.H>
Zane Shelley3a851082021-03-23 16:45:28 -050023#endif
24
Zane Shelley38501e12022-01-10 15:42:28 -060025using namespace analyzer;
26
Caleb Palmer626270a2022-02-21 11:05:08 -060027namespace fs = std::filesystem;
28
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060029namespace util
30{
31
32namespace pdbg
33{
34
35//------------------------------------------------------------------------------
36
Zane Shelleya0299852020-11-13 13:38:04 -060037pdbg_target* getTrgt(const libhei::Chip& i_chip)
38{
39 return (pdbg_target*)i_chip.getChip();
40}
41
42//------------------------------------------------------------------------------
43
Zane Shelley236bb732021-03-24 17:07:46 -050044pdbg_target* getTrgt(const std::string& i_path)
45{
46 return pdbg_target_from_path(nullptr, i_path.c_str());
47}
48
49//------------------------------------------------------------------------------
50
Zane Shelleya0299852020-11-13 13:38:04 -060051const char* getPath(pdbg_target* i_trgt)
52{
53 return pdbg_target_path(i_trgt);
54}
55
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060056const char* getPath(const libhei::Chip& i_chip)
57{
Zane Shelleya0299852020-11-13 13:38:04 -060058 return getPath(getTrgt(i_chip));
59}
60
61//------------------------------------------------------------------------------
62
63uint32_t getChipPos(pdbg_target* i_trgt)
64{
65 uint32_t attr = 0;
66 pdbg_target_get_attribute(i_trgt, "ATTR_FAPI_POS", 4, 1, &attr);
67 return attr;
68}
69
70uint32_t getChipPos(const libhei::Chip& i_chip)
71{
72 return getChipPos(getTrgt(i_chip));
73}
74
75//------------------------------------------------------------------------------
76
Zane Shelley2a394cb2022-02-17 22:01:39 -060077uint8_t getUnitPos(pdbg_target* i_trgt)
78{
79 uint8_t attr = 0;
80 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_UNIT_POS", 1, 1, &attr);
81 return attr;
82}
83
84//------------------------------------------------------------------------------
85
Zane Shelleya0299852020-11-13 13:38:04 -060086uint8_t getTrgtType(pdbg_target* i_trgt)
87{
88 uint8_t attr = 0;
89 pdbg_target_get_attribute(i_trgt, "ATTR_TYPE", 1, 1, &attr);
90 return attr;
91}
92
93uint8_t getTrgtType(const libhei::Chip& i_chip)
94{
95 return getTrgtType(getTrgt(i_chip));
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -060096}
97
98//------------------------------------------------------------------------------
99
Zane Shelley2a394cb2022-02-17 22:01:39 -0600100pdbg_target* getParentChip(pdbg_target* i_unitTarget)
101{
102 assert(nullptr != i_unitTarget);
103
104 // Check if the given target is already a chip.
105 auto targetType = getTrgtType(i_unitTarget);
106 if (TYPE_PROC == targetType || TYPE_OCMB == targetType)
107 {
108 return i_unitTarget; // simply return the given target
109 }
110
111 // Check if this unit is on an OCMB.
112 pdbg_target* parentChip = pdbg_target_parent("ocmb", i_unitTarget);
113
114 // If not on the OCMB, check if this unit is on a PROC.
115 if (nullptr == parentChip)
116 {
117 parentChip = pdbg_target_parent("proc", i_unitTarget);
118 }
119
120 // There should always be a parent chip. Throw an error if not found.
121 if (nullptr == parentChip)
122 {
123 throw std::logic_error("No parent chip found: i_unitTarget=" +
124 std::string{getPath(i_unitTarget)});
125 }
126
127 return parentChip;
128}
129
130//------------------------------------------------------------------------------
131
Zane Shelleyc62813d2023-08-22 16:52:19 -0500132pdbg_target* getParentProcessor(pdbg_target* i_target)
133{
134 assert(nullptr != i_target);
135
136 // Check if the given target is already a processor chip.
137 if (TYPE_PROC == getTrgtType(i_target))
138 {
139 return i_target; // simply return the given target
140 }
141
142 // Get the parent processor chip.
143 pdbg_target* parentChip = pdbg_target_parent("proc", i_target);
144
145 // There should always be a parent chip. Throw an error if not found.
146 if (nullptr == parentChip)
147 {
148 throw std::logic_error("No parent chip found: i_target=" +
149 std::string{getPath(i_target)});
150 }
151
152 return parentChip;
153}
154
155//------------------------------------------------------------------------------
156
Zane Shelley2a394cb2022-02-17 22:01:39 -0600157pdbg_target* getChipUnit(pdbg_target* i_parentChip, TargetType_t i_unitType,
158 uint8_t i_unitPos)
159{
160 assert(nullptr != i_parentChip);
161
162 auto parentType = getTrgtType(i_parentChip);
163
164 std::string devTreeType{};
165
166 if (TYPE_PROC == parentType)
167 {
168 // clang-format off
169 static const std::map<TargetType_t, std::string> m =
170 {
171 {TYPE_MC, "mc" },
172 {TYPE_MCC, "mcc" },
173 {TYPE_OMI, "omi" },
174 {TYPE_OMIC, "omic" },
175 {TYPE_PAUC, "pauc" },
176 {TYPE_PAU, "pau" },
177 {TYPE_NMMU, "nmmu" },
178 {TYPE_IOHS, "iohs" },
179 {TYPE_IOLINK, "smpgroup"},
180 {TYPE_EQ, "eq" },
181 {TYPE_CORE, "core" },
182 {TYPE_PEC, "pec" },
183 {TYPE_PHB, "phb" },
184 {TYPE_NX, "nx" },
185 };
186 // clang-format on
187
188 devTreeType = m.at(i_unitType);
189 }
190 else if (TYPE_OCMB == parentType)
191 {
192 // clang-format off
193 static const std::map<TargetType_t, std::string> m =
194 {
195 {TYPE_MEM_PORT, "mem_port"},
196 };
197 // clang-format on
198
199 devTreeType = m.at(i_unitType);
200 }
201 else
202 {
203 throw std::logic_error("Unexpected parent chip: " +
204 std::string{getPath(i_parentChip)});
205 }
206
207 // Iterate all children of the parent and match the unit position.
208 pdbg_target* unitTarget = nullptr;
209 pdbg_for_each_target(devTreeType.c_str(), i_parentChip, unitTarget)
210 {
211 if (nullptr != unitTarget && i_unitPos == getUnitPos(unitTarget))
212 {
213 break; // found it
214 }
215 }
216
217 // Print a warning if the target unit is not found, but don't throw an
218 // error. Instead let the calling code deal with the it.
219 if (nullptr == unitTarget)
220 {
221 trace::err("No unit target found: i_parentChip=%s i_unitType=0x%02x "
222 "i_unitPos=%u",
223 getPath(i_parentChip), i_unitType, i_unitPos);
224 }
225
226 return unitTarget;
227}
228
229//------------------------------------------------------------------------------
230
Caleb Palmer626270a2022-02-21 11:05:08 -0600231pdbg_target* getTargetAcrossBus(pdbg_target* i_rxTarget)
232{
233 assert(nullptr != i_rxTarget);
234
235 // Validate target type
236 auto rxType = util::pdbg::getTrgtType(i_rxTarget);
237 assert(util::pdbg::TYPE_IOLINK == rxType ||
238 util::pdbg::TYPE_IOHS == rxType);
239
240 pdbg_target* o_peerTarget;
241 fs::path filePath;
242
243 // Open the appropriate data file depending on machine type
244 util::dbus::MachineType machineType = util::dbus::getMachineType();
245 switch (machineType)
246 {
247 // Rainier 4U
248 case util::dbus::MachineType::Rainier_2S4U:
249 case util::dbus::MachineType::Rainier_1S4U:
Patrick Williams27dd6362023-05-10 07:51:20 -0500250 filePath = fs::path{PACKAGE_DIR
251 "util-data/peer-targets-rainier-4u.json"};
Caleb Palmer626270a2022-02-21 11:05:08 -0600252 break;
253 // Rainier 2U
254 case util::dbus::MachineType::Rainier_2S2U:
255 case util::dbus::MachineType::Rainier_1S2U:
Patrick Williams27dd6362023-05-10 07:51:20 -0500256 filePath = fs::path{PACKAGE_DIR
257 "util-data/peer-targets-rainier-2u.json"};
Caleb Palmer626270a2022-02-21 11:05:08 -0600258 break;
259 // Everest
260 case util::dbus::MachineType::Everest:
Patrick Williams27dd6362023-05-10 07:51:20 -0500261 filePath = fs::path{PACKAGE_DIR
262 "util-data/peer-targets-everest.json"};
Caleb Palmer626270a2022-02-21 11:05:08 -0600263 break;
264 default:
265 trace::err("Invalid machine type found %d",
266 static_cast<uint8_t>(machineType));
267 break;
268 }
269
270 std::ifstream file{filePath};
271 assert(file.good());
272
273 try
274 {
Patrick Williams27dd6362023-05-10 07:51:20 -0500275 auto trgtMap = nlohmann::json::parse(file);
276 std::string rxPath = util::pdbg::getPath(i_rxTarget);
Caleb Palmer626270a2022-02-21 11:05:08 -0600277 std::string peerPath = trgtMap.at(rxPath).get<std::string>();
278
279 o_peerTarget = util::pdbg::getTrgt(peerPath);
280 }
281 catch (...)
282 {
283 trace::err("Failed to parse file: %s", filePath.string().c_str());
284 throw;
285 }
286
287 return o_peerTarget;
288}
289
290//------------------------------------------------------------------------------
291
Zane Shelley38501e12022-01-10 15:42:28 -0600292pdbg_target* getConnectedTarget(pdbg_target* i_rxTarget,
293 const callout::BusType& i_busType)
294{
295 assert(nullptr != i_rxTarget);
296
297 pdbg_target* txTarget = nullptr;
298
Patrick Williams27dd6362023-05-10 07:51:20 -0500299 auto rxType = util::pdbg::getTrgtType(i_rxTarget);
Zane Shelley38501e12022-01-10 15:42:28 -0600300 std::string rxPath = util::pdbg::getPath(i_rxTarget);
301
302 if (callout::BusType::SMP_BUS == i_busType &&
303 util::pdbg::TYPE_IOLINK == rxType)
304 {
Caleb Palmer626270a2022-02-21 11:05:08 -0600305 txTarget = getTargetAcrossBus(i_rxTarget);
Zane Shelley38501e12022-01-10 15:42:28 -0600306 }
307 else if (callout::BusType::SMP_BUS == i_busType &&
308 util::pdbg::TYPE_IOHS == rxType)
309 {
Caleb Palmer626270a2022-02-21 11:05:08 -0600310 txTarget = getTargetAcrossBus(i_rxTarget);
Zane Shelley38501e12022-01-10 15:42:28 -0600311 }
312 else if (callout::BusType::OMI_BUS == i_busType &&
313 util::pdbg::TYPE_OMI == rxType)
314 {
315 // This is a bit clunky. The pdbg APIs only give us the ability to
Caleb Palmer626270a2022-02-21 11:05:08 -0600316 // iterate over the children instead of just returning a list. So
317 // we'll push all the children to a list and go from there.
Zane Shelley38501e12022-01-10 15:42:28 -0600318 std::vector<pdbg_target*> childList;
319
320 pdbg_target* childTarget = nullptr;
321 pdbg_for_each_target("ocmb", i_rxTarget, childTarget)
322 {
323 if (nullptr != childTarget)
324 {
325 childList.push_back(childTarget);
326 }
327 }
328
329 // We know there should only be one OCMB per OMI.
330 if (1 != childList.size())
331 {
332 throw std::logic_error("Invalid child list size for " + rxPath);
333 }
334
335 // Get the connected target.
336 txTarget = childList.front();
337 }
338 else if (callout::BusType::OMI_BUS == i_busType &&
339 util::pdbg::TYPE_OCMB == rxType)
340 {
341 txTarget = pdbg_target_parent("omi", i_rxTarget);
342 if (nullptr == txTarget)
343 {
344 throw std::logic_error("No parent OMI found for " + rxPath);
345 }
346 }
347 else
348 {
349 // This would be a code bug.
350 throw std::logic_error("Unsupported config: i_rxTarget=" + rxPath +
351 " i_busType=" + i_busType.getString());
352 }
353
354 assert(nullptr != txTarget); // just in case we missed something above
355
356 return txTarget;
357}
358
359//------------------------------------------------------------------------------
360
Zane Shelley171a2e02020-11-13 13:56:13 -0600361pdbg_target* getPibTrgt(pdbg_target* i_procTrgt)
362{
363 // The input target must be a processor.
Zane Shelley35171d92020-12-03 13:31:13 -0600364 assert(TYPE_PROC == getTrgtType(i_procTrgt));
Zane Shelley171a2e02020-11-13 13:56:13 -0600365
366 // Get the pib path.
367 char path[16];
368 sprintf(path, "/proc%d/pib", pdbg_target_index(i_procTrgt));
369
370 // Return the pib target.
371 pdbg_target* pibTrgt = pdbg_target_from_path(nullptr, path);
372 assert(nullptr != pibTrgt);
373
374 return pibTrgt;
375}
376
377//------------------------------------------------------------------------------
378
Zane Shelleyff76b6b2020-11-18 13:54:26 -0600379pdbg_target* getFsiTrgt(pdbg_target* i_procTrgt)
380{
381 // The input target must be a processor.
Zane Shelley35171d92020-12-03 13:31:13 -0600382 assert(TYPE_PROC == getTrgtType(i_procTrgt));
Zane Shelleyff76b6b2020-11-18 13:54:26 -0600383
384 // Get the fsi path.
385 char path[16];
386 sprintf(path, "/proc%d/fsi", pdbg_target_index(i_procTrgt));
387
388 // Return the fsi target.
389 pdbg_target* fsiTrgt = pdbg_target_from_path(nullptr, path);
390 assert(nullptr != fsiTrgt);
391
392 return fsiTrgt;
393}
394
395//------------------------------------------------------------------------------
396
Zane Shelley35171d92020-12-03 13:31:13 -0600397// IMPORTANT:
Caleb Palmer626270a2022-02-21 11:05:08 -0600398// The ATTR_CHIP_ID attribute will be synced from Hostboot to the BMC at
399// some point during the IPL. It is possible that this information is needed
400// before the sync occurs, in which case the value will return 0.
Zane Shelley171a2e02020-11-13 13:56:13 -0600401uint32_t __getChipId(pdbg_target* i_trgt)
402{
403 uint32_t attr = 0;
404 pdbg_target_get_attribute(i_trgt, "ATTR_CHIP_ID", 4, 1, &attr);
405 return attr;
406}
407
Zane Shelley35171d92020-12-03 13:31:13 -0600408// IMPORTANT:
Caleb Palmer626270a2022-02-21 11:05:08 -0600409// The ATTR_EC attribute will be synced from Hostboot to the BMC at some
410// point during the IPL. It is possible that this information is needed
411// before the sync occurs, in which case the value will return 0.
Zane Shelley171a2e02020-11-13 13:56:13 -0600412uint8_t __getChipEc(pdbg_target* i_trgt)
413{
414 uint8_t attr = 0;
415 pdbg_target_get_attribute(i_trgt, "ATTR_EC", 1, 1, &attr);
416 return attr;
417}
418
419uint32_t __getChipIdEc(pdbg_target* i_trgt)
420{
Zane Shelley35171d92020-12-03 13:31:13 -0600421 auto chipId = __getChipId(i_trgt);
422 auto chipEc = __getChipEc(i_trgt);
423
424 if (((0 == chipId) || (0 == chipEc)) && (TYPE_PROC == getTrgtType(i_trgt)))
425 {
426 // There is a special case where the model/level attributes have not
Caleb Palmer626270a2022-02-21 11:05:08 -0600427 // been initialized in the devtree. This is possible on the epoch
428 // IPL where an attention occurs before Hostboot is able to update
429 // the devtree information on the BMC. It may is still possible to
430 // get this information from chips with CFAM access (i.e. a
431 // processor) via the CFAM chip ID register.
Zane Shelley35171d92020-12-03 13:31:13 -0600432
433 uint32_t val = 0;
434 if (0 == getCfam(i_trgt, 0x100a, val))
435 {
436 chipId = ((val & 0x0F0FF000) >> 12);
437 chipEc = ((val & 0xF0000000) >> 24) | ((val & 0x00F00000) >> 20);
438 }
439 }
440
441 return ((chipId & 0xffff) << 16) | (chipEc & 0xff);
Zane Shelley171a2e02020-11-13 13:56:13 -0600442}
443
444void __addChip(std::vector<libhei::Chip>& o_chips, pdbg_target* i_trgt,
445 libhei::ChipType_t i_type)
446{
Caleb Palmer626270a2022-02-21 11:05:08 -0600447 // Trace each chip for debug. It is important to show the type just in
448 // case the model/EC does not exist. See note below.
Zane Shelley171a2e02020-11-13 13:56:13 -0600449 trace::inf("Chip found: type=0x%08" PRIx32 " chip=%s", i_type,
450 getPath(i_trgt));
451
452 if (0 == i_type)
453 {
Caleb Palmer626270a2022-02-21 11:05:08 -0600454 // This is a special case. See the details in __getChipIdEC(). There
455 // is nothing more we can do with this chip since we don't know what
456 // it is. So ignore the chip for now.
Zane Shelley171a2e02020-11-13 13:56:13 -0600457 }
458 else
459 {
460 o_chips.emplace_back(i_trgt, i_type);
461 }
462}
463
Zane Shelleycd6373d2022-05-12 16:49:56 -0500464// Should ignore OCMBs that have been masked on the processor side of the bus.
465bool __isMaskedOcmb(const libhei::Chip& i_chip)
466{
467 // TODO: This function only works for P10 processors will need to update for
468 // subsequent chips.
469
470 // Map of MCC target position to DSTL_FIR_MASK address.
471 static const std::map<unsigned int, uint64_t> addrs = {
472 {0, 0x0C010D03}, {1, 0x0C010D43}, {2, 0x0D010D03}, {3, 0x0D010D43},
473 {4, 0x0E010D03}, {5, 0x0E010D43}, {6, 0x0F010D03}, {7, 0x0F010D43},
474 };
475
476 auto ocmb = getTrgt(i_chip);
477
478 // Confirm this chip is an OCMB.
479 if (TYPE_OCMB != getTrgtType(ocmb))
480 {
481 return false;
482 }
483
484 // Get the connected MCC target on the processor chip.
485 auto mcc = pdbg_target_parent("mcc", ocmb);
486 if (nullptr == mcc)
487 {
488 throw std::logic_error("No parent MCC found for " +
489 std::string{getPath(ocmb)});
490 }
491
492 // Read the associated DSTL_FIR_MASK.
493 uint64_t val = 0;
494 if (getScom(getParentChip(mcc), addrs.at(getUnitPos(mcc)), val))
495 {
496 // Just let this go. The SCOM code will log the error.
497 return false;
498 }
499
500 // The DSTL_FIR has bits for each of the two memory channels on the MCC.
501 auto chnlPos = getChipPos(ocmb) % 2;
502
503 // Channel 0 => bits 0-3, channel 1 => bits 4-7.
504 auto mask = (val >> (60 - (4 * chnlPos))) & 0xf;
505
506 // Return true if the mask is set to all 1's.
507 if (0xf == mask)
508 {
509 trace::inf("OCMB masked on processor side of bus: %s", getPath(ocmb));
510 return true;
511 }
512
513 return false; // default
514}
515
Zane Shelley171a2e02020-11-13 13:56:13 -0600516void getActiveChips(std::vector<libhei::Chip>& o_chips)
517{
518 o_chips.clear();
519
520 // Iterate each processor.
521 pdbg_target* procTrgt;
522 pdbg_for_each_class_target("proc", procTrgt)
523 {
524 // We cannot use the proc target to determine if the chip is active.
525 // There is some design limitation in pdbg that requires the proc
Caleb Palmer626270a2022-02-21 11:05:08 -0600526 // targets to always be active. Instead, we must get the associated
527 // pib target and check if it is active.
Zane Shelley171a2e02020-11-13 13:56:13 -0600528
529 // Active processors only.
530 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
531 continue;
532
533 // Add the processor to the list.
534 __addChip(o_chips, procTrgt, __getChipIdEc(procTrgt));
535
536 // Iterate the connected OCMBs, if they exist.
537 pdbg_target* ocmbTrgt;
538 pdbg_for_each_target("ocmb", procTrgt, ocmbTrgt)
539 {
540 // Active OCMBs only.
541 if (PDBG_TARGET_ENABLED != pdbg_target_probe(ocmbTrgt))
542 continue;
543
544 // Add the OCMB to the list.
545 __addChip(o_chips, ocmbTrgt, __getChipIdEc(ocmbTrgt));
546 }
547 }
Zane Shelleycd6373d2022-05-12 16:49:56 -0500548
549 // Ignore OCMBs that have been masked on the processor side of the bus.
550 o_chips.erase(
551 std::remove_if(o_chips.begin(), o_chips.end(), __isMaskedOcmb),
552 o_chips.end());
Zane Shelley171a2e02020-11-13 13:56:13 -0600553}
554
555//------------------------------------------------------------------------------
556
Zane Shelley3f363d42022-02-10 16:20:37 -0600557void getActiveProcessorChips(std::vector<pdbg_target*>& o_chips)
558{
559 o_chips.clear();
560
561 pdbg_target* procTrgt;
562 pdbg_for_each_class_target("proc", procTrgt)
563 {
564 // We cannot use the proc target to determine if the chip is active.
565 // There is some design limitation in pdbg that requires the proc
566 // targets to always be active. Instead, we must get the associated pib
567 // target and check if it is active.
568
569 if (PDBG_TARGET_ENABLED != pdbg_target_probe(getPibTrgt(procTrgt)))
570 continue;
571
572 o_chips.push_back(procTrgt);
573 }
574}
575
576//------------------------------------------------------------------------------
577
Zane Shelleyc18ba8f2021-12-01 16:29:20 -0600578pdbg_target* getPrimaryProcessor()
579{
Caleb Palmer626270a2022-02-21 11:05:08 -0600580 // TODO: For at least P10, the primary processor (the one connected
581 // directly
Zane Shelleyc18ba8f2021-12-01 16:29:20 -0600582 // to the BMC), will always be PROC 0. We will need to update this
583 // later if we ever support an alternate primary processor.
584 return getTrgt("/proc0");
585}
586
587//------------------------------------------------------------------------------
588
Zane Shelley7ae9c8c2020-12-02 20:10:31 -0600589bool queryHardwareAnalysisSupported()
590{
591 // Hardware analysis is only supported on P10 systems and up.
Zane Shelley5183af32020-12-07 14:49:03 -0600592 return (PDBG_PROC_P9 < pdbg_get_proc());
Zane Shelley7ae9c8c2020-12-02 20:10:31 -0600593}
594
595//------------------------------------------------------------------------------
596
Zane Shelley3a851082021-03-23 16:45:28 -0500597std::string getLocationCode(pdbg_target* trgt)
598{
599 if (nullptr == trgt)
600 {
601 // Either the path is wrong or the attribute doesn't exist.
602 return std::string{};
603 }
604
605#ifdef CONFIG_PHAL_API
606
607 ATTR_LOCATION_CODE_Type val;
608 if (DT_GET_PROP(ATTR_LOCATION_CODE, trgt, val))
609 {
610 // Get the immediate parent in the devtree path and try again.
611 return getLocationCode(pdbg_target_parent(nullptr, trgt));
612 }
613
614 // Attribute found.
615 return std::string{val};
616
617#else
618
619 return std::string{getPath(trgt)};
620
621#endif
622}
623
624//------------------------------------------------------------------------------
625
626std::string getPhysDevPath(pdbg_target* trgt)
627{
628 if (nullptr == trgt)
629 {
630 // Either the path is wrong or the attribute doesn't exist.
631 return std::string{};
632 }
633
634#ifdef CONFIG_PHAL_API
635
636 ATTR_PHYS_DEV_PATH_Type val;
637 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, trgt, val))
638 {
639 // Get the immediate parent in the devtree path and try again.
640 return getPhysDevPath(pdbg_target_parent(nullptr, trgt));
641 }
642
643 // Attribute found.
644 return std::string{val};
645
646#else
647
648 return std::string{getPath(trgt)};
649
650#endif
651}
652
653//------------------------------------------------------------------------------
654
Zane Shelleybf3326f2021-11-12 13:41:39 -0600655std::vector<uint8_t> getPhysBinPath(pdbg_target* target)
656{
657 std::vector<uint8_t> binPath;
658
659 if (nullptr != target)
660 {
661#ifdef CONFIG_PHAL_API
662
663 ATTR_PHYS_BIN_PATH_Type value;
664 if (DT_GET_PROP(ATTR_PHYS_BIN_PATH, target, value))
665 {
Caleb Palmer626270a2022-02-21 11:05:08 -0600666 // The attrirbute for this target does not exist. Get the
667 // immediate parent in the devtree path and try again. Note that
668 // if there is no parent target, nullptr will be returned and
669 // that will be checked above.
Zane Shelleybf3326f2021-11-12 13:41:39 -0600670 return getPhysBinPath(pdbg_target_parent(nullptr, target));
671 }
672
673 // Attribute was found. Copy the attribute array to the returned
674 // vector. Note that the reason we return the vector instead of just
675 // returning the array is because the array type and details only
676 // exists in this specific configuration.
677 binPath.insert(binPath.end(), value, value + sizeof(value));
678
679#endif
680 }
681
682 return binPath;
683}
684
685//------------------------------------------------------------------------------
686
Zane Shelleyf4bd5ff2020-11-05 22:26:04 -0600687} // namespace pdbg
688
689} // namespace util