blob: a00da37387e9331e42f701d657b08689cee4e236 [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 Spinler89fa0822019-07-17 13:54:30 -050019#include "pel.hpp"
20
Matt Spinler6b1a5c82020-01-07 08:48:53 -060021#include <unistd.h>
22
Matt Spinler89fa0822019-07-17 13:54:30 -050023#include <filesystem>
24#include <fstream>
Matt Spinlera34ab722019-12-16 10:39:32 -060025#include <xyz/openbmc_project/Common/error.hpp>
Matt Spinler4e8078c2019-07-09 13:22:32 -050026
27namespace openpower
28{
29namespace pels
30{
31
32using namespace phosphor::logging;
Matt Spinler89fa0822019-07-17 13:54:30 -050033namespace fs = std::filesystem;
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +080034namespace rg = openpower::pels::message;
Matt Spinler4e8078c2019-07-09 13:22:32 -050035
Matt Spinlera34ab722019-12-16 10:39:32 -060036namespace common_error = sdbusplus::xyz::openbmc_project::Common::Error;
37
Matt Spinler4e8078c2019-07-09 13:22:32 -050038namespace additional_data
39{
40constexpr auto rawPEL = "RAWPEL";
41}
42
43void Manager::create(const std::string& message, uint32_t obmcLogID,
44 uint64_t timestamp, Entry::Level severity,
45 const std::vector<std::string>& additionalData,
46 const std::vector<std::string>& associations)
47{
48 AdditionalData ad{additionalData};
49
50 // If a PEL was passed in, use that. Otherwise, create one.
51 auto rawPelPath = ad.getValue(additional_data::rawPEL);
52 if (rawPelPath)
53 {
54 addRawPEL(*rawPelPath, obmcLogID);
55 }
56 else
57 {
58 createPEL(message, obmcLogID, timestamp, severity, additionalData,
59 associations);
60 }
61}
62
63void Manager::addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID)
64{
Matt Spinler89fa0822019-07-17 13:54:30 -050065 if (fs::exists(rawPelPath))
66 {
67 std::ifstream file(rawPelPath, std::ios::in | std::ios::binary);
68
69 auto data = std::vector<uint8_t>(std::istreambuf_iterator<char>(file),
70 std::istreambuf_iterator<char>());
71 if (file.fail())
72 {
73 log<level::ERR>("Filesystem error reading a raw PEL",
74 entry("PELFILE=%s", rawPelPath.c_str()),
75 entry("OBMCLOGID=%d", obmcLogID));
76 // TODO, Decide what to do here. Maybe nothing.
77 return;
78 }
79
80 file.close();
81
Matt Spinlera34ab722019-12-16 10:39:32 -060082 auto pel = std::make_unique<openpower::pels::PEL>(data, obmcLogID);
Matt Spinler89fa0822019-07-17 13:54:30 -050083 if (pel->valid())
84 {
85 // PELs created by others still need these fields set by us.
86 pel->assignID();
87 pel->setCommitTime();
88
89 try
90 {
91 _repo.add(pel);
92 }
93 catch (std::exception& e)
94 {
95 // Probably a full or r/o filesystem, not much we can do.
96 log<level::ERR>("Unable to add PEL to Repository",
97 entry("PEL_ID=0x%X", pel->id()));
98 }
99 }
100 else
101 {
102 log<level::ERR>("Invalid PEL found",
103 entry("PELFILE=%s", rawPelPath.c_str()),
104 entry("OBMCLOGID=%d", obmcLogID));
105 // TODO, make a whole new OpenBMC event log + PEL
106 }
107 }
108 else
109 {
110 log<level::ERR>("Raw PEL file from BMC event log does not exist",
111 entry("PELFILE=%s", (rawPelPath).c_str()),
112 entry("OBMCLOGID=%d", obmcLogID));
113 }
Matt Spinler4e8078c2019-07-09 13:22:32 -0500114}
115
116void Manager::erase(uint32_t obmcLogID)
117{
Matt Spinler475e5742019-07-18 16:09:49 -0500118 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
119
120 _repo.remove(id);
Matt Spinler4e8078c2019-07-09 13:22:32 -0500121}
122
123bool Manager::isDeleteProhibited(uint32_t obmcLogID)
124{
125 return false;
126}
127
128void Manager::createPEL(const std::string& message, uint32_t obmcLogID,
129 uint64_t timestamp,
130 phosphor::logging::Entry::Level severity,
131 const std::vector<std::string>& additionalData,
132 const std::vector<std::string>& associations)
133{
Harisuddin Mohamed Isa0f717e12020-01-15 20:05:33 +0800134 auto entry = _registry.lookup(message, rg::LookupType::name);
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600135 std::string msg;
Matt Spinler67456c22019-10-21 12:22:49 -0500136
137 if (entry)
138 {
139 AdditionalData ad{additionalData};
140
Matt Spinlera34ab722019-12-16 10:39:32 -0600141 auto pel = std::make_unique<openpower::pels::PEL>(
142 *entry, obmcLogID, timestamp, severity, ad, *_dataIface);
Matt Spinler67456c22019-10-21 12:22:49 -0500143
144 _repo.add(pel);
Matt Spinler67456c22019-10-21 12:22:49 -0500145
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600146 auto src = pel->primarySRC();
147 if (src)
148 {
149 using namespace std::literals::string_literals;
150 char id[11];
151 sprintf(id, "0x%08X", pel->id());
152 msg = "Created PEL "s + id + " with SRC "s + (*src)->asciiString();
153 while (msg.back() == ' ')
154 {
155 msg.pop_back();
156 }
157 log<level::INFO>(msg.c_str());
158 }
159 }
160 else
161 {
162 // TODO ibm-openbmc/dev/1151: Create a new PEL for this case.
163 // For now, just trace it.
164 msg = "Event not found in PEL message registry: " + message;
165 log<level::INFO>(msg.c_str());
166 }
Matt Spinler4e8078c2019-07-09 13:22:32 -0500167}
168
Matt Spinlera34ab722019-12-16 10:39:32 -0600169sdbusplus::message::unix_fd Manager::getPEL(uint32_t pelID)
170{
171 Repository::LogID id{Repository::LogID::Pel(pelID)};
172 std::optional<int> fd;
173
174 try
175 {
176 fd = _repo.getPELFD(id);
177 }
178 catch (std::exception& e)
179 {
180 throw common_error::InternalFailure();
181 }
182
183 if (!fd)
184 {
185 throw common_error::InvalidArgument();
186 }
187
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600188 scheduleFDClose(*fd);
189
Matt Spinlera34ab722019-12-16 10:39:32 -0600190 return *fd;
191}
192
Matt Spinler6b1a5c82020-01-07 08:48:53 -0600193void Manager::scheduleFDClose(int fd)
194{
195 _fdCloserEventSource = std::make_unique<sdeventplus::source::Defer>(
196 _logManager.getBus().get_event(),
197 std::bind(std::mem_fn(&Manager::closeFD), this, fd,
198 std::placeholders::_1));
199}
200
201void Manager::closeFD(int fd, sdeventplus::source::EventBase& source)
202{
203 close(fd);
204 _fdCloserEventSource.reset();
205}
206
Matt Spinlera34ab722019-12-16 10:39:32 -0600207std::vector<uint8_t> Manager::getPELFromOBMCID(uint32_t obmcLogID)
208{
209 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
210 std::optional<std::vector<uint8_t>> data;
211
212 try
213 {
214 data = _repo.getPELData(id);
215 }
216 catch (std::exception& e)
217 {
218 throw common_error::InternalFailure();
219 }
220
221 if (!data)
222 {
223 throw common_error::InvalidArgument();
224 }
225
226 return *data;
227}
228
229void Manager::hostAck(uint32_t pelID)
230{
231 Repository::LogID id{Repository::LogID::Pel(pelID)};
232
233 if (!_repo.hasPEL(id))
234 {
235 throw common_error::InvalidArgument();
236 }
237
238 if (_hostNotifier)
239 {
240 _hostNotifier->ackPEL(pelID);
241 }
242}
243
244void Manager::hostReject(uint32_t pelID, RejectionReason reason)
245{
246 Repository::LogID id{Repository::LogID::Pel(pelID)};
247
248 if (!_repo.hasPEL(id))
249 {
250 throw common_error::InvalidArgument();
251 }
252
253 if (_hostNotifier)
254 {
255 if (reason == RejectionReason::BadPEL)
256 {
257 _hostNotifier->setBadPEL(pelID);
258 }
259 else if (reason == RejectionReason::HostFull)
260 {
261 _hostNotifier->setHostFull(pelID);
262 }
263 }
264}
265
Matt Spinler4e8078c2019-07-09 13:22:32 -0500266} // namespace pels
267} // namespace openpower