Merge tag 'efi-next-for-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Jan 2022 23:36:30 +0000 (15:36 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 11 Jan 2022 23:36:30 +0000 (15:36 -0800)
Pull EFI updates from Ard Biesheuvel:

 - support taking the measurement of the initrd when loaded via the
   LoadFile2 protocol

 - kobject API cleanup from Greg

 - some header file whitespace fixes

* tag 'efi-next-for-v5.17' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi:
  efi: use default_groups in kobj_type
  efi/libstub: measure loaded initrd info into the TPM
  efi/libstub: consolidate initrd handling across architectures
  efi/libstub: x86/mixed: increase supported argument count
  efi/libstub: add prototype of efi_tcg2_protocol::hash_log_extend_event()
  include/linux/efi.h: Remove unneeded whitespaces before tabs

arch/x86/boot/compressed/efi_thunk_64.S
arch/x86/include/asm/efi.h
arch/x86/platform/efi/efi_thunk_64.S
drivers/firmware/efi/efivars.c
drivers/firmware/efi/esrt.c
drivers/firmware/efi/libstub/efi-stub-helper.c
drivers/firmware/efi/libstub/efi-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/x86-stub.c
drivers/firmware/efi/runtime-map.c
include/linux/efi.h

index 8bb92e9..d05f781 100644 (file)
@@ -26,8 +26,6 @@ SYM_FUNC_START(__efi64_thunk)
        push    %rbp
        push    %rbx
 
-       leaq    1f(%rip), %rbp
-
        movl    %ds, %eax
        push    %rax
        movl    %es, %eax
@@ -35,6 +33,11 @@ SYM_FUNC_START(__efi64_thunk)
        movl    %ss, %eax
        push    %rax
 
+       /* Copy args passed on stack */
+       movq    0x30(%rsp), %rbp
+       movq    0x38(%rsp), %rbx
+       movq    0x40(%rsp), %rax
+
        /*
         * Convert x86-64 ABI params to i386 ABI
         */
@@ -44,13 +47,18 @@ SYM_FUNC_START(__efi64_thunk)
        movl    %ecx, 0x8(%rsp)
        movl    %r8d, 0xc(%rsp)
        movl    %r9d, 0x10(%rsp)
+       movl    %ebp, 0x14(%rsp)
+       movl    %ebx, 0x18(%rsp)
+       movl    %eax, 0x1c(%rsp)
 
-       leaq    0x14(%rsp), %rbx
+       leaq    0x20(%rsp), %rbx
        sgdt    (%rbx)
 
        addq    $16, %rbx
        sidt    (%rbx)
 
+       leaq    1f(%rip), %rbp
+
        /*
         * Switch to IDT and GDT with 32-bit segments. This is the firmware GDT
         * and IDT that was installed when the kernel started executing. The
index 63158fd..03cb127 100644 (file)
@@ -46,13 +46,14 @@ extern unsigned long efi_mixed_mode_stack_pa;
 
 #define __efi_nargs(...) __efi_nargs_(__VA_ARGS__)
 #define __efi_nargs_(...) __efi_nargs__(0, ##__VA_ARGS__,      \
+       __efi_arg_sentinel(9), __efi_arg_sentinel(8),           \
        __efi_arg_sentinel(7), __efi_arg_sentinel(6),           \
        __efi_arg_sentinel(5), __efi_arg_sentinel(4),           \
        __efi_arg_sentinel(3), __efi_arg_sentinel(2),           \
        __efi_arg_sentinel(1), __efi_arg_sentinel(0))
-#define __efi_nargs__(_0, _1, _2, _3, _4, _5, _6, _7, n, ...)  \
+#define __efi_nargs__(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, n, ...)  \
        __take_second_arg(n,                                    \
-               ({ BUILD_BUG_ON_MSG(1, "__efi_nargs limit exceeded"); 8; }))
+               ({ BUILD_BUG_ON_MSG(1, "__efi_nargs limit exceeded"); 10; }))
 #define __efi_arg_sentinel(n) , n
 
 /*
@@ -176,8 +177,9 @@ extern u64 efi_setup;
 extern efi_status_t __efi64_thunk(u32, ...);
 
 #define efi64_thunk(...) ({                                            \
-       __efi_nargs_check(efi64_thunk, 6, __VA_ARGS__);                 \
-       __efi64_thunk(__VA_ARGS__);                                     \
+       u64 __pad[3]; /* must have space for 3 args on the stack */     \
+       __efi_nargs_check(efi64_thunk, 9, __VA_ARGS__);                 \
+       __efi64_thunk(__VA_ARGS__, __pad);                              \
 })
 
 static inline bool efi_is_mixed(void)
