x86/compressed/acpi: Move EFI detection to helper
authorMichael Roth <michael.roth@amd.com>
Wed, 9 Feb 2022 18:10:18 +0000 (12:10 -0600)
committerBorislav Petkov <bp@suse.de>
Wed, 6 Apr 2022 15:07:02 +0000 (17:07 +0200)
Future patches for SEV-SNP-validated CPUID will also require early
parsing of the EFI configuration. Incrementally move the related code
into a set of helpers that can be re-used for that purpose.

First, carve out the functionality which determines the EFI environment
type the machine is booting on.

  [ bp: Massage commit message. ]

Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: https://lore.kernel.org/r/20220307213356.2797205-25-brijesh.singh@amd.com
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/acpi.c
arch/x86/boot/compressed/efi.c [new file with mode: 0644]
arch/x86/boot/compressed/misc.h

index 6115274..e69c3d2 100644 (file)
@@ -103,6 +103,7 @@ endif
 vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
 
 vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
+vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
 efi-obj-$(CONFIG_EFI_STUB) = $(objtree)/drivers/firmware/efi/libstub/lib.a
 
 $(obj)/vmlinux: $(vmlinux-objs-y) $(efi-obj-y) FORCE
index 8bcbcee..db6c561 100644 (file)
@@ -87,7 +87,7 @@ static acpi_physical_address kexec_get_rsdp_addr(void)
        efi_system_table_64_t *systab;
        struct efi_setup_data *esd;
        struct efi_info *ei;
-       char *sig;
+       enum efi_type et;
 
        esd = (struct efi_setup_data *)get_kexec_setup_data_addr();
        if (!esd)
@@ -98,10 +98,9 @@ static acpi_physical_address kexec_get_rsdp_addr(void)
                return 0;
        }
 
-       ei = &boot_params->efi_info;
-       sig = (char *)&ei->efi_loader_signature;
-       if (strncmp(sig, EFI64_LOADER_SIGNATURE, 4)) {
-               debug_putstr("Wrong kexec EFI loader signature.\n");
+       et = efi_get_type(boot_params);
+       if (et != EFI_TYPE_64) {
+               debug_putstr("Unexpected kexec EFI environment (expected 64-bit EFI).\n");
                return 0;
        }
 
@@ -122,29 +121,22 @@ static acpi_physical_address efi_get_rsdp_addr(void)
        unsigned long systab, config_tables;
        unsigned int nr_tables;
        struct efi_info *ei;
+       enum efi_type et;
        bool efi_64;
-       char *sig;
-
-       ei = &boot_params->efi_info;
-       sig = (char *)&ei->efi_loader_signature;
 
-       if (!strncmp(sig, EFI64_LOADER_SIGNATURE, 4)) {
+       et = efi_get_type(boot_params);
+       if (et == EFI_TYPE_64)
                efi_64 = true;
-       } else if (!strncmp(sig, EFI32_LOADER_SIGNATURE, 4)) {
+       else if (et == EFI_TYPE_32)
                efi_64 = false;
-       } else {
-               debug_putstr("Wrong EFI loader signature.\n");
+       else
                return 0;
-       }
 
        /* Get systab from boot params. */
+       ei = &boot_params->efi_info;
 #ifdef CONFIG_X86_64
        systab = ei->efi_systab | ((__u64)ei->efi_systab_hi << 32);
 #else
-       if (ei->efi_systab_hi || ei->efi_memmap_hi) {
-               debug_putstr("Error getting RSDP address: EFI system table located above 4GB.\n");
-               return 0;
-       }
        systab = ei->efi_systab;
 #endif
        if (!systab)
diff --git a/arch/x86/boot/compressed/efi.c b/arch/x86/boot/compressed/efi.c
new file mode 100644 (file)
index 0000000..bad0ce3
--- /dev/null
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Helpers for early access to EFI configuration table.
+ *
+ * Originally derived from arch/x86/boot/compressed/acpi.c
+ */
+
+#include "misc.h"
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+/**
+ * efi_get_type - Given a pointer to boot_params, determine the type of EFI environment.
+ *
+ * @bp:         pointer to boot_params
+ *
+ * Return: EFI_TYPE_{32,64} for valid EFI environments, EFI_TYPE_NONE otherwise.
+ */
+enum efi_type efi_get_type(struct boot_params *bp)
+{
+       struct efi_info *ei;
+       enum efi_type et;
+       const char *sig;
+
+       ei = &bp->efi_info;
+       sig = (char *)&ei->efi_loader_signature;
+
+       if (!strncmp(sig, EFI64_LOADER_SIGNATURE, 4)) {
+               et = EFI_TYPE_64;
+       } else if (!strncmp(sig, EFI32_LOADER_SIGNATURE, 4)) {
+               et = EFI_TYPE_32;
+       } else {
+               debug_putstr("No EFI environment detected.\n");
+               et = EFI_TYPE_NONE;
+       }
+
+#ifndef CONFIG_X86_64
+       /*
+        * Existing callers like acpi.c treat this case as an indicator to
+        * fall-through to non-EFI, rather than an error, so maintain that
+        * functionality here as well.
+        */
+       if (ei->efi_systab_hi || ei->efi_memmap_hi) {
+               debug_putstr("EFI system table is located above 4GB and cannot be accessed.\n");
+               et = EFI_TYPE_NONE;
+       }
+#endif
+
+       return et;
+}
index 01cc13c..fede1af 100644 (file)
@@ -176,4 +176,20 @@ void boot_stage2_vc(void);
 
 unsigned long sev_verify_cbit(unsigned long cr3);
 
+enum efi_type {
+       EFI_TYPE_64,
+       EFI_TYPE_32,
+       EFI_TYPE_NONE,
+};
+
+#ifdef CONFIG_EFI
+/* helpers for early EFI config table access */
+enum efi_type efi_get_type(struct boot_params *bp);
+#else
+static inline enum efi_type efi_get_type(struct boot_params *bp)
+{
+       return EFI_TYPE_NONE;
+}
+#endif /* CONFIG_EFI */
+
 #endif /* BOOT_COMPRESSED_MISC_H */