fdtparams.c 2.9 KB

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