@@ -306,6 +308,10 @@ static inline u32 efi64_convert_status(efi_status_t status)
 #define __efi64_argmap_query_mode(gop, mode, size, info)               \
        ((gop), (mode), efi64_zero_upper(size), efi64_zero_upper(info))
 
+/* TCG2 protocol */
+#define __efi64_argmap_hash_log_extend_event(prot, fl, addr, size, ev) \
+       ((prot), (fl), 0ULL, (u64)(addr), 0ULL, (u64)(size), 0ULL, ev)
+
 /*
  * The macros below handle the plumbing for the argument mapping. To add a
  * mapping for a specific EFI method, simply define a macro
index fd3dd17..5b7c6e0 100644 (file)
@@ -36,6 +36,17 @@ SYM_CODE_START(__efi64_thunk)
        movq    efi_mixed_mode_stack_pa(%rip), %rsp
        push    %rax
 
+       /*
+        * Copy args passed via the stack
+        */
+       subq    $0x24, %rsp
+       movq    0x18(%rax), %rbp
+       movq    0x20(%rax), %rbx
+       movq    0x28(%rax), %rax
+       movl    %ebp, 0x18(%rsp)
+       movl    %ebx, 0x1c(%rsp)
+       movl    %eax, 0x20(%rsp)
+
        /*
         * Calculate the physical address of the kernel text.
         */
@@ -47,7 +58,6 @@ SYM_CODE_START(__efi64_thunk)
        subq    %rax, %rbp
        subq    %rax, %rbx
 
-       subq    $28, %rsp
        movl    %ebx, 0x0(%rsp)         /* return address */
        movl    %esi, 0x4(%rsp)
        movl    %edx, 0x8(%rsp)
@@ -60,7 +70,7 @@ SYM_CODE_START(__efi64_thunk)
        pushq   %rdi                    /* EFI runtime service address */
        lretq
 
-1:     movq    24(%rsp), %rsp
+1:     movq    0x20(%rsp), %rsp
        pop     %rbx
        pop     %rbp
        retq
index e6b16b3..ea0bc39 100644 (file)
@@ -352,11 +352,12 @@ static struct attribute *def_attrs[] = {
        &efivar_attr_raw_var.attr,
        NULL,
 };
+ATTRIBUTE_GROUPS(def);
 
 static struct kobj_type efivar_ktype = {
        .release = efivar_release,
        .sysfs_ops = &efivar_attr_ops,
-       .default_attrs = def_attrs,
+       .default_groups = def_groups,
 };
 
 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
index d591527..2a2f52b 100644 (file)
@@ -146,6 +146,8 @@ static struct attribute *esre1_attrs[] = {
        &esre_last_attempt_status.attr,
        NULL
 };
+ATTRIBUTE_GROUPS(esre1);
+
 static void esre_release(struct kobject *kobj)
 {
        struct esre_entry *entry = to_entry(kobj);
@@ -157,7 +159,7 @@ static void esre_release(struct kobject *kobj)
 static struct kobj_type esre1_ktype = {
        .release = esre_release,
        .sysfs_ops = &esre_attr_ops,
-       .default_attrs = esre1_attrs,
+       .default_groups = esre1_groups,
 };
 
 
index d489bdc..3d97206 100644 (file)
 
 bool efi_nochunk;
 bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
-bool efi_noinitrd;
 int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
 bool efi_novamap;
 
+static bool efi_noinitrd;
 static bool efi_nosoftreserve;
 static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
 
@@ -625,6 +625,47 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
                                    load_addr, load_size);
 }
 
