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 case 0x09: 270 messageID += ".BIOSAttributesChanged"; 271 break; 272 default: 273 return defaultMessageHook(ipmiRaw); 274 break; 275 } 276 break; 277 } 278 default: 279 return defaultMessageHook(ipmiRaw); 280 break; 281 } 282 break; 283 default: 284 return defaultMessageHook(ipmiRaw); 285 break; 286 } 287 288 // Log the Redfish message to the journal with the appropriate metadata 289 std::string journalMsg = "BIOS POST IPMI event: " + ipmiRaw; 290 if (messageArgs.empty()) 291 { 292 phosphor::logging::log<phosphor::logging::level::INFO>( 293 journalMsg.c_str(), 294 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", 295 messageID.c_str())); 296 } 297 else 298 { 299 std::string messageArgsString = 300 boost::algorithm::join(messageArgs, ","); 301 phosphor::logging::log<phosphor::logging::level::INFO>( 302 journalMsg.c_str(), 303 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", 304 messageID.c_str()), 305 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s", 306 messageArgsString.c_str())); 307 } 308 309 return true; 310 } 311 312 // Record a BIOS SMI message as a Redfish message instead of a SEL record 313 static bool biosSMIMessageHook(const SELData& selData, 314 const std::string& ipmiRaw) 315 { 316 // This is a BIOS SMI message, so record it as a Redfish message instead 317 // of a SEL record 318 319 // Walk through the SEL request record to build the appropriate Redfish 320 // message 321 static constexpr std::string_view openBMCMessageRegistryVersion = "0.1"; 322 std::string messageID = 323 "OpenBMC." + std::string(openBMCMessageRegistryVersion); 324 std::vector<std::string> messageArgs; 325 BIOSSMISensors sensor = static_cast<BIOSSMISensors>(selData.sensorNum); 326 BIOSEventTypes eventType = static_cast<BIOSEventTypes>(selData.eventType); 327 switch (sensor) 328 { 329 case BIOSSMISensors::mirroringRedundancyState: 330 switch (eventType) 331 { 332 case BIOSEventTypes::discreteRedundancyStates: 333 { 334 switch (selData.offset) 335 { 336 case 0x00: 337 messageID += ".MirroringRedundancyFull"; 338 break; 339 case 0x02: 340 messageID += ".MirroringRedundancyDegraded"; 341 break; 342 default: 343 return defaultMessageHook(ipmiRaw); 344 break; 345 } 346 // Get the message data from eventData2 and eventData3 347 348 // pair = eventData2 bits [7:4] 349 int pair = selData.eventData2 >> 4 & 0x0F; 350 // rank = eventData2 bits [1:0] 351 int rank = selData.eventData2 & 0x03; 352 353 // Socket ID = eventData3 bits [7:5] 354 int socket = selData.eventData3 >> 5 & 0x07; 355 // Channel = eventData3 bits [4:2] 356 int channel = selData.eventData3 >> 2 & 0x07; 357 char channelLetter[4] = {'A'}; 358 channelLetter[0] += channel; 359 // DIMM = eventData3 bits [1:0] 360 int dimm = selData.eventData3 & 0x03; 361 362 // Save the messageArgs 363 messageArgs.push_back(std::to_string(socket + 1)); 364 messageArgs.push_back(std::string(channelLetter)); 365 messageArgs.push_back(std::to_string(dimm + 1)); 366 messageArgs.push_back(std::to_string(pair)); 367 messageArgs.push_back(std::to_string(rank)); 368 369 break; 370 } 371 default: 372 return defaultMessageHook(ipmiRaw); 373 break; 374 } 375 break; 376 case BIOSSMISensors::memoryECCError: 377 switch (eventType) 378 { 379 case BIOSEventTypes::sensorSpecificOffset: 380 { 381 switch (selData.offset) 382 { 383 case 0x00: 384 messageID += ".MemoryECCCorrectable"; 385 break; 386 case 0x01: 387 messageID += ".MemoryECCUncorrectable"; 388 break; 389 default: 390 return defaultMessageHook(ipmiRaw); 391 break; 392 } 393 // Get the message data from eventData2 and eventData3 394 395 // dimm = eventData2 bits [7:4] 396 int dimm = selData.eventData2 >> 4 & 0x0F; 397 // rank = eventData2 bits [3:0] 398 int rank = selData.eventData2 & 0x0F; 399 400 // Socket ID = eventData3 bits [7:4] 401 int socket = selData.eventData3 >> 4 & 0x0F; 402 // Channel = eventData3 bits [3:0] 403 int channel = selData.eventData3 & 0x0F; 404 char channelLetter[4] = {'A'}; 405 channelLetter[0] += channel; 406 407 // Save the messageArgs 408 messageArgs.push_back(std::to_string(socket + 1)); 409 messageArgs.push_back(std::string(channelLetter)); 410 messageArgs.push_back(std::to_string(dimm)); 411 messageArgs.push_back(std::to_string(rank)); 412 413 break; 414 } 415 default: 416 return defaultMessageHook(ipmiRaw); 417 break; 418 } 419 break; 420 case BIOSSMISensors::legacyPCIError: 421 switch (eventType) 422 { 423 case BIOSEventTypes::sensorSpecificOffset: 424 { 425 switch (selData.offset) 426 { 427 case 0x04: 428 messageID += ".LegacyPCIPERR"; 429 break; 430 case 0x05: 431 messageID += ".LegacyPCISERR"; 432 break; 433 default: 434 return defaultMessageHook(ipmiRaw); 435 break; 436 } 437 // Get the message data from eventData2 and eventData3 438 439 // Bus = eventData2 bits [7:0] 440 int bus = selData.eventData2; 441 // Device = eventData3 bits [7:3] 442 int device = selData.eventData3 >> 3 & 0x1F; 443 // Function = eventData3 bits [2:0] 444 int function = selData.eventData3 >> 0x07; 445 446 // Save the messageArgs 447 messageArgs.push_back(std::to_string(bus)); 448 messageArgs.push_back(std::to_string(device)); 449 messageArgs.push_back(std::to_string(function)); 450 451 break; 452 } 453 default: 454 return defaultMessageHook(ipmiRaw); 455 break; 456 } 457 break; 458 case BIOSSMISensors::pcieFatalError: 459 switch (eventType) 460 { 461 case BIOSEventTypes::oemDiscrete0: 462 { 463 switch (selData.offset) 464 { 465 case 0x00: 466 messageID += ".PCIeFatalDataLinkLayerProtocol"; 467 break; 468 case 0x01: 469 messageID += ".PCIeFatalSurpriseLinkDown"; 470 break; 471 case 0x02: 472 messageID += ".PCIeFatalCompleterAbort"; 473 break; 474 case 0x03: 475 messageID += ".PCIeFatalUnsupportedRequest"; 476 break; 477 case 0x04: 478 messageID += ".PCIeFatalPoisonedTLP"; 479 break; 480 case 0x05: 481 messageID += ".PCIeFatalFlowControlProtocol"; 482 break; 483 case 0x06: 484 messageID += ".PCIeFatalCompletionTimeout"; 485 break; 486 case 0x07: 487 messageID += ".PCIeFatalReceiverBufferOverflow"; 488 break; 489 case 0x08: 490 messageID += ".PCIeFatalACSViolation"; 491 break; 492 case 0x09: 493 messageID += ".PCIeFatalMalformedTLP"; 494 break; 495 case 0x0a: 496 messageID += ".PCIeFatalECRCError"; 497 break; 498 case 0x0b: 499 messageID += 500 ".PCIeFatalReceivedFatalMessageFromDownstream"; 501 break; 502 case 0x0c: 503 messageID += ".PCIeFatalUnexpectedCompletion"; 504 break; 505 case 0x0d: 506 messageID += ".PCIeFatalReceivedErrNonFatalMessage"; 507 break; 508 case 0x0e: 509 messageID += ".PCIeFatalUncorrectableInternal"; 510 break; 511 case 0x0f: 512 messageID += ".PCIeFatalMCBlockedTLP"; 513 break; 514 default: 515 return defaultMessageHook(ipmiRaw); 516 break; 517 } 518 // Get the message data from eventData2 and eventData3 519 520 // Bus = eventData2 bits [7:0] 521 int bus = selData.eventData2; 522 // Device = eventData3 bits [7:3] 523 int device = selData.eventData3 >> 3 & 0x1F; 524 // Function = eventData3 bits [2:0] 525 int function = selData.eventData3 >> 0x07; 526 527 // Save the messageArgs 528 messageArgs.push_back(std::to_string(bus)); 529 messageArgs.push_back(std::to_string(device)); 530 messageArgs.push_back(std::to_string(function)); 531 532 break; 533 } 534 default: 535 return defaultMessageHook(ipmiRaw); 536 break; 537 } 538 break; 539 case BIOSSMISensors::pcieCorrectableError: 540 switch (eventType) 541 { 542 case BIOSEventTypes::oemDiscrete1: 543 { 544 switch (selData.offset) 545 { 546 case 0x00: 547 messageID += ".PCIeCorrectableReceiverError"; 548 break; 549 case 0x01: 550 messageID += ".PCIeCorrectableBadDLLP"; 551 break; 552 case 0x02: 553 messageID += ".PCIeCorrectableBadTLP"; 554 break; 555 case 0x03: 556 messageID += ".PCIeCorrectableReplayNumRollover"; 557 break; 558 case 0x04: 559 messageID += ".PCIeCorrectableReplayTimerTimeout"; 560 break; 561 case 0x05: 562 messageID += ".PCIeCorrectableAdvisoryNonFatal"; 563 break; 564 case 0x06: 565 messageID += ".PCIeCorrectableLinkBWChanged"; 566 break; 567 case 0x07: 568 messageID += ".PCIeCorrectableInternal"; 569 break; 570 case 0x08: 571 messageID += ".PCIeCorrectableHeaderLogOverflow"; 572 break; 573 case 0x0f: 574 messageID += ".PCIeCorrectableUnspecifiedAERError"; 575 break; 576 default: 577 return defaultMessageHook(ipmiRaw); 578 break; 579 } 580 // Get the message data from eventData2 and eventData3 581 582 // Bus = eventData2 bits [7:0] 583 int bus = selData.eventData2; 584 // Device = eventData3 bits [7:3] 585 int device = selData.eventData3 >> 3 & 0x1F; 586 // Function = eventData3 bits [2:0] 587 int function = selData.eventData3 >> 0x07; 588 589 // Save the messageArgs 590 messageArgs.push_back(std::to_string(bus)); 591 messageArgs.push_back(std::to_string(device)); 592 messageArgs.push_back(std::to_string(function)); 593 594 break; 595 } 596 default: 597 return defaultMessageHook(ipmiRaw); 598 break; 599 } 600 break; 601 case BIOSSMISensors::sparingRedundancyState: 602 switch (eventType) 603 { 604 case BIOSEventTypes::discreteRedundancyStates: 605 { 606 switch (selData.offset) 607 { 608 case 0x00: 609 messageID += ".SparingRedundancyFull"; 610 break; 611 case 0x02: 612 messageID += ".SparingRedundancyDegraded"; 613 break; 614 default: 615 return defaultMessageHook(ipmiRaw); 616 break; 617 } 618 // Get the message data from eventData2 and eventData3 619 620 // domain = eventData2 bits [7:4] 621 int domain = selData.eventData2 >> 4 & 0x0F; 622 char domainLetter[4] = {'A'}; 623 domainLetter[0] += domain; 624 // rank = eventData2 bits [1:0] 625 int rank = selData.eventData2 & 0x03; 626 627 // Socket ID = eventData3 bits [7:5] 628 int socket = selData.eventData3 >> 5 & 0x07; 629 // Channel = eventData3 bits [4:2] 630 int channel = selData.eventData3 >> 2 & 0x07; 631 char channelLetter[4] = {'A'}; 632 channelLetter[0] += channel; 633 // DIMM = eventData3 bits [1:0] 634 int dimm = selData.eventData3 & 0x03; 635 636 // Save the messageArgs 637 messageArgs.push_back(std::to_string(socket + 1)); 638 messageArgs.push_back(std::string(channelLetter)); 639 messageArgs.push_back(std::to_string(dimm + 1)); 640 messageArgs.push_back(std::string(domainLetter)); 641 messageArgs.push_back(std::to_string(rank)); 642 643 break; 644 } 645 default: 646 return defaultMessageHook(ipmiRaw); 647 break; 648 } 649 break; 650 case BIOSSMISensors::memoryParityError: 651 switch (eventType) 652 { 653 case BIOSEventTypes::sensorSpecificOffset: 654 { 655 switch (selData.offset) 656 { 657 case 0x03: 658 { 659 // type = eventData2 bits [2:0] 660 int type = selData.eventData2 & 0x07; 661 switch (type) 662 { 663 case 0x00: 664 messageID += ".MemoryParityNotKnown"; 665 break; 666 case 0x03: 667 messageID += 668 ".MemoryParityCommandAndAddress"; 669 break; 670 default: 671 return defaultMessageHook(ipmiRaw); 672 break; 673 } 674 break; 675 } 676 default: 677 return defaultMessageHook(ipmiRaw); 678 break; 679 } 680 // Get the message data from eventData2 and eventData3 681 682 // channelValid = eventData2 bit [4] 683 int channelValid = selData.eventData2 >> 4 & 0x01; 684 // dimmValid = eventData2 bit [3] 685 int dimmValid = selData.eventData2 >> 3 & 0x01; 686 687 // Socket ID = eventData3 bits [7:5] 688 int socket = selData.eventData3 >> 5 & 0x07; 689 // Channel = eventData3 bits [4:2] 690 int channel = selData.eventData3 >> 2 & 0x07; 691 char channelLetter[4] = {'A'}; 692 channelLetter[0] += channel; 693 // DIMM = eventData3 bits [1:0] 694 int dimm = selData.eventData3 & 0x03; 695 696 // Save the messageArgs 697 messageArgs.push_back(std::to_string(socket + 1)); 698 messageArgs.push_back(std::string(channelLetter)); 699 messageArgs.push_back(std::to_string(dimm + 1)); 700 messageArgs.push_back(std::to_string(channelValid)); 701 messageArgs.push_back(std::to_string(dimmValid)); 702 703 break; 704 } 705 default: 706 return defaultMessageHook(ipmiRaw); 707 break; 708 } 709 break; 710 case BIOSSMISensors::pcieFatalError2: 711 switch (eventType) 712 { 713 case BIOSEventTypes::oemDiscrete6: 714 { 715 switch (selData.offset) 716 { 717 case 0x00: 718 messageID += ".PCIeFatalAtomicEgressBlocked"; 719 break; 720 case 0x01: 721 messageID += ".PCIeFatalTLPPrefixBlocked"; 722 break; 723 case 0x0f: 724 messageID += 725 ".PCIeFatalUnspecifiedNonAERFatalError"; 726 break; 727 default: 728 return defaultMessageHook(ipmiRaw); 729 break; 730 } 731 // Get the message data from eventData2 and eventData3 732 733 // Bus = eventData2 bits [7:0] 734 int bus = selData.eventData2; 735 // Device = eventData3 bits [7:3] 736 int device = selData.eventData3 >> 3 & 0x1F; 737 // Function = eventData3 bits [2:0] 738 int function = selData.eventData3 >> 0x07; 739 740 // Save the messageArgs 741 messageArgs.push_back(std::to_string(bus)); 742 messageArgs.push_back(std::to_string(device)); 743 messageArgs.push_back(std::to_string(function)); 744 745 break; 746 } 747 default: 748 return defaultMessageHook(ipmiRaw); 749 break; 750 } 751 break; 752 case BIOSSMISensors::biosRecovery: 753 switch (eventType) 754 { 755 case BIOSEventTypes::oemDiscrete0: 756 { 757 switch (selData.offset) 758 { 759 case 0x01: 760 messageID += ".BIOSRecoveryStart"; 761 break; 762 default: 763 return defaultMessageHook(ipmiRaw); 764 break; 765 } 766 break; 767 } 768 case BIOSEventTypes::reservedF0: 769 { 770 switch (selData.offset) 771 { 772 case 0x01: 773 messageID += ".BIOSRecoveryComplete"; 774 break; 775 default: 776 return defaultMessageHook(ipmiRaw); 777 break; 778 } 779 break; 780 } 781 default: 782 return defaultMessageHook(ipmiRaw); 783 break; 784 } 785 break; 786 case BIOSSMISensors::adddcError: 787 switch (eventType) 788 { 789 case BIOSEventTypes::reservedA0: 790 { 791 messageID += ".ADDDCCorrectable"; 792 793 // Get the message data from eventData2 and eventData3 794 795 // dimm = eventData2 bits [7:4] 796 int dimm = selData.eventData2 >> 4 & 0x0F; 797 // rank = eventData2 bits [3:0] 798 int rank = selData.eventData2 & 0x0F; 799 800 // Socket ID = eventData3 bits [7:4] 801 int socket = selData.eventData3 >> 4 & 0x0F; 802 // Channel = eventData3 bits [3:0] 803 int channel = selData.eventData3 & 0x0F; 804 char channelLetter[4] = {'A'}; 805 channelLetter[0] += channel; 806 807 // Save the messageArgs 808 messageArgs.push_back(std::to_string(socket + 1)); 809 messageArgs.push_back(std::string(channelLetter)); 810 messageArgs.push_back(std::to_string(dimm)); 811 messageArgs.push_back(std::to_string(rank)); 812 813 break; 814 } 815 default: 816 return defaultMessageHook(ipmiRaw); 817 break; 818 } 819 break; 820 default: 821 return defaultMessageHook(ipmiRaw); 822 break; 823 } 824 825 // Log the Redfish message to the journal with the appropriate metadata 826 std::string journalMsg = "BIOS SMI IPMI event: " + ipmiRaw; 827 std::string messageArgsString = boost::algorithm::join(messageArgs, ","); 828 phosphor::logging::log<phosphor::logging::level::INFO>( 829 journalMsg.c_str(), 830 phosphor::logging::entry("REDFISH_MESSAGE_ID=%s", messageID.c_str()), 831 phosphor::logging::entry("REDFISH_MESSAGE_ARGS=%s", 832 messageArgsString.c_str())); 833 834 return true; 835 } 836 837 static bool startRedfishHook(const SELData& selData, const std::string& ipmiRaw) 838 { 839 uint8_t generatorIDLowByte = static_cast<uint8_t>(selData.generatorID); 840 // Generator ID is 7 bit and LS Bit contains '1' or '0' depending on the 841 // source. Refer IPMI SPEC, Table 32, SEL Event Records. 842 switch (generatorIDLowByte) 843 { 844 case 0x01: // Check if this message is from the BIOS Generator ID 845 // Let the BIOS hook handle this request 846 return biosMessageHook(selData, ipmiRaw); 847 break; 848 849 case 0x33: // Check if this message is from the BIOS SMI Generator ID 850 // Let the BIOS SMI hook handle this request 851 return biosSMIMessageHook(selData, ipmiRaw); 852 break; 853 854 case 0x2C: // Message from Intel ME 855 return me::messageHook(selData, ipmiRaw); 856 break; 857 } 858 859 // No hooks handled the request, so let it go to default 860 return defaultMessageHook(ipmiRaw); 861 } 862 } // namespace redfish_hooks 863 864 bool checkRedfishHooks(uint16_t recordID, uint8_t recordType, 865 uint32_t timestamp, uint16_t generatorID, uint8_t evmRev, 866 uint8_t sensorType, uint8_t sensorNum, uint8_t eventType, 867 uint8_t eventData1, uint8_t eventData2, 868 uint8_t eventData3) 869 { 870 // Save the raw IPMI string of the request 871 std::string ipmiRaw; 872 std::array selBytes = {static_cast<uint8_t>(recordID), 873 static_cast<uint8_t>(recordID >> 8), 874 recordType, 875 static_cast<uint8_t>(timestamp), 876 static_cast<uint8_t>(timestamp >> 8), 877 static_cast<uint8_t>(timestamp >> 16), 878 static_cast<uint8_t>(timestamp >> 24), 879 static_cast<uint8_t>(generatorID), 880 static_cast<uint8_t>(generatorID >> 8), 881 evmRev, 882 sensorType, 883 sensorNum, 884 eventType, 885 eventData1, 886 eventData2, 887 eventData3}; 888 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw); 889 890 // First check that this is a system event record type since that 891 // determines the definition of the rest of the data 892 if (recordType != ipmi::sel::systemEvent) 893 { 894 // OEM record type, so let it go to the SEL 895 return redfish_hooks::defaultMessageHook(ipmiRaw); 896 } 897 898 // Extract the SEL data for the hook 899 redfish_hooks::SELData selData = {.generatorID = generatorID, 900 .sensorNum = sensorNum, 901 .eventType = eventType, 902 .offset = eventData1 & 0x0F, 903 .eventData2 = eventData2, 904 .eventData3 = eventData3}; 905 906 return redfish_hooks::startRedfishHook(selData, ipmiRaw); 907 } 908 909 bool checkRedfishHooks(uint16_t generatorID, uint8_t evmRev, uint8_t sensorType, 910 uint8_t sensorNum, uint8_t eventType, uint8_t eventData1, 911 uint8_t eventData2, uint8_t eventData3) 912 { 913 // Save the raw IPMI string of the selData 914 std::string ipmiRaw; 915 std::array selBytes = {static_cast<uint8_t>(generatorID), 916 static_cast<uint8_t>(generatorID >> 8), 917 evmRev, 918 sensorType, 919 sensorNum, 920 eventType, 921 eventData1, 922 eventData2, 923 eventData3}; 924 redfish_hooks::toHexStr(boost::beast::span<uint8_t>(selBytes), ipmiRaw); 925 926 // Extract the SEL data for the hook 927 redfish_hooks::SELData selData = {.generatorID = generatorID, 928 .sensorNum = sensorNum, 929 .eventType = eventType, 930 .offset = eventData1 & 0x0F, 931 .eventData2 = eventData2, 932 .eventData3 = eventData3}; 933 934 return redfish_hooks::startRedfishHook(selData, ipmiRaw); 935 } 936 937 } // namespace intel_oem::ipmi::sel 938