Skip to content

Commit b1dd1e2

Browse files
committed
Merge tag 'efi-next-for-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi
Pull EFI updates from Ard Biesheuvel: "The usual trickle of EFI contributions: - Parse SMBIOS tables in memory directly on Macbooks that do not implement the EFI SMBIOS protocol - Obtain EDID information from the primary display while running in the EFI stub, and expose it via bootparams on x86 (generic method is in the works, and will likely land during the next cycle) - Bring CPER handling for ARM systems up to data with the latest EFI spec changes - Various cosmetic changes" * tag 'efi-next-for-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi: docs: efi: add CPER functions to driver-api efi/cper: align ARM CPER type with UEFI 2.9A/2.10 specs efi/cper: Add a new helper function to print bitmasks efi/cper: Adjust infopfx size to accept an extra space RAS: Report all ARM processor CPER information to userspace efi/libstub: x86: Store EDID in boot_params efi/libstub: gop: Add support for reading EDID efi/libstub: gop: Initialize screen_info in helper function efi/libstub: gop: Find GOP handle instead of GOP data efi: Fix trailing whitespace in header file efi/memattr: Convert efi_memattr_init() return type to void efi: stmm: fix kernel-doc "bad line" warnings efi/riscv: Remove the useless failure return message print efistub/x86: Add fallback for SMBIOS record lookup
2 parents b0206c4 + 7a2ff00 commit b1dd1e2

16 files changed

Lines changed: 438 additions & 134 deletions

File tree

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
.. SPDX-License-Identifier: GPL-2.0
22
3-
============
4-
UEFI Support
5-
============
3+
====================================================
4+
Unified Extensible Firmware Interface (UEFI) Support
5+
====================================================
66

77
UEFI stub library functions
88
===========================
99

1010
.. kernel-doc:: drivers/firmware/efi/libstub/mem.c
1111
:internal:
12+
13+
UEFI Common Platform Error Record (CPER) functions
14+
==================================================
15+
16+
.. kernel-doc:: drivers/firmware/efi/cper.c

drivers/acpi/apei/ghes.c

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/moduleparam.h>
2323
#include <linux/init.h>
2424
#include <linux/acpi.h>
25+
#include <linux/bitfield.h>
2526
#include <linux/io.h>
2627
#include <linux/interrupt.h>
2728
#include <linux/timer.h>
@@ -552,26 +553,25 @@ static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata,
552553
}
553554

554555
static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
555-
int sev, bool sync)
556+
int sev, bool sync)
556557
{
557558
struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata);
558559
int flags = sync ? MF_ACTION_REQUIRED : 0;
560+
char error_type[120];
559561
bool queued = false;
560562
int sec_sev, i;
561563
char *p;
562564

563-
log_arm_hw_error(err);
564-
565565
sec_sev = ghes_severity(gdata->error_severity);
566+
log_arm_hw_error(err, sec_sev);
566567
if (sev != GHES_SEV_RECOVERABLE || sec_sev != GHES_SEV_RECOVERABLE)
567568
return false;
568569

