Commit d1343da3 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'efi-changes-for-v5.8' of...

Merge tag 'efi-changes-for-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi into efi/core

More EFI changes for v5.8:

 - Rename pr_efi/pr_efi_err to efi_info/efi_err, and use them consistently
 - Simplify and unify initrd loading
 - Parse the builtin command line on x86 (if provided)
 - Implement printk() support, including support for wide character strings
 - Some fixes for issues introduced by the first batch of v5.8 changes
 - Fix a missing prototypes warning
 - Simplify GDT handling in early mixed mode thunking code
 - Some other minor fixes and cleanups

Conflicts:
	drivers/firmware/efi/libstub/efistub.h
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents a5d8e55b 9241dfe7
...@@ -63,4 +63,9 @@ auto ...@@ -63,4 +63,9 @@ auto
with the highest resolution, it will choose one with the highest color with the highest resolution, it will choose one with the highest color
depth. depth.
list
The EFI stub will list out all the display modes that are available. A
specific mode can then be chosen using one of the above options for the
next boot.
Edgar Hucek <gimli@dark-green.com> Edgar Hucek <gimli@dark-green.com>
...@@ -60,7 +60,7 @@ optional_header: ...@@ -60,7 +60,7 @@ optional_header:
.long __pecoff_code_size @ SizeOfCode .long __pecoff_code_size @ SizeOfCode
.long __pecoff_data_size @ SizeOfInitializedData .long __pecoff_data_size @ SizeOfInitializedData
.long 0 @ SizeOfUninitializedData .long 0 @ SizeOfUninitializedData
.long efi_entry - start @ AddressOfEntryPoint .long efi_pe_entry - start @ AddressOfEntryPoint
.long start_offset @ BaseOfCode .long start_offset @ BaseOfCode
.long __pecoff_data_start - start @ BaseOfData .long __pecoff_data_start - start @ BaseOfData
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
SYM_CODE_START(efi_enter_kernel) SYM_CODE_START(efi_enter_kernel)
/* /*
* efi_entry() will have copied the kernel image if necessary and we * efi_pe_entry() will have copied the kernel image if necessary and we
* end up here with device tree address in x1 and the kernel entry * end up here with device tree address in x1 and the kernel entry
* point stored in x0. Save those values in registers which are * point stored in x0. Save those values in registers which are
* callee preserved. * callee preserved.
......
...@@ -27,7 +27,7 @@ optional_header: ...@@ -27,7 +27,7 @@ optional_header:
.long __initdata_begin - efi_header_end // SizeOfCode .long __initdata_begin - efi_header_end // SizeOfCode
.long __pecoff_data_size // SizeOfInitializedData .long __pecoff_data_size // SizeOfInitializedData
.long 0 // SizeOfUninitializedData .long 0 // SizeOfUninitializedData
.long __efistub_efi_entry - _head // AddressOfEntryPoint .long __efistub_efi_pe_entry - _head // AddressOfEntryPoint
.long efi_header_end - _head // BaseOfCode .long efi_header_end - _head // BaseOfCode
extra_header_fields: extra_header_fields:
......
...@@ -28,8 +28,6 @@ SYM_FUNC_START(__efi64_thunk) ...@@ -28,8 +28,6 @@ SYM_FUNC_START(__efi64_thunk)
push %rbx push %rbx
leaq 1f(%rip), %rbp leaq 1f(%rip), %rbp
leaq efi_gdt64(%rip), %rbx
movl %ebx, 2(%rbx) /* Fixup the gdt base address */
movl %ds, %eax movl %ds, %eax
push %rax push %rax
...@@ -48,7 +46,8 @@ SYM_FUNC_START(__efi64_thunk) ...@@ -48,7 +46,8 @@ SYM_FUNC_START(__efi64_thunk)
movl %r8d, 0xc(%rsp) movl %r8d, 0xc(%rsp)
movl %r9d, 0x10(%rsp) movl %r9d, 0x10(%rsp)
sgdt 0x14(%rsp) leaq 0x14(%rsp), %rbx
sgdt (%rbx)
/* /*
* Switch to gdt with 32-bit segments. This is the firmware GDT * Switch to gdt with 32-bit segments. This is the firmware GDT
...@@ -68,8 +67,7 @@ SYM_FUNC_START(__efi64_thunk) ...@@ -68,8 +67,7 @@ SYM_FUNC_START(__efi64_thunk)
pushq %rax pushq %rax
lretq lretq
1: lgdt 0x14(%rsp) 1: addq $32, %rsp
addq $32, %rsp
movq %rdi, %rax movq %rdi, %rax
pop %rbx pop %rbx
...@@ -175,14 +173,3 @@ SYM_DATA_END(efi32_boot_cs) ...@@ -175,14 +173,3 @@ SYM_DATA_END(efi32_boot_cs)
SYM_DATA_START(efi32_boot_ds) SYM_DATA_START(efi32_boot_ds)
.word 0 .word 0
SYM_DATA_END(efi32_boot_ds) SYM_DATA_END(efi32_boot_ds)
SYM_DATA_START(efi_gdt64)
.word efi_gdt64_end - efi_gdt64
.long 0 /* Filled out by user */
.word 0
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x00af9a000000ffff /* __KERNEL_CS */
.quad 0x00cf92000000ffff /* __KERNEL_DS */
.quad 0x0080890000000000 /* TS descriptor */
.quad 0x0000000000000000 /* TS continued */
SYM_DATA_END_LABEL(efi_gdt64, SYM_L_LOCAL, efi_gdt64_end)
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <asm/nospec-branch.h> #include <asm/nospec-branch.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <linux/build_bug.h> #include <linux/build_bug.h>
#include <linux/kernel.h>
extern unsigned long efi_fw_vendor, efi_config_table; extern unsigned long efi_fw_vendor, efi_config_table;
...@@ -225,13 +226,15 @@ efi_status_t efi_set_virtual_address_map(unsigned long memory_map_size, ...@@ -225,13 +226,15 @@ efi_status_t efi_set_virtual_address_map(unsigned long memory_map_size,
/* arch specific definitions used by the stub code */ /* arch specific definitions used by the stub code */
extern const bool efi_is64; #ifdef CONFIG_EFI_MIXED
#define ARCH_HAS_EFISTUB_WRAPPERS
static inline bool efi_is_64bit(void) static inline bool efi_is_64bit(void)
{ {
if (IS_ENABLED(CONFIG_EFI_MIXED)) extern const bool efi_is64;
return efi_is64;
return IS_ENABLED(CONFIG_X86_64); return efi_is64;
} }
static inline bool efi_is_native(void) static inline bool efi_is_native(void)
...@@ -291,6 +294,15 @@ static inline u32 efi64_convert_status(efi_status_t status) ...@@ -291,6 +294,15 @@ static inline u32 efi64_convert_status(efi_status_t status)
#define __efi64_argmap_allocate_pool(type, size, buffer) \ #define __efi64_argmap_allocate_pool(type, size, buffer) \
((type), (size), efi64_zero_upper(buffer)) ((type), (size), efi64_zero_upper(buffer))
#define __efi64_argmap_create_event(type, tpl, f, c, event) \
((type), (tpl), (f), (c), efi64_zero_upper(event))
#define __efi64_argmap_set_timer(event, type, time) \
((event), (type), lower_32_bits(time), upper_32_bits(time))
#define __efi64_argmap_wait_for_event(num, event, index) \
((num), (event), efi64_zero_upper(index))
#define __efi64_argmap_handle_protocol(handle, protocol, interface) \ #define __efi64_argmap_handle_protocol(handle, protocol, interface) \
((handle), (protocol), efi64_zero_upper(interface)) ((handle), (protocol), efi64_zero_upper(interface))
...@@ -356,6 +368,15 @@ static inline u32 efi64_convert_status(efi_status_t status) ...@@ -356,6 +368,15 @@ static inline u32 efi64_convert_status(efi_status_t status)
runtime), \ runtime), \
func, __VA_ARGS__)) func, __VA_ARGS__))
#else /* CONFIG_EFI_MIXED */
static inline bool efi_is_64bit(void)
{
return IS_ENABLED(CONFIG_X86_64);
}
#endif /* CONFIG_EFI_MIXED */
extern bool efi_reboot_required(void); extern bool efi_reboot_required(void);
extern bool efi_is_table_address(unsigned long phys_addr); extern bool efi_is_table_address(unsigned long phys_addr);
......
...@@ -29,7 +29,7 @@ static efi_system_table_t efi_systab_xen __initdata = { ...@@ -29,7 +29,7 @@ static efi_system_table_t efi_systab_xen __initdata = {
.fw_vendor = EFI_INVALID_TABLE_ADDR, /* Initialized later. */ .fw_vendor = EFI_INVALID_TABLE_ADDR, /* Initialized later. */
.fw_revision = 0, /* Initialized later. */ .fw_revision = 0, /* Initialized later. */
.con_in_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ .con_in_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
.con_in = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ .con_in = NULL, /* Not used under Xen. */
.con_out_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ .con_out_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
.con_out = NULL, /* Not used under Xen. */ .con_out = NULL, /* Not used under Xen. */
.stderr_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */ .stderr_handle = EFI_INVALID_TABLE_ADDR, /* Not used under Xen. */
......
...@@ -522,8 +522,10 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var) ...@@ -522,8 +522,10 @@ efivar_create_sysfs_entry(struct efivar_entry *new_var)
ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype, ret = kobject_init_and_add(&new_var->kobj, &efivar_ktype,
NULL, "%s", short_name); NULL, "%s", short_name);
kfree(short_name); kfree(short_name);
if (ret) if (ret) {
kobject_put(&new_var->kobj);
return ret; return ret;
}
kobject_uevent(&new_var->kobj, KOBJ_ADD); kobject_uevent(&new_var->kobj, KOBJ_ADD);
if (efivar_entry_add(new_var, &efivar_sysfs_list)) { if (efivar_entry_add(new_var, &efivar_sysfs_list)) {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# #
cflags-$(CONFIG_X86_32) := -march=i386 cflags-$(CONFIG_X86_32) := -march=i386
cflags-$(CONFIG_X86_64) := -mcmodel=small cflags-$(CONFIG_X86_64) := -mcmodel=small
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ -O2 \ 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 \
-Wno-pointer-sign \ -Wno-pointer-sign \
...@@ -25,11 +25,12 @@ cflags-$(CONFIG_ARM) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \ ...@@ -25,11 +25,12 @@ cflags-$(CONFIG_ARM) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt cflags-$(CONFIG_EFI_GENERIC_STUB) += -I$(srctree)/scripts/dtc/libfdt
KBUILD_CFLAGS := $(cflags-y) -DDISABLE_BRANCH_PROFILING \ KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
-include $(srctree)/drivers/firmware/efi/libstub/hidden.h \ -include $(srctree)/drivers/firmware/efi/libstub/hidden.h \
-D__NO_FORTIFY \ -D__NO_FORTIFY \
$(call cc-option,-ffreestanding) \ $(call cc-option,-ffreestanding) \
$(call cc-option,-fno-stack-protector) \ $(call cc-option,-fno-stack-protector) \
$(call cc-option,-fno-addrsig) \
-D__DISABLE_EXPORTS -D__DISABLE_EXPORTS
GCOV_PROFILE := n GCOV_PROFILE := n
...@@ -43,7 +44,7 @@ KCOV_INSTRUMENT := n ...@@ -43,7 +44,7 @@ KCOV_INSTRUMENT := n
lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \ lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
file.o mem.o random.o randomalloc.o pci.o \ file.o mem.o random.o randomalloc.o pci.o \
skip_spaces.o lib-cmdline.o lib-ctype.o \ skip_spaces.o lib-cmdline.o lib-ctype.o \
alignedmem.o relocate.o alignedmem.o relocate.o vsprintf.o
# include the stub's generic dependencies from lib/ when building for ARM/arm64 # include the stub's generic dependencies from lib/ when building for ARM/arm64
efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c efi-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c
......
...@@ -18,7 +18,7 @@ efi_status_t check_platform_features(void) ...@@ -18,7 +18,7 @@ efi_status_t check_platform_features(void)
/* LPAE kernels need compatible hardware */ /* LPAE kernels need compatible hardware */
block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0); block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
if (block < 5) { if (block < 5) {
pr_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; return EFI_UNSUPPORTED;
} }
return EFI_SUCCESS; return EFI_SUCCESS;
...@@ -120,7 +120,7 @@ static efi_status_t reserve_kernel_base(unsigned long dram_base, ...@@ -120,7 +120,7 @@ static efi_status_t reserve_kernel_base(unsigned long dram_base,
*/ */
status = efi_get_memory_map(&map); status = efi_get_memory_map(&map);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n"); efi_err("reserve_kernel_base(): Unable to retrieve memory map.\n");
return status; return status;
} }
...@@ -162,7 +162,7 @@ static efi_status_t reserve_kernel_base(unsigned long dram_base, ...@@ -162,7 +162,7 @@ static efi_status_t reserve_kernel_base(unsigned long dram_base,
(end - start) / EFI_PAGE_SIZE, (end - start) / EFI_PAGE_SIZE,
&start); &start);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("reserve_kernel_base(): alloc failed.\n"); efi_err("reserve_kernel_base(): alloc failed.\n");
goto out; goto out;
} }
break; break;
...@@ -219,7 +219,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -219,7 +219,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
status = reserve_kernel_base(kernel_base, reserve_addr, reserve_size); status = reserve_kernel_base(kernel_base, reserve_addr, reserve_size);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Unable to allocate memory for uncompressed kernel.\n"); efi_err("Unable to allocate memory for uncompressed kernel.\n");
return status; return status;
} }
...@@ -232,7 +232,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -232,7 +232,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
status = efi_relocate_kernel(image_addr, *image_size, *image_size, status = efi_relocate_kernel(image_addr, *image_size, *image_size,
kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0, 0); kernel_base + MAX_UNCOMP_KERNEL_SIZE, 0, 0);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to relocate kernel.\n"); efi_err("Failed to relocate kernel.\n");
efi_free(*reserve_size, *reserve_addr); efi_free(*reserve_size, *reserve_addr);
*reserve_size = 0; *reserve_size = 0;
return status; return status;
...@@ -244,7 +244,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -244,7 +244,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
* address at which the zImage is loaded. * address at which the zImage is loaded.
*/ */
if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) { if (*image_addr + *image_size > dram_base + ZIMAGE_OFFSET_LIMIT) {
pr_efi_err("Failed to relocate kernel, no low memory available.\n"); efi_err("Failed to relocate kernel, no low memory available.\n");
efi_free(*reserve_size, *reserve_addr); efi_free(*reserve_size, *reserve_addr);
*reserve_size = 0; *reserve_size = 0;
efi_free(*image_size, *image_addr); efi_free(*image_size, *image_addr);
......
...@@ -26,9 +26,9 @@ efi_status_t check_platform_features(void) ...@@ -26,9 +26,9 @@ efi_status_t check_platform_features(void)
tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf; tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_TGRAN_SHIFT) & 0xf;
if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) { if (tg != ID_AA64MMFR0_TGRAN_SUPPORTED) {
if (IS_ENABLED(CONFIG_ARM64_64K_PAGES)) if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
pr_efi_err("This 64 KB granular kernel is not supported by your CPU\n"); efi_err("This 64 KB granular kernel is not supported by your CPU\n");
else else
pr_efi_err("This 16 KB granular kernel is not supported by your CPU\n"); efi_err("This 16 KB granular kernel is not supported by your CPU\n");
return EFI_UNSUPPORTED; return EFI_UNSUPPORTED;
} }
return EFI_SUCCESS; return EFI_SUCCESS;
...@@ -59,18 +59,18 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -59,18 +59,18 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
status = efi_get_random_bytes(sizeof(phys_seed), status = efi_get_random_bytes(sizeof(phys_seed),
(u8 *)&phys_seed); (u8 *)&phys_seed);
if (status == EFI_NOT_FOUND) { if (status == EFI_NOT_FOUND) {
pr_efi("EFI_RNG_PROTOCOL unavailable, no randomness supplied\n"); efi_info("EFI_RNG_PROTOCOL unavailable, no randomness supplied\n");
} else if (status != EFI_SUCCESS) { } else if (status != EFI_SUCCESS) {
pr_efi_err("efi_get_random_bytes() failed\n"); efi_err("efi_get_random_bytes() failed\n");
return status; return status;
} }
} else { } else {
pr_efi("KASLR disabled on kernel command line\n"); efi_info("KASLR disabled on kernel command line\n");
} }
} }
if (image->image_base != _text) if (image->image_base != _text)
pr_efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n"); efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
kernel_size = _edata - _text; kernel_size = _edata - _text;
kernel_memsize = kernel_size + (_end - _edata); kernel_memsize = kernel_size + (_end - _edata);
...@@ -102,7 +102,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -102,7 +102,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
ULONG_MAX, min_kimg_align); ULONG_MAX, min_kimg_align);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to relocate kernel\n"); efi_err("Failed to relocate kernel\n");
*reserve_size = 0; *reserve_size = 0;
return status; return status;
} }
......
...@@ -73,7 +73,7 @@ static void install_memreserve_table(void) ...@@ -73,7 +73,7 @@ static void install_memreserve_table(void)
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv), status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
(void **)&rsv); (void **)&rsv);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to allocate memreserve entry!\n"); efi_err("Failed to allocate memreserve entry!\n");
return; return;
} }
...@@ -84,7 +84,7 @@ static void install_memreserve_table(void) ...@@ -84,7 +84,7 @@ static void install_memreserve_table(void)
status = efi_bs_call(install_configuration_table, status = efi_bs_call(install_configuration_table,
&memreserve_table_guid, rsv); &memreserve_table_guid, rsv);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
pr_efi_err("Failed to install memreserve config table!\n"); efi_err("Failed to install memreserve config table!\n");
} }
static unsigned long get_dram_base(void) static unsigned long get_dram_base(void)
...@@ -144,7 +144,8 @@ asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint, ...@@ -144,7 +144,8 @@ asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
* for both archictectures, with the arch-specific code provided in the * for both archictectures, with the arch-specific code provided in the
* handle_kernel_image() function. * handle_kernel_image() function.
*/ */
efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg) efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_system_table_t *sys_table_arg)
{ {
efi_loaded_image_t *image; efi_loaded_image_t *image;
efi_status_t status; efi_status_t status;
...@@ -186,13 +187,13 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg) ...@@ -186,13 +187,13 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
status = efi_system_table->boottime->handle_protocol(handle, status = efi_system_table->boottime->handle_protocol(handle,
&loaded_image_proto, (void *)&image); &loaded_image_proto, (void *)&image);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to get loaded image protocol\n"); efi_err("Failed to get loaded image protocol\n");
goto fail; goto fail;
} }
dram_base = get_dram_base(); dram_base = get_dram_base();
if (dram_base == EFI_ERROR) { if (dram_base == EFI_ERROR) {
pr_efi_err("Failed to find DRAM base\n"); efi_err("Failed to find DRAM base\n");
status = EFI_LOAD_ERROR; status = EFI_LOAD_ERROR;
goto fail; goto fail;
} }
...@@ -202,22 +203,32 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg) ...@@ -202,22 +203,32 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
* protocol. We are going to copy the command line into the * protocol. We are going to copy the command line into the
* device tree, so this can be allocated anywhere. * device tree, so this can be allocated anywhere.
*/ */
cmdline_ptr = efi_convert_cmdline(image, &cmdline_size, ULONG_MAX); cmdline_ptr = efi_convert_cmdline(image, &cmdline_size);
if (!cmdline_ptr) { if (!cmdline_ptr) {
pr_efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n"); efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
status = EFI_OUT_OF_RESOURCES; status = EFI_OUT_OF_RESOURCES;
goto fail; goto fail;
} }
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
IS_ENABLED(CONFIG_CMDLINE_FORCE) || IS_ENABLED(CONFIG_CMDLINE_FORCE) ||
cmdline_size == 0) cmdline_size == 0) {
efi_parse_options(CONFIG_CMDLINE); status = efi_parse_options(CONFIG_CMDLINE);
if (status != EFI_SUCCESS) {
efi_err("Failed to parse options\n");
goto fail_free_cmdline;
}
}
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
efi_parse_options(cmdline_ptr); status = efi_parse_options(cmdline_ptr);
if (status != EFI_SUCCESS) {
efi_err("Failed to parse options\n");
goto fail_free_cmdline;
}
}
pr_efi("Booting Linux Kernel...\n"); efi_info("Booting Linux Kernel...\n");
si = setup_graphics(); si = setup_graphics();
...@@ -226,8 +237,8 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg) ...@@ -226,8 +237,8 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
&reserve_size, &reserve_size,
dram_base, image); dram_base, image);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to relocate kernel\n"); efi_err("Failed to relocate kernel\n");
goto fail_free_cmdline; goto fail_free_screeninfo;
} }
efi_retrieve_tpm2_eventlog(); efi_retrieve_tpm2_eventlog();
...@@ -245,42 +256,34 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg) ...@@ -245,42 +256,34 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) || if (!IS_ENABLED(CONFIG_EFI_ARMSTUB_DTB_LOADER) ||
secure_boot != efi_secureboot_mode_disabled) { secure_boot != efi_secureboot_mode_disabled) {
if (strstr(cmdline_ptr, "dtb=")) if (strstr(cmdline_ptr, "dtb="))
pr_efi("Ignoring DTB from command line.\n"); efi_err("Ignoring DTB from command line.\n");
} else { } else {
status = efi_load_dtb(image, &fdt_addr, &fdt_size); status = efi_load_dtb(image, &fdt_addr, &fdt_size);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to load device tree!\n"); efi_err("Failed to load device tree!\n");
goto fail_free_image; goto fail_free_image;
} }
} }
if (fdt_addr) { if (fdt_addr) {
pr_efi("Using DTB from command line\n"); efi_info("Using DTB from command line\n");
} else { } else {
/* Look for a device tree configuration table entry. */ /* Look for a device tree configuration table entry. */
fdt_addr = (uintptr_t)get_fdt(&fdt_size); fdt_addr = (uintptr_t)get_fdt(&fdt_size);
if (fdt_addr) if (fdt_addr)
pr_efi("Using DTB from configuration table\n"); efi_info("Using DTB from configuration table\n");
} }
if (!fdt_addr) if (!fdt_addr)
pr_efi("Generating empty DTB\n"); efi_info("Generating empty DTB\n");
if (!efi_noinitrd) { if (!efi_noinitrd) {
max_addr = efi_get_max_initrd_addr(dram_base, image_addr); max_addr = efi_get_max_initrd_addr(dram_base, image_addr);
status = efi_load_initrd_dev_path(&initrd_addr, &initrd_size, status = efi_load_initrd(image, &initrd_addr, &initrd_size,
max_addr); ULONG_MAX, max_addr);
if (status == EFI_SUCCESS) {
pr_efi("Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID device path\n");
} else if (status == EFI_NOT_FOUND) {
status = efi_load_initrd(image, &initrd_addr, &initrd_size,
ULONG_MAX, max_addr);
if (status == EFI_SUCCESS && initrd_size > 0)
pr_efi("Loaded initrd from command line option\n");
}
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
pr_efi_err("Failed to load initrd!\n"); efi_err("Failed to load initrd!\n");
} }
efi_random_get_seed(); efi_random_get_seed();
...@@ -330,7 +333,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg) ...@@ -330,7 +333,7 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
/* not reached */ /* not reached */
fail_free_initrd: fail_free_initrd:
pr_efi_err("Failed to update FDT and exit boot services\n"); efi_err("Failed to update FDT and exit boot services\n");
efi_free(initrd_size, initrd_addr); efi_free(initrd_size, initrd_addr);
efi_free(fdt_size, fdt_addr); efi_free(fdt_size, fdt_addr);
...@@ -338,9 +341,10 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg) ...@@ -338,9 +341,10 @@ efi_status_t efi_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg)
fail_free_image: fail_free_image:
efi_free(image_size, image_addr); efi_free(image_size, image_addr);
efi_free(reserve_size, reserve_addr); efi_free(reserve_size, reserve_addr);
fail_free_cmdline: fail_free_screeninfo:
free_screen_info(si); free_screen_info(si);
efi_free(cmdline_size, (unsigned long)cmdline_ptr); fail_free_cmdline:
efi_bs_call(free_pool, cmdline_ptr);
fail: fail:
return status; return status;
} }
......
...@@ -3,6 +3,13 @@ ...@@ -3,6 +3,13 @@
#ifndef _DRIVERS_FIRMWARE_EFI_EFISTUB_H #ifndef _DRIVERS_FIRMWARE_EFI_EFISTUB_H
#define _DRIVERS_FIRMWARE_EFI_EFISTUB_H #define _DRIVERS_FIRMWARE_EFI_EFISTUB_H
#include <linux/compiler.h>
#include <linux/efi.h>
#include <linux/kernel.h>
#include <linux/kern_levels.h>
#include <linux/types.h>
#include <asm/efi.h>
/* error code which can't be mistaken for valid address */ /* error code which can't be mistaken for valid address */
#define EFI_ERROR (~0UL) #define EFI_ERROR (~0UL)
...@@ -28,32 +35,30 @@ ...@@ -28,32 +35,30 @@
extern bool efi_nochunk; extern bool efi_nochunk;
extern bool efi_nokaslr; extern bool efi_nokaslr;
extern bool efi_noinitrd; extern bool efi_noinitrd;
extern bool efi_quiet; extern int efi_loglevel;
extern bool efi_novamap; extern bool efi_novamap;
extern const efi_system_table_t *efi_system_table; extern const efi_system_table_t *efi_system_table;
#ifndef efi_bs_call efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_system_table_t *sys_table_arg);
#ifndef ARCH_HAS_EFISTUB_WRAPPERS
#define efi_is_native() (true)
#define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__) #define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__)
#endif
#ifndef efi_rt_call
#define efi_rt_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__) #define efi_rt_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__)
#endif
#ifndef efi_is_native
#define efi_is_native() (true)
#endif
#ifndef efi_table_attr
#define efi_table_attr(inst, attr) (inst->attr) #define efi_table_attr(inst, attr) (inst->attr)
#endif
#ifndef efi_call_proto
#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__) #define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
#endif
#define pr_efi(msg) do { \ #endif
if (!efi_quiet) efi_printk("EFI stub: "msg); \
} while (0)
#define pr_efi_err(msg) efi_printk("EFI stub: ERROR: "msg) #define efi_info(fmt, ...) \
efi_printk(KERN_INFO fmt, ##__VA_ARGS__)
#define efi_err(fmt, ...) \
efi_printk(KERN_ERR "ERROR: " fmt, ##__VA_ARGS__)
#define efi_debug(fmt, ...) \
efi_printk(KERN_DEBUG "DEBUG: " fmt, ##__VA_ARGS__)
/* Helper macros for the usual case of using simple C variables: */ /* Helper macros for the usual case of using simple C variables: */
#ifndef fdt_setprop_inplace_var #ifndef fdt_setprop_inplace_var
...@@ -87,6 +92,13 @@ extern const efi_system_table_t *efi_system_table; ...@@ -87,6 +92,13 @@ extern const efi_system_table_t *efi_system_table;
((handle = efi_get_handle_at((array), i)) || true); \ ((handle = efi_get_handle_at((array), i)) || true); \
i++) i++)
static inline
void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
{
*lo = lower_32_bits(data);
*hi = upper_32_bits(data);
}
/* /*
* Allocation types for calls to boottime->allocate_pages. * Allocation types for calls to boottime->allocate_pages.
*/ */
...@@ -102,6 +114,16 @@ extern const efi_system_table_t *efi_system_table; ...@@ -102,6 +114,16 @@ extern const efi_system_table_t *efi_system_table;
#define EFI_LOCATE_BY_REGISTER_NOTIFY 1 #define EFI_LOCATE_BY_REGISTER_NOTIFY 1
#define EFI_LOCATE_BY_PROTOCOL 2 #define EFI_LOCATE_BY_PROTOCOL 2
/*
* boottime->stall takes the time period in microseconds
*/
#define EFI_USEC_PER_SEC 1000000
/*
* boottime->set_timer takes the time in 100ns units
*/
#define EFI_100NSEC_PER_USEC ((u64)10)
/* /*
* An efi_boot_memmap is used by efi_get_memory_map() to return the * An efi_boot_memmap is used by efi_get_memory_map() to return the
* EFI memory map in a dynamically allocated buffer. * EFI memory map in a dynamically allocated buffer.
...@@ -126,6 +148,39 @@ struct efi_boot_memmap { ...@@ -126,6 +148,39 @@ struct efi_boot_memmap {
typedef struct efi_generic_dev_path efi_device_path_protocol_t; typedef struct efi_generic_dev_path efi_device_path_protocol_t;
typedef void *efi_event_t;
/* Note that notifications won't work in mixed mode */
typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *);
#define EFI_EVT_TIMER 0x80000000U
#define EFI_EVT_RUNTIME 0x40000000U
#define EFI_EVT_NOTIFY_WAIT 0x00000100U
#define EFI_EVT_NOTIFY_SIGNAL 0x00000200U
/*
* boottime->wait_for_event takes an array of events as input.
* Provide a helper to set it up correctly for mixed mode.
*/
static inline
void efi_set_event_at(efi_event_t *events, size_t idx, efi_event_t event)
{
if (efi_is_native())
events[idx] = event;
else
((u32 *)events)[idx] = (u32)(unsigned long)event;
}
#define EFI_TPL_APPLICATION 4
#define EFI_TPL_CALLBACK 8
#define EFI_TPL_NOTIFY 16
#define EFI_TPL_HIGH_LEVEL 31
typedef enum {
EfiTimerCancel,
EfiTimerPeriodic,
EfiTimerRelative
} EFI_TIMER_DELAY;
/* /*
* EFI Boot Services table * EFI Boot Services table
*/ */
...@@ -144,11 +199,16 @@ union efi_boot_services { ...@@ -144,11 +199,16 @@ union efi_boot_services {
efi_status_t (__efiapi *allocate_pool)(int, unsigned long, efi_status_t (__efiapi *allocate_pool)(int, unsigned long,
void **); void **);
efi_status_t (__efiapi *free_pool)(void *); efi_status_t (__efiapi *free_pool)(void *);
void *create_event; efi_status_t (__efiapi *create_event)(u32, unsigned long,
void *set_timer; efi_event_notify_t, void *,
void *wait_for_event; efi_event_t *);
efi_status_t (__efiapi *set_timer)(efi_event_t,
EFI_TIMER_DELAY, u64);
efi_status_t (__efiapi *wait_for_event)(unsigned long,
efi_event_t *,
unsigned long *);
void *signal_event; void *signal_event;
void *close_event; efi_status_t (__efiapi *close_event)(efi_event_t);
void *check_event; void *check_event;
void *install_protocol_interface; void *install_protocol_interface;
void *reinstall_protocol_interface; void *reinstall_protocol_interface;
...@@ -175,7 +235,7 @@ union efi_boot_services { ...@@ -175,7 +235,7 @@ union efi_boot_services {
efi_status_t (__efiapi *exit_boot_services)(efi_handle_t, efi_status_t (__efiapi *exit_boot_services)(efi_handle_t,
unsigned long); unsigned long);
void *get_next_monotonic_count; void *get_next_monotonic_count;
void *stall; efi_status_t (__efiapi *stall)(unsigned long);
void *set_watchdog_timer; void *set_watchdog_timer;
void *connect_controller; void *connect_controller;
efi_status_t (__efiapi *disconnect_controller)(efi_handle_t, efi_status_t (__efiapi *disconnect_controller)(efi_handle_t,
...@@ -260,6 +320,27 @@ union efi_uga_draw_protocol { ...@@ -260,6 +320,27 @@ union efi_uga_draw_protocol {
} mixed_mode; } mixed_mode;
}; };
typedef struct {
u16 scan_code;
efi_char16_t unicode_char;
} efi_input_key_t;
union efi_simple_text_input_protocol {
struct {
void *reset;
efi_status_t (__efiapi *read_keystroke)(efi_simple_text_input_protocol_t *,
efi_input_key_t *);
efi_event_t wait_for_key;
};
struct {
u32 reset;
u32 read_keystroke;
u32 wait_for_key;
} mixed_mode;
};
efi_status_t efi_wait_for_key(unsigned long usec, efi_input_key_t *key);
union efi_simple_text_output_protocol { union efi_simple_text_output_protocol {
struct { struct {
void *reset; void *reset;
...@@ -612,8 +693,6 @@ efi_status_t efi_exit_boot_services(void *handle, ...@@ -612,8 +693,6 @@ efi_status_t efi_exit_boot_services(void *handle,
void *priv, void *priv,
efi_exit_boot_map_processing priv_func); efi_exit_boot_map_processing priv_func);
void efi_char16_printk(efi_char16_t *);
efi_status_t allocate_new_fdt_and_exit_boot(void *handle, efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
unsigned long *new_fdt_addr, unsigned long *new_fdt_addr,
unsigned long max_addr, unsigned long max_addr,
...@@ -637,12 +716,15 @@ efi_status_t check_platform_features(void); ...@@ -637,12 +716,15 @@ efi_status_t check_platform_features(void);
void *get_efi_config_table(efi_guid_t guid); void *get_efi_config_table(efi_guid_t guid);
void efi_printk(char *str); /* NOTE: These functions do not print a trailing newline after the string */
void efi_char16_puts(efi_char16_t *);
void efi_puts(const char *str);
__printf(1, 2) int efi_printk(char const *fmt, ...);
void efi_free(unsigned long size, unsigned long addr); void efi_free(unsigned long size, unsigned long addr);
char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len, char *efi_convert_cmdline(efi_loaded_image_t *image, int *cmd_line_len);
unsigned long max_addr);
efi_status_t efi_get_memory_map(struct efi_boot_memmap *map); efi_status_t efi_get_memory_map(struct efi_boot_memmap *map);
...@@ -683,21 +765,10 @@ static inline efi_status_t efi_load_dtb(efi_loaded_image_t *image, ...@@ -683,21 +765,10 @@ static inline efi_status_t efi_load_dtb(efi_loaded_image_t *image,
ULONG_MAX, ULONG_MAX, load_addr, load_size); ULONG_MAX, ULONG_MAX, load_addr, load_size);
} }
static inline 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,
unsigned long soft_limit, unsigned long soft_limit,
unsigned long hard_limit) unsigned long hard_limit);
{
if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER))
return EFI_SUCCESS;
return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
soft_limit, hard_limit, load_addr, load_size);
}
efi_status_t efi_load_initrd_dev_path(unsigned long *load_addr,
unsigned long *load_size,
unsigned long max);
#endif #endif
...@@ -39,7 +39,7 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size, ...@@ -39,7 +39,7 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
/* Do some checks on provided FDT, if it exists: */ /* Do some checks on provided FDT, if it exists: */
if (orig_fdt) { if (orig_fdt) {
if (fdt_check_header(orig_fdt)) { if (fdt_check_header(orig_fdt)) {
pr_efi_err("Device Tree header not valid!\n"); efi_err("Device Tree header not valid!\n");
return EFI_LOAD_ERROR; return EFI_LOAD_ERROR;
} }
/* /*
...@@ -47,7 +47,7 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size, ...@@ -47,7 +47,7 @@ static efi_status_t update_fdt(void *orig_fdt, unsigned long orig_fdt_size,
* configuration table: * configuration table:
*/ */
if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) { if (orig_fdt_size && fdt_totalsize(orig_fdt) > orig_fdt_size) {
pr_efi_err("Truncated device tree! foo!\n"); efi_err("Truncated device tree! foo!\n");
return EFI_LOAD_ERROR; return EFI_LOAD_ERROR;
} }
} }
...@@ -270,16 +270,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, ...@@ -270,16 +270,16 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
*/ */
status = efi_get_memory_map(&map); status = efi_get_memory_map(&map);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Unable to retrieve UEFI memory map.\n"); efi_err("Unable to retrieve UEFI memory map.\n");
return status; return status;
} }
pr_efi("Exiting boot services and installing virtual address map...\n"); efi_info("Exiting boot services and installing virtual address map...\n");
map.map = &memory_map; map.map = &memory_map;
status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, max_addr); status = efi_allocate_pages(MAX_FDT_SIZE, new_fdt_addr, max_addr);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Unable to allocate memory for new device tree.\n"); efi_err("Unable to allocate memory for new device tree.\n");
goto fail; goto fail;
} }
...@@ -296,7 +296,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, ...@@ -296,7 +296,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
initrd_addr, initrd_size); initrd_addr, initrd_size);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Unable to construct new device tree.\n"); efi_err("Unable to construct new device tree.\n");
goto fail_free_new_fdt; goto fail_free_new_fdt;
} }
...@@ -342,7 +342,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle, ...@@ -342,7 +342,7 @@ efi_status_t allocate_new_fdt_and_exit_boot(void *handle,
return EFI_SUCCESS; return EFI_SUCCESS;
} }
pr_efi_err("Exit boot services failed.\n"); efi_err("Exit boot services failed.\n");
fail_free_new_fdt: fail_free_new_fdt:
efi_free(MAX_FDT_SIZE, *new_fdt_addr); efi_free(MAX_FDT_SIZE, *new_fdt_addr);
...@@ -363,7 +363,7 @@ void *get_fdt(unsigned long *fdt_size) ...@@ -363,7 +363,7 @@ void *get_fdt(unsigned long *fdt_size)
return NULL; return NULL;
if (fdt_check_header(fdt) != 0) { if (fdt_check_header(fdt) != 0) {
pr_efi_err("Invalid header detected on UEFI supplied FDT, ignoring ...\n"); efi_err("Invalid header detected on UEFI supplied FDT, ignoring ...\n");
return NULL; return NULL;
} }
*fdt_size = fdt_totalsize(fdt); *fdt_size = fdt_totalsize(fdt);
......
...@@ -46,16 +46,14 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume, ...@@ -46,16 +46,14 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0); status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to open file: "); efi_err("Failed to open file: %ls\n", fi->filename);
efi_char16_printk(fi->filename);
efi_printk("\n");
return status; return status;
} }
info_sz = sizeof(struct finfo); info_sz = sizeof(struct finfo);
status = fh->get_info(fh, &info_guid, &info_sz, fi); status = fh->get_info(fh, &info_guid, &info_sz, fi);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to get file info\n"); efi_err("Failed to get file info\n");
fh->close(fh); fh->close(fh);
return status; return status;
} }
...@@ -75,13 +73,13 @@ static efi_status_t efi_open_volume(efi_loaded_image_t *image, ...@@ -75,13 +73,13 @@ static efi_status_t efi_open_volume(efi_loaded_image_t *image,
status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto, status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto,
(void **)&io); (void **)&io);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to handle fs_proto\n"); efi_err("Failed to handle fs_proto\n");
return status; return status;
} }
status = io->open_volume(io, fh); status = io->open_volume(io, fh);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
pr_efi_err("Failed to open volume\n"); efi_err("Failed to open volume\n");
return status; return status;
} }
...@@ -191,7 +189,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, ...@@ -191,7 +189,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
&alloc_addr, &alloc_addr,
hard_limit); hard_limit);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to allocate memory for files\n"); efi_err("Failed to allocate memory for files\n");
goto err_close_file; goto err_close_file;
} }
...@@ -215,7 +213,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image, ...@@ -215,7 +213,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
status = file->read(file, &chunksize, addr); status = file->read(file, &chunksize, addr);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to read file\n"); efi_err("Failed to read file\n");
goto err_close_file; goto err_close_file;
} }
addr += chunksize; addr += chunksize;
......
...@@ -19,7 +19,8 @@ enum efi_cmdline_option { ...@@ -19,7 +19,8 @@ enum efi_cmdline_option {
EFI_CMDLINE_NONE, EFI_CMDLINE_NONE,
EFI_CMDLINE_MODE_NUM, EFI_CMDLINE_MODE_NUM,
EFI_CMDLINE_RES, EFI_CMDLINE_RES,
EFI_CMDLINE_AUTO EFI_CMDLINE_AUTO,
EFI_CMDLINE_LIST
}; };
static struct { static struct {
...@@ -100,6 +101,19 @@ static bool parse_auto(char *option, char **next) ...@@ -100,6 +101,19 @@ static bool parse_auto(char *option, char **next)
return true; return true;
} }
static bool parse_list(char *option, char **next)
{
if (!strstarts(option, "list"))
return false;
option += strlen("list");
if (*option && *option++ != ',')
return false;
cmdline.option = EFI_CMDLINE_LIST;
*next = option;
return true;
}
void efi_parse_option_graphics(char *option) void efi_parse_option_graphics(char *option)
{ {
while (*option) { while (*option) {
...@@ -109,6 +123,8 @@ void efi_parse_option_graphics(char *option) ...@@ -109,6 +123,8 @@ void efi_parse_option_graphics(char *option)
continue; continue;
if (parse_auto(option, &option)) if (parse_auto(option, &option))
continue; continue;
if (parse_list(option, &option))
continue;
while (*option && *option++ != ',') while (*option && *option++ != ',')
; ;
...@@ -134,14 +150,14 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop) ...@@ -134,14 +150,14 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
max_mode = efi_table_attr(mode, max_mode); max_mode = efi_table_attr(mode, max_mode);
if (cmdline.mode >= max_mode) { if (cmdline.mode >= max_mode) {
efi_printk("Requested mode is invalid\n"); efi_err("Requested mode is invalid\n");
return cur_mode; return cur_mode;
} }
status = efi_call_proto(gop, query_mode, cmdline.mode, status = efi_call_proto(gop, query_mode, cmdline.mode,
&info_size, &info); &info_size, &info);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Couldn't get mode information\n"); efi_err("Couldn't get mode information\n");
return cur_mode; return cur_mode;
} }
...@@ -150,7 +166,7 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop) ...@@ -150,7 +166,7 @@ static u32 choose_mode_modenum(efi_graphics_output_protocol_t *gop)
efi_bs_call(free_pool, info); efi_bs_call(free_pool, info);
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) { if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX) {
efi_printk("Invalid PixelFormat\n"); efi_err("Invalid PixelFormat\n");
return cur_mode; return cur_mode;
} }
...@@ -222,7 +238,7 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop) ...@@ -222,7 +238,7 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
return m; return m;
} }
efi_printk("Couldn't find requested mode\n"); efi_err("Couldn't find requested mode\n");
return cur_mode; return cur_mode;
} }
...@@ -290,6 +306,82 @@ static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop) ...@@ -290,6 +306,82 @@ static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop)
return best_mode; return best_mode;
} }
static u32 choose_mode_list(efi_graphics_output_protocol_t *gop)
{
efi_status_t status;
efi_graphics_output_protocol_mode_t *mode;
efi_graphics_output_mode_info_t *info;
unsigned long info_size;
u32 max_mode, cur_mode;
int pf;
efi_pixel_bitmask_t pi;
u32 m, w, h;
u8 d;
const char *dstr;
bool valid;
efi_input_key_t key;
mode = efi_table_attr(gop, mode);
cur_mode = efi_table_attr(mode, mode);
max_mode = efi_table_attr(mode, max_mode);
efi_printk("Available graphics modes are 0-%u\n", max_mode-1);
efi_puts(" * = current mode\n"
" - = unusable mode\n");
for (m = 0; m < max_mode; m++) {
status = efi_call_proto(gop, query_mode, m,
&info_size, &info);
if (status != EFI_SUCCESS)
continue;
pf = info->pixel_format;
pi = info->pixel_information;
w = info->horizontal_resolution;
h = info->vertical_resolution;
efi_bs_call(free_pool, info);
valid = !(pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX);
d = 0;
switch (pf) {
case PIXEL_RGB_RESERVED_8BIT_PER_COLOR:
dstr = "rgb";
break;
case PIXEL_BGR_RESERVED_8BIT_PER_COLOR:
dstr = "bgr";
break;
case PIXEL_BIT_MASK:
dstr = "";
d = pixel_bpp(pf, pi);
break;
case PIXEL_BLT_ONLY:
dstr = "blt";
break;
default:
dstr = "xxx";
break;
}
efi_printk("Mode %3u %c%c: Resolution %ux%u-%s%.0hhu\n",
m,
m == cur_mode ? '*' : ' ',
!valid ? '-' : ' ',
w, h, dstr, d);
}
efi_puts("\nPress any key to continue (or wait 10 seconds)\n");
status = efi_wait_for_key(10 * EFI_USEC_PER_SEC, &key);
if (status != EFI_SUCCESS && status != EFI_TIMEOUT) {
efi_err("Unable to read key, continuing in 10 seconds\n");
efi_bs_call(stall, 10 * EFI_USEC_PER_SEC);
}
return cur_mode;
}
static void set_mode(efi_graphics_output_protocol_t *gop) static void set_mode(efi_graphics_output_protocol_t *gop)
{ {
efi_graphics_output_protocol_mode_t *mode; efi_graphics_output_protocol_mode_t *mode;
...@@ -305,6 +397,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop) ...@@ -305,6 +397,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
case EFI_CMDLINE_AUTO: case EFI_CMDLINE_AUTO:
new_mode = choose_mode_auto(gop); new_mode = choose_mode_auto(gop);
break; break;
case EFI_CMDLINE_LIST:
new_mode = choose_mode_list(gop);
break;
default: default:
return; return;
} }
...@@ -316,7 +411,7 @@ static void set_mode(efi_graphics_output_protocol_t *gop) ...@@ -316,7 +411,7 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
return; return;
if (efi_call_proto(gop, set_mode, new_mode) != EFI_SUCCESS) if (efi_call_proto(gop, set_mode, new_mode) != EFI_SUCCESS)
efi_printk("Failed to set requested mode\n"); efi_err("Failed to set requested mode\n");
} }
static void find_bits(u32 mask, u8 *pos, u8 *size) static void find_bits(u32 mask, u8 *pos, u8 *size)
...@@ -422,7 +517,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, ...@@ -422,7 +517,6 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
efi_graphics_output_protocol_t *gop; efi_graphics_output_protocol_t *gop;
efi_graphics_output_protocol_mode_t *mode; efi_graphics_output_protocol_mode_t *mode;
efi_graphics_output_mode_info_t *info; efi_graphics_output_mode_info_t *info;
efi_physical_addr_t fb_base;
gop = find_gop(proto, size, handles); gop = find_gop(proto, size, handles);
...@@ -442,9 +536,8 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto, ...@@ -442,9 +536,8 @@ static efi_status_t setup_gop(struct screen_info *si, efi_guid_t *proto,
si->lfb_width = info->horizontal_resolution; si->lfb_width = info->horizontal_resolution;
si->lfb_height = info->vertical_resolution; si->lfb_height = info->vertical_resolution;
fb_base = efi_table_attr(mode, frame_buffer_base); efi_set_u64_split(efi_table_attr(mode, frame_buffer_base),
si->lfb_base = lower_32_bits(fb_base); &si->lfb_base, &si->ext_lfb_base);
si->ext_lfb_base = upper_32_bits(fb_base);
if (si->ext_lfb_base) if (si->ext_lfb_base)
si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE; si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
......
...@@ -28,21 +28,21 @@ void efi_pci_disable_bridge_busmaster(void) ...@@ -28,21 +28,21 @@ void efi_pci_disable_bridge_busmaster(void)
if (status != EFI_BUFFER_TOO_SMALL) { if (status != EFI_BUFFER_TOO_SMALL) {
if (status != EFI_SUCCESS && status != EFI_NOT_FOUND) if (status != EFI_SUCCESS && status != EFI_NOT_FOUND)
pr_efi_err("Failed to locate PCI I/O handles'\n"); efi_err("Failed to locate PCI I/O handles'\n");
return; return;
} }
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, pci_handle_size, status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, pci_handle_size,
(void **)&pci_handle); (void **)&pci_handle);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to allocate memory for 'pci_handle'\n"); efi_err("Failed to allocate memory for 'pci_handle'\n");
return; return;
} }
status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto, status = efi_bs_call(locate_handle, EFI_LOCATE_BY_PROTOCOL, &pci_proto,
NULL, &pci_handle_size, pci_handle); NULL, &pci_handle_size, pci_handle);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to locate PCI I/O handles'\n"); efi_err("Failed to locate PCI I/O handles'\n");
goto free_handle; goto free_handle;
} }
...@@ -69,7 +69,7 @@ void efi_pci_disable_bridge_busmaster(void) ...@@ -69,7 +69,7 @@ void efi_pci_disable_bridge_busmaster(void)
* access to the framebuffer. Drivers for true PCIe graphics * access to the framebuffer. Drivers for true PCIe graphics
* controllers that are behind a PCIe root port do not use * controllers that are behind a PCIe root port do not use
* DMA to implement the GOP framebuffer anyway [although they * DMA to implement the GOP framebuffer anyway [although they
* may use it in their implentation of Gop->Blt()], and so * may use it in their implementation of Gop->Blt()], and so
* disabling DMA in the PCI bridge should not interfere with * disabling DMA in the PCI bridge should not interfere with
* normal operation of the device. * normal operation of the device.
*/ */
...@@ -106,7 +106,7 @@ void efi_pci_disable_bridge_busmaster(void) ...@@ -106,7 +106,7 @@ void efi_pci_disable_bridge_busmaster(void)
status = efi_call_proto(pci, pci.write, EfiPciIoWidthUint16, status = efi_call_proto(pci, pci.write, EfiPciIoWidthUint16,
PCI_COMMAND, 1, &command); PCI_COMMAND, 1, &command);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
pr_efi_err("Failed to disable PCI busmastering\n"); efi_err("Failed to disable PCI busmastering\n");
} }
free_handle: free_handle:
......
...@@ -140,7 +140,7 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr, ...@@ -140,7 +140,7 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
* The EFI firmware loader could have placed the kernel image * The EFI firmware loader could have placed the kernel image
* anywhere in memory, but the kernel has restrictions on the * anywhere in memory, but the kernel has restrictions on the
* max physical address it can run at. Some architectures * max physical address it can run at. Some architectures
* also have a prefered address, so first try to relocate * also have a preferred address, so first try to relocate
* to the preferred address. If that fails, allocate as low * to the preferred address. If that fails, allocate as low
* as possible while respecting the required alignment. * as possible while respecting the required alignment.
*/ */
...@@ -157,7 +157,7 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr, ...@@ -157,7 +157,7 @@ efi_status_t efi_relocate_kernel(unsigned long *image_addr,
min_addr); min_addr);
} }
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
pr_efi_err("Failed to allocate usable memory for kernel.\n"); efi_err("Failed to allocate usable memory for kernel.\n");
return status; return status;
} }
......
...@@ -67,10 +67,10 @@ enum efi_secureboot_mode efi_get_secureboot(void) ...@@ -67,10 +67,10 @@ enum efi_secureboot_mode efi_get_secureboot(void)
return efi_secureboot_mode_disabled; return efi_secureboot_mode_disabled;
secure_boot_enabled: secure_boot_enabled:
pr_efi("UEFI Secure Boot is enabled.\n"); efi_info("UEFI Secure Boot is enabled.\n");
return efi_secureboot_mode_enabled; return efi_secureboot_mode_enabled;
out_efi_err: out_efi_err:
pr_efi_err("Could not determine UEFI Secure Boot status.\n"); efi_err("Could not determine UEFI Secure Boot status.\n");
return efi_secureboot_mode_unknown; return efi_secureboot_mode_unknown;
} }
...@@ -119,7 +119,7 @@ void efi_retrieve_tpm2_eventlog(void) ...@@ -119,7 +119,7 @@ void efi_retrieve_tpm2_eventlog(void)
sizeof(*log_tbl) + log_size, (void **)&log_tbl); sizeof(*log_tbl) + log_size, (void **)&log_tbl);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Unable to allocate memory for event log\n"); efi_err("Unable to allocate memory for event log\n");
return; return;
} }
......
This diff is collapsed.
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
const efi_system_table_t *efi_system_table; const efi_system_table_t *efi_system_table;
extern u32 image_offset; extern u32 image_offset;
static efi_loaded_image_t *image = NULL;
static efi_status_t static efi_status_t
preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
...@@ -49,7 +50,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) ...@@ -49,7 +50,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
(void **)&rom); (void **)&rom);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Failed to allocate memory for 'rom'\n"); efi_err("Failed to allocate memory for 'rom'\n");
return status; return status;
} }
...@@ -65,7 +66,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) ...@@ -65,7 +66,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
PCI_VENDOR_ID, 1, &rom->vendor); PCI_VENDOR_ID, 1, &rom->vendor);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Failed to read rom->vendor\n"); efi_err("Failed to read rom->vendor\n");
goto free_struct; goto free_struct;
} }
...@@ -73,7 +74,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom) ...@@ -73,7 +74,7 @@ preserve_pci_rom_image(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
PCI_DEVICE_ID, 1, &rom->devid); PCI_DEVICE_ID, 1, &rom->devid);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Failed to read rom->devid\n"); efi_err("Failed to read rom->devid\n");
goto free_struct; goto free_struct;
} }
...@@ -118,7 +119,7 @@ static void setup_efi_pci(struct boot_params *params) ...@@ -118,7 +119,7 @@ static void setup_efi_pci(struct boot_params *params)
(void **)&pci_handle); (void **)&pci_handle);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Failed to allocate memory for 'pci_handle'\n"); efi_err("Failed to allocate memory for 'pci_handle'\n");
return; return;
} }
...@@ -172,7 +173,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) ...@@ -172,7 +173,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
return; return;
if (efi_table_attr(p, version) != 0x10000) { if (efi_table_attr(p, version) != 0x10000) {
efi_printk("Unsupported properties proto version\n"); efi_err("Unsupported properties proto version\n");
return; return;
} }
...@@ -185,7 +186,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params) ...@@ -185,7 +186,7 @@ static void retrieve_apple_device_properties(struct boot_params *boot_params)
size + sizeof(struct setup_data), size + sizeof(struct setup_data),
(void **)&new); (void **)&new);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Failed to allocate memory for 'properties'\n"); efi_err("Failed to allocate memory for 'properties'\n");
return; return;
} }
...@@ -355,7 +356,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -355,7 +356,6 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
{ {
struct boot_params *boot_params; struct boot_params *boot_params;
struct setup_header *hdr; struct setup_header *hdr;
efi_loaded_image_t *image;
void *image_base; void *image_base;
efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID;
int options_size = 0; int options_size = 0;
...@@ -372,20 +372,21 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -372,20 +372,21 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image); status = efi_bs_call(handle_protocol, handle, &proto, (void **)&image);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); efi_err("Failed to get handle for LOADED_IMAGE_PROTOCOL\n");
efi_exit(handle, status); efi_exit(handle, status);
} }
image_base = efi_table_attr(image, image_base); image_base = efi_table_attr(image, image_base);
image_offset = (void *)startup_32 - image_base; image_offset = (void *)startup_32 - image_base;
status = efi_allocate_pages(0x4000, (unsigned long *)&boot_params, ULONG_MAX); status = efi_allocate_pages(sizeof(struct boot_params),
(unsigned long *)&boot_params, ULONG_MAX);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("Failed to allocate lowmem for boot params\n"); efi_err("Failed to allocate lowmem for boot params\n");
efi_exit(handle, status); efi_exit(handle, status);
} }
memset(boot_params, 0x0, 0x4000); memset(boot_params, 0x0, sizeof(struct boot_params));
hdr = &boot_params->hdr; hdr = &boot_params->hdr;
...@@ -403,43 +404,21 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle, ...@@ -403,43 +404,21 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
hdr->type_of_loader = 0x21; hdr->type_of_loader = 0x21;
/* Convert unicode cmdline to ascii */ /* Convert unicode cmdline to ascii */
cmdline_ptr = efi_convert_cmdline(image, &options_size, ULONG_MAX); cmdline_ptr = efi_convert_cmdline(image, &options_size);
if (!cmdline_ptr) if (!cmdline_ptr)
goto fail; goto fail;
hdr->cmd_line_ptr = (unsigned long)cmdline_ptr; efi_set_u64_split((unsigned long)cmdline_ptr,
/* Fill in upper bits of command line address, NOP on 32 bit */ &hdr->cmd_line_ptr, &boot_params->ext_cmd_line_ptr);
boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;
hdr->ramdisk_image = 0; hdr->ramdisk_image = 0;
hdr->ramdisk_size = 0; hdr->ramdisk_size = 0;
if (efi_is_native()) {
status = efi_parse_options(cmdline_ptr);
if (status != EFI_SUCCESS)
goto fail2;
if (!efi_noinitrd) {
status = efi_load_initrd(image, &ramdisk_addr,
&ramdisk_size,
hdr->initrd_addr_max,
ULONG_MAX);
if (status != EFI_SUCCESS)
goto fail2;
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;
}
}
efi_stub_entry(handle, sys_table_arg, boot_params); efi_stub_entry(handle, sys_table_arg, boot_params);
/* not reached */ /* not reached */
fail2:
efi_free(options_size, (unsigned long)cmdline_ptr);
fail: fail:
efi_free(0x4000, (unsigned long)boot_params); efi_free(sizeof(struct boot_params), (unsigned long)boot_params);
efi_exit(handle, status); efi_exit(handle, status);
} }
...@@ -632,17 +611,14 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map, ...@@ -632,17 +611,14 @@ static efi_status_t exit_boot_func(struct efi_boot_memmap *map,
: EFI32_LOADER_SIGNATURE; : EFI32_LOADER_SIGNATURE;
memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32)); memcpy(&p->efi->efi_loader_signature, signature, sizeof(__u32));
p->efi->efi_systab = (unsigned long)efi_system_table; efi_set_u64_split((unsigned long)efi_system_table,
&p->efi->efi_systab, &p->efi->efi_systab_hi);
p->efi->efi_memdesc_size = *map->desc_size; p->efi->efi_memdesc_size = *map->desc_size;
p->efi->efi_memdesc_version = *map->desc_ver; p->efi->efi_memdesc_version = *map->desc_ver;
p->efi->efi_memmap = (unsigned long)*map->map; efi_set_u64_split((unsigned long)*map->map,
&p->efi->efi_memmap, &p->efi->efi_memmap_hi);
p->efi->efi_memmap_size = *map->map_size; p->efi->efi_memmap_size = *map->map_size;
#ifdef CONFIG_X86_64
p->efi->efi_systab_hi = (unsigned long)efi_system_table >> 32;
p->efi->efi_memmap_hi = (unsigned long)*map->map >> 32;
#endif
return EFI_SUCCESS; return EFI_SUCCESS;
} }
...@@ -698,7 +674,6 @@ unsigned long efi_main(efi_handle_t handle, ...@@ -698,7 +674,6 @@ unsigned long efi_main(efi_handle_t handle,
unsigned long buffer_start, buffer_end; unsigned long buffer_start, buffer_end;
struct setup_header *hdr = &boot_params->hdr; struct setup_header *hdr = &boot_params->hdr;
efi_status_t status; efi_status_t status;
unsigned long cmdline_paddr;
efi_system_table = sys_table_arg; efi_system_table = sys_table_arg;
...@@ -746,7 +721,7 @@ unsigned long efi_main(efi_handle_t handle, ...@@ -746,7 +721,7 @@ unsigned long efi_main(efi_handle_t handle,
hdr->kernel_alignment, hdr->kernel_alignment,
LOAD_PHYSICAL_ADDR); LOAD_PHYSICAL_ADDR);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("efi_relocate_kernel() failed!\n"); efi_err("efi_relocate_kernel() failed!\n");
goto fail; goto fail;
} }
/* /*
...@@ -757,35 +732,46 @@ unsigned long efi_main(efi_handle_t handle, ...@@ -757,35 +732,46 @@ unsigned long efi_main(efi_handle_t handle,
image_offset = 0; image_offset = 0;
} }
/* #ifdef CONFIG_CMDLINE_BOOL
* efi_pe_entry() may have been called before efi_main(), in which status = efi_parse_options(CONFIG_CMDLINE);
* case this is the second time we parse the cmdline. This is ok, if (status != EFI_SUCCESS) {
* parsing the cmdline multiple times does not have side-effects. efi_err("Failed to parse options\n");
*/ goto fail;
cmdline_paddr = ((u64)hdr->cmd_line_ptr | }
((u64)boot_params->ext_cmd_line_ptr << 32)); #endif
efi_parse_options((char *)cmdline_paddr); if (!IS_ENABLED(CONFIG_CMDLINE_OVERRIDE)) {
unsigned long cmdline_paddr = ((u64)hdr->cmd_line_ptr |
((u64)boot_params->ext_cmd_line_ptr << 32));
status = efi_parse_options((char *)cmdline_paddr);
if (status != EFI_SUCCESS) {
efi_err("Failed to parse options\n");
goto fail;
}
}
/* /*
* At this point, an initrd may already have been loaded, either by * At this point, an initrd may already have been loaded by the
* the bootloader and passed via bootparams, or loaded from a initrd= * bootloader and passed via bootparams. We permit an initrd loaded
* command line option by efi_pe_entry() above. In either case, we * from the LINUX_EFI_INITRD_MEDIA_GUID device path to supersede it.
* permit an initrd loaded from the LINUX_EFI_INITRD_MEDIA_GUID device *
* path to supersede it. * If the device path is not present, any command-line initrd=
* 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) { if (!efi_noinitrd) {
unsigned long addr, size; unsigned long addr, size;
status = efi_load_initrd_dev_path(&addr, &size, ULONG_MAX); status = efi_load_initrd(image, &addr, &size,
if (status == EFI_SUCCESS) { hdr->initrd_addr_max, ULONG_MAX);
hdr->ramdisk_image = (u32)addr;
hdr->ramdisk_size = (u32)size; if (status != EFI_SUCCESS) {
boot_params->ext_ramdisk_image = (u64)addr >> 32; efi_err("Failed to load initrd!\n");
boot_params->ext_ramdisk_size = (u64)size >> 32;
} else if (status != EFI_NOT_FOUND) {
efi_printk("efi_load_initrd_dev_path() failed!\n");
goto fail; goto fail;
} }
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);
} }
/* /*
...@@ -810,13 +796,13 @@ unsigned long efi_main(efi_handle_t handle, ...@@ -810,13 +796,13 @@ unsigned long efi_main(efi_handle_t handle,
status = exit_boot(boot_params, handle); status = exit_boot(boot_params, handle);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
efi_printk("exit_boot() failed!\n"); efi_err("exit_boot() failed!\n");
goto fail; goto fail;
} }
return bzimage_addr; return bzimage_addr;
fail: fail:
efi_printk("efi_main() failed!\n"); efi_err("efi_main() failed!\n");
efi_exit(handle, status); efi_exit(handle, status);
} }
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1))) #define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1)))
#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1))) #define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1)))
#define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1)))
#define EFI_TIMEOUT (18 | (1UL << (BITS_PER_LONG-1)))
#define EFI_ABORTED (21 | (1UL << (BITS_PER_LONG-1))) #define EFI_ABORTED (21 | (1UL << (BITS_PER_LONG-1)))
#define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1))) #define EFI_SECURITY_VIOLATION (26 | (1UL << (BITS_PER_LONG-1)))
...@@ -426,6 +427,7 @@ typedef struct { ...@@ -426,6 +427,7 @@ typedef struct {
u32 tables; u32 tables;
} efi_system_table_32_t; } efi_system_table_32_t;
typedef union efi_simple_text_input_protocol efi_simple_text_input_protocol_t;
typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t; typedef union efi_simple_text_output_protocol efi_simple_text_output_protocol_t;
typedef union { typedef union {
...@@ -434,7 +436,7 @@ typedef union { ...@@ -434,7 +436,7 @@ typedef union {
unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */ unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */
u32 fw_revision; u32 fw_revision;
unsigned long con_in_handle; unsigned long con_in_handle;
unsigned long con_in; efi_simple_text_input_protocol_t *con_in;
unsigned long con_out_handle; unsigned long con_out_handle;
efi_simple_text_output_protocol_t *con_out; efi_simple_text_output_protocol_t *con_out;
unsigned long stderr_handle; unsigned long stderr_handle;
......
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