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