Page MenuHomeFreeBSD

D12732.diff
No OneTemporary

D12732.diff

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

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)

Event Timeline