svn commit: r353501 - in stable/12/stand: efi/boot1 efi/include efi/libefi efi/loader efi/loader/arch/i386 libsa
Toomas Soome
tsoome at FreeBSD.org
Mon Oct 14 19:17:02 UTC 2019
Author: tsoome
Date: Mon Oct 14 19:17:00 2019
New Revision: 353501
URL: https://svnweb.freebsd.org/changeset/base/353501
Log:
loader.efi: Block IO should honor align_io
MFC: r347195, r350654, r350655, r350656, r351274, r351630, r351637
r352421, r352439, r352443, r352444, r352445, r352446, r352451
We need to bring in a bit more than just align_io change.
Modified:
stable/12/stand/efi/boot1/boot1.c
stable/12/stand/efi/include/efilib.h
stable/12/stand/efi/libefi/devpath.c
stable/12/stand/efi/libefi/efinet.c
stable/12/stand/efi/libefi/efipart.c
stable/12/stand/efi/libefi/libefi.c
stable/12/stand/efi/loader/arch/i386/efimd.c
stable/12/stand/efi/loader/efi_main.c
stable/12/stand/efi/loader/framebuffer.c
stable/12/stand/efi/loader/main.c
stable/12/stand/libsa/stand.h
stable/12/stand/libsa/zalloc.c
stable/12/stand/libsa/zalloc_defs.h
stable/12/stand/libsa/zalloc_malloc.c
stable/12/stand/libsa/zalloc_mem.h
stable/12/stand/libsa/zalloc_protos.h
Directory Properties:
stable/12/ (props changed)
Modified: stable/12/stand/efi/boot1/boot1.c
==============================================================================
--- stable/12/stand/efi/boot1/boot1.c Mon Oct 14 19:06:17 2019 (r353500)
+++ stable/12/stand/efi/boot1/boot1.c Mon Oct 14 19:17:00 2019 (r353501)
@@ -246,8 +246,9 @@ try_boot(void)
goto errout;
}
- if ((status = BS->HandleProtocol(loaderhandle, &LoadedImageGUID,
- (VOID**)&loaded_image)) != EFI_SUCCESS) {
+ status = OpenProtocolByHandle(loaderhandle, &LoadedImageGUID,
+ (void **)&loaded_image);
+ if (status != EFI_SUCCESS) {
printf("Failed to query LoadedImage provided by %s (%lu)\n",
mod->name, EFI_ERROR_CODE(status));
goto errout;
@@ -306,7 +307,7 @@ probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, B
UINTN i;
/* Figure out if we're dealing with an actual partition. */
- status = BS->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+ status = OpenProtocolByHandle(h, &DevicePathGUID, (void **)&devpath);
if (status == EFI_UNSUPPORTED)
return (status);
@@ -322,7 +323,7 @@ probe_handle(EFI_HANDLE h, EFI_DEVICE_PATH *imgpath, B
efi_free_devpath_name(text);
}
#endif
- status = BS->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+ status = OpenProtocolByHandle(h, &BlockIoProtocolGUID, (void **)&blkio);
if (status == EFI_UNSUPPORTED)
return (status);
@@ -445,7 +446,7 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
putchar('\n');
/* Determine the devpath of our image so we can prefer it. */
- status = BS->HandleProtocol(IH, &LoadedImageGUID, (VOID**)&img);
+ status = OpenProtocolByHandle(IH, &LoadedImageGUID, (void **)&img);
imgpath = NULL;
if (status == EFI_SUCCESS) {
text = efi_devpath_name(img->FilePath);
@@ -455,8 +456,8 @@ efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
efi_free_devpath_name(text);
}
- status = BS->HandleProtocol(img->DeviceHandle, &DevicePathGUID,
- (void **)&imgpath);
+ status = OpenProtocolByHandle(img->DeviceHandle,
+ &DevicePathGUID, (void **)&imgpath);
if (status != EFI_SUCCESS) {
DPRINTF("Failed to get image DevicePath (%lu)\n",
EFI_ERROR_CODE(status));
Modified: stable/12/stand/efi/include/efilib.h
==============================================================================
--- stable/12/stand/efi/include/efilib.h Mon Oct 14 19:06:17 2019 (r353500)
+++ stable/12/stand/efi/include/efilib.h Mon Oct 14 19:17:00 2019 (r353501)
@@ -69,6 +69,7 @@ pdinfo_t *efiblk_get_pdinfo_by_handle(EFI_HANDLE h);
pdinfo_t *efiblk_get_pdinfo_by_device_path(EFI_DEVICE_PATH *path);
void *efi_get_table(EFI_GUID *tbl);
+EFI_STATUS OpenProtocolByHandle(EFI_HANDLE, EFI_GUID *, void **);
int efi_getdev(void **vdev, const char *devspec, const char **path);
char *efi_fmtdev(void *vdev);
@@ -92,6 +93,7 @@ CHAR16 *efi_devpath_name(EFI_DEVICE_PATH *);
void efi_free_devpath_name(CHAR16 *);
EFI_DEVICE_PATH *efi_devpath_to_media_path(EFI_DEVICE_PATH *);
UINTN efi_devpath_length(EFI_DEVICE_PATH *);
+EFI_HANDLE efi_devpath_to_handle(EFI_DEVICE_PATH *path, EFI_HANDLE *handles, unsigned nhandles);
int efi_status_to_errno(EFI_STATUS);
EFI_STATUS errno_to_efi_status(int errno);
Modified: stable/12/stand/efi/libefi/devpath.c
==============================================================================
--- stable/12/stand/efi/libefi/devpath.c Mon Oct 14 19:06:17 2019 (r353500)
+++ stable/12/stand/efi/libefi/devpath.c Mon Oct 14 19:17:00 2019 (r353501)
@@ -42,8 +42,8 @@ efi_lookup_image_devpath(EFI_HANDLE handle)
EFI_DEVICE_PATH *devpath;
EFI_STATUS status;
- status = BS->HandleProtocol(handle, &ImageDevicePathGUID,
- (VOID **)&devpath);
+ status = OpenProtocolByHandle(handle, &ImageDevicePathGUID,
+ (void **)&devpath);
if (EFI_ERROR(status))
devpath = NULL;
return (devpath);
@@ -55,7 +55,8 @@ efi_lookup_devpath(EFI_HANDLE handle)
EFI_DEVICE_PATH *devpath;
EFI_STATUS status;
- status = BS->HandleProtocol(handle, &DevicePathGUID, (VOID **)&devpath);
+ status = OpenProtocolByHandle(handle, &DevicePathGUID,
+ (void **)&devpath);
if (EFI_ERROR(status))
devpath = NULL;
return (devpath);
@@ -228,4 +229,26 @@ efi_devpath_length(EFI_DEVICE_PATH *path)
while (!IsDevicePathEnd(path))
path = NextDevicePathNode(path);
return ((UINTN)path - (UINTN)start) + DevicePathNodeLength(path);
+}
+
+EFI_HANDLE
+efi_devpath_to_handle(EFI_DEVICE_PATH *path, EFI_HANDLE *handles, unsigned nhandles)
+{
+ unsigned i;
+ EFI_DEVICE_PATH *media, *devpath;
+ EFI_HANDLE h;
+
+ media = efi_devpath_to_media_path(path);
+ if (media == NULL)
+ return (NULL);
+ for (i = 0; i < nhandles; i++) {
+ h = handles[i];
+ devpath = efi_lookup_devpath(h);
+ if (devpath == NULL)
+ continue;
+ if (!efi_devpath_match_node(media, efi_devpath_to_media_path(devpath)))
+ continue;
+ return (h);
+ }
+ return (NULL);
}
Modified: stable/12/stand/efi/libefi/efinet.c
==============================================================================
--- stable/12/stand/efi/libefi/efinet.c Mon Oct 14 19:06:17 2019 (r353500)
+++ stable/12/stand/efi/libefi/efinet.c Mon Oct 14 19:17:00 2019 (r353501)
@@ -195,7 +195,7 @@ efinet_init(struct iodesc *desc, void *machdep_hint)
}
h = nif->nif_driver->netif_ifs[nif->nif_unit].dif_private;
- status = BS->HandleProtocol(h, &sn_guid, (VOID **)&nif->nif_devdata);
+ status = OpenProtocolByHandle(h, &sn_guid, (void **)&nif->nif_devdata);
if (status != EFI_SUCCESS) {
printf("net%d: cannot fetch interface data (status=%lu)\n",
nif->nif_unit, EFI_ERROR_CODE(status));
Modified: stable/12/stand/efi/libefi/efipart.c
==============================================================================
--- stable/12/stand/efi/libefi/efipart.c Mon Oct 14 19:06:17 2019 (r353500)
+++ stable/12/stand/efi/libefi/efipart.c Mon Oct 14 19:17:00 2019 (r353501)
@@ -64,6 +64,9 @@ static int efipart_printhd(int);
#define PNP0700 0x700
#define PNP0701 0x701
+/* Bounce buffer max size */
+#define BIO_BUFFER_SIZE 0x4000
+
struct devsw efipart_fddev = {
.dv_name = "fd",
.dv_type = DEVT_FD,
@@ -100,12 +103,18 @@ struct devsw efipart_hddev = {
.dv_cleanup = NULL
};
-static pdinfo_list_t fdinfo;
-static pdinfo_list_t cdinfo;
-static pdinfo_list_t hdinfo;
+static pdinfo_list_t fdinfo = STAILQ_HEAD_INITIALIZER(fdinfo);
+static pdinfo_list_t cdinfo = STAILQ_HEAD_INITIALIZER(cdinfo);
+static pdinfo_list_t hdinfo = STAILQ_HEAD_INITIALIZER(hdinfo);
-static EFI_HANDLE *efipart_handles = NULL;
-static UINTN efipart_nhandles = 0;
+/*
+ * efipart_inithandles() is used to build up the pdinfo list from
+ * block device handles. Then each devsw init callback is used to
+ * pick items from pdinfo and move to proper device list.
+ * In ideal world, we should end up with empty pdinfo once all
+ * devsw initializers are called.
+ */
+static pdinfo_list_t pdinfo = STAILQ_HEAD_INITIALIZER(pdinfo);
pdinfo_list_t *
efiblk_get_pdinfo_list(struct devsw *dev)
@@ -140,23 +149,14 @@ efiblk_get_pdinfo(struct devdesc *dev)
pdinfo_t *
efiblk_get_pdinfo_by_device_path(EFI_DEVICE_PATH *path)
{
- unsigned i;
- EFI_DEVICE_PATH *media, *devpath;
EFI_HANDLE h;
+ EFI_STATUS status;
+ EFI_DEVICE_PATH *devp = path;
- media = efi_devpath_to_media_path(path);
- if (media == NULL)
+ status = BS->LocateDevicePath(&blkio_guid, &devp, &h);
+ if (EFI_ERROR(status))
return (NULL);
- for (i = 0; i < efipart_nhandles; i++) {
- h = efipart_handles[i];
- devpath = efi_lookup_devpath(h);
- if (devpath == NULL)
- continue;
- if (!efi_devpath_match_node(media, efi_devpath_to_media_path(devpath)))
- continue;
- return (efiblk_get_pdinfo_by_handle(h));
- }
- return (NULL);
+ return (efiblk_get_pdinfo_by_handle(h));
}
static bool
@@ -185,6 +185,10 @@ efiblk_get_pdinfo_by_handle(EFI_HANDLE h)
STAILQ_FOREACH(dp, &cdinfo, pd_link) {
if (same_handle(dp, h))
return (dp);
+ STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
+ if (same_handle(pp, h))
+ return (pp);
+ }
}
STAILQ_FOREACH(dp, &fdinfo, pd_link) {
if (same_handle(dp, h))
@@ -208,15 +212,16 @@ efiblk_pdinfo_count(pdinfo_list_t *pdi)
int
efipart_inithandles(void)
{
+ unsigned i, nin;
UINTN sz;
EFI_HANDLE *hin;
+ EFI_DEVICE_PATH *devpath;
+ EFI_BLOCK_IO *blkio;
EFI_STATUS status;
+ pdinfo_t *pd;
- if (efipart_nhandles != 0) {
- free(efipart_handles);
- efipart_handles = NULL;
- efipart_nhandles = 0;
- }
+ if (!STAILQ_EMPTY(&pdinfo))
+ return (0);
sz = 0;
hin = NULL;
@@ -231,12 +236,60 @@ efipart_inithandles(void)
if (EFI_ERROR(status))
return (efi_status_to_errno(status));
- efipart_handles = hin;
- efipart_nhandles = sz / sizeof(*hin);
+ nin = sz / sizeof(*hin);
#ifdef EFIPART_DEBUG
- printf("%s: Got %d BLOCK IO MEDIA handle(s)\n", __func__,
- efipart_nhandles);
+ printf("%s: Got %d BLOCK IO MEDIA handle(s)\n", __func__, nin);
#endif
+
+ for (i = 0; i < nin; i++) {
+ /*
+ * Get devpath and open protocol.
+ * We should not get errors here
+ */
+ if ((devpath = efi_lookup_devpath(hin[i])) == NULL)
+ continue;
+
+ status = OpenProtocolByHandle(hin[i], &blkio_guid,
+ (void **)&blkio);
+ if (EFI_ERROR(status)) {
+ printf("error %lu\n", EFI_ERROR_CODE(status));
+ continue;
+ }
+
+ /*
+ * We assume the block size 512 or greater power of 2.
+ * Also skip devices with block size > 64k (16 is max
+ * ashift supported by zfs).
+ * iPXE is known to insert stub BLOCK IO device with
+ * BlockSize 1.
+ */
+ if (blkio->Media->BlockSize < 512 ||
+ blkio->Media->BlockSize > (1 << 16) ||
+ !powerof2(blkio->Media->BlockSize)) {
+ continue;
+ }
+
+ /* Allowed values are 0, 1 and power of 2. */
+ if (blkio->Media->IoAlign > 1 &&
+ !powerof2(blkio->Media->IoAlign)) {
+ continue;
+ }
+
+ /* This is bad. */
+ if ((pd = calloc(1, sizeof(*pd))) == NULL) {
+ printf("efipart_inithandles: Out of memory.\n");
+ free(hin);
+ return (ENOMEM);
+ }
+ STAILQ_INIT(&pd->pd_part);
+
+ pd->pd_handle = hin[i];
+ pd->pd_devpath = devpath;
+ pd->pd_blkio = blkio;
+ STAILQ_INSERT_TAIL(&pdinfo, pd, pd_link);
+ }
+
+ free(hin);
return (0);
}
@@ -257,134 +310,49 @@ efipart_floppy(EFI_DEVICE_PATH *node)
return (NULL);
}
-/*
- * 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)
+static pdinfo_t *
+efipart_find_parent(pdinfo_list_t *pdi, EFI_DEVICE_PATH *devpath)
{
- unsigned i;
- EFI_DEVICE_PATH *devpath, *node;
- EFI_BLOCK_IO *blkio;
- EFI_STATUS status;
+ pdinfo_t *pd;
- 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.
- */
- for (i = 0; i < efipart_nhandles; 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);
- }
-
- /*
- * We assume the block size 512 or greater power of 2.
- * iPXE is known to insert stub BLOCK IO device with
- * BlockSize 1.
- */
- if (blkio->Media->BlockSize < 512 ||
- !powerof2(blkio->Media->BlockSize)) {
- return (false);
- }
+ STAILQ_FOREACH(pd, pdi, pd_link) {
+ if (efi_devpath_is_prefix(pd->pd_devpath, devpath))
+ return (pd);
}
- return (true);
+ return (NULL);
}
-/*
- * Add or update entries with new handle data.
- */
static int
-efipart_fdinfo_add(EFI_HANDLE handle, uint32_t uid, EFI_DEVICE_PATH *devpath)
+efipart_initfd(void)
{
- pdinfo_t *fd;
-
- fd = calloc(1, sizeof(pdinfo_t));
- if (fd == NULL) {
- printf("Failed to register floppy %d, out of memory\n", uid);
- return (ENOMEM);
- }
- STAILQ_INIT(&fd->pd_part);
-
- fd->pd_unit = uid;
- fd->pd_handle = handle;
- fd->pd_devpath = devpath;
- fd->pd_parent = NULL;
- fd->pd_devsw = &efipart_fddev;
- STAILQ_INSERT_TAIL(&fdinfo, fd, pd_link);
- return (0);
-}
-
-static void
-efipart_updatefd(void)
-{
- EFI_DEVICE_PATH *devpath, *node;
+ EFI_DEVICE_PATH *node;
ACPI_HID_DEVICE_PATH *acpi;
- int i;
+ pdinfo_t *parent, *fd;
- for (i = 0; i < efipart_nhandles; i++) {
- devpath = efi_lookup_devpath(efipart_handles[i]);
- if (devpath == NULL)
+restart:
+ STAILQ_FOREACH(fd, &pdinfo, pd_link) {
+ if ((node = efi_devpath_last_node(fd->pd_devpath)) == NULL)
continue;
- if ((node = efi_devpath_last_node(devpath)) == NULL)
+ if ((acpi = efipart_floppy(node)) == NULL)
continue;
- if ((acpi = efipart_floppy(node)) != NULL) {
- efipart_fdinfo_add(efipart_handles[i], acpi->UID,
- devpath);
+
+ STAILQ_REMOVE(&pdinfo, fd, pdinfo, pd_link);
+ parent = efipart_find_parent(&pdinfo, fd->pd_devpath);
+ if (parent != NULL) {
+ STAILQ_REMOVE(&pdinfo, parent, pdinfo, pd_link);
+ parent->pd_alias = fd->pd_handle;
+ parent->pd_unit = acpi->UID;
+ free(fd);
+ fd = parent;
+ } else {
+ fd->pd_unit = acpi->UID;
}
+ fd->pd_devsw = &efipart_fddev;
+ STAILQ_INSERT_TAIL(&fdinfo, fd, pd_link);
+ goto restart;
}
-}
-static int
-efipart_initfd(void)
-{
-
- STAILQ_INIT(&fdinfo);
-
- efipart_updatefd();
-
bcache_add_dev(efiblk_pdinfo_count(&fdinfo));
return (0);
}
@@ -392,68 +360,90 @@ efipart_initfd(void)
/*
* Add or update entries with new handle data.
*/
-static int
-efipart_cdinfo_add(EFI_HANDLE handle, EFI_HANDLE alias,
- EFI_DEVICE_PATH *devpath)
+static void
+efipart_cdinfo_add(pdinfo_t *cd)
{
- int unit;
- pdinfo_t *cd;
- pdinfo_t *pd;
+ pdinfo_t *pd, *last;
- unit = 0;
STAILQ_FOREACH(pd, &cdinfo, pd_link) {
- if (efi_devpath_match(pd->pd_devpath, devpath) == true) {
- pd->pd_handle = handle;
- pd->pd_alias = alias;
- return (0);
+ if (efi_devpath_is_prefix(pd->pd_devpath, cd->pd_devpath)) {
+ last = STAILQ_LAST(&pd->pd_part, pdinfo, pd_link);
+ if (last != NULL)
+ cd->pd_unit = last->pd_unit + 1;
+ else
+ cd->pd_unit = 0;
+ cd->pd_parent = pd;
+ cd->pd_devsw = &efipart_cddev;
+ STAILQ_INSERT_TAIL(&pd->pd_part, cd, pd_link);
+ return;
}
- unit++;
}
- cd = calloc(1, sizeof(pdinfo_t));
- if (cd == NULL) {
- printf("Failed to add cd %d, out of memory\n", unit);
- return (ENOMEM);
- }
- STAILQ_INIT(&cd->pd_part);
+ last = STAILQ_LAST(&cdinfo, pdinfo, pd_link);
+ if (last != NULL)
+ cd->pd_unit = last->pd_unit + 1;
+ else
+ cd->pd_unit = 0;
- cd->pd_handle = handle;
- cd->pd_unit = unit;
- cd->pd_alias = alias;
- cd->pd_devpath = devpath;
cd->pd_parent = NULL;
cd->pd_devsw = &efipart_cddev;
STAILQ_INSERT_TAIL(&cdinfo, cd, pd_link);
- return (0);
}
+static bool
+efipart_testcd(EFI_DEVICE_PATH *node, EFI_BLOCK_IO *blkio)
+{
+ if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(node) == MEDIA_CDROM_DP) {
+ return (true);
+ }
+
+ /* cd drive without the media. */
+ if (blkio->Media->RemovableMedia &&
+ !blkio->Media->MediaPresent) {
+ return (true);
+ }
+
+ return (false);
+}
+
static void
efipart_updatecd(void)
{
- int i;
- EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
- EFI_HANDLE handle;
- EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath, *node;
EFI_STATUS status;
+ pdinfo_t *parent, *cd;
- for (i = 0; i < efipart_nhandles; i++) {
- devpath = efi_lookup_devpath(efipart_handles[i]);
- if (devpath == NULL)
+restart:
+ STAILQ_FOREACH(cd, &pdinfo, pd_link) {
+ if ((node = efi_devpath_last_node(cd->pd_devpath)) == NULL)
continue;
- if ((node = efi_devpath_last_node(devpath)) == NULL)
- continue;
-
if (efipart_floppy(node) != NULL)
continue;
- if (efipart_hdd(devpath))
- continue;
+ /* Is parent of this device already registered? */
+ parent = efipart_find_parent(&cdinfo, cd->pd_devpath);
+ if (parent != NULL) {
+ STAILQ_REMOVE(&pdinfo, cd, pdinfo, pd_link);
+ efipart_cdinfo_add(cd);
+ goto restart;
+ }
- status = BS->HandleProtocol(efipart_handles[i],
- &blkio_guid, (void **)&blkio);
- if (EFI_ERROR(status))
+ if (!efipart_testcd(node, cd->pd_blkio))
continue;
+
+ /* Find parent and unlink both parent and cd from pdinfo */
+ STAILQ_REMOVE(&pdinfo, cd, pdinfo, pd_link);
+ parent = efipart_find_parent(&pdinfo, cd->pd_devpath);
+ if (parent != NULL) {
+ STAILQ_REMOVE(&pdinfo, parent, pdinfo, pd_link);
+ efipart_cdinfo_add(parent);
+ }
+
+ if (parent == NULL)
+ parent = efipart_find_parent(&cdinfo, cd->pd_devpath);
+
/*
* If we come across a logical partition of subtype CDROM
* it doesn't refer to the CD filesystem itself, but rather
@@ -462,132 +452,79 @@ efipart_updatecd(void)
* that will be the CD filesystem.
*/
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
- DevicePathSubType(node) == MEDIA_CDROM_DP) {
- devpathcpy = efi_devpath_trim(devpath);
- if (devpathcpy == NULL)
- continue;
- tmpdevpath = devpathcpy;
- status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
- &handle);
- free(devpathcpy);
- if (EFI_ERROR(status))
- continue;
- devpath = efi_lookup_devpath(handle);
- efipart_cdinfo_add(handle, efipart_handles[i],
- devpath);
- continue;
- }
+ DevicePathSubType(node) == MEDIA_CDROM_DP &&
+ parent == NULL) {
+ parent = calloc(1, sizeof(*parent));
+ if (parent == NULL) {
+ printf("efipart_updatecd: out of memory\n");
+ /* this device is lost but try again. */
+ free(cd);
+ goto restart;
+ }
- if (DevicePathType(node) == MESSAGING_DEVICE_PATH &&
- DevicePathSubType(node) == MSG_ATAPI_DP) {
- efipart_cdinfo_add(efipart_handles[i], NULL,
- devpath);
- continue;
+ devpath = efi_devpath_trim(cd->pd_devpath);
+ if (devpath == NULL) {
+ printf("efipart_updatecd: out of memory\n");
+ /* this device is lost but try again. */
+ free(parent);
+ free(cd);
+ goto restart;
+ }
+ parent->pd_devpath = devpath;
+ status = BS->LocateDevicePath(&blkio_guid,
+ &parent->pd_devpath, &parent->pd_handle);
+ free(devpath);
+ if (EFI_ERROR(status)) {
+ printf("efipart_updatecd: error %lu\n",
+ EFI_ERROR_CODE(status));
+ free(parent);
+ free(cd);
+ goto restart;
+ }
+ parent->pd_devpath =
+ efi_lookup_devpath(parent->pd_handle);
+ efipart_cdinfo_add(parent);
}
- /* USB or SATA cd without the media. */
- if (blkio->Media->RemovableMedia &&
- !blkio->Media->MediaPresent) {
- efipart_cdinfo_add(efipart_handles[i], NULL,
- devpath);
- }
+ efipart_cdinfo_add(cd);
+ goto restart;
}
}
static int
efipart_initcd(void)
{
-
- STAILQ_INIT(&cdinfo);
-
efipart_updatecd();
bcache_add_dev(efiblk_pdinfo_count(&cdinfo));
return (0);
}
-static int
-efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle)
+static void
+efipart_hdinfo_add(pdinfo_t *hd, HARDDRIVE_DEVICE_PATH *node)
{
- EFI_DEVICE_PATH *disk_devpath, *part_devpath;
- HARDDRIVE_DEVICE_PATH *node;
- int unit;
- pdinfo_t *hd, *pd, *last;
+ pdinfo_t *pd, *last;
- disk_devpath = efi_lookup_devpath(disk_handle);
- 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;
- }
-
- pd = calloc(1, sizeof(pdinfo_t));
- if (pd == NULL) {
- printf("Failed to add disk, out of memory\n");
- return (ENOMEM);
- }
- STAILQ_INIT(&pd->pd_part);
-
- STAILQ_FOREACH(hd, &hdinfo, pd_link) {
- if (efi_devpath_match(hd->pd_devpath, disk_devpath) == true) {
- if (part_devpath == NULL)
- return (0);
-
+ STAILQ_FOREACH(pd, &hdinfo, pd_link) {
+ if (efi_devpath_is_prefix(pd->pd_devpath, hd->pd_devpath)) {
/* Add the partition. */
- pd->pd_handle = part_handle;
- pd->pd_unit = node->PartitionNumber;
- pd->pd_devpath = part_devpath;
- pd->pd_parent = hd;
- pd->pd_devsw = &efipart_hddev;
- STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
- return (0);
+ hd->pd_unit = node->PartitionNumber;
+ hd->pd_parent = pd;
+ hd->pd_devsw = &efipart_hddev;
+ STAILQ_INSERT_TAIL(&pd->pd_part, hd, pd_link);
+ return;
}
}
last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
if (last != NULL)
- unit = last->pd_unit + 1;
+ hd->pd_unit = last->pd_unit + 1;
else
- unit = 0;
+ hd->pd_unit = 0;
/* Add the disk. */
- hd = pd;
- hd->pd_handle = disk_handle;
- hd->pd_unit = unit;
- hd->pd_devpath = disk_devpath;
- hd->pd_parent = NULL;
hd->pd_devsw = &efipart_hddev;
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");
- return (ENOMEM);
- }
- STAILQ_INIT(&pd->pd_part);
-
- /* Add the partition. */
- pd->pd_handle = part_handle;
- pd->pd_unit = node->PartitionNumber;
- pd->pd_devpath = part_devpath;
- pd->pd_parent = hd;
- pd->pd_devsw = &efipart_hddev;
- STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
-
- return (0);
}
/*
@@ -596,40 +533,25 @@ efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE
* 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)
+static void
+efipart_hdinfo_add_filepath(pdinfo_t *hd, FILEPATH_DEVICE_PATH *node)
{
- EFI_DEVICE_PATH *devpath;
- FILEPATH_DEVICE_PATH *node;
char *pathname, *p;
- int unit, len;
- pdinfo_t *pd, *last;
+ int len;
+ pdinfo_t *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 = calloc(1, sizeof(pdinfo_t));
- if (pd == NULL) {
- printf("Failed to add disk, out of memory\n");
- return (ENOMEM);
- }
- STAILQ_INIT(&pd->pd_part);
last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
if (last != NULL)
- unit = last->pd_unit + 1;
+ hd->pd_unit = last->pd_unit + 1;
else
- unit = 0;
+ hd->pd_unit = 0;
/* FILEPATH_DEVICE_PATH has 0 terminated string */
len = ucs2len(node->PathName);
if ((pathname = malloc(len + 1)) == NULL) {
printf("Failed to add disk, out of memory\n");
- free(pd);
- return (ENOMEM);
+ free(hd);
+ return;
}
cpy16to8(node->PathName, pathname, len + 1);
p = strchr(pathname, ':');
@@ -640,23 +562,19 @@ efipart_hdinfo_add_filepath(EFI_HANDLE disk_handle)
* 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;
- pd->pd_parent = NULL;
- pd->pd_devsw = &efipart_hddev;
- STAILQ_INSERT_TAIL(&hdinfo, pd, pd_link);
+ hd->pd_devsw = &efipart_hddev;
+ STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link);
free(pathname);
- return (0);
+ return;
}
p++; /* skip the colon */
errno = 0;
- unit = (int)strtol(p, NULL, 0);
+ hd->pd_unit = (int)strtol(p, NULL, 0);
if (errno != 0) {
printf("Bad unit number for partition \"%s\"\n", pathname);
free(pathname);
- free(pd);
- return (EUNIT);
+ free(hd);
+ return;
}
/*
@@ -668,80 +586,99 @@ efipart_hdinfo_add_filepath(EFI_HANDLE disk_handle)
if (last == NULL) {
printf("BUG: No disk for partition \"%s\"\n", pathname);
free(pathname);
- free(pd);
- return (EINVAL);
+ free(hd);
+ return;
}
/* Add the partition. */
- pd->pd_handle = disk_handle;
- pd->pd_unit = unit;
- pd->pd_devpath = devpath;
- pd->pd_parent = last;
- pd->pd_devsw = &efipart_hddev;
- STAILQ_INSERT_TAIL(&last->pd_part, pd, pd_link);
+ hd->pd_parent = last;
+ hd->pd_devsw = &efipart_hddev;
+ STAILQ_INSERT_TAIL(&last->pd_part, hd, pd_link);
free(pathname);
- return (0);
}
static void
efipart_updatehd(void)
{
- int i;
- EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
- EFI_HANDLE handle;
- EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath, *node;
EFI_STATUS status;
+ pdinfo_t *parent, *hd;
- for (i = 0; i < efipart_nhandles; i++) {
- devpath = efi_lookup_devpath(efipart_handles[i]);
- if (devpath == NULL)
+restart:
+ STAILQ_FOREACH(hd, &pdinfo, pd_link) {
+ if ((node = efi_devpath_last_node(hd->pd_devpath)) == NULL)
continue;
- if ((node = efi_devpath_last_node(devpath)) == NULL)
+ if (efipart_floppy(node) != NULL)
continue;
- if (!efipart_hdd(devpath))
+ if (efipart_testcd(node, hd->pd_blkio))
continue;
- status = BS->HandleProtocol(efipart_handles[i],
- &blkio_guid, (void **)&blkio);
- if (EFI_ERROR(status))
- continue;
+ if (DevicePathType(node) == HARDWARE_DEVICE_PATH &&
+ (DevicePathSubType(node) == HW_PCI_DP ||
+ DevicePathSubType(node) == HW_VENDOR_DP)) {
+ STAILQ_REMOVE(&pdinfo, hd, pdinfo, pd_link);
+ efipart_hdinfo_add(hd, NULL);
+ goto restart;
+ }
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
DevicePathSubType(node) == MEDIA_FILEPATH_DP) {
- efipart_hdinfo_add_filepath(efipart_handles[i]);
- continue;
+ STAILQ_REMOVE(&pdinfo, hd, pdinfo, pd_link);
+ efipart_hdinfo_add_filepath(hd,
+ (FILEPATH_DEVICE_PATH *)node);
+ goto restart;
}
+ STAILQ_REMOVE(&pdinfo, hd, pdinfo, pd_link);
+ parent = efipart_find_parent(&pdinfo, hd->pd_devpath);
+ if (parent != NULL) {
+ STAILQ_REMOVE(&pdinfo, parent, pdinfo, pd_link);
+ efipart_hdinfo_add(parent, NULL);
+ } else {
+ parent = efipart_find_parent(&hdinfo, hd->pd_devpath);
+ }
+
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
- DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) {
- devpathcpy = efi_devpath_trim(devpath);
- if (devpathcpy == NULL)
- continue;
- tmpdevpath = devpathcpy;
- status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath,
- &handle);
- free(devpathcpy);
- if (EFI_ERROR(status))
- continue;
- /*
- * We do not support nested partitions.
- */
- devpathcpy = efi_lookup_devpath(handle);
- if (devpathcpy == NULL)
- continue;
- if ((node = efi_devpath_last_node(devpathcpy)) == NULL)
- continue;
+ DevicePathSubType(node) == MEDIA_HARDDRIVE_DP &&
+ parent == NULL) {
+ parent = calloc(1, sizeof(*parent));
+ if (parent == NULL) {
+ printf("efipart_updatehd: out of memory\n");
+ /* this device is lost but try again. */
+ free(hd);
+ goto restart;
+ }
- if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
- DevicePathSubType(node) == MEDIA_HARDDRIVE_DP)
- continue;
+ devpath = efi_devpath_trim(hd->pd_devpath);
+ if (devpath == NULL) {
+ printf("efipart_updatehd: out of memory\n");
+ /* this device is lost but try again. */
+ free(parent);
+ free(hd);
+ goto restart;
+ }
- efipart_hdinfo_add(handle, efipart_handles[i]);
- continue;
+ parent->pd_devpath = devpath;
+ status = BS->LocateDevicePath(&blkio_guid,
+ &parent->pd_devpath, &parent->pd_handle);
+ free(devpath);
+ if (EFI_ERROR(status)) {
+ printf("efipart_updatehd: error %lu\n",
+ EFI_ERROR_CODE(status));
+ free(parent);
+ free(hd);
+ goto restart;
+ }
+
+ parent->pd_devpath =
+ efi_lookup_devpath(&parent->pd_handle);
+
+ efipart_hdinfo_add(parent, NULL);
}
- efipart_hdinfo_add(efipart_handles[i], NULL);
+ efipart_hdinfo_add(hd, (HARDDRIVE_DEVICE_PATH *)node);
+ goto restart;
}
}
@@ -749,8 +686,6 @@ static int
efipart_inithd(void)
{
- STAILQ_INIT(&hdinfo);
-
efipart_updatehd();
bcache_add_dev(efiblk_pdinfo_count(&hdinfo));
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list