1 #pragma once
2 
3 #include <analyzer/analyzer_main.hpp>
4 #include <analyzer/callout.hpp>
5 #include <hei_main.hpp>
6 #include <nlohmann/json.hpp>
7 #include <util/pdbg.hpp>
8 
9 #include <format>
10 
11 namespace analyzer
12 {
13 
14 /**
15  * @brief Data regarding required service actions based on the hardware error
16  *        analysis.
17  */
18 class ServiceData
19 {
20   public:
21     /**
22      * @brief Constructor from components.
23      * @param i_rootCause    The signature of the root cause attention.
24      * @param i_analysisType The type of analysis to perform.
25      * @param i_isoData      The data found during isolation.
26      */
27     ServiceData(const libhei::Signature& i_rootCause,
28                 AnalysisType i_analysisType,
29                 const libhei::IsolationData& i_isoData) :
30         iv_rootCause(i_rootCause),
31         iv_analysisType(i_analysisType), iv_isoData(i_isoData)
32     {}
33 
34     /** @brief Destructor. */
35     ~ServiceData() = default;
36 
37     /** @brief Copy constructor. */
38     ServiceData(const ServiceData&) = default;
39 
40     /** @brief Assignment operator. */
41     ServiceData& operator=(const ServiceData&) = default;
42 
43   private:
44     /** The signature of the root cause attention. */
45     const libhei::Signature iv_rootCause;
46 
47     /** The type of analysis to perform. */
48     const AnalysisType iv_analysisType;
49 
50     /** The data found during isolation. */
51     const libhei::IsolationData iv_isoData;
52 
53     /** The list of callouts that will be added to a PEL. */
54     nlohmann::json iv_calloutList = nlohmann::json::array();
55 
56     /** FFDC for callouts that would otherwise not be available in the
57      *  callout list (unit paths, bus types, etc.). */
58     nlohmann::json iv_calloutFFDC = nlohmann::json::array();
59 
60   public:
61     /** @return The signature of the root cause attention. */
62     const libhei::Signature& getRootCause() const
63     {
64         return iv_rootCause;
65     }
66 
67     /** @return The type of analysis to perform. */
68     AnalysisType getAnalysisType() const
69     {
70         return iv_analysisType;
71     }
72 
73     /** @return The data found during isolation. */
74     const libhei::IsolationData& getIsolationData() const
75     {
76         return iv_isoData;
77     }
78 
79     /** @return Returns the guard type based on current analysis policies. */
80     callout::GuardType queryGuardPolicy() const
81     {
82         if (AnalysisType::SYSTEM_CHECKSTOP == iv_analysisType)
83         {
84             return callout::GuardType::UNRECOVERABLE;
85         }
86         else if (AnalysisType::TERMINATE_IMMEDIATE == iv_analysisType)
87         {
88             return callout::GuardType::PREDICTIVE;
89         }
90 
91         return callout::GuardType::NONE;
92     }
93 
94     /**
95      * @brief Add callout for a pdbg_target.
96      * @param i_target   The chip or unit target to add to the callout list.
97      * @param i_priority The callout priority.
98      * @param i_guard    True if guard is required. False, otherwise.
99      */
100     void calloutTarget(pdbg_target* i_target, callout::Priority i_priority,
101                        bool i_guard);
102 
103     /**
104      * @brief Add callout for a connected target on the other side of a bus.
105      * @param i_rxTarget The target on the receiving side (RX) of the bus.
106      * @param i_busType  The bus type.
107      * @param i_priority The callout priority.
108      * @param i_guard    True if guard is required. False, otherwise.
109      */
110     void calloutConnected(pdbg_target* i_rxTarget,
111                           const callout::BusType& i_busType,
112                           callout::Priority i_priority, bool i_guard);
113 
114     /**
115      * @brief Add callout for an entire bus.
116      * @param i_rxTarget The target on the receiving side (RX) of the bus.
117      * @param i_busType  The bus type.
118      * @param i_priority The callout priority.
119      * @param i_guard    True if guard is required. False, otherwise.
120      */
121     void calloutBus(pdbg_target* i_rxTarget, const callout::BusType& i_busType,
122                     callout::Priority i_priority, bool i_guard);
123 
124     /**
125      * @brief Add callout for a clock.
126      * @param i_clockType The clock type.
127      * @param i_priority  The callout priority.
128      * @param i_guard     True if guard is required. False, otherwise.
129      */
130     void calloutClock(const callout::ClockType& i_clockType,
131                       callout::Priority i_priority, bool i_guard);
132 
133     /**
134      * @brief Add callout for a service procedure.
135      * @param i_procedure The procedure type.
136      * @param i_priority  The callout priority.
137      */
138     void calloutProcedure(const callout::Procedure& i_procedure,
139                           callout::Priority i_priority);
140 
141     /**
142      * @brief Add callout for part type.
143      * @param i_part     The part type.
144      * @param i_priority The callout priority.
145      */
146     void calloutPart(const callout::PartType& i_part,
147                      callout::Priority i_priority);
148 
149     /** @brief Accessor to iv_calloutList. */
150     const nlohmann::json& getCalloutList() const
151     {
152         return iv_calloutList;
153     }
154 
155     /** @brief Accessor to iv_calloutFFDC. */
156     const nlohmann::json& getCalloutFFDC() const
157     {
158         return iv_calloutFFDC;
159     }
160 
161     /**
162      * @brief Adds the SRC subsystem to the given additional PEL data.
163      * @param io_additionalData The additional PEL data.
164      */
165     void addSrcSubsystem(
166         std::map<std::string, std::string>& io_additionalData) const
167     {
168         io_additionalData["PEL_SUBSYSTEM"] = std::format(
169             "0x{:02x}", static_cast<uint8_t>(iv_srcSubsystem.first));
170     }
171 
172     /** @brief Accessor to iv_srcSubsystem. */
173     const std::pair<callout::SrcSubsystem, callout::Priority> getSubsys() const
174     {
175         return iv_srcSubsystem;
176     }
177 
178   private:
179     /**
180      * @brief Add callout information to the callout list.
181      * @param The JSON object for this callout.
182      */
183     void addCallout(const nlohmann::json& i_callout);
184 
185     /**
186      * @brief Add FFDC for a callout that would otherwise not be available in
187      *        the callout list (unit paths, bus types, etc.).
188      * @param The JSON object for this callout.
189      */
190     void addCalloutFFDC(const nlohmann::json& i_ffdc)
191     {
192         iv_calloutFFDC.push_back(i_ffdc);
193     }
194 
195     /**
196      * @brief A simple helper function for all the callout functions that need
197      *        to callout a target (callout only, no FFDC).
198      * @param i_target   The chip or unit target to add to the callout list.
199      * @param i_priority The callout priority.
200      * @param i_guard    True if guard is required. False, otherwise.
201      */
202     void addTargetCallout(pdbg_target* i_target, callout::Priority i_priority,
203                           bool i_guard);
204 
205     /**
206      * @brief A simple helper function for all the callout functions that need
207      *        to callout a the backplane (callout only, no FFDC).
208      * @param i_priority The callout priority.
209      */
210     void addBackplaneCallout(callout::Priority i_priority);
211 
212   private:
213     /**
214      * @brief Compares the current SRC subsystem type with the given SRC
215      *        subsystem type and stores the highest priority callout subsystem.
216      *        If the two subsystems are of equal priority. The stored subsystem
217      *        is used.
218      * @param i_subsystem The given subsystem type.
219      * @param i_priority  The callout priority associated with the given
220      *                    subsystem.
221      */
222     void setSrcSubsystem(callout::SrcSubsystem i_subsystem,
223                          callout::Priority i_priority);
224 
225     /**
226      * @brief Returns the appropriate SRC subsystem based on the input target.
227      * @param i_trgt The given pdbg target.
228      */
229     callout::SrcSubsystem getTargetSubsystem(pdbg_target* i_target);
230 
231     /** The SRC subsystem field (2nd byte of the primary SRC) is based on the
232      *  callouts the PEL. As callouts are to the service data, we'll need to
233      *  keep track of the highest priority callout subsystem. */
234     std::pair<callout::SrcSubsystem, callout::Priority> iv_srcSubsystem = {
235         callout::SrcSubsystem::CEC_HARDWARE, callout::Priority::LOW};
236 };
237 
238 } // namespace analyzer
239