blob: be4dd3ac8b2b4ff5f0d17eba105d0fa3bf4bd158 [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:
526 messageID +=
527 ".PCIeFatalReceivedERR_NONFATALMessage";
528 break;
529 case 0x0e:
530 messageID += ".PCIeFatalUncorrectableInternal";
531 break;
532 case 0x0f:
533 messageID += ".PCIeFatalMCBlockedTLP";
534 break;
535 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700536 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800537 break;
538 }
539 // Get the message data from eventData2 and eventData3
540
541 // Bus = eventData2 bits [7:0]
542 int bus = selData.eventData2;
543 // Device = eventData3 bits [7:3]
544 int device = selData.eventData3 >> 3 & 0x1F;
545 // Function = eventData3 bits [2:0]
546 int function = selData.eventData3 >> 0x07;
547
548 // Save the messageArgs
549 messageArgs.push_back(std::to_string(bus));
550 messageArgs.push_back(std::to_string(device));
551 messageArgs.push_back(std::to_string(function));
552
553 break;
554 }
555 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700556 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800557 break;
558 }
559 break;
560 case BIOSSMISensors::pcieCorrectableError:
561 switch (eventType)
562 {
563 case BIOSEventTypes::oemDiscrete1:
564 {
565 switch (selData.offset)
566 {
567 case 0x00:
568 messageID += ".PCIeCorrectableReceiverError";
569 break;
570 case 0x01:
571 messageID += ".PCIeCorrectableBadDLLP";
572 break;
573 case 0x02:
574 messageID += ".PCIeCorrectableBadTLP";
575 break;
576 case 0x03:
577 messageID += ".PCIeCorrectableReplayNumRollover";
578 break;
579 case 0x04:
580 messageID += ".PCIeCorrectableReplayTimerTimeout";
581 break;
582 case 0x05:
583 messageID += ".PCIeCorrectableAdvisoryNonFatal";
584 break;
585 case 0x06:
586 messageID += ".PCIeCorrectableLinkBWChanged";
587 break;
588 case 0x07:
589 messageID += ".PCIeCorrectableInternal";
590 break;
591 case 0x08:
592 messageID += ".PCIeCorrectableHeaderLogOverflow";
593 break;
594 case 0x0f:
595 messageID += ".PCIeCorrectableUnspecifiedAERError";
596 break;
597 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700598 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800599 break;
600 }
601 // Get the message data from eventData2 and eventData3
602
603 // Bus = eventData2 bits [7:0]
604 int bus = selData.eventData2;
605 // Device = eventData3 bits [7:3]
606 int device = selData.eventData3 >> 3 & 0x1F;
607 // Function = eventData3 bits [2:0]
608 int function = selData.eventData3 >> 0x07;
609
610 // Save the messageArgs
611 messageArgs.push_back(std::to_string(bus));
612 messageArgs.push_back(std::to_string(device));
613 messageArgs.push_back(std::to_string(function));
614
615 break;
616 }
617 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700618 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800619 break;
620 }
621 break;
622 case BIOSSMISensors::sparingRedundancyState:
623 switch (eventType)
624 {
625 case BIOSEventTypes::discreteRedundancyStates:
626 {
627 switch (selData.offset)
628 {
629 case 0x00:
630 messageID += ".SparingRedundancyFull";
631 break;
632 case 0x02:
633 messageID += ".SparingRedundancyDegraded";
634 break;
635 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700636 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800637 break;
638 }
639 // Get the message data from eventData2 and eventData3
640
641 // domain = eventData2 bits [7:4]
642 int domain = selData.eventData2 >> 4 & 0x0F;
643 char domainLetter[4] = {'A'};
644 domainLetter[0] += domain;
645 // rank = eventData2 bits [1:0]
646 int rank = selData.eventData2 & 0x03;
647
648 // Socket ID = eventData3 bits [7:5]
649 int socket = selData.eventData3 >> 5 & 0x07;
650 // Channel = eventData3 bits [4:2]
651 int channel = selData.eventData3 >> 2 & 0x07;
652 char channelLetter[4] = {'A'};
653 channelLetter[0] += channel;
654 // DIMM = eventData3 bits [1:0]
655 int dimm = selData.eventData3 & 0x03;
656
657 // Save the messageArgs
658 messageArgs.push_back(std::to_string(socket + 1));
659 messageArgs.push_back(std::string(channelLetter));
660 messageArgs.push_back(std::to_string(dimm + 1));
661 messageArgs.push_back(std::string(domainLetter));
662 messageArgs.push_back(std::to_string(rank));
663
664 break;
665 }
666 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700667 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800668 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:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700692 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800693 break;
694 }
695 break;
696 }
697 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700698 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800699 break;
700 }
701 // Get the message data from eventData2 and eventData3
702
703 // channelValid = eventData2 bit [4]
704 int channelValid = selData.eventData2 >> 4 & 0x01;
705 // dimmValid = eventData2 bit [3]
706 int dimmValid = selData.eventData2 >> 3 & 0x01;
707
708 // Socket ID = eventData3 bits [7:5]
709 int socket = selData.eventData3 >> 5 & 0x07;
710 // Channel = eventData3 bits [4:2]
711 int channel = selData.eventData3 >> 2 & 0x07;
712 char channelLetter[4] = {'A'};
713 channelLetter[0] += channel;
714 // DIMM = eventData3 bits [1:0]
715 int dimm = selData.eventData3 & 0x03;
716
717 // Save the messageArgs
718 messageArgs.push_back(std::to_string(socket + 1));
719 messageArgs.push_back(std::string(channelLetter));
720 messageArgs.push_back(std::to_string(dimm + 1));
721 messageArgs.push_back(std::to_string(channelValid));
722 messageArgs.push_back(std::to_string(dimmValid));
723
724 break;
725 }
726 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700727 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800728 break;
729 }
730 break;
731 case BIOSSMISensors::pcieFatalError2:
732 switch (eventType)
733 {
734 case BIOSEventTypes::oemDiscrete6:
735 {
736 switch (selData.offset)
737 {
738 case 0x00:
739 messageID += ".PCIeFatalAtomicEgressBlocked";
740 break;
741 case 0x01:
742 messageID += ".PCIeFatalTLPPrefixBlocked";
743 break;
744 case 0x0f:
745 messageID +=
746 ".PCIeFatalUnspecifiedNonAERFatalError";
747 break;
748 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700749 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800750 break;
751 }
752 // Get the message data from eventData2 and eventData3
753
754 // Bus = eventData2 bits [7:0]
755 int bus = selData.eventData2;
756 // Device = eventData3 bits [7:3]
757 int device = selData.eventData3 >> 3 & 0x1F;
758 // Function = eventData3 bits [2:0]
759 int function = selData.eventData3 >> 0x07;
760
761 // Save the messageArgs
762 messageArgs.push_back(std::to_string(bus));
763 messageArgs.push_back(std::to_string(device));
764 messageArgs.push_back(std::to_string(function));
765
766 break;
767 }
768 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700769 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800770 break;
771 }
772 break;
773 case BIOSSMISensors::biosRecovery:
774 switch (eventType)
775 {
776 case BIOSEventTypes::oemDiscrete0:
777 {
778 switch (selData.offset)
779 {
780 case 0x01:
781 messageID += ".BIOSRecoveryStart";
782 break;
783 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700784 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800785 break;
786 }
787 break;
788 }
789 case BIOSEventTypes::reservedF0:
790 {
791 switch (selData.offset)
792 {
793 case 0x01:
794 messageID += ".BIOSRecoveryComplete";
795 break;
796 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700797 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800798 break;
799 }
800 break;
801 }
802 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700803 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800804 break;
805 }
806 break;
807 case BIOSSMISensors::adddcError:
808 switch (eventType)
809 {
810 case BIOSEventTypes::reservedA0:
811 {
812 messageID += ".ADDDCCorrectable";
813
814 // Get the message data from eventData2 and eventData3
815
816 // dimm = eventData2 bits [7:4]
817 int dimm = selData.eventData2 >> 4 & 0x0F;
818 // rank = eventData2 bits [3:0]
819 int rank = selData.eventData2 & 0x0F;
820
821 // Socket ID = eventData3 bits [7:4]
822 int socket = selData.eventData3 >> 4 & 0x0F;
823 // Channel = eventData3 bits [3:0]
824 int channel = selData.eventData3 & 0x0F;
825 char channelLetter[4] = {'A'};
826 channelLetter[0] += channel;
827
828 // Save the messageArgs
829 messageArgs.push_back(std::to_string(socket + 1));
830 messageArgs.push_back(std::string(channelLetter));
831 messageArgs.push_back(std::to_string(dimm));
832 messageArgs.push_back(std::to_string(rank));
833
834 break;
835 }
836 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700837 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800838 break;
839 }
840 break;
841 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700842 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800843 break;
844 }
845
846 // Log the Redfish message to the journal with the appropriate metadata
847 std::string journalMsg = "BIOS SMI IPMI event: " + ipmiRaw;
848 std::string messageArgsString = boost::algorithm::join(messageArgs, ",");
849 phosphor::logging::log<phosphor::logging::level::INFO>(
850 journalMsg.c_str(),
851 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageID.c_str()),
852 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
853 messageArgsString.c_str()));
854
855 return true;
856}
857
858static bool startRedfishHook(const SELData& selData, const std::string& ipmiRaw)
859{
860 switch (selData.generatorID)
861 {
862 case 0x01: // Check if this message is from the BIOS Generator ID
863 // Let the BIOS hook handle this request
864 return biosMessageHook(selData, ipmiRaw);
865 break;
866
867 case 0x33: // Check if this message is from the BIOS SMI Generator ID
868 // Let the BIOS SMI hook handle this request
869 return biosSMIMessageHook(selData, ipmiRaw);
870 break;
871 }
872
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700873 // No hooks handled the request, so let it go to default
874 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800875}
876} // namespace redfish_hooks
877
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700878bool checkRedfishHooks(uint16_t recordID, uint8_t recordType,
879 uint32_t timestamp, uint16_t generatorID, uint8_t evmRev,
880 uint8_t sensorType, uint8_t sensorNum, uint8_t eventType,
881 uint8_t eventData1, uint8_t eventData2,
882 uint8_t eventData3)
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800883{
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800884 // Save the raw IPMI string of the request
885 std::string ipmiRaw;
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700886 std::array selBytes = {static_cast<uint8_t>(recordID),
887 static_cast<uint8_t>(recordID >> 8),
888 recordType,
889 static_cast<uint8_t>(timestamp),
890 static_cast<uint8_t>(timestamp >> 8),
891 static_cast<uint8_t>(timestamp >> 16),
892 static_cast<uint8_t>(timestamp >> 24),
893 static_cast<uint8_t>(generatorID),
894 static_cast<uint8_t>(generatorID >> 8),
895 evmRev,
896 sensorType,
897 sensorNum,
898 eventType,
899 eventData1,
900 eventData2,
901 eventData3};
902 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
903
904 // First check that this is a system event record type since that
905 // determines the definition of the rest of the data
906 if (recordType != ipmi::sel::systemEvent)
907 {
908 // OEM record type, so let it go to the SEL
909 return redfish_hooks::defaultMessageHook(ipmiRaw);
910 }
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800911
912 // Extract the SEL data for the hook
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700913 redfish_hooks::SELData selData = {.generatorID = generatorID,
914 .sensorNum = sensorNum,
915 .eventType = eventType,
916 .offset = eventData1 & 0x0F,
917 .eventData2 = eventData2,
918 .eventData3 = eventData3};
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800919
920 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
921}
922
923bool checkRedfishHooks(uint8_t generatorID, uint8_t evmRev, uint8_t sensorType,
924 uint8_t sensorNum, uint8_t eventType, uint8_t eventData1,
925 uint8_t eventData2, uint8_t eventData3)
926{
927 // Save the raw IPMI string of the selData
928 std::string ipmiRaw;
929 std::array selBytes = {generatorID, evmRev, sensorType, sensorNum,
930 eventType, eventData1, eventData2, eventData3};
931 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
932
933 // Extract the SEL data for the hook
934 redfish_hooks::SELData selData = {.generatorID = generatorID,
935 .sensorNum = sensorNum,
936 .eventType = eventType,
937 .offset = eventData1 & 0x0F,
938 .eventData2 = eventData2,
939 .eventData3 = eventData3};
940
941 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
942}
943
944} // namespace intel_oem::ipmi::sel