blob: ff850816a52a3a29819e175be19e83b230b534f3 [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
43// Record a BIOS message as a Redfish message instead of a SEL record
44static bool biosMessageHook(const SELData& selData, const std::string& ipmiRaw)
45{
46 // This is a BIOS message, so record it as a Redfish message instead
47 // of a SEL record
48
49 // Walk through the SEL request record to build the appropriate Redfish
50 // message
51 static constexpr std::string_view openBMCMessageRegistryVersion = "0.1";
52 std::string messageID =
53 "OpenBMC." + std::string(openBMCMessageRegistryVersion);
54 std::vector<std::string> messageArgs;
55 BIOSSensors sensor = static_cast<BIOSSensors>(selData.sensorNum);
56 BIOSEventTypes eventType = static_cast<BIOSEventTypes>(selData.eventType);
57 switch (sensor)
58 {
59 case BIOSSensors::memoryRASConfigStatus:
60 switch (eventType)
61 {
62 case BIOSEventTypes::digitalDiscrete:
63 {
64 switch (selData.offset)
65 {
66 case 0x00:
67 messageID += ".MemoryRASConfigurationDisabled";
68 break;
69 case 0x01:
70 messageID += ".MemoryRASConfigurationEnabled";
71 break;
72 default:
73 messageID += ".Unknown";
74 messageArgs.push_back(ipmiRaw);
75 break;
76 }
77 // Get the message data from eventData2 and eventData3
78
79 // error = eventData2 bits [3:0]
80 int error = selData.eventData2 & 0x0F;
81
82 // mode = eventData3 bits [3:0]
83 int mode = selData.eventData3 & 0x0F;
84
85 // Save the messageArgs
86 switch (error)
87 {
88 case 0x00:
89 messageArgs.push_back("None");
90 break;
91 case 0x03:
92 messageArgs.push_back("Invalid DIMM Config");
93 break;
94 default:
95 messageArgs.push_back(std::to_string(error));
96 break;
97 }
98 switch (mode)
99 {
100 case 0x00:
101 messageArgs.push_back("None");
102 break;
103 case 0x01:
104 messageArgs.push_back("Mirroring");
105 break;
106 case 0x02:
107 messageArgs.push_back("Lockstep");
108 break;
109 case 0x04:
110 messageArgs.push_back("Rank Sparing");
111 break;
112 default:
113 messageArgs.push_back(std::to_string(mode));
114 break;
115 }
116
117 break;
118 }
119 default:
120 messageID += ".Unknown";
121 messageArgs.push_back(ipmiRaw);
122 break;
123 }
124 break;
125 case BIOSSensors::biosPOSTError:
126 switch (eventType)
127 {
128 case BIOSEventTypes::sensorSpecificOffset:
129 {
130 switch (selData.offset)
131 {
132 case 0x00:
133 messageID += ".BIOSPOSTError";
134 break;
135 default:
136 messageID += ".Unknown";
137 messageArgs.push_back(ipmiRaw);
138 break;
139 }
140 // Get the message data from eventData2 and eventData3
141
142 std::array<uint8_t, 2> post;
143 // post LSB = eventData2 bits [7:0]
144 post[1] = selData.eventData2;
145 // post MSB = eventData3 bits [7:0]
146 post[0] = selData.eventData3;
147
148 // Save the messageArgs
149 messageArgs.emplace_back();
150 std::string& postStr = messageArgs.back();
151 toHexStr(boost::beast::span<uint8_t>(post), postStr);
152
153 break;
154 }
155 default:
156 messageID += ".Unknown";
157 messageArgs.push_back(ipmiRaw);
158 break;
159 }
160 break;
161 case BIOSSensors::intelUPILinkWidthReduced:
162 switch (eventType)
163 {
164 case BIOSEventTypes::oemDiscrete7:
165 {
166 switch (selData.offset)
167 {
168 case 0x01:
169 messageID += ".IntelUPILinkWidthReducedToHalf";
170 break;
171 case 0x02:
172 messageID += ".IntelUPILinkWidthReducedToQuarter";
173 break;
174 default:
175 messageID += ".Unknown";
176 messageArgs.push_back(ipmiRaw);
177 break;
178 }
179 // Get the message data from eventData2
180
181 // Node ID = eventData2 bits [7:0]
182 int node = selData.eventData2;
183
184 // Save the messageArgs
185 messageArgs.push_back(std::to_string(node + 1));
186
187 break;
188 }
189 default:
190 messageID += ".Unknown";
191 messageArgs.push_back(ipmiRaw);
192 break;
193 }
194 break;
195 case BIOSSensors::memoryRASModeSelect:
196 switch (eventType)
197 {
198 case BIOSEventTypes::digitalDiscrete:
199 {
200 switch (selData.offset)
201 {
202 case 0x00:
203 messageID += ".MemoryRASModeDisabled";
204 break;
205 case 0x01:
206 messageID += ".MemoryRASModeEnabled";
207 break;
208 default:
209 messageID += ".Unknown";
210 messageArgs.push_back(ipmiRaw);
211 break;
212 }
213 // Get the message data from eventData2 and eventData3
214
215 // prior mode = eventData2 bits [3:0]
216 int priorMode = selData.eventData2 & 0x0F;
217
218 // selected mode = eventData3 bits [3:0]
219 int selectedMode = selData.eventData3 & 0x0F;
220
221 // Save the messageArgs
222 switch (priorMode)
223 {
224 case 0x00:
225 messageArgs.push_back("None");
226 break;
227 case 0x01:
228 messageArgs.push_back("Mirroring");
229 break;
230 case 0x02:
231 messageArgs.push_back("Lockstep");
232 break;
233 case 0x04:
234 messageArgs.push_back("Rank Sparing");
235 break;
236 default:
237 messageArgs.push_back(std::to_string(priorMode));
238 break;
239 }
240 switch (selectedMode)
241 {
242 case 0x00:
243 messageArgs.push_back("None");
244 break;
245 case 0x01:
246 messageArgs.push_back("Mirroring");
247 break;
248 case 0x02:
249 messageArgs.push_back("Lockstep");
250 break;
251 case 0x04:
252 messageArgs.push_back("Rank Sparing");
253 break;
254 default:
255 messageArgs.push_back(std::to_string(selectedMode));
256 break;
257 }
258
259 break;
260 }
261 default:
262 messageID += ".Unknown";
263 messageArgs.push_back(ipmiRaw);
264 break;
265 }
266 break;
267 case BIOSSensors::bootEvent:
268 switch (eventType)
269 {
270 case BIOSEventTypes::sensorSpecificOffset:
271 {
272 switch (selData.offset)
273 {
274 case 0x01:
275 messageID += ".BIOSBoot";
276 break;
277 default:
278 messageID += ".Unknown";
279 messageArgs.push_back(ipmiRaw);
280 break;
281 }
282 break;
283 }
284 default:
285 messageID += ".Unknown";
286 messageArgs.push_back(ipmiRaw);
287 break;
288 }
289 break;
290 default:
291 messageID += ".Unknown";
292 messageArgs.push_back(ipmiRaw);
293 break;
294 }
295
296 // Log the Redfish message to the journal with the appropriate metadata
297 std::string journalMsg = "BIOS POST IPMI event: " + ipmiRaw;
298 if (messageArgs.empty())
299 {
300 phosphor::logging::log<phosphor::logging::level::INFO>(
301 journalMsg.c_str(),
302 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s",
303 messageID.c_str()));
304 }
305 else
306 {
307 std::string messageArgsString =
308 boost::algorithm::join(messageArgs, ",");
309 phosphor::logging::log<phosphor::logging::level::INFO>(
310 journalMsg.c_str(),
311 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s",
312 messageID.c_str()),
313 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
314 messageArgsString.c_str()));
315 }
316
317 return true;
318}
319
320// Record a BIOS SMI message as a Redfish message instead of a SEL record
321static bool biosSMIMessageHook(const SELData& selData,
322 const std::string& ipmiRaw)
323{
324 // This is a BIOS SMI message, so record it as a Redfish message instead
325 // of a SEL record
326
327 // Walk through the SEL request record to build the appropriate Redfish
328 // message
329 static constexpr std::string_view openBMCMessageRegistryVersion = "0.1";
330 std::string messageID =
331 "OpenBMC." + std::string(openBMCMessageRegistryVersion);
332 std::vector<std::string> messageArgs;
333 BIOSSMISensors sensor = static_cast<BIOSSMISensors>(selData.sensorNum);
334 BIOSEventTypes eventType = static_cast<BIOSEventTypes>(selData.eventType);
335 switch (sensor)
336 {
337 case BIOSSMISensors::mirroringRedundancyState:
338 switch (eventType)
339 {
340 case BIOSEventTypes::discreteRedundancyStates:
341 {
342 switch (selData.offset)
343 {
344 case 0x00:
345 messageID += ".MirroringRedundancyFull";
346 break;
347 case 0x02:
348 messageID += ".MirroringRedundancyDegraded";
349 break;
350 default:
351 messageID += ".Unknown";
352 messageArgs.push_back(ipmiRaw);
353 break;
354 }
355 // Get the message data from eventData2 and eventData3
356
357 // pair = eventData2 bits [7:4]
358 int pair = selData.eventData2 >> 4 & 0x0F;
359 // rank = eventData2 bits [1:0]
360 int rank = selData.eventData2 & 0x03;
361
362 // Socket ID = eventData3 bits [7:5]
363 int socket = selData.eventData3 >> 5 & 0x07;
364 // Channel = eventData3 bits [4:2]
365 int channel = selData.eventData3 >> 2 & 0x07;
366 char channelLetter[4] = {'A'};
367 channelLetter[0] += channel;
368 // DIMM = eventData3 bits [1:0]
369 int dimm = selData.eventData3 & 0x03;
370
371 // Save the messageArgs
372 messageArgs.push_back(std::to_string(socket + 1));
373 messageArgs.push_back(std::string(channelLetter));
374 messageArgs.push_back(std::to_string(dimm + 1));
375 messageArgs.push_back(std::to_string(pair));
376 messageArgs.push_back(std::to_string(rank));
377
378 break;
379 }
380 default:
381 messageID += ".Unknown";
382 messageArgs.push_back(ipmiRaw);
383 break;
384 }
385 break;
386 case BIOSSMISensors::memoryECCError:
387 switch (eventType)
388 {
389 case BIOSEventTypes::sensorSpecificOffset:
390 {
391 switch (selData.offset)
392 {
393 case 0x00:
394 messageID += ".MemoryECCCorrectable";
395 break;
396 case 0x01:
397 messageID += ".MemoryECCUncorrectable";
398 break;
399 default:
400 messageID += ".Unknown";
401 messageArgs.push_back(ipmiRaw);
402 break;
403 }
404 // Get the message data from eventData2 and eventData3
405
406 // dimm = eventData2 bits [7:4]
407 int dimm = selData.eventData2 >> 4 & 0x0F;
408 // rank = eventData2 bits [3:0]
409 int rank = selData.eventData2 & 0x0F;
410
411 // Socket ID = eventData3 bits [7:4]
412 int socket = selData.eventData3 >> 4 & 0x0F;
413 // Channel = eventData3 bits [3:0]
414 int channel = selData.eventData3 & 0x0F;
415 char channelLetter[4] = {'A'};
416 channelLetter[0] += channel;
417
418 // Save the messageArgs
419 messageArgs.push_back(std::to_string(socket + 1));
420 messageArgs.push_back(std::string(channelLetter));
421 messageArgs.push_back(std::to_string(dimm));
422 messageArgs.push_back(std::to_string(rank));
423
424 break;
425 }
426 default:
427 messageID += ".Unknown";
428 messageArgs.push_back(ipmiRaw);
429 break;
430 }
431 break;
432 case BIOSSMISensors::legacyPCIError:
433 switch (eventType)
434 {
435 case BIOSEventTypes::sensorSpecificOffset:
436 {
437 switch (selData.offset)
438 {
439 case 0x04:
440 messageID += ".LegacyPCIPERR";
441 break;
442 case 0x05:
443 messageID += ".LegacyPCISERR";
444 break;
445 default:
446 messageID += ".Unknown";
447 messageArgs.push_back(ipmiRaw);
448 break;
449 }
450 // Get the message data from eventData2 and eventData3
451
452 // Bus = eventData2 bits [7:0]
453 int bus = selData.eventData2;
454 // Device = eventData3 bits [7:3]
455 int device = selData.eventData3 >> 3 & 0x1F;
456 // Function = eventData3 bits [2:0]
457 int function = selData.eventData3 >> 0x07;
458
459 // Save the messageArgs
460 messageArgs.push_back(std::to_string(bus));
461 messageArgs.push_back(std::to_string(device));
462 messageArgs.push_back(std::to_string(function));
463
464 break;
465 }
466 default:
467 messageID += ".Unknown";
468 messageArgs.push_back(ipmiRaw);
469 break;
470 }
471 break;
472 case BIOSSMISensors::pcieFatalError:
473 switch (eventType)
474 {
475 case BIOSEventTypes::oemDiscrete0:
476 {
477 switch (selData.offset)
478 {
479 case 0x00:
480 messageID += ".PCIeFatalDataLinkLayerProtocol";
481 break;
482 case 0x01:
483 messageID += ".PCIeFatalSurpriseLinkDown";
484 break;
485 case 0x02:
486 messageID += ".PCIeFatalCompleterAbort";
487 break;
488 case 0x03:
489 messageID += ".PCIeFatalUnsupportedRequest";
490 break;
491 case 0x04:
492 messageID += ".PCIeFatalPoisonedTLP";
493 break;
494 case 0x05:
495 messageID += ".PCIeFatalFlowControlProtocol";
496 break;
497 case 0x06:
498 messageID += ".PCIeFatalCompletionTimeout";
499 break;
500 case 0x07:
501 messageID += ".PCIeFatalReceiverBufferOverflow";
502 break;
503 case 0x08:
504 messageID += ".PCIeFatalACSViolation";
505 break;
506 case 0x09:
507 messageID += ".PCIeFatalMalformedTLP";
508 break;
509 case 0x0a:
510 messageID += ".PCIeFatalECRCError";
511 break;
512 case 0x0b:
513 messageID +=
514 ".PCIeFatalReceivedFatalMessageFromDownstream";
515 break;
516 case 0x0c:
517 messageID += ".PCIeFatalUnexpectedCompletion";
518 break;
519 case 0x0d:
520 messageID +=
521 ".PCIeFatalReceivedERR_NONFATALMessage";
522 break;
523 case 0x0e:
524 messageID += ".PCIeFatalUncorrectableInternal";
525 break;
526 case 0x0f:
527 messageID += ".PCIeFatalMCBlockedTLP";
528 break;
529 default:
530 messageID += ".Unknown";
531 messageArgs.push_back(ipmiRaw);
532 break;
533 }
534 // Get the message data from eventData2 and eventData3
535
536 // Bus = eventData2 bits [7:0]
537 int bus = selData.eventData2;
538 // Device = eventData3 bits [7:3]
539 int device = selData.eventData3 >> 3 & 0x1F;
540 // Function = eventData3 bits [2:0]
541 int function = selData.eventData3 >> 0x07;
542
543 // Save the messageArgs
544 messageArgs.push_back(std::to_string(bus));
545 messageArgs.push_back(std::to_string(device));
546 messageArgs.push_back(std::to_string(function));
547
548 break;
549 }
550 default:
551 messageID += ".Unknown";
552 messageArgs.push_back(ipmiRaw);
553 break;
554 }
555 break;
556 case BIOSSMISensors::pcieCorrectableError:
557 switch (eventType)
558 {
559 case BIOSEventTypes::oemDiscrete1:
560 {
561 switch (selData.offset)
562 {
563 case 0x00:
564 messageID += ".PCIeCorrectableReceiverError";
565 break;
566 case 0x01:
567 messageID += ".PCIeCorrectableBadDLLP";
568 break;
569 case 0x02:
570 messageID += ".PCIeCorrectableBadTLP";
571 break;
572 case 0x03:
573 messageID += ".PCIeCorrectableReplayNumRollover";
574 break;
575 case 0x04:
576 messageID += ".PCIeCorrectableReplayTimerTimeout";
577 break;
578 case 0x05:
579 messageID += ".PCIeCorrectableAdvisoryNonFatal";
580 break;
581 case 0x06:
582 messageID += ".PCIeCorrectableLinkBWChanged";
583 break;
584 case 0x07:
585 messageID += ".PCIeCorrectableInternal";
586 break;
587 case 0x08:
588 messageID += ".PCIeCorrectableHeaderLogOverflow";
589 break;
590 case 0x0f:
591 messageID += ".PCIeCorrectableUnspecifiedAERError";
592 break;
593 default:
594 messageID += ".Unknown";
595 messageArgs.push_back(ipmiRaw);
596 break;
597 }
598 // Get the message data from eventData2 and eventData3
599
600 // Bus = eventData2 bits [7:0]
601 int bus = selData.eventData2;
602 // Device = eventData3 bits [7:3]
603 int device = selData.eventData3 >> 3 & 0x1F;
604 // Function = eventData3 bits [2:0]
605 int function = selData.eventData3 >> 0x07;
606
607 // Save the messageArgs
608 messageArgs.push_back(std::to_string(bus));
609 messageArgs.push_back(std::to_string(device));
610 messageArgs.push_back(std::to_string(function));
611
612 break;
613 }
614 default:
615 messageID += ".Unknown";
616 messageArgs.push_back(ipmiRaw);
617 break;
618 }
619 break;
620 case BIOSSMISensors::sparingRedundancyState:
621 switch (eventType)
622 {
623 case BIOSEventTypes::discreteRedundancyStates:
624 {
625 switch (selData.offset)
626 {
627 case 0x00:
628 messageID += ".SparingRedundancyFull";
629 break;
630 case 0x02:
631 messageID += ".SparingRedundancyDegraded";
632 break;
633 default:
634 messageID += ".Unknown";
635 messageArgs.push_back(ipmiRaw);
636 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:
666 messageID += ".Unknown";
667 messageArgs.push_back(ipmiRaw);
668 break;
669 }
670 break;
671 case BIOSSMISensors::memoryParityError:
672 switch (eventType)
673 {
674 case BIOSEventTypes::sensorSpecificOffset:
675 {
676 switch (selData.offset)
677 {
678 case 0x03:
679 {
680 // type = eventData2 bits [2:0]
681 int type = selData.eventData2 & 0x07;
682 switch (type)
683 {
684 case 0x00:
685 messageID += ".MemoryParityNotKnown";
686 break;
687 case 0x03:
688 messageID +=
689 ".MemoryParityCommandAndAddress";
690 break;
691 default:
692 messageID += ".Unknown";
693 messageArgs.push_back(ipmiRaw);
694 break;
695 }
696 break;
697 }
698 default:
699 messageID += ".Unknown";
700 messageArgs.push_back(ipmiRaw);
701 break;
702 }
703 // Get the message data from eventData2 and eventData3
704
705 // channelValid = eventData2 bit [4]
706 int channelValid = selData.eventData2 >> 4 & 0x01;
707 // dimmValid = eventData2 bit [3]
708 int dimmValid = selData.eventData2 >> 3 & 0x01;
709
710 // Socket ID = eventData3 bits [7:5]
711 int socket = selData.eventData3 >> 5 & 0x07;
712 // Channel = eventData3 bits [4:2]
713 int channel = selData.eventData3 >> 2 & 0x07;
714 char channelLetter[4] = {'A'};
715 channelLetter[0] += channel;
716 // DIMM = eventData3 bits [1:0]
717 int dimm = selData.eventData3 & 0x03;
718
719 // Save the messageArgs
720 messageArgs.push_back(std::to_string(socket + 1));
721 messageArgs.push_back(std::string(channelLetter));
722 messageArgs.push_back(std::to_string(dimm + 1));
723 messageArgs.push_back(std::to_string(channelValid));
724 messageArgs.push_back(std::to_string(dimmValid));
725
726 break;
727 }
728 default:
729 messageID += ".Unknown";
730 messageArgs.push_back(ipmiRaw);
731 break;
732 }
733 break;
734 case BIOSSMISensors::pcieFatalError2:
735 switch (eventType)
736 {
737 case BIOSEventTypes::oemDiscrete6:
738 {
739 switch (selData.offset)
740 {
741 case 0x00:
742 messageID += ".PCIeFatalAtomicEgressBlocked";
743 break;
744 case 0x01:
745 messageID += ".PCIeFatalTLPPrefixBlocked";
746 break;
747 case 0x0f:
748 messageID +=
749 ".PCIeFatalUnspecifiedNonAERFatalError";
750 break;
751 default:
752 messageID += ".Unknown";
753 messageArgs.push_back(ipmiRaw);
754 break;
755 }
756 // Get the message data from eventData2 and eventData3
757
758 // Bus = eventData2 bits [7:0]
759 int bus = selData.eventData2;
760 // Device = eventData3 bits [7:3]
761 int device = selData.eventData3 >> 3 & 0x1F;
762 // Function = eventData3 bits [2:0]
763 int function = selData.eventData3 >> 0x07;
764
765 // Save the messageArgs
766 messageArgs.push_back(std::to_string(bus));
767 messageArgs.push_back(std::to_string(device));
768 messageArgs.push_back(std::to_string(function));
769
770 break;
771 }
772 default:
773 messageID += ".Unknown";
774 messageArgs.push_back(ipmiRaw);
775 break;
776 }
777 break;
778 case BIOSSMISensors::biosRecovery:
779 switch (eventType)
780 {
781 case BIOSEventTypes::oemDiscrete0:
782 {
783 switch (selData.offset)
784 {
785 case 0x01:
786 messageID += ".BIOSRecoveryStart";
787 break;
788 default:
789 messageID += ".Unknown";
790 messageArgs.push_back(ipmiRaw);
791 break;
792 }
793 break;
794 }
795 case BIOSEventTypes::reservedF0:
796 {
797 switch (selData.offset)
798 {
799 case 0x01:
800 messageID += ".BIOSRecoveryComplete";
801 break;
802 default:
803 messageID += ".Unknown";
804 messageArgs.push_back(ipmiRaw);
805 break;
806 }
807 break;
808 }
809 default:
810 messageID += ".Unknown";
811 messageArgs.push_back(ipmiRaw);
812 break;
813 }
814 break;
815 case BIOSSMISensors::adddcError:
816 switch (eventType)
817 {
818 case BIOSEventTypes::reservedA0:
819 {
820 messageID += ".ADDDCCorrectable";
821
822 // Get the message data from eventData2 and eventData3
823
824 // dimm = eventData2 bits [7:4]
825 int dimm = selData.eventData2 >> 4 & 0x0F;
826 // rank = eventData2 bits [3:0]
827 int rank = selData.eventData2 & 0x0F;
828
829 // Socket ID = eventData3 bits [7:4]
830 int socket = selData.eventData3 >> 4 & 0x0F;
831 // Channel = eventData3 bits [3:0]
832 int channel = selData.eventData3 & 0x0F;
833 char channelLetter[4] = {'A'};
834 channelLetter[0] += channel;
835
836 // Save the messageArgs
837 messageArgs.push_back(std::to_string(socket + 1));
838 messageArgs.push_back(std::string(channelLetter));
839 messageArgs.push_back(std::to_string(dimm));
840 messageArgs.push_back(std::to_string(rank));
841
842 break;
843 }
844 default:
845 messageID += ".Unknown";
846 messageArgs.push_back(ipmiRaw);
847 break;
848 }
849 break;
850 default:
851 messageID += ".Unknown";
852 messageArgs.push_back(ipmiRaw);
853 break;
854 }
855
856 // Log the Redfish message to the journal with the appropriate metadata
857 std::string journalMsg = "BIOS SMI IPMI event: " + ipmiRaw;
858 std::string messageArgsString = boost::algorithm::join(messageArgs, ",");
859 phosphor::logging::log<phosphor::logging::level::INFO>(
860 journalMsg.c_str(),
861 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageID.c_str()),
862 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
863 messageArgsString.c_str()));
864
865 return true;
866}
867
868static bool startRedfishHook(const SELData& selData, const std::string& ipmiRaw)
869{
870 switch (selData.generatorID)
871 {
872 case 0x01: // Check if this message is from the BIOS Generator ID
873 // Let the BIOS hook handle this request
874 return biosMessageHook(selData, ipmiRaw);
875 break;
876
877 case 0x33: // Check if this message is from the BIOS SMI Generator ID
878 // Let the BIOS SMI hook handle this request
879 return biosSMIMessageHook(selData, ipmiRaw);
880 break;
881 }
882
883 // No hooks handled the request, so let it go to the SEL
884 return false;
885}
886} // namespace redfish_hooks
887
888bool checkRedfishHooks(AddSELRequest* selRequest)
889{
890 // First check that this is a system event record type since that
891 // determines the definition of the rest of the data
892 if (selRequest->recordType != ipmi::sel::systemEvent)
893 {
894 // OEM record type, so let it go to the SEL
895 return false;
896 }
897
898 // Save the raw IPMI string of the request
899 std::string ipmiRaw;
900 const boost::beast::span<uint8_t> selBytes(
901 reinterpret_cast<uint8_t*>(selRequest), sizeof(AddSELRequest));
902 redfish_hooks::toHexStr(selBytes, ipmiRaw);
903
904 // Extract the SEL data for the hook
905 redfish_hooks::SELData selData = {
906 .generatorID = selRequest->record.system.generatorID,
907 .sensorNum = selRequest->record.system.sensorNum,
908 .eventType = selRequest->record.system.eventType,
909 .offset = selRequest->record.system.eventData[0] & 0x0F,
910 .eventData2 = selRequest->record.system.eventData[1],
911 .eventData3 = selRequest->record.system.eventData[2]};
912
913 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
914}
915
916bool checkRedfishHooks(uint8_t generatorID, uint8_t evmRev, uint8_t sensorType,
917 uint8_t sensorNum, uint8_t eventType, uint8_t eventData1,
918 uint8_t eventData2, uint8_t eventData3)
919{
920 // Save the raw IPMI string of the selData
921 std::string ipmiRaw;
922 std::array selBytes = {generatorID, evmRev, sensorType, sensorNum,
923 eventType, eventData1, eventData2, eventData3};
924 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
925
926 // Extract the SEL data for the hook
927 redfish_hooks::SELData selData = {.generatorID = generatorID,
928 .sensorNum = sensorNum,
929 .eventType = eventType,
930 .offset = eventData1 & 0x0F,
931 .eventData2 = eventData2,
932 .eventData3 = eventData3};
933
934 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
935}
936
937} // namespace intel_oem::ipmi::sel