blob: 92f9f2eda269741b136bcaac6125cd695fa98613 [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
Jason M. Bills99b78ec2019-01-18 10:42:18 -080017#include <boost/beast/core/span.hpp>
Jason M. Bills99b78ec2019-01-18 10:42:18 -080018#include <ipmi_to_redfish_hooks.hpp>
Agnieszka Szlendakd2220cc2020-04-17 15:00:12 +020019#include <me_to_redfish_hooks.hpp>
Jason M. Bills99b78ec2019-01-18 10:42:18 -080020#include <storagecommands.hpp>
James Feistfcd2d3a2020-05-28 10:38:15 -070021
22#include <iomanip>
23#include <sstream>
Jason M. Bills99b78ec2019-01-18 10:42:18 -080024#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:
Jason M. Bills6dd8f042019-04-11 10:39:02 -070073 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -080074 break;
75 }
76 // Get the message data from eventData2 and eventData3
77
78 // error = eventData2 bits [3:0]
79 int error = selData.eventData2 & 0x0F;
80
81 // mode = eventData3 bits [3:0]
82 int mode = selData.eventData3 & 0x0F;
83
84 // Save the messageArgs
85 switch (error)
86 {
87 case 0x00:
88 messageArgs.push_back("None");
89 break;
90 case 0x03:
91 messageArgs.push_back("Invalid DIMM Config");
92 break;
93 default:
94 messageArgs.push_back(std::to_string(error));
95 break;
96 }
97 switch (mode)
98 {
99 case 0x00:
100 messageArgs.push_back("None");
101 break;
102 case 0x01:
103 messageArgs.push_back("Mirroring");
104 break;
105 case 0x02:
106 messageArgs.push_back("Lockstep");
107 break;
108 case 0x04:
109 messageArgs.push_back("Rank Sparing");
110 break;
111 default:
112 messageArgs.push_back(std::to_string(mode));
113 break;
114 }
115
116 break;
117 }
118 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700119 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800120 break;
121 }
122 break;
123 case BIOSSensors::biosPOSTError:
124 switch (eventType)
125 {
126 case BIOSEventTypes::sensorSpecificOffset:
127 {
128 switch (selData.offset)
129 {
130 case 0x00:
131 messageID += ".BIOSPOSTError";
132 break;
133 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700134 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800135 break;
136 }
137 // Get the message data from eventData2 and eventData3
138
139 std::array<uint8_t, 2> post;
140 // post LSB = eventData2 bits [7:0]
141 post[1] = selData.eventData2;
142 // post MSB = eventData3 bits [7:0]
143 post[0] = selData.eventData3;
144
145 // Save the messageArgs
146 messageArgs.emplace_back();
147 std::string& postStr = messageArgs.back();
148 toHexStr(boost::beast::span<uint8_t>(post), postStr);
149
150 break;
151 }
152 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700153 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800154 break;
155 }
156 break;
157 case BIOSSensors::intelUPILinkWidthReduced:
158 switch (eventType)
159 {
160 case BIOSEventTypes::oemDiscrete7:
161 {
162 switch (selData.offset)
163 {
164 case 0x01:
165 messageID += ".IntelUPILinkWidthReducedToHalf";
166 break;
167 case 0x02:
168 messageID += ".IntelUPILinkWidthReducedToQuarter";
169 break;
170 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700171 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800172 break;
173 }
174 // Get the message data from eventData2
175
176 // Node ID = eventData2 bits [7:0]
177 int node = selData.eventData2;
178
179 // Save the messageArgs
180 messageArgs.push_back(std::to_string(node + 1));
181
182 break;
183 }
184 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700185 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800186 break;
187 }
188 break;
189 case BIOSSensors::memoryRASModeSelect:
190 switch (eventType)
191 {
192 case BIOSEventTypes::digitalDiscrete:
193 {
194 switch (selData.offset)
195 {
196 case 0x00:
197 messageID += ".MemoryRASModeDisabled";
198 break;
199 case 0x01:
200 messageID += ".MemoryRASModeEnabled";
201 break;
202 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700203 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800204 break;
205 }
206 // Get the message data from eventData2 and eventData3
207
208 // prior mode = eventData2 bits [3:0]
209 int priorMode = selData.eventData2 & 0x0F;
210
211 // selected mode = eventData3 bits [3:0]
212 int selectedMode = selData.eventData3 & 0x0F;
213
214 // Save the messageArgs
215 switch (priorMode)
216 {
217 case 0x00:
218 messageArgs.push_back("None");
219 break;
220 case 0x01:
221 messageArgs.push_back("Mirroring");
222 break;
223 case 0x02:
224 messageArgs.push_back("Lockstep");
225 break;
226 case 0x04:
227 messageArgs.push_back("Rank Sparing");
228 break;
229 default:
230 messageArgs.push_back(std::to_string(priorMode));
231 break;
232 }
233 switch (selectedMode)
234 {
235 case 0x00:
236 messageArgs.push_back("None");
237 break;
238 case 0x01:
239 messageArgs.push_back("Mirroring");
240 break;
241 case 0x02:
242 messageArgs.push_back("Lockstep");
243 break;
244 case 0x04:
245 messageArgs.push_back("Rank Sparing");
246 break;
247 default:
248 messageArgs.push_back(std::to_string(selectedMode));
249 break;
250 }
251
252 break;
253 }
254 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700255 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800256 break;
257 }
258 break;
259 case BIOSSensors::bootEvent:
260 switch (eventType)
261 {
262 case BIOSEventTypes::sensorSpecificOffset:
263 {
264 switch (selData.offset)
265 {
266 case 0x01:
267 messageID += ".BIOSBoot";
268 break;
269 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700270 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800271 break;
272 }
273 break;
274 }
275 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700276 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800277 break;
278 }
279 break;
280 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700281 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800282 break;
283 }
284
285 // Log the Redfish message to the journal with the appropriate metadata
286 std::string journalMsg = "BIOS POST IPMI event: " + ipmiRaw;
287 if (messageArgs.empty())
288 {
289 phosphor::logging::log<phosphor::logging::level::INFO>(
290 journalMsg.c_str(),
291 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s",
292 messageID.c_str()));
293 }
294 else
295 {
296 std::string messageArgsString =
297 boost::algorithm::join(messageArgs, ",");
298 phosphor::logging::log<phosphor::logging::level::INFO>(
299 journalMsg.c_str(),
300 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s",
301 messageID.c_str()),
302 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
303 messageArgsString.c_str()));
304 }
305
306 return true;
307}
308
309// Record a BIOS SMI message as a Redfish message instead of a SEL record
310static bool biosSMIMessageHook(const SELData& selData,
311 const std::string& ipmiRaw)
312{
313 // This is a BIOS SMI message, so record it as a Redfish message instead
314 // of a SEL record
315
316 // Walk through the SEL request record to build the appropriate Redfish
317 // message
318 static constexpr std::string_view openBMCMessageRegistryVersion = "0.1";
319 std::string messageID =
320 "OpenBMC." + std::string(openBMCMessageRegistryVersion);
321 std::vector<std::string> messageArgs;
322 BIOSSMISensors sensor = static_cast<BIOSSMISensors>(selData.sensorNum);
323 BIOSEventTypes eventType = static_cast<BIOSEventTypes>(selData.eventType);
324 switch (sensor)
325 {
326 case BIOSSMISensors::mirroringRedundancyState:
327 switch (eventType)
328 {
329 case BIOSEventTypes::discreteRedundancyStates:
330 {
331 switch (selData.offset)
332 {
333 case 0x00:
334 messageID += ".MirroringRedundancyFull";
335 break;
336 case 0x02:
337 messageID += ".MirroringRedundancyDegraded";
338 break;
339 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700340 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800341 break;
342 }
343 // Get the message data from eventData2 and eventData3
344
345 // pair = eventData2 bits [7:4]
346 int pair = selData.eventData2 >> 4 & 0x0F;
347 // rank = eventData2 bits [1:0]
348 int rank = selData.eventData2 & 0x03;
349
350 // Socket ID = eventData3 bits [7:5]
351 int socket = selData.eventData3 >> 5 & 0x07;
352 // Channel = eventData3 bits [4:2]
353 int channel = selData.eventData3 >> 2 & 0x07;
354 char channelLetter[4] = {'A'};
355 channelLetter[0] += channel;
356 // DIMM = eventData3 bits [1:0]
357 int dimm = selData.eventData3 & 0x03;
358
359 // Save the messageArgs
360 messageArgs.push_back(std::to_string(socket + 1));
361 messageArgs.push_back(std::string(channelLetter));
362 messageArgs.push_back(std::to_string(dimm + 1));
363 messageArgs.push_back(std::to_string(pair));
364 messageArgs.push_back(std::to_string(rank));
365
366 break;
367 }
368 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700369 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800370 break;
371 }
372 break;
373 case BIOSSMISensors::memoryECCError:
374 switch (eventType)
375 {
376 case BIOSEventTypes::sensorSpecificOffset:
377 {
378 switch (selData.offset)
379 {
380 case 0x00:
381 messageID += ".MemoryECCCorrectable";
382 break;
383 case 0x01:
384 messageID += ".MemoryECCUncorrectable";
385 break;
386 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700387 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800388 break;
389 }
390 // Get the message data from eventData2 and eventData3
391
392 // dimm = eventData2 bits [7:4]
393 int dimm = selData.eventData2 >> 4 & 0x0F;
394 // rank = eventData2 bits [3:0]
395 int rank = selData.eventData2 & 0x0F;
396
397 // Socket ID = eventData3 bits [7:4]
398 int socket = selData.eventData3 >> 4 & 0x0F;
399 // Channel = eventData3 bits [3:0]
400 int channel = selData.eventData3 & 0x0F;
401 char channelLetter[4] = {'A'};
402 channelLetter[0] += channel;
403
404 // Save the messageArgs
405 messageArgs.push_back(std::to_string(socket + 1));
406 messageArgs.push_back(std::string(channelLetter));
407 messageArgs.push_back(std::to_string(dimm));
408 messageArgs.push_back(std::to_string(rank));
409
410 break;
411 }
412 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700413 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800414 break;
415 }
416 break;
417 case BIOSSMISensors::legacyPCIError:
418 switch (eventType)
419 {
420 case BIOSEventTypes::sensorSpecificOffset:
421 {
422 switch (selData.offset)
423 {
424 case 0x04:
425 messageID += ".LegacyPCIPERR";
426 break;
427 case 0x05:
428 messageID += ".LegacyPCISERR";
429 break;
430 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700431 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800432 break;
433 }
434 // Get the message data from eventData2 and eventData3
435
436 // Bus = eventData2 bits [7:0]
437 int bus = selData.eventData2;
438 // Device = eventData3 bits [7:3]
439 int device = selData.eventData3 >> 3 & 0x1F;
440 // Function = eventData3 bits [2:0]
441 int function = selData.eventData3 >> 0x07;
442
443 // Save the messageArgs
444 messageArgs.push_back(std::to_string(bus));
445 messageArgs.push_back(std::to_string(device));
446 messageArgs.push_back(std::to_string(function));
447
448 break;
449 }
450 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700451 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800452 break;
453 }
454 break;
455 case BIOSSMISensors::pcieFatalError:
456 switch (eventType)
457 {
458 case BIOSEventTypes::oemDiscrete0:
459 {
460 switch (selData.offset)
461 {
462 case 0x00:
463 messageID += ".PCIeFatalDataLinkLayerProtocol";
464 break;
465 case 0x01:
466 messageID += ".PCIeFatalSurpriseLinkDown";
467 break;
468 case 0x02:
469 messageID += ".PCIeFatalCompleterAbort";
470 break;
471 case 0x03:
472 messageID += ".PCIeFatalUnsupportedRequest";
473 break;
474 case 0x04:
475 messageID += ".PCIeFatalPoisonedTLP";
476 break;
477 case 0x05:
478 messageID += ".PCIeFatalFlowControlProtocol";
479 break;
480 case 0x06:
481 messageID += ".PCIeFatalCompletionTimeout";
482 break;
483 case 0x07:
484 messageID += ".PCIeFatalReceiverBufferOverflow";
485 break;
486 case 0x08:
487 messageID += ".PCIeFatalACSViolation";
488 break;
489 case 0x09:
490 messageID += ".PCIeFatalMalformedTLP";
491 break;
492 case 0x0a:
493 messageID += ".PCIeFatalECRCError";
494 break;
495 case 0x0b:
496 messageID +=
497 ".PCIeFatalReceivedFatalMessageFromDownstream";
498 break;
499 case 0x0c:
500 messageID += ".PCIeFatalUnexpectedCompletion";
501 break;
502 case 0x0d:
Jason M. Bills6757fb42019-06-14 08:58:38 -0700503 messageID += ".PCIeFatalReceivedErrNonFatalMessage";
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800504 break;
505 case 0x0e:
506 messageID += ".PCIeFatalUncorrectableInternal";
507 break;
508 case 0x0f:
509 messageID += ".PCIeFatalMCBlockedTLP";
510 break;
511 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700512 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800513 break;
514 }
515 // Get the message data from eventData2 and eventData3
516
517 // Bus = eventData2 bits [7:0]
518 int bus = selData.eventData2;
519 // Device = eventData3 bits [7:3]
520 int device = selData.eventData3 >> 3 & 0x1F;
521 // Function = eventData3 bits [2:0]
522 int function = selData.eventData3 >> 0x07;
523
524 // Save the messageArgs
525 messageArgs.push_back(std::to_string(bus));
526 messageArgs.push_back(std::to_string(device));
527 messageArgs.push_back(std::to_string(function));
528
529 break;
530 }
531 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700532 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800533 break;
534 }
535 break;
536 case BIOSSMISensors::pcieCorrectableError:
537 switch (eventType)
538 {
539 case BIOSEventTypes::oemDiscrete1:
540 {
541 switch (selData.offset)
542 {
543 case 0x00:
544 messageID += ".PCIeCorrectableReceiverError";
545 break;
546 case 0x01:
547 messageID += ".PCIeCorrectableBadDLLP";
548 break;
549 case 0x02:
550 messageID += ".PCIeCorrectableBadTLP";
551 break;
552 case 0x03:
553 messageID += ".PCIeCorrectableReplayNumRollover";
554 break;
555 case 0x04:
556 messageID += ".PCIeCorrectableReplayTimerTimeout";
557 break;
558 case 0x05:
559 messageID += ".PCIeCorrectableAdvisoryNonFatal";
560 break;
561 case 0x06:
562 messageID += ".PCIeCorrectableLinkBWChanged";
563 break;
564 case 0x07:
565 messageID += ".PCIeCorrectableInternal";
566 break;
567 case 0x08:
568 messageID += ".PCIeCorrectableHeaderLogOverflow";
569 break;
570 case 0x0f:
571 messageID += ".PCIeCorrectableUnspecifiedAERError";
572 break;
573 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700574 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800575 break;
576 }
577 // Get the message data from eventData2 and eventData3
578
579 // Bus = eventData2 bits [7:0]
580 int bus = selData.eventData2;
581 // Device = eventData3 bits [7:3]
582 int device = selData.eventData3 >> 3 & 0x1F;
583 // Function = eventData3 bits [2:0]
584 int function = selData.eventData3 >> 0x07;
585
586 // Save the messageArgs
587 messageArgs.push_back(std::to_string(bus));
588 messageArgs.push_back(std::to_string(device));
589 messageArgs.push_back(std::to_string(function));
590
591 break;
592 }
593 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700594 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800595 break;
596 }
597 break;
598 case BIOSSMISensors::sparingRedundancyState:
599 switch (eventType)
600 {
601 case BIOSEventTypes::discreteRedundancyStates:
602 {
603 switch (selData.offset)
604 {
605 case 0x00:
606 messageID += ".SparingRedundancyFull";
607 break;
608 case 0x02:
609 messageID += ".SparingRedundancyDegraded";
610 break;
611 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700612 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800613 break;
614 }
615 // Get the message data from eventData2 and eventData3
616
617 // domain = eventData2 bits [7:4]
618 int domain = selData.eventData2 >> 4 & 0x0F;
619 char domainLetter[4] = {'A'};
620 domainLetter[0] += domain;
621 // rank = eventData2 bits [1:0]
622 int rank = selData.eventData2 & 0x03;
623
624 // Socket ID = eventData3 bits [7:5]
625 int socket = selData.eventData3 >> 5 & 0x07;
626 // Channel = eventData3 bits [4:2]
627 int channel = selData.eventData3 >> 2 & 0x07;
628 char channelLetter[4] = {'A'};
629 channelLetter[0] += channel;
630 // DIMM = eventData3 bits [1:0]
631 int dimm = selData.eventData3 & 0x03;
632
633 // Save the messageArgs
634 messageArgs.push_back(std::to_string(socket + 1));
635 messageArgs.push_back(std::string(channelLetter));
636 messageArgs.push_back(std::to_string(dimm + 1));
637 messageArgs.push_back(std::string(domainLetter));
638 messageArgs.push_back(std::to_string(rank));
639
640 break;
641 }
642 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700643 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800644 break;
645 }
646 break;
647 case BIOSSMISensors::memoryParityError:
648 switch (eventType)
649 {
650 case BIOSEventTypes::sensorSpecificOffset:
651 {
652 switch (selData.offset)
653 {
654 case 0x03:
655 {
656 // type = eventData2 bits [2:0]
657 int type = selData.eventData2 & 0x07;
658 switch (type)
659 {
660 case 0x00:
661 messageID += ".MemoryParityNotKnown";
662 break;
663 case 0x03:
664 messageID +=
665 ".MemoryParityCommandAndAddress";
666 break;
667 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700668 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800669 break;
670 }
671 break;
672 }
673 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700674 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800675 break;
676 }
677 // Get the message data from eventData2 and eventData3
678
679 // channelValid = eventData2 bit [4]
680 int channelValid = selData.eventData2 >> 4 & 0x01;
681 // dimmValid = eventData2 bit [3]
682 int dimmValid = selData.eventData2 >> 3 & 0x01;
683
684 // Socket ID = eventData3 bits [7:5]
685 int socket = selData.eventData3 >> 5 & 0x07;
686 // Channel = eventData3 bits [4:2]
687 int channel = selData.eventData3 >> 2 & 0x07;
688 char channelLetter[4] = {'A'};
689 channelLetter[0] += channel;
690 // DIMM = eventData3 bits [1:0]
691 int dimm = selData.eventData3 & 0x03;
692
693 // Save the messageArgs
694 messageArgs.push_back(std::to_string(socket + 1));
695 messageArgs.push_back(std::string(channelLetter));
696 messageArgs.push_back(std::to_string(dimm + 1));
697 messageArgs.push_back(std::to_string(channelValid));
698 messageArgs.push_back(std::to_string(dimmValid));
699
700 break;
701 }
702 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700703 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800704 break;
705 }
706 break;
707 case BIOSSMISensors::pcieFatalError2:
708 switch (eventType)
709 {
710 case BIOSEventTypes::oemDiscrete6:
711 {
712 switch (selData.offset)
713 {
714 case 0x00:
715 messageID += ".PCIeFatalAtomicEgressBlocked";
716 break;
717 case 0x01:
718 messageID += ".PCIeFatalTLPPrefixBlocked";
719 break;
720 case 0x0f:
721 messageID +=
722 ".PCIeFatalUnspecifiedNonAERFatalError";
723 break;
724 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700725 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800726 break;
727 }
728 // Get the message data from eventData2 and eventData3
729
730 // Bus = eventData2 bits [7:0]
731 int bus = selData.eventData2;
732 // Device = eventData3 bits [7:3]
733 int device = selData.eventData3 >> 3 & 0x1F;
734 // Function = eventData3 bits [2:0]
735 int function = selData.eventData3 >> 0x07;
736
737 // Save the messageArgs
738 messageArgs.push_back(std::to_string(bus));
739 messageArgs.push_back(std::to_string(device));
740 messageArgs.push_back(std::to_string(function));
741
742 break;
743 }
744 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700745 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800746 break;
747 }
748 break;
749 case BIOSSMISensors::biosRecovery:
750 switch (eventType)
751 {
752 case BIOSEventTypes::oemDiscrete0:
753 {
754 switch (selData.offset)
755 {
756 case 0x01:
757 messageID += ".BIOSRecoveryStart";
758 break;
759 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700760 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800761 break;
762 }
763 break;
764 }
765 case BIOSEventTypes::reservedF0:
766 {
767 switch (selData.offset)
768 {
769 case 0x01:
770 messageID += ".BIOSRecoveryComplete";
771 break;
772 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700773 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800774 break;
775 }
776 break;
777 }
778 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700779 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800780 break;
781 }
782 break;
783 case BIOSSMISensors::adddcError:
784 switch (eventType)
785 {
786 case BIOSEventTypes::reservedA0:
787 {
788 messageID += ".ADDDCCorrectable";
789
790 // Get the message data from eventData2 and eventData3
791
792 // dimm = eventData2 bits [7:4]
793 int dimm = selData.eventData2 >> 4 & 0x0F;
794 // rank = eventData2 bits [3:0]
795 int rank = selData.eventData2 & 0x0F;
796
797 // Socket ID = eventData3 bits [7:4]
798 int socket = selData.eventData3 >> 4 & 0x0F;
799 // Channel = eventData3 bits [3:0]
800 int channel = selData.eventData3 & 0x0F;
801 char channelLetter[4] = {'A'};
802 channelLetter[0] += channel;
803
804 // Save the messageArgs
805 messageArgs.push_back(std::to_string(socket + 1));
806 messageArgs.push_back(std::string(channelLetter));
807 messageArgs.push_back(std::to_string(dimm));
808 messageArgs.push_back(std::to_string(rank));
809
810 break;
811 }
812 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700813 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800814 break;
815 }
816 break;
817 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700818 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800819 break;
820 }
821
822 // Log the Redfish message to the journal with the appropriate metadata
823 std::string journalMsg = "BIOS SMI IPMI event: " + ipmiRaw;
824 std::string messageArgsString = boost::algorithm::join(messageArgs, ",");
825 phosphor::logging::log<phosphor::logging::level::INFO>(
826 journalMsg.c_str(),
827 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageID.c_str()),
828 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
829 messageArgsString.c_str()));
830
831 return true;
832}
833
834static bool startRedfishHook(const SELData& selData, const std::string& ipmiRaw)
835{
836 switch (selData.generatorID)
837 {
838 case 0x01: // Check if this message is from the BIOS Generator ID
839 // Let the BIOS hook handle this request
840 return biosMessageHook(selData, ipmiRaw);
841 break;
842
843 case 0x33: // Check if this message is from the BIOS SMI Generator ID
844 // Let the BIOS SMI hook handle this request
845 return biosSMIMessageHook(selData, ipmiRaw);
846 break;
Agnieszka Szlendakd2220cc2020-04-17 15:00:12 +0200847
848 case 0x2C: // Message from Intel ME
849 return me::messageHook(selData, ipmiRaw);
850 break;
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800851 }
852
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700853 // No hooks handled the request, so let it go to default
854 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800855}
856} // namespace redfish_hooks
857
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700858bool checkRedfishHooks(uint16_t recordID, uint8_t recordType,
859 uint32_t timestamp, uint16_t generatorID, uint8_t evmRev,
860 uint8_t sensorType, uint8_t sensorNum, uint8_t eventType,
861 uint8_t eventData1, uint8_t eventData2,
862 uint8_t eventData3)
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800863{
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800864 // Save the raw IPMI string of the request
865 std::string ipmiRaw;
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700866 std::array selBytes = {static_cast<uint8_t>(recordID),
867 static_cast<uint8_t>(recordID >> 8),
868 recordType,
869 static_cast<uint8_t>(timestamp),
870 static_cast<uint8_t>(timestamp >> 8),
871 static_cast<uint8_t>(timestamp >> 16),
872 static_cast<uint8_t>(timestamp >> 24),
873 static_cast<uint8_t>(generatorID),
874 static_cast<uint8_t>(generatorID >> 8),
875 evmRev,
876 sensorType,
877 sensorNum,
878 eventType,
879 eventData1,
880 eventData2,
881 eventData3};
882 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
883
884 // First check that this is a system event record type since that
885 // determines the definition of the rest of the data
886 if (recordType != ipmi::sel::systemEvent)
887 {
888 // OEM record type, so let it go to the SEL
889 return redfish_hooks::defaultMessageHook(ipmiRaw);
890 }
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800891
892 // Extract the SEL data for the hook
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700893 redfish_hooks::SELData selData = {.generatorID = generatorID,
894 .sensorNum = sensorNum,
895 .eventType = eventType,
896 .offset = eventData1 & 0x0F,
897 .eventData2 = eventData2,
898 .eventData3 = eventData3};
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800899
900 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
901}
902
903bool checkRedfishHooks(uint8_t generatorID, uint8_t evmRev, uint8_t sensorType,
904 uint8_t sensorNum, uint8_t eventType, uint8_t eventData1,
905 uint8_t eventData2, uint8_t eventData3)
906{
907 // Save the raw IPMI string of the selData
908 std::string ipmiRaw;
909 std::array selBytes = {generatorID, evmRev, sensorType, sensorNum,
910 eventType, eventData1, eventData2, eventData3};
911 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
912
913 // Extract the SEL data for the hook
914 redfish_hooks::SELData selData = {.generatorID = generatorID,
915 .sensorNum = sensorNum,
916 .eventType = eventType,
917 .offset = eventData1 & 0x0F,
918 .eventData2 = eventData2,
919 .eventData3 = eventData3};
920
921 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
922}
923
924} // namespace intel_oem::ipmi::sel