1 extern "C"
2 {
3 #include <libpdbg.h>
4 }
5 
6 #include "extensions/phal/pdbg_utils.hpp"
7 #include "extensions/phal/phal_error.hpp"
8 
9 #include <fmt/format.h>
10 
11 #include <phosphor-logging/log.hpp>
12 
13 namespace openpower
14 {
15 namespace phal
16 {
17 
18 using namespace phosphor::logging;
19 
20 pdbg_target* getFsiTarget(struct pdbg_target* procTarget)
21 {
22 
23     struct pdbg_target* fsiTarget = nullptr;
24     pdbg_for_each_target("fsi", procTarget, fsiTarget)
25     {
26         // grab first one we find
27         break;
28     }
29     if (!fsiTarget)
30     {
31         log<level::ERR>(
32             "fsi path of target not found",
33             entry("PROC_TARGET_PATH=%s", pdbg_target_path(procTarget)));
34         return nullptr;
35     }
36 
37     return fsiTarget;
38 }
39 
40 uint32_t probeTarget(struct pdbg_target* procTarget)
41 {
42     struct pdbg_target* pibTarget = nullptr;
43     pdbg_for_each_target("pib", procTarget, pibTarget)
44     {
45         // grab first one we find
46         break;
47     }
48     if (!pibTarget)
49     {
50         log<level::ERR>(
51             "pib path of target not found",
52             entry("PROC_TARGET_PATH=%s", pdbg_target_path(procTarget)));
53         return -1;
54     }
55     // probe PIB and ensure it's enabled
56     if (PDBG_TARGET_ENABLED != pdbg_target_probe(pibTarget))
57     {
58         log<level::ERR>(
59             "probe on pib target failed",
60             entry("PIB_TARGET_PATH=%s", pdbg_target_path(pibTarget)));
61         return -1;
62     }
63     return 0;
64 }
65 
66 uint32_t getCFAM(struct pdbg_target* procTarget, const uint32_t reg,
67                  uint32_t& val)
68 {
69 
70     pdbg_target* fsiTarget = getFsiTarget(procTarget);
71     if (nullptr == fsiTarget)
72     {
73         log<level::ERR>("getCFAM: fsi path or target not found");
74         return -1;
75     }
76 
77     auto rc = probeTarget(procTarget);
78     if (rc)
79     {
80         // probe function logged details to journal
81         return rc;
82     }
83 
84     rc = fsi_read(fsiTarget, reg, &val);
85     if (rc)
86     {
87         log<level::ERR>(
88             "failed to read input cfam", entry("RC=%u", rc),
89             entry("CFAM=0x%X", reg),
90             entry("FSI_TARGET_PATH=%s", pdbg_target_path(fsiTarget)));
91         return rc;
92     }
93     return 0;
94 }
95 
96 uint32_t putCFAM(struct pdbg_target* procTarget, const uint32_t reg,
97                  const uint32_t val)
98 {
99     pdbg_target* fsiTarget = getFsiTarget(procTarget);
100     if (nullptr == fsiTarget)
101     {
102         log<level::ERR>("putCFAM: fsi path or target not found");
103         return -1;
104     }
105 
106     auto rc = probeTarget(procTarget);
107     if (rc)
108     {
109         // probe function logged details to journal
110         return rc;
111     }
112 
113     rc = fsi_write(fsiTarget, reg, val);
114     if (rc)
115     {
116         log<level::ERR>(
117             "failed to write input cfam", entry("RC=%u", rc),
118             entry("CFAM=0x%X", reg),
119             entry("FSI_TARGET_PATH=%s", pdbg_target_path(fsiTarget)));
120         return rc;
121     }
122     return 0;
123 }
124 
125 void setDevtreeEnv()
126 {
127     // PDBG_DTB environment variable set to CEC device tree path
128     static constexpr auto PDBG_DTB_PATH =
129         "/var/lib/phosphor-software-manager/pnor/rw/DEVTREE";
130 
131     if (setenv("PDBG_DTB", PDBG_DTB_PATH, 1))
132     {
133         log<level::ERR>(
134             fmt::format("Failed to set PDBG_DTB: ({})", strerror(errno))
135                 .c_str());
136         throw std::runtime_error("Failed to set PDBG_DTB");
137     }
138 }
139 
140 } // namespace phal
141 } // namespace openpower
142