blob: 9e6a088d1c66015fac99f50895b602746ff1c928 [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
17#include "sbe_ffdc_handler.hpp"
18
Jayanth Othayothc74c2202021-06-04 06:42:43 -050019#include "fapi_data_process.hpp"
20#include "pel.hpp"
21#include "temporary_file.hpp"
22
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050023#include <ekb/hwpf/fapi2/include/return_code_defs.H>
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050024#include <fmt/format.h>
25
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050026#include <new>
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050027#include <phosphor-logging/log.hpp>
28
29namespace openpower
30{
31namespace pels
32{
33namespace sbe
34{
35
36using namespace phosphor::logging;
37
38SbeFFDC::SbeFFDC(const AdditionalData& aData, const PelFFDC& files)
39{
40 log<level::INFO>("SBE FFDC processing requested");
41
42 // SRC6 field in the additional data contains Processor position
43 // associated to the SBE FFDC
44 //"[0:15] chip position"
45 auto src6 = aData.getValue("SRC6");
46 if (src6 == std::nullopt)
47 {
48 log<level::ERR>("Fail to extract SRC6 data: failing to get proc index");
49 return;
50 }
51 try
52 {
53 procPos = std::stoi((src6.value()).substr(0, 4));
54 }
55 catch (std::exception& err)
56 {
57 log<level::ERR>(
58 fmt::format("Conversion failure errormsg({})", err.what()).c_str());
59 return;
60 }
61
62 if (files.empty())
63 {
64 log<level::INFO>("SbeFFDC : No files found, skipping ffdc processing");
65 return;
66 }
67
68 for (const auto& file : files)
69 {
70 if ((file.format == UserDataFormat::custom) &&
71 (file.subType == sbeFFDCSubType))
72 {
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050073 // Process SBE file.
74 parse(file.fd);
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050075 }
76 }
77}
78
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050079void SbeFFDC::parse(int fd)
80{
81 log<level::INFO>(
82 fmt::format("SBE FFDC file fd:({}), parsing started", fd).c_str());
83
84 uint32_t ffdcBufOffset = 0;
85 uint32_t pktCount = 0;
86 sbeFfdcPacketType ffdcPkt;
87
88 // get SBE FFDC data.
89 auto ffdcData = util::readFD(fd);
90 if (ffdcData.empty())
91 {
92 log<level::ERR>(
93 fmt::format("Empty SBE FFDC file fd:({}), skipping", fd).c_str());
94 return;
95 }
96
97 while ((ffdcBufOffset < ffdcData.size()) && (sbeMaxFfdcPackets != pktCount))
98 {
99 // Next un-extracted FFDC Packet
100 fapiFfdcBufType* ffdc =
101 reinterpret_cast<fapiFfdcBufType*>(ffdcData.data() + ffdcBufOffset);
102 auto magicBytes = ntohs(ffdc->magic_bytes);
103 auto lenWords = ntohs(ffdc->lengthinWords);
104 auto fapiRc = ntohl(ffdc->fapiRc);
105
106 auto msg = fmt::format("FFDC magic: {} length in words:{} Fapirc:{}",
107 magicBytes, lenWords, fapiRc);
108 log<level::INFO>(msg.c_str());
109
110 if (magicBytes != ffdcMagicCode)
111 {
112 log<level::ERR>("Invalid FFDC magic code in Header: Skipping ");
113 return;
114 }
115 ffdcPkt.fapiRc = fapiRc;
116 // Not interested in the first 2 words (these are not ffdc)
117 auto pktLenWords = lenWords - (2 * ffdcPkgOneWord);
118 ffdcPkt.ffdcLengthInWords = pktLenWords;
119 if (pktLenWords)
120 {
121 // Memory freeing will be taking care by ffdcPkt structure
122 // destructor
123 ffdcPkt.ffdcData = new uint32_t[pktLenWords];
124 memcpy(ffdcPkt.ffdcData,
125 ((reinterpret_cast<uint32_t*>(ffdc)) +
126 (2 * ffdcPkgOneWord)), // skip first 2 words
127 (pktLenWords * sizeof(uint32_t)));
128 }
129 else
130 {
131 log<level::ERR>("FFDC packet size is zero skipping");
132 return;
133 }
134
135 // SBE FFDC processing is not required for SBE Plat errors RCs.
136 // Plat errors processing is driven by SBE provided user data
137 // plugins, which need to link with PEL tool infrastructure.
138 if (ffdcPkt.fapiRc != fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA)
139 {
140 process(ffdcPkt);
141 }
142 ffdcBufOffset += ffdc->lengthinWords;
143 ++pktCount;
144 }
145 if (pktCount == sbeMaxFfdcPackets)
146 {
147 log<level::ERR>(fmt::format("Received more than the limit of ({})"
148 " FFDC packets, processing only ({})",
149 sbeMaxFfdcPackets, pktCount)
150 .c_str());
151 }
152}
153
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500154void SbeFFDC::process(const sbeFfdcPacketType& ffdcPkt)
155{
156 using json = nlohmann::json;
157
158 // formated FFDC data structure after FFDC packet processing
159 FFDC ffdc;
160
161 try
162 {
163 // libekb provided wrapper function to convert SBE FFDC
164 // in to known ffdc structure.
165 libekb_get_sbe_ffdc(ffdc, ffdcPkt, procPos);
166 }
167 catch (...)
168 {
169 log<level::ERR>("libekb_get_sbe_ffdc failed, skipping ffdc processing");
170 return;
171 }
172
173 // To store callouts details in json format as per pel expectation.
174 json pelJSONFmtCalloutDataList;
175 pelJSONFmtCalloutDataList = json::array();
176
177 // To store other user data from FFDC.
178 openpower::pels::phal::FFDCData ffdcUserData;
179
180 // Get FFDC and required info to include in PEL
181 openpower::pels::phal::convertFAPItoPELformat(
182 ffdc, pelJSONFmtCalloutDataList, ffdcUserData);
183
184 // Get callout information and sore in to file.
185 auto calloutData = pelJSONFmtCalloutDataList.dump();
186 util::TemporaryFile ffdcFile(calloutData.c_str(), calloutData.size());
187
188 // Create json callout type pel FFDC file structre.
189 PelFFDCfile pf;
190 pf.format = openpower::pels::UserDataFormat::json;
191 pf.subType = openpower::pels::jsonCalloutSubtype;
192 pf.version = 0x01;
193 pf.fd = ffdcFile.getFd();
194 ffdcFiles.push_back(pf);
195
196 // save the file path to delete the file after usage.
197 paths.push_back(ffdcFile.getPath());
198
199 // Format ffdc user data and create new file.
200 std::string data;
201 for (auto& d : ffdcUserData)
202 {
203 data += d.first + " = " + d.second + "\n";
204 }
205 util::TemporaryFile pelDataFile(data.c_str(), data.size());
206 PelFFDCfile pdf;
207 pdf.format = openpower::pels::UserDataFormat::text;
208 pdf.version = 0x01;
209 pdf.fd = pelDataFile.getFd();
210 ffdcFiles.push_back(pdf);
211
212 paths.push_back(pelDataFile.getPath());
213}
214
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -0500215} // namespace sbe
216} // namespace pels
217} // namespace openpower