blob: 7743ccc72fa0e75733ca67ded2ccb0d9deb7a469 [file] [log] [blame]
Francois Toguo15cbc3b2021-01-26 10:27:49 -08001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <acpi/acpi.h>
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>
9
Felix Heldfba479262021-05-28 16:11:43 +020010static bool boot_error_src_present(void)
11{
Felix Heldfba479262021-05-28 16:11:43 +020012 if (!discover_crashlog()) {
13 printk(BIOS_SPEW, "Crashlog discovery result: crashlog not found\n");
14 return false;
15 }
16
17 collect_pmc_and_cpu_crashlog_from_srams();
18
19 /* Discovery tables sizes can be larger than the actual valid collected data */
20 u32 crashlog_size = cl_get_total_data_size();
21
22 return (crashlog_size > 0);
23}
Francois Toguo15cbc3b2021-01-26 10:27:49 -080024
Jonathan Zhang01acc032022-10-26 17:53:25 -070025static enum cb_err record_crashlog_into_bert(void **region, size_t *length)
Francois Toguo15cbc3b2021-01-26 10:27:49 -080026{
27 acpi_generic_error_status_t *status = NULL;
28 size_t cpu_record_size, pmc_record_size;
Francois Toguo Fotsoc1751462021-05-27 01:10:16 -070029 size_t gesb_header_size;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080030 void *cl_data = NULL;
31
Felix Heldfba479262021-05-28 16:11:43 +020032 if (!boot_error_src_present()) {
33 return CB_ERR;
34 }
35
Francois Toguo15cbc3b2021-01-26 10:27:49 -080036 if (!cl_get_total_data_size()) {
Julius Wernere9665952022-01-21 17:06:20 -080037 printk(BIOS_ERR, "No crashlog record present\n");
Felix Held29405482021-05-28 16:01:57 +020038 return CB_ERR;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080039 }
40
41 status = bert_new_event(&CPER_SEC_FW_ERR_REC_REF_GUID);
Francois Toguo Fotsoc1751462021-05-27 01:10:16 -070042 gesb_header_size = sizeof(*status);
43
Francois Toguo15cbc3b2021-01-26 10:27:49 -080044 if (!status) {
Julius Wernere9665952022-01-21 17:06:20 -080045 printk(BIOS_ERR, "unable to allocate GSB\n");
Felix Held29405482021-05-28 16:01:57 +020046 return CB_ERR;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080047 }
48
49 if (cl_get_total_data_size() > bert_storage_remaining()) {
Julius Wernere9665952022-01-21 17:06:20 -080050 printk(BIOS_ERR, "Crashlog entry would exceed "
Francois Toguo15cbc3b2021-01-26 10:27:49 -080051 "available region\n");
Felix Held29405482021-05-28 16:01:57 +020052 return CB_ERR;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080053 }
54
55 cpu_record_size = cl_get_cpu_record_size();
56 if (cpu_record_size) {
57 cl_data = new_cper_fw_error_crashlog(status, cpu_record_size);
58 if (!cl_data) {
Arthur Heymans4cd8f612022-05-13 16:38:37 +020059 printk(BIOS_ERR, "Crashlog CPU entry(size %zu) "
Francois Toguo15cbc3b2021-01-26 10:27:49 -080060 "would exceed available region\n",
61 cpu_record_size);
Felix Held29405482021-05-28 16:01:57 +020062 return CB_ERR;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080063 }
Arthur Heymans4cd8f612022-05-13 16:38:37 +020064 printk(BIOS_DEBUG, "cl_data %p, cpu_record_size %zu\n",
Francois Toguo15cbc3b2021-01-26 10:27:49 -080065 cl_data, cpu_record_size);
66 cl_fill_cpu_records(cl_data);
67 }
68
69 pmc_record_size = cl_get_pmc_record_size();
70 if (pmc_record_size) {
71 /* Allocate new FW ERR structure in case CPU crashlog is present */
72 if (cpu_record_size && !bert_append_fw_err(status)) {
Julius Wernere9665952022-01-21 17:06:20 -080073 printk(BIOS_ERR, "Crashlog PMC entry would "
Francois Toguo15cbc3b2021-01-26 10:27:49 -080074 "exceed available region\n");
Felix Held29405482021-05-28 16:01:57 +020075 return CB_ERR;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080076 }
77
78 cl_data = new_cper_fw_error_crashlog(status, pmc_record_size);
79 if (!cl_data) {
Arthur Heymans4cd8f612022-05-13 16:38:37 +020080 printk(BIOS_ERR, "Crashlog PMC entry(size %zu) "
Francois Toguo15cbc3b2021-01-26 10:27:49 -080081 "would exceed available region\n",
82 pmc_record_size);
Felix Held29405482021-05-28 16:01:57 +020083 return CB_ERR;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080084 }
Arthur Heymans4cd8f612022-05-13 16:38:37 +020085 printk(BIOS_DEBUG, "cl_data %p, pmc_record_size %zu\n",
Francois Toguo15cbc3b2021-01-26 10:27:49 -080086 cl_data, pmc_record_size);
87 cl_fill_pmc_records(cl_data);
88 }
89
Francois Toguo Fotsoc1751462021-05-27 01:10:16 -070090 *length = status->data_length + gesb_header_size;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080091 *region = (void *)status;
92
Felix Held29405482021-05-28 16:01:57 +020093 return CB_SUCCESS;
Francois Toguo15cbc3b2021-01-26 10:27:49 -080094}
Jonathan Zhang01acc032022-10-26 17:53:25 -070095
96enum cb_err acpi_soc_get_bert_region(void **region, size_t *length)
97{
98 if (CONFIG(SOC_INTEL_CRASHLOG)) {
99 return record_crashlog_into_bert(region, length);
100 } else {
101 /* Check if MCA error has been added into BERT. */
102 if (bert_should_generate_acpi_table()) {
103 bert_errors_region(region, length);
104 if (!*region) {
105 printk(BIOS_ERR, "Can't find BERT storage area\n");
106 return CB_ERR;
107 }
108 }
109 return CB_SUCCESS;
110 }
111}