diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-04 20:13:50 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-04 20:13:50 -0400 |
| commit | 76f09aa464a1913efd596dd0edbf88f932fde08c (patch) | |
| tree | ce9aadc9a1c30597b9d61c7aac86bfb2e6caf961 /drivers/firmware | |
| parent | e9c9eecabaa898ff3fedd98813ee4ac1a00d006a (diff) | |
| parent | 99a5603e2a1f146ac0c6414d8a3669aa749ccff8 (diff) | |
Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/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()
...
Diffstat (limited to 'drivers/firmware')
| -rw-r--r-- | drivers/firmware/efi/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/firmware/efi/Makefile | 4 | ||||
| -rw-r--r-- | drivers/firmware/efi/efi.c | 40 | ||||
| -rw-r--r-- | drivers/firmware/efi/efivars.c | 1 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/Makefile | 26 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/arm-stub.c (renamed from drivers/firmware/efi/arm-stub.c) | 32 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/efi-stub-helper.c (renamed from drivers/firmware/efi/efi-stub-helper.c) | 74 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/efistub.h | 42 | ||||
| -rw-r--r-- | drivers/firmware/efi/libstub/fdt.c (renamed from drivers/firmware/efi/fdt.c) | 20 | ||||
| -rw-r--r-- | drivers/firmware/efi/reboot.c | 56 | ||||
| -rw-r--r-- | drivers/firmware/efi/runtime-wrappers.c | 161 |
11 files changed, 391 insertions, 71 deletions
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig index d420ae2d3413..f712d47f30d8 100644 --- a/drivers/firmware/efi/Kconfig +++ b/drivers/firmware/efi/Kconfig | |||
| @@ -54,6 +54,12 @@ config EFI_PARAMS_FROM_FDT | |||
| 54 | the EFI runtime support gets system table address, memory | 54 | the EFI runtime support gets system table address, memory |
| 55 | map address, and other parameters from the device tree. | 55 | map address, and other parameters from the device tree. |
| 56 | 56 | ||
| 57 | config EFI_RUNTIME_WRAPPERS | ||
| 58 | bool | ||
| 59 | |||
| 60 | config EFI_ARMSTUB | ||
| 61 | bool | ||
| 62 | |||
| 57 | endmenu | 63 | endmenu |
| 58 | 64 | ||
| 59 | config UEFI_CPER | 65 | config UEFI_CPER |
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index 9553496b0f43..d8be608a9f3b 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
| @@ -1,8 +1,10 @@ | |||
| 1 | # | 1 | # |
| 2 | # Makefile for linux kernel | 2 | # Makefile for linux kernel |
| 3 | # | 3 | # |
| 4 | obj-$(CONFIG_EFI) += efi.o vars.o | 4 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o |
| 5 | obj-$(CONFIG_EFI_VARS) += efivars.o | 5 | obj-$(CONFIG_EFI_VARS) += efivars.o |
| 6 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o | 6 | obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o |
| 7 | obj-$(CONFIG_UEFI_CPER) += cper.o | 7 | obj-$(CONFIG_UEFI_CPER) += cper.o |
| 8 | obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o | 8 | obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o |
| 9 | obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o | ||
| 10 | obj-$(CONFIG_EFI_STUB) += libstub/ | ||
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index dc79346689e6..64ecbb501c50 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/of.h> | 23 | #include <linux/of.h> |
| 24 | #include <linux/of_fdt.h> | 24 | #include <linux/of_fdt.h> |
| 25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 26 | #include <linux/platform_device.h> | ||
| 26 | 27 | ||
| 27 | struct efi __read_mostly efi = { | 28 | struct efi __read_mostly efi = { |
| 28 | .mps = EFI_INVALID_TABLE_ADDR, | 29 | .mps = EFI_INVALID_TABLE_ADDR, |
| @@ -104,16 +105,19 @@ static struct attribute *efi_subsys_attrs[] = { | |||
| 104 | static umode_t efi_attr_is_visible(struct kobject *kobj, | 105 | static umode_t efi_attr_is_visible(struct kobject *kobj, |
| 105 | struct attribute *attr, int n) | 106 | struct attribute *attr, int n) |
| 106 | { | 107 | { |
| 107 | umode_t mode = attr->mode; | 108 | if (attr == &efi_attr_fw_vendor.attr) { |
| 108 | 109 | if (efi_enabled(EFI_PARAVIRT) || | |
| 109 | if (attr == &efi_attr_fw_vendor.attr) | 110 | efi.fw_vendor == EFI_INVALID_TABLE_ADDR) |
| 110 | return (efi.fw_vendor == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | 111 | return 0; |
| 111 | else if (attr == &efi_attr_runtime.attr) | 112 | } else if (attr == &efi_attr_runtime.attr) { |
| 112 | return (efi.runtime == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | 113 | if (efi.runtime == EFI_INVALID_TABLE_ADDR) |
| 113 | else if (attr == &efi_attr_config_table.attr) | 114 | return 0; |
| 114 | return (efi.config_table == EFI_INVALID_TABLE_ADDR) ? 0 : mode; | 115 | } else if (attr == &efi_attr_config_table.attr) { |
| 116 | if (efi.config_table == EFI_INVALID_TABLE_ADDR) | ||
| 117 | return 0; | ||
| 118 | } | ||
| 115 | 119 | ||
| 116 | return mode; | 120 | return attr->mode; |
| 117 | } | 121 | } |
| 118 | 122 | ||
| 119 | static struct attribute_group efi_subsys_attr_group = { | 123 | static struct attribute_group efi_subsys_attr_group = { |
| @@ -298,7 +302,7 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) | |||
| 298 | if (table64 >> 32) { | 302 | if (table64 >> 32) { |
| 299 | pr_cont("\n"); | 303 | pr_cont("\n"); |
| 300 | pr_err("Table located above 4GB, disabling EFI.\n"); | 304 | pr_err("Table located above 4GB, disabling EFI.\n"); |
| 301 | early_iounmap(config_tables, | 305 | early_memunmap(config_tables, |
| 302 | efi.systab->nr_tables * sz); | 306 | efi.systab->nr_tables * sz); |
| 303 | return -EINVAL; | 307 | return -EINVAL; |
| 304 | } | 308 | } |
| @@ -314,13 +318,27 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables) | |||
| 314 | tablep += sz; | 318 | tablep += sz; |
| 315 | } | 319 | } |
| 316 | pr_cont("\n"); | 320 | pr_cont("\n"); |
| 317 | early_iounmap(config_tables, efi.systab->nr_tables * sz); | 321 | early_memunmap(config_tables, efi.systab->nr_tables * sz); |
| 318 | 322 | ||
| 319 | set_bit(EFI_CONFIG_TABLES, &efi.flags); | 323 | set_bit(EFI_CONFIG_TABLES, &efi.flags); |
| 320 | 324 | ||
| 321 | return 0; | 325 | return 0; |
| 322 | } | 326 | } |
| 323 | 327 | ||
| 328 | #ifdef CONFIG_EFI_VARS_MODULE | ||
| 329 | static int __init efi_load_efivars(void) | ||
| 330 | { | ||
| 331 | struct platform_device *pdev; | ||
| 332 | |||
| 333 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | ||
| 334 | return 0; | ||
| 335 | |||
| 336 | pdev = platform_device_register_simple("efivars", 0, NULL, 0); | ||
| 337 | return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; | ||
| 338 | } | ||
| 339 | device_initcall(efi_load_efivars); | ||
| 340 | #endif | ||
| 341 | |||
| 324 | #ifdef CONFIG_EFI_PARAMS_FROM_FDT | 342 | #ifdef CONFIG_EFI_PARAMS_FROM_FDT |
| 325 | 343 | ||
| 326 | #define UEFI_PARAM(name, prop, field) \ | 344 | #define UEFI_PARAM(name, prop, field) \ |
diff --git a/drivers/firmware/efi/efivars.c b/drivers/firmware/efi/efivars.c index 463c56545ae8..f256ecd8a176 100644 --- a/drivers/firmware/efi/efivars.c +++ b/drivers/firmware/efi/efivars.c | |||
| @@ -78,6 +78,7 @@ MODULE_AUTHOR("Matt Domsch <Matt_Domsch@Dell.com>"); | |||
| 78 | MODULE_DESCRIPTION("sysfs interface to EFI Variables"); | 78 | MODULE_DESCRIPTION("sysfs interface to EFI Variables"); |
| 79 | MODULE_LICENSE("GPL"); | 79 | MODULE_LICENSE("GPL"); |
| 80 | MODULE_VERSION(EFIVARS_VERSION); | 80 | MODULE_VERSION(EFIVARS_VERSION); |
| 81 | MODULE_ALIAS("platform:efivars"); | ||
| 81 | 82 | ||
| 82 | LIST_HEAD(efivar_sysfs_list); | 83 | LIST_HEAD(efivar_sysfs_list); |
| 83 | EXPORT_SYMBOL_GPL(efivar_sysfs_list); | 84 | EXPORT_SYMBOL_GPL(efivar_sysfs_list); |
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile new file mode 100644 index 000000000000..b14bc2b9fb4d --- /dev/null +++ b/drivers/firmware/efi/libstub/Makefile | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | # | ||
| 2 | # The stub may be linked into the kernel proper or into a separate boot binary, | ||
| 3 | # but in either case, it executes before the kernel does (with MMU disabled) so | ||
| 4 | # things like ftrace and stack-protector are likely to cause trouble if left | ||
| 5 | # enabled, even if doing so doesn't break the build. | ||
| 6 | # | ||
| 7 | cflags-$(CONFIG_X86_32) := -march=i386 | ||
| 8 | cflags-$(CONFIG_X86_64) := -mcmodel=small | ||
| 9 | cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 \ | ||
| 10 | -fPIC -fno-strict-aliasing -mno-red-zone \ | ||
| 11 | -mno-mmx -mno-sse -DDISABLE_BRANCH_PROFILING | ||
| 12 | |||
| 13 | cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS)) | ||
| 14 | cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \ | ||
| 15 | -fno-builtin -fpic -mno-single-pic-base | ||
| 16 | |||
| 17 | KBUILD_CFLAGS := $(cflags-y) \ | ||
| 18 | $(call cc-option,-ffreestanding) \ | ||
| 19 | $(call cc-option,-fno-stack-protector) | ||
| 20 | |||
| 21 | GCOV_PROFILE := n | ||
| 22 | |||
| 23 | lib-y := efi-stub-helper.o | ||
| 24 | lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o | ||
| 25 | |||
| 26 | CFLAGS_fdt.o += -I$(srctree)/scripts/dtc/libfdt/ | ||
diff --git a/drivers/firmware/efi/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 41114ce03b01..480339b6b110 100644 --- a/drivers/firmware/efi/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c | |||
| @@ -12,6 +12,11 @@ | |||
| 12 | * | 12 | * |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #include <linux/efi.h> | ||
| 16 | #include <asm/efi.h> | ||
| 17 | |||
| 18 | #include "efistub.h" | ||
| 19 | |||
| 15 | static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) | 20 | static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) |
| 16 | { | 21 | { |
| 17 | static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; | 22 | static efi_guid_t const var_guid __initconst = EFI_GLOBAL_VARIABLE_GUID; |
| @@ -36,8 +41,8 @@ static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) | |||
| 36 | } | 41 | } |
| 37 | } | 42 | } |
| 38 | 43 | ||
| 39 | static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, | 44 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, |
| 40 | void *__image, void **__fh) | 45 | void *__image, void **__fh) |
| 41 | { | 46 | { |
| 42 | efi_file_io_interface_t *io; | 47 | efi_file_io_interface_t *io; |
| 43 | efi_loaded_image_t *image = __image; | 48 | efi_loaded_image_t *image = __image; |
| @@ -60,14 +65,15 @@ static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, | |||
| 60 | *__fh = fh; | 65 | *__fh = fh; |
| 61 | return status; | 66 | return status; |
| 62 | } | 67 | } |
| 63 | static efi_status_t efi_file_close(void *handle) | 68 | |
| 69 | efi_status_t efi_file_close(void *handle) | ||
| 64 | { | 70 | { |
| 65 | efi_file_handle_t *fh = handle; | 71 | efi_file_handle_t *fh = handle; |
| 66 | 72 | ||
| 67 | return fh->close(handle); | 73 | return fh->close(handle); |
| 68 | } | 74 | } |
| 69 | 75 | ||
| 70 | static efi_status_t | 76 | efi_status_t |
| 71 | efi_file_read(void *handle, unsigned long *size, void *addr) | 77 | efi_file_read(void *handle, unsigned long *size, void *addr) |
| 72 | { | 78 | { |
| 73 | efi_file_handle_t *fh = handle; | 79 | efi_file_handle_t *fh = handle; |
| @@ -76,7 +82,7 @@ efi_file_read(void *handle, unsigned long *size, void *addr) | |||
| 76 | } | 82 | } |
| 77 | 83 | ||
| 78 | 84 | ||
| 79 | static efi_status_t | 85 | efi_status_t |
| 80 | efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, | 86 | efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, |
| 81 | efi_char16_t *filename_16, void **handle, u64 *file_sz) | 87 | efi_char16_t *filename_16, void **handle, u64 *file_sz) |
| 82 | { | 88 | { |
| @@ -129,7 +135,7 @@ grow: | |||
| 129 | 135 | ||
| 130 | 136 | ||
| 131 | 137 | ||
| 132 | static void efi_char16_printk(efi_system_table_t *sys_table_arg, | 138 | void efi_char16_printk(efi_system_table_t *sys_table_arg, |
| 133 | efi_char16_t *str) | 139 | efi_char16_t *str) |
| 134 | { | 140 | { |
| 135 | struct efi_simple_text_output_protocol *out; | 141 | struct efi_simple_text_output_protocol *out; |
| @@ -145,13 +151,13 @@ static void efi_char16_printk(efi_system_table_t *sys_table_arg, | |||
| 145 | * must be reserved. On failure it is required to free all | 151 | * must be reserved. On failure it is required to free all |
| 146 | * all allocations it has made. | 152 | * all allocations it has made. |
| 147 | */ | 153 | */ |
| 148 | static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, | 154 | efi_status_t handle_kernel_image(efi_system_table_t *sys_table, |
| 149 | unsigned long *image_addr, | 155 | unsigned long *image_addr, |
| 150 | unsigned long *image_size, | 156 | unsigned long *image_size, |
| 151 | unsigned long *reserve_addr, | 157 | unsigned long *reserve_addr, |
| 152 | unsigned long *reserve_size, | 158 | unsigned long *reserve_size, |
| 153 | unsigned long dram_base, | 159 | unsigned long dram_base, |
| 154 | efi_loaded_image_t *image); | 160 | efi_loaded_image_t *image); |
| 155 | /* | 161 | /* |
| 156 | * EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint | 162 | * EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint |
| 157 | * that is described in the PE/COFF header. Most of the code is the same | 163 | * that is described in the PE/COFF header. Most of the code is the same |
diff --git a/drivers/firmware/efi/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index eb6d4be9e722..32d5cca30f49 100644 --- a/drivers/firmware/efi/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c | |||
| @@ -9,18 +9,20 @@ | |||
| 9 | * under the terms of the GNU General Public License version 2. | 9 | * under the terms of the GNU General Public License version 2. |
| 10 | * | 10 | * |
| 11 | */ | 11 | */ |
| 12 | #define EFI_READ_CHUNK_SIZE (1024 * 1024) | ||
| 13 | 12 | ||
| 14 | /* error code which can't be mistaken for valid address */ | 13 | #include <linux/efi.h> |
| 15 | #define EFI_ERROR (~0UL) | 14 | #include <asm/efi.h> |
| 15 | |||
| 16 | #include "efistub.h" | ||
| 16 | 17 | ||
| 18 | #define EFI_READ_CHUNK_SIZE (1024 * 1024) | ||
| 17 | 19 | ||
| 18 | struct file_info { | 20 | struct file_info { |
| 19 | efi_file_handle_t *handle; | 21 | efi_file_handle_t *handle; |
| 20 | u64 size; | 22 | u64 size; |
| 21 | }; | 23 | }; |
| 22 | 24 | ||
| 23 | static void efi_printk(efi_system_table_t *sys_table_arg, char *str) | 25 | void efi_printk(efi_system_table_t *sys_table_arg, char *str) |
| 24 | { | 26 | { |
| 25 | char *s8; | 27 | char *s8; |
| 26 | 28 | ||
| @@ -37,16 +39,12 @@ static void efi_printk(efi_system_table_t *sys_table_arg, char *str) | |||
| 37 | } | 39 | } |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 40 | #define pr_efi(sys_table, msg) efi_printk(sys_table, "EFI stub: "msg) | 42 | efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, |
| 41 | #define pr_efi_err(sys_table, msg) efi_printk(sys_table, "EFI stub: ERROR: "msg) | 43 | efi_memory_desc_t **map, |
| 42 | 44 | unsigned long *map_size, | |
| 43 | 45 | unsigned long *desc_size, | |
| 44 | static efi_status_t efi_get_memory_map(efi_system_table_t *sys_table_arg, | 46 | u32 *desc_ver, |
| 45 | efi_memory_desc_t **map, | 47 | unsigned long *key_ptr) |
| 46 | unsigned long *map_size, | ||
| 47 | unsigned long *desc_size, | ||
| 48 | u32 *desc_ver, | ||
| 49 | unsigned long *key_ptr) | ||
| 50 | { | 48 | { |
| 51 | efi_memory_desc_t *m = NULL; | 49 | efi_memory_desc_t *m = NULL; |
| 52 | efi_status_t status; | 50 | efi_status_t status; |
| @@ -88,7 +86,7 @@ fail: | |||
| 88 | } | 86 | } |
| 89 | 87 | ||
| 90 | 88 | ||
| 91 | static unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg) | 89 | unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg) |
| 92 | { | 90 | { |
| 93 | efi_status_t status; | 91 | efi_status_t status; |
| 94 | unsigned long map_size; | 92 | unsigned long map_size; |
| @@ -116,9 +114,9 @@ static unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg) | |||
| 116 | /* | 114 | /* |
| 117 | * Allocate at the highest possible address that is not above 'max'. | 115 | * Allocate at the highest possible address that is not above 'max'. |
| 118 | */ | 116 | */ |
| 119 | static efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, | 117 | efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, |
| 120 | unsigned long size, unsigned long align, | 118 | unsigned long size, unsigned long align, |
| 121 | unsigned long *addr, unsigned long max) | 119 | unsigned long *addr, unsigned long max) |
| 122 | { | 120 | { |
| 123 | unsigned long map_size, desc_size; | 121 | unsigned long map_size, desc_size; |
| 124 | efi_memory_desc_t *map; | 122 | efi_memory_desc_t *map; |
| @@ -202,9 +200,9 @@ fail: | |||
| 202 | /* | 200 | /* |
| 203 | * Allocate at the lowest possible address. | 201 | * Allocate at the lowest possible address. |
| 204 | */ | 202 | */ |
| 205 | static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, | 203 | efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, |
| 206 | unsigned long size, unsigned long align, | 204 | unsigned long size, unsigned long align, |
| 207 | unsigned long *addr) | 205 | unsigned long *addr) |
| 208 | { | 206 | { |
| 209 | unsigned long map_size, desc_size; | 207 | unsigned long map_size, desc_size; |
| 210 | efi_memory_desc_t *map; | 208 | efi_memory_desc_t *map; |
| @@ -271,8 +269,8 @@ fail: | |||
| 271 | return status; | 269 | return status; |
| 272 | } | 270 | } |
| 273 | 271 | ||
| 274 | static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, | 272 | void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, |
| 275 | unsigned long addr) | 273 | unsigned long addr) |
| 276 | { | 274 | { |
| 277 | unsigned long nr_pages; | 275 | unsigned long nr_pages; |
| 278 | 276 | ||
| @@ -290,12 +288,12 @@ static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, | |||
| 290 | * We only support loading a file from the same filesystem as | 288 | * We only support loading a file from the same filesystem as |
| 291 | * the kernel image. | 289 | * the kernel image. |
| 292 | */ | 290 | */ |
| 293 | static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, | 291 | efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, |
| 294 | efi_loaded_image_t *image, | 292 | efi_loaded_image_t *image, |
| 295 | char *cmd_line, char *option_string, | 293 | char *cmd_line, char *option_string, |
| 296 | unsigned long max_addr, | 294 | unsigned long max_addr, |
| 297 | unsigned long *load_addr, | 295 | unsigned long *load_addr, |
| 298 | unsigned long *load_size) | 296 | unsigned long *load_size) |
| 299 | { | 297 | { |
| 300 | struct file_info *files; | 298 | struct file_info *files; |
| 301 | unsigned long file_addr; | 299 | unsigned long file_addr; |
| @@ -477,12 +475,12 @@ fail: | |||
| 477 | * address is not available the lowest available address will | 475 | * address is not available the lowest available address will |
| 478 | * be used. | 476 | * be used. |
| 479 | */ | 477 | */ |
| 480 | static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, | 478 | efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, |
| 481 | unsigned long *image_addr, | 479 | unsigned long *image_addr, |
| 482 | unsigned long image_size, | 480 | unsigned long image_size, |
| 483 | unsigned long alloc_size, | 481 | unsigned long alloc_size, |
| 484 | unsigned long preferred_addr, | 482 | unsigned long preferred_addr, |
| 485 | unsigned long alignment) | 483 | unsigned long alignment) |
| 486 | { | 484 | { |
| 487 | unsigned long cur_image_addr; | 485 | unsigned long cur_image_addr; |
| 488 | unsigned long new_addr = 0; | 486 | unsigned long new_addr = 0; |
| @@ -589,9 +587,9 @@ static u8 *efi_utf16_to_utf8(u8 *dst, const u16 *src, int n) | |||
| 589 | * Size of memory allocated return in *cmd_line_len. | 587 | * Size of memory allocated return in *cmd_line_len. |
| 590 | * Returns NULL on error. | 588 | * Returns NULL on error. |
| 591 | */ | 589 | */ |
| 592 | static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, | 590 | char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, |
| 593 | efi_loaded_image_t *image, | 591 | efi_loaded_image_t *image, |
| 594 | int *cmd_line_len) | 592 | int *cmd_line_len) |
| 595 | { | 593 | { |
| 596 | const u16 *s2; | 594 | const u16 *s2; |
| 597 | u8 *s1 = NULL; | 595 | u8 *s1 = NULL; |
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h new file mode 100644 index 000000000000..304ab295ca1a --- /dev/null +++ b/drivers/firmware/efi/libstub/efistub.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | |||
| 2 | #ifndef _DRIVERS_FIRMWARE_EFI_EFISTUB_H | ||
| 3 | #define _DRIVERS_FIRMWARE_EFI_EFISTUB_H | ||
| 4 | |||
| 5 | /* error code which can't be mistaken for valid address */ | ||
| 6 | #define EFI_ERROR (~0UL) | ||
| 7 | |||
| 8 | void efi_char16_printk(efi_system_table_t *, efi_char16_t *); | ||
| 9 | |||
| 10 | efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image, | ||
| 11 | void **__fh); | ||
| 12 | |||
| 13 | efi_status_t efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, | ||
| 14 | efi_char16_t *filename_16, void **handle, | ||
| 15 | u64 *file_sz); | ||
| 16 | |||
| 17 | efi_status_t efi_file_read(void *handle, unsigned long *size, void *addr); | ||
| 18 | |||
| 19 | efi_status_t efi_file_close(void *handle); | ||
| 20 | |||
| 21 | unsigned long get_dram_base(efi_system_table_t *sys_table_arg); | ||
| 22 | |||
| 23 | efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, | ||
| 24 | unsigned long orig_fdt_size, | ||
| 25 | void *fdt, int new_fdt_size, char *cmdline_ptr, | ||
| 26 | u64 initrd_addr, u64 initrd_size, | ||
| 27 | efi_memory_desc_t *memory_map, | ||
| 28 | unsigned long map_size, unsigned long desc_size, | ||
| 29 | u32 desc_ver); | ||
| 30 | |||
| 31 | efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table, | ||
| 32 | void *handle, | ||
| 33 | unsigned long *new_fdt_addr, | ||
| 34 | unsigned long max_addr, | ||
| 35 | u64 initrd_addr, u64 initrd_size, | ||
| 36 | char *cmdline_ptr, | ||
| 37 | unsigned long fdt_addr, | ||
| 38 | unsigned long fdt_size); | ||
| 39 | |||
| 40 | void *get_fdt(efi_system_table_t *sys_table); | ||
| 41 | |||
| 42 | #endif | ||
diff --git a/drivers/firmware/efi/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 507a3df46a5d..a56bb3528755 100644 --- a/drivers/firmware/efi/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c | |||
| @@ -10,13 +10,17 @@ | |||
| 10 | * | 10 | * |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, | 13 | #include <linux/efi.h> |
| 14 | unsigned long orig_fdt_size, | 14 | #include <linux/libfdt.h> |
| 15 | void *fdt, int new_fdt_size, char *cmdline_ptr, | 15 | #include <asm/efi.h> |
| 16 | u64 initrd_addr, u64 initrd_size, | 16 | |
| 17 | efi_memory_desc_t *memory_map, | 17 | efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, |
| 18 | unsigned long map_size, unsigned long desc_size, | 18 | unsigned long orig_fdt_size, |
| 19 | u32 desc_ver) | 19 | void *fdt, int new_fdt_size, char *cmdline_ptr, |
| 20 | u64 initrd_addr, u64 initrd_size, | ||
| 21 | efi_memory_desc_t *memory_map, | ||
| 22 | unsigned long map_size, unsigned long desc_size, | ||
| 23 | u32 desc_ver) | ||
| 20 | { | 24 | { |
| 21 | int node, prev; | 25 | int node, prev; |
| 22 | int status; | 26 | int status; |
| @@ -255,7 +259,7 @@ fail: | |||
| 255 | return EFI_LOAD_ERROR; | 259 | return EFI_LOAD_ERROR; |
| 256 | } | 260 | } |
| 257 | 261 | ||
| 258 | static void *get_fdt(efi_system_table_t *sys_table) | 262 | void *get_fdt(efi_system_table_t *sys_table) |
| 259 | { | 263 | { |
| 260 | efi_guid_t fdt_guid = DEVICE_TREE_GUID; | 264 | efi_guid_t fdt_guid = DEVICE_TREE_GUID; |
| 261 | efi_config_table_t *tables; | 265 | efi_config_table_t *tables; |
diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c new file mode 100644 index 000000000000..9c59d1c795d1 --- /dev/null +++ b/drivers/firmware/efi/reboot.c | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Intel Corporation; author Matt Fleming | ||
| 3 | * Copyright (c) 2014 Red Hat, Inc., Mark Salter <msalter@redhat.com> | ||
| 4 | */ | ||
| 5 | #include <linux/efi.h> | ||
| 6 | #include <linux/reboot.h> | ||
| 7 | |||
| 8 | int efi_reboot_quirk_mode = -1; | ||
| 9 | |||
| 10 | void efi_reboot(enum reboot_mode reboot_mode, const char *__unused) | ||
| 11 | { | ||
| 12 | int efi_mode; | ||
| 13 | |||
| 14 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | ||
| 15 | return; | ||
| 16 | |||
| 17 | switch (reboot_mode) { | ||
| 18 | case REBOOT_WARM: | ||
| 19 | case REBOOT_SOFT: | ||
| 20 | efi_mode = EFI_RESET_WARM; | ||
| 21 | break; | ||
| 22 | default: | ||
| 23 | efi_mode = EFI_RESET_COLD; | ||
| 24 | break; | ||
| 25 | } | ||
| 26 | |||
| 27 | /* | ||
| 28 | * If a quirk forced an EFI reset mode, always use that. | ||
| 29 | */ | ||
| 30 | if (efi_reboot_quirk_mode != -1) | ||
| 31 | efi_mode = efi_reboot_quirk_mode; | ||
| 32 | |||
| 33 | efi.reset_system(efi_mode, EFI_SUCCESS, 0, NULL); | ||
| 34 | } | ||
| 35 | |||
| 36 | bool __weak efi_poweroff_required(void) | ||
| 37 | { | ||
| 38 | return false; | ||
| 39 | } | ||
| 40 | |||
| 41 | static void efi_power_off(void) | ||
| 42 | { | ||
| 43 | efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL); | ||
| 44 | } | ||
| 45 | |||
| 46 | static int __init efi_shutdown_init(void) | ||
| 47 | { | ||
| 48 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) | ||
| 49 | return -ENODEV; | ||
| 50 | |||
| 51 | if (efi_poweroff_required()) | ||
| 52 | pm_power_off = efi_power_off; | ||
| 53 | |||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | late_initcall(efi_shutdown_init); | ||
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c new file mode 100644 index 000000000000..10daa4bbb258 --- /dev/null +++ b/drivers/firmware/efi/runtime-wrappers.c | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* | ||
| 2 | * runtime-wrappers.c - Runtime Services function call wrappers | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org> | ||
| 5 | * | ||
| 6 | * Split off from arch/x86/platform/efi/efi.c | ||
| 7 | * | ||
| 8 | * Copyright (C) 1999 VA Linux Systems | ||
| 9 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | ||
| 10 | * Copyright (C) 1999-2002 Hewlett-Packard Co. | ||
| 11 | * Copyright (C) 2005-2008 Intel Co. | ||
| 12 | * Copyright (C) 2013 SuSE Labs | ||
| 13 | * | ||
| 14 | * This file is released under the GPLv2. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/efi.h> | ||
| 18 | #include <linux/spinlock.h> /* spinlock_t */ | ||
| 19 | #include <asm/efi.h> | ||
| 20 | |||
| 21 | /* | ||
| 22 | * As per commit ef68c8f87ed1 ("x86: Serialize EFI time accesses on rtc_lock"), | ||
| 23 | * the EFI specification requires that callers of the time related runtime | ||
| 24 | * functions serialize with other CMOS accesses in the kernel, as the EFI time | ||
| 25 | * functions may choose to also use the legacy CMOS RTC. | ||
| 26 | */ | ||
| 27 | __weak DEFINE_SPINLOCK(rtc_lock); | ||
| 28 | |||
| 29 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | ||
| 30 | { | ||
| 31 | unsigned long flags; | ||
| 32 | efi_status_t status; | ||
| 33 | |||
| 34 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 35 | status = efi_call_virt(get_time, tm, tc); | ||
| 36 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 37 | return status; | ||
| 38 | } | ||
| 39 | |||
| 40 | static efi_status_t virt_efi_set_time(efi_time_t *tm) | ||
| 41 | { | ||
| 42 | unsigned long flags; | ||
| 43 | efi_status_t status; | ||
| 44 | |||
| 45 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 46 | status = efi_call_virt(set_time, tm); | ||
| 47 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 48 | return status; | ||
| 49 | } | ||
| 50 | |||
| 51 | static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled, | ||
| 52 | efi_bool_t *pending, | ||
| 53 | efi_time_t *tm) | ||
| 54 | { | ||
| 55 | unsigned long flags; | ||
| 56 | efi_status_t status; | ||
| 57 | |||
| 58 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 59 | status = efi_call_virt(get_wakeup_time, enabled, pending, tm); | ||
| 60 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 61 | return status; | ||
| 62 | } | ||
| 63 | |||
| 64 | static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm) | ||
| 65 | { | ||
| 66 | unsigned long flags; | ||
| 67 | efi_status_t status; | ||
| 68 | |||
| 69 | spin_lock_irqsave(&rtc_lock, flags); | ||
| 70 | status = efi_call_virt(set_wakeup_time, enabled, tm); | ||
| 71 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
| 72 | return status; | ||
| 73 | } | ||
| 74 | |||
| 75 | static efi_status_t virt_efi_get_variable(efi_char16_t *name, | ||
| 76 | efi_guid_t *vendor, | ||
| 77 | u32 *attr, | ||
| 78 | unsigned long *data_size, | ||
| 79 | void *data) | ||
| 80 | { | ||
| 81 | return efi_call_virt(get_variable, name, vendor, attr, data_size, data); | ||
| 82 | } | ||
| 83 | |||
| 84 | static efi_status_t virt_efi_get_next_variable(unsigned long *name_size, | ||
| 85 | efi_char16_t *name, | ||
| 86 | efi_guid_t *vendor) | ||
| 87 | { | ||
| 88 | return efi_call_virt(get_next_variable, name_size, name, vendor); | ||
| 89 | } | ||
| 90 | |||
| 91 | static efi_status_t virt_efi_set_variable(efi_char16_t *name, | ||
| 92 | efi_guid_t *vendor, | ||
| 93 | u32 attr, | ||
| 94 | unsigned long data_size, | ||
| 95 | void *data) | ||
| 96 | { | ||
| 97 | return efi_call_virt(set_variable, name, vendor, attr, data_size, data); | ||
| 98 | } | ||
| 99 | |||
| 100 | static efi_status_t virt_efi_query_variable_info(u32 attr, | ||
| 101 | u64 *storage_space, | ||
| 102 | u64 *remaining_space, | ||
| 103 | u64 *max_variable_size) | ||
| 104 | { | ||
| 105 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
| 106 | return EFI_UNSUPPORTED; | ||
| 107 | |||
| 108 | return efi_call_virt(query_variable_info, attr, storage_space, | ||
| 109 | remaining_space, max_variable_size); | ||
| 110 | } | ||
| 111 | |||
| 112 | static efi_status_t virt_efi_get_next_high_mono_count(u32 *count) | ||
| 113 | { | ||
| 114 | return efi_call_virt(get_next_high_mono_count, count); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void virt_efi_reset_system(int reset_type, | ||
| 118 | efi_status_t status, | ||
| 119 | unsigned long data_size, | ||
| 120 | efi_char16_t *data) | ||
| 121 | { | ||
| 122 | __efi_call_virt(reset_system, reset_type, status, data_size, data); | ||
| 123 | } | ||
| 124 | |||
| 125 | static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules, | ||
| 126 | unsigned long count, | ||
| 127 | unsigned long sg_list) | ||
| 128 | { | ||
| 129 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
| 130 | return EFI_UNSUPPORTED; | ||
| 131 | |||
| 132 | return efi_call_virt(update_capsule, capsules, count, sg_list); | ||
| 133 | } | ||
| 134 | |||
| 135 | static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules, | ||
| 136 | unsigned long count, | ||
| 137 | u64 *max_size, | ||
| 138 | int *reset_type) | ||
| 139 | { | ||
| 140 | if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION) | ||
| 141 | return EFI_UNSUPPORTED; | ||
| 142 | |||
| 143 | return efi_call_virt(query_capsule_caps, capsules, count, max_size, | ||
| 144 | reset_type); | ||
| 145 | } | ||
| 146 | |||
| 147 | void efi_native_runtime_setup(void) | ||
| 148 | { | ||
| 149 | efi.get_time = virt_efi_get_time; | ||
| 150 | efi.set_time = virt_efi_set_time; | ||
| 151 | efi.get_wakeup_time = virt_efi_get_wakeup_time; | ||
| 152 | efi.set_wakeup_time = virt_efi_set_wakeup_time; | ||
| 153 | efi.get_variable = virt_efi_get_variable; | ||
| 154 | efi.get_next_variable = virt_efi_get_next_variable; | ||
| 155 | efi.set_variable = virt_efi_set_variable; | ||
| 156 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; | ||
| 157 | efi.reset_system = virt_efi_reset_system; | ||
| 158 | efi.query_variable_info = virt_efi_query_variable_info; | ||
| 159 | efi.update_capsule = virt_efi_update_capsule; | ||
| 160 | efi.query_capsule_caps = virt_efi_query_capsule_caps; | ||
| 161 | } | ||