569570
p = (char *)(err + 1);
570571
for (i = 0; i < err->err_info_num; i++) {
571572
struct cper_arm_err_info *err_info = (struct cper_arm_err_info *)p;
572-
bool is_cache = (err_info->type == CPER_ARM_CACHE_ERROR);
573+
bool is_cache = err_info->type & CPER_ARM_CACHE_ERROR;
573574
bool has_pa = (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR);
574-
const char *error_type = "unknown error";
575575

576576
/*
577577
* The field (err_info->error_info & BIT(26)) is fixed to set to
@@ -585,12 +585,15 @@ static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata,
585585
continue;
586586
}
587587

588-
if (err_info->type < ARRAY_SIZE(cper_proc_error_type_strs))
589-
error_type = cper_proc_error_type_strs[err_info->type];
588+
cper_bits_to_str(error_type, sizeof(error_type),
589+
FIELD_GET(CPER_ARM_ERR_TYPE_MASK, err_info->type),
590+
cper_proc_error_type_strs,
591+
ARRAY_SIZE(cper_proc_error_type_strs));
590592

591593
pr_warn_ratelimited(FW_WARN GHES_PFX
592-
"Unhandled processor error type: %s\n",
593-
error_type);
594+
"Unhandled processor error type 0x%02x: %s%s\n",
595+
err_info->type, error_type,
596+
(err_info->type & ~CPER_ARM_ERR_TYPE_MASK) ? " with reserved bit(s)" : "");
594597
p += err_info->length;
595598
}
596599

@@ -895,11 +898,9 @@ static void ghes_do_proc(struct ghes *ghes,
895898

896899
arch_apei_report_mem_error(sev, mem_err);
897900
queued = ghes_handle_memory_failure(gdata, sev, sync);
898-
}
899-
else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
901+
} else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
900902
ghes_handle_aer(gdata);
901-
}
902-
else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
903+
} else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
903904
queued = ghes_handle_arm_hw_error(gdata, sev, sync);
904905
} else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
905906
struct cxl_cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata);

drivers/firmware/efi/cper-arm.c

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -93,15 +93,11 @@ static void cper_print_arm_err_info(const char *pfx, u32 type,
9393
bool proc_context_corrupt, corrected, precise_pc, restartable_pc;
9494
bool time_out, access_mode;
9595

96-
/* If the type is unknown, bail. */
97-
if (type > CPER_ARM_MAX_TYPE)
98-
return;
99-
10096
/*
10197
* Vendor type errors have error information values that are vendor
10298
* specific.
10399
*/
104-
if (type == CPER_ARM_VENDOR_ERROR)
100+
if (type & CPER_ARM_VENDOR_ERROR)
105101
return;
106102

107103
if (error_info & CPER_ARM_ERR_VALID_TRANSACTION_TYPE) {
@@ -116,43 +112,38 @@ static void cper_print_arm_err_info(const char *pfx, u32 type,
116112
if (error_info & CPER_ARM_ERR_VALID_OPERATION_TYPE) {
117113
op_type = ((error_info >> CPER_ARM_ERR_OPERATION_SHIFT)
118114
& CPER_ARM_ERR_OPERATION_MASK);
119-
switch (type) {
120-
case CPER_ARM_CACHE_ERROR:
115+
if (type & CPER_ARM_CACHE_ERROR) {
121116
if (op_type < ARRAY_SIZE(arm_cache_err_op_strs)) {
122-
printk("%soperation type: %s\n", pfx,
117+
printk("%scache error, operation type: %s\n", pfx,
123118
arm_cache_err_op_strs[op_type]);
124119
}
125-
break;
126-
case CPER_ARM_TLB_ERROR:
120+
}
121+
if (type & CPER_ARM_TLB_ERROR) {
127122
if (op_type < ARRAY_SIZE(arm_tlb_err_op_strs)) {
128-
printk("%soperation type: %s\n", pfx,
123+
printk("%sTLB error, operation type: %s\n", pfx,
129124
arm_tlb_err_op_strs[op_type]);
130125
}
131-
break;
132-
case CPER_ARM_BUS_ERROR:
126+
}
127+
if (type & CPER_ARM_BUS_ERROR) {
133128
if (op_type < ARRAY_SIZE(arm_bus_err_op_strs)) {
134-
printk("%soperation type: %s\n", pfx,
129+
printk("%sbus error, operation type: %s\n", pfx,
135130
arm_bus_err_op_strs[op_type]);
136131
}
137-
break;
138132
}
139133
}
140134

141135
if (error_info & CPER_ARM_ERR_VALID_LEVEL) {
142136
level = ((error_info >> CPER_ARM_ERR_LEVEL_SHIFT)
143137
& CPER_ARM_ERR_LEVEL_MASK);
144-
switch (type) {
145-
case CPER_ARM_CACHE_ERROR:
138+
if (type & CPER_ARM_CACHE_ERROR)
146139
printk("%scache level: %d\n", pfx, level);
147-
break;
148-
case CPER_ARM_TLB_ERROR:
140+
141+
if (type & CPER_ARM_TLB_ERROR)
149142
printk("%sTLB level: %d\n", pfx, level);
150-
break;
151-
case CPER_ARM_BUS_ERROR:
143+
144+
if (type & CPER_ARM_BUS_ERROR)
152145
printk("%saffinity level at which the bus error occurred: %d\n",
153146
pfx, level);
154-
break;
155-
}
156147
}
157148

158149
if (error_info & CPER_ARM_ERR_VALID_PROC_CONTEXT_CORRUPT) {
@@ -240,7 +231,8 @@ void cper_print_proc_arm(const char *pfx,
240231
int i, len, max_ctx_type;
241232
struct cper_arm_err_info *err_info;
242233
struct cper_arm_ctx_info *ctx_info;
243-
char newpfx[64], infopfx[64];
234+
char newpfx[64], infopfx[ARRAY_SIZE(newpfx) + 1];
235+
char error_type[120];
244236

245237
printk("%sMIDR: 0x%016llx\n", pfx, proc->midr);
246238

@@ -289,9 +281,15 @@ void cper_print_proc_arm(const char *pfx,
289281
newpfx);
290282
}
291283

292-
printk("%serror_type: %d, %s\n", newpfx, err_info->type,
293-
err_info->type < ARRAY_SIZE(cper_proc_error_type_strs) ?
294-
cper_proc_error_type_strs[err_info->type] : "unknown");
284+
cper_bits_to_str(error_type, sizeof(error_type),
285+
FIELD_GET(CPER_ARM_ERR_TYPE_MASK, err_info->type),
286+
cper_proc_error_type_strs,
287+
ARRAY_SIZE(cper_proc_error_type_strs));
288+
289+
printk("%serror_type: 0x%02x: %s%s\n", newpfx, err_info->type,
290+
error_type,
291+
(err_info->type & ~CPER_ARM_ERR_TYPE_MASK) ? " with reserved bit(s)" : "");
292+
295293
if (err_info->validation_bits & CPER_ARM_INFO_VALID_ERR_INFO) {
296294
printk("%serror_info: 0x%016llx\n", newpfx,
297295
err_info->error_info);

drivers/firmware/efi/cper.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* Specification version 2.4.
1313
*/
1414

15+
#include <linux/bitmap.h>
1516
#include <linux/kernel.h>
1617
#include <linux/module.h>
1718
#include <linux/time.h>
@@ -69,7 +70,7 @@ const char *cper_severity_str(unsigned int severity)
6970
}
7071
EXPORT_SYMBOL_GPL(cper_severity_str);
7172

72-
/*
73+
/**
7374
* cper_print_bits - print strings for set bits
7475
* @pfx: prefix for each line, including log level and prefix string
7576
* @bits: bit mask
@@ -106,6 +107,65 @@ void cper_print_bits(const char *pfx, unsigned int bits,
106107
printk("%s\n", buf);
107108
}
108109

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 len - buf_size;
166+
}
167+
EXPORT_SYMBOL_GPL(cper_bits_to_str);
168+
109169
static const char * const proc_type_strs[] = {
110170
"IA32/X64",
111171
"IA64",

drivers/firmware/efi/libstub/efi-stub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static struct screen_info *setup_graphics(void)
5656
{
5757
struct screen_info *si, tmp = {};
5858

59-
if (efi_setup_gop(&tmp) != EFI_SUCCESS)
59+
if (efi_setup_graphics(&tmp, NULL) != EFI_SUCCESS)
6060
return NULL;
6161

6262
si = alloc_screen_info();

drivers/firmware/efi/libstub/efistub.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#define EFI_ALLOC_LIMIT ULONG_MAX
3535
#endif
3636

37+
struct edid_info;
38+
struct screen_info;
39+
3740
extern bool efi_no5lvl;
3841
extern bool efi_nochunk;
3942
extern bool efi_nokaslr;
@@ -578,6 +581,32 @@ union efi_graphics_output_protocol {
578581
} mixed_mode;
579582
};
580583

584+
typedef union efi_edid_discovered_protocol efi_edid_discovered_protocol_t;
585+
586+
union efi_edid_discovered_protocol {
587+
struct {
588+
u32 size_of_edid;
589+
u8 *edid;
590+
};
591+
struct {
592+
u32 size_of_edid;
593+
u32 edid;
594+
} mixed_mode;
595+
};
596+
597+
typedef union efi_edid_active_protocol efi_edid_active_protocol_t;
598+
599+
union efi_edid_active_protocol {
600+
struct {
601+
u32 size_of_edid;
602+
u8 *edid;
603+
};
604+
struct {
605+
u32 size_of_edid;
606+
u32 edid;
607+
} mixed_mode;
608+
};
609+
581610
typedef union {
582611
struct {
583612
u32 revision;
@@ -1085,7 +1114,7 @@ efi_status_t efi_parse_options(char const *cmdline);
10851114

10861115
void efi_parse_option_graphics(char *option);
10871116

1088-
efi_status_t efi_setup_gop(struct screen_info *si);
1117+
efi_status_t efi_setup_graphics(struct screen_info *si, struct edid_info *edid);
10891118

10901119
efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
10911120
const efi_char16_t *optstr,

0 commit comments

Comments
 (0)