diff options
Diffstat (limited to 'src/soc/intel/common/block/acpi/acpi_bert.c')
-rw-r--r-- | src/soc/intel/common/block/acpi/acpi_bert.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/acpi/acpi_bert.c b/src/soc/intel/common/block/acpi/acpi_bert.c new file mode 100644 index 0000000000..d090dfd2cf --- /dev/null +++ b/src/soc/intel/common/block/acpi/acpi_bert.c @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <acpi/acpi.h> +#include <acpi/acpigen.h> +#include <arch/bert_storage.h> +#include <console/console.h> +#include <intelblocks/acpi.h> +#include <intelblocks/crashlog.h> + + +void acpi_soc_fill_bert(acpi_bert_t *bert, + void **region, + size_t *length) +{ + acpi_generic_error_status_t *status = NULL; + size_t cpu_record_size, pmc_record_size; + void *cl_data = NULL; + + if (!cl_get_total_data_size()) { + printk(BIOS_ERR, "Error: No crashlog record present\n"); + return; + } + + status = bert_new_event(&CPER_SEC_FW_ERR_REC_REF_GUID); + if (!status) { + printk(BIOS_ERR, "Error: unable to allocate GSB\n"); + return; + } + + if (cl_get_total_data_size() > bert_storage_remaining()) { + printk(BIOS_ERR, "Error: Crashlog entry would exceed " + "available region\n"); + return; + } + + cpu_record_size = cl_get_cpu_record_size(); + if (cpu_record_size) { + cl_data = new_cper_fw_error_crashlog(status, cpu_record_size); + if (!cl_data) { + printk(BIOS_ERR, "Error: Crashlog CPU entry(size %lu) " + "would exceed available region\n", + cpu_record_size); + return; + } + printk(BIOS_DEBUG, "cl_data %p, cpu_record_size %lu\n", + cl_data, cpu_record_size); + cl_fill_cpu_records(cl_data); + } + + pmc_record_size = cl_get_pmc_record_size(); + if (pmc_record_size) { + /* Allocate new FW ERR structure in case CPU crashlog is present */ + if (cpu_record_size && !bert_append_fw_err(status)) { + printk(BIOS_ERR, "Error: Crashlog PMC entry would " + "exceed available region\n"); + return; + } + + cl_data = new_cper_fw_error_crashlog(status, pmc_record_size); + if (!cl_data) { + printk(BIOS_ERR, "Error: Crashlog PMC entry(size %lu) " + "would exceed available region\n", + pmc_record_size); + return; + } + printk(BIOS_DEBUG, "cl_data %p, pmc_record_size %lu\n", + cl_data, pmc_record_size); + cl_fill_pmc_records(cl_data); + } + + *length = status->raw_data_length; + *region = (void *)status; + +} + +bool acpi_is_boot_error_src_present(void) +{ + + if (!CONFIG(SOC_INTEL_CRASHLOG)) { + printk(BIOS_DEBUG, "Crashlog disabled.\n"); + return false; + } + + if (!discover_crashlog()) { + printk(BIOS_SPEW, "Crashlog discovery result: crashlog not found\n"); + return false; + } + + collect_pmc_and_cpu_crashlog_from_srams(); + + /* Discovery tables sizes can be larger than the actual valid collected data */ + u32 crashlog_size = cl_get_total_data_size(); + + return (crashlog_size > 0); +} |