linux/drivers/firmware/efi/fdtparams.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2
   3#define pr_fmt(fmt) "efi: " fmt
   4
   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 <asm/unaligned.h>
  12
  13enum {
  14        SYSTAB,
  15        MMBASE,
  16        MMSIZE,
  17        DCSIZE,
  18        DCVERS,
  19
  20        PARAMCOUNT
  21};
  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        const char      params[PARAMCOUNT][26];
  34} dt_params[] = {
  35        {
  36#ifdef CONFIG_XEN    //  <-------17------>
  37                .path = "/hypervisor/uefi",
  38                .params = {
  39                        [SYSTAB] = "xen,uefi-system-table",
  40                        [MMBASE] = "xen,uefi-mmap-start",
  41                        [MMSIZE] = "xen,uefi-mmap-size",
  42                        [DCSIZE] = "xen,uefi-mmap-desc-size",
  43                        [DCVERS] = "xen,uefi-mmap-desc-ver",
  44                }
  45        }, {
  46#endif
  47                .path = "/chosen",
  48                .params = {     //  <-----------26----------->
  49                        [SYSTAB] = "linux,uefi-system-table",
  50                        [MMBASE] = "linux,uefi-mmap-start",
  51                        [MMSIZE] = "linux,uefi-mmap-size",
  52                        [DCSIZE] = "linux,uefi-mmap-desc-size",
  53                        [DCVERS] = "linux,uefi-mmap-desc-ver",
  54                }
  55        }
  56};
  57
  58static int __init efi_get_fdt_prop(const void *fdt, int node, const char *pname,
  59                                   const char *rname, void *var, int size)
  60{
  61        const void *prop;
  62        int len;
  63        u64 val;
  64
  65        prop = fdt_getprop(fdt, node, pname, &len);
  66        if (!prop)
  67                return 1;
  68
  69        val = (len == 4) ? (u64)be32_to_cpup(prop) : get_unaligned_be64(prop);
  70
  71        if (size == 8)
  72                *(u64 *)var = val;
  73        else
  74                *(u32 *)var = (val < U32_MAX) ? val : U32_MAX; // saturate
  75
  76        if (efi_enabled(EFI_DBG))
  77                pr_info("  %s: 0x%0*llx\n", rname, size * 2, val);
  78
  79        return 0;
  80}
  81
  82u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm)
  83{
  84        const void *fdt = initial_boot_params;
  85        unsigned long systab;
  86        int i, j, node;
  87        struct {
  88                void    *var;
  89                int     size;
  90        } target[] = {
  91                [SYSTAB] = { &systab,           sizeof(systab) },
  92                [MMBASE] = { &mm->phys_map,     sizeof(mm->phys_map) },
  93                [MMSIZE] = { &mm->size,         sizeof(mm->size) },
  94                [DCSIZE] = { &mm->desc_size,    sizeof(mm->desc_size) },
  95                [DCVERS] = { &mm->desc_version, sizeof(mm->desc_version) },
  96        };
  97
  98        BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name));
  99        BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(dt_params[0].params));
 100
 101        if (!fdt)
 102                return 0;
 103
 104        for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
 105                node = fdt_path_offset(fdt, dt_params[i].path);
 106                if (node < 0)
 107                        continue;
 108
 109                if (efi_enabled(EFI_DBG))
 110                        pr_info("Getting UEFI parameters from %s in DT:\n",
 111                                dt_params[i].path);
 112
 113                for (j = 0; j < ARRAY_SIZE(target); j++) {
 114                        const char *pname = dt_params[i].params[j];
 115
 116                        if (!efi_get_fdt_prop(fdt, node, pname, name[j],
 117                                              target[j].var, target[j].size))
 118                                continue;
 119                        if (!j)
 120                                goto notfound;
 121                        pr_err("Can't find property '%s' in DT!\n", pname);
 122                        return 0;
 123                }
 124                return systab;
 125        }
 126notfound:
 127        pr_info("UEFI not found.\n");
 128        return 0;
 129}
 130