Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mark Salter and committed by
Matt Fleming
0302f71c 719e2843

+95
+7
drivers/firmware/efi/Kconfig
··· 47 47 48 48 See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map. 49 49 50 + config 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 + 50 57 endmenu 51 58 52 59 config UEFI_CPER
+79
drivers/firmware/efi/efi.c
··· 20 20 #include <linux/init.h> 21 21 #include <linux/device.h> 22 22 #include <linux/efi.h> 23 + #include <linux/of.h> 24 + #include <linux/of_fdt.h> 23 25 #include <linux/io.h> 24 26 25 27 struct efi __read_mostly efi = { ··· 320 318 321 319 return 0; 322 320 } 321 + 322 + #ifdef CONFIG_EFI_PARAMS_FROM_FDT 323 + 324 + #define UEFI_PARAM(name, prop, field) \ 325 + { \ 326 + { name }, \ 327 + { prop }, \ 328 + offsetof(struct efi_fdt_params, field), \ 329 + FIELD_SIZEOF(struct efi_fdt_params, field) \ 330 + } 331 + 332 + static __initdata struct { 333 + const char name[32]; 334 + const char propname[32]; 335 + int offset; 336 + int size; 337 + } dt_params[] = { 338 + UEFI_PARAM("System Table", "linux,uefi-system-table", system_table), 339 + UEFI_PARAM("MemMap Address", "linux,uefi-mmap-start", mmap), 340 + UEFI_PARAM("MemMap Size", "linux,uefi-mmap-size", mmap_size), 341 + UEFI_PARAM("MemMap Desc. Size", "linux,uefi-mmap-desc-size", desc_size), 342 + UEFI_PARAM("MemMap Desc. Version", "linux,uefi-mmap-desc-ver", desc_ver) 343 + }; 344 + 345 + struct param_info { 346 + int verbose; 347 + void *params; 348 + }; 349 + 350 + static int __init fdt_find_uefi_params(unsigned long node, const char *uname, 351 + int depth, void *data) 352 + { 353 + struct param_info *info = data; 354 + void *prop, *dest; 355 + unsigned long len; 356 + u64 val; 357 + int i; 358 + 359 + if (depth != 1 || 360 + (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) 361 + return 0; 362 + 363 + pr_info("Getting parameters from FDT:\n"); 364 + 365 + for (i = 0; i < ARRAY_SIZE(dt_params); i++) { 366 + prop = of_get_flat_dt_prop(node, dt_params[i].propname, &len); 367 + if (!prop) { 368 + pr_err("Can't find %s in device tree!\n", 369 + dt_params[i].name); 370 + return 0; 371 + } 372 + dest = info->params + dt_params[i].offset; 373 + 374 + val = of_read_number(prop, len / sizeof(u32)); 375 + 376 + if (dt_params[i].size == sizeof(u32)) 377 + *(u32 *)dest = val; 378 + else 379 + *(u64 *)dest = val; 380 + 381 + if (info->verbose) 382 + pr_info(" %s: 0x%0*llx\n", dt_params[i].name, 383 + dt_params[i].size * 2, val); 384 + } 385 + return 1; 386 + } 387 + 388 + int __init efi_get_fdt_params(struct efi_fdt_params *params, int verbose) 389 + { 390 + struct param_info info; 391 + 392 + info.verbose = verbose; 393 + info.params = params; 394 + 395 + return of_scan_flat_dt(fdt_find_uefi_params, &info); 396 + } 397 + #endif /* CONFIG_EFI_PARAMS_FROM_FDT */
+9
include/linux/efi.h
··· 664 664 unsigned long desc_size; 665 665 }; 666 666 667 + struct efi_fdt_params { 668 + u64 system_table; 669 + u64 mmap; 670 + u32 mmap_size; 671 + u32 desc_size; 672 + u32 desc_ver; 673 + }; 674 + 667 675 typedef struct { 668 676 u32 revision; 669 677 u32 parent_handle; ··· 869 861 extern void efi_get_time(struct timespec *now); 870 862 extern int efi_set_rtc_mmss(const struct timespec *now); 871 863 extern void efi_reserve_boot_services(void); 864 + extern int efi_get_fdt_params(struct efi_fdt_params *params, int verbose); 872 865 extern struct efi_memory_map memmap; 873 866 874 867 /* Iterate through an efi_memory_map */