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 | |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 10 | static bool boot_error_src_present(cl_node_t *head) |
Felix Held | fba47926 | 2021-05-28 16:11:43 +0200 | [diff] [blame] | 11 | { |
Felix Held | fba47926 | 2021-05-28 16:11:43 +0200 | [diff] [blame] | 12 | if (!discover_crashlog()) { |
| 13 | printk(BIOS_SPEW, "Crashlog discovery result: crashlog not found\n"); |
| 14 | return false; |
| 15 | } |
| 16 | |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 17 | collect_pmc_and_cpu_crashlog_from_srams(head); |
Felix Held | fba47926 | 2021-05-28 16:11:43 +0200 | [diff] [blame] | 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 Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 24 | |
Jonathan Zhang | 01acc03 | 2022-10-26 17:53:25 -0700 | [diff] [blame] | 25 | static enum cb_err record_crashlog_into_bert(void **region, size_t *length) |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 26 | { |
| 27 | acpi_generic_error_status_t *status = NULL; |
Francois Toguo Fotso | c175146 | 2021-05-27 01:10:16 -0700 | [diff] [blame] | 28 | size_t gesb_header_size; |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 29 | void *cl_acpi_data = NULL; |
| 30 | cl_node_t cl_list_head = {.size = 0, .data = NULL, .next = NULL}; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 31 | |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 32 | if (!boot_error_src_present(&cl_list_head)) { |
Felix Held | fba47926 | 2021-05-28 16:11:43 +0200 | [diff] [blame] | 33 | return CB_ERR; |
| 34 | } |
| 35 | |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 36 | if (!cl_get_total_data_size()) { |
Julius Werner | e966595 | 2022-01-21 17:06:20 -0800 | [diff] [blame] | 37 | printk(BIOS_ERR, "No crashlog record present\n"); |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 38 | return CB_ERR; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 39 | } |
| 40 | |
| 41 | status = bert_new_event(&CPER_SEC_FW_ERR_REC_REF_GUID); |
Francois Toguo Fotso | c175146 | 2021-05-27 01:10:16 -0700 | [diff] [blame] | 42 | gesb_header_size = sizeof(*status); |
| 43 | |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 44 | if (!status) { |
Julius Werner | e966595 | 2022-01-21 17:06:20 -0800 | [diff] [blame] | 45 | printk(BIOS_ERR, "unable to allocate GSB\n"); |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 46 | return CB_ERR; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | if (cl_get_total_data_size() > bert_storage_remaining()) { |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 50 | printk(BIOS_ERR, "Crashlog entry would exceed available region\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 | |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 54 | bool multi_entry = false; |
| 55 | cl_node_t *cl_node = cl_list_head.next; |
| 56 | while (cl_node) { |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 57 | |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 58 | if ((cl_node->size <= 0) || (!(cl_node->data))) { |
| 59 | cl_node = cl_node->next; |
| 60 | continue; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 61 | } |
| 62 | |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 63 | if (multi_entry) { |
| 64 | if (!bert_append_fw_err(status)) { |
| 65 | printk(BIOS_ERR, "Crashlog entry would exceed available region\n"); |
Pratikkumar Prajapati | e4893d6 | 2023-05-30 12:30:36 -0700 | [diff] [blame] | 66 | return CB_ERR; |
| 67 | } |
Pratikkumar Prajapati | e4893d6 | 2023-05-30 12:30:36 -0700 | [diff] [blame] | 68 | } |
Pratikkumar Prajapati | 4db9213 | 2023-10-05 13:12:12 -0700 | [diff] [blame^] | 69 | |
| 70 | cl_acpi_data = new_cper_fw_error_crashlog(status, cl_node->size); |
| 71 | if (!cl_acpi_data) { |
| 72 | printk(BIOS_ERR, "Crashlog entry(size 0x%x) would exceed available region\n", |
| 73 | cl_node->size); |
| 74 | return CB_ERR; |
| 75 | } |
| 76 | memcpy(cl_acpi_data, (void *) cl_node->data, cl_node->size); |
| 77 | |
| 78 | cl_node_t *temp = cl_node; |
| 79 | cl_node = cl_node->next; |
| 80 | free_cl_node(temp); |
| 81 | multi_entry = true; |
Pratikkumar Prajapati | e4893d6 | 2023-05-30 12:30:36 -0700 | [diff] [blame] | 82 | } |
| 83 | |
Francois Toguo Fotso | c175146 | 2021-05-27 01:10:16 -0700 | [diff] [blame] | 84 | *length = status->data_length + gesb_header_size; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 85 | *region = (void *)status; |
| 86 | |
Felix Held | 2940548 | 2021-05-28 16:01:57 +0200 | [diff] [blame] | 87 | return CB_SUCCESS; |
Francois Toguo | 15cbc3b | 2021-01-26 10:27:49 -0800 | [diff] [blame] | 88 | } |
Jonathan Zhang | 01acc03 | 2022-10-26 17:53:25 -0700 | [diff] [blame] | 89 | |
| 90 | enum cb_err acpi_soc_get_bert_region(void **region, size_t *length) |
| 91 | { |
| 92 | if (CONFIG(SOC_INTEL_CRASHLOG)) { |
| 93 | return record_crashlog_into_bert(region, length); |
| 94 | } else { |
| 95 | /* Check if MCA error has been added into BERT. */ |
| 96 | if (bert_should_generate_acpi_table()) { |
| 97 | bert_errors_region(region, length); |
| 98 | if (!*region) { |
| 99 | printk(BIOS_ERR, "Can't find BERT storage area\n"); |
| 100 | return CB_ERR; |
| 101 | } |
| 102 | } |
| 103 | return CB_SUCCESS; |
| 104 | } |
| 105 | } |