diff options
author | Toomas Soome <tsoome@FreeBSD.org> | 2017-02-11 15:25:49 +0000 |
---|---|---|
committer | Toomas Soome <tsoome@FreeBSD.org> | 2017-02-11 15:25:49 +0000 |
commit | c05d6667473ba69ade25bff7186eaa5a565b66d0 (patch) | |
tree | de819f74511b1b0e6106b19aa20556d282f52460 /sys/boot | |
parent | 07569d55334c6221ee70333030883bba9185978d (diff) | |
download | src-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.c | 89 |
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; + } } } |