diff options
author | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2017-05-16 02:53:29 +0000 |
---|---|---|
committer | YASUOKA Masahiko <yasuoka@cvs.openbsd.org> | 2017-05-16 02:53:29 +0000 |
commit | b1a5f4cd964a389b1458cffe5b7cc77485ac3294 (patch) | |
tree | c5ef81f18de4ac4fb71ab1d9f3d26fd26aa4be41 /sys/arch/amd64 | |
parent | 15cc7e5ebd35badc2441a72ec828e31ed988f4d2 (diff) |
Compare device pathes properly to find the booted disk.
Work with and test by Michele Curti.
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/stand/efiboot/efiboot.c | 68 |
1 files changed, 38 insertions, 30 deletions
diff --git a/sys/arch/amd64/stand/efiboot/efiboot.c b/sys/arch/amd64/stand/efiboot/efiboot.c index efa371f2ecd..d668258989f 100644 --- a/sys/arch/amd64/stand/efiboot/efiboot.c +++ b/sys/arch/amd64/stand/efiboot/efiboot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efiboot.c,v 1.17 2017/03/03 08:56:18 yasuoka Exp $ */ +/* $OpenBSD: efiboot.c,v 1.18 2017/05/16 02:53:28 yasuoka Exp $ */ /* * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net> @@ -52,7 +52,9 @@ static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; static EFI_GUID devp_guid = DEVICE_PATH_PROTOCOL; u_long efi_loadaddr; -static int efi_device_path_cmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, int); +static int efi_device_path_depth(EFI_DEVICE_PATH *dp, int); +static int efi_device_path_ncmp(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *, + int); static void efi_heap_init(void); static void efi_memprobe_internal(void); static void efi_video_init(void); @@ -159,7 +161,7 @@ struct disklist_lh efi_disklist; void efi_diskprobe(void) { - int i, bootdev; + int i, bootdev = 0, depth = -1; UINTN sz; EFI_STATUS status; EFI_HANDLE *handles = NULL; @@ -180,8 +182,10 @@ efi_diskprobe(void) if (handles == NULL || EFI_ERROR(status)) panic("BS->LocateHandle() returns %d", status); + if (efi_bootdp != NULL) + depth = efi_device_path_depth(efi_bootdp, MEDIA_DEVICE_PATH); + for (i = 0; i < sz / sizeof(EFI_HANDLE); i++) { - bootdev = 0; status = EFI_CALL(BS->HandleProtocol, handles[i], &blkio_guid, (void **)&blkio); if (EFI_ERROR(status)) @@ -193,53 +197,57 @@ efi_diskprobe(void) di = alloc(sizeof(struct diskinfo)); efid_init(di, blkio); - if (efi_bootdp == NULL) + if (efi_bootdp == NULL || depth == -1 || bootdev != 0) goto next; status = EFI_CALL(BS->HandleProtocol, handles[i], &devp_guid, (void **)&dp); if (EFI_ERROR(status)) goto next; - if (!efi_device_path_cmp(efi_bootdp, dp, HARDWARE_DEVICE_PATH)&& - !efi_device_path_cmp(efi_bootdp, dp, ACPI_DEVICE_PATH) && - !efi_device_path_cmp(efi_bootdp, dp, MESSAGING_DEVICE_PATH)) + if (efi_device_path_ncmp(efi_bootdp, dp, depth) == 0) { + TAILQ_INSERT_HEAD(&efi_disklist, di, list); bootdev = 1; + continue; + } next: - if (bootdev) - TAILQ_INSERT_HEAD(&efi_disklist, di, list); - else - TAILQ_INSERT_TAIL(&efi_disklist, di, list); + TAILQ_INSERT_TAIL(&efi_disklist, di, list); } free(handles, sz); } static int -efi_device_path_cmp(EFI_DEVICE_PATH *dpa, EFI_DEVICE_PATH *dpb, int dptype) +efi_device_path_depth(EFI_DEVICE_PATH *dp, int dptype) { - int cmp; - EFI_DEVICE_PATH *dp, *dpt_a = NULL, *dpt_b = NULL; + int i; - for (dp = dpa; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { - if (DevicePathType(dp) == dptype) { - dpt_a = dp; - break; - } - } - for (dp = dpb; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp)) { - if (DevicePathType(dp) == dptype) { - dpt_b = dp; - break; - } + for (i = 0; !IsDevicePathEnd(dp); dp = NextDevicePathNode(dp), i++) { + if (DevicePathType(dp) == dptype) + return (i); } - if (dpt_a && dpt_b) { - cmp = DevicePathNodeLength(dpt_a) - DevicePathNodeLength(dpt_b); + return (-1); +} + +static int +efi_device_path_ncmp(EFI_DEVICE_PATH *dpa, EFI_DEVICE_PATH *dpb, int deptn) +{ + int i, cmp; + + for (i = 0; i < deptn; i++) { + if (IsDevicePathEnd(dpa) || IsDevicePathEnd(dpb)) + return ((IsDevicePathEnd(dpa) && IsDevicePathEnd(dpb)) + ? 0 : (IsDevicePathEnd(dpa))? -1 : 1); + cmp = DevicePathNodeLength(dpa) - DevicePathNodeLength(dpb); + if (cmp) + return (cmp); + cmp = memcmp(dpa, dpb, DevicePathNodeLength(dpa)); if (cmp) return (cmp); - return (memcmp(dpt_a, dpt_b, DevicePathNodeLength(dpt_a))); + dpa = NextDevicePathNode(dpa); + dpb = NextDevicePathNode(dpb); } - return ((uintptr_t)dpt_a - (uintptr_t)dpt_b); + return (0); } /*********************************************************************** |