aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-04 20:13:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-04 20:13:50 -0400
commit76f09aa464a1913efd596dd0edbf88f932fde08c (patch)
treece9aadc9a1c30597b9d61c7aac86bfb2e6caf961 /drivers/firmware
parente9c9eecabaa898ff3fedd98813ee4ac1a00d006a (diff)
parent99a5603e2a1f146ac0c6414d8a3669aa749ccff8 (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/Kconfig6
-rw-r--r--drivers/firmware/efi/Makefile4
-rw-r--r--drivers/firmware/efi/efi.c40
-rw-r--r--drivers/firmware/efi/efivars.c1
-rw-r--r--drivers/firmware/efi/libstub/Makefile26
-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.h42
-rw-r--r--drivers/firmware/efi/libstub/fdt.c (renamed from drivers/firmware/efi/fdt.c)20
-rw-r--r--drivers/firmware/efi/reboot.c56
-rw-r--r--drivers/firmware/efi/runtime-wrappers.c161
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
57config EFI_RUNTIME_WRAPPERS
58 bool
59
60config EFI_ARMSTUB
61 bool
62
57endmenu 63endmenu
58 64
59config UEFI_CPER 65config 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#
4obj-$(CONFIG_EFI) += efi.o vars.o 4obj-$(CONFIG_EFI) += efi.o vars.o reboot.o
5obj-$(CONFIG_EFI_VARS) += efivars.o 5obj-$(CONFIG_EFI_VARS) += efivars.o
6obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o 6obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
7obj-$(CONFIG_UEFI_CPER) += cper.o 7obj-$(CONFIG_UEFI_CPER) += cper.o
8obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o 8obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
9obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
10obj-$(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
27struct efi __read_mostly efi = { 28struct 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[] = {
104static umode_t efi_attr_is_visible(struct kobject *kobj, 105static 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
119static struct attribute_group efi_subsys_attr_group = { 123static 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
329static 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}
339device_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>");
78MODULE_DESCRIPTION("sysfs interface to EFI Variables"); 78MODULE_DESCRIPTION("sysfs interface to EFI Variables");
79MODULE_LICENSE("GPL"); 79MODULE_LICENSE("GPL");
80MODULE_VERSION(EFIVARS_VERSION); 80MODULE_VERSION(EFIVARS_VERSION);
81MODULE_ALIAS("platform:efivars");
81 82
82LIST_HEAD(efivar_sysfs_list); 83LIST_HEAD(efivar_sysfs_list);
83EXPORT_SYMBOL_GPL(efivar_sysfs_list); 84EXPORT_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#
7cflags-$(CONFIG_X86_32) := -march=i386
8cflags-$(CONFIG_X86_64) := -mcmodel=small
9cflags-$(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
13cflags-$(CONFIG_ARM64) := $(subst -pg,,$(KBUILD_CFLAGS))
14cflags-$(CONFIG_ARM) := $(subst -pg,,$(KBUILD_CFLAGS)) \
15 -fno-builtin -fpic -mno-single-pic-base
16
17KBUILD_CFLAGS := $(cflags-y) \
18 $(call cc-option,-ffreestanding) \
19 $(call cc-option,-fno-stack-protector)
20
21GCOV_PROFILE := n
22
23lib-y := efi-stub-helper.o
24lib-$(CONFIG_EFI_ARMSTUB) += arm-stub.o fdt.o
25
26CFLAGS_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
15static int __init efi_secureboot_enabled(efi_system_table_t *sys_table_arg) 20static 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
39static efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, 44efi_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}
63static efi_status_t efi_file_close(void *handle) 68
69efi_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
70static efi_status_t 76efi_status_t
71efi_file_read(void *handle, unsigned long *size, void *addr) 77efi_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
79static efi_status_t 85efi_status_t
80efi_file_size(efi_system_table_t *sys_table_arg, void *__fh, 86efi_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
132static void efi_char16_printk(efi_system_table_t *sys_table_arg, 138void 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 */
148static efi_status_t handle_kernel_image(efi_system_table_t *sys_table, 154efi_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
18struct file_info { 20struct file_info {
19 efi_file_handle_t *handle; 21 efi_file_handle_t *handle;
20 u64 size; 22 u64 size;
21}; 23};
22 24
23static void efi_printk(efi_system_table_t *sys_table_arg, char *str) 25void 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) 42efi_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,
44static 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
91static unsigned long __init get_dram_base(efi_system_table_t *sys_table_arg) 89unsigned 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 */
119static efi_status_t efi_high_alloc(efi_system_table_t *sys_table_arg, 117efi_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 */
205static efi_status_t efi_low_alloc(efi_system_table_t *sys_table_arg, 203efi_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
274static void efi_free(efi_system_table_t *sys_table_arg, unsigned long size, 272void 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 */
293static efi_status_t handle_cmdline_files(efi_system_table_t *sys_table_arg, 291efi_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 */
480static efi_status_t efi_relocate_kernel(efi_system_table_t *sys_table_arg, 478efi_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 */
592static char *efi_convert_cmdline(efi_system_table_t *sys_table_arg, 590char *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
8void efi_char16_printk(efi_system_table_t *, efi_char16_t *);
9
10efi_status_t efi_open_volume(efi_system_table_t *sys_table_arg, void *__image,
11 void **__fh);
12
13efi_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
17efi_status_t efi_file_read(void *handle, unsigned long *size, void *addr);
18
19efi_status_t efi_file_close(void *handle);
20
21unsigned long get_dram_base(efi_system_table_t *sys_table_arg);
22
23efi_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
31efi_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
40void *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
13static 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, 17efi_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
258static void *get_fdt(efi_system_table_t *sys_table) 262void *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
8int efi_reboot_quirk_mode = -1;
9
10void 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
36bool __weak efi_poweroff_required(void)
37{
38 return false;
39}
40
41static void efi_power_off(void)
42{
43 efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
44}
45
46static 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}
56late_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
29static 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
40static 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
51static 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
64static 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
75static 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
84static 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
91static 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
100static 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
112static 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
117static 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
125static 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
135static 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
147void 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}