blob: e90814f5e023860b8e09a6b2c54aa9bf00b735ef [file] [log] [blame]
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -05001/**
2 * Copyright © 2021 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jayanth Othayoth66e186d2021-06-15 22:44:35 -050017extern "C" {
18#include <libpdbg.h>
19}
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050020
Jayanth Othayothc74c2202021-06-04 06:42:43 -050021#include "fapi_data_process.hpp"
22#include "pel.hpp"
Jayanth Othayoth66e186d2021-06-15 22:44:35 -050023#include "sbe_ffdc_handler.hpp"
Jayanth Othayothc74c2202021-06-04 06:42:43 -050024#include "temporary_file.hpp"
25
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050026#include <ekb/hwpf/fapi2/include/return_code_defs.H>
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050027#include <fmt/format.h>
Jayanth Othayotheff307e2021-07-15 03:27:01 -050028#include <libekb.H>
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050029
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050030#include <new>
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050031#include <phosphor-logging/log.hpp>
32
33namespace openpower
34{
35namespace pels
36{
37namespace sbe
38{
39
40using namespace phosphor::logging;
41
42SbeFFDC::SbeFFDC(const AdditionalData& aData, const PelFFDC& files)
43{
44 log<level::INFO>("SBE FFDC processing requested");
45
46 // SRC6 field in the additional data contains Processor position
47 // associated to the SBE FFDC
48 //"[0:15] chip position"
49 auto src6 = aData.getValue("SRC6");
50 if (src6 == std::nullopt)
51 {
52 log<level::ERR>("Fail to extract SRC6 data: failing to get proc index");
53 return;
54 }
55 try
56 {
57 procPos = std::stoi((src6.value()).substr(0, 4));
58 }
Patrick Williams66491c62021-10-06 12:23:37 -050059 catch (const std::exception& err)
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050060 {
61 log<level::ERR>(
62 fmt::format("Conversion failure errormsg({})", err.what()).c_str());
63 return;
64 }
65
66 if (files.empty())
67 {
68 log<level::INFO>("SbeFFDC : No files found, skipping ffdc processing");
69 return;
70 }
71
72 for (const auto& file : files)
73 {
74 if ((file.format == UserDataFormat::custom) &&
75 (file.subType == sbeFFDCSubType))
76 {
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050077 // Process SBE file.
78 parse(file.fd);
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050079 }
80 }
81}
82
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050083void SbeFFDC::parse(int fd)
84{
85 log<level::INFO>(
86 fmt::format("SBE FFDC file fd:({}), parsing started", fd).c_str());
87
88 uint32_t ffdcBufOffset = 0;
89 uint32_t pktCount = 0;
90 sbeFfdcPacketType ffdcPkt;
91
92 // get SBE FFDC data.
93 auto ffdcData = util::readFD(fd);
94 if (ffdcData.empty())
95 {
96 log<level::ERR>(
97 fmt::format("Empty SBE FFDC file fd:({}), skipping", fd).c_str());
98 return;
99 }
100
101 while ((ffdcBufOffset < ffdcData.size()) && (sbeMaxFfdcPackets != pktCount))
102 {
103 // Next un-extracted FFDC Packet
104 fapiFfdcBufType* ffdc =
105 reinterpret_cast<fapiFfdcBufType*>(ffdcData.data() + ffdcBufOffset);
106 auto magicBytes = ntohs(ffdc->magic_bytes);
107 auto lenWords = ntohs(ffdc->lengthinWords);
108 auto fapiRc = ntohl(ffdc->fapiRc);
109
110 auto msg = fmt::format("FFDC magic: {} length in words:{} Fapirc:{}",
111 magicBytes, lenWords, fapiRc);
112 log<level::INFO>(msg.c_str());
113
114 if (magicBytes != ffdcMagicCode)
115 {
116 log<level::ERR>("Invalid FFDC magic code in Header: Skipping ");
117 return;
118 }
119 ffdcPkt.fapiRc = fapiRc;
120 // Not interested in the first 2 words (these are not ffdc)
121 auto pktLenWords = lenWords - (2 * ffdcPkgOneWord);
122 ffdcPkt.ffdcLengthInWords = pktLenWords;
123 if (pktLenWords)
124 {
125 // Memory freeing will be taking care by ffdcPkt structure
126 // destructor
127 ffdcPkt.ffdcData = new uint32_t[pktLenWords];
128 memcpy(ffdcPkt.ffdcData,
129 ((reinterpret_cast<uint32_t*>(ffdc)) +
130 (2 * ffdcPkgOneWord)), // skip first 2 words
131 (pktLenWords * sizeof(uint32_t)));
132 }
133 else
134 {
135 log<level::ERR>("FFDC packet size is zero skipping");
136 return;
137 }
138
139 // SBE FFDC processing is not required for SBE Plat errors RCs.
140 // Plat errors processing is driven by SBE provided user data
141 // plugins, which need to link with PEL tool infrastructure.
142 if (ffdcPkt.fapiRc != fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA)
143 {
144 process(ffdcPkt);
145 }
Jayanth Othayothfb9b8112021-10-07 04:10:18 -0500146 else
147 {
148 log<level::INFO>("SBE FFDC: Internal FFDC packet");
149 }
150
151 // Update Buffer offset in Bytes
152 ffdcBufOffset += lenWords * sizeof(uint32_t);
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500153 ++pktCount;
154 }
155 if (pktCount == sbeMaxFfdcPackets)
156 {
157 log<level::ERR>(fmt::format("Received more than the limit of ({})"
158 " FFDC packets, processing only ({})",
159 sbeMaxFfdcPackets, pktCount)
160 .c_str());
161 }
162}
163
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500164void SbeFFDC::process(const sbeFfdcPacketType& ffdcPkt)
165{
166 using json = nlohmann::json;
167
168 // formated FFDC data structure after FFDC packet processing
169 FFDC ffdc;
170
Jayanth Othayoth66e186d2021-06-15 22:44:35 -0500171 if (!pdbg_targets_init(NULL))
172 {
173 log<level::ERR>("pdbg_targets_init failed, skipping ffdc processing");
174 return;
175 }
176
Jayanth Othayotheff307e2021-07-15 03:27:01 -0500177 if (libekb_init())
178 {
179 log<level::ERR>("libekb_init failed, skipping ffdc processing");
180 return;
181 }
182
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500183 try
184 {
185 // libekb provided wrapper function to convert SBE FFDC
186 // in to known ffdc structure.
187 libekb_get_sbe_ffdc(ffdc, ffdcPkt, procPos);
188 }
189 catch (...)
190 {
191 log<level::ERR>("libekb_get_sbe_ffdc failed, skipping ffdc processing");
192 return;
193 }
194
195 // To store callouts details in json format as per pel expectation.
196 json pelJSONFmtCalloutDataList;
197 pelJSONFmtCalloutDataList = json::array();
198
199 // To store other user data from FFDC.
200 openpower::pels::phal::FFDCData ffdcUserData;
201
202 // Get FFDC and required info to include in PEL
203 openpower::pels::phal::convertFAPItoPELformat(
204 ffdc, pelJSONFmtCalloutDataList, ffdcUserData);
205
206 // Get callout information and sore in to file.
207 auto calloutData = pelJSONFmtCalloutDataList.dump();
208 util::TemporaryFile ffdcFile(calloutData.c_str(), calloutData.size());
209
210 // Create json callout type pel FFDC file structre.
211 PelFFDCfile pf;
212 pf.format = openpower::pels::UserDataFormat::json;
213 pf.subType = openpower::pels::jsonCalloutSubtype;
214 pf.version = 0x01;
215 pf.fd = ffdcFile.getFd();
216 ffdcFiles.push_back(pf);
217
218 // save the file path to delete the file after usage.
219 paths.push_back(ffdcFile.getPath());
220
221 // Format ffdc user data and create new file.
222 std::string data;
223 for (auto& d : ffdcUserData)
224 {
225 data += d.first + " = " + d.second + "\n";
226 }
227 util::TemporaryFile pelDataFile(data.c_str(), data.size());
228 PelFFDCfile pdf;
229 pdf.format = openpower::pels::UserDataFormat::text;
230 pdf.version = 0x01;
231 pdf.fd = pelDataFile.getFd();
232 ffdcFiles.push_back(pdf);
233
234 paths.push_back(pelDataFile.getPath());
235}
236
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -0500237} // namespace sbe
238} // namespace pels
239} // namespace openpower