aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Salter <msalter@redhat.com>2013-12-30 12:12:12 -0500
committerMatt Fleming <matt.fleming@intel.com>2014-04-30 14:49:46 -0400
commit0302f71c0aa59571ac306f93068fbbfe65ea349b (patch)
tree0a34f2ec1ace904079f09accd4329ec36bf021f2
parent719e284369d23c3feb02d02ad58b3a516df47806 (diff)
efi: add helper function to get UEFI params from FDT
ARM and ARM64 architectures use the device tree to pass UEFI parameters from stub to kernel. These parameters are things known to the stub but not discoverable by the kernel after the stub calls ExitBootSerives(). There is a helper function in: drivers/firmware/efi/fdt.c which the stub uses to add the UEFI parameters to the device tree. This patch adds a complimentary helper function which UEFI runtime support may use to retrieve the parameters from the device tree. If an architecture wants to use this helper, it should select CONFIG_EFI_PARAMS_FROM_FDT. Signed-off-by: Mark Salter <msalter@redhat.com> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Matt Fleming <matt.fleming@intel.com>
-rw-r--r--drivers/firmware/efi/Kconfig7
-rw-r--r--drivers/firmware/efi/efi.c79
-rw-r--r--include/linux/efi.h9
3 files changed, 95 insertions, 0 deletions
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 1e75f48b61f8..d420ae2d3413 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -47,6 +47,13 @@ config EFI_RUNTIME_MAP
47 47
48 See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map. 48 See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
49 49
50config EFI_PARAMS_FROM_FDT
51 bool
52 help
53 Select this config option from the architecture Kconfig if
54 the EFI runtime support gets system table address, memory
55 map address, and other parameters from the device tree.
56
50endmenu 57endmenu
51 58
52config UEFI_CPER 59config UEFI_CPER
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index af20f1712337..cd36deb619fa 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -20,6 +20,8 @@
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/device.h> 21#include <linux/device.h>
22#include <linux/efi.h> 22#include <linux/efi.h>
23#include <linux/of.h>
24#include <linux/of_fdt.h>
23#include <linux/io.h> 25#include <linux/io.h>
24 26
25struct efi __read_mostly efi = { 27struct efi __read_mostly efi = {
@@ -318,3 +320,80 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
318 320
319 return 0; 321 return 0;
320} 322}
323
324#ifdef CONFIG_EFI_PARAMS_FROM_FDT
325
326#define UEFI_PARAM(name, prop, field) \
327 { \
328 { name }, \
329 { prop }, \
330 offsetof(struct efi_fdt_params, field), \
331 FIELD_SIZEOF(struct efi_fdt_params, field) \
332 }
333
334static __initdata struct {
335 const char name[32];
336 const char propname[32];
337 int offset;
338 int size;
339} dt_params[] = {
340 UEFI_PARAM("System Table", "linux,uefi-system-table", system_table),
341 UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap),
342 UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size),
343 UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size),
344 UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver)
345};
346
347struct param_info {
348 int verbose;
349 void *params;
350};
351
352static int __init fdt_find_uefi_params(unsigned long node, const char *uname,
353 int depth, void *data)
354{
355 struct param_info *info = data;
356 void *prop, *dest;
357 unsigned long len;
358 u64 val;
359 int i;
360
361 if (depth != 1 ||
362 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
363 return 0;
364
365 pr_info("Getting parameters from FDT:\n");
366
367 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
368 prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len);
369 if (!prop) {
370 pr_err("Can't find %s in device tree!\n",
371 dt_params[i].name);
372 return 0;
373 }
374 dest = info->params + dt_params[i].offset;
375
376 val = of_read_number(prop, len / sizeof(u32));
377
378 if (dt_params[i].size == sizeof(u32))
379 *(u32 *)dest = val;
380 else
381 *(u64 *)dest = val;
382
383 if (info->verbose)
384 pr_info(" %s: 0x%0*llx\n", dt_params[i].name,
385 dt_params[i].size * 2, val);
386 }
387 return 1;
388}
389
390int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose)
391{
392 struct param_info info;
393
394 info.verbose = verbose;
395 info.params = params;
396
397 return of_scan_flat_dt(fdt_find_uefi_params, &info);
398}
399#endif /* CONFIG_EFI_PARAMS_FROM_FDT */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 6a4d8e27d1d7..cd0172e796cb 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -664,6 +664,14 @@ struct efi_memory_map {
664 unsigned long desc_size; 664 unsigned long desc_size;
665}; 665};
666 666
667struct efi_fdt_params {
668 u64 system_table;
669 u64 mmap;
670 u32 mmap_size;
671 u32 desc_size;
672 u32 desc_ver;
673};
674
667typedef struct { 675typedef struct {
668 u32 revision; 676 u32 revision;
669 u32 parent_handle; 677 u32 parent_handle;
@@ -861,6 +869,7 @@ extern void efi_initialize_iomem_resources(struct resource *code_resource,
861extern void efi_get_time(struct timespec *now); 869extern void efi_get_time(struct timespec *now);
862extern int efi_set_rtc_mmss(const struct timespec *now); 870extern int efi_set_rtc_mmss(const struct timespec *now);
863extern void efi_reserve_boot_services(void); 871extern void efi_reserve_boot_services(void);
872extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose);
864extern struct efi_memory_map memmap; 873extern struct efi_memory_map memmap;
865 874
866/* Iterate through an efi_memory_map */ 875/* Iterate through an efi_memory_map */