blob: 9cac813c497f00fd0ab220a80eb85a9636687d99 [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>
18#include <iomanip>
19#include <ipmi_to_redfish_hooks.hpp>
Agnieszka Szlendakd2220cc2020-04-17 15:00:12 +020020#include <me_to_redfish_hooks.hpp>
Jason M. Bills99b78ec2019-01-18 10:42:18 -080021#include <sstream>
22#include <storagecommands.hpp>
23#include <string_view>
24
25namespace intel_oem::ipmi::sel
26{
27
28namespace redfish_hooks
29{
30static void toHexStr(const boost::beast::span<uint8_t> bytes,
31 std::string& hexStr)
32{
33 std::stringstream stream;
34 stream << std::hex << std::uppercase << std::setfill('0');
35 for (const uint8_t& byte : bytes)
36 {
37 stream << std::setw(2) << static_cast<int>(byte);
38 }
39 hexStr = stream.str();
40}
41
42// Record a BIOS message as a Redfish message instead of a SEL record
43static bool biosMessageHook(const SELData& selData, const std::string& ipmiRaw)
44{
45 // This is a BIOS message, so record it as a Redfish message instead
46 // of a SEL record
47
48 // Walk through the SEL request record to build the appropriate Redfish
49 // message
50 static constexpr std::string_view openBMCMessageRegistryVersion = "0.1";
51 std::string messageID =
52 "OpenBMC." + std::string(openBMCMessageRegistryVersion);
53 std::vector<std::string> messageArgs;
54 BIOSSensors sensor = static_cast<BIOSSensors>(selData.sensorNum);
55 BIOSEventTypes eventType = static_cast<BIOSEventTypes>(selData.eventType);
56 switch (sensor)
57 {
58 case BIOSSensors::memoryRASConfigStatus:
59 switch (eventType)
60 {
61 case BIOSEventTypes::digitalDiscrete:
62 {
63 switch (selData.offset)
64 {
65 case 0x00:
66 messageID += ".MemoryRASConfigurationDisabled";
67 break;
68 case 0x01:
69 messageID += ".MemoryRASConfigurationEnabled";
70 break;
71 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -070072 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -080073 break;
74 }
75 // Get the message data from eventData2 and eventData3
76
77 // error = eventData2 bits [3:0]
78 int error = selData.eventData2 & 0x0F;
79
80 // mode = eventData3 bits [3:0]
81 int mode = selData.eventData3 & 0x0F;
82
83 // Save the messageArgs
84 switch (error)
85 {
86 case 0x00:
87 messageArgs.push_back("None");
88 break;
89 case 0x03:
90 messageArgs.push_back("Invalid DIMM Config");
91 break;
92 default:
93 messageArgs.push_back(std::to_string(error));
94 break;
95 }
96 switch (mode)
97 {
98 case 0x00:
99 messageArgs.push_back("None");
100 break;
101 case 0x01:
102 messageArgs.push_back("Mirroring");
103 break;
104 case 0x02:
105 messageArgs.push_back("Lockstep");
106 break;
107 case 0x04:
108 messageArgs.push_back("Rank Sparing");
109 break;
110 default:
111 messageArgs.push_back(std::to_string(mode));
112 break;
113 }
114
115 break;
116 }
117 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700118 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800119 break;
120 }
121 break;
122 case BIOSSensors::biosPOSTError:
123 switch (eventType)
124 {
125 case BIOSEventTypes::sensorSpecificOffset:
126 {
127 switch (selData.offset)
128 {
129 case 0x00:
130 messageID += ".BIOSPOSTError";
131 break;
132 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700133 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800134 break;
135 }
136 // Get the message data from eventData2 and eventData3
137
138 std::array<uint8_t, 2> post;
139 // post LSB = eventData2 bits [7:0]
140 post[1] = selData.eventData2;
141 // post MSB = eventData3 bits [7:0]
142 post[0] = selData.eventData3;
143
144 // Save the messageArgs
145 messageArgs.emplace_back();
146 std::string& postStr = messageArgs.back();
147 toHexStr(boost::beast::span<uint8_t>(post), postStr);
148
149 break;
150 }
151 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700152 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800153 break;
154 }
155 break;
156 case BIOSSensors::intelUPILinkWidthReduced:
157 switch (eventType)
158 {
159 case BIOSEventTypes::oemDiscrete7:
160 {
161 switch (selData.offset)
162 {
163 case 0x01:
164 messageID += ".IntelUPILinkWidthReducedToHalf";
165 break;
166 case 0x02:
167 messageID += ".IntelUPILinkWidthReducedToQuarter";
168 break;
169 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700170 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800171 break;
172 }
173 // Get the message data from eventData2
174
175 // Node ID = eventData2 bits [7:0]
176 int node = selData.eventData2;
177
178 // Save the messageArgs
179 messageArgs.push_back(std::to_string(node + 1));
180
181 break;
182 }
183 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700184 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800185 break;
186 }
187 break;
188 case BIOSSensors::memoryRASModeSelect:
189 switch (eventType)
190 {
191 case BIOSEventTypes::digitalDiscrete:
192 {
193 switch (selData.offset)
194 {
195 case 0x00:
196 messageID += ".MemoryRASModeDisabled";
197 break;
198 case 0x01:
199 messageID += ".MemoryRASModeEnabled";
200 break;
201 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700202 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800203 break;
204 }
205 // Get the message data from eventData2 and eventData3
206
207 // prior mode = eventData2 bits [3:0]
208 int priorMode = selData.eventData2 & 0x0F;
209
210 // selected mode = eventData3 bits [3:0]
211 int selectedMode = selData.eventData3 & 0x0F;
212
213 // Save the messageArgs
214 switch (priorMode)
215 {
216 case 0x00:
217 messageArgs.push_back("None");
218 break;
219 case 0x01:
220 messageArgs.push_back("Mirroring");
221 break;
222 case 0x02:
223 messageArgs.push_back("Lockstep");
224 break;
225 case 0x04:
226 messageArgs.push_back("Rank Sparing");
227 break;
228 default:
229 messageArgs.push_back(std::to_string(priorMode));
230 break;
231 }
232 switch (selectedMode)
233 {
234 case 0x00:
235 messageArgs.push_back("None");
236 break;
237 case 0x01:
238 messageArgs.push_back("Mirroring");
239 break;
240 case 0x02:
241 messageArgs.push_back("Lockstep");
242 break;
243 case 0x04:
244 messageArgs.push_back("Rank Sparing");
245 break;
246 default:
247 messageArgs.push_back(std::to_string(selectedMode));
248 break;
249 }
250
251 break;
252 }
253 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700254 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800255 break;
256 }
257 break;
258 case BIOSSensors::bootEvent:
259 switch (eventType)
260 {
261 case BIOSEventTypes::sensorSpecificOffset:
262 {
263 switch (selData.offset)
264 {
265 case 0x01:
266 messageID += ".BIOSBoot";
267 break;
268 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700269 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800270 break;
271 }
272 break;
273 }
274 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700275 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800276 break;
277 }
278 break;
279 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700280 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800281 break;
282 }
283
284 // Log the Redfish message to the journal with the appropriate metadata
285 std::string journalMsg = "BIOS POST IPMI event: " + ipmiRaw;
286 if (messageArgs.empty())
287 {
288 phosphor::logging::log<phosphor::logging::level::INFO>(
289 journalMsg.c_str(),
290 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s",
291 messageID.c_str()));
292 }
293 else
294 {
295 std::string messageArgsString =
296 boost::algorithm::join(messageArgs, ",");
297 phosphor::logging::log<phosphor::logging::level::INFO>(
298 journalMsg.c_str(),
299 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s",
300 messageID.c_str()),
301 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
302 messageArgsString.c_str()));
303 }
304
305 return true;
306}
307
308// Record a BIOS SMI message as a Redfish message instead of a SEL record
309static bool biosSMIMessageHook(const SELData& selData,
310 const std::string& ipmiRaw)
311{
312 // This is a BIOS SMI message, so record it as a Redfish message instead
313 // of a SEL record
314
315 // Walk through the SEL request record to build the appropriate Redfish
316 // message
317 static constexpr std::string_view openBMCMessageRegistryVersion = "0.1";
318 std::string messageID =
319 "OpenBMC." + std::string(openBMCMessageRegistryVersion);
320 std::vector<std::string> messageArgs;
321 BIOSSMISensors sensor = static_cast<BIOSSMISensors>(selData.sensorNum);
322 BIOSEventTypes eventType = static_cast<BIOSEventTypes>(selData.eventType);
323 switch (sensor)
324 {
325 case BIOSSMISensors::mirroringRedundancyState:
326 switch (eventType)
327 {
328 case BIOSEventTypes::discreteRedundancyStates:
329 {
330 switch (selData.offset)
331 {
332 case 0x00:
333 messageID += ".MirroringRedundancyFull";
334 break;
335 case 0x02:
336 messageID += ".MirroringRedundancyDegraded";
337 break;
338 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700339 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800340 break;
341 }
342 // Get the message data from eventData2 and eventData3
343
344 // pair = eventData2 bits [7:4]
345 int pair = selData.eventData2 >> 4 & 0x0F;
346 // rank = eventData2 bits [1:0]
347 int rank = selData.eventData2 & 0x03;
348
349 // Socket ID = eventData3 bits [7:5]
350 int socket = selData.eventData3 >> 5 & 0x07;
351 // Channel = eventData3 bits [4:2]
352 int channel = selData.eventData3 >> 2 & 0x07;
353 char channelLetter[4] = {'A'};
354 channelLetter[0] += channel;
355 // DIMM = eventData3 bits [1:0]
356 int dimm = selData.eventData3 & 0x03;
357
358 // Save the messageArgs
359 messageArgs.push_back(std::to_string(socket + 1));
360 messageArgs.push_back(std::string(channelLetter));
361 messageArgs.push_back(std::to_string(dimm + 1));
362 messageArgs.push_back(std::to_string(pair));
363 messageArgs.push_back(std::to_string(rank));
364
365 break;
366 }
367 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700368 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800369 break;
370 }
371 break;
372 case BIOSSMISensors::memoryECCError:
373 switch (eventType)
374 {
375 case BIOSEventTypes::sensorSpecificOffset:
376 {
377 switch (selData.offset)
378 {
379 case 0x00:
380 messageID += ".MemoryECCCorrectable";
381 break;
382 case 0x01:
383 messageID += ".MemoryECCUncorrectable";
384 break;
385 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700386 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800387 break;
388 }
389 // Get the message data from eventData2 and eventData3
390
391 // dimm = eventData2 bits [7:4]
392 int dimm = selData.eventData2 >> 4 & 0x0F;
393 // rank = eventData2 bits [3:0]
394 int rank = selData.eventData2 & 0x0F;
395
396 // Socket ID = eventData3 bits [7:4]
397 int socket = selData.eventData3 >> 4 & 0x0F;
398 // Channel = eventData3 bits [3:0]
399 int channel = selData.eventData3 & 0x0F;
400 char channelLetter[4] = {'A'};
401 channelLetter[0] += channel;
402
403 // Save the messageArgs
404 messageArgs.push_back(std::to_string(socket + 1));
405 messageArgs.push_back(std::string(channelLetter));
406 messageArgs.push_back(std::to_string(dimm));
407 messageArgs.push_back(std::to_string(rank));
408
409 break;
410 }
411 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700412 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800413 break;
414 }
415 break;
416 case BIOSSMISensors::legacyPCIError:
417 switch (eventType)
418 {
419 case BIOSEventTypes::sensorSpecificOffset:
420 {
421 switch (selData.offset)
422 {
423 case 0x04:
424 messageID += ".LegacyPCIPERR";
425 break;
426 case 0x05:
427 messageID += ".LegacyPCISERR";
428 break;
429 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700430 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800431 break;
432 }
433 // Get the message data from eventData2 and eventData3
434
435 // Bus = eventData2 bits [7:0]
436 int bus = selData.eventData2;
437 // Device = eventData3 bits [7:3]
438 int device = selData.eventData3 >> 3 & 0x1F;
439 // Function = eventData3 bits [2:0]
440 int function = selData.eventData3 >> 0x07;
441
442 // Save the messageArgs
443 messageArgs.push_back(std::to_string(bus));
444 messageArgs.push_back(std::to_string(device));
445 messageArgs.push_back(std::to_string(function));
446
447 break;
448 }
449 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700450 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800451 break;
452 }
453 break;
454 case BIOSSMISensors::pcieFatalError:
455 switch (eventType)
456 {
457 case BIOSEventTypes::oemDiscrete0:
458 {
459 switch (selData.offset)
460 {
461 case 0x00:
462 messageID += ".PCIeFatalDataLinkLayerProtocol";
463 break;
464 case 0x01:
465 messageID += ".PCIeFatalSurpriseLinkDown";
466 break;
467 case 0x02:
468 messageID += ".PCIeFatalCompleterAbort";
469 break;
470 case 0x03:
471 messageID += ".PCIeFatalUnsupportedRequest";
472 break;
473 case 0x04:
474 messageID += ".PCIeFatalPoisonedTLP";
475 break;
476 case 0x05:
477 messageID += ".PCIeFatalFlowControlProtocol";
478 break;
479 case 0x06:
480 messageID += ".PCIeFatalCompletionTimeout";
481 break;
482 case 0x07:
483 messageID += ".PCIeFatalReceiverBufferOverflow";
484 break;
485 case 0x08:
486 messageID += ".PCIeFatalACSViolation";
487 break;
488 case 0x09:
489 messageID += ".PCIeFatalMalformedTLP";
490 break;
491 case 0x0a:
492 messageID += ".PCIeFatalECRCError";
493 break;
494 case 0x0b:
495 messageID +=
496 ".PCIeFatalReceivedFatalMessageFromDownstream";
497 break;
498 case 0x0c:
499 messageID += ".PCIeFatalUnexpectedCompletion";
500 break;
501 case 0x0d:
Jason M. Bills6757fb42019-06-14 08:58:38 -0700502 messageID += ".PCIeFatalReceivedErrNonFatalMessage";
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800503 break;
504 case 0x0e:
505 messageID += ".PCIeFatalUncorrectableInternal";
506 break;
507 case 0x0f:
508 messageID += ".PCIeFatalMCBlockedTLP";
509 break;
510 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700511 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800512 break;
513 }
514 // Get the message data from eventData2 and eventData3
515
516 // Bus = eventData2 bits [7:0]
517 int bus = selData.eventData2;
518 // Device = eventData3 bits [7:3]
519 int device = selData.eventData3 >> 3 & 0x1F;
520 // Function = eventData3 bits [2:0]
521 int function = selData.eventData3 >> 0x07;
522
523 // Save the messageArgs
524 messageArgs.push_back(std::to_string(bus));
525 messageArgs.push_back(std::to_string(device));
526 messageArgs.push_back(std::to_string(function));
527
528 break;
529 }
530 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700531 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800532 break;
533 }
534 break;
535 case BIOSSMISensors::pcieCorrectableError:
536 switch (eventType)
537 {
538 case BIOSEventTypes::oemDiscrete1:
539 {
540 switch (selData.offset)
541 {
542 case 0x00:
543 messageID += ".PCIeCorrectableReceiverError";
544 break;
545 case 0x01:
546 messageID += ".PCIeCorrectableBadDLLP";
547 break;
548 case 0x02:
549 messageID += ".PCIeCorrectableBadTLP";
550 break;
551 case 0x03:
552 messageID += ".PCIeCorrectableReplayNumRollover";
553 break;
554 case 0x04:
555 messageID += ".PCIeCorrectableReplayTimerTimeout";
556 break;
557 case 0x05:
558 messageID += ".PCIeCorrectableAdvisoryNonFatal";
559 break;
560 case 0x06:
561 messageID += ".PCIeCorrectableLinkBWChanged";
562 break;
563 case 0x07:
564 messageID += ".PCIeCorrectableInternal";
565 break;
566 case 0x08:
567 messageID += ".PCIeCorrectableHeaderLogOverflow";
568 break;
569 case 0x0f:
570 messageID += ".PCIeCorrectableUnspecifiedAERError";
571 break;
572 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700573 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800574 break;
575 }
576 // Get the message data from eventData2 and eventData3
577
578 // Bus = eventData2 bits [7:0]
579 int bus = selData.eventData2;
580 // Device = eventData3 bits [7:3]
581 int device = selData.eventData3 >> 3 & 0x1F;
582 // Function = eventData3 bits [2:0]
583 int function = selData.eventData3 >> 0x07;
584
585 // Save the messageArgs
586 messageArgs.push_back(std::to_string(bus));
587 messageArgs.push_back(std::to_string(device));
588 messageArgs.push_back(std::to_string(function));
589
590 break;
591 }
592 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700593 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800594 break;
595 }
596 break;
597 case BIOSSMISensors::sparingRedundancyState:
598 switch (eventType)
599 {
600 case BIOSEventTypes::discreteRedundancyStates:
601 {
602 switch (selData.offset)
603 {
604 case 0x00:
605 messageID += ".SparingRedundancyFull";
606 break;
607 case 0x02:
608 messageID += ".SparingRedundancyDegraded";
609 break;
610 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700611 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800612 break;
613 }
614 // Get the message data from eventData2 and eventData3
615
616 // domain = eventData2 bits [7:4]
617 int domain = selData.eventData2 >> 4 & 0x0F;
618 char domainLetter[4] = {'A'};
619 domainLetter[0] += domain;
620 // rank = eventData2 bits [1:0]
621 int rank = selData.eventData2 & 0x03;
622
623 // Socket ID = eventData3 bits [7:5]
624 int socket = selData.eventData3 >> 5 & 0x07;
625 // Channel = eventData3 bits [4:2]
626 int channel = selData.eventData3 >> 2 & 0x07;
627 char channelLetter[4] = {'A'};
628 channelLetter[0] += channel;
629 // DIMM = eventData3 bits [1:0]
630 int dimm = selData.eventData3 & 0x03;
631
632 // Save the messageArgs
633 messageArgs.push_back(std::to_string(socket + 1));
634 messageArgs.push_back(std::string(channelLetter));
635 messageArgs.push_back(std::to_string(dimm + 1));
636 messageArgs.push_back(std::string(domainLetter));
637 messageArgs.push_back(std::to_string(rank));
638
639 break;
640 }
641 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700642 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800643 break;
644 }
645 break;
646 case BIOSSMISensors::memoryParityError:
647 switch (eventType)
648 {
649 case BIOSEventTypes::sensorSpecificOffset:
650 {
651 switch (selData.offset)
652 {
653 case 0x03:
654 {
655 // type = eventData2 bits [2:0]
656 int type = selData.eventData2 & 0x07;
657 switch (type)
658 {
659 case 0x00:
660 messageID += ".MemoryParityNotKnown";
661 break;
662 case 0x03:
663 messageID +=
664 ".MemoryParityCommandAndAddress";
665 break;
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 }
672 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700673 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800674 break;
675 }
676 // Get the message data from eventData2 and eventData3
677
678 // channelValid = eventData2 bit [4]
679 int channelValid = selData.eventData2 >> 4 & 0x01;
680 // dimmValid = eventData2 bit [3]
681 int dimmValid = selData.eventData2 >> 3 & 0x01;
682
683 // Socket ID = eventData3 bits [7:5]
684 int socket = selData.eventData3 >> 5 & 0x07;
685 // Channel = eventData3 bits [4:2]
686 int channel = selData.eventData3 >> 2 & 0x07;
687 char channelLetter[4] = {'A'};
688 channelLetter[0] += channel;
689 // DIMM = eventData3 bits [1:0]
690 int dimm = selData.eventData3 & 0x03;
691
692 // Save the messageArgs
693 messageArgs.push_back(std::to_string(socket + 1));
694 messageArgs.push_back(std::string(channelLetter));
695 messageArgs.push_back(std::to_string(dimm + 1));
696 messageArgs.push_back(std::to_string(channelValid));
697 messageArgs.push_back(std::to_string(dimmValid));
698
699 break;
700 }
701 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700702 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800703 break;
704 }
705 break;
706 case BIOSSMISensors::pcieFatalError2:
707 switch (eventType)
708 {
709 case BIOSEventTypes::oemDiscrete6:
710 {
711 switch (selData.offset)
712 {
713 case 0x00:
714 messageID += ".PCIeFatalAtomicEgressBlocked";
715 break;
716 case 0x01:
717 messageID += ".PCIeFatalTLPPrefixBlocked";
718 break;
719 case 0x0f:
720 messageID +=
721 ".PCIeFatalUnspecifiedNonAERFatalError";
722 break;
723 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700724 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800725 break;
726 }
727 // Get the message data from eventData2 and eventData3
728
729 // Bus = eventData2 bits [7:0]
730 int bus = selData.eventData2;
731 // Device = eventData3 bits [7:3]
732 int device = selData.eventData3 >> 3 & 0x1F;
733 // Function = eventData3 bits [2:0]
734 int function = selData.eventData3 >> 0x07;
735
736 // Save the messageArgs
737 messageArgs.push_back(std::to_string(bus));
738 messageArgs.push_back(std::to_string(device));
739 messageArgs.push_back(std::to_string(function));
740
741 break;
742 }
743 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700744 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800745 break;
746 }
747 break;
748 case BIOSSMISensors::biosRecovery:
749 switch (eventType)
750 {
751 case BIOSEventTypes::oemDiscrete0:
752 {
753 switch (selData.offset)
754 {
755 case 0x01:
756 messageID += ".BIOSRecoveryStart";
757 break;
758 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700759 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800760 break;
761 }
762 break;
763 }
764 case BIOSEventTypes::reservedF0:
765 {
766 switch (selData.offset)
767 {
768 case 0x01:
769 messageID += ".BIOSRecoveryComplete";
770 break;
771 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700772 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800773 break;
774 }
775 break;
776 }
777 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700778 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800779 break;
780 }
781 break;
782 case BIOSSMISensors::adddcError:
783 switch (eventType)
784 {
785 case BIOSEventTypes::reservedA0:
786 {
787 messageID += ".ADDDCCorrectable";
788
789 // Get the message data from eventData2 and eventData3
790
791 // dimm = eventData2 bits [7:4]
792 int dimm = selData.eventData2 >> 4 & 0x0F;
793 // rank = eventData2 bits [3:0]
794 int rank = selData.eventData2 & 0x0F;
795
796 // Socket ID = eventData3 bits [7:4]
797 int socket = selData.eventData3 >> 4 & 0x0F;
798 // Channel = eventData3 bits [3:0]
799 int channel = selData.eventData3 & 0x0F;
800 char channelLetter[4] = {'A'};
801 channelLetter[0] += channel;
802
803 // Save the messageArgs
804 messageArgs.push_back(std::to_string(socket + 1));
805 messageArgs.push_back(std::string(channelLetter));
806 messageArgs.push_back(std::to_string(dimm));
807 messageArgs.push_back(std::to_string(rank));
808
809 break;
810 }
811 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700812 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800813 break;
814 }
815 break;
816 default:
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700817 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800818 break;
819 }
820
821 // Log the Redfish message to the journal with the appropriate metadata
822 std::string journalMsg = "BIOS SMI IPMI event: " + ipmiRaw;
823 std::string messageArgsString = boost::algorithm::join(messageArgs, ",");
824 phosphor::logging::log<phosphor::logging::level::INFO>(
825 journalMsg.c_str(),
826 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageID.c_str()),
827 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s",
828 messageArgsString.c_str()));
829
830 return true;
831}
832
833static bool startRedfishHook(const SELData& selData, const std::string& ipmiRaw)
834{
835 switch (selData.generatorID)
836 {
837 case 0x01: // Check if this message is from the BIOS Generator ID
838 // Let the BIOS hook handle this request
839 return biosMessageHook(selData, ipmiRaw);
840 break;
841
842 case 0x33: // Check if this message is from the BIOS SMI Generator ID
843 // Let the BIOS SMI hook handle this request
844 return biosSMIMessageHook(selData, ipmiRaw);
845 break;
Agnieszka Szlendakd2220cc2020-04-17 15:00:12 +0200846
847 case 0x2C: // Message from Intel ME
848 return me::messageHook(selData, ipmiRaw);
849 break;
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800850 }
851
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700852 // No hooks handled the request, so let it go to default
853 return defaultMessageHook(ipmiRaw);
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800854}
855} // namespace redfish_hooks
856
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700857bool checkRedfishHooks(uint16_t recordID, uint8_t recordType,
858 uint32_t timestamp, uint16_t generatorID, uint8_t evmRev,
859 uint8_t sensorType, uint8_t sensorNum, uint8_t eventType,
860 uint8_t eventData1, uint8_t eventData2,
861 uint8_t eventData3)
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800862{
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800863 // Save the raw IPMI string of the request
864 std::string ipmiRaw;
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700865 std::array selBytes = {static_cast<uint8_t>(recordID),
866 static_cast<uint8_t>(recordID >> 8),
867 recordType,
868 static_cast<uint8_t>(timestamp),
869 static_cast<uint8_t>(timestamp >> 8),
870 static_cast<uint8_t>(timestamp >> 16),
871 static_cast<uint8_t>(timestamp >> 24),
872 static_cast<uint8_t>(generatorID),
873 static_cast<uint8_t>(generatorID >> 8),
874 evmRev,
875 sensorType,
876 sensorNum,
877 eventType,
878 eventData1,
879 eventData2,
880 eventData3};
881 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
882
883 // First check that this is a system event record type since that
884 // determines the definition of the rest of the data
885 if (recordType != ipmi::sel::systemEvent)
886 {
887 // OEM record type, so let it go to the SEL
888 return redfish_hooks::defaultMessageHook(ipmiRaw);
889 }
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800890
891 // Extract the SEL data for the hook
Jason M. Bills6dd8f042019-04-11 10:39:02 -0700892 redfish_hooks::SELData selData = {.generatorID = generatorID,
893 .sensorNum = sensorNum,
894 .eventType = eventType,
895 .offset = eventData1 & 0x0F,
896 .eventData2 = eventData2,
897 .eventData3 = eventData3};
Jason M. Bills99b78ec2019-01-18 10:42:18 -0800898
899 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
900}
901
902bool checkRedfishHooks(uint8_t generatorID, uint8_t evmRev, uint8_t sensorType,
903 uint8_t sensorNum, uint8_t eventType, uint8_t eventData1,
904 uint8_t eventData2, uint8_t eventData3)
905{
906 // Save the raw IPMI string of the selData
907 std::string ipmiRaw;
908 std::array selBytes = {generatorID, evmRev, sensorType, sensorNum,
909 eventType, eventData1, eventData2, eventData3};
910 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw);
911
912 // Extract the SEL data for the hook
913 redfish_hooks::SELData selData = {.generatorID = generatorID,
914 .sensorNum = sensorNum,
915 .eventType = eventType,
916 .offset = eventData1 & 0x0F,
917 .eventData2 = eventData2,
918 .eventData3 = eventData3};
919
920 return redfish_hooks::startRedfishHook(selData, ipmiRaw);
921}
922
923} // namespace intel_oem::ipmi::sel