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