diff options
| author | Andrew Turner <andrew@FreeBSD.org> | 2018-03-20 13:35:20 +0000 |
|---|---|---|
| committer | Andrew Turner <andrew@FreeBSD.org> | 2018-03-20 13:35:20 +0000 |
| commit | ed4c884f2e7774bf4f2c86e2af644be8365c8029 (patch) | |
| tree | 84b1636bbe72269450e747eb6b8fc4ae852312a7 /sys/dev/efidev | |
| parent | 400326b667622a97ce4d0d8f12e8ae1bfa93c75f (diff) | |
Notes
Diffstat (limited to 'sys/dev/efidev')
| -rw-r--r-- | sys/dev/efidev/efirt.c | 37 |
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); } |
