Skip to content

Commit

Permalink
Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/kernel/git/tip/tip

Pull EFI changes from Ingo Molnar:
 "Main changes in this cycle are:

   - arm64 efi stub fixes, preservation of FP/SIMD registers across
     firmware calls, and conversion of the EFI stub code into a static
     library - Ard Biesheuvel

   - Xen EFI support - Daniel Kiper

   - Support for autoloading the efivars driver - Lee, Chun-Yi

   - Use the PE/COFF headers in the x86 EFI boot stub to request that
     the stub be loaded with CONFIG_PHYSICAL_ALIGN alignment - Michael
     Brown

   - Consolidate all the x86 EFI quirks into one file - Saurabh Tangri

   - Additional error logging in x86 EFI boot stub - Ulf Winkelvos

   - Support loading initrd above 4G in EFI boot stub - Yinghai Lu

   - EFI reboot patches for ACPI hardware reduced platforms"

* 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (31 commits)
  efi/arm64: Handle missing virtual mapping for UEFI System Table
  arch/x86/xen: Silence compiler warnings
  xen: Silence compiler warnings
  x86/efi: Request desired alignment via the PE/COFF headers
  x86/efi: Add better error logging to EFI boot stub
  efi: Autoload efivars
  efi: Update stale locking comment for struct efivars
  arch/x86: Remove efi_set_rtc_mmss()
  arch/x86: Replace plain strings with constants
  xen: Put EFI machinery in place
  xen: Define EFI related stuff
  arch/x86: Remove redundant set_bit(EFI_MEMMAP) call
  arch/x86: Remove redundant set_bit(EFI_SYSTEM_TABLES) call
  efi: Introduce EFI_PARAVIRT flag
  arch/x86: Do not access EFI memory map if it is not available
  efi: Use early_mem*() instead of early_io*()
  arch/ia64: Define early_memunmap()
  x86/reboot: Add EFI reboot quirk for ACPI Hardware Reduced flag
  efi/reboot: Allow powering off machines using EFI
  efi/reboot: Add generic wrapper around EfiResetSystem()
  ...
  • Loading branch information
Linus Torvalds committed Aug 5, 2014
2 parents e9c9eec + 99a5603 commit 76f09aa
Show file tree
Hide file tree
Showing 40 changed files with 1,508 additions and 622 deletions.
6 changes: 6 additions & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -347,12 +347,18 @@ config CMDLINE_FORCE
This is useful if you cannot or don't want to change the
command-line options your boot loader passes to the kernel.

config EFI_STUB
bool

config EFI
bool "UEFI runtime support"
depends on OF && !CPU_BIG_ENDIAN
select LIBFDT
select UCS2_STRING
select EFI_PARAMS_FROM_FDT
select EFI_RUNTIME_WRAPPERS
select EFI_STUB
select EFI_ARMSTUB
default y
help
This option provides support for runtime services provided
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ core-$(CONFIG_XEN) += arch/arm64/xen/
core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
libs-y := arch/arm64/lib/ $(libs-y)
libs-y += $(LIBGCC)
libs-$(CONFIG_EFI_STUB) += drivers/firmware/efi/libstub/

# Default target when executing plain make
KBUILD_IMAGE := Image.gz
Expand Down
33 changes: 33 additions & 0 deletions arch/arm64/include/asm/efi.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define _ASM_EFI_H

#include <asm/io.h>
#include <asm/neon.h>

#ifdef CONFIG_EFI
extern void efi_init(void);
Expand All @@ -11,4 +12,36 @@ extern void efi_idmap_init(void);
#define efi_idmap_init()
#endif

#define efi_call_virt(f, ...) \
({ \
efi_##f##_t *__f = efi.systab->runtime->f; \
efi_status_t __s; \
\
kernel_neon_begin(); \
__s = __f(__VA_ARGS__); \
kernel_neon_end(); \
__s; \
})

#define __efi_call_virt(f, ...) \
({ \
efi_##f##_t *__f = efi.systab->runtime->f; \
\
kernel_neon_begin(); \
__f(__VA_ARGS__); \
kernel_neon_end(); \
})

