1b1ebfcb1SBen Tyner #include <unistd.h>
2b1ebfcb1SBen Tyner 
3135793a8SBen Tyner #include <analyzer/analyzer_main.hpp>
45c5db65aSBen Tyner #include <attn/attn_common.hpp>
5188f1096SBen Tyner #include <attn/attn_dbus.hpp>
67029e525SBen Tyner #include <attn/attn_dump.hpp>
7b797b3e1SBen Tyner #include <attn/attn_logging.hpp>
8f5210bb6SBen Tyner #include <attn/pel/pel_minimal.hpp>
9b1ebfcb1SBen Tyner #include <phosphor-logging/log.hpp>
101315968cSBen Tyner #include <util/dbus.hpp>
11faf33367SBen Tyner #include <util/ffdc.hpp>
12bfa831a8Saustinfcui #include <util/trace.hpp>
13f5210bb6SBen Tyner 
14b1ebfcb1SBen Tyner namespace attn
15b1ebfcb1SBen Tyner {
16f5210bb6SBen Tyner /** @brief Tuple containing information about ffdc files */
17f5210bb6SBen Tyner using FFDCTuple =
18f5210bb6SBen Tyner     std::tuple<util::FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>;
19f5210bb6SBen Tyner 
20f5210bb6SBen Tyner /**
21f5210bb6SBen Tyner  * Create FFDCTuple objects corresponding to the specified FFDC files.
22f5210bb6SBen Tyner  *
23f5210bb6SBen Tyner  * The D-Bus method to create an error log requires a vector of tuples to
24f5210bb6SBen Tyner  * pass in the FFDC file information.
25f5210bb6SBen Tyner  *
26f5210bb6SBen Tyner  * @param   files - FFDC files
27f5210bb6SBen Tyner  * @return  vector of FFDCTuple objects
28f5210bb6SBen Tyner  */
29f5210bb6SBen Tyner std::vector<FFDCTuple>
createFFDCTuples(const std::vector<util::FFDCFile> & files)30f5210bb6SBen Tyner     createFFDCTuples(const std::vector<util::FFDCFile>& files)
31f5210bb6SBen Tyner {
32f5210bb6SBen Tyner     std::vector<FFDCTuple> ffdcTuples{};
33a79f6c8fSZane Shelley     util::transformFFDC(files, ffdcTuples);
34f5210bb6SBen Tyner 
35f5210bb6SBen Tyner     return ffdcTuples;
36f5210bb6SBen Tyner }
37f5210bb6SBen Tyner 
38f5210bb6SBen Tyner /**
39f5210bb6SBen Tyner  * @brief Create an FFDCFile object containing raw data
40f5210bb6SBen Tyner  *
41f5210bb6SBen Tyner  * Throws an exception if an error occurs.
42f5210bb6SBen Tyner  *
43f5210bb6SBen Tyner  * @param   i_buffer - raw data to add to ffdc faw data file
44f5210bb6SBen Tyner  * @param   i_size - size of the raw data
45f5210bb6SBen Tyner  * @return  FFDCFile object
46f5210bb6SBen Tyner  */
createFFDCRawFile(void * i_buffer,size_t i_size)47f5210bb6SBen Tyner util::FFDCFile createFFDCRawFile(void* i_buffer, size_t i_size)
48f5210bb6SBen Tyner {
49f5210bb6SBen Tyner     util::FFDCFile file{util::FFDCFormat::Custom};
50f5210bb6SBen Tyner 
51f5210bb6SBen Tyner     // Write buffer to file and then reset file description file offset
52f5210bb6SBen Tyner     int fd = file.getFileDescriptor();
53d700609cSBen Tyner     size_t numBytes = write(fd, static_cast<char*>(i_buffer), i_size);
54d700609cSBen Tyner     if (i_size != numBytes)
55d700609cSBen Tyner     {
56bfa831a8Saustinfcui         trace::err("%s only %u of %u bytes written", file.getPath().c_str(),
57bfa831a8Saustinfcui                    numBytes, i_size);
58d700609cSBen Tyner     }
59d700609cSBen Tyner 
60f5210bb6SBen Tyner     lseek(fd, 0, SEEK_SET);
61f5210bb6SBen Tyner 
62f5210bb6SBen Tyner     return file;
63f5210bb6SBen Tyner }
64f5210bb6SBen Tyner 
65f5210bb6SBen Tyner /**
66f5210bb6SBen Tyner  * Create FFDCFile objects containing debug data to store in the error log.
67f5210bb6SBen Tyner  *
68f5210bb6SBen Tyner  * If an error occurs, the error is written to the journal but an exception
69f5210bb6SBen Tyner  * is not thrown.
70f5210bb6SBen Tyner  *
71f5210bb6SBen Tyner  * @param   i_buffer - raw data (if creating raw dump ffdc entry in log)
72f5210bb6SBen Tyner  * @return  vector of FFDCFile objects
73f5210bb6SBen Tyner  */
createFFDCFiles(char * i_buffer=nullptr,size_t i_size=0)74f5210bb6SBen Tyner std::vector<util::FFDCFile> createFFDCFiles(char* i_buffer = nullptr,
75f5210bb6SBen Tyner                                             size_t i_size = 0)
76f5210bb6SBen Tyner {
77f5210bb6SBen Tyner     std::vector<util::FFDCFile> files{};
78f5210bb6SBen Tyner 
79f5210bb6SBen Tyner     // Create raw dump file
80f5210bb6SBen Tyner     if ((nullptr != i_buffer) && (0 != i_size))
81f5210bb6SBen Tyner     {
82f5210bb6SBen Tyner         files.emplace_back(createFFDCRawFile(i_buffer, i_size));
83f5210bb6SBen Tyner     }
84f5210bb6SBen Tyner 
85f5210bb6SBen Tyner     // Create trace dump file
86faf33367SBen Tyner     util::createFFDCTraceFiles(files);
87f5210bb6SBen Tyner 
8821cc6270SBen Tyner     // Add PRD scratch registers
8921cc6270SBen Tyner     addPrdScratchRegs(files);
9021cc6270SBen Tyner 
91f5210bb6SBen Tyner     return files;
92f5210bb6SBen Tyner }
93f5210bb6SBen Tyner 
94f5210bb6SBen Tyner /**
95f5210bb6SBen Tyner  * Create a PEL from an existing PEL
96f5210bb6SBen Tyner  *
97f5210bb6SBen Tyner  * Create a new PEL based on the specified raw PEL and submit the new PEL
98f5210bb6SBen Tyner  * to the backend logging code as a raw PEL. Note that  additional data map
99f5210bb6SBen Tyner  * here contains data to be committed to the PEL and it can also be used to
100f5210bb6SBen Tyner  * create the PEL as it contains needed information.
101f5210bb6SBen Tyner  *
102135793a8SBen Tyner  * @param   i_rawPel - buffer containing a raw PEL
103f5210bb6SBen Tyner  * @param   i_additional - additional data to be added to the new PEL
104f5210bb6SBen Tyner  */
createPelCustom(std::vector<uint8_t> & i_rawPel,std::map<std::string,std::string> i_additional)105f5210bb6SBen Tyner void createPelCustom(std::vector<uint8_t>& i_rawPel,
106f5210bb6SBen Tyner                      std::map<std::string, std::string> i_additional)
107f5210bb6SBen Tyner {
108f5210bb6SBen Tyner     // create PEL object from buffer
109f5210bb6SBen Tyner     auto tiPel = std::make_unique<pel::PelMinimal>(i_rawPel);
110f5210bb6SBen Tyner 
111f5210bb6SBen Tyner     // The additional data contains the TI info as well as the value for the
112f5210bb6SBen Tyner     // subystem that provided the TI info. Get the subystem from additional
113c49d20b9Saustinfcui     // data and then populate the primary SRC and SRC words for the custom PEL
114c49d20b9Saustinfcui     // based on the subsystem's TI info.
115c49d20b9Saustinfcui     std::map<std::string, std::string>::iterator it;
116c49d20b9Saustinfcui     uint8_t subsystem;
117c49d20b9Saustinfcui 
118c49d20b9Saustinfcui     it = i_additional.find("Subsystem");
119c49d20b9Saustinfcui     if (it != i_additional.end())
120c49d20b9Saustinfcui     {
121c49d20b9Saustinfcui         subsystem = std::stoi(it->second);
122f5210bb6SBen Tyner         tiPel->setSubsystem(subsystem);
123c49d20b9Saustinfcui     }
124c49d20b9Saustinfcui     else
125c49d20b9Saustinfcui     {
126c49d20b9Saustinfcui         // The entry with key "Subsystem" does not exist in the additional map.
127c49d20b9Saustinfcui         // Log the error, create failure event, and return.
12867b8229bSZane Shelley         trace::err("Error the key Subsystem does not exist in the map.");
129c49d20b9Saustinfcui         eventAttentionFail((int)AttnSection::attnLogging | ATTN_INVALID_KEY);
130c49d20b9Saustinfcui         return;
131c49d20b9Saustinfcui     }
132f5210bb6SBen Tyner 
133135793a8SBen Tyner     // If recoverable attentions are active we will call the analyzer and
134135793a8SBen Tyner     // then link the custom pel to analyzer pel.
135135793a8SBen Tyner     it = i_additional.find("recoverables");
136135793a8SBen Tyner     if (it != i_additional.end() && "true" == it->second)
137135793a8SBen Tyner     {
138135793a8SBen Tyner         DumpParameters dumpParameters;
139ebff0d37SZane Shelley         auto plid = analyzer::analyzeHardware(
140ebff0d37SZane Shelley             analyzer::AnalysisType::TERMINATE_IMMEDIATE, dumpParameters);
141611b3442SZane Shelley         if (0 != plid)
142135793a8SBen Tyner         {
143611b3442SZane Shelley             // Link the PLID if an attention was found and a PEL was generated.
144611b3442SZane Shelley             tiPel->setPlid(plid);
145135793a8SBen Tyner         }
146135793a8SBen Tyner     }
147135793a8SBen Tyner 
148f5210bb6SBen Tyner     if (static_cast<uint8_t>(pel::SubsystemID::hypervisor) == subsystem)
149f5210bb6SBen Tyner     {
150f5210bb6SBen Tyner         // populate hypervisor SRC words
151f5210bb6SBen Tyner         tiPel->setSrcWords(std::array<uint32_t, pel::numSrcWords>{
152f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x10 SRC Word 12"], 0, 16),
153f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x14 SRC Word 13"], 0, 16),
154f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x18 SRC Word 14"], 0, 16),
155f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x1c SRC Word 15"], 0, 16),
156f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x20 SRC Word 16"], 0, 16),
157f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x24 SRC Word 17"], 0, 16),
158f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x28 SRC Word 18"], 0, 16),
159f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x2c SRC Word 19"], 0, 16)});
160f5210bb6SBen Tyner 
1619d4f91cdSBen Tyner         // Populate phyp primary SRC
1629d4f91cdSBen Tyner 
1639d4f91cdSBen Tyner         // char array for raw pel src
164f5210bb6SBen Tyner         std::array<char, pel::asciiStringSize> srcChars{'0'};
165c49d20b9Saustinfcui         std::string srcString;
1669d4f91cdSBen Tyner 
1679d4f91cdSBen Tyner         // src from TI info
168c49d20b9Saustinfcui         it = i_additional.find("SrcAscii");
169c49d20b9Saustinfcui         if (it != i_additional.end())
170c49d20b9Saustinfcui         {
171c49d20b9Saustinfcui             srcString = it->second;
172c49d20b9Saustinfcui         }
173c49d20b9Saustinfcui         else
174c49d20b9Saustinfcui         {
175c49d20b9Saustinfcui             // The entry with key "Subsystem" does not exist in the additional
176c49d20b9Saustinfcui             // map. Log the error, create failure event, and return.
17767b8229bSZane Shelley             trace::err("Error the key SrcAscii does not exist in the map.");
178c49d20b9Saustinfcui             eventAttentionFail((int)AttnSection::attnLogging |
179c49d20b9Saustinfcui                                ATTN_INVALID_KEY);
180c49d20b9Saustinfcui             return;
181c49d20b9Saustinfcui         }
1829d4f91cdSBen Tyner 
1839d4f91cdSBen Tyner         // copy from string to char array
184f5210bb6SBen Tyner         srcString.copy(srcChars.data(),
185f5210bb6SBen Tyner                        std::min(srcString.size(), pel::asciiStringSize), 0);
1869d4f91cdSBen Tyner 
1879d4f91cdSBen Tyner         tiPel->setAsciiString(srcChars); // pel object src is char array
188feeea83bSBen Tyner 
189feeea83bSBen Tyner         // set symptom-id
190c49d20b9Saustinfcui         auto symptomId = (srcString.substr(0, 8) + '_');
191feeea83bSBen Tyner 
192feeea83bSBen Tyner         symptomId += (i_additional["0x10 SRC Word 12"]);
193feeea83bSBen Tyner         symptomId += (i_additional["0x14 SRC Word 13"] + '_');
194feeea83bSBen Tyner         symptomId += (i_additional["0x18 SRC Word 14"]);
195feeea83bSBen Tyner         symptomId += (i_additional["0x1c SRC Word 15"] + '_');
196feeea83bSBen Tyner         symptomId += (i_additional["0x20 SRC Word 16"]);
197feeea83bSBen Tyner         symptomId += (i_additional["0x24 SRC Word 17"] + '_');
198feeea83bSBen Tyner         symptomId += (i_additional["0x28 SRC Word 18"]);
199feeea83bSBen Tyner         symptomId += (i_additional["0x2c SRC Word 19"]);
200feeea83bSBen Tyner 
201feeea83bSBen Tyner         // setSymptomId will take care of required null-terminate and padding
202feeea83bSBen Tyner         tiPel->setSymptomId(symptomId);
203f5210bb6SBen Tyner     }
204f5210bb6SBen Tyner     else
205f5210bb6SBen Tyner     {
206f5210bb6SBen Tyner         // Populate hostboot SRC words - note HB word 0 from the shared info
207f5210bb6SBen Tyner         // data (additional data "0x10 HB Word") is reflected in the PEL as
208f5210bb6SBen Tyner         // "reason code" so we zero it here. Also note that the first word
209f5210bb6SBen Tyner         // in this group of words starts at word 0 and word 1 does not exits.
210f5210bb6SBen Tyner         tiPel->setSrcWords(std::array<uint32_t, pel::numSrcWords>{
211f5210bb6SBen Tyner             (uint32_t)0x00000000,
212f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x14 HB Word 2"], 0, 16),
213f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x18 HB Word 3"], 0, 16),
214f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x1c HB Word 4"], 0, 16),
215f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x20 HB Word 5"], 0, 16),
216f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x24 HB Word 6"], 0, 16),
217f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x28 HB Word 7"], 0, 16),
218f5210bb6SBen Tyner             (uint32_t)std::stoul(i_additional["0x2c HB Word 8"], 0, 16)});
219f5210bb6SBen Tyner 
2209d4f91cdSBen Tyner         // Populate hostboot primary SRC
2219d4f91cdSBen Tyner 
2229d4f91cdSBen Tyner         // char array for raw pel src
223f5210bb6SBen Tyner         std::array<char, pel::asciiStringSize> srcChars{'0'};
224c49d20b9Saustinfcui         std::string srcString;
2259d4f91cdSBen Tyner 
2269d4f91cdSBen Tyner         // src from TI info
227c49d20b9Saustinfcui         it = i_additional.find("SrcAscii");
228c49d20b9Saustinfcui         if (it != i_additional.end())
229c49d20b9Saustinfcui         {
230c49d20b9Saustinfcui             srcString = it->second;
231c49d20b9Saustinfcui         }
232c49d20b9Saustinfcui         else
233c49d20b9Saustinfcui         {
234c49d20b9Saustinfcui             // The entry with key "Subsystem" does not exist in the additional
235c49d20b9Saustinfcui             // map. Log the error, create failure event, and return.
23667b8229bSZane Shelley             trace::err("Error the key SrcAscii does not exist in the map.");
237c49d20b9Saustinfcui             eventAttentionFail((int)AttnSection::attnLogging |
238c49d20b9Saustinfcui                                ATTN_INVALID_KEY);
239c49d20b9Saustinfcui             return;
240c49d20b9Saustinfcui         }
2419d4f91cdSBen Tyner 
2429d4f91cdSBen Tyner         // copy from string to char array
243f5210bb6SBen Tyner         srcString.copy(srcChars.data(),
244f5210bb6SBen Tyner                        std::min(srcString.size(), pel::asciiStringSize), 0);
2459d4f91cdSBen Tyner 
2469d4f91cdSBen Tyner         tiPel->setAsciiString(srcChars); // pel object src is char array
247feeea83bSBen Tyner 
248feeea83bSBen Tyner         // set symptom-id
249c49d20b9Saustinfcui         auto symptomId = (srcString.substr(0, 8) + '_');
250feeea83bSBen Tyner 
251feeea83bSBen Tyner         symptomId += (i_additional["0x10 HB Word 0"]);       // note: word 1
252feeea83bSBen Tyner         symptomId += (i_additional["0x14 HB Word 2"] + '_'); // does not exist
253feeea83bSBen Tyner         symptomId += (i_additional["0x18 HB Word 3"]);
254feeea83bSBen Tyner         symptomId += (i_additional["0x1c HB Word 4"] + '_');
255feeea83bSBen Tyner         symptomId += (i_additional["0x20 HB Word 5"]);
256feeea83bSBen Tyner         symptomId += (i_additional["0x24 HB Word 6"] + '_');
257feeea83bSBen Tyner         symptomId += (i_additional["0x28 HB Word 7"]);
258feeea83bSBen Tyner         symptomId += (i_additional["0x2c HB Word 8"]);
259feeea83bSBen Tyner 
260feeea83bSBen Tyner         // setSymptomId will take care of required null-terminate and padding
261feeea83bSBen Tyner         tiPel->setSymptomId(symptomId);
262f5210bb6SBen Tyner     }
263f5210bb6SBen Tyner 
264f5210bb6SBen Tyner     // set severity, event type and action flags
265f5210bb6SBen Tyner     tiPel->setSeverity(static_cast<uint8_t>(pel::Severity::termination));
266f5210bb6SBen Tyner     tiPel->setType(static_cast<uint8_t>(pel::EventType::na));
267ac5bd05cSBen Tyner 
268ac5bd05cSBen Tyner     auto actionFlags = pel::ActionFlags::service | pel::ActionFlags::report |
269ac5bd05cSBen Tyner                        pel::ActionFlags::call;
270ac5bd05cSBen Tyner 
271ac5bd05cSBen Tyner     it = i_additional.find("hidden");
272ac5bd05cSBen Tyner     if (it != i_additional.end() && "true" == it->second)
273ac5bd05cSBen Tyner     {
274ac5bd05cSBen Tyner         trace::inf("making HB TI PEL hidden");
275ac5bd05cSBen Tyner         actionFlags = actionFlags | pel::ActionFlags::hidden;
276ac5bd05cSBen Tyner     }
277ac5bd05cSBen Tyner 
278ac5bd05cSBen Tyner     tiPel->setAction(static_cast<uint16_t>(actionFlags));
279f5210bb6SBen Tyner 
28021cc6270SBen Tyner     // The raw PEL that we used as the basis for this custom PEL contains some
28121cc6270SBen Tyner     // user data sections that do not need to be in this PEL. However we do
28221cc6270SBen Tyner     // want to include the raw TI information.
28321cc6270SBen Tyner     int ffdcCount = 0;
28421cc6270SBen Tyner     it = i_additional.find("FFDC count");
28521cc6270SBen Tyner     if (it != i_additional.end())
28621cc6270SBen Tyner     {
28721cc6270SBen Tyner         // remove all sections except 1 (raw Ti info)
28821cc6270SBen Tyner         ffdcCount = std::stoi(it->second) - 1;
28921cc6270SBen Tyner     }
29021cc6270SBen Tyner     tiPel->setSectionCount(tiPel->getSectionCount() - ffdcCount);
291f5210bb6SBen Tyner 
292f5210bb6SBen Tyner     // Update the raw PEL with the new custom PEL data
293f5210bb6SBen Tyner     tiPel->raw(i_rawPel);
294f5210bb6SBen Tyner 
295f5210bb6SBen Tyner     // create PEL from raw data
296f5210bb6SBen Tyner     createPelRaw(i_rawPel);
297f5210bb6SBen Tyner }
298f5210bb6SBen Tyner 
299f5210bb6SBen Tyner /**
300f5210bb6SBen Tyner  * Log an event handled by the attention handler
301f5210bb6SBen Tyner  *
302f5210bb6SBen Tyner  * Basic (non TI) events will generate a standard message-registry based PEL
303f5210bb6SBen Tyner  *
304f5210bb6SBen Tyner  * TI events will create two PEL's. One PEL will be informational and will
305f5210bb6SBen Tyner  * contain trace information relevent to attention handler. The second PEL
306f5210bb6SBen Tyner  * will be specific to the TI type (including the primary SRC) and will be
307f5210bb6SBen Tyner  * based off of the TI information provided to the attention handler through
308f5210bb6SBen Tyner  * shared TI info data area.
309f5210bb6SBen Tyner  *
310f5210bb6SBen Tyner  * @param  i_event - The event type
311f5210bb6SBen Tyner  * @param  i_additional - Additional PEL data
312f5210bb6SBen Tyner  * @param  i_ffdc - FFDC PEL data
31390516851SBen Tyner  * @param  i_severity - Severity level
3147f6ce6acSBen Tyner  * @return Event log Id (0 if no event log generated)
315f5210bb6SBen Tyner  */
event(EventType i_event,std::map<std::string,std::string> & i_additional,const std::vector<util::FFDCFile> & i_ffdc,std::string i_severity=levelPelError)3167f6ce6acSBen Tyner uint32_t event(EventType i_event,
3177f6ce6acSBen Tyner                std::map<std::string, std::string>& i_additional,
31890516851SBen Tyner                const std::vector<util::FFDCFile>& i_ffdc,
31990516851SBen Tyner                std::string i_severity = levelPelError)
320b1ebfcb1SBen Tyner {
3217f6ce6acSBen Tyner     uint32_t pelId = 0;      // assume no event log generated
3227f6ce6acSBen Tyner 
323b1ebfcb1SBen Tyner     bool eventValid = false; // assume no event created
324f5210bb6SBen Tyner     bool tiEvent = false;    // assume not a terminate event
325b1ebfcb1SBen Tyner 
32621cc6270SBen Tyner     // count user data sections so we can fixup custom PEL
32721cc6270SBen Tyner     i_additional["FFDC count"] = std::to_string(i_ffdc.size());
32821cc6270SBen Tyner 
329b1ebfcb1SBen Tyner     std::string eventName;
330b1ebfcb1SBen Tyner 
331b1ebfcb1SBen Tyner     switch (i_event)
332b1ebfcb1SBen Tyner     {
333b1ebfcb1SBen Tyner         case EventType::Checkstop:
334b1ebfcb1SBen Tyner             eventName = "org.open_power.HwDiags.Error.Checkstop";
335b1ebfcb1SBen Tyner             eventValid = true;
336b1ebfcb1SBen Tyner             break;
337b1ebfcb1SBen Tyner         case EventType::Terminate:
338b1ebfcb1SBen Tyner             eventName = "org.open_power.Attn.Error.Terminate";
339b1ebfcb1SBen Tyner             eventValid = true;
340f5210bb6SBen Tyner             tiEvent = true;
341b1ebfcb1SBen Tyner             break;
342b1ebfcb1SBen Tyner         case EventType::Vital:
343b1ebfcb1SBen Tyner             eventName = "org.open_power.Attn.Error.Vital";
344b1ebfcb1SBen Tyner             eventValid = true;
345b1ebfcb1SBen Tyner             break;
346b1ebfcb1SBen Tyner         case EventType::HwDiagsFail:
347b1ebfcb1SBen Tyner         case EventType::AttentionFail:
348b1ebfcb1SBen Tyner             eventName = "org.open_power.Attn.Error.Fail";
349b1ebfcb1SBen Tyner             eventValid = true;
350b1ebfcb1SBen Tyner             break;
351b1ebfcb1SBen Tyner         default:
352b1ebfcb1SBen Tyner             eventValid = false;
353b1ebfcb1SBen Tyner             break;
354b1ebfcb1SBen Tyner     }
355b1ebfcb1SBen Tyner 
356b1ebfcb1SBen Tyner     if (true == eventValid)
357b1ebfcb1SBen Tyner     {
358f5210bb6SBen Tyner         // Create PEL with additional data and FFDC data. The newly created
359f5210bb6SBen Tyner         // PEL's platform log-id will be returned.
36090516851SBen Tyner         pelId = util::dbus::createPel(eventName, i_severity, i_additional,
3611315968cSBen Tyner                                       createFFDCTuples(i_ffdc));
362b1ebfcb1SBen Tyner 
363f5210bb6SBen Tyner         // If this is a TI event we will create an additional PEL that is
364f5210bb6SBen Tyner         // specific to the subsystem that generated the TI.
365135793a8SBen Tyner         if ((0 != pelId) && (true == tiEvent))
366f5210bb6SBen Tyner         {
367f5210bb6SBen Tyner             // get file descriptor and size of information PEL
368188f1096SBen Tyner             int pelFd = getPel(pelId);
3691b1915efSBen Tyner 
370f5210bb6SBen Tyner             // if PEL found, read into buffer
371f5210bb6SBen Tyner             if (-1 != pelFd)
372f5210bb6SBen Tyner             {
373f5210bb6SBen Tyner                 auto pelSize = lseek(pelFd, 0, SEEK_END);
374f5210bb6SBen Tyner                 lseek(pelFd, 0, SEEK_SET);
3751b1915efSBen Tyner 
376f5210bb6SBen Tyner                 // read information PEL into buffer
377f5210bb6SBen Tyner                 std::vector<uint8_t> buffer(pelSize);
378d700609cSBen Tyner                 size_t numBytes = read(pelFd, buffer.data(), buffer.size());
379d700609cSBen Tyner                 if (buffer.size() != numBytes)
380d700609cSBen Tyner                 {
381bfa831a8Saustinfcui                     trace::err("Error reading event log: %u of %u bytes read",
382bfa831a8Saustinfcui                                numBytes, buffer.size());
383d700609cSBen Tyner                 }
384d700609cSBen Tyner                 else
385d700609cSBen Tyner                 {
386f5210bb6SBen Tyner                     // create PEL from buffer
387f5210bb6SBen Tyner                     createPelCustom(buffer, i_additional);
388f5210bb6SBen Tyner                 }
389d700609cSBen Tyner 
390d700609cSBen Tyner                 close(pelFd);
391d700609cSBen Tyner             }
3925c5db65aSBen Tyner 
393c49d20b9Saustinfcui             std::map<std::string, std::string>::iterator it;
394c49d20b9Saustinfcui             uint8_t subsystem;
395c49d20b9Saustinfcui 
396c49d20b9Saustinfcui             it = i_additional.find("Subsystem");
397c49d20b9Saustinfcui             if (it != i_additional.end())
398c49d20b9Saustinfcui             {
399c49d20b9Saustinfcui                 subsystem = std::stoi(it->second);
400c49d20b9Saustinfcui             }
401c49d20b9Saustinfcui             else
402c49d20b9Saustinfcui             {
403c49d20b9Saustinfcui                 // The entry with key "Subsystem" does not exist in the
404c49d20b9Saustinfcui                 // additional map. Log the error, create failure event, and
405c49d20b9Saustinfcui                 // return.
40667b8229bSZane Shelley                 trace::err(
40767b8229bSZane Shelley                     "Error the key Subsystem does not exist in the map.");
408c49d20b9Saustinfcui                 eventAttentionFail((int)AttnSection::attnLogging |
409c49d20b9Saustinfcui                                    ATTN_INVALID_KEY);
410c49d20b9Saustinfcui                 return 0;
411c49d20b9Saustinfcui             }
4125c5db65aSBen Tyner 
4135c5db65aSBen Tyner             // If not hypervisor TI
4145c5db65aSBen Tyner             if (static_cast<uint8_t>(pel::SubsystemID::hypervisor) != subsystem)
4155c5db65aSBen Tyner             {
4165c5db65aSBen Tyner                 // Request a dump and transition the host
4175c5db65aSBen Tyner                 if ("true" == i_additional["Dump"])
4185c5db65aSBen Tyner                 {
4196bc43c9bSBen Tyner                     // will not return until dump is complete
420611b3442SZane Shelley                     requestDump(pelId, DumpParameters{0, DumpType::Hostboot});
4216bc43c9bSBen Tyner                 }
4225c5db65aSBen Tyner             }
4235c5db65aSBen Tyner         }
424b1ebfcb1SBen Tyner     }
4257f6ce6acSBen Tyner     return pelId;
426b1ebfcb1SBen Tyner }
427b1ebfcb1SBen Tyner 
428f5210bb6SBen Tyner /**
429f5210bb6SBen Tyner  * Commit special attention TI event to log
430f5210bb6SBen Tyner  *
431f5210bb6SBen Tyner  * Create a event log with provided additional information and standard
432f5210bb6SBen Tyner  * FFDC data plus TI FFDC data
433f5210bb6SBen Tyner  *
434f5210bb6SBen Tyner  * @param i_additional - Additional log data
435f5210bb6SBen Tyner  * @param i_ti_InfoData - TI FFDC data
436f5210bb6SBen Tyner  */
eventTerminate(std::map<std::string,std::string> i_additionalData,char * i_tiInfoData)437f5210bb6SBen Tyner void eventTerminate(std::map<std::string, std::string> i_additionalData,
438f5210bb6SBen Tyner                     char* i_tiInfoData)
439b1ebfcb1SBen Tyner {
44029651ef8SBen Tyner     uint32_t tiInfoSize = 0; // assume TI info was not available
44129651ef8SBen Tyner 
44229651ef8SBen Tyner     if (nullptr != i_tiInfoData)
44329651ef8SBen Tyner     {
44429651ef8SBen Tyner         tiInfoSize = 56; // assume not hypervisor TI
445b6401edfSBen Tyner 
446c49d20b9Saustinfcui         std::map<std::string, std::string>::iterator it;
447c49d20b9Saustinfcui         uint8_t subsystem;
448c49d20b9Saustinfcui 
449c49d20b9Saustinfcui         it = i_additionalData.find("Subsystem");
450c49d20b9Saustinfcui         if (it != i_additionalData.end())
451c49d20b9Saustinfcui         {
452c49d20b9Saustinfcui             subsystem = std::stoi(it->second);
453c49d20b9Saustinfcui         }
454c49d20b9Saustinfcui         else
455c49d20b9Saustinfcui         {
456c49d20b9Saustinfcui             // The entry with key "Subsystem" does not exist in the additional
457c49d20b9Saustinfcui             // map. Log the error, create failure event, and return.
45867b8229bSZane Shelley             trace::err("Error the key Subsystem does not exist in the map.");
459c49d20b9Saustinfcui             eventAttentionFail((int)AttnSection::attnLogging |
460c49d20b9Saustinfcui                                ATTN_INVALID_KEY);
461c49d20b9Saustinfcui             return;
462c49d20b9Saustinfcui         }
463b6401edfSBen Tyner 
464b6401edfSBen Tyner         // If hypervisor
465b6401edfSBen Tyner         if (static_cast<uint8_t>(pel::SubsystemID::hypervisor) == subsystem)
466b6401edfSBen Tyner         {
467b6401edfSBen Tyner             tiInfoSize = 1024; // assume hypervisor max
468b6401edfSBen Tyner 
469b6401edfSBen Tyner             // hypervisor may just want some of the data
470b6401edfSBen Tyner             if (0 == (*(i_tiInfoData + 0x09) & 0x01))
471b6401edfSBen Tyner             {
472b6401edfSBen Tyner                 uint32_t* additionalLength = (uint32_t*)(i_tiInfoData + 0x50);
473b6401edfSBen Tyner                 uint32_t tiAdditional = be32toh(*additionalLength);
474b6401edfSBen Tyner                 tiInfoSize = std::min(tiInfoSize, (84 + tiAdditional));
475b6401edfSBen Tyner             }
476b6401edfSBen Tyner         }
47729651ef8SBen Tyner     }
478b6401edfSBen Tyner 
479bfa831a8Saustinfcui     trace::inf("TI info size = %u", tiInfoSize);
480b6401edfSBen Tyner 
481*4d3f093aSZane Shelley     event(EventType::Terminate, i_additionalData,
482*4d3f093aSZane Shelley           createFFDCFiles(i_tiInfoData, tiInfoSize));
483b1ebfcb1SBen Tyner }
484b1ebfcb1SBen Tyner 
4857f6ce6acSBen Tyner /** @brief Commit SBE vital event to log, returns event log ID */
eventVital(std::string severity)48690516851SBen Tyner uint32_t eventVital(std::string severity)
487b1ebfcb1SBen Tyner {
488f5210bb6SBen Tyner     // Additional data for log
489b1ebfcb1SBen Tyner     std::map<std::string, std::string> additionalData;
490b1ebfcb1SBen Tyner 
491f5210bb6SBen Tyner     // Create log event with additional data and FFDC data
49290516851SBen Tyner     return event(EventType::Vital, additionalData, createFFDCFiles(nullptr, 0),
49390516851SBen Tyner                  severity);
494b1ebfcb1SBen Tyner }
495b1ebfcb1SBen Tyner 
496f5210bb6SBen Tyner /**
497f5210bb6SBen Tyner  * Commit attention handler failure event to log
498f5210bb6SBen Tyner  *
499f5210bb6SBen Tyner  * Create an event log containing the specified error code.
500f5210bb6SBen Tyner  *
501f5210bb6SBen Tyner  * @param i_error - Error code
502f5210bb6SBen Tyner  */
eventAttentionFail(int i_error)503f5210bb6SBen Tyner void eventAttentionFail(int i_error)
504f5210bb6SBen Tyner {
505f5210bb6SBen Tyner     // Additional data for log
506f5210bb6SBen Tyner     std::map<std::string, std::string> additionalData;
507f5210bb6SBen Tyner     additionalData["ERROR_CODE"] = std::to_string(i_error);
508f5210bb6SBen Tyner 
509f5210bb6SBen Tyner     // Create log event with additional data and FFDC data
510f5210bb6SBen Tyner     event(EventType::AttentionFail, additionalData,
511f5210bb6SBen Tyner           createFFDCFiles(nullptr, 0));
512f5210bb6SBen Tyner }
513f5210bb6SBen Tyner 
514b1ebfcb1SBen Tyner } // namespace attn
515