1# phosphor-logging 2 3The phosphor logging repository provides mechanisms for event and journal 4logging. 5 6## Table Of Contents 7 8- [Building](#to-build) 9- [Structured Logging](#structured-logging) 10- [Event Logs](#event-logs) 11- [Application Specific Error YAML](#adding-application-specific-error-yaml) 12- [Event Log Extensions](#event-log-extensions) 13- [Remote Logging](#remote-logging-via-rsyslog) 14- [Boot Fail on Hardware Errors](#boot-fail-on-hardware-errors) 15 16## To Build 17 18To build this package, do the following steps: 19 201. meson builddir 212. ninja -c builddir 22 23## Structured Logging 24 25phosphor-logging provides APIs to add program logging information to the 26systemd-journal and it is preferred that this logging data is formatted in a 27structured manner (using the facilities provided by the APIs). 28 29See [Structured Logging](./docs/structured-logging.md) for more details on this 30API. 31 32## Event Logs 33 34OpenBMC event logs are a collection of D-Bus interfaces owned by 35phosphor-log-manager that reside at `/xyz/openbmc_project/logging/entry/X`, 36where X starts at 1 and is incremented for each new log. 37 38The interfaces are: 39 40- [xyz.openbmc_project.Logging.Entry] 41 - The main event log interface. 42- [xyz.openbmc_project.Association.Definitions] 43 - Used for specifying inventory items as the cause of the event. 44 - For more information on associations, see [here][associations-doc]. 45- [xyz.openbmc_project.Object.Delete] 46 - Provides a Delete method to delete the event. 47- [xyz.openbmc_project.Software.Version] 48 - Stores the code version that the error occurred on. 49 50On platforms that make use of these event logs, the intent is that they are the 51common event log representation that other types of event logs can be created 52from. For example, there is code to convert these into both Redfish and IPMI 53event logs, in addition to the event log extensions mentioned 54[below](#event-log-extensions). 55 56The logging daemon has the ability to add `callout` associations to an event log 57based on text in the AdditionalData property. A callout is a link to the 58inventory item(s) that were the cause of the event log. See [here][callout-doc] 59for details. 60 61### Creating Event Logs In Code 62 63The preferred method for creating event logs is specified in the project-level 64[event log design][event-log-design]. Events are defined using YAML in the 65phosphor-dbus-interfaces repository, such as the 66[Logging.Cleared][logging-cleared] event, which will generate a C++ class for 67the event. Then a call to `lg2::commit` is made on a constructed event to add it 68to the event log. 69 70```cpp 71lg2::commit(sdbusplus::event::xyz::openbmc_project::Logging::Cleared( 72 "NUMBER_OF_LOGS", count)); 73``` 74 75There are two other, but now deprecated, methods to creating event logs in 76OpenBMC code. The first makes use of the systemd journal to store metadata 77needed for the log, and the second is a plain D-Bus method call. 78 79[event-log-design]: 80 https://github.com/openbmc/docs/blob/master/designs/event-logging.md#phosphor-logging 81[logging-cleared]: 82 https://github.com/openbmc/phosphor-dbus-interfaces/blob/6a8507d06e172d8d29c0459f0a0d078553d2ecc7/yaml/xyz/openbmc_project/Logging.events.yaml#L4 83 84#### Journal Based Event Log Creation [deprecated] 85 86Event logs can be created by using phosphor-logging APIs to commit sdbusplus 87exceptions. These APIs write to the journal, and then call a `Commit` D-Bus 88method on the logging daemon to create the event log using the information it 89put in the journal. 90 91The APIs are found in `<phosphor-logging/elog.hpp>`: 92 93- `elog()`: Throw an sdbusplus error. 94- `commit()`: Catch an error thrown by elog(), and commit it to create the event 95 log. 96- `report()`: Create an event log from an sdbusplus error without throwing the 97 exception first. 98 99Any errors passed into these APIs must be known to phosphor-logging, usually by 100being defined in `<phosphor-logging/elog-errors.hpp>`. The errors must also be 101known by sdbusplus, and be defined in their corresponding error.hpp. See below 102for details on how get errors into these headers. 103 104Example: 105 106```cpp 107#include <phosphor-logging/elog-errors.hpp> 108#include <phosphor-logging/elog.hpp> 109#include <xyz/openbmc_project/Common/error.hpp> 110... 111using InternalFailure = 112 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 113... 114if (somethingBadHappened) 115{ 116 phosphor::logging::report<InternalFailure>(); 117} 118 119``` 120 121Alternatively, to throw, catch, and then commit the error: 122 123```cpp 124try 125{ 126 phosphor::logging::elog<InternalFailure>(); 127} 128catch (InternalFailure& e) 129{ 130 phosphor::logging::commit<InternalFailure>(); 131} 132``` 133 134Metadata can be added to event logs to add debug data captured at the time of 135the event. It shows up in the AdditionalData property in the 136`xyz.openbmc_project.Logging.Entry` interface. Metadata is passed in via the 137`elog()` or `report()` functions, which write it to the journal. The metadata 138must be predefined for the error in the [metadata YAML](#event-log-definition) 139so that the daemon knows to look for it in the journal when it creates the event 140log. 141 142Example: 143 144```cpp 145#include <phosphor-logging/elog-errors.hpp> 146#include <phosphor-logging/elog.hpp> 147#include <xyz/openbmc_project/Control/Device/error.hpp> 148... 149using WriteFailure = 150 sdbusplus::xyz::openbmc_project::Control::Device::Error::WriteFailure; 151using metadata = 152 xyz::openbmc_project::Control::Device::WriteFailure; 153... 154if (somethingBadHappened) 155{ 156 phosphor::logging::report<WriteFailure>(metadata::CALLOUT_ERRNO(5), 157 metadata::CALLOUT_DEVICE_PATH("some path")); 158} 159``` 160 161In the above example, the AdditionalData property would look like: 162 163```cpp 164["CALLOUT_ERRNO=5", "CALLOUT_DEVICE_PATH=some path"] 165``` 166 167Note that the metadata fields must be all uppercase. 168 169##### Event Log Definition [deprecated] 170 171As mentioned above, both sdbusplus and phosphor-logging must know about the 172event logs in their header files, or the code that uses them will not even 173compile. The standard way to do this to define the event in the appropriate 174`<error-category>.errors.yaml` file, and define any metadata in the 175`<error-category>.metadata.yaml` file in the appropriate `*-dbus-interfaces` 176repository. During the build, phosphor-logging generates the elog-errors.hpp 177file for use by the calling code. 178 179In much the same way, sdbusplus uses the event log definitions to generate an 180error.hpp file that contains the specific exception. The path of the error.hpp 181matches the path of the YAML file. 182 183For example, if in phosphor-dbus-interfaces there is 184`xyz/openbmc_project/Control/Device.errors.yaml`, the errors that come from that 185file will be in the include: `xyz/openbmc_project/Control/Device/error.hpp`. 186 187In rare cases, one may want one to define their errors in the same repository 188that uses them. To do that, one must: 189 1901. Add the error and metadata YAML files to the repository. 1912. Run the sdbus++ script within the makefile to create the error.hpp and .cpp 192 files from the local YAML, and include the error.cpp file in the application 193 that uses it. See [openpower-occ-control] for an example. 1943. Tell phosphor-logging about the error. This is done by either: 195 - Following the [directions](#adding-application-specific-error-yaml) defined 196 in this README, or 197 - Running the script yourself: 198 1. Run phosphor-logging\'s `elog-gen.py` script on the local yaml to generate 199 an elog-errors.hpp file that just contains the local errors, and check 200 that into the repository and include it where the errors are needed. 201 2. Create a recipe that copies the local YAML files to a place that 202 phosphor-logging can find it during the build. See [here][led-link] for an 203 example. 204 205#### D-Bus Event Log Creation [deprecated] 206 207There is also a [D-Bus method][log-create-link] to create event logs: 208 209- Service: xyz.openbmc_project.Logging 210- Object Path: /xyz/openbmc_project/logging 211- Interface: xyz.openbmc_project.Logging.Create 212- Method: Create 213 - Method Arguments: 214 - Message: The `Message` string property for the 215 `xyz.openbmc_project.Logging.Entry` interface. 216 - Severity: The `severity` property for the 217 `xyz.openbmc_project.Logging.Entry` interface. An 218 `xyz.openbmc_project.Logging.Entry.Level` enum value. 219 - AdditionalData: The `AdditionalData` property for the 220 `xyz.openbmc_project.Logging.Entry` interface, but in a map instead of in 221 a vector of "KEY=VALUE" strings. Example: 222 223```cpp 224 std::map<std::string, std::string> additionalData; 225 additionalData["KEY"] = "VALUE"; 226``` 227 228Unlike the previous APIs where errors could also act as exceptions that could be 229thrown across D-Bus, this API does not require that the error be defined in the 230error YAML in the D-Bus interfaces repository so that sdbusplus knows about it. 231Additionally, as this method passes in everything needed to create the event 232log, the logging daemon doesn't have to know about it ahead of time either. 233 234That being said, it is recommended that users of this API still follow some 235guidelines for the message field, which is normally generated from a combination 236of the path to the error YAML file and the error name itself. For example, the 237`Timeout` error in `xyz/openbmc_project/Common.errors.yaml` will have a Message 238property of `xyz.openbmc_project.Common.Error.Timeout`. 239 240The guidelines are: 241 2421. When it makes sense, one can still use an existing error that has already 243 been defined in an error YAML file, and use the same severity and metadata 244 (AdditionalData) as in the corresponding metadata YAML file. 245 2462. If creating a new error, use the same naming scheme as other errors, which 247 starts with the domain, `xyz.openbmc_project`, `org.open_power`, etc, 248 followed by the capitalized category values, followed by `Error`, followed by 249 the capitalized error name itself, with everything separated by "."s. For 250 example: `xyz.openbmc_project.Some.Category.Error.Name`. 251 2523. If creating a new common error, still add it to the appropriate error and 253 metadata YAML files in the appropriate D-Bus interfaces repository so that 254 others can know about it and use it in the future. This can be done after the 255 fact. 256 257[xyz.openbmc_project.logging.entry]: 258 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Logging/Entry.interface.yaml 259[xyz.openbmc_project.association.definitions]: 260 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Association/Definitions.interface.yaml 261[associations-doc]: 262 https://github.com/openbmc/docs/blob/master/architecture/object-mapper.md#associations 263[callout-doc]: 264 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Common/Callout/README.md 265[xyz.openbmc_project.object.delete]: 266 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Object/Delete.interface.yaml 267[xyz.openbmc_project.software.version]: 268 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Software/Version.errors.yaml 269[openpower-occ-control]: https://github.com/openbmc/openpower-occ-control 270[led-link]: 271 https://github.com/openbmc/openbmc/tree/master/meta-phosphor/recipes-phosphor/leds 272[log-create-link]: 273 https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Logging/Create.interface.yaml 274 275## Adding application specific error YAML 276 277- This document captures steps for adding application specific error YAML files 278 and generating local elog-errors.hpp header file for application use. 279- Should cater for continuous integration (CI) build, bitbake image build, and 280 local repository build. 281 282### Continuous Integration (CI) build 283 284- Make is called on the repository that is modified. 285- Dependent packages are pulled based on the dependency list specified in the 286 configure.ac script. 287 288#### Recipe build 289 290- Native recipes copy error YAML files to shared location. 291- phosphor-logging builds elog-errors.hpp by parsing the error YAML files from 292 the shared location. 293 294#### Local repository build 295 296- Copies local error YAML files to the shared location in SDK 297- Make generates elog-errors.hpp by parsing the error YAML files from the shared 298 location. 299 300#### Makefile changes 301 302[Reference](https://github.com/openbmc/openpower-debug-collector/blob/master/Makefile.am) 303 304##### Export error YAML to shared location 305 306##### Modify Makefile.am to export newly added error YAML to shared location 307 308```make 309yamldir = ${datadir}/phosphor-dbus-yaml/yaml 310nobase_yaml_DATA = \ 311 org/open_power/Host.errors.yaml 312``` 313 314###### Generate elog-errors.hpp using elog parser from SDK location 315 316- Add a conditional check "GEN_ERRORS" 317- Disable the check for recipe bitbake image build 318- Enable it for local repository build 319- If "GEN_ERRORS" is enabled, build generates elog-errors.hpp header file. 320 321```make 322 # Generate phosphor-logging/elog-errors.hpp 323 if GEN_ERRORS 324 ELOG_MAKO ?= elog-gen-template.mako.hpp 325 ELOG_DIR ?= ${OECORE_NATIVE_SYSROOT}${datadir}/phosphor-logging/elog 326 ELOG_GEN_DIR ?= ${ELOG_DIR}/tools/ 327 ELOG_MAKO_DIR ?= ${ELOG_DIR}/tools/phosphor-logging/templates/ 328 YAML_DIR ?= ${OECORE_NATIVE_SYSROOT}${datadir}/phosphor-dbus-yaml/yaml 329 phosphor-logging/elog-errors.hpp: 330 @mkdir -p ${YAML_DIR}/org/open_power/ 331 @cp ${top_srcdir}/org/open_power/Host.errors.yaml \ 332 ${YAML_DIR}/org/open_power/Host.errors.yaml 333 @mkdir -p `dirname $@` 334 @chmod 777 $(ELOG_GEN_DIR)/elog-gen.py 335 $(AM_V_at)$(PYTHON) $(ELOG_GEN_DIR)/elog-gen.py -y ${YAML_DIR} \ 336 -t ${ELOG_MAKO_DIR} -m ${ELOG_MAKO} -o $@ 337 endif 338``` 339 340###### Update BUILT_SOURCES 341 342- Append elog-errors.hpp to BUILT_SOURCES list and put it in conditional check 343 GEN_ERRORS so that the elog-errors.hpp is generated only during local 344 repository build. 345 346```make 347 if GEN_ERRORS 348 nobase_nodist_include_HEADERS += \ 349 phosphor-logging/elog-errors.hpp 350 endif 351 if GEN_ERRORS 352 BUILT_SOURCES += phosphor-logging/elog-errors.hpp 353 endif 354``` 355 356###### Conditional check for native build 357 358- As the same Makefile is used both for recipe image build and native recipe 359 build, add a conditional to ensure that only installation of error yaml files 360 happens during native build. It is not required to build repository during 361 native build. 362 363```make 364 if !INSTALL_ERROR_YAML 365 endif 366``` 367 368#### Autotools changes 369 370[Reference](https://github.com/openbmc/openpower-debug-collector/blob/master/configure.ac) 371 372##### Add option(argument) to enable/disable installing error yaml file 373 374- Install error yaml option(argument) is enabled for native recipe build and 375 disabled for bitbake build. 376 377- When install error yaml option is disabled do not check for target specific 378 packages in autotools configure script. 379 380###### Add option(argument) to install error yaml files 381 382```autoconf 383AC_ARG_ENABLE([install_error_yaml], 384 AS_HELP_STRING([--enable-install_error_yaml], 385 [Enable installing error yaml file]),[], [install_error_yaml=no]) 386AM_CONDITIONAL([INSTALL_ERROR_YAML], 387 [test "x$enable_install_error_yaml" = "xyes"]) 388AS_IF([test "x$enable_install_error_yaml" != "xyes"], [ 389.. 390.. 391]) 392``` 393 394###### Add option(argument) to enable/disable generating elog-errors header file 395 396```autoconf 397AC_ARG_ENABLE([gen_errors], 398 AS_HELP_STRING([--enable-gen_errors], [Enable elog-errors.hpp generation ]), 399 [],[gen_errors=yes]) 400AM_CONDITIONAL([GEN_ERRORS], [test "x$enable_gen_errors" != "xno"]) 401``` 402 403#### Recipe changes 404 405[Reference](https://github.com/openbmc/openbmc/blob/master/meta-openbmc-machines/meta-openpower/common/recipes-phosphor/debug/openpower-debug-collector.bb) 406 407##### Extend recipe for native and nativesdk 408 409- Extend the recipe for native and native SDK builds 410 411```BitBake 412BBCLASSEXTEND += "native nativesdk" 413``` 414 415###### Remove dependencies for native and native SDK build 416 417- Native recipe caters only for copying error yaml files to shared location. 418- For native and native SDK build remove dependency on packages that recipe 419 build depends 420 421###### Remove dependency on phosphor-logging for native build 422 423```BitBake 424DEPENDS_remove_class-native = "phosphor-logging" 425``` 426 427###### Remove dependency on phosphor-logging for native SDK build 428 429```BitBake 430DEPENDS_remove_class-nativesdk = "phosphor-logging" 431``` 432 433###### Add install_error_yaml argument during native build 434 435- Add package config to enable/disable install_error_yaml feature. 436 437###### Add package config to enable/disable install_error_yaml feature 438 439```BitBake 440PACKAGECONFIG ??= "install_error_yaml" 441PACKAGECONFIG[install_error_yaml] = " \ 442 --enable-install_error_yaml, \ 443 --disable-install_error_yaml, ,\ 444 " 445``` 446 447###### Enable install_error_yaml check for native build 448 449```BitBake 450PACKAGECONFIG_add_class-native = "install_error_yaml" 451PACKAGECONFIG_add_class-nativesdk = "install_error_yaml" 452``` 453 454###### Disable install_error_yaml during target build 455 456```BitBake 457PACKAGECONFIG_remove_class-target = "install_error_yaml" 458``` 459 460###### Disable generating elog-errors.hpp for bitbake build 461 462- Disable gen_errors argument for bitbake image build as the application uses 463 the elog-errors.hpp generated by phosphor-logging 464- Argument is enabled by default for local repository build in the configure 465 script of the local repository. 466 467```BitBake 468 XTRA_OECONF += "--disable-gen_errors" 469``` 470 471#### Local build 472 473- During local build use --prefix=/usr for the configure script. 474 475[Reference](https://github.com/openbmc/openpower-debug-collector/blob/master/README.md) 476 477## Event Log Extensions 478 479The extension concept is a way to allow code that creates other formats of error 480logs besides phosphor-logging's event logs to still reside in the 481phosphor-log-manager application. 482 483The extension code lives in the `extensions/<extension>` subdirectories, and is 484enabled with a `--enable-<extension>` configure flag. The extension code won't 485compile unless enabled with this flag. 486 487Extensions can register themselves to have functions called at the following 488points using the REGISTER_EXTENSION_FUNCTION macro. 489 490- On startup 491 - Function type void(internal::Manager&) 492- After an event log is created 493 - Function type void(args) 494 - The args are: 495 - const std::string& - The Message property 496 - uin32_t - The event log ID 497 - uint64_t - The event log timestamp 498 - Level - The event level 499 - const AdditionalDataArg& - the additional data 500 - const AssociationEndpointsArg& - Association endpoints (callouts) 501- Before an event log is deleted, to check if it is allowed. 502 - Function type void(std::uint32_t, bool&) that takes the event ID 503- After an event log is deleted 504 - Function type void(std::uint32_t) that takes the event ID 505 506Using these callback points, they can create their own event log for each 507OpenBMC event log that is created, and delete these logs when the corresponding 508OpenBMC event log is deleted. 509 510In addition, an extension has the option of disabling phosphor-logging's default 511error log capping policy so that it can use its own. The macro 512DISABLE_LOG_ENTRY_CAPS() is used for that. 513 514### Motivation 515 516The reason for adding support for extensions inside the phosphor-log-manager 517daemon as opposed to just creating new daemons that listen for D-Bus signals is 518to allow interactions that would be complicated or expensive if just done over 519D-Bus, such as: 520 521- Allowing for custom old log retention algorithms. 522- Prohibiting manual deleting of certain logs based on an extension's 523 requirements. 524 525### Creating extensions 526 5271. Add a new flag to configure.ac to enable the extension: 528 529 ```autoconf 530 AC_ARG_ENABLE([foo-extension], 531 AS_HELP_STRING([--enable-foo-extension], 532 [Create Foo logs])) 533 AM_CONDITIONAL([ENABLE_FOO_EXTENSION], 534 [test "x$enable_foo_extension" == "xyes"]) 535 ``` 536 5372. Add the code in `extensions/<extension>/`. 5383. Create a makefile include to add the new code to phosphor-log-manager: 539 540 ```make 541 phosphor_log_manager_SOURCES += \ 542 extensions/foo/foo.cpp 543 ``` 544 5454. In `extensions/extensions.mk`, add the makefile include: 546 547 ```make 548 if ENABLE_FOO_EXTENSION 549 include extensions/foo/foo.mk 550 endif 551 ``` 552 5535. In the extension code, register the functions to call and optionally disable 554 log capping using the provided macros: 555 556 ```cpp 557 DISABLE_LOG_ENTRY_CAPS(); 558 559 void fooStartup(internal::Manager& manager) 560 { 561 // Initialize 562 } 563 564 REGISTER_EXTENSION_FUNCTION(fooStartup); 565 566 void fooCreate(const std::string& message, uint32_t id, uint64_t timestamp, 567 Entry::Level severity, const AdditionalDataArg& additionalData, 568 const AssociationEndpointsArg& assocs) 569 { 570 // Create a different type of error log based on 'entry'. 571 } 572 573 REGISTER_EXTENSION_FUNCTION(fooCreate); 574 575 void fooRemove(uint32_t id) 576 { 577 // Delete the extension error log that corresponds to 'id'. 578 } 579 580 REGISTER_EXTENSION_FUNCTION(fooRemove); 581 ``` 582 583### Extension List 584 585The supported extensions are: 586 587- OpenPower PELs 588 - Enabled with --enable-openpower-pel-extension 589 - Detailed information can be found 590 [here](extensions/openpower-pels/README.md) 591 592## Remote Logging via Rsyslog 593 594The BMC has the ability to stream out local logs (that go to the systemd 595journal) via rsyslog (<https://www.rsyslog.com/>). 596 597The BMC will send everything. Any kind of filtering and appropriate storage will 598have to be managed on the rsyslog server. Various examples are available on the 599internet. Here are few pointers : 600<https://www.rsyslog.com/storing-and-forwarding-remote-messages/> 601<https://www.rsyslog.com/doc/rsyslog%255Fconf%255Ffilter.html> 602<https://www.thegeekdiary.com/understanding-rsyslog-filter-options/> 603 604### Configuring rsyslog server for remote logging 605 606The BMC is an rsyslog client. To stream out logs, it needs to talk to an rsyslog 607server, to which there's connectivity over a network. REST API can be used to 608set the remote server's IP address and port number. 609 610The following presumes a user has logged on to the BMC (see 611<https://github.com/openbmc/docs/blob/master/rest-api.md>). 612 613Set the IP: 614 615```sh 616curl -b cjar -k -H "Content-Type: application/json" -X PUT \ 617 -d '{"data": <IP address>}' \ 618 https://<BMC IP address>/xyz/openbmc_project/logging/config/remote/attr/Address 619``` 620 621Set the port: 622 623```sh 624curl -b cjar -k -H "Content-Type: application/json" -X PUT \ 625 -d '{"data": <port number>}' \ 626 https://<BMC IP address>/xyz/openbmc_project/logging/config/remote/attr/Port 627``` 628 629#### Querying the current configuration 630 631```sh 632curl -b cjar -k \ 633 https://<BMC IP address>/xyz/openbmc_project/logging/config/remote 634``` 635 636#### Setting the hostname 637 638Rsyslog can store logs separately for each host. For this reason, it's useful to 639provide a unique hostname to each managed BMC. Here's how that can be done via a 640REST API : 641 642```sh 643curl -b cjar -k -H "Content-Type: application/json" -X PUT \ 644 -d '{"data": "myHostName"}' \ 645 https://<BMC IP address>//xyz/openbmc_project/network/config/attr/HostName 646``` 647 648#### Disabling remote logging 649 650Remote logging can be disabled by writing 0 to the port, or an empty string("") 651to the IP. 652 653#### Changing the rsyslog server 654 655When switching to a new server from an existing one (i.e the address, or port, 656or both change), it is recommended to disable the existing configuration first. 657 658## Boot Fail on Hardware Errors 659 660phosphor-logging supports a setting, which when set, will result in the software 661looking at new phosphor-logging entries being created, and if a CALLOUT\* is 662found within the entry, ensuring the system will not power on. Entries with 663severities of Informational or Debug will not block boots, even if they have 664callouts. 665 666The full design for this can be found 667[here](https://github.com/openbmc/docs/blob/master/designs/fail-boot-on-hw-error.md) 668 669To enable this function: 670 671```sh 672busctl set-property xyz.openbmc_project.Settings /xyz/openbmc_project/logging/settings xyz.openbmc_project.Logging.Settings QuiesceOnHwError b true 673``` 674 675To check if an entry is blocking the boot: 676 677```sh 678obmcutil listbootblock 679``` 680 681Resolve or clear the corresponding entry to allow the system to boot. 682