1 #include <analyzer/service_data.hpp>
2 
3 namespace analyzer
4 {
5 
6 //------------------------------------------------------------------------------
7 
8 void ServiceData::calloutTarget(pdbg_target* i_target,
9                                 const callout::Priority& i_priority,
10                                 bool i_guard)
11 {
12     // Add the target to the callout list.
13     addTargetCallout(i_target, i_priority, i_guard);
14 
15     // Add the callout FFDC.
16     nlohmann::json ffdc;
17     ffdc["Callout Type"] = "Hardware Callout";
18     ffdc["Target"]       = util::pdbg::getPhysDevPath(i_target);
19     ffdc["Priority"]     = i_priority.getRegistryString();
20     ffdc["Guard"]        = i_guard;
21     addCalloutFFDC(ffdc);
22 }
23 
24 //------------------------------------------------------------------------------
25 
26 void ServiceData::calloutConnected(pdbg_target* i_rxTarget,
27                                    const callout::BusType& i_busType,
28                                    const callout::Priority& i_priority,
29                                    bool i_guard)
30 {
31     // Get the endpoint target for the transfer side of the bus.
32     auto txTarget = util::pdbg::getConnectedTarget(i_rxTarget, i_busType);
33 
34     // Callout the TX endpoint.
35     addTargetCallout(txTarget, i_priority, i_guard);
36 
37     // Add the callout FFDC.
38     nlohmann::json ffdc;
39     ffdc["Callout Type"] = "Connected Callout";
40     ffdc["Bus Type"]     = i_busType.getString();
41     ffdc["RX Target"]    = util::pdbg::getPhysDevPath(i_rxTarget);
42     ffdc["TX Target"]    = util::pdbg::getPhysDevPath(txTarget);
43     ffdc["Priority"]     = i_priority.getRegistryString();
44     ffdc["Guard"]        = i_guard;
45     addCalloutFFDC(ffdc);
46 }
47 
48 //------------------------------------------------------------------------------
49 
50 void ServiceData::calloutBus(pdbg_target* i_rxTarget,
51                              const callout::BusType& i_busType,
52                              const callout::Priority& i_priority, bool i_guard)
53 {
54     // Get the endpoint target for the transfer side of the bus.
55     auto txTarget = util::pdbg::getConnectedTarget(i_rxTarget, i_busType);
56 
57     // Callout the RX endpoint.
58     addTargetCallout(i_rxTarget, i_priority, i_guard);
59 
60     // Callout the TX endpoint.
61     addTargetCallout(txTarget, i_priority, i_guard);
62 
63     // Callout everything else in between.
64     // TODO: For P10 (OMI bus and XBUS), the callout is simply the backplane.
65     addBackplaneCallout(i_priority);
66 
67     // Add the callout FFDC.
68     nlohmann::json ffdc;
69     ffdc["Callout Type"] = "Bus Callout";
70     ffdc["Bus Type"]     = i_busType.getString();
71     ffdc["RX Target"]    = util::pdbg::getPhysDevPath(i_rxTarget);
72     ffdc["TX Target"]    = util::pdbg::getPhysDevPath(txTarget);
73     ffdc["Priority"]     = i_priority.getRegistryString();
74     ffdc["Guard"]        = i_guard;
75     addCalloutFFDC(ffdc);
76 }
77 
78 //------------------------------------------------------------------------------
79 
80 void ServiceData::calloutClock(const callout::ClockType& i_clockType,
81                                const callout::Priority& i_priority, bool)
82 {
83     // Callout the clock target.
84     // TODO: For P10, the callout is simply the backplane. Also, there are no
85     //       clock targets in the device tree. So at the moment there is no
86     //       guard support for clock targets.
87     addBackplaneCallout(i_priority);
88 
89     // Add the callout FFDC.
90     // TODO: Add the target and guard type if guard is ever supported.
91     nlohmann::json ffdc;
92     ffdc["Callout Type"] = "Clock Callout";
93     ffdc["Clock Type"]   = i_clockType.getString();
94     ffdc["Priority"]     = i_priority.getRegistryString();
95     addCalloutFFDC(ffdc);
96 }
97 
98 //------------------------------------------------------------------------------
99 
100 void ServiceData::calloutProcedure(const callout::Procedure& i_procedure,
101                                    const callout::Priority& i_priority)
102 {
103     // Add the actual callout to the service data.
104     nlohmann::json callout;
105     callout["Procedure"] = i_procedure.getString();
106     callout["Priority"]  = i_priority.getUserDataString();
107     addCallout(callout);
108 
109     // Add the callout FFDC.
110     nlohmann::json ffdc;
111     ffdc["Callout Type"] = "Procedure Callout";
112     ffdc["Procedure"]    = i_procedure.getString();
113     ffdc["Priority"]     = i_priority.getRegistryString();
114     addCalloutFFDC(ffdc);
115 }
116 
117 //------------------------------------------------------------------------------
118 
119 void ServiceData::calloutPart(const callout::PartType& i_part,
120                               const callout::Priority& i_priority)
121 {
122     if (callout::PartType::PNOR == i_part)
123     {
124         // The PNOR is on the BMC card.
125         // TODO: Will need to be modified if we ever support systems with more
126         //       than one BMC.
127         addTargetCallout(util::pdbg::getTrgt("/bmc0"), i_priority, false);
128     }
129     else
130     {
131         throw std::logic_error("Unsupported part type: " + i_part.getString());
132     }
133 
134     // Add the callout FFDC.
135     nlohmann::json ffdc;
136     ffdc["Callout Type"] = "Part Callout";
137     ffdc["Part Type"]    = i_part.getString();
138     ffdc["Priority"]     = i_priority.getRegistryString();
139     addCalloutFFDC(ffdc);
140 }
141 
142 //------------------------------------------------------------------------------
143 
144 void ServiceData::addCallout(const nlohmann::json& i_callout)
145 {
146     // The new callout is either a hardware callout with a location code or a
147     // procedure callout.
148 
149     std::string type{};
150     if (i_callout.contains("LocationCode"))
151     {
152         type = "LocationCode";
153     }
154     else if (i_callout.contains("Procedure"))
155     {
156         type = "Procedure";
157     }
158     else
159     {
160         throw std::logic_error("Unsupported callout: " + i_callout.dump());
161     }
162 
163     // A map to determine the priority order. All of the medium priorities,
164     // including the medium group priorities, are all the same level.
165     static const std::map<std::string, unsigned int> m = {
166         {"H", 3}, {"M", 2}, {"A", 2}, {"B", 2}, {"C", 2}, {"L", 1},
167     };
168 
169     bool addCallout = true;
170 
171     for (auto& c : iv_calloutList)
172     {
173         if (c.contains(type) && (c.at(type) == i_callout.at(type)))
174         {
175             // The new callout already exists. Don't add a new callout.
176             addCallout = false;
177 
178             if (m.at(c.at("Priority")) < m.at(i_callout.at("Priority")))
179             {
180                 // The new callout has a higher priority, update it.
181                 c["Priority"] = i_callout.at("Priority");
182             }
183         }
184     }
185 
186     if (addCallout)
187     {
188         iv_calloutList.push_back(i_callout);
189     }
190 }
191 
192 //------------------------------------------------------------------------------
193 
194 void ServiceData::addTargetCallout(pdbg_target* i_target,
195                                    const callout::Priority& i_priority,
196                                    bool i_guard)
197 {
198     nlohmann::json callout;
199 
200     callout["LocationCode"] = util::pdbg::getLocationCode(i_target);
201     callout["Priority"]     = i_priority.getUserDataString();
202     callout["Deconfigured"] = false;
203     callout["Guarded"]      = false; // default
204 
205     // Check if guard info should be added.
206     if (i_guard)
207     {
208         auto guardType = queryGuardPolicy();
209 
210         if (!(callout::GuardType::NONE == guardType))
211         {
212             callout["Guarded"]    = true;
213             callout["EntityPath"] = util::pdbg::getPhysBinPath(i_target);
214             callout["GuardType"]  = guardType.getString();
215         }
216     }
217 
218     addCallout(callout);
219 }
220 
221 //------------------------------------------------------------------------------
222 
223 void ServiceData::addBackplaneCallout(const callout::Priority& i_priority)
224 {
225     // TODO: There isn't a device tree object for this. So will need to hardcode
226     //       the location code for now. In the future, we will need a mechanism
227     //       to make this data driven.
228 
229     nlohmann::json callout;
230 
231     callout["LocationCode"] = "P0";
232     callout["Priority"]     = i_priority.getUserDataString();
233     callout["Deconfigured"] = false;
234     callout["Guarded"]      = false;
235 
236     addCallout(callout);
237 }
238 
239 //------------------------------------------------------------------------------
240 
241 } // namespace analyzer
242