xref: /linux/drivers/firmware/efi/cper.c (revision 92480a2b00a15b0add512b6fc474151ec5340a8e)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * UEFI Common Platform Error Record (CPER) support
4  *
5  * Copyright (C) 2010, Intel Corp.
6  *	Author: Huang Ying <ying.huang@intel.com>
7  *
8  * CPER is the format used to describe platform hardware error by
9  * various tables, such as ERST, BERT and HEST etc.
10  *
11  * For more information about CPER, please refer to Appendix N of UEFI
12  * Specification version 2.4.
13  */
14 
15 #include <linux/bitmap.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/time.h>
19 #include <linux/cper.h>
20 #include <linux/dmi.h>
21 #include <linux/acpi.h>
22 #include <linux/pci.h>
23 #include <linux/aer.h>
24 #include <linux/printk.h>
25 #include <linux/bcd.h>
26 #include <acpi/ghes.h>
27 #include <ras/ras_event.h>
28 #include <cxl/event.h>
29 
30 /*
31  * CPER record ID need to be unique even after reboot, because record
32  * ID is used as index for ERST storage, while CPER records from
33  * multiple boot may co-exist in ERST.
34  */
35 u64 cper_next_record_id(void)
36 {
37 	static atomic64_t seq;
38 
39 	if (!atomic64_read(&seq)) {
40 		time64_t time = ktime_get_real_seconds();
41 
42 		/*
43 		 * This code is unlikely to still be needed in year 2106,
44 		 * but just in case, let's use a few more bits for timestamps
45 		 * after y2038 to be sure they keep increasing monotonically
46 		 * for the next few hundred years...
47 		 */
48 		if (time < 0x80000000)
49 			atomic64_set(&seq, (ktime_get_real_seconds()) << 32);
50 		else
51 			atomic64_set(&seq, 0x8000000000000000ull |
52 					   ktime_get_real_seconds() << 24);
53 	}
54 
55 	return atomic64_inc_return(&seq);
56 }
57 EXPORT_SYMBOL_GPL(cper_next_record_id);
58 
59 static const char * const severity_strs[] = {
60 	"recoverable",
61 	"fatal",
62 	"corrected",
63 	"info",
64 };
65 
66 const char *cper_severity_str(unsigned int severity)
67 {
68 	return severity < ARRAY_SIZE(severity_strs) ?
69 		severity_strs[severity] : "unknown";
70 }
71 EXPORT_SYMBOL_GPL(cper_severity_str);
72 
73 /**
74  * cper_print_bits - print strings for set bits
75  * @pfx: prefix for each line, including log level and prefix string
76  * @bits: bit mask
77  * @strs: string array, indexed by bit position
78  * @strs_size: size of the string array: @strs
79  *
80  * For each set bit in @bits, print the corresponding string in @strs.
81  * If the output length is longer than 80, multiple line will be
82  * printed, with @pfx is printed at the beginning of each line.
83  */
84 void cper_print_bits(const char *pfx, unsigned int bits,
85 		     const char * const strs[], unsigned int strs_size)
86 {
87 	int i, len = 0;
88 	const char *str;
89 	char buf[84];
90 
91 	for (i = 0; i < strs_size; i++) {
92 		if (!(bits & (1U << i)))
93 			continue;
94 		str = strs[i];
95 		if (!str)
96 			continue;
97 		if (len && len + strlen(str) + 2 > 80) {
98 			printk("%s\n", buf);
99 			len = 0;
100 		}
101 		if (!len)
102 			len = snprintf(buf, sizeof(buf), "%s%s", pfx, str);
103 		else
104 			len += scnprintf(buf+len, sizeof(buf)-len, ", %s", str);
105 	}
106 	if (len)
107 		printk("%s\n", buf);
108 }
109 
110 /**
111  * cper_bits_to_str - return a string for set bits
112  * @buf: buffer to store the output string
113  * @buf_size: size of the output string buffer
114  * @bits: bit mask
115  * @strs: string array, indexed by bit position
116  * @strs_size: size of the string array: @strs
117  *
118  * Add to @buf the bitmask in hexadecimal. Then, for each set bit in @bits,
119  * add the corresponding string describing the bit in @strs to @buf.
120  *
121  * A typical example is::
122  *
123  *	const char * const bits[] = {
124  *		"bit 3 name",
125  *		"bit 4 name",
126  *		"bit 5 name",
127  *	};
128  *	char str[120];
129  *	unsigned int bitmask = BIT(3) | BIT(5);
130  *	#define MASK GENMASK(5,3)
131  *
132  *	cper_bits_to_str(str, sizeof(str), FIELD_GET(MASK, bitmask),
133  *			 bits, ARRAY_SIZE(bits));
134  *
135  * The above code fills the string ``str`` with ``bit 3 name|bit 5 name``.
136  *
137  * Return: number of bytes stored or an error code if lower than zero.
138  */
139 int cper_bits_to_str(char *buf, int buf_size, unsigned long bits,
140 		     const char * const strs[], unsigned int strs_size)
141 {
142 	int len = buf_size;
143 	char *str = buf;
144 	int i, size;
145 
146 	*buf = '\0';
147 
148 	for_each_set_bit(i, &bits, strs_size) {
149 		if (!(bits & BIT_ULL(i)))
150 			continue;
151 
152 		if (*buf && len > 0) {
153 			*str = '|';
154 			len--;
155 			str++;
156 		}
157 
158 		size = strscpy(str, strs[i], len);
159 		if (size < 0)
160 			return size;
161 
162 		len -= size;
163 		str += size;
164 	}
165 	return buf_size - len;
166 }
167 EXPORT_SYMBOL_GPL(cper_bits_to_str);
168 
169 static const char * const proc_type_strs[] = {
170 	"IA32/X64",
171 	"IA64",
172 	"ARM",
173 };
174 
175 static const char * const proc_isa_strs[] = {
176 	"IA32",
177 	"IA64",
178 	"X64",
179 	"ARM A32/T32",
180 	"ARM A64",
181 };
182 
183 const char * const cper_proc_error_type_strs[] = {
184 	"cache error",
185 	"TLB error",
186 	"bus error",
187 	"micro-architectural error",
188 };
189 
190 static const char * const proc_op_strs[] = {
191 	"unknown or generic",
192 	"data read",
193 	"data write",
194 	"instruction execution",
195 };
196 
197 static const char * const proc_flag_strs[] = {
198 	"restartable",
199 	"precise IP",
200 	"overflow",
201 	"corrected",
202 };
203 
204 static void cper_print_proc_generic(const char *pfx,
205 				    const struct cper_sec_proc_generic *proc)
206 {
207 	if (proc->validation_bits & CPER_PROC_VALID_TYPE)
208 		printk("%s""processor_type: %d, %s\n", pfx, proc->proc_type,
209 		       proc->proc_type < ARRAY_SIZE(proc_type_strs) ?
210 		       proc_type_strs[proc->proc_type] : "unknown");
211 	if (proc->validation_bits & CPER_PROC_VALID_ISA)
212 		printk("%s""processor_isa: %d, %s\n", pfx, proc->proc_isa,
213 		       proc->proc_isa < ARRAY_SIZE(proc_isa_strs) ?
214 		       proc_isa_strs[proc->proc_isa] : "unknown");
215 	if (proc->validation_bits & CPER_PROC_VALID_ERROR_TYPE) {
216 		printk("%s""error_type: 0x%02x\n", pfx, proc->proc_error_type);
217 		cper_print_bits(pfx, proc->proc_error_type,
218 				cper_proc_error_type_strs,
219 				ARRAY_SIZE(cper_proc_error_type_strs));
220 	}
221 	if (proc->validation_bits & CPER_PROC_VALID_OPERATION)
222 		printk("%s""operation: %d, %s\n", pfx, proc->operation,
223 		       proc->operation < ARRAY_SIZE(proc_op_strs) ?
224 		       proc_op_strs[proc->operation] : "unknown");
225 	if (proc->validation_bits & CPER_PROC_VALID_FLAGS) {
226 		printk("%s""flags: 0x%02x\n", pfx, proc->flags);
227 		cper_print_bits(pfx, proc->flags, proc_flag_strs,
228 				ARRAY_SIZE(proc_flag_strs));
229 	}
230 	if (proc->validation_bits & CPER_PROC_VALID_LEVEL)
231 		printk("%s""level: %d\n", pfx, proc->level);
232 	if (proc->validation_bits & CPER_PROC_VALID_VERSION)
233 		printk("%s""version_info: 0x%016llx\n", pfx, proc->cpu_version);
234 	if (proc->validation_bits & CPER_PROC_VALID_ID)
235 		printk("%s""processor_id: 0x%016llx\n", pfx, proc->proc_id);
236 	if (proc->validation_bits & CPER_PROC_VALID_TARGET_ADDRESS)
237 		printk("%s""target_address: 0x%016llx\n",
238 		       pfx, proc->target_addr);
239 	if (proc->validation_bits & CPER_PROC_VALID_REQUESTOR_ID)
240 		printk("%s""requestor_id: 0x%016llx\n",
241 		       pfx, proc->requestor_id);
242 	if (proc->validation_bits & CPER_PROC_VALID_RESPONDER_ID)
243 		printk("%s""responder_id: 0x%016llx\n",
244 		       pfx, proc->responder_id);
245 	if (proc->validation_bits & CPER_PROC_VALID_IP)
246 		printk("%s""IP: 0x%016llx\n", pfx, proc->ip);
247 }
248 
249 static const char * const mem_err_type_strs[] = {
250 	"unknown",
251 	"no error",
252 	"single-bit ECC",
253 	"multi-bit ECC",
254 	"single-symbol chipkill ECC",
255 	"multi-symbol chipkill ECC",
256 	"master abort",
257 	"target abort",
258 	"parity error",
259 	"watchdog timeout",
260 	"invalid address",
261 	"mirror Broken",
262 	"memory sparing",
263 	"scrub corrected error",
264 	"scrub uncorrected error",
265 	"physical memory map-out event",
266 };
267 
268 const char *cper_mem_err_type_str(unsigned int etype)
269 {
270 	return etype < ARRAY_SIZE(mem_err_type_strs) ?
271 		mem_err_type_strs[etype] : "unknown";
272 }
273 EXPORT_SYMBOL_GPL(cper_mem_err_type_str);
274 
275 const char *cper_mem_err_status_str(u64 status)
276 {
277 	switch ((status >> 8) & 0xff) {
278 	case  1:	return "Error detected internal to the component";
279 	case  4:	return "Storage error in DRAM memory";
280 	case  5:	return "Storage error in TLB";
281 	case  6:	return "Storage error in cache";
282 	case  7:	return "Error in one or more functional units";
283 	case  8:	return "Component failed self test";
284 	case  9:	return "Overflow or undervalue of internal queue";
285 	case 16:	return "Error detected in the bus";
286 	case 17:	return "Virtual address not found on IO-TLB or IO-PDIR";
287 	case 18:	return "Improper access error";
288 	case 19:	return "Access to a memory address which is not mapped to any component";
289 	case 20:	return "Loss of Lockstep";
290 	case 21:	return "Response not associated with a request";
291 	case 22:	return "Bus parity error - must also set the A, C, or D Bits";
292 	case 23:	return "Detection of a protocol error";
293 	case 24:	return "Detection of a PATH_ERROR";
294 	case 25:	return "Bus operation timeout";
295 	case 26:	return "A read was issued to data that has been poisoned";
296 	default:	return "Reserved";
297 	}
298 }
299 EXPORT_SYMBOL_GPL(cper_mem_err_status_str);
300 
301 int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
302 {
303 	u32 len, n;
304 
305 	if (!msg)
306 		return 0;
307 
308 	n = 0;
309 	len = CPER_REC_LEN;
310 	if (mem->validation_bits & CPER_MEM_VALID_NODE)
311 		n += scnprintf(msg + n, len - n, "node:%d ", mem->node);
312 	if (mem->validation_bits & CPER_MEM_VALID_CARD)
313 		n += scnprintf(msg + n, len - n, "card:%d ", mem->card);
314 	if (mem->validation_bits & CPER_MEM_VALID_MODULE)
315 		n += scnprintf(msg + n, len - n, "module:%d ", mem->module);
316 	if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
317 		n += scnprintf(msg + n, len - n, "rank:%d ", mem->rank);
318 	if (mem->validation_bits & CPER_MEM_VALID_BANK)
319 		n += scnprintf(msg + n, len - n, "bank:%d ", mem->bank);
320 	if (mem->validation_bits & CPER_MEM_VALID_BANK_GROUP)
321 		n += scnprintf(msg + n, len - n, "bank_group:%d ",
322 			       mem->bank >> CPER_MEM_BANK_GROUP_SHIFT);
323 	if (mem->validation_bits & CPER_MEM_VALID_BANK_ADDRESS)
324 		n += scnprintf(msg + n, len - n, "bank_address:%d ",
325 			       mem->bank & CPER_MEM_BANK_ADDRESS_MASK);
326 	if (mem->validation_bits & CPER_MEM_VALID_DEVICE)
327 		n += scnprintf(msg + n, len - n, "device:%d ", mem->device);
328 	if (mem->validation_bits & (CPER_MEM_VALID_ROW | CPER_MEM_VALID_ROW_EXT)) {
329 		u32 row = mem->row;
330 
331 		row |= cper_get_mem_extension(mem->validation_bits, mem->extended);
332 		n += scnprintf(msg + n, len - n, "row:%d ", row);
333 	}
334 	if (mem->validation_bits & CPER_MEM_VALID_COLUMN)
335 		n += scnprintf(msg + n, len - n, "column:%d ", mem->column);
336 	if (mem->validation_bits & CPER_MEM_VALID_BIT_POSITION)
337 		n += scnprintf(msg + n, len - n, "bit_position:%d ",
338 			       mem->bit_pos);
339 	if (mem->validation_bits & CPER_MEM_VALID_REQUESTOR_ID)
340 		n += scnprintf(msg + n, len - n, "requestor_id:0x%016llx ",
341 			       mem->requestor_id);
342 	if (mem->validation_bits & CPER_MEM_VALID_RESPONDER_ID)
343 		n += scnprintf(msg + n, len - n, "responder_id:0x%016llx ",
344 			       mem->responder_id);
345 	if (mem->validation_bits & CPER_MEM_VALID_TARGET_ID)
346 		n += scnprintf(msg + n, len - n, "target_id:0x%016llx ",
347 			       mem->target_id);
348 	if (mem->validation_bits & CPER_MEM_VALID_CHIP_ID)
349 		n += scnprintf(msg + n, len - n, "chip_id:%d ",
350 			       mem->extended >> CPER_MEM_CHIP_ID_SHIFT);
351 
352 	return n;
353 }
354 EXPORT_SYMBOL_GPL(cper_mem_err_location);
355 
356 int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
357 {
358 	u32 len, n;
359 	const char *bank = NULL, *device = NULL;
360 
361 	if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE))
362 		return 0;
363 
364 	len = CPER_REC_LEN;
365 	dmi_memdev_name(mem->mem_dev_handle, &bank, &device);
366 	if (bank && device)
367 		n = snprintf(msg, len, "DIMM location: %s %s ", bank, device);
368 	else
369 		n = snprintf(msg, len,
370 			     "DIMM location: not present. DMI handle: 0x%.4x ",
371 			     mem->mem_dev_handle);
372 
373 	return n;
374 }
375 EXPORT_SYMBOL_GPL(cper_dimm_err_location);
376 
377 void cper_mem_err_pack(const struct cper_sec_mem_err *mem,
378 		       struct cper_mem_err_compact *cmem)
379 {
380 	cmem->validation_bits = mem->validation_bits;
381 	cmem->node = mem->node;
382 	cmem->card = mem->card;
383 	cmem->module = mem->module;
384 	cmem->bank = mem->bank;
385 	cmem->device = mem->device;
386 	cmem->row = mem->row;
387 	cmem->column = mem->column;
388 	cmem->bit_pos = mem->bit_pos;
389 	cmem->requestor_id = mem->requestor_id;
390 	cmem->responder_id = mem->responder_id;
391 	cmem->target_id = mem->target_id;
392 
393 	/*
394 	 * These four sit past the end of the UEFI 2.1/2.2 layout, which older
395 	 * firmware still emits, so reading them unconditionally runs off a
396 	 * short record. Every consumer of the compact record gates them on the
397 	 * same validation bits, so leave them zero when firmware does not
398 	 * claim them.
399 	 */
400 	cmem->extended = 0;
401 	cmem->rank = 0;
402 	cmem->mem_array_handle = 0;
403 	cmem->mem_dev_handle = 0;
404 
405 	if (mem->validation_bits &
406 	    (CPER_MEM_VALID_ROW_EXT | CPER_MEM_VALID_CHIP_ID))
407 		cmem->extended = mem->extended;
408 	if (mem->validation_bits & CPER_MEM_VALID_RANK_NUMBER)
409 		cmem->rank = mem->rank;
410 	if (mem->validation_bits & CPER_MEM_VALID_CARD_HANDLE)
411 		cmem->mem_array_handle = mem->mem_array_handle;
412 	if (mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE)
413 		cmem->mem_dev_handle = mem->mem_dev_handle;
414 }
415 EXPORT_SYMBOL_GPL(cper_mem_err_pack);
416 
417 const char *cper_mem_err_unpack(struct trace_seq *p,
418 				struct cper_mem_err_compact *cmem)
419 {
420 	const char *ret = trace_seq_buffer_ptr(p);
421 	char rcd_decode_str[CPER_REC_LEN];
422 
423 	if (cper_mem_err_location(cmem, rcd_decode_str))
424 		trace_seq_printf(p, "%s", rcd_decode_str);
425 	if (cper_dimm_err_location(cmem, rcd_decode_str))
426 		trace_seq_printf(p, "%s", rcd_decode_str);
427 	trace_seq_putc(p, '\0');
428 
429 	return ret;
430 }
431 
432 static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem,
433 	int len)
434 {
435 	struct cper_mem_err_compact cmem;
436 	char rcd_decode_str[CPER_REC_LEN];
437 
438 	/* Don't trust UEFI 2.1/2.2 structure with bad validation bits */
439 	if (len == sizeof(struct cper_sec_mem_err_old) &&
440 	    (mem->validation_bits & ~(CPER_MEM_VALID_RANK_NUMBER - 1))) {
441 		pr_err(FW_WARN "valid bits set for fields beyond structure\n");
442 		return;
443 	}
444 	if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
445 		printk("%s error_status: %s (0x%016llx)\n",
446 		       pfx, cper_mem_err_status_str(mem->error_status),
447 		       mem->error_status);
448 	if (mem->validation_bits & CPER_MEM_VALID_PA)
449 		printk("%s""physical_address: 0x%016llx\n",
450 		       pfx, mem->physical_addr);
451 	if (mem->validation_bits & CPER_MEM_VALID_PA_MASK)
452 		printk("%s""physical_address_mask: 0x%016llx\n",
453 		       pfx, mem->physical_addr_mask);
454 	cper_mem_err_pack(mem, &cmem);
455 	if (cper_mem_err_location(&cmem, rcd_decode_str))
456 		printk("%s%s\n", pfx, rcd_decode_str);
457 	if (mem->validation_bits & CPER_MEM_VALID_ERROR_TYPE) {
458 		u8 etype = mem->error_type;
459 		printk("%s""error_type: %d, %s\n", pfx, etype,
460 		       cper_mem_err_type_str(etype));
461 	}
462 	if (cper_dimm_err_location(&cmem, rcd_decode_str))
463 		printk("%s%s\n", pfx, rcd_decode_str);
464 }
465 
466 static const char * const pcie_port_type_strs[] = {
467 	"PCIe end point",
468 	"legacy PCI end point",
469 	"unknown",
470 	"unknown",
471 	"root port",
472 	"upstream switch port",
473 	"downstream switch port",
474 	"PCIe to PCI/PCI-X bridge",
475 	"PCI/PCI-X to PCIe bridge",
476 	"root complex integrated endpoint device",
477 	"root complex event collector",
478 };
479 
480 static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
481 			    const struct acpi_hest_generic_data *gdata)
482 {
483 	if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
484 		printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
485 		       pcie->port_type < ARRAY_SIZE(pcie_port_type_strs) ?
486 		       pcie_port_type_strs[pcie->port_type] : "unknown");
487 	if (pcie->validation_bits & CPER_PCIE_VALID_VERSION)
488 		printk("%s""version: %d.%d\n", pfx,
489 		       pcie->version.major, pcie->version.minor);
490 	if (pcie->validation_bits & CPER_PCIE_VALID_COMMAND_STATUS)
491 		printk("%s""command: 0x%04x, status: 0x%04x\n", pfx,
492 		       pcie->command, pcie->status);
493 	if (pcie->validation_bits & CPER_PCIE_VALID_DEVICE_ID) {
494 		const __u8 *p;
495 		printk("%s""device_id: %04x:%02x:%02x.%x\n", pfx,
496 		       pcie->device_id.segment, pcie->device_id.bus,
497 		       pcie->device_id.device, pcie->device_id.function);
498 		printk("%s""slot: %d\n", pfx,
499 		       pcie->device_id.slot >> CPER_PCIE_SLOT_SHIFT);
500 		printk("%s""secondary_bus: 0x%02x\n", pfx,
501 		       pcie->device_id.secondary_bus);
502 		printk("%s""vendor_id: 0x%04x, device_id: 0x%04x\n", pfx,
503 		       pcie->device_id.vendor_id, pcie->device_id.device_id);
504 		p = pcie->device_id.class_code;
505 		printk("%s""class_code: %02x%02x%02x\n", pfx, p[2], p[1], p[0]);
506 	}
507 	if (pcie->validation_bits & CPER_PCIE_VALID_SERIAL_NUMBER)
508 		printk("%s""serial number: 0x%04x, 0x%04x\n", pfx,
509 		       pcie->serial_number.lower, pcie->serial_number.upper);
510 	if (pcie->validation_bits & CPER_PCIE_VALID_BRIDGE_CONTROL_STATUS)
511 		printk(
512 	"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
513 	pfx, pcie->bridge.secondary_status, pcie->bridge.control);
514 
515 	/*
516 	 * Print all valid AER info. Record may be from BERT (boot-time) or GHES (run-time).
517 	 *
518 	 * Fatal errors call __ghes_panic() before AER handler prints this.
519 	 */
520 	if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) {
521 		struct aer_capability_regs *aer;
522 
523 		aer = (struct aer_capability_regs *)pcie->aer_info;
524 		printk("%saer_cor_status: 0x%08x, aer_cor_mask: 0x%08x\n",
525 		       pfx, aer->cor_status, aer->cor_mask);
526 		printk("%saer_uncor_status: 0x%08x, aer_uncor_mask: 0x%08x\n",
527 		       pfx, aer->uncor_status, aer->uncor_mask);
528 		printk("%saer_uncor_severity: 0x%08x\n",
529 		       pfx, aer->uncor_severity);
530 		printk("%sTLP Header: %08x %08x %08x %08x\n", pfx,
531 		       aer->header_log.dw[0], aer->header_log.dw[1],
532 		       aer->header_log.dw[2], aer->header_log.dw[3]);
533 	}
534 }
535 
536 static const char * const fw_err_rec_type_strs[] = {
537 	"IPF SAL Error Record",
538 	"SOC Firmware Error Record Type1 (Legacy CrashLog Support)",
539 	"SOC Firmware Error Record Type2",
540 };
541 
542 static void cper_print_fw_err(const char *pfx,
543 			      struct acpi_hest_generic_data *gdata,
544 			      const struct cper_sec_fw_err_rec_ref *fw_err)
545 {
546 	void *buf = acpi_hest_get_payload(gdata);
547 	u32 offset, length = gdata->error_data_length;
548 
549 	printk("%s""Firmware Error Record Type: %s\n", pfx,
550 	       fw_err->record_type < ARRAY_SIZE(fw_err_rec_type_strs) ?
551 	       fw_err_rec_type_strs[fw_err->record_type] : "unknown");
552 	printk("%s""Revision: %d\n", pfx, fw_err->revision);
553 
554 	/* Record Type based on UEFI 2.7 */
555 	if (fw_err->revision == 0) {
556 		printk("%s""Record Identifier: %08llx\n", pfx,
557 		       fw_err->record_identifier);
558 	} else if (fw_err->revision == 2) {
559 		printk("%s""Record Identifier: %pUl\n", pfx,
560 		       &fw_err->record_identifier_guid);
561 	}
562 
563 	/*
564 	 * The FW error record may contain trailing data beyond the
565 	 * structure defined by the specification. As the fields
566 	 * defined (and hence the offset of any trailing data) vary
567 	 * with the revision, set the offset to account for this
568 	 * variation.
569 	 */
570 	if (fw_err->revision == 0) {
571 		/* record_identifier_guid not defined */
572 		offset = offsetof(struct cper_sec_fw_err_rec_ref,
573 				  record_identifier_guid);
574 	} else if (fw_err->revision == 1) {
575 		/* record_identifier not defined */
576 		offset = offsetof(struct cper_sec_fw_err_rec_ref,
577 				  record_identifier);
578 	} else {
579 		offset = sizeof(*fw_err);
580 	}
581 	if (offset > length) {
582 		printk("%s""error section length is too small: offset=%d, length=%d\n",
583 		       pfx, offset, length);
584 		return;
585 	}
586 
587 	buf += offset;
588 	length -= offset;
589 
590 	print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, buf, length, true);
591 }
592 
593 static void cper_print_tstamp(const char *pfx,
594 				   struct acpi_hest_generic_data_v300 *gdata)
595 {
596 	__u8 hour, min, sec, day, mon, year, century, *timestamp;
597 
598 	if (gdata->validation_bits & ACPI_HEST_GEN_VALID_TIMESTAMP) {
599 		timestamp = (__u8 *)&(gdata->time_stamp);
600 		sec       = bcd2bin(timestamp[0]);
601 		min       = bcd2bin(timestamp[1]);
602 		hour      = bcd2bin(timestamp[2]);
603 		day       = bcd2bin(timestamp[4]);
604 		mon       = bcd2bin(timestamp[5]);
605 		year      = bcd2bin(timestamp[6]);
606 		century   = bcd2bin(timestamp[7]);
607 
608 		printk("%s%ststamp: %02d%02d-%02d-%02d %02d:%02d:%02d\n", pfx,
609 		       (timestamp[3] & 0x1 ? "precise " : "imprecise "),
610 		       century, year, mon, day, hour, min, sec);
611 	}
612 }
613 
614 struct ignore_section {
615 	guid_t guid;
616 	const char *name;
617 };
618 
619 static const struct ignore_section ignore_sections[] = {
620 	{ .guid = CPER_SEC_CXL_GEN_MEDIA_GUID, .name = "CXL General Media Event" },
621 	{ .guid = CPER_SEC_CXL_DRAM_GUID, .name = "CXL DRAM Event" },
622 	{ .guid = CPER_SEC_CXL_MEM_MODULE_GUID, .name = "CXL Memory Module Event" },
623 };
624 
625 static void
626 cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata,
627 			   int sec_no)
628 {
629 	guid_t *sec_type = (guid_t *)gdata->section_type;
630 	__u16 severity;
631 	char newpfx[64];
632 
633 	if (acpi_hest_get_version(gdata) >= 3)
634 		cper_print_tstamp(pfx, (struct acpi_hest_generic_data_v300 *)gdata);
635 
636 	severity = gdata->error_severity;
637 	printk("%s""Error %d, type: %s\n", pfx, sec_no,
638 	       cper_severity_str(severity));
639 	if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
640 		printk("%s""fru_id: %pUl\n", pfx, gdata->fru_id);
641 	if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
642 		printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text);
643 
644 	snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
645 
646 	for (int i = 0; i < ARRAY_SIZE(ignore_sections); i++) {
647 		if (guid_equal(sec_type, &ignore_sections[i].guid)) {
648 			printk("%ssection_type: %s\n", newpfx, ignore_sections[i].name);
649 			return;
650 		}
651 	}
652 
653 	if (guid_equal(sec_type, &CPER_SEC_PROC_GENERIC)) {
654 		struct cper_sec_proc_generic *proc_err = acpi_hest_get_payload(gdata);
655 
656 		printk("%s""section_type: general processor error\n", newpfx);
657 		if (gdata->error_data_length >= sizeof(*proc_err))
658 			cper_print_proc_generic(newpfx, proc_err);
659 		else
660 			goto err_section_too_small;
661 	} else if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
662 		struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata);
663 
664 		printk("%s""section_type: memory error\n", newpfx);
665 		if (gdata->error_data_length >=
666 		    sizeof(struct cper_sec_mem_err_old))
667 			cper_print_mem(newpfx, mem_err,
668 				       gdata->error_data_length);
669 		else
670 			goto err_section_too_small;
671 	} else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
672 		struct cper_sec_pcie *pcie = acpi_hest_get_payload(gdata);
673 
674 		printk("%s""section_type: PCIe error\n", newpfx);
675 		if (gdata->error_data_length >= sizeof(*pcie))
676 			cper_print_pcie(newpfx, pcie, gdata);
677 		else
678 			goto err_section_too_small;
679 #if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
680 	} else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
681 		struct cper_sec_proc_arm *arm_err = acpi_hest_get_payload(gdata);
682 
683 		printk("%ssection_type: ARM processor error\n", newpfx);
684 		if (gdata->error_data_length >= sizeof(*arm_err))
685 			cper_print_proc_arm(newpfx, arm_err,
686 					    gdata->error_data_length);
687 		else
688 			goto err_section_too_small;
689 #endif
690 #if defined(CONFIG_UEFI_CPER_X86)
691 	} else if (guid_equal(sec_type, &CPER_SEC_PROC_IA)) {
692 		struct cper_sec_proc_ia *ia_err = acpi_hest_get_payload(gdata);
693 
694 		printk("%ssection_type: IA32/X64 processor error\n", newpfx);
695 		if (gdata->error_data_length >= sizeof(*ia_err))
696 			cper_print_proc_ia(newpfx, ia_err);
697 		else
698 			goto err_section_too_small;
699 #endif
700 	} else if (guid_equal(sec_type, &CPER_SEC_FW_ERR_REC_REF)) {
701 		struct cper_sec_fw_err_rec_ref *fw_err = acpi_hest_get_payload(gdata);
702 
703 		printk("%ssection_type: Firmware Error Record Reference\n",
704 		       newpfx);
705 		/* The minimal FW Error Record contains 16 bytes */
706 		if (gdata->error_data_length >= SZ_16)
707 			cper_print_fw_err(newpfx, gdata, fw_err);
708 		else
709 			goto err_section_too_small;
710 	} else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
711 		struct cxl_cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata);
712 
713 		printk("%ssection_type: CXL Protocol Error\n", newpfx);
714 		if (gdata->error_data_length >= sizeof(*prot_err))
715 			cxl_cper_print_prot_err(newpfx, prot_err);
716 		else
717 			goto err_section_too_small;
718 	} else {
719 		const void *err = acpi_hest_get_payload(gdata);
720 
721 		printk("%ssection type: unknown, %pUl\n", newpfx, sec_type);
722 		printk("%ssection length: %#x\n", newpfx,
723 		       gdata->error_data_length);
724 		print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, 4, err,
725 			       gdata->error_data_length, true);
726 	}
727 
728 	return;
729 
730 err_section_too_small:
731 	pr_err(FW_WARN "error section length is too small\n");
732 }
733 
734 void cper_estatus_print(const char *pfx,
735 			const struct acpi_hest_generic_status *estatus)
736 {
737 	struct acpi_hest_generic_data *gdata;
738 	int sec_no = 0;
739 	char newpfx[64];
740 	__u16 severity;
741 
742 	severity = estatus->error_severity;
743 	if (severity == CPER_SEV_CORRECTED)
744 		printk("%s%s\n", pfx,
745 		       "It has been corrected by h/w "
746 		       "and requires no further action");
747 	printk("%s""event severity: %s\n", pfx, cper_severity_str(severity));
748 	snprintf(newpfx, sizeof(newpfx), "%s ", pfx);
749 
750 	apei_estatus_for_each_section(estatus, gdata) {
751 		cper_estatus_print_section(newpfx, gdata, sec_no);
752 		sec_no++;
753 	}
754 }
755 EXPORT_SYMBOL_GPL(cper_estatus_print);
756 
757 int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus)
758 {
759 	if (estatus->data_length &&
760 	    estatus->data_length < sizeof(struct acpi_hest_generic_data))
761 		return -EINVAL;
762 	if (estatus->raw_data_length &&
763 	    estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length)
764 		return -EINVAL;
765 
766 	/*
767 	 * cper_estatus_len() sums these into a u32, and a wrapped sum reads
768 	 * back smaller than the record. Reject a length that cannot be
769 	 * expressed so no caller is handed the short value.
770 	 */
771 	if ((u64)sizeof(*estatus) + estatus->data_length > U32_MAX)
772 		return -EINVAL;
773 	if (estatus->raw_data_length &&
774 	    (u64)estatus->raw_data_offset + estatus->raw_data_length > U32_MAX)
775 		return -EINVAL;
776 
777 	return 0;
778 }
779 EXPORT_SYMBOL_GPL(cper_estatus_check_header);
780 
781 int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
782 {
783 	struct acpi_hest_generic_data *gdata;
784 	unsigned int data_len;
785 	int rc;
786 
787 	rc = cper_estatus_check_header(estatus);
788 	if (rc)
789 		return rc;
790 
791 	data_len = estatus->data_length;
792 
793 	apei_estatus_for_each_section(estatus, gdata) {
794 		int record_size;
795 
796 		/*
797 		 * The <acpi/ghes.h> helpers sum these as a signed int, so a
798 		 * huge error_data_length wraps small rather than large and the
799 		 * walk then advances by that wrapped value. Reject a size an
800 		 * int cannot carry.
801 		 */
802 		if (check_add_overflow(acpi_hest_get_size(gdata),
803 				       gdata->error_data_length, &record_size))
804 			return -EINVAL;
805 
806 		if (record_size > data_len)
807 			return -EINVAL;
808 
809 		data_len -= record_size;
810 	}
811 	if (data_len)
812 		return -EINVAL;
813 
814 	return 0;
815 }
816 EXPORT_SYMBOL_GPL(cper_estatus_check);
817