svn commit: r326089 - head/stand/efi/libefi

Toomas Soome tsoome at FreeBSD.org
Wed Nov 22 08:48:02 UTC 2017


Author: tsoome
Date: Wed Nov 22 08:48:00 2017
New Revision: 326089
URL: https://svnweb.freebsd.org/changeset/base/326089

Log:
  loader.efi: efipart does not recognize partitionless disks
  
  Rework the block device handle check to allow more robust device
  classification. This is mostly usability issue - it can be quite confusing
  for user when no disks are listed with lsdev.
  
  Add more comments about what and why is done.
  
  Reviewed by:	imp
  Differential Revision:	https://reviews.freebsd.org/D13026

Modified:
  head/stand/efi/libefi/efipart.c

Modified: head/stand/efi/libefi/efipart.c
==============================================================================
--- head/stand/efi/libefi/efipart.c	Wed Nov 22 06:36:55 2017	(r326088)
+++ head/stand/efi/libefi/efipart.c	Wed Nov 22 08:48:00 2017	(r326089)
@@ -196,6 +196,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
@@ -308,9 +374,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))
@@ -380,13 +450,21 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_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) {
@@ -397,6 +475,9 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_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;
@@ -419,6 +500,9 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_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");
@@ -541,7 +625,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],
@@ -550,6 +635,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)
@@ -568,18 +659,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);
 	}
 }
 


More information about the svn-src-head mailing list