mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-08 14:54:23 +08:00
d85e3e3494
Currently, the EFI_PARAVIRT flag is only used by Xen dom0 boot on x86, even though other architectures also support pseudo-EFI boot, where the core kernel is invoked directly and provided with a set of data tables that resemble the ones constructed by the EFI stub, which never actually runs in that case. Let's fix this inconsistency, and always set this flag when booting dom0 via the EFI boot path. Note that Xen on x86 does not provide the EFI memory map in this case, whereas other architectures do, so move the associated EFI_PARAVIRT check into the x86 platform code. Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
134 lines
3.0 KiB
C
134 lines
3.0 KiB
C
// 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];
|
|
u8 paravirt;
|
|
const char params[PARAMCOUNT][26];
|
|
} dt_params[] = {
|
|
{
|
|
#ifdef CONFIG_XEN // <-------17------>
|
|
.path = "/hypervisor/uefi",
|
|
.paravirt = 1,
|
|
.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;
|
|
}
|
|
if (dt_params[i].paravirt)
|
|
set_bit(EFI_PARAVIRT, &efi.flags);
|
|
return systab;
|
|
}
|
|
notfound:
|
|
pr_info("UEFI not found.\n");
|
|
return 0;
|
|
}
|