blob: 40501a5cfdf429f5b14212d093e72cae48c3411c [file] [log] [blame]
Matt Spinler711d51d2019-11-06 09:36:51 -06001/**
2 * Copyright © 2019 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 */
Matt Spinler4e8078c2019-07-09 13:22:32 -050016#include "manager.hpp"
17
18#include "additional_data.hpp"
Matt Spinler05c2c6c2019-12-18 14:02:09 -060019#include "json_utils.hpp"
Matt Spinler89fa0822019-07-17 13:54:30 -050020#include "pel.hpp"
21
Matt Spinler6b1a5c82020-01-07 08:48:53 -060022#include <unistd.h>
23
Matt Spinler89fa0822019-07-17 13:54:30 -050024#include <filesystem>
25#include <fstream>
Matt Spinlera34ab722019-12-16 10:39:32 -060026#include <xyz/openbmc_project/Common/error.hpp>
Matt Spinler4e8078c2019-07-09 13:22:32 -050027
28namespace openpower
29{
30namespace pels
31{
32
33using namespace phosphor::logging;
Matt Spinler89fa0822019-07-17 13:54:30 -050034namespace fs = std::filesystem;
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080035namespace rg = openpower::pels::message;
Matt Spinler4e8078c2019-07-09 13:22:32 -050036
Matt Spinlera34ab722019-12-16 10:39:32 -060037namespace common_error = sdbusplus::xyz::openbmc_project::Common::Error;
38
Matt Spinler4e8078c2019-07-09 13:22:32 -050039namespace additional_data
40{
41constexpr auto rawPEL = "RAWPEL";
42}
43
44void Manager::create(const std::string& message, uint32_t obmcLogID,
45 uint64_t timestamp, Entry::Level severity,
46 const std::vector<std::string>& additionalData,
47 const std::vector<std::string>& associations)
48{
49 AdditionalData ad{additionalData};
50
51 // If a PEL was passed in, use that. Otherwise, create one.
52 auto rawPelPath = ad.getValue(additional_data::rawPEL);
53 if (rawPelPath)
54 {
55 addRawPEL(*rawPelPath, obmcLogID);
56 }
57 else
58 {
59 createPEL(message, obmcLogID, timestamp, severity, additionalData,
60 associations);
61 }
62}
63
64void Manager::addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID)
65{
Matt Spinler89fa0822019-07-17 13:54:30 -050066 if (fs::exists(rawPelPath))
67 {
68 std::ifstream file(rawPelPath, std::ios::in | std::ios::binary);
69
70 auto data = std::vector<uint8_t>(std::istreambuf_iterator<char>(file),
71 std::istreambuf_iterator<char>());
72 if (file.fail())
73 {
74 log<level::ERR>("Filesystem error reading a raw PEL",
75 entry("PELFILE=%s", rawPelPath.c_str()),
76 entry("OBMCLOGID=%d", obmcLogID));
77 // TODO, Decide what to do here. Maybe nothing.
78 return;
79 }
80
81 file.close();
82
Matt Spinlera34ab722019-12-16 10:39:32 -060083 auto pel = std::make_unique<openpower::pels::PEL>(data, obmcLogID);
Matt Spinler89fa0822019-07-17 13:54:30 -050084 if (pel->valid())
85 {
86 // PELs created by others still need these fields set by us.
87 pel->assignID();
88 pel->setCommitTime();
89
90 try
91 {
92 _repo.add(pel);
93 }
94 catch (std::exception& e)
95 {
96 // Probably a full or r/o filesystem, not much we can do.
97 log<level::ERR>("Unable to add PEL to Repository",
98 entry("PEL_ID=0x%X", pel->id()));
99 }
100 }
101 else
102 {
103 log<level::ERR>("Invalid PEL found",
104 entry("PELFILE=%s", rawPelPath.c_str()),
105 entry("OBMCLOGID=%d", obmcLogID));
106 // TODO, make a whole new OpenBMC event log + PEL
107 }
108 }
109 else
110 {
111 log<level::ERR>("Raw PEL file from BMC event log does not exist",
112 entry("PELFILE=%s", (rawPelPath).c_str()),
113 entry("OBMCLOGID=%d", obmcLogID));
114 }
Matt Spinler4e8078c2019-07-09 13:22:32 -0500115}
116
117void Manager::erase(uint32_t obmcLogID)
118{
Matt Spinler475e5742019-07-18 16:09:49 -0500119 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
120
121 _repo.remove(id);
Matt Spinler4e8078c2019-07-09 13:22:32 -0500122}
123
124bool Manager::isDeleteProhibited(uint32_t obmcLogID)
125{
126 return false;
127}
128
129void Manager::createPEL(const std::string& message, uint32_t obmcLogID,
130 uint64_t timestamp,
131 phosphor::logging::Entry::Level severity,
132 const std::vector<std::string>& additionalData,
133 const std::vector<std::string>& associations)
134{
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800135 auto entry = _registry.lookup(message, rg::LookupType::name);
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600136 std::string msg;
Matt Spinler67456c22019-10-21 12:22:49 -0500137
138 if (entry)
139 {
140 AdditionalData ad{additionalData};
141
Matt Spinlera34ab722019-12-16 10:39:32 -0600142 auto pel = std::make_unique<openpower::pels::PEL>(
143 *entry, obmcLogID, timestamp, severity, ad, *_dataIface);
Matt Spinler67456c22019-10-21 12:22:49 -0500144
145 _repo.add(pel);
Matt Spinler67456c22019-10-21 12:22:49 -0500146
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600147 auto src = pel->primarySRC();
148 if (src)
149 {
150 using namespace std::literals::string_literals;
151 char id[11];
152 sprintf(id, "0x%08X", pel->id());
153 msg = "Created PEL "s + id + " with SRC "s + (*src)->asciiString();
154 while (msg.back() == ' ')
155 {
156 msg.pop_back();
157 }
158 log<level::INFO>(msg.c_str());
159 }
160 }
161 else
162 {
163 // TODO ibm-openbmc/dev/1151: Create a new PEL for this case.
164 // For now, just trace it.
165 msg = "Event not found in PEL message registry: " + message;
166 log<level::INFO>(msg.c_str());
167 }
Matt Spinler4e8078c2019-07-09 13:22:32 -0500168}
169
Matt Spinlera34ab722019-12-16 10:39:32 -0600170sdbusplus::message::unix_fd Manager::getPEL(uint32_t pelID)
171{
172 Repository::LogID id{Repository::LogID::Pel(pelID)};
173 std::optional<int> fd;
174
175 try
176 {
177 fd = _repo.getPELFD(id);
178 }
179 catch (std::exception& e)
180 {
181 throw common_error::InternalFailure();
182 }
183
184 if (!fd)
185 {
186 throw common_error::InvalidArgument();
187 }
188
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600189 scheduleFDClose(*fd);
190
Matt Spinlera34ab722019-12-16 10:39:32 -0600191 return *fd;
192}
193
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600194void Manager::scheduleFDClose(int fd)
195{
196 _fdCloserEventSource = std::make_unique<sdeventplus::source::Defer>(
197 _logManager.getBus().get_event(),
198 std::bind(std::mem_fn(&Manager::closeFD), this, fd,
199 std::placeholders::_1));
200}
201
202void Manager::closeFD(int fd, sdeventplus::source::EventBase& source)
203{
204 close(fd);
205 _fdCloserEventSource.reset();
206}
207
Matt Spinlera34ab722019-12-16 10:39:32 -0600208std::vector<uint8_t> Manager::getPELFromOBMCID(uint32_t obmcLogID)
209{
210 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
211 std::optional<std::vector<uint8_t>> data;
212
213 try
214 {
215 data = _repo.getPELData(id);
216 }
217 catch (std::exception& e)
218 {
219 throw common_error::InternalFailure();
220 }
221
222 if (!data)
223 {
224 throw common_error::InvalidArgument();
225 }
226
227 return *data;
228}
229
230void Manager::hostAck(uint32_t pelID)
231{
232 Repository::LogID id{Repository::LogID::Pel(pelID)};
233
234 if (!_repo.hasPEL(id))
235 {
236 throw common_error::InvalidArgument();
237 }
238
239 if (_hostNotifier)
240 {
241 _hostNotifier->ackPEL(pelID);
242 }
243}
244
245void Manager::hostReject(uint32_t pelID, RejectionReason reason)
246{
247 Repository::LogID id{Repository::LogID::Pel(pelID)};
248
249 if (!_repo.hasPEL(id))
250 {
251 throw common_error::InvalidArgument();
252 }
253
Matt Spinler05c2c6c2019-12-18 14:02:09 -0600254 if (reason == RejectionReason::BadPEL)
Matt Spinlera34ab722019-12-16 10:39:32 -0600255 {
Matt Spinler05c2c6c2019-12-18 14:02:09 -0600256 AdditionalData data;
257 data.add("BAD_ID", getNumberString("0x%08X", pelID));
258 _eventLogger.log("org.open_power.Logging.Error.SentBadPELToHost",
259 Entry::Level::Informational, data);
260 if (_hostNotifier)
Matt Spinlera34ab722019-12-16 10:39:32 -0600261 {
262 _hostNotifier->setBadPEL(pelID);
263 }
Matt Spinler05c2c6c2019-12-18 14:02:09 -0600264 }
265 else if ((reason == RejectionReason::HostFull) && _hostNotifier)
266 {
267 _hostNotifier->setHostFull(pelID);
Matt Spinlera34ab722019-12-16 10:39:32 -0600268 }
269}
270
Matt Spinler4e8078c2019-07-09 13:22:32 -0500271} // namespace pels
272} // namespace openpower