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 | } | ||