summaryrefslogtreecommitdiff
path: root/sys/dev/efidev
diff options
context:
space:
mode:
authorAndrew Turner <andrew@FreeBSD.org>2018-03-20 13:35:20 +0000
committerAndrew Turner <andrew@FreeBSD.org>2018-03-20 13:35:20 +0000
commited4c884f2e7774bf4f2c86e2af644be8365c8029 (patch)
tree84b1636bbe72269450e747eb6b8fc4ae852312a7 /sys/dev/efidev
parent400326b667622a97ce4d0d8f12e8ae1bfa93c75f (diff)
Notes
Diffstat (limited to 'sys/dev/efidev')
-rw-r--r--sys/dev/efidev/efirt.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c
index 6fd6d0066e35..f1c543b116de 100644
--- a/sys/dev/efidev/efirt.c
+++ b/sys/dev/efidev/efirt.c
@@ -99,6 +99,25 @@ efi_status_to_errno(efi_status status)
static struct mtx efi_lock;
+static bool
+efi_is_in_map(struct efi_md *map, int ndesc, int descsz, vm_offset_t addr)
+{
+ struct efi_md *p;
+ int i;
+
+ for (i = 0, p = map; i < ndesc; i++, p = efi_next_descriptor(p,
+ descsz)) {
+ if ((p->md_attr & EFI_MD_ATTR_RT) == 0)
+ continue;
+
+ if (addr >= (uintptr_t)p->md_virt &&
+ addr < (uintptr_t)p->md_virt + p->md_pages * PAGE_SIZE)
+ return (true);
+ }
+
+ return (false);
+}
+
static int
efi_init(void)
{
@@ -164,6 +183,24 @@ efi_init(void)
return (ENXIO);
}
+ /*
+ * Some UEFI implementations have multiple implementations of the
+ * RS->GetTime function. They switch from one we can only use early
+ * in the boot process to one valid as a RunTime service only when we
+ * call RS->SetVirtualAddressMap. As this is not always the case, e.g.
+ * with an old loader.efi, check if the RS->GetTime function is within
+ * the EFI map, and fail to attach if not.
+ */
+ if (!efi_is_in_map(map, efihdr->memory_size / efihdr->descriptor_size,
+ efihdr->descriptor_size, (vm_offset_t)efi_runtime->rt_gettime)) {
+ if (bootverbose)
+ printf(
+ "EFI runtime services table has an invalid pointer\n");
+ efi_runtime = NULL;
+ efi_destroy_1t1_map();
+ return (ENXIO);
+ }
+
return (0);
}