1 /* SPDX-License-Identifier: GPL-2.0-or-later */
4 #include <acpi/acpigen.h>
5 #include <arch/bert_storage.h>
6 #include <console/console.h>
7 #include <intelblocks/acpi.h>
8 #include <intelblocks/crashlog.h>
10 static bool boot_error_src_present(cl_node_t
*head
)
12 if (!discover_crashlog()) {
13 printk(BIOS_SPEW
, "Crashlog discovery result: crashlog not found\n");
17 collect_pmc_and_cpu_crashlog_from_srams(head
);
19 /* Discovery tables sizes can be larger than the actual valid collected data */
20 u32 crashlog_size
= cl_get_total_data_size();
22 return (crashlog_size
> 0);
25 static enum cb_err
record_crashlog_into_bert(void **region
, size_t *length
)
27 acpi_generic_error_status_t
*status
= NULL
;
28 size_t gesb_header_size
;
29 void *cl_acpi_data
= NULL
;
30 cl_node_t cl_list_head
= {.size
= 0, .data
= NULL
, .next
= NULL
};
32 if (!boot_error_src_present(&cl_list_head
)) {
36 if (!cl_get_total_data_size()) {
37 printk(BIOS_ERR
, "No crashlog record present\n");
41 status
= bert_new_event(&CPER_SEC_FW_ERR_REC_REF_GUID
);
42 gesb_header_size
= sizeof(*status
);
45 printk(BIOS_ERR
, "unable to allocate GSB\n");
49 if (cl_get_total_data_size() > bert_storage_remaining()) {
50 printk(BIOS_ERR
, "Crashlog entry would exceed available region\n");
54 bool multi_entry
= false;
55 cl_node_t
*cl_node
= cl_list_head
.next
;
57 if ((cl_node
->size
<= 0) || (!(cl_node
->data
))) {
58 cl_node
= cl_node
->next
;
63 if (!bert_append_fw_err(status
)) {
64 printk(BIOS_ERR
, "Crashlog entry would exceed available region\n");
69 cl_acpi_data
= new_cper_fw_error_crashlog(status
, cl_node
->size
);
71 printk(BIOS_ERR
, "Crashlog entry(size 0x%x) would exceed available region\n",
75 memcpy(cl_acpi_data
, (void *) cl_node
->data
, cl_node
->size
);
77 cl_node_t
*temp
= cl_node
;
78 cl_node
= cl_node
->next
;
83 *length
= status
->data_length
+ gesb_header_size
;
84 *region
= (void *)status
;
89 enum cb_err
acpi_soc_get_bert_region(void **region
, size_t *length
)
91 if (CONFIG(SOC_INTEL_CRASHLOG
)) {
92 return record_crashlog_into_bert(region
, length
);
94 /* Check if MCA error has been added into BERT. */
95 if (bert_should_generate_acpi_table()) {
96 bert_errors_region(region
, length
);
98 printk(BIOS_ERR
, "Can't find BERT storage area\n");