1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #ifndef _BERT_STORAGE_H_
4 #define _BERT_STORAGE_H_
5
6 #include <acpi/acpi.h>
7 #include <types.h>
8
9 /* Items in the BERT region
10 *
11 * * Each item begins with a Generic Error Status Block
12 * * Zero or more Generic Error Data Entries follow, and
13 * are associated with the Status Block
14 * * Each Generic Error Data Entry must be a certain type,
15 * as defined in the UEFI CPER appendix
16 * * Each type may allow zero or more additional sets of
17 * data, e.g. error descriptions, or processor contexts.
18 *
19 * In the example layout below, there are three BERT region
20 * entries. The first two are a single error. The third
21 * has two errors, with one providing a variable amount
22 * of additional information.
23 *
24 * +====================================================================+
25 * | Generic Error | Generic Error | Platform Memory Error |
26 * | Status | Data Entry | |
27 * |====================================================================|
28 * | Generic Error | Generic Error | Generic Processor Error |
29 * | Status | Data Entry | |
30 * |====================================================================|
31 * | Generic Error | Generic Error | IA32/X64 Processor Error |
32 * | Status | Data Entry | +----------------------------+
33 * | | | | Error Check Data |
34 * | | | +----------------------------+
35 * | | | | MSR Context |
36 * | | | +----------------------------+
37 * | | | | X64 Registers Context |
38 * | +-----------------+----+----------------------------+
39 * | | Generic Error | PCI Express Error |
40 * | | Data Entry | |
41 * +--------------------------------------------------------------------+
42 */
43
44 #define CRASHLOG_RECORD_TYPE 0x2
45 #define CRASHLOG_FW_ERR_REV 0x2
46
47 /* Get the region where BERT error structures have been constructed for
48 * generating the ACPI table
49 */
50 void bert_errors_region(void **start, size_t *size);
51
52 /* Get amount of available storage left for error info */
53 size_t bert_storage_remaining(void);
54 /* Find if errors were added, a BERT region is present, and ACPI table needed */
55 bool bert_errors_present(void);
56 /* The BERT table should only be generated when BERT support is enabled and there's an error */
bert_should_generate_acpi_table(void)57 static inline bool bert_should_generate_acpi_table(void)
58 {
59 return CONFIG(ACPI_BERT) && bert_errors_present();
60 }
61
62 /* Get the number of entries associated with status */
bert_entry_count(acpi_generic_error_status_t * status)63 static inline size_t bert_entry_count(acpi_generic_error_status_t *status)
64 {
65 return (status->block_status & GENERIC_ERR_STS_ENTRY_COUNT_MASK)
66 >> GENERIC_ERR_STS_ENTRY_COUNT_SHIFT;
67 }
68
69 /* Increment the number of entries this status describes */
bert_bump_entry_count(acpi_generic_error_status_t * status)70 static inline void bert_bump_entry_count(acpi_generic_error_status_t *status)
71 {
72 int count;
73
74 count = bert_entry_count(status) + 1;
75 status->block_status &= ~GENERIC_ERR_STS_ENTRY_COUNT_MASK;
76 status->block_status |= count << GENERIC_ERR_STS_ENTRY_COUNT_SHIFT;
77 }
78
79 /* Find the address of the first Generic Data structure from its status entry */
acpi_hest_generic_data3(acpi_generic_error_status_t * status)80 static inline acpi_hest_generic_data_v300_t *acpi_hest_generic_data3(
81 acpi_generic_error_status_t *status)
82 {
83 return (acpi_hest_generic_data_v300_t *)
84 ((u8 *)status + sizeof(*status));
85 }
86
87 /* Find the address of a Generic Data structure's CPER error record section */
88 #define section_of_acpientry(A, B) ((typeof(A))((u8 *)(B) + sizeof(*(B))))
89
90 /* Add a context to an existing IA32/X64-type error entry */
91 cper_ia32x64_context_t *new_cper_ia32x64_ctx(
92 acpi_generic_error_status_t *status,
93 cper_ia32x64_proc_error_section_t *x86err, int type, int num);
94
95 /* Helper to add an MSR context to an existing IA32/X64-type error entry */
96 cper_ia32x64_context_t *cper_new_ia32x64_context_msr(
97 acpi_generic_error_status_t *status,
98 cper_ia32x64_proc_error_section_t *x86err, u32 addr, int num);
99
100 /* Add check info to an existing IA32/X64-type error entry */
101 cper_ia32x64_proc_error_info_t *new_cper_ia32x64_check(
102 acpi_generic_error_status_t *status,
103 cper_ia32x64_proc_error_section_t *x86err,
104 enum cper_x86_check_type type);
105
106 /* Append a new ACPI Generic Error Data Entry plus CPER Error Section to an
107 * existing ACPI Generic Error Status Block. The caller is responsible for
108 * the setting the status and entry severity, as well as populating all fields
109 * of the error section.
110 */
111 acpi_hest_generic_data_v300_t *bert_append_error_datasection(
112 acpi_generic_error_status_t *status, guid_t *guid);
113
114 /* Helper to append an ACPI Generic Error Data Entry plus a CPER Processor
115 * Generic Error Section. As many fields are populated as possible for the
116 * caller.
117 */
118 acpi_hest_generic_data_v300_t *bert_append_genproc(
119 acpi_generic_error_status_t *status);
120
121 /* Helper to append an ACPI Generic Error Data Entry plus a CPER IA32/X64
122 * Processor Error Section. As many fields are populated as possible for the
123 * caller.
124 */
125 acpi_hest_generic_data_v300_t *bert_append_ia32x64(
126 acpi_generic_error_status_t *status);
127
128 void *new_cper_fw_error_crashlog(acpi_generic_error_status_t *status, size_t cl_size);
129 acpi_hest_generic_data_v300_t *bert_append_fw_err(acpi_generic_error_status_t *status);
130
131 /* Add a new event to the BERT region. An event consists of an ACPI Error
132 * Status Block, a Generic Error Data Entry, and an associated CPER Error
133 * Section.
134 */
135 acpi_generic_error_status_t *bert_new_event(guid_t *guid);
136
137 #endif /* _BERT_STORAGE_H_ */
138