aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware/efi
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 /drivers/firmware/efi
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>
Diffstat (limited to 'drivers/firmware/efi')
-rw-r--r--drivers/firmware/efi/Kconfig7
-rw-r--r--drivers/firmware/efi/efi.c79
2 files changed, 86 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 */