mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
Add support for using a sysfail boot entry in case of UEFI firmware capsule update failure [1]. The status of a firmware update is obtained from the EFI System Resource Table (ESRT), which provides an optional mechanism for identifying device and system firmware resources for the purposes of targeting firmware updates to those resources. Current implementation uses the value of LastAttemptStatus field from ESRT, which describes the result of the last firmware update attempt for the firmware resource entry. The field is updated each time an UpdateCapsule() is attempted for an ESRT entry and is preserved across reboots (non-volatile). This can be be used in setups with support for A/B OTA updates, where the boot firmware and Linux/RootFS might be updated synchronously. [1] https://uefi.org/specs/UEFI/2.10/23_Firmware_Update_and_Reporting.html Signed-off-by: Igor Opaniuk <igor.opaniuk@foundries.io>
40 lines
1.1 KiB
C
40 lines
1.1 KiB
C
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
|
|
#include "sysfail.h"
|
|
#include "util.h"
|
|
|
|
static bool firmware_update_has_failed(void) {
|
|
const EFI_SYSTEM_RESOURCE_TABLE *esrt_table;
|
|
const EFI_SYSTEM_RESOURCE_ENTRY *esrt_entries;
|
|
|
|
esrt_table = find_configuration_table(MAKE_GUID_PTR(EFI_SYSTEM_RESOURCE_TABLE));
|
|
if (!esrt_table)
|
|
return false;
|
|
|
|
esrt_entries = esrt_table->Entries;
|
|
|
|
FOREACH_ARRAY(esrt_entry, esrt_entries, esrt_table->FwResourceCount)
|
|
if (esrt_entry->FwType == ESRT_FW_TYPE_SYSTEMFIRMWARE)
|
|
return esrt_entry->LastAttemptStatus != LAST_ATTEMPT_STATUS_SUCCESS;
|
|
|
|
return false;
|
|
}
|
|
|
|
SysFailType sysfail_check(void) {
|
|
if (firmware_update_has_failed())
|
|
return SYSFAIL_FIRMWARE_UPDATE;
|
|
|
|
return SYSFAIL_NO_FAILURE;
|
|
}
|
|
|
|
const char16_t* sysfail_get_error_str(SysFailType fail_type) {
|
|
switch (fail_type) {
|
|
case SYSFAIL_NO_FAILURE:
|
|
return NULL;
|
|
case SYSFAIL_FIRMWARE_UPDATE:
|
|
return u"firmware-updare-failure";
|
|
default:
|
|
assert_not_reached();
|
|
}
|
|
}
|