/* arch specific definitions used by the stub code */

/*
* AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
* start of kernel and may not cross a 2MiB boundary. We set alignment to
* 2MiB so we know it won't cross a 2MiB boundary.
*/
#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */
#define MAX_FDT_OFFSET SZ_512M

#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)

#endif /* _ASM_EFI_H */
3 changes: 1 addition & 2 deletions arch/arm64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)
AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) \
-I$(src)/../../../scripts/dtc/libfdt
CFLAGS_efi-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)

CFLAGS_REMOVE_ftrace.o = -pg
CFLAGS_REMOVE_insn.o = -pg
Expand Down
48 changes: 9 additions & 39 deletions arch/arm64/kernel/efi-stub.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,16 @@
*
*/
#include <linux/efi.h>
#include <linux/libfdt.h>
#include <asm/efi.h>
#include <asm/sections.h>

/*
* AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from
* start of kernel and may not cross a 2MiB boundary. We set alignment to
* 2MiB so we know it won't cross a 2MiB boundary.
*/
#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */
#define MAX_FDT_OFFSET SZ_512M

#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__)

static void efi_char16_printk(efi_system_table_t *sys_table_arg,
efi_char16_t *str);

static efi_status_t efi_open_volume(efi_system_table_t *sys_table,
void *__image, void **__fh);
static efi_status_t efi_file_close(void *handle);

static efi_status_t
efi_file_read(void *handle, unsigned long *size, void *addr);

static efi_status_t
efi_file_size(efi_system_table_t *sys_table, void *__fh,
efi_char16_t *filename_16, void **handle, u64 *file_sz);

/* Include shared EFI stub code */
#include "../../../drivers/firmware/efi/efi-stub-helper.c"
#include "../../../drivers/firmware/efi/fdt.c"
#include "../../../drivers/firmware/efi/arm-stub.c"


static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
unsigned long *image_addr,
unsigned long *image_size,
unsigned long *reserve_addr,
unsigned long *reserve_size,
unsigned long dram_base,
efi_loaded_image_t *image)
efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
unsigned long *image_addr,
unsigned long *image_size,
unsigned long *reserve_addr,
unsigned long *reserve_size,
unsigned long dram_base,
efi_loaded_image_t *image)
{
efi_status_t status;
unsigned long kernel_size, kernel_memsize = 0;
Expand All @@ -69,7 +39,7 @@ static efi_status_t handle_kernel_image(efi_system_table_t *sys_table,
if (*image_addr != (dram_base + TEXT_OFFSET)) {
pr_efi_err(sys_table, "Failed to alloc kernel memory\n");
efi_free(sys_table, kernel_memsize, *image_addr);
return EFI_ERROR;
return EFI_LOAD_ERROR;
}
*image_size = kernel_memsize;
}
Expand Down
42 changes: 25 additions & 17 deletions arch/arm64/kernel/efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,13 +414,24 @@ static int __init arm64_enter_virtual_mode(void)
for_each_efi_memory_desc(&memmap, md) {
if (!(md->attribute & EFI_MEMORY_RUNTIME))
continue;
if (remap_region(md, &virt_md))
++count;
if (!remap_region(md, &virt_md))
goto err_unmap;
++count;
}

efi.systab = (__force void *)efi_lookup_mapped_addr(efi_system_table);
if (efi.systab)
set_bit(EFI_SYSTEM_TABLES, &efi.flags);
if (!efi.systab) {
/*
* If we have no virtual mapping for the System Table at this
* point, the memory map doesn't cover the physical offset where
* it resides. This means the System Table will be inaccessible
* to Runtime Services themselves once the virtual mapping is
* installed.
*/
pr_err("Failed to remap EFI System Table -- buggy firmware?\n");
goto err_unmap;
}
set_bit(EFI_SYSTEM_TABLES, &efi.flags);

local_irq_save(flags);
cpu_switch_mm(idmap_pg_dir, &init_mm);
Expand Down Expand Up @@ -449,21 +460,18 @@ static int __init arm64_enter_virtual_mode(void)

/* Set up runtime services function pointers */
runtime = efi.systab->runtime;
efi.get_time = runtime->get_time;
efi.set_time = runtime->set_time;
efi.get_wakeup_time = runtime->get_wakeup_time;
efi.set_wakeup_time = runtime->set_wakeup_time;
efi.get_variable = runtime->get_variable;
efi.get_next_variable = runtime->get_next_variable;
efi.set_variable = runtime->set_variable;
efi.query_variable_info = runtime->query_variable_info;
efi.update_capsule = runtime->update_capsule;
efi.query_capsule_caps = runtime->query_capsule_caps;
efi.get_next_high_mono_count = runtime->get_next_high_mono_count;
efi.reset_system = runtime->reset_system;

efi_native_runtime_setup();
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);

