Commit bc53f67d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'efi-urgent-2020-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull EFI fixes from Ingo Molnar:

 - Fix build regression on v4.8 and older

 - Robustness fix for TPM log parsing code

 - kobject refcount fix for the ESRT parsing code

 - Two efivarfs fixes to make it behave more like an ordinary file
   system

 - Style fixup for zero length arrays

 - Fix a regression in path separator handling in the initrd loader

 - Fix a missing prototype warning

 - Add some kerneldoc headers for newly introduced stub routines

 - Allow support for SSDT overrides via EFI variables to be disabled

 - Report CPU mode and MMU state upon entry for 32-bit ARM

 - Use the correct stack pointer alignment when entering from mixed mode

* tag 'efi-urgent-2020-06-28' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  efi/libstub: arm: Print CPU boot mode and MMU state at boot
  efi/libstub: arm: Omit arch specific config table matching array on arm64
  efi/x86: Setup stack correctly for efi_pe_entry
  efi: Make it possible to disable efivar_ssdt entirely
  efi/libstub: Descriptions for stub helper functions
  efi/libstub: Fix path separator regression
  efi/libstub: Fix missing-prototype warning for skip_spaces()
  efi: Replace zero-length array and use struct_size() helper
  efivarfs: Don't return -EINTR when rate-limiting reads
  efivarfs: Update inode modification time for successful writes
  efi/esrt: Fix reference count leak in esre_create_sysfs_entry.
  efi/tpm: Verify event log header before parsing
  efi/x86: Fix build with gcc 4
