diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-16 19:47:38 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-16 19:47:38 -0400 |
commit | cc9b499a1f71696054a2771aae504c53eecff31d (patch) | |
tree | 96b18e65c38bfcacd2f03a9012bd5384e1c54bf2 | |
parent | 98c82b4b8be60b05bc96aa4ab664ca0b0e39001f (diff) | |
parent | d3dc0168e93233ba4d4ed9a2c506c9d2b8d8cd33 (diff) |
Merge branch 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI updates from Ingo Molnar:
- refactor the EFI config table handling across architectures
- add support for the Dell EMC OEM config table
- include AER diagnostic output to CPER handling of fatal PCIe errors
* 'efi-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
efi: cper: print AER info of PCIe fatal error
efi: Export Runtime Configuration Interface table to sysfs
efi: ia64: move SAL systab handling out of generic EFI code
efi/x86: move UV_SYSTAB handling into arch/x86
efi: x86: move efi_is_table_address() into arch/x86
-rw-r--r-- | Documentation/ABI/testing/sysfs-firmware-efi | 8 | ||||
-rw-r--r-- | arch/ia64/include/asm/sal.h | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/efi.c | 3 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/efi.h | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/uv/uv.h | 4 | ||||
-rw-r--r-- | arch/x86/mm/ioremap.c | 1 | ||||
-rw-r--r-- | arch/x86/platform/efi/efi.c | 39 | ||||
-rw-r--r-- | arch/x86/platform/uv/bios_uv.c | 10 | ||||
-rw-r--r-- | drivers/firmware/efi/Kconfig | 13 | ||||
-rw-r--r-- | drivers/firmware/efi/Makefile | 1 | ||||
-rw-r--r-- | drivers/firmware/efi/cper.c | 15 | ||||
-rw-r--r-- | drivers/firmware/efi/efi.c | 39 | ||||
-rw-r--r-- | drivers/firmware/efi/rci2-table.c | 147 | ||||
-rw-r--r-- | include/linux/efi.h | 14 |
15 files changed, 250 insertions, 52 deletions
diff --git a/Documentation/ABI/testing/sysfs-firmware-efi b/Documentation/ABI/testing/sysfs-firmware-efi index e794eac32a90..5e4d0b27cdfe 100644 --- a/Documentation/ABI/testing/sysfs-firmware-efi +++ b/Documentation/ABI/testing/sysfs-firmware-efi | |||
@@ -28,3 +28,11 @@ Description: Displays the physical addresses of all EFI Configuration | |||
28 | versions are always printed first, i.e. ACPI20 comes | 28 | versions are always printed first, i.e. ACPI20 comes |
29 | before ACPI. | 29 | before ACPI. |
30 | Users: dmidecode | 30 | Users: dmidecode |
31 | |||
32 | What: /sys/firmware/efi/tables/rci2 | ||
33 | Date: July 2019 | ||
34 | Contact: Narendra K <Narendra.K@dell.com>, linux-bugs@dell.com | ||
35 | Description: Displays the content of the Runtime Configuration Interface | ||
36 | Table version 2 on Dell EMC PowerEdge systems in binary format | ||
37 | Users: It is used by Dell EMC OpenManage Server Administrator tool to | ||
38 | populate BIOS setup page. | ||
diff --git a/arch/ia64/include/asm/sal.h b/arch/ia64/include/asm/sal.h index 588f33156da6..08f5b6aaed73 100644 --- a/arch/ia64/include/asm/sal.h +++ b/arch/ia64/include/asm/sal.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/pal.h> | 43 | #include <asm/pal.h> |
44 | #include <asm/fpu.h> | 44 | #include <asm/fpu.h> |
45 | 45 | ||
46 | extern unsigned long sal_systab_phys; | ||
46 | extern spinlock_t sal_lock; | 47 | extern spinlock_t sal_lock; |
47 | 48 | ||
48 | /* SAL spec _requires_ eight args for each call. */ | 49 | /* SAL spec _requires_ eight args for each call. */ |
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 3795d18276c4..0a34dcc435c6 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -47,8 +47,11 @@ | |||
47 | 47 | ||
48 | static __initdata unsigned long palo_phys; | 48 | static __initdata unsigned long palo_phys; |
49 | 49 | ||
50 | unsigned long sal_systab_phys = EFI_INVALID_TABLE_ADDR; | ||
51 | |||
50 | static __initdata efi_config_table_type_t arch_tables[] = { | 52 | static __initdata efi_config_table_type_t arch_tables[] = { |
51 | {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, "PALO", &palo_phys}, | 53 | {PROCESSOR_ABSTRACTION_LAYER_OVERWRITE_GUID, "PALO", &palo_phys}, |
54 | {SAL_SYSTEM_TABLE_GUID, "SALsystab", &sal_systab_phys}, | ||
52 | {NULL_GUID, NULL, 0}, | 55 | {NULL_GUID, NULL, 0}, |
53 | }; | 56 | }; |
54 | 57 | ||
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 18de565d5825..8eb276aac5ce 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -586,7 +586,7 @@ setup_arch (char **cmdline_p) | |||
586 | find_memory(); | 586 | find_memory(); |
587 | 587 | ||
588 | /* process SAL system table: */ | 588 | /* process SAL system table: */ |
589 | ia64_sal_init(__va(efi.sal_systab)); | 589 | ia64_sal_init(__va(sal_systab_phys)); |
590 | 590 | ||
591 | #ifdef CONFIG_ITANIUM | 591 | #ifdef CONFIG_ITANIUM |
592 | ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); | 592 | ia64_patch_rse((u64) __start___rse_patchlist, (u64) __end___rse_patchlist); |
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 606a4b6a9812..43a82e59c59d 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h | |||
@@ -242,6 +242,7 @@ static inline bool efi_is_64bit(void) | |||
242 | __efi_early()->runtime_services), __VA_ARGS__) | 242 | __efi_early()->runtime_services), __VA_ARGS__) |
243 | 243 | ||
244 | extern bool efi_reboot_required(void); | 244 | extern bool efi_reboot_required(void); |
245 | extern bool efi_is_table_address(unsigned long phys_addr); | ||
245 | 246 | ||
246 | #else | 247 | #else |
247 | static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} | 248 | static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {} |
@@ -249,6 +250,10 @@ static inline bool efi_reboot_required(void) | |||
249 | { | 250 | { |
250 | return false; | 251 | return false; |
251 | } | 252 | } |
253 | static inline bool efi_is_table_address(unsigned long phys_addr) | ||
254 | { | ||
255 | return false; | ||
256 | } | ||
252 | #endif /* CONFIG_EFI */ | 257 | #endif /* CONFIG_EFI */ |
253 | 258 | ||
254 | #endif /* _ASM_X86_EFI_H */ | 259 | #endif /* _ASM_X86_EFI_H */ |
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h index e60c45fd3679..6bc6d89d8e2a 100644 --- a/arch/x86/include/asm/uv/uv.h +++ b/arch/x86/include/asm/uv/uv.h | |||
@@ -12,10 +12,12 @@ struct mm_struct; | |||
12 | #ifdef CONFIG_X86_UV | 12 | #ifdef CONFIG_X86_UV |
13 | #include <linux/efi.h> | 13 | #include <linux/efi.h> |
14 | 14 | ||
15 | extern unsigned long uv_systab_phys; | ||
16 | |||
15 | extern enum uv_system_type get_uv_system_type(void); | 17 | extern enum uv_system_type get_uv_system_type(void); |
16 | static inline bool is_early_uv_system(void) | 18 | static inline bool is_early_uv_system(void) |
17 | { | 19 | { |
18 | return !((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || !efi.uv_systab); | 20 | return uv_systab_phys && uv_systab_phys != EFI_INVALID_TABLE_ADDR; |
19 | } | 21 | } |
20 | extern int is_uv_system(void); | 22 | extern int is_uv_system(void); |
21 | extern int is_uv_hubless(void); | 23 | extern int is_uv_hubless(void); |
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 63e99f15d7cf..a39dcdb5ae34 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <asm/set_memory.h> | 20 | #include <asm/set_memory.h> |
21 | #include <asm/e820/api.h> | 21 | #include <asm/e820/api.h> |
22 | #include <asm/efi.h> | ||
22 | #include <asm/fixmap.h> | 23 | #include <asm/fixmap.h> |
23 | #include <asm/pgtable.h> | 24 | #include <asm/pgtable.h> |
24 | #include <asm/tlbflush.h> | 25 | #include <asm/tlbflush.h> |
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index a7189a3b4d70..c202e1b07e29 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c | |||
@@ -59,11 +59,34 @@ static efi_system_table_t efi_systab __initdata; | |||
59 | 59 | ||
60 | static efi_config_table_type_t arch_tables[] __initdata = { | 60 | static efi_config_table_type_t arch_tables[] __initdata = { |
61 | #ifdef CONFIG_X86_UV | 61 | #ifdef CONFIG_X86_UV |
62 | {UV_SYSTEM_TABLE_GUID, "UVsystab", &efi.uv_systab}, | 62 | {UV_SYSTEM_TABLE_GUID, "UVsystab", &uv_systab_phys}, |
63 | #endif | 63 | #endif |
64 | {NULL_GUID, NULL, NULL}, | 64 | {NULL_GUID, NULL, NULL}, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | static const unsigned long * const efi_tables[] = { | ||
68 | &efi.mps, | ||
69 | &efi.acpi, | ||
70 | &efi.acpi20, | ||
71 | &efi.smbios, | ||
72 | &efi.smbios3, | ||
73 | &efi.boot_info, | ||
74 | &efi.hcdp, | ||
75 | &efi.uga, | ||
76 | #ifdef CONFIG_X86_UV | ||
77 | &uv_systab_phys, | ||
78 | #endif | ||
79 | &efi.fw_vendor, | ||
80 | &efi.runtime, | ||
81 | &efi.config_table, | ||
82 | &efi.esrt, | ||
83 | &efi.properties_table, | ||
84 | &efi.mem_attr_table, | ||
85 | #ifdef CONFIG_EFI_RCI2_TABLE | ||
86 | &rci2_table_phys, | ||
87 | #endif | ||
88 | }; | ||
89 | |||
67 | u64 efi_setup; /* efi setup_data physical address */ | 90 | u64 efi_setup; /* efi setup_data physical address */ |
68 | 91 | ||
69 | static int add_efi_memmap __initdata; | 92 | static int add_efi_memmap __initdata; |
@@ -1049,3 +1072,17 @@ static int __init arch_parse_efi_cmdline(char *str) | |||
1049 | return 0; | 1072 | return 0; |
1050 | } | 1073 | } |
1051 | early_param("efi", arch_parse_efi_cmdline); | 1074 | early_param("efi", arch_parse_efi_cmdline); |
1075 | |||
1076 | bool efi_is_table_address(unsigned long phys_addr) | ||
1077 | { | ||
1078 | unsigned int i; | ||
1079 | |||
1080 | if (phys_addr == EFI_INVALID_TABLE_ADDR) | ||
1081 | return false; | ||
1082 | |||
1083 | for (i = 0; i < ARRAY_SIZE(efi_tables); i++) | ||
1084 | if (*(efi_tables[i]) == phys_addr) | ||
1085 | return true; | ||
1086 | |||
1087 | return false; | ||
1088 | } | ||
diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c index 7c69652ffeea..c2ee31953372 100644 --- a/arch/x86/platform/uv/bios_uv.c +++ b/arch/x86/platform/uv/bios_uv.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <asm/uv/bios.h> | 14 | #include <asm/uv/bios.h> |
15 | #include <asm/uv/uv_hub.h> | 15 | #include <asm/uv/uv_hub.h> |
16 | 16 | ||
17 | unsigned long uv_systab_phys __ro_after_init = EFI_INVALID_TABLE_ADDR; | ||
18 | |||
17 | struct uv_systab *uv_systab; | 19 | struct uv_systab *uv_systab; |
18 | 20 | ||
19 | static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, | 21 | static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, |
@@ -185,13 +187,13 @@ EXPORT_SYMBOL_GPL(uv_bios_set_legacy_vga_target); | |||
185 | void uv_bios_init(void) | 187 | void uv_bios_init(void) |
186 | { | 188 | { |
187 | uv_systab = NULL; | 189 | uv_systab = NULL; |
188 | if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) || | 190 | if ((uv_systab_phys == EFI_INVALID_TABLE_ADDR) || |
189 | !efi.uv_systab || efi_runtime_disabled()) { | 191 | !uv_systab_phys || efi_runtime_disabled()) { |
190 | pr_crit("UV: UVsystab: missing\n"); | 192 | pr_crit("UV: UVsystab: missing\n"); |
191 | return; | 193 | return; |
192 | } | 194 | } |
193 | 195 | ||
194 | uv_systab = ioremap(efi.uv_systab, sizeof(struct uv_systab)); | 196 | uv_systab = ioremap(uv_systab_phys, sizeof(struct uv_systab)); |
195 | if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { | 197 | if (!uv_systab || strncmp(uv_systab->signature, UV_SYSTAB_SIG, 4)) { |
196 | pr_err("UV: UVsystab: bad signature!\n"); | 198 | pr_err("UV: UVsystab: bad signature!\n"); |
197 | iounmap(uv_systab); | 199 | iounmap(uv_systab); |
@@ -203,7 +205,7 @@ void uv_bios_init(void) | |||
203 | int size = uv_systab->size; | 205 | int size = uv_systab->size; |
204 | 206 | ||
205 | iounmap(uv_systab); | 207 | iounmap(uv_systab); |
206 | uv_systab = ioremap(efi.uv_systab, size); | 208 | uv_systab = ioremap(uv_systab_phys, size); |
207 | if (!uv_systab) { | 209 | if (!uv_systab) { |
208 | pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); | 210 | pr_err("UV: UVsystab: ioremap(%d) failed!\n", size); |
209 | return; | 211 | return; |
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index d4ea929e8b34..178ee8106828 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig | |||
@@ -180,6 +180,19 @@ config RESET_ATTACK_MITIGATION | |||
180 | have been evicted, since otherwise it will trigger even on clean | 180 | have been evicted, since otherwise it will trigger even on clean |
181 | reboots. | 181 | reboots. |
182 | 182 | ||
183 | config EFI_RCI2_TABLE | ||
184 | bool "EFI Runtime Configuration Interface Table Version 2 Support" | ||
185 | help | ||
186 | Displays the content of the Runtime Configuration Interface | ||
187 | Table version 2 on Dell EMC PowerEdge systems as a binary | ||
188 | attribute 'rci2' under /sys/firmware/efi/tables directory. | ||
189 | |||
190 | RCI2 table contains BIOS HII in XML format and is used to populate | ||
191 | BIOS setup page in Dell EMC OpenManage Server Administrator tool. | ||
192 | The BIOS setup page contains BIOS tokens which can be configured. | ||
193 | |||
194 | Say Y here for Dell EMC PowerEdge systems. | ||
195 | |||
183 | endmenu | 196 | endmenu |
184 | 197 | ||
185 | config UEFI_CPER | 198 | config UEFI_CPER |
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index d2d0d2030620..4ac2de4dfa72 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
@@ -25,6 +25,7 @@ obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o | |||
25 | obj-$(CONFIG_EFI_TEST) += test/ | 25 | obj-$(CONFIG_EFI_TEST) += test/ |
26 | obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o | 26 | obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o |
27 | obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o | 27 | obj-$(CONFIG_APPLE_PROPERTIES) += apple-properties.o |
28 | obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o | ||
28 | 29 | ||
29 | arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o | 30 | arm-obj-$(CONFIG_EFI) := arm-init.o arm-runtime.o |
30 | obj-$(CONFIG_ARM) += $(arm-obj-y) | 31 | obj-$(CONFIG_ARM) += $(arm-obj-y) |
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c index 8fa977c7861f..addf0749dd8b 100644 --- a/drivers/firmware/efi/cper.c +++ b/drivers/firmware/efi/cper.c | |||
@@ -390,6 +390,21 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, | |||
390 | printk( | 390 | printk( |
391 | "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", | 391 | "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", |
392 | pfx, pcie->bridge.secondary_status, pcie->bridge.control); | 392 | pfx, pcie->bridge.secondary_status, pcie->bridge.control); |
393 | |||
394 | /* Fatal errors call __ghes_panic() before AER handler prints this */ | ||
395 | if ((pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) && | ||
396 | (gdata->error_severity & CPER_SEV_FATAL)) { | ||
397 | struct aer_capability_regs *aer; | ||
398 | |||
399 | aer = (struct aer_capability_regs *)pcie->aer_info; | ||
400 | printk("%saer_uncor_status: 0x%08x, aer_uncor_mask: 0x%08x\n", | ||
401 | pfx, aer->uncor_status, aer->uncor_mask); | ||
402 | printk("%saer_uncor_severity: 0x%08x\n", | ||
403 | pfx, aer->uncor_severity); | ||
404 | printk("%sTLP Header: %08x %08x %08x %08x\n", pfx, | ||
405 | aer->header_log.dw0, aer->header_log.dw1, | ||
406 | aer->header_log.dw2, aer->header_log.dw3); | ||
407 | } | ||
393 | } | 408 | } |
394 | 409 | ||
395 | static void cper_print_tstamp(const char *pfx, | 410 | static void cper_print_tstamp(const char *pfx, |
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index ad3b1f4866b3..8f1ab04f6743 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -39,11 +39,9 @@ struct efi __read_mostly efi = { | |||
39 | .acpi20 = EFI_INVALID_TABLE_ADDR, | 39 | .acpi20 = EFI_INVALID_TABLE_ADDR, |
40 | .smbios = EFI_INVALID_TABLE_ADDR, | 40 | .smbios = EFI_INVALID_TABLE_ADDR, |
41 | .smbios3 = EFI_INVALID_TABLE_ADDR, | 41 | .smbios3 = EFI_INVALID_TABLE_ADDR, |
42 | .sal_systab = EFI_INVALID_TABLE_ADDR, | ||
43 | .boot_info = EFI_INVALID_TABLE_ADDR, | 42 | .boot_info = EFI_INVALID_TABLE_ADDR, |
44 | .hcdp = EFI_INVALID_TABLE_ADDR, | 43 | .hcdp = EFI_INVALID_TABLE_ADDR, |
45 | .uga = EFI_INVALID_TABLE_ADDR, | 44 | .uga = EFI_INVALID_TABLE_ADDR, |
46 | .uv_systab = EFI_INVALID_TABLE_ADDR, | ||
47 | .fw_vendor = EFI_INVALID_TABLE_ADDR, | 45 | .fw_vendor = EFI_INVALID_TABLE_ADDR, |
48 | .runtime = EFI_INVALID_TABLE_ADDR, | 46 | .runtime = EFI_INVALID_TABLE_ADDR, |
49 | .config_table = EFI_INVALID_TABLE_ADDR, | 47 | .config_table = EFI_INVALID_TABLE_ADDR, |
@@ -57,25 +55,6 @@ struct efi __read_mostly efi = { | |||
57 | }; | 55 | }; |
58 | EXPORT_SYMBOL(efi); | 56 | EXPORT_SYMBOL(efi); |
59 | 57 | ||
60 | static unsigned long *efi_tables[] = { | ||
61 | &efi.mps, | ||
62 | &efi.acpi, | ||
63 | &efi.acpi20, | ||
64 | &efi.smbios, | ||
65 | &efi.smbios3, | ||
66 | &efi.sal_systab, | ||
67 | &efi.boot_info, | ||
68 | &efi.hcdp, | ||
69 | &efi.uga, | ||
70 | &efi.uv_systab, | ||
71 | &efi.fw_vendor, | ||
72 | &efi.runtime, | ||
73 | &efi.config_table, | ||
74 | &efi.esrt, | ||
75 | &efi.properties_table, | ||
76 | &efi.mem_attr_table, | ||
77 | }; | ||
78 | |||
79 | struct mm_struct efi_mm = { | 58 | struct mm_struct efi_mm = { |
80 | .mm_rb = RB_ROOT, | 59 | .mm_rb = RB_ROOT, |
81 | .mm_users = ATOMIC_INIT(2), | 60 | .mm_users = ATOMIC_INIT(2), |
@@ -476,7 +455,6 @@ static __initdata efi_config_table_type_t common_tables[] = { | |||
476 | {ACPI_TABLE_GUID, "ACPI", &efi.acpi}, | 455 | {ACPI_TABLE_GUID, "ACPI", &efi.acpi}, |
477 | {HCDP_TABLE_GUID, "HCDP", &efi.hcdp}, | 456 | {HCDP_TABLE_GUID, "HCDP", &efi.hcdp}, |
478 | {MPS_TABLE_GUID, "MPS", &efi.mps}, | 457 | {MPS_TABLE_GUID, "MPS", &efi.mps}, |
479 | {SAL_SYSTEM_TABLE_GUID, "SALsystab", &efi.sal_systab}, | ||
480 | {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, | 458 | {SMBIOS_TABLE_GUID, "SMBIOS", &efi.smbios}, |
481 | {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, | 459 | {SMBIOS3_TABLE_GUID, "SMBIOS 3.0", &efi.smbios3}, |
482 | {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, | 460 | {UGA_IO_PROTOCOL_GUID, "UGA", &efi.uga}, |
@@ -487,6 +465,9 @@ static __initdata efi_config_table_type_t common_tables[] = { | |||
487 | {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log}, | 465 | {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log}, |
488 | {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log}, | 466 | {LINUX_EFI_TPM_FINAL_LOG_GUID, "TPMFinalLog", &efi.tpm_final_log}, |
489 | {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve}, | 467 | {LINUX_EFI_MEMRESERVE_TABLE_GUID, "MEMRESERVE", &efi.mem_reserve}, |
468 | #ifdef CONFIG_EFI_RCI2_TABLE | ||
469 | {DELLEMC_EFI_RCI2_TABLE_GUID, NULL, &rci2_table_phys}, | ||
470 | #endif | ||
490 | {NULL_GUID, NULL, NULL}, | 471 | {NULL_GUID, NULL, NULL}, |
491 | }; | 472 | }; |
492 | 473 | ||
@@ -964,20 +945,6 @@ int efi_status_to_err(efi_status_t status) | |||
964 | return err; | 945 | return err; |
965 | } | 946 | } |
966 | 947 | ||
967 | bool efi_is_table_address(unsigned long phys_addr) | ||
968 | { | ||
969 | unsigned int i; | ||
970 | |||
971 | if (phys_addr == EFI_INVALID_TABLE_ADDR) | ||
972 | return false; | ||
973 | |||
974 | for (i = 0; i < ARRAY_SIZE(efi_tables); i++) | ||
975 | if (*(efi_tables[i]) == phys_addr) | ||
976 | return true; | ||
977 | |||
978 | return false; | ||
979 | } | ||
980 | |||
981 | static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); | 948 | static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); |
982 | static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init; | 949 | static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init; |
983 | 950 | ||
diff --git a/drivers/firmware/efi/rci2-table.c b/drivers/firmware/efi/rci2-table.c new file mode 100644 index 000000000000..3e290f96620a --- /dev/null +++ b/drivers/firmware/efi/rci2-table.c | |||
@@ -0,0 +1,147 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Export Runtime Configuration Interface Table Version 2 (RCI2) | ||
4 | * to sysfs | ||
5 | * | ||
6 | * Copyright (C) 2019 Dell Inc | ||
7 | * by Narendra K <Narendra.K@dell.com> | ||
8 | * | ||
9 | * System firmware advertises the address of the RCI2 Table via | ||
10 | * an EFI Configuration Table entry. This code retrieves the RCI2 | ||
11 | * table from the address and exports it to sysfs as a binary | ||
12 | * attribute 'rci2' under /sys/firmware/efi/tables directory. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kobject.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/sysfs.h> | ||
18 | #include <linux/efi.h> | ||
19 | #include <linux/types.h> | ||
20 | #include <linux/io.h> | ||
21 | |||
22 | #define RCI_SIGNATURE "_RC_" | ||
23 | |||
24 | struct rci2_table_global_hdr { | ||
25 | u16 type; | ||
26 | u16 resvd0; | ||
27 | u16 hdr_len; | ||
28 | u8 rci2_sig[4]; | ||
29 | u16 resvd1; | ||
30 | u32 resvd2; | ||
31 | u32 resvd3; | ||
32 | u8 major_rev; | ||
33 | u8 minor_rev; | ||
34 | u16 num_of_structs; | ||
35 | u32 rci2_len; | ||
36 | u16 rci2_chksum; | ||
37 | } __packed; | ||
38 | |||
39 | static u8 *rci2_base; | ||
40 | static u32 rci2_table_len; | ||
41 | unsigned long rci2_table_phys __ro_after_init = EFI_INVALID_TABLE_ADDR; | ||
42 | |||
43 | static ssize_t raw_table_read(struct file *file, struct kobject *kobj, | ||
44 | struct bin_attribute *attr, char *buf, | ||
45 | loff_t pos, size_t count) | ||
46 | { | ||
47 | memcpy(buf, attr->private + pos, count); | ||
48 | return count; | ||
49 | } | ||
50 | |||
51 | static BIN_ATTR(rci2, S_IRUSR, raw_table_read, NULL, 0); | ||
52 | |||
53 | static u16 checksum(void) | ||
54 | { | ||
55 | u8 len_is_odd = rci2_table_len % 2; | ||
56 | u32 chksum_len = rci2_table_len; | ||
57 | u16 *base = (u16 *)rci2_base; | ||
58 | u8 buf[2] = {0}; | ||
59 | u32 offset = 0; | ||
60 | u16 chksum = 0; | ||
61 | |||
62 | if (len_is_odd) | ||
63 | chksum_len -= 1; | ||
64 | |||
65 | while (offset < chksum_len) { | ||
66 | chksum += *base; | ||
67 | offset += 2; | ||
68 | base++; | ||
69 | } | ||
70 | |||
71 | if (len_is_odd) { | ||
72 | buf[0] = *(u8 *)base; | ||
73 | chksum += *(u16 *)(buf); | ||
74 | } | ||
75 | |||
76 | return chksum; | ||
77 | } | ||
78 | |||
79 | int __init efi_rci2_sysfs_init(void) | ||
80 | { | ||
81 | struct kobject *tables_kobj; | ||
82 | int ret = -ENOMEM; | ||
83 | |||
84 | rci2_base = memremap(rci2_table_phys, | ||
85 | sizeof(struct rci2_table_global_hdr), | ||
86 | MEMREMAP_WB); | ||
87 | if (!rci2_base) { | ||
88 | pr_debug("RCI2 table init failed - could not map RCI2 table\n"); | ||
89 | goto err; | ||
90 | } | ||
91 | |||
92 | if (strncmp(rci2_base + | ||
93 | offsetof(struct rci2_table_global_hdr, rci2_sig), | ||
94 | RCI_SIGNATURE, 4)) { | ||
95 | pr_debug("RCI2 table init failed - incorrect signature\n"); | ||
96 | ret = -ENODEV; | ||
97 | goto err_unmap; | ||
98 | } | ||
99 | |||
100 | rci2_table_len = *(u32 *)(rci2_base + | ||
101 | offsetof(struct rci2_table_global_hdr, | ||
102 | rci2_len)); | ||
103 | |||
104 | memunmap(rci2_base); | ||
105 | |||
106 | if (!rci2_table_len) { | ||
107 | pr_debug("RCI2 table init failed - incorrect table length\n"); | ||
108 | goto err; | ||
109 | } | ||
110 | |||
111 | rci2_base = memremap(rci2_table_phys, rci2_table_len, MEMREMAP_WB); | ||
112 | if (!rci2_base) { | ||
113 | pr_debug("RCI2 table - could not map RCI2 table\n"); | ||
114 | goto err; | ||
115 | } | ||
116 | |||
117 | if (checksum() != 0) { | ||
118 | pr_debug("RCI2 table - incorrect checksum\n"); | ||
119 | ret = -ENODEV; | ||
120 | goto err_unmap; | ||
121 | } | ||
122 | |||
123 | tables_kobj = kobject_create_and_add("tables", efi_kobj); | ||
124 | if (!tables_kobj) { | ||
125 | pr_debug("RCI2 table - tables_kobj creation failed\n"); | ||
126 | goto err_unmap; | ||
127 | } | ||
128 | |||
129 | bin_attr_rci2.size = rci2_table_len; | ||
130 | bin_attr_rci2.private = rci2_base; | ||
131 | ret = sysfs_create_bin_file(tables_kobj, &bin_attr_rci2); | ||
132 | if (ret != 0) { | ||
133 | pr_debug("RCI2 table - rci2 sysfs bin file creation failed\n"); | ||
134 | kobject_del(tables_kobj); | ||
135 | kobject_put(tables_kobj); | ||
136 | goto err_unmap; | ||
137 | } | ||
138 | |||
139 | return 0; | ||
140 | |||
141 | err_unmap: | ||
142 | memunmap(rci2_base); | ||
143 | err: | ||
144 | pr_debug("RCI2 table - sysfs initialization failed\n"); | ||
145 | return ret; | ||
146 | } | ||
147 | late_initcall(efi_rci2_sysfs_init); | ||
diff --git a/include/linux/efi.h b/include/linux/efi.h index f87fabea4a85..bd3837022307 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -692,6 +692,9 @@ void efi_native_runtime_setup(void); | |||
692 | #define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) | 692 | #define LINUX_EFI_TPM_FINAL_LOG_GUID EFI_GUID(0x1e2ed096, 0x30e2, 0x4254, 0xbd, 0x89, 0x86, 0x3b, 0xbe, 0xf8, 0x23, 0x25) |
693 | #define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2) | 693 | #define LINUX_EFI_MEMRESERVE_TABLE_GUID EFI_GUID(0x888eb0c6, 0x8ede, 0x4ff5, 0xa8, 0xf0, 0x9a, 0xee, 0x5c, 0xb9, 0x77, 0xc2) |
694 | 694 | ||
695 | /* OEM GUIDs */ | ||
696 | #define DELLEMC_EFI_RCI2_TABLE_GUID EFI_GUID(0x2d9f28a2, 0xa886, 0x456a, 0x97, 0xa8, 0xf1, 0x1e, 0xf2, 0x4f, 0xf4, 0x55) | ||
697 | |||
695 | typedef struct { | 698 | typedef struct { |
696 | efi_guid_t guid; | 699 | efi_guid_t guid; |
697 | u64 table; | 700 | u64 table; |
@@ -984,11 +987,9 @@ extern struct efi { | |||
984 | unsigned long acpi20; /* ACPI table (ACPI 2.0) */ | 987 | unsigned long acpi20; /* ACPI table (ACPI 2.0) */ |
985 | unsigned long smbios; /* SMBIOS table (32 bit entry point) */ | 988 | unsigned long smbios; /* SMBIOS table (32 bit entry point) */ |
986 | unsigned long smbios3; /* SMBIOS table (64 bit entry point) */ | 989 | unsigned long smbios3; /* SMBIOS table (64 bit entry point) */ |
987 | unsigned long sal_systab; /* SAL system table */ | ||
988 | unsigned long boot_info; /* boot info table */ | 990 | unsigned long boot_info; /* boot info table */ |
989 | unsigned long hcdp; /* HCDP table */ | 991 | unsigned long hcdp; /* HCDP table */ |
990 | unsigned long uga; /* UGA table */ | 992 | unsigned long uga; /* UGA table */ |
991 | unsigned long uv_systab; /* UV system table */ | ||
992 | unsigned long fw_vendor; /* fw_vendor */ | 993 | unsigned long fw_vendor; /* fw_vendor */ |
993 | unsigned long runtime; /* runtime table */ | 994 | unsigned long runtime; /* runtime table */ |
994 | unsigned long config_table; /* config tables */ | 995 | unsigned long config_table; /* config tables */ |
@@ -1211,8 +1212,6 @@ static inline bool efi_enabled(int feature) | |||
1211 | return test_bit(feature, &efi.flags) != 0; | 1212 | return test_bit(feature, &efi.flags) != 0; |
1212 | } | 1213 | } |
1213 | extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused); | 1214 | extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused); |
1214 | |||
1215 | extern bool efi_is_table_address(unsigned long phys_addr); | ||
1216 | #else | 1215 | #else |
1217 | static inline bool efi_enabled(int feature) | 1216 | static inline bool efi_enabled(int feature) |
1218 | { | 1217 | { |
@@ -1226,11 +1225,6 @@ efi_capsule_pending(int *reset_type) | |||
1226 | { | 1225 | { |
1227 | return false; | 1226 | return false; |
1228 | } | 1227 | } |
1229 | |||
1230 | static inline bool efi_is_table_address(unsigned long phys_addr) | ||
1231 | { | ||
1232 | return false; | ||
1233 | } | ||
1234 | #endif | 1228 | #endif |
1235 | 1229 | ||
1236 | extern int efi_status_to_err(efi_status_t status); | 1230 | extern int efi_status_to_err(efi_status_t status); |
@@ -1722,6 +1716,8 @@ struct efi_tcg2_final_events_table { | |||
1722 | }; | 1716 | }; |
1723 | extern int efi_tpm_final_log_size; | 1717 | extern int efi_tpm_final_log_size; |
1724 | 1718 | ||
1719 | extern unsigned long rci2_table_phys; | ||
1720 | |||
1725 | /* | 1721 | /* |
1726 | * efi_runtime_service() function identifiers. | 1722 | * efi_runtime_service() function identifiers. |
1727 | * "NONE" is used by efi_recover_from_page_fault() to check if the page | 1723 | * "NONE" is used by efi_recover_from_page_fault() to check if the page |