1 /* 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/beast/core/span.hpp> 18 #include <ipmi_to_redfish_hooks.hpp> 19 #include <me_to_redfish_hooks.hpp> 20 #include <storagecommands.hpp> 21 22 #include <iomanip> 23 #include <sstream> 24 #include <string_view> 25 26 namespace intel_oem::ipmi::sel 27 { 28 29 namespace redfish_hooks 30 { 31 static 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 44 static 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 return defaultMessageHook(ipmiRaw); 74 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: 119 return defaultMessageHook(ipmiRaw); 120 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: 134 return defaultMessageHook(ipmiRaw); 135 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: 153 return defaultMessageHook(ipmiRaw); 154 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: 171 return defaultMessageHook(ipmiRaw); 172 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: 185 return defaultMessageHook(ipmiRaw); 186 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: 203 return defaultMessageHook(ipmiRaw); 204 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: 255 return defaultMessageHook(ipmiRaw); 256 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: 270 return defaultMessageHook(ipmiRaw); 271 break; 272 } 273 break; 274 } 275 default: 276 return defaultMessageHook(ipmiRaw); 277 break; 278 } 279 break; 280 default: 281 return defaultMessageHook(ipmiRaw); 282 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 310 static 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: 340 return defaultMessageHook(ipmiRaw); 341 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: 369 return defaultMessageHook(ipmiRaw); 370 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: 387 return defaultMessageHook(ipmiRaw); 388 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: 413 return defaultMessageHook(ipmiRaw); 414 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: 431 return defaultMessageHook(ipmiRaw); 432 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: 451 return defaultMessageHook(ipmiRaw); 452 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: 503 messageID += ".PCIeFatalReceivedErrNonFatalMessage"; 504 break; 505 case 0x0e: 506 messageID += ".PCIeFatalUncorrectableInternal"; 507 break; 508 case 0x0f: 509 messageID += ".PCIeFatalMCBlockedTLP"; 510 break; 511 default: 512 return defaultMessageHook(ipmiRaw); 513 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: 532 return defaultMessageHook(ipmiRaw); 533 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: 574 return defaultMessageHook(ipmiRaw); 575 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: 594 return defaultMessageHook(ipmiRaw); 595 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: 612 return defaultMessageHook(ipmiRaw); 613 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: 643 return defaultMessageHook(ipmiRaw); 644 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: 668 return defaultMessageHook(ipmiRaw); 669 break; 670 } 671 break; 672 } 673 default: 674 return defaultMessageHook(ipmiRaw); 675 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: 703 return defaultMessageHook(ipmiRaw); 704 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: 725 return defaultMessageHook(ipmiRaw); 726 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: 745 return defaultMessageHook(ipmiRaw); 746 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: 760 return defaultMessageHook(ipmiRaw); 761 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: 773 return defaultMessageHook(ipmiRaw); 774 break; 775 } 776 break; 777 } 778 default: 779 return defaultMessageHook(ipmiRaw); 780 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: 813 return defaultMessageHook(ipmiRaw); 814 break; 815 } 816 break; 817 default: 818 return defaultMessageHook(ipmiRaw); 819 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 834 static 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; 847 848 case 0x2C: // Message from Intel ME 849 return me::messageHook(selData, ipmiRaw); 850 break; 851 } 852 853 // No hooks handled the request, so let it go to default 854 return defaultMessageHook(ipmiRaw); 855 } 856 } // namespace redfish_hooks 857 858 bool 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) 863 { 864 // Save the raw IPMI string of the request 865 std::string ipmiRaw; 866 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 } 891 892 // Extract the SEL data for the hook 893 redfish_hooks::SELData selData = {.generatorID = generatorID, 894 .sensorNum = sensorNum, 895 .eventType = eventType, 896 .offset = eventData1 & 0x0F, 897 .eventData2 = eventData2, 898 .eventData3 = eventData3}; 899 900 return redfish_hooks::startRedfishHook(selData, ipmiRaw); 901 } 902 903 bool 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 925