From f58b22cff52aa6f7ce2ef23b9bbcc9d9e13f6cd7 Mon Sep 17 00:00:00 2001 From: Toomas Soome Date: Fri, 10 Nov 2017 13:41:53 +0200 Subject: [PATCH] 8796 loader.efi: efipart does not recognize partitionless disks Reviewed by: Robert Mustacchi Approved by: Hans Rosenfeld --- usr/src/boot/sys/boot/efi/libefi/efipart.c | 111 ++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 11 deletions(-) diff --git a/usr/src/boot/sys/boot/efi/libefi/efipart.c b/usr/src/boot/sys/boot/efi/libefi/efipart.c index 21d741849a..347c14f68a 100644 --- a/usr/src/boot/sys/boot/efi/libefi/efipart.c +++ b/usr/src/boot/sys/boot/efi/libefi/efipart.c @@ -178,6 +178,72 @@ efipart_floppy(EFI_DEVICE_PATH *node) } /* + * Determine if the provided device path is hdd. + * + * There really is no simple fool proof way to classify the devices. + * Since we do build three lists of devices - floppy, cd and hdd, we + * will try to see if the device is floppy or cd, and list anything else + * as hdd. + */ +static bool +efipart_hdd(EFI_DEVICE_PATH *dp) +{ + unsigned i, nin; + EFI_DEVICE_PATH *devpath, *node; + EFI_BLOCK_IO *blkio; + EFI_STATUS status; + + if (dp == NULL) + return (false); + + if ((node = efi_devpath_last_node(dp)) == NULL) + return (false); + + if (efipart_floppy(node) != NULL) + return (false); + + /* + * Test every EFI BLOCK IO handle to make sure dp is not device path + * for CD/DVD. + */ + nin = efipart_nhandles / sizeof (*efipart_handles); + for (i = 0; i < nin; i++) { + devpath = efi_lookup_devpath(efipart_handles[i]); + if (devpath == NULL) + return (false); + + /* Only continue testing when dp is prefix in devpath. */ + if (!efi_devpath_is_prefix(dp, devpath)) + continue; + + /* + * The device path has to have last node describing the + * device, or we can not test the type. + */ + if ((node = efi_devpath_last_node(devpath)) == NULL) + return (false); + + if (DevicePathType(node) == MEDIA_DEVICE_PATH && + DevicePathSubType(node) == MEDIA_CDROM_DP) { + return (false); + } + + /* Make sure we do have the media. */ + status = BS->HandleProtocol(efipart_handles[i], + &blkio_guid, (void **)&blkio); + if (EFI_ERROR(status)) + return (false); + + /* USB or SATA cd without the media. */ + if (blkio->Media->RemovableMedia && + !blkio->Media->MediaPresent) { + return (false); + } + } + return (true); +} + +/* * Add or update entries with new handle data. */ static int @@ -290,9 +356,13 @@ efipart_updatecd(void) if ((node = efi_devpath_last_node(devpath)) == NULL) continue; + if (efipart_floppy(node) != NULL) continue; + if (efipart_hdd(devpath)) + continue; + status = BS->HandleProtocol(efipart_handles[i], &blkio_guid, (void **)&blkio); if (EFI_ERROR(status)) @@ -362,13 +432,21 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle) pdinfo_t *hd, *pd, *last; disk_devpath = efi_lookup_devpath(disk_handle); - part_devpath = efi_lookup_devpath(part_handle); - if (disk_devpath == NULL || part_devpath == NULL) { + if (disk_devpath == NULL) return (ENOENT); + + if (part_handle != NULL) { + part_devpath = efi_lookup_devpath(part_handle); + if (part_devpath == NULL) + return (ENOENT); + node = (HARDDRIVE_DEVICE_PATH *) + efi_devpath_last_node(part_devpath); + if (node == NULL) + return (ENOENT); /* This should not happen. */ + } else { + part_devpath = NULL; + node = NULL; } - node = (HARDDRIVE_DEVICE_PATH *)efi_devpath_last_node(part_devpath); - if (node == NULL) - return (ENOENT); /* This should not happen. */ pd = calloc(1, sizeof(pdinfo_t)); if (pd == NULL) { @@ -379,6 +457,9 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle) STAILQ_FOREACH(hd, &hdinfo, pd_link) { if (efi_devpath_match(hd->pd_devpath, disk_devpath) == true) { + if (part_devpath == NULL) + return (0); + /* Add the partition. */ pd->pd_handle = part_handle; pd->pd_unit = node->PartitionNumber; @@ -401,6 +482,9 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle) hd->pd_devpath = disk_devpath; STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link); + if (part_devpath == NULL) + return (0); + pd = calloc(1, sizeof(pdinfo_t)); if (pd == NULL) { printf("Failed to add partition, out of memory\n"); @@ -523,7 +607,8 @@ efipart_updatehd(void) if ((node = efi_devpath_last_node(devpath)) == NULL) continue; - if (efipart_floppy(node) != NULL) + + if (!efipart_hdd(devpath)) continue; status = BS->HandleProtocol(efipart_handles[i], @@ -532,6 +617,12 @@ efipart_updatehd(void) continue; if (DevicePathType(node) == MEDIA_DEVICE_PATH && + DevicePathSubType(node) == MEDIA_FILEPATH_DP) { + efipart_hdinfo_add_filepath(efipart_handles[i]); + continue; + } + + if (DevicePathType(node) == MEDIA_DEVICE_PATH && DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) { devpathcpy = efi_devpath_trim(devpath); if (devpathcpy == NULL) @@ -550,18 +641,16 @@ efipart_updatehd(void) continue; if ((node = efi_devpath_last_node(devpathcpy)) == NULL) continue; + if (DevicePathType(node) == MEDIA_DEVICE_PATH && DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) continue; + efipart_hdinfo_add(handle, efipart_handles[i]); continue; } - if (DevicePathType(node) == MEDIA_DEVICE_PATH && - DevicePathSubType(node) == MEDIA_FILEPATH_DP) { - efipart_hdinfo_add_filepath(efipart_handles[i]); - continue; - } + efipart_hdinfo_add(efipart_handles[i], NULL); } } -- 2.11.4.GIT