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