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 217 - If the AdditionalData property in the OpenBMC event log has anything in it, 218 it will be saved in a UserData section as a JSON string. 219 220- System information 221 - This section contains various pieces of system information, such as the full 222 code level and the BMC, chassis, and host state properties. 223 224## The PEL Message Registry 225 226The PEL message registry is used to create PELs from OpenBMC event logs. 227Documentation can be found [here](registry/README.md). 228 229## Callouts 230 231A callout points to a FRU, a symbolic FRU, or an isolation procedure. There can 232be from zero to ten of them in each PEL, where they are located in the SRC 233section. 234 235There are a few different ways to add callouts to a PEL. In all cases, the 236callouts will be sorted from highest to lowest priority within the PEL after 237they are added. 238 239### Passing callouts in with the AdditionalData property 240 241The PEL code can add callouts based on the values of special entries in the 242AdditionalData event log property. They are: 243 244- CALLOUT_INVENTORY_PATH 245 246 This keyword is used to call out a single FRU by passing in its D-Bus 247 inventory path. When the PEL code sees this, it will create a single FRU 248 callout, using the VPD properties (location code, FN, CCIN) from that 249 inventory item. If that item is not a FRU itself and does not have a location 250 code, it will keep searching its parents until it finds one that is. 251 252 The priority of the FRU callout will be high, unless the CALLOUT_PRIORITY 253 keyword is also present and contains a different priority in which case it 254 will be used instead. This can be useful when a maintenance procedure with a 255 high priority callout is specified for this error in the message registry and 256 the FRU callout needs to have a different priority. 257 258```ascii 259 CALLOUT_INVENTORY_PATH= 260 "/xyz/openbmc_project/inventory/system/chassis/motherboard" 261``` 262 263- CALLOUT_DEVICE_PATH with CALLOUT_ERRNO 264 265 These keywords are required as a pair to indicate faulty device communication, 266 usually detected by a failure accessing a device at that sysfs path. The PEL 267 code will use a data table generated by the MRW to map these device paths to 268 FRU callout lists. The errno value may influence the callout. 269 270 I2C, FSI, FSI-I2C, and FSI-SPI paths are supported. 271 272```ascii 273 CALLOUT_DEVICE_PATH="/sys/bus/i2c/devices/3-0069" 274 CALLOUT_ERRNO="2" 275``` 276 277- CALLOUT_IIC_BUS with CALLOUT_IIC_ADDR and CALLOUT_ERRNO 278 279 These 3 keywords can be used to callout a failing I2C device path when the 280 full device path isn't known. It is similar to CALLOUT_DEVICE_PATH in that it 281 will use data tables generated by the MRW to create the callouts. 282 283 CALLOUT_IIC_BUS is in the form "/dev/i2c-X" where X is the bus number, or just 284 the bus number by itself. CALLOUT_IIC_ADDR is the 7 bit address either as a 285 decimal or a hex number if preceded with a "0x". 286 287```ascii 288 CALLOUT_IIC_BUS="/dev/i2c-7" 289 CALLOUT_IIC_ADDR="81" 290 CALLOUT_ERRNO=62 291``` 292 293### Defining callouts in the message registry 294 295Callouts can be completely defined inside that error's definition in the PEL 296message registry. This method allows the callouts to vary based on the system 297type or on any AdditionalData item. 298 299At a high level, this involves defining a callout section inside the registry 300entry that contain the location codes or procedure names to use, along with 301their priority. If these can vary based on system type, the type provided by the 302entity manager will be one of the keys. If they can also depend on an 303AdditionalData entry, then that will also be a key. 304 305See the message registry [README](registry/README.md) and 306[schema](registry/schema/schema.json) for the details. 307 308### Using the message registry along with CALLOUT\_ entries 309 310If the message registry entry contains a callout definition and the event log 311also contains one of aforementioned CALLOUT keys in the AdditionalData property, 312then the PEL code will first add the callouts stemming from the CALLOUT items, 313followed by the callouts from the message registry. 314 315### Specifying multiple callouts using JSON format FFDC files 316 317Multiple callouts can be passed in by the creator at the time of PEL creation. 318This is done by specifying them in a JSON file that is then passed in as an 319[FFDC file](#ffdc-intended-for-userdata-pel-sections). The JSON will still be 320added into a PEL UserData section for debug. 321 322To specify that an FFDC file contains callouts, the format value for that FFDC 323entry must be set to JSON, and the subtype field must be set to 0xCA: 324 325```cpp 326using FFDC = std::tuple<CreateIface::FFDCFormat, 327 uint8_t, 328 uint8_t, 329 sdbusplus::message::unix_fd>; 330 331FFDC ffdc{ 332 CreateIface::FFDCFormat::JSON, 333 0xCA, // Callout subtype 334 0x01, // Callout version, set to 0x01 335 fd}; 336``` 337 338The JSON contains an array of callouts that must be in order of highest priority 339to lowest, with a maximum of 10. Any callouts after the 10th will just be thrown 340away as there is no room for them in the PEL. The format looks like: 341 342```jsonl 343[ 344 { 345 // First callout 346 }, 347 { 348 // Second callout 349 }, 350 { 351 // Nth callout 352 } 353] 354``` 355 356A callout entry can be a normal hardware callout, a maintenance procedure 357callout, or a symbolic FRU callout. Each callout must contain a Priority field, 358where the possible values are: 359 360- "H" = High 361- "M" = Medium 362- "A" = Medium Group A 363- "B" = Medium Group B 364- "C" = Medium Group C 365- "L" = Low 366 367Either unexpanded location codes or D-Bus inventory object paths can be used to 368specify the called out part. An unexpanded location code does not have the 369system VPD information embedded in it, and the 'Ufcs-' prefix is optional (so 370can be either Ufcs-P1 or just P1). 371 372#### Normal hardware FRU callout 373 374Normal hardware callouts must contain either the location code or inventory 375path, and priority. Even though the PEL code doesn't do any guarding or 376deconfiguring itself, it needs to know if either of those things occurred as 377there are status bits in the PEL to reflect them. The Guarded and Deconfigured 378fields are used for this. Those fields are optional and if omitted then their 379values will be false. 380 381When the inventory path of a sub-FRU is passed in, the PEL code will put the 382location code of the parent FRU into the callout. 383 384```jsonl 385{ 386 "LocationCode": "P0-C1", 387 "Priority": "H" 388} 389 390{ 391 "InventoryPath": "/xyz/openbmc_project/inventory/motherboard/cpu0/core5", 392 "Priority": "H", 393 "Deconfigured": true, 394 "Guarded": true 395} 396 397``` 398 399MRUs (Manufacturing Replaceable Units) are 4 byte numbers that can optionally be 400added to callouts to specify failing devices on a FRU. These may be used during 401the manufacturing test process, where there may be the ability to do these 402replacements. There can be up to 15 MRUs, each with its own priority, embedded 403in a callout. The possible priority values match the FRU priority values. 404 405Note that since JSON only supports numbers in decimal and not in hex, MRU IDs 406will show up as decimal when visually inspecting the JSON. 407 408```jsonl 409{ 410 "LocationCode": "P0-C1", 411 "Priority": "H", 412 "MRUs": [ 413 { 414 "ID": 1234, 415 "Priority": "H" 416 }, 417 { 418 "ID": 5678, 419 "Priority": "H" 420 } 421 ] 422} 423``` 424 425#### Maintenance procedure callout 426 427The LocationCode field is not used with procedure callouts. Only the first 7 428characters of the Procedure field will be used by the PEL. 429 430```jsonl 431{ 432 "Procedure": "PRONAME", 433 "Priority": "H" 434} 435``` 436 437#### Symbolic FRU callout 438 439Only the first seven characters of the SymbolicFRU field will be used by the 440PEL. 441 442If the TrustedLocationCode field is present and set to true, this means the 443location code may be used to turn on service indicators, so the LocationCode 444field is required. If TrustedLocationCode is false or missing, then the 445LocationCode field is optional. 446 447```jsonl 448{ 449 "TrustedLocationCode": true, 450 "Location Code": "P0-C1", 451 "Priority": "H", 452 "SymbolicFRU": "FRUNAME" 453} 454``` 455 456## `Action Flags` and `Event Type` Rules 457 458The `Action Flags` and `Event Type` PEL fields are optional in the message 459registry, and if not present the code will set them based on certain rules layed 460out in the PEL spec. 461 462These rules are: 463 4641. Always set the `Report` flag, unless the `Do Not Report` flag is already on. 4652. Always clear the `SP Call Home` flag, as that feature isn't supported. 4663. If the severity is `Non-error Event`: 467 - Clear the `Service Action` flag. 468 - Clear the `Call Home` flag. 469 - If the `Event Type` field is `Not Applicable`, change it to 470 `Information Only`. 471 - If the `Event Type` field is `Information Only` or `Tracing`, set the 472 `Hidden` flag. 4734. If the severity is `Recovered`: 474 - Set the `Hidden` flag. 475 - Clear the `Service Action` flag. 476 - Clear the `Call Home` flag. 4775. For all other severities: 478 - Clear the `Hidden` flag. 479 - Set the `Service Action` flag. 480 - Set the `Call Home` flag. 481 482Additional rules may be added in the future if necessary. 483 484## D-Bus Interfaces 485 486See the org.open_power.Logging.PEL interface definition for the most up to date 487information. 488 489## PEL Retention 490 491The PEL repository is allocated a set amount of space on the BMC. When that 492space gets close to being full, the code will remove a percentage of PELs to 493make room for new ones. In addition, the code will keep a cap on the total 494number of PELs allowed. Note that removing a PEL will also remove the 495corresponding OpenBMC event log. 496 497The disk capacity limit is set to 20MB, and the number limit is 3000. 498 499The rules used to remove logs are listed below. The checks will be run after a 500PEL has been added and the method to create the PEL has returned to the caller, 501i.e. run when control gets back to the event loop. 502 503### Removal Algorithm 504 505If the size used is 95% or under of the allocated space and under the limit on 506the number of PELs, nothing further needs to be done, otherwise continue and run 507all 5 of the following steps. Each step itself only deletes PELs until it meets 508its requirement and then it stops. 509 510The steps are: 511 5121. Remove BMC created informational PELs until they take up 15% or less of the 513 allocated space. 514 5152. Remove BMC created non-informational PELs until they take up 30% or less of 516 the allocated space. 517 5183. Remove non-BMC created informational PELs until they take up 15% or less of 519 the allocated space. 520 5214. Remove non-BMC created non-informational PELs until they take up 30% or less 522 of the allocated space. 523 5245. After the previous 4 steps are complete, if there are still more than the 525 maximum number of PELs, remove PELs down to 80% of the maximum. 526 527PELs with associated guard records will never be deleted. Each step above makes 528the following 4 passes, stopping as soon as its limit is reached: 529 530- Pass 1. Remove HMC acknowledged PELs. 531- Pass 2. Remove OS acknowledged PELs. 532- Pass 3. Remove PHYP acknowledged PELs. 533- Pass 4. Remove all PELs. 534 535After all these steps, disk capacity will be at most 90% (15% + 30% + 15% + 53630%). 537 538## Adding python3 modules for PEL UserData and SRC parsing 539 540In order to support python3 modules for the parsing of PEL User Data sections 541and to decode SRC data, setuptools is used to import python3 packages from 542external repos to be included in the OpenBMC image. 543 544Sample layout for setuptools: 545 546setup.py src/usr/scom/plugins/ebmc/b0300.py src/usr/i2c/plugins/ebmc/b0700.py 547src/build/tools/ebmc/errludP_Helpers.py 548 549`setup.py` is the build script for setuptools. It contains information about the 550package (such as the name and version) as well as which code files to include. 551 552The setup.py template to be used for eBMC User Data parsers: 553 554```python3 555import os.path 556from setuptools import setup 557 558# To update this dict with new key/value pair for every component added 559# Key: The package name to be installed as 560# Value: The path containing the package's python modules 561dirmap = { 562 "b0300": "src/usr/scom/plugins/ebmc", 563 "b0700": "src/usr/i2c/plugins/ebmc", 564 "helpers": "src/build/tools/ebmc" 565} 566 567# All packages will be installed under 'udparsers' namespace 568def get_package_name(dirmap_key): 569 return "udparsers.{}".format(dirmap_key) 570 571def get_package_dirent(dirmap_item): 572 package_name = get_package_name(dirmap_item[0]) 573 package_dir = dirmap_item[1] 574 return (package_name, package_dir) 575 576def get_packages(): 577 return map(get_package_name, dirmap.keys()) 578 579def get_package_dirs(): 580 return map(get_package_dirent, dirmap.items()) 581 582setup( 583 name="Hostboot", 584 version="0.1", 585 packages=list(get_packages()), 586 package_dir=dict(get_package_dirs()) 587) 588``` 589 590- User Data parser module 591 592 - Module name: `xzzzz.py`, where `x` is the Creator Subsystem from the Private 593 Header section (in ASCII) and `zzzz` is the 2 byte Component ID from the 594 User Data section itself (in HEX). All should be converted to lowercase. 595 - For example: `b0100.py` for Hostboot created UserData with CompID 0x0100 596 - Function to provide: `parseUDToJson` 597 598 - Argument list: 599 1. (int) Sub-section type 600 2. (int) Section version 601 3. (memoryview): Data 602 - Return data: 603 1. (str) JSON string 604 605 - Sample User Data parser module: 606 607```python3 608 import json 609 def parseUDToJson(subType, ver, data): 610 d = dict() 611 ... 612 # Parse and populate data into dictionary 613 ... 614 jsonStr = json.dumps(d) 615 return jsonStr 616``` 617 618- SRC parser module 619 620 - Module name: `xsrc.py`, where `x` is the Creator Subsystem from the Private 621 Header section (in ASCII, converted to lowercase). 622 - For example: `bsrc.py` for Hostboot generated SRCs 623 - Function to provide: `parseSRCToJson` 624 625 - Argument list: 626 1. (str) Refcode ASCII string 627 2. (str) Hexword 2 628 3. (str) Hexword 3 629 4. (str) Hexword 4 630 5. (str) Hexword 5 631 6. (str) Hexword 6 632 7. (str) Hexword 7 633 8. (str) Hexword 8 634 9. (str) Hexword 9 635 - Return data: 636 1. (str) JSON string 637 638 - Sample SRC parser module: 639 640 ```python3 641 import json 642 def parseSRCToJson(ascii_str, word2, word3, word4, word5, word6, word7, \ 643 word8, word9): 644 d = dict({'A': 1, 'B': 2}) 645 ... 646 # Decode SRC data into dictionary 647 ... 648 jsonStr = json.dumps(d) 649 return jsonStr 650 ``` 651 652## Fail Boot on Host Errors 653 654The fail boot on hw error [design][1] provides a function where a system owner 655can tell the firmware to fail the boot of a system if a BMC phosphor-logging 656event has a hardware callout in it. 657 658It is required that when this fail boot on hardware error setting is enabled, 659that the BMC fail the boot for **any** error from the host which satisfies the 660following criteria: 661 662- not SeverityType::nonError 663- has a callout of any kind from the `FailingComponentType` structure 664 665## Self Boot Engine First Failure Data Capture Support 666 667During SBE chip-op failure SBE creates FFDC with custom data format. SBE FFDC 668contains different packets, which include SBE internal failure related Trace and 669user data also Hardware procedure failure FFDC created by FAPI infrastructure. 670PEL infrastructure provides support to process SBE FFDC packets created by FAPI 671infrastructure during hardware procedure execution failures, also add callouts, 672user data section information based on FAPI processing in case non FAPI based 673failure, just keeps the raw FFDC data in the user section to support SBE parser 674plugins. 675 676CreatePELWithFFDCFiles D-Bus method on the `org.open_power.Logging.PEL` 677interface must be used when creating a new event log. 678 679To specify that an FFDC file contains SBE FFDC, the format value for that FFDC 680entry must be set to "custom", and the subtype field must be set to 0xCB: 681 682```cpp 683using FFDC = std::tuple<CreateIface::FFDCFormat, 684 uint8_t, 685 uint8_t, 686 sdbusplus::message::unix_fd>; 687 688FFDC ffdc{ 689 CreateIface::FFDCFormat::custom, 690 0xCB, // SBE FFDC subtype 691 0x01, // SBE FFDC version, set to 0x01 692 fd}; 693``` 694 695"SRC6" Keyword in the additional data section should be populated with below. 696 697- [0:15] chip position (hex) 698- [16:23] command class (hex) 699- [24:31] command (hex) 700 701e.g for GetSCOM 702 703SRC6="0002A201" 704 705Note: "phal" build-time configure option should be "enabled" to enable this 706feature. 707 708## PEL Archiving 709 710When an OpenBMC event log is deleted its corresponding PEL is moved to an 711archive folder. These archived PELs will be available in BMC dump. The archive 712path: /var/lib/phosphor-logging/extensions/pels/logs/archive. 713 714Highlighted points are: 715 716- PELs whose corresponding event logs have been deleted will be available in the 717 archive folder. 718- Archive folder size is tracked along with logs folder size and if combined 719 size exceeds warning size all archived PELs will be deleted. 720- Archived PEL logs can be viewed using peltool with flag --archive. 721- If a PEL is deleted using peltool its not archived. 722 723## Handling PELs for hot plugged FRUs 724 725The degraded mode reporting functionality (i.e. nag) implemented by IBM creates 726periodic degraded mode reports when a system is running in degraded mode. This 727includes when hardware has been deconfigured or guarded by hostboot, and also 728when there is a fault on a redundant fan, VRM, or power supply. The report 729includes the PELs created for the fails leading to the degraded mode. These PELs 730can be identified by the 'deconfig' or 'guard' flags set in the SRC of BMC or 731hostboot PELs. 732 733Fans and power supplies can be hot plugged when they are replaced, and as that 734FRU is no longer considered degraded the PELs that led to its replacement no 735longer need be picked up in the degraded mode report. 736 737To handle this, the PEL daemon will watch the inventory D-Bus objects that have 738the 'xyz.openbmc_project.Inventory.Item.Fan' or 739'xyz.openbmc_project.Inventory.Item.PowerSupply' interface. When the 'Present' 740property on the 'xyz.openbmc_project.Inventory.Item' interface on these paths 741change to true, the code will find all fan/PS PELs with the deconfig bit set and 742that location code in the callout list and clear the deconfig flag in the PEL. 743That way, when the code that does the report searches for PELs, it will no 744longer find them. 745 746[1]: 747 https://github.com/openbmc/docs/blob/master/designs/fail-boot-on-hw-error.md 748