parents 91a9a90d 2a55280a
...@@ -87,4 +87,11 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base, ...@@ -87,4 +87,11 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long dram_base,
return dram_base + SZ_512M; return dram_base + SZ_512M;
} }
struct efi_arm_entry_state {
u32 cpsr_before_ebs;
u32 sctlr_before_ebs;
u32 cpsr_after_ebs;
u32 sctlr_after_ebs;
};
#endif /* _ASM_ARM_EFI_H */ #endif /* _ASM_ARM_EFI_H */
...@@ -213,7 +213,6 @@ SYM_FUNC_START(startup_32) ...@@ -213,7 +213,6 @@ SYM_FUNC_START(startup_32)
* We place all of the values on our mini stack so lret can * We place all of the values on our mini stack so lret can
* used to perform that far jump. * used to perform that far jump.
*/ */
pushl $__KERNEL_CS
leal startup_64(%ebp), %eax leal startup_64(%ebp), %eax
#ifdef CONFIG_EFI_MIXED #ifdef CONFIG_EFI_MIXED
movl efi32_boot_args(%ebp), %edi movl efi32_boot_args(%ebp), %edi
...@@ -224,11 +223,20 @@ SYM_FUNC_START(startup_32) ...@@ -224,11 +223,20 @@ SYM_FUNC_START(startup_32)
movl efi32_boot_args+8(%ebp), %edx // saved bootparams pointer movl efi32_boot_args+8(%ebp), %edx // saved bootparams pointer
cmpl $0, %edx cmpl $0, %edx
jnz 1f jnz 1f
/*
* efi_pe_entry uses MS calling convention, which requires 32 bytes of
* shadow space on the stack even if all arguments are passed in
* registers. We also need an additional 8 bytes for the space that
* would be occupied by the return address, and this also results in
* the correct stack alignment for entry.
*/
subl $40, %esp
leal efi_pe_entry(%ebp), %eax leal efi_pe_entry(%ebp), %eax
movl %edi, %ecx // MS calling convention movl %edi, %ecx // MS calling convention
movl %esi, %edx movl %esi, %edx
1: 1:
#endif #endif
pushl $__KERNEL_CS
pushl %eax pushl %eax
/* Enter paged protected Mode, activating Long Mode */ /* Enter paged protected Mode, activating Long Mode */
...@@ -784,6 +792,7 @@ SYM_DATA_LOCAL(boot_heap, .fill BOOT_HEAP_SIZE, 1, 0) ...@@ -784,6 +792,7 @@ SYM_DATA_LOCAL(boot_heap, .fill BOOT_HEAP_SIZE, 1, 0)
SYM_DATA_START_LOCAL(boot_stack) SYM_DATA_START_LOCAL(boot_stack)
.fill BOOT_STACK_SIZE, 1, 0 .fill BOOT_STACK_SIZE, 1, 0
.balign 16
SYM_DATA_END_LABEL(boot_stack, SYM_L_LOCAL, boot_stack_end) SYM_DATA_END_LABEL(boot_stack, SYM_L_LOCAL, boot_stack_end)
/* /*
......
...@@ -278,3 +278,14 @@ config EFI_EARLYCON ...@@ -278,3 +278,14 @@ config EFI_EARLYCON
depends on SERIAL_EARLYCON && !ARM && !IA64 depends on SERIAL_EARLYCON && !ARM && !IA64
select FONT_SUPPORT select FONT_SUPPORT
select ARCH_USE_MEMREMAP_PROT select ARCH_USE_MEMREMAP_PROT
config EFI_CUSTOM_SSDT_OVERLAYS
bool "Load custom ACPI SSDT overlay from an EFI variable"
depends on EFI_VARS && ACPI
default ACPI_TABLE_UPGRADE
help
Allow loading of an ACPI SSDT overlay from an EFI variable specified
by a kernel command line option.
See Documentation/admin-guide/acpi/ssdt-overlays.rst for more
information.
...@@ -52,9 +52,11 @@ static phys_addr_t __init efi_to_phys(unsigned long addr) ...@@ -52,9 +52,11 @@ static phys_addr_t __init efi_to_phys(unsigned long addr)
} }
static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR; static __initdata unsigned long screen_info_table = EFI_INVALID_TABLE_ADDR;
static __initdata unsigned long cpu_state_table = EFI_INVALID_TABLE_ADDR;
static const efi_config_table_type_t arch_tables[] __initconst = { static const efi_config_table_type_t arch_tables[] __initconst = {
{LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table}, {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table},
{LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table},
{} {}
}; };
...@@ -62,7 +64,8 @@ static void __init init_screen_info(void) ...@@ -62,7 +64,8 @@ static void __init init_screen_info(void)
{ {
struct screen_info *si; struct screen_info *si;
if (screen_info_table != EFI_INVALID_TABLE_ADDR) { if (IS_ENABLED(CONFIG_ARM) &&
screen_info_table != EFI_INVALID_TABLE_ADDR) {
si = early_memremap_ro(screen_info_table, sizeof(*si)); si = early_memremap_ro(screen_info_table, sizeof(*si));
if (!si) { if (!si) {
pr_err("Could not map screen_info config table\n"); pr_err("Could not map screen_info config table\n");
...@@ -116,7 +119,8 @@ static int __init uefi_init(u64 efi_system_table) ...@@ -116,7 +119,8 @@ static int __init uefi_init(u64 efi_system_table)
goto out; goto out;
} }
retval = efi_config_parse_tables(config_tables, systab->nr_tables, retval = efi_config_parse_tables(config_tables, systab->nr_tables,
arch_tables); IS_ENABLED(CONFIG_ARM) ? arch_tables
: NULL);
early_memunmap(config_tables, table_size); early_memunmap(config_tables, table_size);
out: out:
...@@ -238,9 +242,37 @@ void __init efi_init(void) ...@@ -238,9 +242,37 @@ void __init efi_init(void)
init_screen_info(); init_screen_info();
#ifdef CONFIG_ARM
/* ARM does not permit early mappings to persist across paging_init() */ /* ARM does not permit early mappings to persist across paging_init() */
if (IS_ENABLED(CONFIG_ARM))
efi_memmap_unmap(); efi_memmap_unmap();
if (cpu_state_table != EFI_INVALID_TABLE_ADDR) {
struct efi_arm_entry_state *state;
bool dump_state = true;
state = early_memremap_ro(cpu_state_table,
sizeof(struct efi_arm_entry_state));
if (state == NULL) {
pr_warn("Unable to map CPU entry state table.\n");
return;
}
if ((state->sctlr_before_ebs & 1) == 0)
pr_warn(FW_BUG "EFI stub was entered with MMU and Dcache disabled, please fix your firmware!\n");
else if ((state->sctlr_after_ebs & 1) == 0)
pr_warn(FW_BUG "ExitBootServices() returned with MMU and Dcache disabled, please fix your firmware!\n");
else
dump_state = false;
if (dump_state || efi_enabled(EFI_DBG)) {
pr_info("CPSR at EFI stub entry : 0x%08x\n", state->cpsr_before_ebs);
pr_info("SCTLR at EFI stub entry : 0x%08x\n", state->sctlr_before_ebs);
pr_info("CPSR after ExitBootServices() : 0x%08x\n", state->cpsr_after_ebs);
pr_info("SCTLR after ExitBootServices(): 0x%08x\n", state->sctlr_after_ebs);
}
early_memunmap(state, sizeof(struct efi_arm_entry_state));
}
#endif
} }
static bool efifb_overlaps_pci_range(const struct of_pci_range *range) static bool efifb_overlaps_pci_range(const struct of_pci_range *range)
......
...@@ -189,7 +189,7 @@ static void generic_ops_unregister(void) ...@@ -189,7 +189,7 @@ static void generic_ops_unregister(void)
efivars_unregister(&generic_efivars); efivars_unregister(&generic_efivars);
} }
#if IS_ENABLED(CONFIG_ACPI) #ifdef CONFIG_EFI_CUSTOM_SSDT_OVERLAYS
#define EFIVAR_SSDT_NAME_MAX 16 #define EFIVAR_SSDT_NAME_MAX 16
static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata; static char efivar_ssdt[EFIVAR_SSDT_NAME_MAX] __initdata;
static int __init efivar_ssdt_setup(char *str) static int __init efivar_ssdt_setup(char *str)
...@@ -622,7 +622,8 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, ...@@ -622,7 +622,8 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
rsv = (void *)(p + prsv % PAGE_SIZE); rsv = (void *)(p + prsv % PAGE_SIZE);
/* reserve the entry itself */ /* reserve the entry itself */
memblock_reserve(prsv, EFI_MEMRESERVE_SIZE(rsv->size)); memblock_reserve(prsv,
struct_size(rsv, entry, rsv->size));
for (i = 0; i < atomic_read(&rsv->count); i++) { for (i = 0; i < atomic_read(&rsv->count); i++) {
memblock_reserve(rsv->entry[i].base, memblock_reserve(rsv->entry[i].base,
......
...@@ -181,7 +181,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num) ...@@ -181,7 +181,7 @@ static int esre_create_sysfs_entry(void *esre, int entry_num)
rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL, rc = kobject_init_and_add(&entry->kobj, &esre1_ktype, NULL,
"entry%d", entry_num); "entry%d", entry_num);
if (rc) { if (rc) {
kfree(entry); kobject_put(&entry->kobj);
return rc; return rc;
} }
} }
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
# enabled, even if doing so doesn't break the build. # enabled, even if doing so doesn't break the build.
# #
cflags-$(CONFIG_X86_32) := -march=i386 cflags-$(CONFIG_X86_32) := -march=i386
cflags-$(CONFIG_X86_64) := -mcmodel=small cflags-$(CONFIG_X86_64) := -mcmodel=small \
$(call cc-option,-maccumulate-outgoing-args)
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
-fPIC -fno-strict-aliasing -mno-red-zone \ -fPIC -fno-strict-aliasing -mno-red-zone \
-mno-mmx -mno-sse -fshort-wchar \ -mno-mmx -mno-sse -fshort-wchar \
......
...@@ -7,10 +7,49 @@ ...@@ -7,10 +7,49 @@
#include "efistub.h" #include "efistub.h"
static efi_guid_t cpu_state_guid = LINUX_EFI_ARM_CPU_STATE_TABLE_GUID;
struct efi_arm_entry_state *efi_entry_state;
static void get_cpu_state(u32 *cpsr, u32 *sctlr)
{
asm("mrs %0, cpsr" : "=r"(*cpsr));
if ((*cpsr & MODE_MASK) == HYP_MODE)
asm("mrc p15, 4, %0, c1, c0, 0" : "=r"(*sctlr));
else
asm("mrc p15, 0, %0, c1, c0, 0" : "=r"(*sctlr));
}
efi_status_t check_platform_features(void) efi_status_t check_platform_features(void)
{ {
efi_status_t status;
u32 cpsr, sctlr;
int block; int block;
get_cpu_state(&cpsr, &sctlr);
efi_info("Entering in %s mode with MMU %sabled\n",
((cpsr & MODE_MASK) == HYP_MODE) ? "HYP" : "SVC",
(sctlr & 1) ? "en" : "dis");
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
sizeof(*efi_entry_state),
(void **)&efi_entry_state);
if (status != EFI_SUCCESS) {
efi_err("allocate_pool() failed\n");
return status;
}
efi_entry_state->cpsr_before_ebs = cpsr;
efi_entry_state->sctlr_before_ebs = sctlr;
status = efi_bs_call(install_configuration_table, &cpu_state_guid,
efi_entry_state);
if (status != EFI_SUCCESS) {
efi_err("install_configuration_table() failed\n");
goto free_state;
}
/* non-LPAE kernels can run anywhere */ /* non-LPAE kernels can run anywhere */
if (!IS_ENABLED(CONFIG_ARM_LPAE)) if (!IS_ENABLED(CONFIG_ARM_LPAE))
return EFI_SUCCESS; return EFI_SUCCESS;
...@@ -19,9 +58,22 @@ efi_status_t check_platform_features(void) ...@@ -19,9 +58,22 @@ efi_status_t check_platform_features(void)
block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0); block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
if (block < 5) { if (block < 5) {
efi_err("This LPAE kernel is not supported by your CPU\n"); efi_err("This LPAE kernel is not supported by your CPU\n");
return EFI_UNSUPPORTED; status = EFI_UNSUPPORTED;
goto drop_table;
} }
return EFI_SUCCESS; return EFI_SUCCESS;
drop_table:
efi_bs_call(install_configuration_table, &cpu_state_guid, NULL);
free_state:
efi_bs_call(free_pool, efi_entry_state);
return status;
}
void efi_handle_post_ebs_state(void)
{
get_cpu_state(&efi_entry_state->cpsr_after_ebs,
&efi_entry_state->sctlr_after_ebs);
} }
static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID; static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;
......
...@@ -32,6 +32,10 @@ bool __pure __efi_soft_reserve_enabled(void) ...@@ -32,6 +32,10 @@ bool __pure __efi_soft_reserve_enabled(void)
return !efi_nosoftreserve; return !efi_nosoftreserve;
} }
/**
* efi_char16_puts() - Write a UCS-2 encoded string to the console
* @str: UCS-2 encoded string
*/
void efi_char16_puts(efi_char16_t *str) void efi_char16_puts(efi_char16_t *str)
{ {
efi_call_proto(efi_table_attr(efi_system_table, con_out), efi_call_proto(efi_table_attr(efi_system_table, con_out),
...@@ -83,6 +87,10 @@ u32 utf8_to_utf32(const u8 **s8) ...@@ -83,6 +87,10 @@ u32 utf8_to_utf32(const u8 **s8)
return c32; return c32;
} }
/**
* efi_puts() - Write a UTF-8 encoded string to the console
* @str: UTF-8 encoded string
*/
void efi_puts(const char *str) void efi_puts(const char *str)
{ {
efi_char16_t buf[128]; efi_char16_t buf[128];
...@@ -113,6 +121,16 @@ void efi_puts(const char *str) ...@@ -113,6 +121,16 @@ void efi_puts(const char *str)
} }
} }
/**
* efi_printk() - Print a kernel message
* @fmt: format string
*
* The first letter of the format string is used to determine the logging level
* of the message. If the level is less then the current EFI logging level, the
* message is suppressed. The message will be truncated to 255 bytes.
*
* Return: number of printed characters
*/
int efi_printk(const char *fmt, ...) int efi_printk(const char *fmt, ...)
{ {
char printf_buf[256]; char printf_buf[256];
...@@ -154,13 +172,18 @@ int efi_printk(const char *fmt, ...) ...@@ -154,13 +172,18 @@ int efi_printk(const char *fmt, ...)
return printed; return printed;
} }
/* /**
* Parse the ASCII string 'cmdline' for EFI options, denoted by the efi= * efi_parse_options() - Parse EFI command line options
* @cmdline: kernel command line
*
* Parse the ASCII string @cmdline for EFI options, denoted by the efi=
* option, e.g. efi=nochunk. * option, e.g. efi=nochunk.
* *
* It should be noted that efi= is parsed in two very different * It should be noted that efi= is parsed in two very different
* environments, first in the early boot environment of the EFI boot * environments, first in the early boot environment of the EFI boot
* stub, and subsequently during the kernel boot. * stub, and subsequently during the kernel boot.
*
* Return: status code
*/ */
efi_status_t efi_parse_options(char const *cmdline) efi_status_t efi_parse_options(char const *cmdline)
{ {
...@@ -286,13 +309,21 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len) ...@@ -286,13 +309,21 @@ char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len)
return (char *)cmdline_addr; return (char *)cmdline_addr;
} }
/* /**
* efi_exit_boot_services() - Exit boot services
* @handle: handle of the exiting image
* @map: pointer to receive the memory map
* @priv: argument to be passed to @priv_func
* @priv_func: function to process the memory map before exiting boot services
*
* Handle calling ExitBootServices according to the requirements set out by the * Handle calling ExitBootServices according to the requirements set out by the
* spec. Obtains the current memory map, and returns that info after calling * spec. Obtains the current memory map, and returns that info after calling
* ExitBootServices. The client must specify a function to perform any * ExitBootServices. The client must specify a function to perform any
* processing of the memory map data prior to ExitBootServices. A client * processing of the memory map data prior to ExitBootServices. A client
* specific structure may be passed to the function via priv. The client * specific structure may be passed to the function via priv. The client
* function may be called multiple times. * function may be called multiple times.
*
* Return: status code
*/ */
efi_status_t efi_exit_boot_services(void *handle, efi_status_t efi_exit_boot_services(void *handle,
struct efi_boot_memmap *map, struct efi_boot_memmap *map,
...@@ -361,6 +392,11 @@ efi_status_t efi_exit_boot_services(void *handle, ...@@ -361,6 +392,11 @@ efi_status_t efi_exit_boot_services(void *handle,
return status; return status;
} }
/**
* get_efi_config_table() - retrieve UEFI configuration table
* @guid: GUID of the configuration table to be retrieved
* Return: pointer to the configuration table or NULL
*/
void *get_efi_config_table(efi_guid_t guid) void *get_efi_config_table(efi_guid_t guid)
{ {
unsigned long tables = efi_table_attr(efi_system_table, tables); unsigned long tables = efi_table_attr(efi_system_table, tables);
...@@ -408,17 +444,18 @@ static const struct { ...@@ -408,17 +444,18 @@ static const struct {
}; };
/** /**
* efi_load_initrd_dev_path - load the initrd from the Linux initrd device path * efi_load_initrd_dev_path() - load the initrd from the Linux initrd device path
* @load_addr: pointer to store the address where the initrd was loaded * @load_addr: pointer to store the address where the initrd was loaded
* @load_size: pointer to store the size of the loaded initrd * @load_size: pointer to store the size of the loaded initrd
* @max: upper limit for the initrd memory allocation * @max: upper limit for the initrd memory allocation
* @return: %EFI_SUCCESS if the initrd was loaded successfully, in which *
* Return:
* * %EFI_SUCCESS if the initrd was loaded successfully, in which
* case @load_addr and @load_size are assigned accordingly * case @load_addr and @load_size are assigned accordingly
* %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd * * %EFI_NOT_FOUND if no LoadFile2 protocol exists on the initrd device path
* device path * * %EFI_INVALID_PARAMETER if load_addr == NULL or load_size == NULL
* %EFI_INVALID_PARAMETER if load_addr == NULL or load_size == NULL * * %EFI_OUT_OF_RESOURCES if memory allocation failed
* %EFI_OUT_OF_RESOURCES if memory allocation failed * * %EFI_LOAD_ERROR in all other cases
* %EFI_LOAD_ERROR in all other cases
*/ */
static static
efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr, efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
...@@ -481,6 +518,16 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image, ...@@ -481,6 +518,16 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
load_addr, load_size); load_addr, load_size);
} }
/**
* efi_load_initrd() - Load initial RAM disk
* @image: EFI loaded image protocol
* @load_addr: pointer to loaded initrd
* @load_size: size of loaded initrd
* @soft_limit: preferred size of allocated memory for loading the initrd
* @hard_limit: minimum size of allocated memory
*
* Return: status code
*/
efi_status_t efi_load_initrd(efi_loaded_image_t *image, efi_status_t efi_load_initrd(efi_loaded_image_t *image,
unsigned long *load_addr, unsigned long *load_addr,
unsigned long *load_size, unsigned long *load_size,
...@@ -505,6 +552,15 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image, ...@@ -505,6 +552,15 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
return status; return status;
} }
/**
* efi_wait_for_key() - Wait for key stroke
* @usec: number of microseconds to wait for key stroke
* @key: key entered
*
* Wait for up to @usec microseconds for a key stroke.
*
* Return: status code, EFI_SUCCESS if key received
*/
efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key) efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key)
{ {
efi_event_t events[2], timer; efi_event_t events[2], timer;
......
...@@ -329,6 +329,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -329,6 +329,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
goto fail_free_initrd; goto fail_free_initrd;
if (IS_ENABLED(CONFIG_ARM))
efi_handle_post_ebs_state();
efi_enter_kernel(image_addr, fdt_addr, fdt_totalsize((void *)fdt_addr)); efi_enter_kernel(image_addr, fdt_addr, fdt_totalsize((void *)fdt_addr));
/* not reached */ /* not reached */
......
...@@ -157,8 +157,14 @@ typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *); ...@@ -157,8 +157,14 @@ typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *);
#define EFI_EVT_NOTIFY_WAIT 0x00000100U #define EFI_EVT_NOTIFY_WAIT 0x00000100U
#define EFI_EVT_NOTIFY_SIGNAL 0x00000200U #define EFI_EVT_NOTIFY_SIGNAL 0x00000200U
/* /**
* boottime->wait_for_event takes an array of events as input. * efi_set_event_at() - add event to events array
*
* @events: array of UEFI events
* @ids: index where to put the event in the array
* @event: event to add to the aray
*
* boottime->wait_for_event() takes an array of events as input.
* Provide a helper to set it up correctly for mixed mode. * Provide a helper to set it up correctly for mixed mode.
*/ */
static inline static inline
...@@ -771,4 +777,6 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image, ...@@ -771,4 +777,6 @@ efi_status_t efi_load_initrd(efi_loaded_image_t *image,
unsigned long soft_limit, unsigned long soft_limit,
unsigned long hard_limit); unsigned long hard_limit);
void efi_handle_post_ebs_state(void);
#endif #endif
...@@ -102,12 +102,20 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len, ...@@ -102,12 +102,20 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len,
if (!found) if (!found)
return 0; return 0;
/* Skip any leading slashes */
while (cmdline[i] == L'/' || cmdline[i] == L'\\')
i++;
while (--result_len > 0 && i < cmdline_len) { while (--result_len > 0 && i < cmdline_len) {
if (cmdline[i] == L'\0' || efi_char16_t c = cmdline[i++];
cmdline[i] == L'\n' ||
cmdline[i] == L' ') if (c == L'\0' || c == L'\n' || c == L' ')
break; break;
*result++ = cmdline[i++]; else if (c == L'/')
/* Replace UNIX dir separators with EFI standard ones */
*result++ = L'\\';
else
*result++ = c;
} }
*result = L'\0'; *result = L'\0';
return i; return i;
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
char *skip_spaces(const char *str) char *skip_spaces(const char *str)
......
...@@ -51,6 +51,7 @@ static ssize_t efivarfs_file_write(struct file *file, ...@@ -51,6 +51,7 @@ static ssize_t efivarfs_file_write(struct file *file,
} else { } else {
inode_lock(inode); inode_lock(inode);
i_size_write(inode, datasize + sizeof(attributes)); i_size_write(inode, datasize + sizeof(attributes));
inode->i_mtime = current_time(inode);
inode_unlock(inode); inode_unlock(inode);
} }
...@@ -72,10 +73,8 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf, ...@@ -72,10 +73,8 @@ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
ssize_t size = 0; ssize_t size = 0;
int err; int err;
while (!__ratelimit(&file->f_cred->user->ratelimit)) { while (!__ratelimit(&file->f_cred->user->ratelimit))
if (!msleep_interruptible(50)) msleep(50);
return -EINTR;
}
err = efivar_entry_size(var, &datasize); err = efivar_entry_size(var, &datasize);
......
...@@ -350,6 +350,7 @@ void efi_native_runtime_setup(void); ...@@ -350,6 +350,7 @@ void efi_native_runtime_setup(void);
* associated with ConOut * associated with ConOut
*/ */
#define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
#define LINUX_EFI_ARM_CPU_STATE_TABLE_GUID EFI_GUID(0xef79e4aa, 0x3c3d, 0x4989, 0xb9, 0x02, 0x07, 0xa9, 0x43, 0xe5, 0x50, 0xd2)
#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b) #define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
#define LINUX_EFI_TPM_EVENT_LOG_GUID EFI_GUID(0xb7799cb0, 0xeca2, 0x4943, 0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa) #define LINUX_EFI_TPM_EVENT_LOG_GUID EFI_GUID(0xb7799cb0, 0xeca2, 0x4943, 0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa)
...@@ -1236,14 +1237,11 @@ struct linux_efi_memreserve { ...@@ -1236,14 +1237,11 @@ struct linux_efi_memreserve {
struct { struct {
phys_addr_t base; phys_addr_t base;
phys_addr_t size; phys_addr_t size;
} entry[0]; } entry[];
}; };
#define EFI_MEMRESERVE_SIZE(count) (sizeof(struct linux_efi_memreserve) + \
(count) * sizeof(((struct linux_efi_memreserve *)0)->entry[0]))
#define EFI_MEMRESERVE_COUNT(size) (((size) - sizeof(struct linux_efi_memreserve)) \ #define EFI_MEMRESERVE_COUNT(size) (((size) - sizeof(struct linux_efi_memreserve)) \
/ sizeof(((struct linux_efi_memreserve *)0)->entry[0])) / sizeof_field(struct linux_efi_memreserve, entry[0]))
void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size); void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size);
......
...@@ -81,6 +81,8 @@ struct tcg_efi_specid_event_algs { ...@@ -81,6 +81,8 @@ struct tcg_efi_specid_event_algs {
u16 digest_size; u16 digest_size;
} __packed; } __packed;
#define TCG_SPECID_SIG "Spec ID Event03"
struct tcg_efi_specid_event_head { struct tcg_efi_specid_event_head {
u8 signature[16]; u8 signature[16];
u32 platform_class; u32 platform_class;
...@@ -171,6 +173,7 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, ...@@ -171,6 +173,7 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
int i; int i;
int j; int j;
u32 count, event_type; u32 count, event_type;
const u8 zero_digest[sizeof(event_header->digest)] = {0};
marker = event; marker = event;
marker_start = marker; marker_start = marker;
...@@ -198,10 +201,19 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, ...@@ -198,10 +201,19 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
count = READ_ONCE(event->count); count = READ_ONCE(event->count);
event_type = READ_ONCE(event->event_type); event_type = READ_ONCE(event->event_type);
/* Verify that it's the log header */
if (event_header->pcr_idx != 0 ||
event_header->event_type != NO_ACTION ||
memcmp(event_header->digest, zero_digest, sizeof(zero_digest))) {
size = 0;
goto out;
}
efispecid = (struct tcg_efi_specid_event_head *)event_header->event; efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
/* Check if event is malformed. */ /* Check if event is malformed. */
if (count > efispecid->num_algs) { if (memcmp(efispecid->signature, TCG_SPECID_SIG,
sizeof(TCG_SPECID_SIG)) || count > efispecid->num_algs) {
size = 0; size = 0;
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment