Skip to content

Commit 3d8c11e

Browse files
punitagrawalardbiesheuvel
authored andcommitted
efi: cper: Add support for printing Firmware Error Record Reference
While debugging a boot failure, the following unknown error record was seen in the boot logs. <...> BERT: Error records from previous boot: [Hardware Error]: event severity: fatal [Hardware Error]: Error 0, type: fatal [Hardware Error]: section type: unknown, 81212a96-09ed-4996-9471-8d729c8e69ed [Hardware Error]: section length: 0x290 [Hardware Error]: 00000000: 00000001 00000000 00000000 00020002 ................ [Hardware Error]: 00000010: 00020002 0000001f 00000320 00000000 ........ ....... [Hardware Error]: 00000020: 00000000 00000000 00000000 00000000 ................ [Hardware Error]: 00000030: 00000000 00000000 00000000 00000000 ................ <...> On further investigation, it was found that the error record with UUID (81212a96-09ed-4996-9471-8d729c8e69ed) has been defined in the UEFI Specification at least since v2.4 and has recently had additional fields defined in v2.7 Section N.2.10 Firmware Error Record Reference. Add support for parsing and printing the defined fields to give users a chance to figure out what went wrong. Signed-off-by: Punit Agrawal <[email protected]> Cc: Ard Biesheuvel <[email protected]> Cc: "Rafael J. Wysocki" <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: James Morse <[email protected]> Cc: [email protected] Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ard Biesheuvel <[email protected]>
1 parent fd62619 commit 3d8c11e

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

drivers/firmware/efi/cper.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,58 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
407407
}
408408
}
409409

410+
static const char * const fw_err_rec_type_strs[] = {
411+
"IPF SAL Error Record",
412+
"SOC Firmware Error Record Type1 (Legacy CrashLog Support)",
413+
"SOC Firmware Error Record Type2",
414+
};
415+
416+
static void cper_print_fw_err(const char *pfx,
417+
struct acpi_hest_generic_data *gdata,
418+
const struct cper_sec_fw_err_rec_ref *fw_err)
419+
{
420+
void *buf = acpi_hest_get_payload(gdata);
421+
u32 offset, length = gdata->error_data_length;
422+
423+
printk("%s""Firmware Error Record Type: %s\n", pfx,
424+
fw_err->record_type < ARRAY_SIZE(fw_err_rec_type_strs) ?
425+
fw_err_rec_type_strs[fw_err->record_type] : "unknown");
426+
printk("%s""Revision: %d\n", pfx, fw_err->revision);
427+
428+
/* Record Type based on UEFI 2.7 */
429+
if (fw_err->revision == 0) {
430+
printk("%s""Record Identifier: %08llx\n", pfx,
431+
fw_err->record_identifier);
432+
} else if (fw_err->revision == 2) {
433+
printk("%s""Record Identifier: %pUl\n", pfx,
434+
&fw_err->record_identifier_guid);
435+
}
436+
437+
/*
438+
* The FW error record may contain trailing data beyond the
439+
* structure defined by the specification. As the fields
440+
* defined (and hence the offset of any trailing data) vary
441+
* with the revision, set the offset to account for this
442+
* variation.
443+
*/
444+
if (fw_err->revision == 0) {
445+
/* record_identifier_guid not defined */
446+
offset = offsetof(struct cper_sec_fw_err_rec_ref,
447+
record_identifier_guid);
448+
} else if (fw_err->revision == 1) {
449+
/* record_identifier not defined */
450+
offset = offsetof(struct cper_sec_fw_err_rec_ref,
451+
record_identifier);
452+
} else {
453+
offset = sizeof(*fw_err);
454+
}
455+
456+
buf += offset;
457+
length -= offset;
458+
459+
print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, buf, length, true);
460+
}
461+
410462
static void cper_print_tstamp(const char *pfx,
411463
struct acpi_hest_generic_data_v300 *gdata)
412464
{
@@ -494,6 +546,16 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata
494546
else
495547
goto err_section_too_small;
496548
#endif
549+
} else if (guid_equal(sec_type, &CPER_SEC_FW_ERR_REC_REF)) {
550+
struct cper_sec_fw_err_rec_ref *fw_err = acpi_hest_get_payload(gdata);
551+
552+
printk("%ssection_type: Firmware Error Record Reference\n",
553+
newpfx);
554+
/* The minimal FW Error Record contains 16 bytes */
555+
if (gdata->error_data_length >= SZ_16)
556+
cper_print_fw_err(newpfx, gdata, fw_err);
557+
else
558+
goto err_section_too_small;
497559
} else {
498560
const void *err = acpi_hest_get_payload(gdata);
499561

include/linux/cper.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,15 @@ struct cper_sec_pcie {
521521
u8 aer_info[96];
522522
};
523523

524+
/* Firmware Error Record Reference, UEFI v2.7 sec N.2.10 */
525+
struct cper_sec_fw_err_rec_ref {
526+
u8 record_type;
527+
u8 revision;
528+
u8 reserved[6];
529+
u64 record_identifier;
530+
guid_t record_identifier_guid;
531+
};
532+
524533
/* Reset to default packing */
525534
#pragma pack()
526535

0 commit comments

Comments
 (0)