aboutsummaryrefslogtreecommitdiff
path: root/sys/boot
diff options
context:
space:
mode:
authorToomas Soome <tsoome@FreeBSD.org>2017-02-11 15:25:49 +0000
committerToomas Soome <tsoome@FreeBSD.org>2017-02-11 15:25:49 +0000
commitc05d6667473ba69ade25bff7186eaa5a565b66d0 (patch)
treede819f74511b1b0e6106b19aa20556d282f52460 /sys/boot
parent07569d55334c6221ee70333030883bba9185978d (diff)
downloadsrc-c05d6667473ba69ade25bff7186eaa5a565b66d0.tar.gz
src-c05d6667473ba69ade25bff7186eaa5a565b66d0.zip
loader: implement MEDIA_FILEPATH_DP support in efipart
The efipart rework did break the ARM systems as the new code is using more exact filters to sort the devices and we need to add support for MEDIA_FILEPATH_DP device paths. PR: 216940 Reported by: karl@denninger.net Reviewed by: allanjude, manu Approved by: allanjude (mentor) Differential Revision: https://reviews.freebsd.org/D9520
Notes
Notes: svn path=/head/; revision=313645
Diffstat (limited to 'sys/boot')
-rw-r--r--sys/boot/efi/libefi/efipart.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/sys/boot/efi/libefi/efipart.c b/sys/boot/efi/libefi/efipart.c
index 790f41be6cbf..e23b39ee1f6c 100644
--- a/sys/boot/efi/libefi/efipart.c
+++ b/sys/boot/efi/libefi/efipart.c
@@ -417,6 +417,89 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle)
return (0);
}
+/*
+ * The MEDIA_FILEPATH_DP has device name.
+ * From U-Boot sources it looks like names are in the form
+ * of typeN:M, where type is interface type, N is disk id
+ * and M is partition id.
+ */
+static int
+efipart_hdinfo_add_filepath(EFI_HANDLE disk_handle)
+{
+ EFI_DEVICE_PATH *devpath;
+ FILEPATH_DEVICE_PATH *node;
+ char *pathname, *p;
+ int unit, len;
+ pdinfo_t *pd, *last;
+
+ /* First collect and verify all the data */
+ if ((devpath = efi_lookup_devpath(disk_handle)) == NULL)
+ return (ENOENT);
+ node = (FILEPATH_DEVICE_PATH *)efi_devpath_last_node(devpath);
+ if (node == NULL)
+ return (ENOENT); /* This should not happen. */
+
+ pd = malloc(sizeof(pdinfo_t));
+ if (pd == NULL) {
+ printf("Failed to add disk, out of memory\n");
+ return (ENOMEM);
+ }
+ memset(pd, 0, sizeof(pdinfo_t));
+ STAILQ_INIT(&pd->pd_part);
+ last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
+ if (last != NULL)
+ unit = last->pd_unit + 1;
+ else
+ unit = 0;
+
+ /* FILEPATH_DEVICE_PATH has 0 terminated string */
+ for (len = 0; node->PathName[len] != 0; len++)
+ ;
+ if ((pathname = malloc(len + 1)) == NULL) {
+ printf("Failed to add disk, out of memory\n");
+ free(pd);
+ return (ENOMEM);
+ }
+ cpy16to8(node->PathName, pathname, len + 1);
+ p = strchr(pathname, ':');
+
+ /*
+ * Assume we are receiving handles in order, first disk handle,
+ * then partitions for this disk. If this assumption proves
+ * false, this code would need update.
+ */
+ if (p == NULL) { /* no colon, add the disk */
+ pd->pd_handle = disk_handle;
+ pd->pd_unit = unit;
+ pd->pd_devpath = devpath;
+ STAILQ_INSERT_TAIL(&hdinfo, pd, pd_link);
+ free(pathname);
+ return (0);
+ }
+ p++; /* skip the colon */
+ unit = (int)strtol(p, NULL, 0);
+
+ /*
+ * We should have disk registered, if not, we are receiving
+ * handles out of order, and this code should be reworked
+ * to create "blank" disk for partition, and to find the
+ * disk based on PathName compares.
+ */
+ if (last == NULL) {
+ printf("BUG: No disk for partition \"%s\"\n", pathname);
+ free(pathname);
+ free(pd);
+ return (EINVAL);
+ }
+ /* Add the partition. */
+ pd->pd_handle = disk_handle;
+ pd->pd_unit = unit;
+ pd->pd_devpath = devpath;
+ STAILQ_INSERT_TAIL(&last->pd_part, pd, pd_link);
+ free(pathname);
+ return (0);
+}
+
static void
efipart_updatehd(void)
{
@@ -467,6 +550,12 @@ efipart_updatehd(void)
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;
+ }
}
}