134 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3#define pr_fmt(fmt) "efi: " fmt4 5#include <linux/module.h>6#include <linux/init.h>7#include <linux/efi.h>8#include <linux/libfdt.h>9#include <linux/of_fdt.h>10 11#include <linux/unaligned.h>12 13enum {14 SYSTAB,15 MMBASE,16 MMSIZE,17 DCSIZE,18 DCVERS,19 20 PARAMCOUNT21};22 23static __initconst const char name[][22] = {24 [SYSTAB] = "System Table ",25 [MMBASE] = "MemMap Address ",26 [MMSIZE] = "MemMap Size ",27 [DCSIZE] = "MemMap Desc. Size ",28 [DCVERS] = "MemMap Desc. Version ",29};30 31static __initconst const struct {32 const char path[17];33 u8 paravirt;34 const char params[PARAMCOUNT][26];35} dt_params[] = {36 {37#ifdef CONFIG_XEN // <-------17------>38 .path = "/hypervisor/uefi",39 .paravirt = 1,40 .params = {41 [SYSTAB] = "xen,uefi-system-table",42 [MMBASE] = "xen,uefi-mmap-start",43 [MMSIZE] = "xen,uefi-mmap-size",44 [DCSIZE] = "xen,uefi-mmap-desc-size",45 [DCVERS] = "xen,uefi-mmap-desc-ver",46 }47 }, {48#endif49 .path = "/chosen",50 .params = { // <-----------26----------->51 [SYSTAB] = "linux,uefi-system-table",52 [MMBASE] = "linux,uefi-mmap-start",53 [MMSIZE] = "linux,uefi-mmap-size",54 [DCSIZE] = "linux,uefi-mmap-desc-size",55 [DCVERS] = "linux,uefi-mmap-desc-ver",56 }57 }58};59 60static int __init efi_get_fdt_prop(const void *fdt, int node, const char *pname,61 const char *rname, void *var, int size)62{63 const void *prop;64 int len;65 u64 val;66 67 prop = fdt_getprop(fdt, node, pname, &len);68 if (!prop)69 return 1;70 71 val = (len == 4) ? (u64)be32_to_cpup(prop) : get_unaligned_be64(prop);72 73 if (size == 8)74 *(u64 *)var = val;75 else76 *(u32 *)var = (val < U32_MAX) ? val : U32_MAX; // saturate77 78 if (efi_enabled(EFI_DBG))79 pr_info(" %s: 0x%0*llx\n", rname, size * 2, val);80 81 return 0;82}83 84u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm)85{86 const void *fdt = initial_boot_params;87 unsigned long systab;88 int i, j, node;89 struct {90 void *var;91 int size;92 } target[] = {93 [SYSTAB] = { &systab, sizeof(systab) },94 [MMBASE] = { &mm->phys_map, sizeof(mm->phys_map) },95 [MMSIZE] = { &mm->size, sizeof(mm->size) },96 [DCSIZE] = { &mm->desc_size, sizeof(mm->desc_size) },97 [DCVERS] = { &mm->desc_version, sizeof(mm->desc_version) },98 };99 100 BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name));101 BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(dt_params[0].params));102 103 if (!fdt)104 return 0;105 106 for (i = 0; i < ARRAY_SIZE(dt_params); i++) {107 node = fdt_path_offset(fdt, dt_params[i].path);108 if (node < 0)109 continue;110 111 if (efi_enabled(EFI_DBG))112 pr_info("Getting UEFI parameters from %s in DT:\n",113 dt_params[i].path);114 115 for (j = 0; j < ARRAY_SIZE(target); j++) {116 const char *pname = dt_params[i].params[j];117 118 if (!efi_get_fdt_prop(fdt, node, pname, name[j],119 target[j].var, target[j].size))120 continue;121 if (!j)122 goto notfound;123 pr_err("Can't find property '%s' in DT!\n", pname);124 return 0;125 }126 if (dt_params[i].paravirt)127 set_bit(EFI_PARAVIRT, &efi.flags);128 return systab;129 }130notfound:131 pr_info("UEFI not found.\n");132 return 0;133}134