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-all
mailing list