blob: ca71dfa7d2e66fa667f5173503cb6bba46ec3cef [file] [log] [blame]
Jason M. Bills99b78ec2019-01-18 10:42:18 -08001/*
2// Copyright (c) 2019 Intel 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
17#include <boost/algorithm/string/join.hpp>
18#include <boost/beast/core/span.hpp>
19#include <iomanip>
20#include <ipmi_to_redfish_hooks.hpp>
21#include <phosphor-logging/log.hpp>
22#include <sstream>
23#include <storagecommands.hpp>
24#include <string_view>
25
26namespace intel_oem::ipmi::sel
27{
28
29namespace redfish_hooks
30{
31static void toHexStr(const boost::beast::span<uint8_t> bytes,
32 std::string& hexStr)
33{
34 std::stringstream stream;
35 stream << std::hex << std::uppercase << std::setfill('0');
36 for (const uint8_t& byte : bytes)
37 {
38 stream << std::setw(2) << static_cast<int>(byte);
39 }
40 hexStr = stream.str();
41}
42
Jason M. Bills6dd8f042019-04-11 10:39:02 -070043static bool defaultMessageHook(const std::string& ipmiRaw)
44{
45 // Log the record as a default Redfish message instead of a SEL record
46
47 static const std::string openBMCMessageRegistryVersion("0.1");
48 std::string messageID =
49 "OpenBMC." + openBMCMessageRegistryVersion + ".SELEntryAdded";
50
51 std::vector<std::string> messageArgs;
52 messageArgs.push_back(ipmiRaw);
53
54 // Log the Redfish message to the journal with the appropriate metadata
55 std::string journalMsg = "SEL Entry Added: " + ipmiRaw;
56 std::string messageArgsString = boost::algorithm::join(messageArgs, ",");
57 phosphor::logging::log<phosphor::logging::level::INFO>(
58 journalMsg.c_str(),
59 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageID.c_str()),
60 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
61 messageArgsString.c_str()));
62
63 return true;
64}
65
Jason M. Bills99b78ec2019-01-18 10:42:18 -080066// Record a BIOS message as a Redfish message instead of a SEL record
67static bool biosMessageHook(const SELData& selData, const std::string& ipmiRaw)
68{
69 // This is a BIOS message, so record it as a Redfish message instead
70 // of a SEL record
71
72 // Walk through the SEL request record to build the appropriate Redfish
73 // message
74 static constexpr std::string_view openBMCMessageRegistryVersion = "0.1";
75 std::string messageID =
76 "OpenBMC." + std::string(openBMCMessageRegistryVersion);
77 std::vector<std::string> messageArgs;
78 BIOSSensors sensor = static_cast<BIOSSensors>(selData.sensorNum);
79 BIOSEventTypes eventType = static_cast<BIOSEventTypes>(selData.eventType);
80 switch (sensor)
81 {
82 case BIOSSensors::memoryRASConfigStatus:
83 switch (eventType)
84 {
85 case BIOSEventTypes::digitalDiscrete:
86 {
87 switch (selData.offset)
88 {
89 case 0x00:
90 messageID += ".MemoryRASConfigurationDisabled";
91 break;
92 case 0x01:
93 messageID += ".MemoryRASConfigurationEnabled";
94 break;
95 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -070096 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -080097 break;
98 }
99 // Get the message data from eventData2 and eventData3
100
101 // error = eventData2 bits [3:0]
102 int error = selData.eventData2 & 0x0F;
103
104 // mode = eventData3 bits [3:0]
105 int mode = selData.eventData3 & 0x0F;
106
107 // Save the messageArgs
108 switch (error)
109 {
110 case 0x00:
111 messageArgs.push_back("None");
112 break;
113 case 0x03:
114 messageArgs.push_back("Invalid DIMM Config");
115 break;
116 default:
117 messageArgs.push_back(std::to_string(error));
118 break;
119 }
120 switch (mode)
121 {
122 case 0x00:
123 messageArgs.push_back("None");
124 break;
125 case 0x01:
126 messageArgs.push_back("Mirroring");
127 break;
128 case 0x02:
129 messageArgs.push_back("Lockstep");
130 break;
131 case 0x04:
132 messageArgs.push_back("Rank Sparing");
133 break;
134 default:
135 messageArgs.push_back(std::to_string(mode));
136 break;
137 }
138
139 break;
140 }
141 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700142 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800143 break;
144 }
145 break;
146 case BIOSSensors::biosPOSTError:
147 switch (eventType)
148 {
149 case BIOSEventTypes::sensorSpecificOffset:
150 {
151 switch (selData.offset)
152 {
153 case 0x00:
154 messageID += ".BIOSPOSTError";
155 break;
156 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700157 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800158 break;
159 }
160 // Get the message data from eventData2 and eventData3
161
162 std::array<uint8_t, 2> post;
163 // post LSB = eventData2 bits [7:0]
164 post[1] = selData.eventData2;
165 // post MSB = eventData3 bits [7:0]
166 post[0] = selData.eventData3;
167
168 // Save the messageArgs
169 messageArgs.emplace_back();
170 std::string& postStr = messageArgs.back();
171 toHexStr(boost::beast::span<uint8_t>(post), postStr);
172
173 break;
174 }
175 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700176 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800177 break;
178 }
179 break;
180 case BIOSSensors::intelUPILinkWidthReduced:
181 switch (eventType)
182 {
183 case BIOSEventTypes::oemDiscrete7:
184 {
185 switch (selData.offset)
186 {
187 case 0x01:
188 messageID += ".IntelUPILinkWidthReducedToHalf";
189 break;
190 case 0x02:
191 messageID += ".IntelUPILinkWidthReducedToQuarter";
192 break;
193 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700194 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800195 break;
196 }
197 // Get the message data from eventData2
198
199 // Node ID = eventData2 bits [7:0]
200 int node = selData.eventData2;
201
202 // Save the messageArgs
203 messageArgs.push_back(std::to_string(node + 1));
204
205 break;
206 }
207 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700208 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800209 break;
210 }
211 break;
212 case BIOSSensors::memoryRASModeSelect:
213 switch (eventType)
214 {
215 case BIOSEventTypes::digitalDiscrete:
216 {
217 switch (selData.offset)
218 {
219 case 0x00:
220 messageID += ".MemoryRASModeDisabled";
221 break;
222 case 0x01:
223 messageID += ".MemoryRASModeEnabled";
224 break;
225 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700226 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800227 break;
228 }
229 // Get the message data from eventData2 and eventData3
230
231 // prior mode = eventData2 bits [3:0]
232 int priorMode = selData.eventData2 & 0x0F;
233
234 // selected mode = eventData3 bits [3:0]
235 int selectedMode = selData.eventData3 & 0x0F;
236
237 // Save the messageArgs
238 switch (priorMode)
239 {
240 case 0x00:
241 messageArgs.push_back("None");
242 break;
243 case 0x01:
244 messageArgs.push_back("Mirroring");
245 break;
246 case 0x02:
247 messageArgs.push_back("Lockstep");
248 break;
249 case 0x04:
250 messageArgs.push_back("Rank Sparing");
251 break;
252 default:
253 messageArgs.push_back(std::to_string(priorMode));
254 break;
255 }
256 switch (selectedMode)
257 {
258 case 0x00:
259 messageArgs.push_back("None");
260 break;
261 case 0x01:
262 messageArgs.push_back("Mirroring");
263 break;
264 case 0x02:
265 messageArgs.push_back("Lockstep");
266 break;
267 case 0x04:
268 messageArgs.push_back("Rank Sparing");
269 break;
270 default:
271 messageArgs.push_back(std::to_string(selectedMode));
272 break;
273 }
274
275 break;
276 }
277 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700278 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800279 break;
280 }
281 break;
282 case BIOSSensors::bootEvent:
283 switch (eventType)
284 {
285 case BIOSEventTypes::sensorSpecificOffset:
286 {
287 switch (selData.offset)
288 {
289 case 0x01:
290 messageID += ".BIOSBoot";
291 break;
292 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700293 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800294 break;
295 }
296 break;
297 }
298 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700299 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800300 break;
301 }
302 break;
303 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700304 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800305 break;
306 }
307
308 // Log the Redfish message to the journal with the appropriate metadata
309 std::string journalMsg = "BIOS POST IPMI event: " + ipmiRaw;
310 if (messageArgs.empty())
311 {
312 phosphor::logging::log<phosphor::logging::level::INFO>(
313 journalMsg.c_str(),
314 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s",
315 messageID.c_str()));
316 }
317 else
318 {
319 std::string messageArgsString =
320 boost::algorithm::join(messageArgs, ",");
321 phosphor::logging::log<phosphor::logging::level::INFO>(
322 journalMsg.c_str(),
323 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s",
324 messageID.c_str()),
325 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
326 messageArgsString.c_str()));
327 }
328
329 return true;
330}
331
332// Record a BIOS SMI message as a Redfish message instead of a SEL record
333static bool biosSMIMessageHook(const SELData& selData,
334 const std::string& ipmiRaw)
335{
336 // This is a BIOS SMI message, so record it as a Redfish message instead
337 // of a SEL record
338
339 // Walk through the SEL request record to build the appropriate Redfish
340 // message
341 static constexpr std::string_view openBMCMessageRegistryVersion = "0.1";
342 std::string messageID =
343 "OpenBMC." + std::string(openBMCMessageRegistryVersion);
344 std::vector<std::string> messageArgs;
345 BIOSSMISensors sensor = static_cast<BIOSSMISensors>(selData.sensorNum);
346 BIOSEventTypes eventType = static_cast<BIOSEventTypes>(selData.eventType);
347 switch (sensor)
348 {
349 case BIOSSMISensors::mirroringRedundancyState:
350 switch (eventType)
351 {
352 case BIOSEventTypes::discreteRedundancyStates:
353 {
354 switch (selData.offset)
355 {
356 case 0x00:
357 messageID += ".MirroringRedundancyFull";
358 break;
359 case 0x02:
360 messageID += ".MirroringRedundancyDegraded";
361 break;
362 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700363 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800364 break;
365 }
366 // Get the message data from eventData2 and eventData3
367
368 // pair = eventData2 bits [7:4]
369 int pair = selData.eventData2 >> 4 & 0x0F;
370 // rank = eventData2 bits [1:0]
371 int rank = selData.eventData2 & 0x03;
372
373 // Socket ID = eventData3 bits [7:5]
374 int socket = selData.eventData3 >> 5 & 0x07;
375 // Channel = eventData3 bits [4:2]
376 int channel = selData.eventData3 >> 2 & 0x07;
377 char channelLetter[4] = {'A'};
378 channelLetter[0] += channel;
379 // DIMM = eventData3 bits [1:0]
380 int dimm = selData.eventData3 & 0x03;
381
382 // Save the messageArgs
383 messageArgs.push_back(std::to_string(socket + 1));
384 messageArgs.push_back(std::string(channelLetter));
385 messageArgs.push_back(std::to_string(dimm + 1));
386 messageArgs.push_back(std::to_string(pair));
387 messageArgs.push_back(std::to_string(rank));
388
389 break;
390 }
391 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700392 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800393 break;
394 }
395 break;
396 case BIOSSMISensors::memoryECCError:
397 switch (eventType)
398 {
399 case BIOSEventTypes::sensorSpecificOffset:
400 {
401 switch (selData.offset)
402 {
403 case 0x00:
404 messageID += ".MemoryECCCorrectable";
405 break;
406 case 0x01:
407 messageID += ".MemoryECCUncorrectable";
408 break;
409 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700410 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800411 break;
412 }
413 // Get the message data from eventData2 and eventData3
414
415 // dimm = eventData2 bits [7:4]
416 int dimm = selData.eventData2 >> 4 & 0x0F;
417 // rank = eventData2 bits [3:0]
418 int rank = selData.eventData2 & 0x0F;
419
420 // Socket ID = eventData3 bits [7:4]
421 int socket = selData.eventData3 >> 4 & 0x0F;
422 // Channel = eventData3 bits [3:0]
423 int channel = selData.eventData3 & 0x0F;
424 char channelLetter[4] = {'A'};
425 channelLetter[0] += channel;
426
427 // Save the messageArgs
428 messageArgs.push_back(std::to_string(socket + 1));
429 messageArgs.push_back(std::string(channelLetter));
430 messageArgs.push_back(std::to_string(dimm));
431 messageArgs.push_back(std::to_string(rank));
432
433 break;
434 }
435 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700436 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800437 break;
438 }
439 break;
440 case BIOSSMISensors::legacyPCIError:
441 switch (eventType)
442 {
443 case BIOSEventTypes::sensorSpecificOffset:
444 {
445 switch (selData.offset)
446 {
447 case 0x04:
448 messageID += ".LegacyPCIPERR";
449 break;
450 case 0x05:
451 messageID += ".LegacyPCISERR";
452 break;
453 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700454 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800455 break;
456 }
457 // Get the message data from eventData2 and eventData3
458
459 // Bus = eventData2 bits [7:0]
460 int bus = selData.eventData2;
461 // Device = eventData3 bits [7:3]
462 int device = selData.eventData3 >> 3 & 0x1F;
463 // Function = eventData3 bits [2:0]
464 int function = selData.eventData3 >> 0x07;
465
466 // Save the messageArgs
467 messageArgs.push_back(std::to_string(bus));
468 messageArgs.push_back(std::to_string(device));
469 messageArgs.push_back(std::to_string(function));
470
471 break;
472 }
473 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700474 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800475 break;
476 }
477 break;
478 case BIOSSMISensors::pcieFatalError:
479 switch (eventType)
480 {
481 case BIOSEventTypes::oemDiscrete0:
482 {
483 switch (selData.offset)
484 {
485 case 0x00:
486 messageID += ".PCIeFatalDataLinkLayerProtocol";
487 break;
488 case 0x01:
489 messageID += ".PCIeFatalSurpriseLinkDown";
490 break;
491 case 0x02:
492 messageID += ".PCIeFatalCompleterAbort";
493 break;
494 case 0x03:
495 messageID += ".PCIeFatalUnsupportedRequest";
496 break;
497 case 0x04:
498 messageID += ".PCIeFatalPoisonedTLP";
499 break;
500 case 0x05:
501 messageID += ".PCIeFatalFlowControlProtocol";
502 break;
503 case 0x06:
504 messageID += ".PCIeFatalCompletionTimeout";
505 break;
506 case 0x07:
507 messageID += ".PCIeFatalReceiverBufferOverflow";
508 break;
509 case 0x08:
510 messageID += ".PCIeFatalACSViolation";
511 break;
512 case 0x09:
513 messageID += ".PCIeFatalMalformedTLP";
514 break;
515 case 0x0a:
516 messageID += ".PCIeFatalECRCError";
517 break;
518 case 0x0b:
519 messageID +=
520 ".PCIeFatalReceivedFatalMessageFromDownstream";
521 break;
522 case 0x0c:
523 messageID += ".PCIeFatalUnexpectedCompletion";
524 break;
525 case 0x0d:
Jason M. Bills6757fb42019-06-14 08:58:38 -0700526 messageID += ".PCIeFatalReceivedErrNonFatalMessage";
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800527 break;
528 case 0x0e:
529 messageID += ".PCIeFatalUncorrectableInternal";
530 break;
531 case 0x0f:
532 messageID += ".PCIeFatalMCBlockedTLP";
533 break;
534 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700535 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800536 break;
537 }
538 // Get the message data from eventData2 and eventData3
539
540 // Bus = eventData2 bits [7:0]
541 int bus = selData.eventData2;
542 // Device = eventData3 bits [7:3]
543 int device = selData.eventData3 >> 3 & 0x1F;
544 // Function = eventData3 bits [2:0]
545 int function = selData.eventData3 >> 0x07;
546
547 // Save the messageArgs
548 messageArgs.push_back(std::to_string(bus));
549 messageArgs.push_back(std::to_string(device));
550 messageArgs.push_back(std::to_string(function));
551
552 break;
553 }
554 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700555 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800556 break;
557 }
558 break;
559 case BIOSSMISensors::pcieCorrectableError:
560 switch (eventType)
561 {
562 case BIOSEventTypes::oemDiscrete1:
563 {
564 switch (selData.offset)
565 {
566 case 0x00:
567 messageID += ".PCIeCorrectableReceiverError";
568 break;
569 case 0x01:
570 messageID += ".PCIeCorrectableBadDLLP";
571 break;
572 case 0x02:
573 messageID += ".PCIeCorrectableBadTLP";
574 break;
575 case 0x03:
576 messageID += ".PCIeCorrectableReplayNumRollover";
577 break;
578 case 0x04:
579 messageID += ".PCIeCorrectableReplayTimerTimeout";
580 break;
581 case 0x05:
582 messageID += ".PCIeCorrectableAdvisoryNonFatal";
583 break;
584 case 0x06:
585 messageID += ".PCIeCorrectableLinkBWChanged";
586 break;
587 case 0x07:
588 messageID += ".PCIeCorrectableInternal";
589 break;
590 case 0x08:
591 messageID += ".PCIeCorrectableHeaderLogOverflow";
592 break;
593 case 0x0f:
594 messageID += ".PCIeCorrectableUnspecifiedAERError";
595 break;
596 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700597 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800598 break;
599 }
600 // Get the message data from eventData2 and eventData3
601
602 // Bus = eventData2 bits [7:0]
603 int bus = selData.eventData2;
604 // Device = eventData3 bits [7:3]
605 int device = selData.eventData3 >> 3 & 0x1F;
606 // Function = eventData3 bits [2:0]
607 int function = selData.eventData3 >> 0x07;
608
609 // Save the messageArgs
610 messageArgs.push_back(std::to_string(bus));
611 messageArgs.push_back(std::to_string(device));
612 messageArgs.push_back(std::to_string(function));
613
614 break;
615 }
616 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700617 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800618 break;
619 }
620 break;
621 case BIOSSMISensors::sparingRedundancyState:
622 switch (eventType)
623 {
624 case BIOSEventTypes::discreteRedundancyStates:
625 {
626 switch (selData.offset)
627 {
628 case 0x00:
629 messageID += ".SparingRedundancyFull";
630 break;
631 case 0x02:
632 messageID += ".SparingRedundancyDegraded";
633 break;
634 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700635 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800636 break;
637 }
638 // Get the message data from eventData2 and eventData3
639
640 // domain = eventData2 bits [7:4]
641 int domain = selData.eventData2 >> 4 & 0x0F;
642 char domainLetter[4] = {'A'};
643 domainLetter[0] += domain;
644 // rank = eventData2 bits [1:0]
645 int rank = selData.eventData2 & 0x03;
646
647 // Socket ID = eventData3 bits [7:5]
648 int socket = selData.eventData3 >> 5 & 0x07;
649 // Channel = eventData3 bits [4:2]
650 int channel = selData.eventData3 >> 2 & 0x07;
651 char channelLetter[4] = {'A'};
652 channelLetter[0] += channel;
653 // DIMM = eventData3 bits [1:0]
654 int dimm = selData.eventData3 & 0x03;
655
656 // Save the messageArgs
657 messageArgs.push_back(std::to_string(socket + 1));
658 messageArgs.push_back(std::string(channelLetter));
659 messageArgs.push_back(std::to_string(dimm + 1));
660 messageArgs.push_back(std::string(domainLetter));
661 messageArgs.push_back(std::to_string(rank));
662
663 break;
664 }
665 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700666 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800667 break;
668 }
669 break;
670 case BIOSSMISensors::memoryParityError:
671 switch (eventType)
672 {
673 case BIOSEventTypes::sensorSpecificOffset:
674 {
675 switch (selData.offset)
676 {
677 case 0x03:
678 {
679 // type = eventData2 bits [2:0]
680 int type = selData.eventData2 & 0x07;
681 switch (type)
682 {
683 case 0x00:
684 messageID += ".MemoryParityNotKnown";
685 break;
686 case 0x03:
687 messageID +=
688 ".MemoryParityCommandAndAddress";
689 break;
690 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700691 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800692 break;
693 }
694 break;
695 }
696 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700697 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800698 break;
699 }
700 // Get the message data from eventData2 and eventData3
701
702 // channelValid = eventData2 bit [4]
703 int channelValid = selData.eventData2 >> 4 & 0x01;
704 // dimmValid = eventData2 bit [3]
705 int dimmValid = selData.eventData2 >> 3 & 0x01;
706
707 // Socket ID = eventData3 bits [7:5]
708 int socket = selData.eventData3 >> 5 & 0x07;
709 // Channel = eventData3 bits [4:2]
710 int channel = selData.eventData3 >> 2 & 0x07;
711 char channelLetter[4] = {'A'};
712 channelLetter[0] += channel;
713 // DIMM = eventData3 bits [1:0]
714 int dimm = selData.eventData3 & 0x03;
715
716 // Save the messageArgs
717 messageArgs.push_back(std::to_string(socket + 1));
718 messageArgs.push_back(std::string(channelLetter));
719 messageArgs.push_back(std::to_string(dimm + 1));
720 messageArgs.push_back(std::to_string(channelValid));
721 messageArgs.push_back(std::to_string(dimmValid));
722
723 break;
724 }
725 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700726 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800727 break;
728 }
729 break;
730 case BIOSSMISensors::pcieFatalError2:
731 switch (eventType)
732 {
733 case BIOSEventTypes::oemDiscrete6:
734 {
735 switch (selData.offset)
736 {
737 case 0x00:
738 messageID += ".PCIeFatalAtomicEgressBlocked";
739 break;
740 case 0x01:
741 messageID += ".PCIeFatalTLPPrefixBlocked";
742 break;
743 case 0x0f:
744 messageID +=
745 ".PCIeFatalUnspecifiedNonAERFatalError";
746 break;
747 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700748 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800749 break;
750 }
751 // Get the message data from eventData2 and eventData3
752
753 // Bus = eventData2 bits [7:0]
754 int bus = selData.eventData2;
755 // Device = eventData3 bits [7:3]
756 int device = selData.eventData3 >> 3 & 0x1F;
757 // Function = eventData3 bits [2:0]
758 int function = selData.eventData3 >> 0x07;
759
760 // Save the messageArgs
761 messageArgs.push_back(std::to_string(bus));
762 messageArgs.push_back(std::to_string(device));
763 messageArgs.push_back(std::to_string(function));
764
765 break;
766 }
767 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700768 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800769 break;
770 }
771 break;
772 case BIOSSMISensors::biosRecovery:
773 switch (eventType)
774 {
775 case BIOSEventTypes::oemDiscrete0:
776 {
777 switch (selData.offset)
778 {
779 case 0x01:
780 messageID += ".BIOSRecoveryStart";
781 break;
782 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700783 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800784 break;
785 }
786 break;
787 }
788 case BIOSEventTypes::reservedF0:
789 {
790 switch (selData.offset)
791 {
792 case 0x01:
793 messageID += ".BIOSRecoveryComplete";
794 break;
795 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700796 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800797 break;
798 }
799 break;
800 }
801 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700802 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800803 break;
804 }
805 break;
806 case BIOSSMISensors::adddcError:
807 switch (eventType)
808 {
809 case BIOSEventTypes::reservedA0:
810 {
811 messageID += ".ADDDCCorrectable";
812
813 // Get the message data from eventData2 and eventData3
814
815 // dimm = eventData2 bits [7:4]
816 int dimm = selData.eventData2 >> 4 & 0x0F;
817 // rank = eventData2 bits [3:0]
818 int rank = selData.eventData2 & 0x0F;
819
820 // Socket ID = eventData3 bits [7:4]
821 int socket = selData.eventData3 >> 4 & 0x0F;
822 // Channel = eventData3 bits [3:0]
823 int channel = selData.eventData3 & 0x0F;
824 char channelLetter[4] = {'A'};
825 channelLetter[0] += channel;
826
827 // Save the messageArgs
828 messageArgs.push_back(std::to_string(socket + 1));
829 messageArgs.push_back(std::string(channelLetter));
830 messageArgs.push_back(std::to_string(dimm));
831 messageArgs.push_back(std::to_string(rank));
832
833 break;
834 }
835 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700836 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800837 break;
838 }
839 break;
840 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700841 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800842 break;
843 }
844
845 // Log the Redfish message to the journal with the appropriate metadata
846 std::string journalMsg = "BIOS SMI IPMI event: " + ipmiRaw;
847 std::string messageArgsString = boost::algorithm::join(messageArgs, ",");
848 phosphor::logging::log<phosphor::logging::level::INFO>(
849 journalMsg.c_str(),
850 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageID.c_str()),
851 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
852 messageArgsString.c_str()));
853
854 return true;
855}
856
857static bool startRedfishHook(const SELData& selData, const std::string& ipmiRaw)
858{
859 switch (selData.generatorID)
860 {
861 case 0x01: // Check if this message is from the BIOS Generator ID
862 // Let the BIOS hook handle this request
863 return biosMessageHook(selData, ipmiRaw);
864 break;
865
866 case 0x33: // Check if this message is from the BIOS SMI Generator ID
867 // Let the BIOS SMI hook handle this request
868 return biosSMIMessageHook(selData, ipmiRaw);
869 break;
870 }
871
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700872 // No hooks handled the request, so let it go to default
873 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800874}
875} // namespace redfish_hooks
876
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700877bool checkRedfishHooks(uint16_t recordID, uint8_t recordType,
878 uint32_t timestamp, uint16_t generatorID, uint8_t evmRev,
879 uint8_t sensorType, uint8_t sensorNum, uint8_t eventType,
880 uint8_t eventData1, uint8_t eventData2,
881 uint8_t eventData3)
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800882{
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800883 // Save the raw IPMI string of the request
884 std::string ipmiRaw;
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700885 std::array selBytes = {static_cast<uint8_t>(recordID),
886 static_cast<uint8_t>(recordID >> 8),
887 recordType,
888 static_cast<uint8_t>(timestamp),
889 static_cast<uint8_t>(timestamp >> 8),
890 static_cast<uint8_t>(timestamp >> 16),
891 static_cast<uint8_t>(timestamp >> 24),
892 static_cast<uint8_t>(generatorID),
893 static_cast<uint8_t>(generatorID >> 8),
894 evmRev,
895 sensorType,
896 sensorNum,
897 eventType,
898 eventData1,
899 eventData2,
900 eventData3};
901 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
902
903 // First check that this is a system event record type since that
904 // determines the definition of the rest of the data
905 if (recordType != ipmi::sel::systemEvent)
906 {
907 // OEM record type, so let it go to the SEL
908 return redfish_hooks::defaultMessageHook(ipmiRaw);
909 }
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800910
911 // Extract the SEL data for the hook
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700912 redfish_hooks::SELData selData = {.generatorID = generatorID,
913 .sensorNum = sensorNum,
914 .eventType = eventType,
915 .offset = eventData1 & 0x0F,
916 .eventData2 = eventData2,
917 .eventData3 = eventData3};
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800918
919 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
920}
921
922bool checkRedfishHooks(uint8_t generatorID, uint8_t evmRev, uint8_t sensorType,
923 uint8_t sensorNum, uint8_t eventType, uint8_t eventData1,
924 uint8_t eventData2, uint8_t eventData3)
925{
926 // Save the raw IPMI string of the selData
927 std::string ipmiRaw;
928 std::array selBytes = {generatorID, evmRev, sensorType, sensorNum,
929 eventType, eventData1, eventData2, eventData3};
930 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
931
932 // Extract the SEL data for the hook
933 redfish_hooks::SELData selData = {.generatorID = generatorID,
934 .sensorNum = sensorNum,
935 .eventType = eventType,
936 .offset = eventData1 & 0x0F,
937 .eventData2 = eventData2,
938 .eventData3 = eventData3};
939
940 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
941}
942
943} // namespace intel_oem::ipmi::sel