Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106138411
D12732.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D12732.diff
View Options
Index: stand/efi/include/efilib.h
===================================================================
--- stand/efi/include/efilib.h
+++ stand/efi/include/efilib.h
@@ -30,6 +30,9 @@
#ifndef _LOADER_EFILIB_H
#define _LOADER_EFILIB_H
+#define FREEBSD_GELI_GUID { 0x516e7cbc, 0x6ecf, 0x11d6, \
+ {0x8f, 0xf8, 0x00, 0x02, 0x2d, 0x09, 0x71, 0x2b } }
+
#include <stand.h>
#include <stdbool.h>
#include <sys/queue.h>
@@ -52,6 +55,7 @@
{
STAILQ_ENTRY(pdinfo) pd_link; /* link in device list */
pdinfo_list_t pd_part; /* list of partitions */
+ EFI_HANDLE pd_basehandle;
EFI_HANDLE pd_handle;
EFI_HANDLE pd_alias;
EFI_DEVICE_PATH *pd_devpath;
Index: stand/efi/libefi/efipart.c
===================================================================
--- stand/efi/libefi/efipart.c
+++ stand/efi/libefi/efipart.c
@@ -43,6 +43,7 @@
#include <disk.h>
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
+static EFI_GUID FreeBSDGELIGUID = FREEBSD_GELI_GUID;
static int efipart_initfd(void);
static int efipart_initcd(void);
@@ -299,7 +300,7 @@
}
/*
- * We assume the block size 512 or greater power of 2.
+ * We assume the block size 512 or greater power of 2.
* iPXE is known to insert stub BLOCK IO device with
* BlockSize 1.
*/
@@ -490,13 +491,16 @@
static int
efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle)
{
- EFI_DEVICE_PATH *disk_devpath, *part_devpath;
+ EFI_DEVICE_PATH *disk_devpath, *part_devpath, *trimpath, *lastnode;
+ VENDOR_DEVICE_PATH *vendornode;
HARDDRIVE_DEVICE_PATH *node;
int unit;
- pdinfo_t *hd, *pd, *last;
+ pdinfo_t *hd, *pd, *pp, *last;
disk_devpath = efi_lookup_devpath(disk_handle);
- if (disk_devpath == NULL)
+ part_devpath = efi_lookup_devpath(part_handle);
+
+ if (disk_devpath == NULL || part_devpath == NULL)
return (ENOENT);
if (part_handle != NULL) {
@@ -512,7 +516,45 @@
node = NULL;
}
+ /* Get the disk partition node */
+ lastnode = efi_devpath_last_node(part_devpath);
+ if (lastnode == NULL)
+ return (ENOENT); /* This should not happen. */
+
+
+ if (DevicePathType(lastnode) == MEDIA_DEVICE_PATH) {
+ if (DevicePathSubType(lastnode) == MEDIA_VENDOR_DP) {
+ vendornode = (VENDOR_DEVICE_PATH *)lastnode;
+
+ /* We only want GELI partitions */
+ if (memcmp(&(vendornode->Guid), &FreeBSDGELIGUID,
+ sizeof(EFI_GUID))) {
+ return (EINVAL);
+ }
+
+ /* Trim off the vendor node */
+ trimpath = efi_devpath_trim(part_devpath);
+
+ if (trimpath == NULL)
+ return (ENOENT);
+
+ lastnode = efi_devpath_last_node(trimpath);
+
+ if (lastnode == NULL)
+ return (ENOENT);
+
+ node = (HARDDRIVE_DEVICE_PATH *)lastnode;
+ } else if (DevicePathSubType(lastnode) == MEDIA_HARDDRIVE_DP) {
+ node = (HARDDRIVE_DEVICE_PATH *)lastnode;
+ }
+ else
+ return (EINVAL);
+ } else {
+ return (EINVAL);
+ }
+
pd = calloc(1, sizeof(pdinfo_t));
+
if (pd == NULL) {
printf("Failed to add disk, out of memory\n");
return (ENOMEM);
@@ -520,12 +562,56 @@
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);
-
- /* Add the partition. */
+ if (efi_devpath_match(hd->pd_devpath, disk_devpath) != 0) {
+ /* Check if there's a related device entry
+ * already here.
+ */
+ STAILQ_FOREACH(pp, &hd->pd_part, pd_link) {
+ /* If the new device is a subpath of
+ * an existing device, then the
+ * existing entry subsumes the new
+ * one.
+ */
+ trimpath = efi_devpath_trim(pp->pd_devpath);
+
+ if (trimpath == NULL)
+ return (ENOMEM);
+
+ if (efi_devpath_match(trimpath,
+ part_devpath) != 0) {
+ free(trimpath);
+ free(pd);
+ return (EBUSY);
+ }
+
+ /* If the existing device path is a
+ * subpath of the new one, then the
+ * new entry subsumes the existing
+ * one.
+ */
+ free(trimpath);
+
+ trimpath = efi_devpath_trim(part_devpath);
+
+ if (trimpath == NULL)
+ return (ENOMEM);
+
+ if (efi_devpath_match(trimpath,
+ pp->pd_devpath) != 0) {
+ pp->pd_handle = part_handle;
+ pp->pd_basehandle = disk_handle;
+ pp->pd_devpath = part_devpath;
+ free(trimpath);
+ free(pd);
+ return (0);
+ }
+ free(trimpath);
+
+ }
+
+ /* Add the partition. */
pd->pd_handle = part_handle;
+ pd->pd_basehandle = disk_handle;
pd->pd_unit = node->PartitionNumber;
pd->pd_devpath = part_devpath;
pd->pd_parent = hd;
@@ -544,6 +630,7 @@
/* Add the disk. */
hd = pd;
hd->pd_handle = disk_handle;
+ hd->pd_basehandle = disk_handle;
hd->pd_unit = unit;
hd->pd_devpath = disk_devpath;
hd->pd_parent = NULL;
@@ -562,6 +649,7 @@
/* Add the partition. */
pd->pd_handle = part_handle;
+ pd->pd_basehandle = disk_handle;
pd->pd_unit = node->PartitionNumber;
pd->pd_devpath = part_devpath;
pd->pd_parent = hd;
@@ -622,6 +710,7 @@
*/
if (p == NULL) { /* no colon, add the disk */
pd->pd_handle = disk_handle;
+ pd->pd_basehandle = disk_handle;
pd->pd_unit = unit;
pd->pd_devpath = devpath;
pd->pd_parent = NULL;
@@ -653,7 +742,8 @@
return (EINVAL);
}
/* Add the partition. */
- pd->pd_handle = disk_handle;
+ pd->pd_handle = disk_handle;
+ pd->pd_basehandle = disk_handle;
pd->pd_unit = unit;
pd->pd_devpath = devpath;
pd->pd_parent = last;
@@ -677,7 +767,6 @@
devpath = efi_lookup_devpath(efipart_handles[i]);
if (devpath == NULL)
continue;
-
if ((node = efi_devpath_last_node(devpath)) == NULL)
continue;
@@ -689,6 +778,29 @@
if (EFI_ERROR(status))
continue;
+ /* Handle GELI volumes */
+ if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(node) == MEDIA_VENDOR_DP) {
+ VENDOR_DEVICE_PATH *vendornode;
+
+ vendornode = (VENDOR_DEVICE_PATH *)node;
+
+ /* We only want GELI partitions */
+ if (memcmp(&(vendornode->Guid), &FreeBSDGELIGUID,
+ sizeof(EFI_GUID))) {
+ continue;
+ }
+
+ /* Trim off the vendor node */
+ devpathcpy = efi_devpath_trim(devpath);
+ if (devpathcpy == NULL)
+ continue;
+ if ((node = efi_devpath_last_node(devpathcpy)) == NULL)
+ continue;
+
+ devpath = devpathcpy;
+ }
+
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
DevicePathSubType(node) == MEDIA_FILEPATH_DP) {
efipart_hdinfo_add_filepath(efipart_handles[i]);
@@ -700,16 +812,19 @@
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)
@@ -745,7 +860,8 @@
int ret = 0;
EFI_BLOCK_IO *blkio;
EFI_STATUS status;
- EFI_HANDLE h;
+ EFI_HANDLE handle;
+ EFI_HANDLE base_handle;
pdinfo_t *pd;
CHAR16 *text;
struct disk_devdesc pd_dev;
@@ -759,9 +875,10 @@
return (ret);
STAILQ_FOREACH(pd, pdlist, pd_link) {
- h = pd->pd_handle;
+ handle = pd->pd_handle;
+ base_handle = pd->pd_basehandle;
if (verbose) { /* Output the device path. */
- text = efi_devpath_name(efi_lookup_devpath(h));
+ text = efi_devpath_name(efi_lookup_devpath(base_handle));
if (text != NULL) {
printf(" %S", text);
efi_free_devpath_name(text);
@@ -772,7 +889,8 @@
snprintf(line, sizeof(line),
" %s%d", dev->dv_name, pd->pd_unit);
printf("%s:", line);
- status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
+ status = BS->HandleProtocol(base_handle, &blkio_guid,
+ (void **)&blkio);
if (!EFI_ERROR(status)) {
printf(" %llu",
blkio->Media->LastBlock == 0? 0:
@@ -797,19 +915,22 @@
pd_dev.dd.d_unit = pd->pd_unit;
pd_dev.d_slice = -1;
pd_dev.d_partition = -1;
- ret = disk_open(&pd_dev, blkio->Media->BlockSize *
- (blkio->Media->LastBlock + 1),
- blkio->Media->BlockSize);
- if (ret == 0) {
- ret = disk_print(&pd_dev, line, verbose);
- disk_close(&pd_dev);
- if (ret != 0)
- return (ret);
- } else {
- /* Do not fail from disk_open() */
- ret = 0;
- }
- } else {
+ pd_dev.dd.d_opendata = blkio;
+
+ ret = disk_open(&pd_dev, blkio->Media->BlockSize *
+ (blkio->Media->LastBlock + 1),
+ blkio->Media->BlockSize);
+ if (ret == 0) {
+ ret = disk_print(&pd_dev, line, verbose);
+ disk_close(&pd_dev);
+ if (ret != 0)
+ return (ret);
+ } else {
+ /* Do not fail from disk_open() */
+ printf("Open device failed %d\n", ret);
+ ret = 0;
+ }
+ } else {
if ((ret = pager_output("\n")) != 0)
break;
}
@@ -835,6 +956,53 @@
return (efipart_print_common(&efipart_hddev, &hdinfo, verbose));
}
+static int
+efipart_lookupdev(struct disk_devdesc *dev, pdinfo_t **pp)
+{
+ pdinfo_list_t *pdi;
+ pdinfo_t *pd = NULL, *curr;
+
+ if (dev == NULL) {
+ return (EINVAL);
+ }
+
+ pdi = efiblk_get_pdinfo_list(dev->dd.d_dev);
+ if (pdi == NULL) {
+ return (EINVAL);
+ }
+
+ STAILQ_FOREACH(curr, pdi, pd_link) {
+ if (curr->pd_unit == dev->dd.d_unit) {
+ pd = curr;
+ break;
+ }
+ }
+
+ if (pd == NULL)
+ return (ENOENT);
+
+ *pp = NULL;
+
+ /* If we're looking up a specific partition, get the
+ * IO interface from that devide handle.
+ */
+ if (dev->d_slice != -1) {
+ STAILQ_FOREACH(curr, &pd->pd_part, pd_link) {
+ if (curr->pd_unit == dev->d_slice) {
+ *pp = curr;
+ break;
+ }
+ }
+ } else {
+ *pp = pd;
+ }
+
+ if (*pp == NULL)
+ return (ENOENT);
+
+ return (0);
+}
+
static int
efipart_open(struct open_file *f, ...)
{
@@ -843,48 +1011,34 @@
pdinfo_t *pd;
EFI_BLOCK_IO *blkio;
EFI_STATUS status;
+ int err;
va_start(args, f);
dev = va_arg(args, struct disk_devdesc*);
va_end(args);
- if (dev == NULL)
- return (EINVAL);
- pd = efiblk_get_pdinfo((struct devdesc *)dev);
- if (pd == NULL)
- return (EIO);
+ if ((err = efipart_lookupdev(dev, &pd)) != 0) {
+ return (err);
+ }
if (pd->pd_blkio == NULL) {
- status = BS->HandleProtocol(pd->pd_handle, &blkio_guid,
- (void **)&pd->pd_blkio);
- if (EFI_ERROR(status))
- return (efi_status_to_errno(status));
+ status = BS->HandleProtocol(pd->pd_handle, &blkio_guid,
+ (void **)&pd->pd_blkio);
+ if (EFI_ERROR(status))
+ return (efi_status_to_errno(status));
}
blkio = pd->pd_blkio;
- if (!blkio->Media->MediaPresent)
+ if (!blkio->Media->MediaPresent) {
return (EAGAIN);
+ }
pd->pd_open++;
if (pd->pd_bcache == NULL)
pd->pd_bcache = bcache_allocate();
- if (dev->dd.d_dev->dv_type == DEVT_DISK) {
- int rc;
-
- rc = disk_open(dev,
- blkio->Media->BlockSize * (blkio->Media->LastBlock + 1),
- blkio->Media->BlockSize);
- if (rc != 0) {
- pd->pd_open--;
- if (pd->pd_open == 0) {
- pd->pd_blkio = NULL;
- bcache_free(pd->pd_bcache);
- pd->pd_bcache = NULL;
- }
- }
- return (rc);
- }
+ dev->d_offset = 0;
+
return (0);
}
@@ -893,14 +1047,13 @@
{
struct disk_devdesc *dev;
pdinfo_t *pd;
+ int err;
dev = (struct disk_devdesc *)(f->f_devdata);
- if (dev == NULL)
- return (EINVAL);
- pd = efiblk_get_pdinfo((struct devdesc *)dev);
- if (pd == NULL)
- return (EINVAL);
+ if ((err = efipart_lookupdev(dev, &pd)) != 0) {
+ return (err);
+ }
pd->pd_open--;
if (pd->pd_open == 0) {
@@ -908,8 +1061,7 @@
bcache_free(pd->pd_bcache);
pd->pd_bcache = NULL;
}
- if (dev->dd.d_dev->dv_type == DEVT_DISK)
- return (disk_close(dev));
+
return (0);
}
@@ -918,21 +1070,13 @@
{
struct disk_devdesc *dev;
pdinfo_t *pd;
- int rc;
+ int err;
dev = (struct disk_devdesc *)(f->f_devdata);
- if (dev == NULL)
- return (EINVAL);
-
- pd = efiblk_get_pdinfo((struct devdesc *)dev);
- if (pd == NULL)
- return (EINVAL);
- if (dev->dd.d_dev->dv_type == DEVT_DISK) {
- rc = disk_ioctl(dev, cmd, data);
- if (rc != ENOTTY)
- return (rc);
- }
+ if ((err = efipart_lookupdev(dev, &pd)) != 0) {
+ return (err);
+ }
switch (cmd) {
case DIOCGSECTORSIZE:
@@ -998,14 +1142,13 @@
struct bcache_devdata bcd;
struct disk_devdesc *dev;
pdinfo_t *pd;
+ int err;
dev = (struct disk_devdesc *)devdata;
- if (dev == NULL)
- return (EINVAL);
- pd = efiblk_get_pdinfo((struct devdesc *)dev);
- if (pd == NULL)
- return (EINVAL);
+ if ((err = efipart_lookupdev(dev, &pd)) != 0) {
+ return (err);
+ }
if (pd->pd_blkio->Media->RemovableMedia &&
!pd->pd_blkio->Media->MediaPresent)
@@ -1039,12 +1182,12 @@
int error;
size_t diskend, readstart;
- if (dev == NULL || blk < 0)
+ if (blk < 0)
return (EINVAL);
- pd = efiblk_get_pdinfo((struct devdesc *)dev);
- if (pd == NULL)
- return (EINVAL);
+ if ((error = efipart_lookupdev(dev, &pd)) != 0) {
+ return (error);
+ }
blkio = pd->pd_blkio;
if (blkio == NULL)
@@ -1054,20 +1197,7 @@
return (EIO);
off = blk * 512;
- /*
- * Get disk blocks, this value is either for whole disk or for
- * partition.
- */
- disk_blocks = 0;
- if (dev->dd.d_dev->dv_type == DEVT_DISK) {
- if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
- /* DIOCGMEDIASIZE does return bytes. */
- disk_blocks /= blkio->Media->BlockSize;
- }
- d_offset = dev->d_offset;
- }
- if (disk_blocks == 0)
- disk_blocks = blkio->Media->LastBlock + 1 - d_offset;
+ disk_blocks = blkio->Media->LastBlock + 1 - d_offset;
/* make sure we don't read past disk end */
if ((off + size) / blkio->Media->BlockSize > d_offset + disk_blocks) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Dec 27, 1:00 AM (11 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15609676
Default Alt Text
D12732.diff (16 KB)
Attached To
Mode
D12732: Revert efipart to use EFI_HANDLEs for partitions
Attached
Detach File
Event Timeline
Log In to Comment