Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 1 | /* 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 Held | fba47926 | 2021-05-28 16:11:43 +0200 | [diff] [blame] | 10 | static bool boot_error_src_present(void) |
| 11 | { |
| 12 | if (!CONFIG(SOC_INTEL_CRASHLOG)) { |
| 13 | printk(BIOS_DEBUG, "Crashlog disabled.\n"); |
| 14 | return false; |
| 15 | } |
| 16 | |
| 17 | if (!discover_crashlog()) { |
| 18 | printk(BIOS_SPEW, "Crashlog discovery result: crashlog not found\n"); |
| 19 | return false; |
| 20 | } |
| 21 | |
| 22 | collect_pmc_and_cpu_crashlog_from_srams(); |
| 23 | |
| 24 | /* Discovery tables sizes can be larger than the actual valid collected data */ |
| 25 | u32 crashlog_size = cl_get_total_data_size(); |
| 26 | |
| 27 | return (crashlog_size > 0); |
| 28 | } |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 29 | |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 30 | enum cb_err acpi_soc_get_bert_region(void **region, size_t *length) |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 31 | { |
| 32 | acpi_generic_error_status_t *status = NULL; |
| 33 | size_t cpu_record_size, pmc_record_size; |
Francois Toguo Fotso | c175146 | 2021-05-27 01:10:16 -0700 | [diff] [blame] | 34 | size_t gesb_header_size; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 35 | void *cl_data = NULL; |
| 36 | |
Felix Held | fba47926 | 2021-05-28 16:11:43 +0200 | [diff] [blame] | 37 | if (!boot_error_src_present()) { |
| 38 | return CB_ERR; |
| 39 | } |
| 40 | |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 41 | if (!cl_get_total_data_size()) { |
| 42 | printk(BIOS_ERR, "Error: No crashlog record present\n"); |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 43 | return CB_ERR; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 44 | } |
| 45 | |
| 46 | status = bert_new_event(&CPER_SEC_FW_ERR_REC_REF_GUID); |
Francois Toguo Fotso | c175146 | 2021-05-27 01:10:16 -0700 | [diff] [blame] | 47 | gesb_header_size = sizeof(*status); |
| 48 | |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 49 | if (!status) { |
| 50 | printk(BIOS_ERR, "Error: unable to allocate GSB\n"); |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 51 | return CB_ERR; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | if (cl_get_total_data_size() > bert_storage_remaining()) { |
| 55 | printk(BIOS_ERR, "Error: Crashlog entry would exceed " |
| 56 | "available region\n"); |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 57 | return CB_ERR; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | cpu_record_size = cl_get_cpu_record_size(); |
| 61 | if (cpu_record_size) { |
| 62 | cl_data = new_cper_fw_error_crashlog(status, cpu_record_size); |
| 63 | if (!cl_data) { |
| 64 | printk(BIOS_ERR, "Error: Crashlog CPU entry(size %lu) " |
| 65 | "would exceed available region\n", |
| 66 | cpu_record_size); |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 67 | return CB_ERR; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 68 | } |
| 69 | printk(BIOS_DEBUG, "cl_data %p, cpu_record_size %lu\n", |
| 70 | cl_data, cpu_record_size); |
| 71 | cl_fill_cpu_records(cl_data); |
| 72 | } |
| 73 | |
| 74 | pmc_record_size = cl_get_pmc_record_size(); |
| 75 | if (pmc_record_size) { |
| 76 | /* Allocate new FW ERR structure in case CPU crashlog is present */ |
| 77 | if (cpu_record_size && !bert_append_fw_err(status)) { |
| 78 | printk(BIOS_ERR, "Error: Crashlog PMC entry would " |
| 79 | "exceed available region\n"); |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 80 | return CB_ERR; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | cl_data = new_cper_fw_error_crashlog(status, pmc_record_size); |
| 84 | if (!cl_data) { |
| 85 | printk(BIOS_ERR, "Error: Crashlog PMC entry(size %lu) " |
| 86 | "would exceed available region\n", |
| 87 | pmc_record_size); |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 88 | return CB_ERR; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 89 | } |
| 90 | printk(BIOS_DEBUG, "cl_data %p, pmc_record_size %lu\n", |
| 91 | cl_data, pmc_record_size); |
| 92 | cl_fill_pmc_records(cl_data); |
| 93 | } |
| 94 | |
Francois Toguo Fotso | c175146 | 2021-05-27 01:10:16 -0700 | [diff] [blame] | 95 | *length = status->data_length + gesb_header_size; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 96 | *region = (void *)status; |
| 97 | |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 98 | return CB_SUCCESS; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 99 | } |