Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 
0003 #define pr_fmt(fmt) "efi: " fmt
0004 
0005 #include <linux/module.h>
0006 #include <linux/init.h>
0007 #include <linux/efi.h>
0008 #include <linux/libfdt.h>
0009 #include <linux/of_fdt.h>
0010 
0011 #include <asm/unaligned.h>
0012 
0013 enum {
0014     SYSTAB,
0015     MMBASE,
0016     MMSIZE,
0017     DCSIZE,
0018     DCVERS,
0019 
0020     PARAMCOUNT
0021 };
0022 
0023 static __initconst const char name[][22] = {
0024     [SYSTAB] = "System Table         ",
0025     [MMBASE] = "MemMap Address       ",
0026     [MMSIZE] = "MemMap Size          ",
0027     [DCSIZE] = "MemMap Desc. Size    ",
0028     [DCVERS] = "MemMap Desc. Version ",
0029 };
0030 
0031 static __initconst const struct {
0032     const char  path[17];
0033     const char  params[PARAMCOUNT][26];
0034 } dt_params[] = {
0035     {
0036 #ifdef CONFIG_XEN    //  <-------17------>
0037         .path = "/hypervisor/uefi",
0038         .params = {
0039             [SYSTAB] = "xen,uefi-system-table",
0040             [MMBASE] = "xen,uefi-mmap-start",
0041             [MMSIZE] = "xen,uefi-mmap-size",
0042             [DCSIZE] = "xen,uefi-mmap-desc-size",
0043             [DCVERS] = "xen,uefi-mmap-desc-ver",
0044         }
0045     }, {
0046 #endif
0047         .path = "/chosen",
0048         .params = { //  <-----------26----------->
0049             [SYSTAB] = "linux,uefi-system-table",
0050             [MMBASE] = "linux,uefi-mmap-start",
0051             [MMSIZE] = "linux,uefi-mmap-size",
0052             [DCSIZE] = "linux,uefi-mmap-desc-size",
0053             [DCVERS] = "linux,uefi-mmap-desc-ver",
0054         }
0055     }
0056 };
0057 
0058 static int __init efi_get_fdt_prop(const void *fdt, int node, const char *pname,
0059                    const char *rname, void *var, int size)
0060 {
0061     const void *prop;
0062     int len;
0063     u64 val;
0064 
0065     prop = fdt_getprop(fdt, node, pname, &len);
0066     if (!prop)
0067         return 1;
0068 
0069     val = (len == 4) ? (u64)be32_to_cpup(prop) : get_unaligned_be64(prop);
0070 
0071     if (size == 8)
0072         *(u64 *)var = val;
0073     else
0074         *(u32 *)var = (val < U32_MAX) ? val : U32_MAX; // saturate
0075 
0076     if (efi_enabled(EFI_DBG))
0077         pr_info("  %s: 0x%0*llx\n", rname, size * 2, val);
0078 
0079     return 0;
0080 }
0081 
0082 u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm)
0083 {
0084     const void *fdt = initial_boot_params;
0085     unsigned long systab;
0086     int i, j, node;
0087     struct {
0088         void    *var;
0089         int size;
0090     } target[] = {
0091         [SYSTAB] = { &systab,       sizeof(systab) },
0092         [MMBASE] = { &mm->phys_map, sizeof(mm->phys_map) },
0093         [MMSIZE] = { &mm->size,     sizeof(mm->size) },
0094         [DCSIZE] = { &mm->desc_size,    sizeof(mm->desc_size) },
0095         [DCVERS] = { &mm->desc_version, sizeof(mm->desc_version) },
0096     };
0097 
0098     BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(name));
0099     BUILD_BUG_ON(ARRAY_SIZE(target) != ARRAY_SIZE(dt_params[0].params));
0100 
0101     if (!fdt)
0102         return 0;
0103 
0104     for (i = 0; i < ARRAY_SIZE(dt_params); i++) {
0105         node = fdt_path_offset(fdt, dt_params[i].path);
0106         if (node < 0)
0107             continue;
0108 
0109         if (efi_enabled(EFI_DBG))
0110             pr_info("Getting UEFI parameters from %s in DT:\n",
0111                 dt_params[i].path);
0112 
0113         for (j = 0; j < ARRAY_SIZE(target); j++) {
0114             const char *pname = dt_params[i].params[j];
0115 
0116             if (!efi_get_fdt_prop(fdt, node, pname, name[j],
0117                           target[j].var, target[j].size))
0118                 continue;
0119             if (!j)
0120                 goto notfound;
0121             pr_err("Can't find property '%s' in DT!\n", pname);
0122             return 0;
0123         }
0124         return systab;
0125     }
0126 notfound:
0127     pr_info("UEFI not found.\n");
0128     return 0;
0129 }