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