blob: aec5053b8eaa2ddc7130ba14a52861d61f078c7f [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
21#include <filesystem>
22#include <fstream>
Matt Spinlera34ab722019-12-16 10:39:32 -060023#include <xyz/openbmc_project/Common/error.hpp>
Matt Spinler4e8078c2019-07-09 13:22:32 -050024
25namespace openpower
26{
27namespace pels
28{
29
30using namespace phosphor::logging;
Matt Spinler89fa0822019-07-17 13:54:30 -050031namespace fs = std::filesystem;
Matt Spinler4e8078c2019-07-09 13:22:32 -050032
Matt Spinlera34ab722019-12-16 10:39:32 -060033namespace common_error = sdbusplus::xyz::openbmc_project::Common::Error;
34
Matt Spinler4e8078c2019-07-09 13:22:32 -050035namespace additional_data
36{
37constexpr auto rawPEL = "RAWPEL";
38}
39
40void Manager::create(const std::string& message, uint32_t obmcLogID,
41 uint64_t timestamp, Entry::Level severity,
42 const std::vector<std::string>& additionalData,
43 const std::vector<std::string>& associations)
44{
45 AdditionalData ad{additionalData};
46
47 // If a PEL was passed in, use that. Otherwise, create one.
48 auto rawPelPath = ad.getValue(additional_data::rawPEL);
49 if (rawPelPath)
50 {
51 addRawPEL(*rawPelPath, obmcLogID);
52 }
53 else
54 {
55 createPEL(message, obmcLogID, timestamp, severity, additionalData,
56 associations);
57 }
58}
59
60void Manager::addRawPEL(const std::string& rawPelPath, uint32_t obmcLogID)
61{
Matt Spinler89fa0822019-07-17 13:54:30 -050062 if (fs::exists(rawPelPath))
63 {
64 std::ifstream file(rawPelPath, std::ios::in | std::ios::binary);
65
66 auto data = std::vector<uint8_t>(std::istreambuf_iterator<char>(file),
67 std::istreambuf_iterator<char>());
68 if (file.fail())
69 {
70 log<level::ERR>("Filesystem error reading a raw PEL",
71 entry("PELFILE=%s", rawPelPath.c_str()),
72 entry("OBMCLOGID=%d", obmcLogID));
73 // TODO, Decide what to do here. Maybe nothing.
74 return;
75 }
76
77 file.close();
78
Matt Spinlera34ab722019-12-16 10:39:32 -060079 auto pel = std::make_unique<openpower::pels::PEL>(data, obmcLogID);
Matt Spinler89fa0822019-07-17 13:54:30 -050080 if (pel->valid())
81 {
82 // PELs created by others still need these fields set by us.
83 pel->assignID();
84 pel->setCommitTime();
85
86 try
87 {
88 _repo.add(pel);
89 }
90 catch (std::exception& e)
91 {
92 // Probably a full or r/o filesystem, not much we can do.
93 log<level::ERR>("Unable to add PEL to Repository",
94 entry("PEL_ID=0x%X", pel->id()));
95 }
96 }
97 else
98 {
99 log<level::ERR>("Invalid PEL found",
100 entry("PELFILE=%s", rawPelPath.c_str()),
101 entry("OBMCLOGID=%d", obmcLogID));
102 // TODO, make a whole new OpenBMC event log + PEL
103 }
104 }
105 else
106 {
107 log<level::ERR>("Raw PEL file from BMC event log does not exist",
108 entry("PELFILE=%s", (rawPelPath).c_str()),
109 entry("OBMCLOGID=%d", obmcLogID));
110 }
Matt Spinler4e8078c2019-07-09 13:22:32 -0500111}
112
113void Manager::erase(uint32_t obmcLogID)
114{
Matt Spinler475e5742019-07-18 16:09:49 -0500115 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
116
117 _repo.remove(id);
Matt Spinler4e8078c2019-07-09 13:22:32 -0500118}
119
120bool Manager::isDeleteProhibited(uint32_t obmcLogID)
121{
122 return false;
123}
124
125void Manager::createPEL(const std::string& message, uint32_t obmcLogID,
126 uint64_t timestamp,
127 phosphor::logging::Entry::Level severity,
128 const std::vector<std::string>& additionalData,
129 const std::vector<std::string>& associations)
130{
Matt Spinler67456c22019-10-21 12:22:49 -0500131 auto entry = _registry.lookup(message);
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600132 std::string msg;
Matt Spinler67456c22019-10-21 12:22:49 -0500133
134 if (entry)
135 {
136 AdditionalData ad{additionalData};
137
Matt Spinlera34ab722019-12-16 10:39:32 -0600138 auto pel = std::make_unique<openpower::pels::PEL>(
139 *entry, obmcLogID, timestamp, severity, ad, *_dataIface);
Matt Spinler67456c22019-10-21 12:22:49 -0500140
141 _repo.add(pel);
Matt Spinler67456c22019-10-21 12:22:49 -0500142
Matt Spinler1d4c74a2019-12-16 14:40:21 -0600143 auto src = pel->primarySRC();
144 if (src)
145 {
146 using namespace std::literals::string_literals;
147 char id[11];
148 sprintf(id, "0x%08X", pel->id());
149 msg = "Created PEL "s + id + " with SRC "s + (*src)->asciiString();
150 while (msg.back() == ' ')
151 {
152 msg.pop_back();
153 }
154 log<level::INFO>(msg.c_str());
155 }
156 }
157 else
158 {
159 // TODO ibm-openbmc/dev/1151: Create a new PEL for this case.
160 // For now, just trace it.
161 msg = "Event not found in PEL message registry: " + message;
162 log<level::INFO>(msg.c_str());
163 }
Matt Spinler4e8078c2019-07-09 13:22:32 -0500164}
165
Matt Spinlera34ab722019-12-16 10:39:32 -0600166sdbusplus::message::unix_fd Manager::getPEL(uint32_t pelID)
167{
168 Repository::LogID id{Repository::LogID::Pel(pelID)};
169 std::optional<int> fd;
170
171 try
172 {
173 fd = _repo.getPELFD(id);
174 }
175 catch (std::exception& e)
176 {
177 throw common_error::InternalFailure();
178 }
179
180 if (!fd)
181 {
182 throw common_error::InvalidArgument();
183 }
184
185 return *fd;
186}
187
188std::vector<uint8_t> Manager::getPELFromOBMCID(uint32_t obmcLogID)
189{
190 Repository::LogID id{Repository::LogID::Obmc(obmcLogID)};
191 std::optional<std::vector<uint8_t>> data;
192
193 try
194 {
195 data = _repo.getPELData(id);
196 }
197 catch (std::exception& e)
198 {
199 throw common_error::InternalFailure();
200 }
201
202 if (!data)
203 {
204 throw common_error::InvalidArgument();
205 }
206
207 return *data;
208}
209
210void Manager::hostAck(uint32_t pelID)
211{
212 Repository::LogID id{Repository::LogID::Pel(pelID)};
213
214 if (!_repo.hasPEL(id))
215 {
216 throw common_error::InvalidArgument();
217 }
218
219 if (_hostNotifier)
220 {
221 _hostNotifier->ackPEL(pelID);
222 }
223}
224
225void Manager::hostReject(uint32_t pelID, RejectionReason reason)
226{
227 Repository::LogID id{Repository::LogID::Pel(pelID)};
228
229 if (!_repo.hasPEL(id))
230 {
231 throw common_error::InvalidArgument();
232 }
233
234 if (_hostNotifier)
235 {
236 if (reason == RejectionReason::BadPEL)
237 {
238 _hostNotifier->setBadPEL(pelID);
239 }
240 else if (reason == RejectionReason::HostFull)
241 {
242 _hostNotifier->setHostFull(pelID);
243 }
244 }
245}
246
Matt Spinler4e8078c2019-07-09 13:22:32 -0500247} // namespace pels
248} // namespace openpower