return 0;

err_unmap:
/* unmap all mappings that succeeded: there are 'count' of those */
for (virt_md = virtmap; count--; virt_md += memmap.desc_size) {
md = virt_md;
iounmap((__force void __iomem *)md->virt_addr);
}
kfree(virtmap);
return -1;
}
early_initcall(arm64_enter_virtual_mode);
1 change: 1 addition & 0 deletions arch/ia64/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ extern void iounmap (volatile void __iomem *addr);
extern void __iomem * early_ioremap (unsigned long phys_addr, unsigned long size);
#define early_memremap(phys_addr, size) early_ioremap(phys_addr, size)
extern void early_iounmap (volatile void __iomem *addr, unsigned long size);
#define early_memunmap(addr, size) early_iounmap(addr, size)
static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned long size)
{
return ioremap(phys_addr, size);
Expand Down
2 changes: 1 addition & 1 deletion arch/ia64/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ void
machine_restart (char *restart_cmd)
{
(void) notify_die(DIE_MACHINE_RESTART, restart_cmd, NULL, 0, 0, 0);
(*efi.reset_system)(EFI_RESET_WARM, 0, 0, NULL);
efi_reboot(REBOOT_WARM, NULL);
}

void
Expand Down
1 change: 1 addition & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1522,6 +1522,7 @@ config EFI
bool "EFI runtime service support"
depends on ACPI
select UCS2_STRING
select EFI_RUNTIME_WRAPPERS
---help---
This enables the kernel to use EFI runtime services that are
available (such as the EFI variable services).
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/boot/compressed/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone

ifeq ($(CONFIG_EFI_STUB), y)
VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o \
$(objtree)/drivers/firmware/efi/libstub/lib.a
endif

$(obj)/vmlinux: $(VMLINUX_OBJS) FORCE
Expand Down
48 changes: 29 additions & 19 deletions arch/x86/boot/compressed/eboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@

static efi_system_table_t *sys_table;

static struct efi_config *efi_early;

#define efi_call_early(f, ...) \
efi_early->call(efi_early->f, __VA_ARGS__);
struct efi_config *efi_early;

#define BOOT_SERVICES(bits) \
static void setup_boot_services##bits(struct efi_config *c) \
Expand All @@ -48,8 +45,7 @@ static void setup_boot_services##bits(struct efi_config *c) \
BOOT_SERVICES(32);
BOOT_SERVICES(64);

static void efi_printk(efi_system_table_t *, char *);
static void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
void efi_char16_printk(efi_system_table_t *, efi_char16_t *);

static efi_status_t
__file_size32(void *__fh, efi_char16_t *filename_16,
Expand Down Expand Up @@ -156,7 +152,7 @@ __file_size64(void *__fh, efi_char16_t *filename_16,

return status;
}
static efi_status_t
efi_status_t
efi_file_size(efi_system_table_t *sys_table, void *__fh,
efi_char16_t *filename_16, void **handle, u64 *file_sz)
{
Expand All @@ -166,7 +162,7 @@ efi_file_size(efi_system_table_t *sys_table, void *__fh,
return __file_size32(__fh, filename_16, handle, file_sz);
}

static inline efi_status_t
efi_status_t
efi_file_read(void *handle, unsigned long *size, void *addr)
{
unsigned long func;
Expand All @@ -184,7 +180,7 @@ efi_file_read(void *handle, unsigned long *size, void *addr)
}
}

static inline efi_status_t efi_file_close(void *handle)
efi_status_t efi_file_close(void *handle)
{
if (efi_early->is64) {
efi_file_handle_64_t *fh = handle;
Expand Down Expand Up @@ -249,7 +245,7 @@ static inline efi_status_t __open_volume64(void *__image, void **__fh)
return status;
}

static inline efi_status_t
efi_status_t
efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
{
if (efi_early->is64)
Expand All @@ -258,7 +254,7 @@ efi_open_volume(efi_system_table_t *sys_table, void *__image, void **__fh)
return __open_volume32(__image, __fh);
}

static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
{
unsigned long output_string;
size_t offset;
Expand All @@ -284,8 +280,6 @@ static void efi_char16_printk(efi_system_table_t *table, efi_char16_t *str)
}
}

#include "../../../../drivers/firmware/efi/efi-stub-helper.c"

static void find_bits(unsigned long mask, u8 *pos, u8 *size)
{
u8 first, len;
Expand Down Expand Up @@ -1038,6 +1032,7 @@ struct boot_params *make_boot_params(struct efi_config *c)
int i;
unsigned long ramdisk_addr;
unsigned long ramdisk_size;
unsigned long initrd_addr_max;

efi_early = c;
sys_table = (efi_system_table_t *)(unsigned long)efi_early->table;
Expand Down Expand Up @@ -1100,14 +1095,21 @@ struct boot_params *make_boot_params(struct efi_config *c)

memset(sdt, 0, sizeof(*sdt));

if (hdr->xloadflags & XLF_CAN_BE_LOADED_ABOVE_4G)
initrd_addr_max = -1UL;
else
initrd_addr_max = hdr->initrd_addr_max;

status = handle_cmdline_files(sys_table, image,
(char *)(unsigned long)hdr->cmd_line_ptr,
"initrd=", hdr->initrd_addr_max,
"initrd=", initrd_addr_max,
&ramdisk_addr, &ramdisk_size);
if (status != EFI_SUCCESS)
goto fail2;
hdr->ramdisk_image = ramdisk_addr;
hdr->ramdisk_size = ramdisk_size;
hdr->ramdisk_image = ramdisk_addr & 0xffffffff;
hdr->ramdisk_size = ramdisk_size & 0xffffffff;
boot_params->ext_ramdisk_image = (u64)ramdisk_addr >> 32;
boot_params->ext_ramdisk_size = (u64)ramdisk_size >> 32;

return boot_params;
fail2:
Expand Down Expand Up @@ -1374,7 +1376,10 @@ struct boot_params *efi_main(struct efi_config *c,

setup_graphics(boot_params);

setup_efi_pci(boot_params);
status = setup_efi_pci(boot_params);
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "setup_efi_pci() failed!\n");
}

status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
sizeof(*gdt), (void **)&gdt);
Expand All @@ -1401,16 +1406,20 @@ struct boot_params *efi_main(struct efi_config *c,
hdr->init_size, hdr->init_size,
hdr->pref_address,
hdr->kernel_alignment);
if (status != EFI_SUCCESS)
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "efi_relocate_kernel() failed!\n");
goto fail;
}

hdr->pref_address = hdr->code32_start;
hdr->code32_start = bzimage_addr;
}

status = exit_boot(boot_params, handle, is64);
if (status != EFI_SUCCESS)
if (status != EFI_SUCCESS) {
efi_printk(sys_table, "exit_boot() failed!\n");
goto fail;
}

memset((char *)gdt->address, 0x0, gdt->size);
desc = (struct desc_struct *)gdt->address;
Expand Down Expand Up @@ -1470,5 +1479,6 @@ struct boot_params *efi_main(struct efi_config *c,

return boot_params;
fail:
efi_printk(sys_table, "efi_main() failed!\n");
return NULL;
}
Loading

0 comments on commit 76f09aa

Please sign in to comment.