+static const struct {
+       efi_tcg2_event_t        event_data;
+       efi_tcg2_tagged_event_t tagged_event;
+       u8                      tagged_event_data[];
+} initrd_tcg2_event = {
+       {
+               sizeof(initrd_tcg2_event) + sizeof("Linux initrd"),
+               {
+                       sizeof(initrd_tcg2_event.event_data.event_header),
+                       EFI_TCG2_EVENT_HEADER_VERSION,
+                       9,
+                       EV_EVENT_TAG,
+               },
+       },
+       {
+               INITRD_EVENT_TAG_ID,
+               sizeof("Linux initrd"),
+       },
+       { "Linux initrd" },
+};
+
+static void efi_measure_initrd(unsigned long load_addr, unsigned long load_size)
+{
+       efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
+       efi_tcg2_protocol_t *tcg2 = NULL;
+       efi_status_t status;
+
+       efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2);
+       if (tcg2) {
+               status = efi_call_proto(tcg2, hash_log_extend_event,
+                                       0, load_addr, load_size,
+                                       &initrd_tcg2_event.event_data);
+               if (status != EFI_SUCCESS)
+                       efi_warn("Failed to measure initrd data: 0x%lx\n",
+                                status);
+               else
+                       efi_info("Measured initrd data into PCR %d\n",
+                                initrd_tcg2_event.event_data.event_header.pcr_index);
+       }
+}
+
 /**
  * efi_load_initrd() - Load initial RAM disk
  * @image:     EFI loaded image protocol
@@ -643,17 +684,25 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
 {
        efi_status_t status;
 
-       if (!load_addr || !load_size)
-               return EFI_INVALID_PARAMETER;
-
-       status = efi_load_initrd_dev_path(load_addr, load_size, hard_limit);
-       if (status == EFI_SUCCESS) {
-               efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
-       } else if (status == EFI_NOT_FOUND) {
-               status = efi_load_initrd_cmdline(image, load_addr, load_size,
-                                                soft_limit, hard_limit);
-               if (status == EFI_SUCCESS && *load_size > 0)
-                       efi_info("Loaded initrd from command line option\n");
+       if (efi_noinitrd) {
+               *load_addr = *load_size = 0;
+               status = EFI_SUCCESS;
+       } else {
+               status = efi_load_initrd_dev_path(load_addr, load_size, hard_limit);
+               if (status == EFI_SUCCESS) {
+                       efi_info("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
+                       if (*load_size > 0)
+                               efi_measure_initrd(*load_addr, *load_size);
+               } else if (status == EFI_NOT_FOUND) {
+                       status = efi_load_initrd_cmdline(image, load_addr, load_size,
+                                                        soft_limit, hard_limit);
+                       if (status == EFI_SUCCESS && *load_size > 0)
+                               efi_info("Loaded initrd from command line option\n");
+               }
+               if (status != EFI_SUCCESS) {
+                       efi_err("Failed to load initrd: 0x%lx\n", status);
+                       *load_addr = *load_size = 0;
+               }
        }
 
        return status;
index 26e6978..e87e7f1 100644 (file)
@@ -134,7 +134,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        enum efi_secureboot_mode secure_boot;
        struct screen_info *si;
        efi_properties_table_t *prop_tbl;
-       unsigned long max_addr;
 
        efi_system_table = sys_table_arg;
 
@@ -240,13 +239,8 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
        if (!fdt_addr)
                efi_info("Generating empty DTB\n");
 
-       if (!efi_noinitrd) {
-               max_addr = efi_get_max_initrd_addr(image_addr);
-               status = efi_load_initrd(image, &initrd_addr, &initrd_size,
-                                        ULONG_MAX, max_addr);
-               if (status != EFI_SUCCESS)
-                       efi_err("Failed to load initrd!\n");
-       }
+       efi_load_initrd(image, &initrd_addr, &initrd_size, ULONG_MAX,
+                       efi_get_max_initrd_addr(image_addr));
 
        efi_random_get_seed();
 
index cde0a2e..edb77b0 100644 (file)
@@ -31,7 +31,6 @@
 
 extern bool efi_nochunk;
 extern bool efi_nokaslr;
-extern bool efi_noinitrd;
 extern int efi_loglevel;
 extern bool efi_novamap;
 
@@ -667,6 +666,29 @@ union apple_properties_protocol {
 
 typedef u32 efi_tcg2_event_log_format;
 
+#define INITRD_EVENT_TAG_ID 0x8F3B22ECU
+#define EV_EVENT_TAG 0x00000006U
+#define EFI_TCG2_EVENT_HEADER_VERSION  0x1
+
+struct efi_tcg2_event {
+       u32             event_size;
+       struct {
+               u32     header_size;
+               u16     header_version;
+               u32     pcr_index;
+               u32     event_type;
+       } __packed event_header;
+       /* u8[] event follows here */
+} __packed;
+
+struct efi_tcg2_tagged_event {
+       u32 tagged_event_id;
+       u32 tagged_event_data_size;
+       /* u8  tagged event data follows here */
+} __packed;
+
+typedef struct efi_tcg2_event efi_tcg2_event_t;
+typedef struct efi_tcg2_tagged_event efi_tcg2_tagged_event_t;
 typedef union efi_tcg2_protocol efi_tcg2_protocol_t;
 
 union efi_tcg2_protocol {
@@ -677,7 +699,11 @@ union efi_tcg2_protocol {
                                                       efi_physical_addr_t *,
                                                       efi_physical_addr_t *,
                                                       efi_bool_t *);
-               void *hash_log_extend_event;
+               efi_status_t (__efiapi *hash_log_extend_event)(efi_tcg2_protocol_t *,
+                                                              u64,
+                                                              efi_physical_addr_t,
+                                                              u64,
+                                                              const efi_tcg2_event_t *);
                void *submit_command;
                void *get_active_pcr_banks;
                void *set_active_pcr_banks;
index f14c4ff..01ddd45 100644 (file)
@@ -673,6 +673,7 @@ unsigned long efi_main(efi_handle_t handle,
        unsigned long bzimage_addr = (unsigned long)startup_32;
        unsigned long buffer_start, buffer_end;
        struct setup_header *hdr = &boot_params->hdr;
+       unsigned long addr, size;
        efi_status_t status;
 
        efi_system_table = sys_table_arg;
@@ -761,22 +762,15 @@ unsigned long efi_main(efi_handle_t handle,
         * arguments will be processed only if image is not NULL, which will be
         * the case only if we were loaded via the PE entry point.
         */
-       if (!efi_noinitrd) {
-               unsigned long addr, size;
-
-               status = efi_load_initrd(image, &addr, &size,
-                                        hdr->initrd_addr_max, ULONG_MAX);
-
-               if (status != EFI_SUCCESS) {
-                       efi_err("Failed to load initrd!\n");
-                       goto fail;
-               }
-               if (size > 0) {
-                       efi_set_u64_split(addr, &hdr->ramdisk_image,
-                                         &boot_params->ext_ramdisk_image);
-                       efi_set_u64_split(size, &hdr->ramdisk_size,
-                                         &boot_params->ext_ramdisk_size);
-               }
+       status = efi_load_initrd(image, &addr, &size, hdr->initrd_addr_max,
+                                ULONG_MAX);
+       if (status != EFI_SUCCESS)
+               goto fail;
+       if (size > 0) {
+               efi_set_u64_split(addr, &hdr->ramdisk_image,
+                                 &boot_params->ext_ramdisk_image);
+               efi_set_u64_split(size, &hdr->ramdisk_size,
+                                 &boot_params->ext_ramdisk_size);
        }
 
        /*
index ad9ddef..92a3d45 100644 (file)
@@ -79,6 +79,7 @@ static struct attribute *def_attrs[] = {
        &map_attribute_attr.attr,
        NULL
 };
+ATTRIBUTE_GROUPS(def);
 
 static const struct sysfs_ops map_attr_ops = {
        .show = map_attr_show,
@@ -94,7 +95,7 @@ static void map_release(struct kobject *kobj)
 
 static struct kobj_type __refdata map_ktype = {
        .sysfs_ops      = &map_attr_ops,
-       .default_attrs  = def_attrs,
+       .default_groups = def_groups,
        .release        = map_release,
 };
 
index ef8dbc0..0de9fb1 100644 (file)
@@ -570,8 +570,8 @@ extern struct efi {
        unsigned long                   flags;
 } efi;
 
-#define EFI_RT_SUPPORTED_GET_TIME                              0x0001
-#define EFI_RT_SUPPORTED_SET_TIME                              0x0002
+#define EFI_RT_SUPPORTED_GET_TIME                              0x0001
+#define EFI_RT_SUPPORTED_SET_TIME                              0x0002
 #define EFI_RT_SUPPORTED_GET_WAKEUP_TIME                       0x0004
 #define EFI_RT_SUPPORTED_SET_WAKEUP_TIME                       0x0008
 #define EFI_RT_SUPPORTED_GET_VARIABLE                          0x0010
@@ -838,7 +838,7 @@ extern int efi_status_to_err(efi_status_t status);
 #define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
 #define EFI_VARIABLE_APPEND_WRITE      0x0000000000000040
 
-#define EFI_VARIABLE_MASK      (EFI_VARIABLE_NON_VOLATILE | \
+#define EFI_VARIABLE_MASK      (EFI_VARIABLE_NON_VOLATILE | \
                                EFI_VARIABLE_BOOTSERVICE_ACCESS | \
                                EFI_VARIABLE_RUNTIME_ACCESS | \
                                EFI_VARIABLE_HARDWARE_ERROR_RECORD | \