1# OpenPower Platform Event Log (PEL) extension 2 3This extension will create PELs for every OpenBMC event log. It is also possible 4to point to the raw PEL to use in the OpenBMC event, and then that will be used 5instead of creating one. 6 7## Contents 8 9- [Passing in data when creating PELs](#passing-pel-related-data-within-an-openbmc-event-log) 10- [Default UserData sections for BMC created PELs](#default-userdata-sections-for-bmc-created-pels) 11- [The PEL Message Registry](#the-pel-message-registry) 12- [Callouts](#callouts) 13- [Action Flags and Event Type Rules](#action-flags-and-event-type-rules) 14- [D-Bus Interfaces](#d-bus-interfaces) 15- [PEL Retention](#pel-retention) 16- [Adding python3 modules for PEL UserData and SRC parsing](#adding-python3-modules-for-pel-userdata-and-src-parsing) 17- [Fail Boot on Host Errors](#fail-boot-on-host-errors) 18- [SBE FFDC](#self-boot-engine-first-failure-data-capture-support) 19- [PEL Archiving](#pel-archiving) 20- [Handling PELs for hot plugged FRUs](#handling-pels-for-hot-plugged-frus) 21 22## Passing PEL related data within an OpenBMC event log 23 24An error log creator can pass in data that is relevant to a PEL by using certain 25keywords in the AdditionalData property of the event log. 26 27### AdditionalData keywords 28 29#### RAWPEL 30 31This keyword is used to point to an existing PEL in a binary file that should be 32associated with this event log. The syntax is: 33 34```ascii 35RAWPEL=<path to PEL File> 36e.g. 37RAWPEL="/tmp/pels/pel.5" 38``` 39 40The code will assign its own error log ID to this PEL, and also update the 41commit timestamp field to the current time. 42 43#### POWER_THERMAL_CRITICAL_FAULT 44 45This keyword is used to set the power fault bit in PEL. The syntax is: 46 47```ascii 48POWER_THERMAL_CRITICAL_FAULT=<FLAG> 49e.g. 50POWER_THERMAL_CRITICAL_FAULT=TRUE 51``` 52 53Note that TRUE is the only value supported. 54 55#### SEVERITY_DETAIL 56 57This is used when the passed in event log severity determines the PEL severity 58and a more granular PEL severity is needed beyond what the normal event log to 59PEL severity conversion could give. 60 61The syntax is: 62 63```ascii 64SEVERITY_DETAIL=<SEVERITY_TYPE> 65e.g. 66SEVERITY_DETAIL=SYSTEM_TERM 67``` 68 69Option Supported: 70 71- SYSTEM_TERM, changes the Severity value from 0x50 to 0x51 72 73#### ESEL 74 75This keyword's data contains a full PEL in string format. This is how hostboot 76sends down PELs when it is configured in IPMI communication mode. The PEL is 77handled just like the PEL obtained using the RAWPEL keyword. 78 79The syntax is: 80 81```ascii 82ESEL= 83"00 00 df 00 00 00 00 20 00 04 12 01 6f aa 00 00 50 48 00 30 01 00 33 00 00..." 84``` 85 86Note that there are 16 bytes of IPMI SEL data before the PEL data starts. 87 88#### \_PID 89 90This keyword that contains the application's PID is added automatically by the 91phosphor-logging daemon when the `commit` or `report` APIs are used to create an 92event log, but not when the `Create` D-Bus method is used. If a caller of the 93`Create` API wishes to have their PID captured in the PEL this should be used. 94 95This will be added to the PEL in a section of type User Data (UD), along with 96the application name it corresponds to. 97 98The syntax is: 99 100```ascii 101_PID=<PID of application> 102e.g. 103_PID="12345" 104``` 105 106#### CALLOUT_INVENTORY_PATH 107 108This is used to pass in an inventory item to use as a callout. See 109[here for details](#passing-callouts-in-with-the-additionaldata-property) 110 111#### CALLOUT_PRIORITY 112 113This can be used along with CALLOUT_INVENTORY_PATH to specify the priority of 114that FRU callout. If not specified, the default priority is "H"/High Priority. 115 116The possible values are: 117 118- "H": High Priority 119- "M": Medium Priority 120- "L": Low Priority 121 122See [here for details](#passing-callouts-in-with-the-additionaldata-property) 123 124#### CALLOUT_DEVICE_PATH with CALLOUT_ERRNO 125 126This is used to pass in a device path to create callouts from. See 127[here for details](#passing-callouts-in-with-the-additionaldata-property) 128 129#### CALLOUT_IIC_BUS with CALLOUT_IIC_ADDR and CALLOUT_ERRNO 130 131This is used to pass in an I2C bus and address to create callouts from. See 132[here for details](#passing-callouts-in-with-the-additionaldata-property) 133 134#### PEL_SUBSYSTEM 135 136This keyword is used to pass in the subsystem that should be associated with 137this event log. The syntax is: `PEL_SUBSYSTEM=<subsystem value in hex>` e.g. 138PEL_SUBSYSTEM=0x20 139 140### FFDC Intended For UserData PEL sections 141 142When one needs to add FFDC into the PEL UserData sections, the 143`CreateWithFFDCFiles` D-Bus method on the `xyz.openbmc_project.Logging.Create` 144interface must be used when creating a new event log. This method takes a list 145of files to store in the PEL UserData sections. 146 147That API is the same as the 'Create' one, except it has a new parameter: 148 149```cpp 150std::vector<std::tuple<enum[FFDCFormat], 151 uint8_t, 152 uint8_t, 153 sdbusplus::message::unix_fd>> 154``` 155 156Each entry in the vector contains a file descriptor for a file that will be 157stored in a unique UserData section. The tuple's arguments are: 158 159- enum[FFDCFormat]: The data format type, the options are: 160 - 'JSON' 161 - The parser will use nlohmann::json\'s pretty print 162 - 'CBOR' 163 - The parser will use nlohmann::json\'s pretty print 164 - 'Text' 165 - The parser will output ASCII text 166 - 'Custom' 167 - The parser will hexdump the data, unless there is a parser registered for 168 this component ID and subtype. 169- uint8_t: subType 170 - Useful for the 'custom' type. Not used with the other types. 171- uint8_t: version 172 - The version of the data. 173 - Used for the custom type. 174 - Not planning on using for JSON/BSON unless a reason to do so appears. 175- unixfd - The file descriptor for the opened file that contains the contents. 176 The file descriptor can be closed and the file can be deleted if desired after 177 the method call. 178 179An example of saving JSON data to a file and getting its file descriptor is: 180 181```cpp 182nlohmann::json json = ...; 183auto jsonString = json.dump(); 184FILE* fp = fopen(filename, "w"); 185fwrite(jsonString.data(), 1, jsonString.size(), fp); 186int fd = fileno(fp); 187``` 188 189Alternatively, 'open()' can be used to obtain the file descriptor of the file. 190 191Upon receiving this data, the PEL code will create UserData sections for each 192entry in that vector with the following UserData fields: 193 194- Section header component ID: 195 - If the type field from the tuple is "custom", use the component ID from the 196 message registry. 197 - Otherwise, set the component ID to the phosphor-logging component ID so that 198 the parser knows to use the built in parsers (e.g. json) for the type. 199- Section header subtype: The subtype field from the tuple. 200- Section header version: The version field from the tuple. 201- Section data: The data from the file. 202 203If there is a peltool parser registered for the custom type (method is TBD), 204that will be used by peltool to print the data, otherwise it will be hexdumped. 205 206Before adding each of these UserData sections, a check will be done to see if 207the PEL size will remain under the maximum size of 16KB. If not, the UserData 208section will be truncated down enough so that it will fit into the 16KB. 209 210## Default UserData sections for BMC created PELs 211 212The extension code that creates PELs will add these UserData sections to every 213PEL: 214 215- The AdditionalData property contents 216 - If the AdditionalData property in the OpenBMC event log has anything in it, 217 it will be saved in a UserData section as a JSON string. 218 219- System information 220 - This section contains various pieces of system information, such as the full 221 code level and the BMC, chassis, and host state properties. 222 223## The PEL Message Registry 224 225The PEL message registry is used to create PELs from OpenBMC event logs. 226[Documentation](registry/README.md) is available. 227 228## Callouts 229 230A callout points to a FRU, a symbolic FRU, or an isolation procedure. There can 231be from zero to ten of them in each PEL, where they are located in the SRC 232section. 233 234There are a few different ways to add callouts to a PEL. In all cases, the 235callouts will be sorted from highest to lowest priority within the PEL after 236they are added. 237 238### Passing callouts in with the AdditionalData property 239 240The PEL code can add callouts based on the values of special entries in the 241AdditionalData event log property. They are: 242 243- CALLOUT_INVENTORY_PATH 244 245 This keyword is used to call out a single FRU by passing in its D-Bus 246 inventory path. When the PEL code sees this, it will create a single FRU 247 callout, using the VPD properties (location code, FN, CCIN) from that 248 inventory item. If that item is not a FRU itself and does not have a location 249 code, it will keep searching its parents until it finds one that is. 250 251 The priority of the FRU callout will be high, unless the CALLOUT_PRIORITY 252 keyword is also present and contains a different priority in which case it 253 will be used instead. This can be useful when a maintenance procedure with a 254 high priority callout is specified for this error in the message registry and 255 the FRU callout needs to have a different priority. 256 257```ascii 258 CALLOUT_INVENTORY_PATH= 259 "/xyz/openbmc_project/inventory/system/chassis/motherboard" 260``` 261 262- CALLOUT_DEVICE_PATH with CALLOUT_ERRNO 263 264 These keywords are required as a pair to indicate faulty device communication, 265 usually detected by a failure accessing a device at that sysfs path. The PEL 266 code will use a data table generated by the MRW to map these device paths to 267 FRU callout lists. The errno value may influence the callout. 268 269 I2C, FSI, FSI-I2C, and FSI-SPI paths are supported. 270 271```ascii 272 CALLOUT_DEVICE_PATH="/sys/bus/i2c/devices/3-0069" 273 CALLOUT_ERRNO="2" 274``` 275 276- CALLOUT_IIC_BUS with CALLOUT_IIC_ADDR and CALLOUT_ERRNO 277 278 These 3 keywords can be used to callout a failing I2C device path when the 279 full device path isn't known. It is similar to CALLOUT_DEVICE_PATH in that it 280 will use data tables generated by the MRW to create the callouts. 281 282 CALLOUT_IIC_BUS is in the form "/dev/i2c-X" where X is the bus number, or just 283 the bus number by itself. CALLOUT_IIC_ADDR is the 7 bit address either as a 284 decimal or a hex number if preceded with a "0x". 285 286```ascii 287 CALLOUT_IIC_BUS="/dev/i2c-7" 288 CALLOUT_IIC_ADDR="81" 289 CALLOUT_ERRNO=62 290``` 291 292### Defining callouts in the message registry 293 294Callouts can be completely defined inside that error's definition in the PEL 295message registry. This method allows the callouts to vary based on the system 296type or on any AdditionalData item. 297 298At a high level, this involves defining a callout section inside the registry 299entry that contain the location codes or procedure names to use, along with 300their priority. If these can vary based on system type, the type provided by the 301entity manager will be one of the keys. If they can also depend on an 302AdditionalData entry, then that will also be a key. 303 304See the message registry [README](registry/README.md) and 305[schema](registry/schema/schema.json) for the details. 306 307### Using the message registry along with CALLOUT\_ entries 308 309If the message registry entry contains a callout definition and the event log 310also contains one of aforementioned CALLOUT keys in the AdditionalData property, 311then the PEL code will first add the callouts stemming from the CALLOUT items, 312followed by the callouts from the message registry. 313 314### Specifying multiple callouts using JSON format FFDC files 315 316Multiple callouts can be passed in by the creator at the time of PEL creation. 317This is done by specifying them in a JSON file that is then passed in as an 318[FFDC file](#ffdc-intended-for-userdata-pel-sections). The JSON will still be 319added into a PEL UserData section for debug. 320 321To specify that an FFDC file contains callouts, the format value for that FFDC 322entry must be set to JSON, and the subtype field must be set to 0xCA: 323 324```cpp 325using FFDC = std::tuple<CreateIface::FFDCFormat, 326 uint8_t, 327 uint8_t, 328 sdbusplus::message::unix_fd>; 329 330FFDC ffdc{ 331 CreateIface::FFDCFormat::JSON, 332 0xCA, // Callout subtype 333 0x01, // Callout version, set to 0x01 334 fd}; 335``` 336 337The JSON contains an array of callouts that must be in order of highest priority 338to lowest, with a maximum of 10. Any callouts after the 10th will just be thrown 339away as there is no room for them in the PEL. The format looks like: 340 341```jsonl 342[ 343 { 344 // First callout 345 }, 346 { 347 // Second callout 348 }, 349 { 350 // Nth callout 351 } 352] 353``` 354 355A callout entry can be a normal hardware callout, a maintenance procedure 356callout, or a symbolic FRU callout. Each callout must contain a Priority field, 357where the possible values are: 358 359- "H" = High 360- "M" = Medium 361- "A" = Medium Group A 362- "B" = Medium Group B 363- "C" = Medium Group C 364- "L" = Low 365 366Either unexpanded location codes or D-Bus inventory object paths can be used to 367specify the called out part. An unexpanded location code does not have the 368system VPD information embedded in it, and the 'Ufcs-' prefix is optional (so 369can be either Ufcs-P1 or just P1). 370 371#### Normal hardware FRU callout 372 373Normal hardware callouts must contain either the location code or inventory 374path, and priority. Even though the PEL code doesn't do any guarding or 375deconfiguring itself, it needs to know if either of those things occurred as 376there are status bits in the PEL to reflect them. The Guarded and Deconfigured 377fields are used for this. Those fields are optional and if omitted then their 378values will be false. 379 380When the inventory path of a sub-FRU is passed in, the PEL code will put the 381location code of the parent FRU into the callout. 382 383```jsonl 384{ 385 "LocationCode": "P0-C1", 386 "Priority": "H" 387} 388 389{ 390 "InventoryPath": "/xyz/openbmc_project/inventory/motherboard/cpu0/core5", 391 "Priority": "H", 392 "Deconfigured": true, 393 "Guarded": true 394} 395 396``` 397 398MRUs (Manufacturing Replaceable Units) are 4 byte numbers that can optionally be 399added to callouts to specify failing devices on a FRU. These may be used during 400the manufacturing test process, where there may be the ability to do these 401replacements. There can be up to 15 MRUs, each with its own priority, embedded 402in a callout. The possible priority values match the FRU priority values. 403 404Note that since JSON only supports numbers in decimal and not in hex, MRU IDs 405will show up as decimal when visually inspecting the JSON. 406 407```jsonl 408{ 409 "LocationCode": "P0-C1", 410 "Priority": "H", 411 "MRUs": [ 412 { 413 "ID": 1234, 414 "Priority": "H" 415 }, 416 { 417 "ID": 5678, 418 "Priority": "H" 419 } 420 ] 421} 422``` 423 424#### Maintenance procedure callout 425 426The LocationCode field is not used with procedure callouts. Only the first 7 427characters of the Procedure field will be used by the PEL. 428 429```jsonl 430{ 431 "Procedure": "PRONAME", 432 "Priority": "H" 433} 434``` 435 436#### Symbolic FRU callout 437 438Only the first seven characters of the SymbolicFRU field will be used by the 439PEL. 440 441If the TrustedLocationCode field is present and set to true, this means the 442location code may be used to turn on service indicators, so the LocationCode 443field is required. If TrustedLocationCode is false or missing, then the 444LocationCode field is optional. 445 446```jsonl 447{ 448 "TrustedLocationCode": true, 449 "Location Code": "P0-C1", 450 "Priority": "H", 451 "SymbolicFRU": "FRUNAME" 452} 453``` 454 455## `Action Flags` and `Event Type` Rules 456 457The `Action Flags` and `Event Type` PEL fields are optional in the message 458registry, and if not present the code will set them based on certain rules layed 459out in the PEL spec. 460 461These rules are: 462 4631. Always set the `Report` flag, unless the `Do Not Report` flag is already on. 4642. Always clear the `SP Call Home` flag, as that feature isn't supported. 4653. If the severity is `Non-error Event`: 466 - Clear the `Service Action` flag. 467 - Clear the `Call Home` flag. 468 - If the `Event Type` field is `Not Applicable`, change it to 469 `Information Only`. 470 - If the `Event Type` field is `Information Only` or `Tracing`, set the 471 `Hidden` flag. 4724. If the severity is `Recovered`: 473 - Set the `Hidden` flag. 474 - Clear the `Service Action` flag. 475 - Clear the `Call Home` flag. 4765. For all other severities: 477 - Clear the `Hidden` flag. 478 - Set the `Service Action` flag. 479 - Set the `Call Home` flag. 480 481Additional rules may be added in the future if necessary. 482 483## D-Bus Interfaces 484 485See the org.open_power.Logging.PEL interface definition for the most up to date 486information. 487 488## PEL Retention 489 490The PEL repository is allocated a set amount of space on the BMC. When that 491space gets close to being full, the code will remove a percentage of PELs to 492make room for new ones. In addition, the code will keep a cap on the total 493number of PELs allowed. Note that removing a PEL will also remove the 494corresponding OpenBMC event log. 495 496The disk capacity limit is set to 20MB, and the number limit is 3000. 497 498The rules used to remove logs are listed below. The checks will be run after a 499PEL has been added and the method to create the PEL has returned to the caller, 500i.e. run when control gets back to the event loop. 501 502### Removal Algorithm 503 504If the size used is 95% or under of the allocated space and under the limit on 505the number of PELs, nothing further needs to be done, otherwise continue and run 506all 5 of the following steps. Each step itself only deletes PELs until it meets 507its requirement and then it stops. 508 509The steps are: 510 5111. Remove BMC created informational PELs until they take up 15% or less of the 512 allocated space. 513 5142. Remove BMC created non-informational PELs until they take up 30% or less of 515 the allocated space. 516 5173. Remove non-BMC created informational PELs until they take up 15% or less of 518 the allocated space. 519 5204. Remove non-BMC created non-informational PELs until they take up 30% or less 521 of the allocated space. 522 5235. After the previous 4 steps are complete, if there are still more than the 524 maximum number of PELs, remove PELs down to 80% of the maximum. 525 526PELs with associated guard records will never be deleted. Each step above makes 527the following 4 passes, stopping as soon as its limit is reached: 528 529- Pass 1. Remove HMC acknowledged PELs. 530- Pass 2. Remove OS acknowledged PELs. 531- Pass 3. Remove PHYP acknowledged PELs. 532- Pass 4. Remove all PELs. 533 534After all these steps, disk capacity will be at most 90% (15% + 30% + 15% + 53530%). 536 537## Adding python3 modules for PEL UserData and SRC parsing 538 539In order to support python3 modules for the parsing of PEL User Data sections 540and to decode SRC data, setuptools is used to import python3 packages from 541external repos to be included in the OpenBMC image. 542 543Sample layout for setuptools: 544 545setup.py src/usr/scom/plugins/ebmc/b0300.py src/usr/i2c/plugins/ebmc/b0700.py 546src/build/tools/ebmc/errludP_Helpers.py 547 548`setup.py` is the build script for setuptools. It contains information about the 549package (such as the name and version) as well as which code files to include. 550 551The setup.py template to be used for eBMC User Data parsers: 552 553```python3 554import os.path 555from setuptools import setup 556 557# To update this dict with new key/value pair for every component added 558# Key: The package name to be installed as 559# Value: The path containing the package's python modules 560dirmap = { 561 "b0300": "src/usr/scom/plugins/ebmc", 562 "b0700": "src/usr/i2c/plugins/ebmc", 563 "helpers": "src/build/tools/ebmc" 564} 565 566# All packages will be installed under 'udparsers' namespace 567def get_package_name(dirmap_key): 568 return "udparsers.{}".format(dirmap_key) 569 570def get_package_dirent(dirmap_item): 571 package_name = get_package_name(dirmap_item[0]) 572 package_dir = dirmap_item[1] 573 return (package_name, package_dir) 574 575def get_packages(): 576 return map(get_package_name, dirmap.keys()) 577 578def get_package_dirs(): 579 return map(get_package_dirent, dirmap.items()) 580 581setup( 582 name="Hostboot", 583 version="0.1", 584 packages=list(get_packages()), 585 package_dir=dict(get_package_dirs()) 586) 587``` 588 589- User Data parser module 590 - Module name: `xzzzz.py`, where `x` is the Creator Subsystem from the Private 591 Header section (in ASCII) and `zzzz` is the 2 byte Component ID from the 592 User Data section itself (in HEX). All should be converted to lowercase. 593 - For example: `b0100.py` for Hostboot created UserData with CompID 0x0100 594 - Function to provide: `parseUDToJson` 595 - Argument list: 596 1. (int) Sub-section type 597 2. (int) Section version 598 3. (memoryview): Data 599 - Return data: 600 1. (str) JSON string 601 602 - Sample User Data parser module: 603 604```python3 605 import json 606 def parseUDToJson(subType, ver, data): 607 d = dict() 608 ... 609 # Parse and populate data into dictionary 610 ... 611 jsonStr = json.dumps(d) 612 return jsonStr 613``` 614 615- SRC parser module 616 - Module name: `xsrc.py`, where `x` is the Creator Subsystem from the Private 617 Header section (in ASCII, converted to lowercase). 618 - For example: `bsrc.py` for Hostboot generated SRCs 619 - Function to provide: `parseSRCToJson` 620 - Argument list: 621 1. (str) Refcode ASCII string 622 2. (str) Hexword 2 623 3. (str) Hexword 3 624 4. (str) Hexword 4 625 5. (str) Hexword 5 626 6. (str) Hexword 6 627 7. (str) Hexword 7 628 8. (str) Hexword 8 629 9. (str) Hexword 9 630 - Return data: 631 1. (str) JSON string 632 633 - Sample SRC parser module: 634 635 ```python3 636 import json 637 def parseSRCToJson(ascii_str, word2, word3, word4, word5, word6, word7, \ 638 word8, word9): 639 d = dict({'A': 1, 'B': 2}) 640 ... 641 # Decode SRC data into dictionary 642 ... 643 jsonStr = json.dumps(d) 644 return jsonStr 645 ``` 646 647## Fail Boot on Host Errors 648 649The fail boot on hw error [design][1] provides a function where a system owner 650can tell the firmware to fail the boot of a system if a BMC phosphor-logging 651event has a hardware callout in it. 652 653It is required that when this fail boot on hardware error setting is enabled, 654that the BMC fail the boot for **any** error from the host which satisfies the 655following criteria: 656 657- not SeverityType::nonError 658- has a callout of any kind from the `FailingComponentType` structure 659 660## Self Boot Engine First Failure Data Capture Support 661 662During SBE chip-op failure SBE creates FFDC with custom data format. SBE FFDC 663contains different packets, which include SBE internal failure related Trace and 664user data also Hardware procedure failure FFDC created by FAPI infrastructure. 665PEL infrastructure provides support to process SBE FFDC packets created by FAPI 666infrastructure during hardware procedure execution failures, also add callouts, 667user data section information based on FAPI processing in case non FAPI based 668failure, just keeps the raw FFDC data in the user section to support SBE parser 669plugins. 670 671CreatePELWithFFDCFiles D-Bus method on the `org.open_power.Logging.PEL` 672interface must be used when creating a new event log. 673 674To specify that an FFDC file contains SBE FFDC, the format value for that FFDC 675entry must be set to "custom", and the subtype field must be set to 0xCB: 676 677```cpp 678using FFDC = std::tuple<CreateIface::FFDCFormat, 679 uint8_t, 680 uint8_t, 681 sdbusplus::message::unix_fd>; 682 683FFDC ffdc{ 684 CreateIface::FFDCFormat::custom, 685 0xCB, // SBE FFDC subtype 686 0x01, // SBE FFDC version, set to 0x01 687 fd}; 688``` 689 690"SRC6" Keyword in the additional data section should be populated with below. 691 692- [0:15] chip position (hex) 693- [16:23] command class (hex) 694- [24:31] command (hex) 695 696e.g for GetSCOM 697 698SRC6="0002A201" 699 700Note: "phal" build-time configure option should be "enabled" to enable this 701feature. 702 703## PEL Archiving 704 705When an OpenBMC event log is deleted its corresponding PEL is moved to an 706archive folder. These archived PELs will be available in BMC dump. The archive 707path: /var/lib/phosphor-logging/extensions/pels/logs/archive. 708 709Highlighted points are: 710 711- PELs whose corresponding event logs have been deleted will be available in the 712 archive folder. 713- Archive folder size is tracked along with logs folder size and if combined 714 size exceeds warning size all archived PELs will be deleted. 715- Archived PEL logs can be viewed using peltool with flag --archive. 716- If a PEL is deleted using peltool its not archived. 717 718## Handling PELs for hot plugged FRUs 719 720The degraded mode reporting functionality (i.e. nag) implemented by IBM creates 721periodic degraded mode reports when a system is running in degraded mode. This 722includes when hardware has been deconfigured or guarded by hostboot, and also 723when there is a fault on a redundant fan, VRM, or power supply. The report 724includes the PELs created for the fails leading to the degraded mode. These PELs 725can be identified by the 'deconfig' or 'guard' flags set in the SRC of BMC or 726hostboot PELs. 727 728Fans and power supplies can be hot plugged when they are replaced, and as that 729FRU is no longer considered degraded the PELs that led to its replacement no 730longer need be picked up in the degraded mode report. 731 732To handle this, the PEL daemon will watch the inventory D-Bus objects that have 733the 'xyz.openbmc_project.Inventory.Item.Fan' or 734'xyz.openbmc_project.Inventory.Item.PowerSupply' interface. When the 'Present' 735property on the 'xyz.openbmc_project.Inventory.Item' interface on these paths 736change to true, the code will find all fan/PS PELs with the deconfig bit set and 737that location code in the callout list and clear the deconfig flag in the PEL. 738That way, when the code that does the report searches for PELs, it will no 739longer find them. 740 741[1]: 742 https://github.com/openbmc/docs/blob/master/designs/fail-boot-on-hw-error.md 743