Page MenuHomeFreeBSD

D20347.id58108.diff
No OneTemporary

D20347.id58108.diff

Index: sys/dev/efidev/efirt.c
===================================================================
--- sys/dev/efidev/efirt.c
+++ sys/dev/efidev/efirt.c
@@ -60,6 +60,10 @@
static struct efi_systbl *efi_systbl;
static eventhandler_tag efi_shutdown_tag;
+static struct efi_map_header *efihdr;
+static size_t efi_hdr_sz;
+static struct efi_md *efi_map;
+static int efi_map_ndesc;
/*
* The following pointers point to tables in the EFI runtime service data pages.
* Care should be taken to make sure that we've properly entered the EFI runtime
@@ -133,6 +137,88 @@
return (false);
}
+static int
+efi_map_compare(const void *key, const void *member)
+{
+ uint64_t pa;
+ const struct efi_md *md;
+
+ pa = *(const uint64_t *)key;
+ md = (const struct efi_md *)member;
+
+ if (pa >= (uintptr_t)md->md_phys &&
+ pa < (uintptr_t)md->md_phys + md->md_pages * PAGE_SIZE)
+ return (0);
+ if (pa < (uintptr_t)md->md_phys)
+ return (-1);
+ return (1);
+}
+
+static int
+efi_map_qsort_compare(const void *p1, const void *p2)
+{
+ const struct efi_md *md1;
+ const struct efi_md *md2;
+
+ md1 = (const struct efi_md *)p1;
+ md2 = (const struct efi_md *)p2;
+ return (((uintptr_t)md1->md_phys > (uintptr_t)md2->md_phys) -
+ ((uintptr_t)md1->md_phys < (uintptr_t)md2->md_phys));
+}
+
+static bool
+efi_get_memory_map(void)
+{
+ caddr_t kmdp;
+
+ if (efi_map != NULL)
+ return (true);
+ kmdp = preload_search_by_type("elf kernel");
+ if (kmdp == NULL)
+ kmdp = preload_search_by_type("elf64 kernel");
+ efihdr = (struct efi_map_header *)preload_search_info(kmdp,
+ MODINFO_METADATA | MODINFOMD_EFI_MAP);
+ if (efihdr == NULL)
+ return (false);
+ efi_hdr_sz = roundup2(sizeof(struct efi_map_header), 16);
+ efi_map = (struct efi_md *)((uint8_t *)efihdr + efi_hdr_sz);
+ if (efihdr->descriptor_size == 0)
+ return (false);
+ efi_map_ndesc = efihdr->memory_size / efihdr->descriptor_size;
+ qsort(efi_map, efi_map_ndesc, efihdr->descriptor_size,
+ efi_map_qsort_compare);
+ return (true);
+}
+
+uint64_t
+efi_memory_attribute(vm_paddr_t pa, vm_paddr_t *out)
+{
+ struct efi_md *p, *n;
+
+ if (!efi_get_memory_map())
+ return (0);
+ p = bsearch(&pa, efi_map, efi_map_ndesc, efihdr->descriptor_size,
+ efi_map_compare);
+ if (p == NULL)
+ return (EFI_MD_ATTR_UC);
+ if (out == NULL)
+ return (p->md_attr);
+ *out = pa + (p->md_pages - 1) * PAGE_SIZE;
+ n = p;
+ do {
+ pa += n->md_pages * PAGE_SIZE;
+ n = bsearch(&pa, efi_map, efi_map_ndesc,
+ efihdr->descriptor_size, efi_map_compare);
+ if (n == NULL)
+ break;
+ if (n->md_attr == p->md_attr)
+ *out = pa + (n->md_pages - 1) * PAGE_SIZE;
+ else
+ break;
+ } while (1);
+ return (p->md_attr);
+}
+
static void
efi_shutdown_final(void *dummy __unused, int howto)
{
@@ -149,12 +235,8 @@
static int
efi_init(void)
{
- struct efi_map_header *efihdr;
- struct efi_md *map;
struct efi_rt *rtdm;
- caddr_t kmdp;
- size_t efisz;
- int ndesc, rt_disabled;
+ int rt_disabled;
rt_disabled = 0;
TUNABLE_INT_FETCH("efi.rt.disabled", &rt_disabled);
@@ -182,23 +264,13 @@
printf("EFI config table is not present\n");
}
- kmdp = preload_search_by_type("elf kernel");
- if (kmdp == NULL)
- kmdp = preload_search_by_type("elf64 kernel");
- efihdr = (struct efi_map_header *)preload_search_info(kmdp,
- MODINFO_METADATA | MODINFOMD_EFI_MAP);
- if (efihdr == NULL) {
+ if (!efi_get_memory_map()) {
if (bootverbose)
printf("EFI map is not present\n");
return (0);
}
- efisz = (sizeof(struct efi_map_header) + 0xf) & ~0xf;
- map = (struct efi_md *)((uint8_t *)efihdr + efisz);
- if (efihdr->descriptor_size == 0)
- return (ENOMEM);
- ndesc = efihdr->memory_size / efihdr->descriptor_size;
- if (!efi_create_1t1_map(map, ndesc, efihdr->descriptor_size)) {
+ if (!efi_create_1t1_map(efi_map, efi_map_ndesc, efihdr->descriptor_size)) {
if (bootverbose)
printf("EFI cannot create runtime map\n");
return (ENOMEM);
@@ -223,8 +295,8 @@
* the EFI map, and fail to attach if not.
*/
rtdm = (struct efi_rt *)efi_phys_to_kva((uintptr_t)efi_runtime);
- if (rtdm == NULL || !efi_is_in_map(map, ndesc, efihdr->descriptor_size,
- (vm_offset_t)rtdm->rt_gettime)) {
+ if (rtdm == NULL || !efi_is_in_map(efi_map, efi_map_ndesc,
+ efihdr->descriptor_size, (vm_offset_t)rtdm->rt_gettime)) {
if (bootverbose)
printf(
"EFI runtime services table has an invalid pointer\n");
@@ -234,6 +306,23 @@
}
#endif
+ if (bootverbose) {
+ printf("EFI RT Signature: %jx, Revision=%x, Size=%x, CRC32=%x\n",
+ efi_runtime->rt_hdr.th_sig,
+ efi_runtime->rt_hdr.th_rev,
+ efi_runtime->rt_hdr.th_hdrsz,
+ efi_runtime->rt_hdr.th_crc32);
+ printf("EFI RT Get Time: %p\n", efi_runtime->rt_gettime);
+ printf("EFI RT Set Time: %p\n", efi_runtime->rt_settime);
+ printf("EFI RT Get Wakeup Time: %p\n",
+ efi_runtime->rt_getwaketime);
+ printf("EFI RT Set Wakeup Time: %p\n",
+ efi_runtime->rt_setwaketime);
+ printf("EFI RT Get Var: %p\n", efi_runtime->rt_getvar);
+ printf("EFI RT Get Next Var: %p\n", efi_runtime->rt_scanvar);
+ printf("EFI RT Set Var: %p\n", efi_runtime->rt_setvar);
+ }
+
/*
* We use SHUTDOWN_PRI_LAST - 1 to trigger after IPMI, but before ACPI.
*/
Index: sys/sys/efi.h
===================================================================
--- sys/sys/efi.h
+++ sys/sys/efi.h
@@ -192,6 +192,7 @@
int efi_var_nextname(size_t *namesize, uint16_t *name, struct uuid *vendor);
int efi_var_set(uint16_t *name, struct uuid *vendor, uint32_t attrib,
size_t datasize, void *data);
+uint64_t efi_memory_attribute(vm_paddr_t pa, vm_paddr_t *out);
#endif /* _KERNEL */

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 31, 9:30 AM (10 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30631060
Default Alt Text
D20347.id58108.diff (5 KB)

Event Timeline