svn commit: r313333 - in head: lib/libstand sys/boot/efi/include sys/boot/efi/libefi sys/boot/efi/loader sys/boot/zfs
Toomas Soome
tsoome at FreeBSD.org
Mon Feb 6 09:18:49 UTC 2017
Author: tsoome
Date: Mon Feb 6 09:18:47 2017
New Revision: 313333
URL: https://svnweb.freebsd.org/changeset/base/313333
Log:
loader: Replace EFI part devices.
Rewrite EFI part device interface to present disk devices in more
user friendly way.
We keep list of three types of devices: floppy, cd and disk, the
visible names: fdX: cdX: and diskX:
Use common/disk.c and common/part.c interfaces to manage the
partitioning.
The lsdev -l will additionally list the device path.
Reviewed by: imp, allanjude
Approved by: imp (mentor), allanjude (mentor)
Differential Revision: https://reviews.freebsd.org/D8581
Modified:
head/lib/libstand/stand.h
head/sys/boot/efi/include/efilib.h
head/sys/boot/efi/libefi/devpath.c
head/sys/boot/efi/libefi/efipart.c
head/sys/boot/efi/loader/conf.c
head/sys/boot/efi/loader/devicename.c
head/sys/boot/efi/loader/main.c
head/sys/boot/zfs/zfs.c
Modified: head/lib/libstand/stand.h
==============================================================================
--- head/lib/libstand/stand.h Mon Feb 6 08:58:40 2017 (r313332)
+++ head/lib/libstand/stand.h Mon Feb 6 09:18:47 2017 (r313333)
@@ -168,6 +168,7 @@ struct devdesc
#define DEVT_NET 2
#define DEVT_CD 3
#define DEVT_ZFS 4
+#define DEVT_FD 5
int d_unit;
void *d_opendata;
};
Modified: head/sys/boot/efi/include/efilib.h
==============================================================================
--- head/sys/boot/efi/include/efilib.h Mon Feb 6 08:58:40 2017 (r313332)
+++ head/sys/boot/efi/include/efilib.h Mon Feb 6 09:18:47 2017 (r313333)
@@ -31,16 +31,37 @@
#define _LOADER_EFILIB_H
#include <stand.h>
+#include <sys/queue.h>
extern EFI_HANDLE IH;
extern EFI_SYSTEM_TABLE *ST;
extern EFI_BOOT_SERVICES *BS;
extern EFI_RUNTIME_SERVICES *RS;
-extern struct devsw efipart_dev;
+extern struct devsw efipart_fddev;
+extern struct devsw efipart_cddev;
+extern struct devsw efipart_hddev;
extern struct devsw efinet_dev;
extern struct netif_driver efinetif;
+/* EFI block device data, included here to help efi_zfs_probe() */
+typedef STAILQ_HEAD(pdinfo_list, pdinfo) pdinfo_list_t;
+
+typedef struct pdinfo
+{
+ STAILQ_ENTRY(pdinfo) pd_link; /* link in device list */
+ pdinfo_list_t pd_part; /* link of partitions */
+ EFI_HANDLE pd_handle;
+ EFI_HANDLE pd_alias;
+ EFI_DEVICE_PATH *pd_devpath;
+ EFI_BLOCK_IO *pd_blkio;
+ int pd_unit; /* unit number */
+ int pd_open; /* reference counter */
+ void *pd_bcache; /* buffer cache data */
+} pdinfo_t;
+
+pdinfo_list_t *efiblk_get_pdinfo_list(struct devsw *dev);
+
void *efi_get_table(EFI_GUID *tbl);
int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
@@ -53,6 +74,7 @@ EFI_DEVICE_PATH *efi_lookup_devpath(EFI_
EFI_HANDLE efi_devpath_handle(EFI_DEVICE_PATH *);
EFI_DEVICE_PATH *efi_devpath_last_node(EFI_DEVICE_PATH *);
EFI_DEVICE_PATH *efi_devpath_trim(EFI_DEVICE_PATH *);
+int efi_devpath_match(EFI_DEVICE_PATH *, EFI_DEVICE_PATH *);
CHAR16 *efi_devpath_name(EFI_DEVICE_PATH *);
void efi_free_devpath_name(CHAR16 *);
Modified: head/sys/boot/efi/libefi/devpath.c
==============================================================================
--- head/sys/boot/efi/libefi/devpath.c Mon Feb 6 08:58:40 2017 (r313332)
+++ head/sys/boot/efi/libefi/devpath.c Mon Feb 6 09:18:47 2017 (r313333)
@@ -138,3 +138,31 @@ efi_devpath_handle(EFI_DEVICE_PATH *devp
return (NULL);
return (h);
}
+
+int
+efi_devpath_match(EFI_DEVICE_PATH *devpath1, EFI_DEVICE_PATH *devpath2)
+{
+ int len;
+
+ if (devpath1 == NULL || devpath2 == NULL)
+ return (0);
+
+ while (1) {
+ if (DevicePathType(devpath1) != DevicePathType(devpath2) ||
+ DevicePathSubType(devpath1) != DevicePathSubType(devpath2))
+ return (0);
+
+ len = DevicePathNodeLength(devpath1);
+ if (len != DevicePathNodeLength(devpath2))
+ return (0);
+
+ if (memcmp(devpath1, devpath2, (size_t)len) != 0)
+ return (0);
+
+ if (IsDevicePathEnd(devpath1))
+ break;
+ devpath1 = NextDevicePathNode(devpath1);
+ devpath2 = NextDevicePathNode(devpath2);
+ }
+ return (1);
+}
Modified: head/sys/boot/efi/libefi/efipart.c
==============================================================================
--- head/sys/boot/efi/libefi/efipart.c Mon Feb 6 08:58:40 2017 (r313332)
+++ head/sys/boot/efi/libefi/efipart.c Mon Feb 6 09:18:47 2017 (r313333)
@@ -27,8 +27,10 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/disk.h>
#include <sys/param.h>
#include <sys/time.h>
+#include <sys/queue.h>
#include <stddef.h>
#include <stdarg.h>
@@ -37,57 +39,110 @@ __FBSDID("$FreeBSD$");
#include <efi.h>
#include <efilib.h>
#include <efiprot.h>
+#include <disk.h>
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
-static int efipart_init(void);
+static int efipart_initfd(void);
+static int efipart_initcd(void);
+static int efipart_inithd(void);
+
static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *);
static int efipart_realstrategy(void *, int, daddr_t, size_t, char *, size_t *);
+
static int efipart_open(struct open_file *, ...);
static int efipart_close(struct open_file *);
-static int efipart_print(int);
+static int efipart_ioctl(struct open_file *, u_long, void *);
-struct devsw efipart_dev = {
- .dv_name = "part",
- .dv_type = DEVT_DISK,
- .dv_init = efipart_init,
+static int efipart_printfd(int);
+static int efipart_printcd(int);
+static int efipart_printhd(int);
+
+struct devsw efipart_fddev = {
+ .dv_name = "fd",
+ .dv_type = DEVT_FD,
+ .dv_init = efipart_initfd,
.dv_strategy = efipart_strategy,
.dv_open = efipart_open,
.dv_close = efipart_close,
- .dv_ioctl = noioctl,
- .dv_print = efipart_print,
+ .dv_ioctl = efipart_ioctl,
+ .dv_print = efipart_printfd,
.dv_cleanup = NULL
};
-/*
- * info structure to support bcache
- */
-struct pdinfo {
- int pd_unit; /* unit number */
- int pd_open; /* reference counter */
- void *pd_bcache; /* buffer cache data */
+struct devsw efipart_cddev = {
+ .dv_name = "cd",
+ .dv_type = DEVT_CD,
+ .dv_init = efipart_initcd,
+ .dv_strategy = efipart_strategy,
+ .dv_open = efipart_open,
+ .dv_close = efipart_close,
+ .dv_ioctl = efipart_ioctl,
+ .dv_print = efipart_printcd,
+ .dv_cleanup = NULL
};
-static struct pdinfo *pdinfo;
-static int npdinfo = 0;
-#define PD(dev) (pdinfo[(dev)->d_unit])
+struct devsw efipart_hddev = {
+ .dv_name = "disk",
+ .dv_type = DEVT_DISK,
+ .dv_init = efipart_inithd,
+ .dv_strategy = efipart_strategy,
+ .dv_open = efipart_open,
+ .dv_close = efipart_close,
+ .dv_ioctl = efipart_ioctl,
+ .dv_print = efipart_printhd,
+ .dv_cleanup = NULL
+};
+
+static pdinfo_list_t fdinfo;
+static pdinfo_list_t cdinfo;
+static pdinfo_list_t hdinfo;
+
+static EFI_HANDLE *efipart_handles = NULL;
+static UINTN efipart_nhandles = 0;
+
+static pdinfo_t *
+efiblk_get_pdinfo(pdinfo_list_t *pdi, int unit)
+{
+ pdinfo_t *pd;
+
+ STAILQ_FOREACH(pd, pdi, pd_link) {
+ if (pd->pd_unit == unit)
+ return (pd);
+ }
+ return (NULL);
+}
static int
-efipart_init(void)
+efiblk_pdinfo_count(pdinfo_list_t *pdi)
+{
+ pdinfo_t *pd;
+ int i = 0;
+
+ STAILQ_FOREACH(pd, pdi, pd_link) {
+ i++;
+ }
+ return (i);
+}
+
+static int
+efipart_inithandles(void)
{
- EFI_BLOCK_IO *blkio;
- EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
- EFI_HANDLE *hin, *hout, *aliases, handle;
- EFI_STATUS status;
UINTN sz;
- u_int n, nin, nout, nrdisk;
- int err;
+ EFI_HANDLE *hin;
+ EFI_STATUS status;
+
+ if (efipart_nhandles != 0) {
+ free(efipart_handles);
+ efipart_handles = NULL;
+ efipart_nhandles = 0;
+ }
sz = 0;
hin = NULL;
- status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, 0);
+ status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz, hin);
if (status == EFI_BUFFER_TOO_SMALL) {
- hin = (EFI_HANDLE *)malloc(sz * 3);
+ hin = malloc(sz);
status = BS->LocateHandle(ByProtocol, &blkio_guid, 0, &sz,
hin);
if (EFI_ERROR(status))
@@ -96,33 +151,150 @@ efipart_init(void)
if (EFI_ERROR(status))
return (efi_status_to_errno(status));
- /* Filter handles to only include FreeBSD partitions. */
- nin = sz / sizeof(EFI_HANDLE);
- hout = hin + nin;
- aliases = hout + nin;
- nout = 0;
- nrdisk = 0;
-
- bzero(aliases, nin * sizeof(EFI_HANDLE));
- pdinfo = malloc(nin * sizeof(*pdinfo));
- if (pdinfo == NULL)
- return (ENOMEM);
+ efipart_handles = hin;
+ efipart_nhandles = sz;
+ return (0);
+}
- for (n = 0; n < nin; n++) {
- devpath = efi_lookup_devpath(hin[n]);
- if (devpath == NULL) {
- continue;
+static ACPI_HID_DEVICE_PATH *
+efipart_floppy(EFI_DEVICE_PATH *node)
+{
+ ACPI_HID_DEVICE_PATH *acpi = NULL;
+
+ if (DevicePathType(node) == ACPI_DEVICE_PATH &&
+ DevicePathSubType(node) == ACPI_DP) {
+ acpi = (ACPI_HID_DEVICE_PATH *) node;
+ if (acpi->HID == EISA_PNP_ID(0x604) ||
+ acpi->HID == EISA_PNP_ID(0x700) ||
+ acpi->HID == EISA_ID(0x41d1, 0x701)) {
+ return (acpi);
}
+ }
+ return (acpi);
+}
- status = BS->HandleProtocol(hin[n], &blkio_guid,
- (void**)&blkio);
- if (EFI_ERROR(status))
+/*
+ * Add or update entries with new handle data.
+ */
+static int
+efipart_fdinfo_add(EFI_HANDLE handle, uint32_t uid, EFI_DEVICE_PATH *devpath)
+{
+ pdinfo_t *fd;
+
+ fd = malloc(sizeof(pdinfo_t));
+ if (fd == NULL) {
+ printf("Failed to register floppy %d, out of memory\n", uid);
+ return (ENOMEM);
+ }
+ memset(fd, 0, sizeof(pdinfo_t));
+ STAILQ_INIT(&fd->pd_part);
+
+ fd->pd_unit = uid;
+ fd->pd_handle = handle;
+ fd->pd_devpath = devpath;
+ STAILQ_INSERT_TAIL(&fdinfo, fd, pd_link);
+ return (0);
+}
+
+static void
+efipart_updatefd(void)
+{
+ EFI_DEVICE_PATH *devpath, *node;
+ ACPI_HID_DEVICE_PATH *acpi;
+ int i, nin;
+
+ nin = efipart_nhandles / sizeof (*efipart_handles);
+ for (i = 0; i < nin; i++) {
+ devpath = efi_lookup_devpath(efipart_handles[i]);
+ if (devpath == NULL)
continue;
- if (!blkio->Media->LogicalPartition) {
- nrdisk++;
+
+ if ((node = efi_devpath_last_node(devpath)) == NULL)
continue;
+ if ((acpi = efipart_floppy(node)) != NULL) {
+ efipart_fdinfo_add(efipart_handles[i], acpi->UID,
+ devpath);
+ }
+ }
+}
+
+static int
+efipart_initfd(void)
+{
+ int rv;
+
+ rv = efipart_inithandles();
+ if (rv != 0)
+ return (rv);
+ STAILQ_INIT(&fdinfo);
+
+ efipart_updatefd();
+
+ bcache_add_dev(efiblk_pdinfo_count(&fdinfo));
+ return (0);
+}
+
+/*
+ * Add or update entries with new handle data.
+ */
+static int
+efipart_cdinfo_add(EFI_HANDLE handle, EFI_HANDLE alias,
+ EFI_DEVICE_PATH *devpath)
+{
+ int unit;
+ pdinfo_t *cd;
+ pdinfo_t *pd;
+
+ unit = 0;
+ STAILQ_FOREACH(pd, &cdinfo, pd_link) {
+ if (efi_devpath_match(pd->pd_devpath, devpath) != 0) {
+ pd->pd_handle = handle;
+ pd->pd_alias = alias;
+ return (0);
}
+ unit++;
+ }
+
+ cd = malloc(sizeof(pdinfo_t));
+ if (cd == NULL) {
+ printf("Failed to add cd %d, out of memory\n", unit);
+ return (ENOMEM);
+ }
+ memset(cd, 0, sizeof(pdinfo_t));
+ STAILQ_INIT(&cd->pd_part);
+
+ cd->pd_handle = handle;
+ cd->pd_unit = unit;
+ cd->pd_alias = alias;
+ cd->pd_devpath = devpath;
+ STAILQ_INSERT_TAIL(&cdinfo, cd, pd_link);
+ return (0);
+}
+
+static void
+efipart_updatecd(void)
+{
+ int i, nin;
+ EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
+ EFI_HANDLE handle;
+ EFI_BLOCK_IO *blkio;
+ EFI_STATUS status;
+ nin = efipart_nhandles / sizeof (*efipart_handles);
+ for (i = 0; i < nin; i++) {
+ devpath = efi_lookup_devpath(efipart_handles[i]);
+ if (devpath == NULL)
+ continue;
+
+ if ((node = efi_devpath_last_node(devpath)) == NULL)
+ continue;
+ if (efipart_floppy(node) != NULL)
+ continue;
+
+ status = BS->HandleProtocol(efipart_handles[i],
+ &blkio_guid, (void **)&blkio);
+ if (EFI_ERROR(status))
+ continue;
/*
* If we come across a logical partition of subtype CDROM
* it doesn't refer to the CD filesystem itself, but rather
@@ -130,8 +302,6 @@ efipart_init(void)
* we try to find the parent device and add that instead as
* that will be the CD filesystem.
*/
- if ((node = efi_devpath_last_node(devpath)) == NULL)
- continue;
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
DevicePathSubType(node) == MEDIA_CDROM_DP) {
devpathcpy = efi_devpath_trim(devpath);
@@ -143,109 +313,400 @@ efipart_init(void)
free(devpathcpy);
if (EFI_ERROR(status))
continue;
- hout[nout] = handle;
- aliases[nout] = hin[n];
- } else
- hout[nout] = hin[n];
- nout++;
- pdinfo[npdinfo].pd_open = 0;
- pdinfo[npdinfo].pd_bcache = NULL;
- pdinfo[npdinfo].pd_unit = npdinfo;
- npdinfo++;
+ devpath = efi_lookup_devpath(handle);
+ efipart_cdinfo_add(handle, efipart_handles[i],
+ devpath);
+ continue;
+ }
+
+ if (DevicePathType(node) == MESSAGING_DEVICE_PATH &&
+ DevicePathSubType(node) == MSG_ATAPI_DP) {
+ efipart_cdinfo_add(efipart_handles[i], NULL,
+ devpath);
+ continue;
+ }
+
+ /* USB or SATA cd without the media. */
+ if (blkio->Media->RemovableMedia &&
+ !blkio->Media->MediaPresent) {
+ efipart_cdinfo_add(efipart_handles[i], NULL,
+ devpath);
+ }
}
+}
- bcache_add_dev(npdinfo);
- err = efi_register_handles(&efipart_dev, hout, aliases, nout);
- free(hin);
+static int
+efipart_initcd(void)
+{
+ int rv;
+
+ rv = efipart_inithandles();
+ if (rv != 0)
+ return (rv);
+ STAILQ_INIT(&cdinfo);
- if (nout == 0 && nrdisk > 0)
- printf("Found %d disk(s) but no logical partition\n", nrdisk);
- return (err);
+ efipart_updatecd();
+
+ bcache_add_dev(efiblk_pdinfo_count(&cdinfo));
+ return (0);
}
static int
-efipart_print(int verbose)
+efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle)
{
- char line[80];
+ EFI_DEVICE_PATH *disk_devpath, *part_devpath;
+ HARDDRIVE_DEVICE_PATH *node;
+ int unit;
+ pdinfo_t *hd, *pd, *last;
+
+ disk_devpath = efi_lookup_devpath(disk_handle);
+ part_devpath = efi_lookup_devpath(part_handle);
+ if (disk_devpath == NULL || part_devpath == NULL) {
+ return (ENOENT);
+ }
+
+ 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);
+ node = (HARDDRIVE_DEVICE_PATH *)efi_devpath_last_node(part_devpath);
+
+ STAILQ_FOREACH(hd, &hdinfo, pd_link) {
+ if (efi_devpath_match(hd->pd_devpath, disk_devpath) != 0) {
+ /* Add the partition. */
+ pd->pd_handle = part_handle;
+ pd->pd_unit = node->PartitionNumber;
+ pd->pd_devpath = part_devpath;
+ STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
+ return (0);
+ }
+ }
+
+ last = STAILQ_LAST(&hdinfo, pdinfo, pd_link);
+ if (last != NULL)
+ unit = last->pd_unit + 1;
+ else
+ unit = 0;
+
+ /* Add the disk. */
+ hd = pd;
+ hd->pd_handle = disk_handle;
+ hd->pd_unit = unit;
+ hd->pd_devpath = disk_devpath;
+ STAILQ_INSERT_TAIL(&hdinfo, hd, pd_link);
+
+ pd = malloc(sizeof(pdinfo_t));
+ if (pd == NULL) {
+ printf("Failed to add partition, out of memory\n");
+ return (ENOMEM);
+ }
+ memset(pd, 0, sizeof(pdinfo_t));
+ STAILQ_INIT(&pd->pd_part);
+
+ /* Add the partition. */
+ pd->pd_handle = part_handle;
+ pd->pd_unit = node->PartitionNumber;
+ pd->pd_devpath = part_devpath;
+ STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link);
+
+ return (0);
+}
+
+static void
+efipart_updatehd(void)
+{
+ int i, nin;
+ EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node;
+ EFI_HANDLE handle;
EFI_BLOCK_IO *blkio;
- EFI_HANDLE h;
EFI_STATUS status;
- u_int unit;
+
+ nin = efipart_nhandles / sizeof (*efipart_handles);
+ for (i = 0; i < nin; i++) {
+ devpath = efi_lookup_devpath(efipart_handles[i]);
+ if (devpath == NULL)
+ continue;
+
+ if ((node = efi_devpath_last_node(devpath)) == NULL)
+ continue;
+ if (efipart_floppy(node) != NULL)
+ continue;
+
+ status = BS->HandleProtocol(efipart_handles[i],
+ &blkio_guid, (void **)&blkio);
+ if (EFI_ERROR(status))
+ continue;
+
+ 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;
+ if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType(node) == MEDIA_HARDDRIVE_DP)
+ continue;
+ efipart_hdinfo_add(handle, efipart_handles[i]);
+ continue;
+ }
+ }
+}
+
+static int
+efipart_inithd(void)
+{
+ int rv;
+
+ rv = efipart_inithandles();
+ if (rv != 0)
+ return (rv);
+ STAILQ_INIT(&hdinfo);
+
+ efipart_updatehd();
+
+ bcache_add_dev(efiblk_pdinfo_count(&hdinfo));
+ return (0);
+}
+
+static int
+efipart_print_common(struct devsw *dev, pdinfo_list_t *pdlist, int verbose)
+{
int ret = 0;
+ EFI_BLOCK_IO *blkio;
+ EFI_STATUS status;
+ EFI_HANDLE h;
+ pdinfo_t *pd;
+ CHAR16 *text;
+ struct disk_devdesc pd_dev;
+ char line[80];
- printf("%s devices:", efipart_dev.dv_name);
+ if (STAILQ_EMPTY(pdlist))
+ return (0);
+
+ printf("%s devices:", dev->dv_name);
if ((ret = pager_output("\n")) != 0)
return (ret);
- for (unit = 0, h = efi_find_handle(&efipart_dev, 0);
- h != NULL; h = efi_find_handle(&efipart_dev, ++unit)) {
- snprintf(line, sizeof(line), " %s%d:",
- efipart_dev.dv_name, unit);
- if ((ret = pager_output(line)) != 0)
- break;
-
+ STAILQ_FOREACH(pd, pdlist, pd_link) {
+ h = pd->pd_handle;
+ if (verbose) { /* Output the device path. */
+ text = efi_devpath_name(efi_lookup_devpath(h));
+ if (text != NULL) {
+ printf(" %S", text);
+ efi_free_devpath_name(text);
+ if ((ret = pager_output("\n")) != 0)
+ break;
+ }
+ }
+ snprintf(line, sizeof(line),
+ " %s%d", dev->dv_name, pd->pd_unit);
+ printf("%s:", line);
status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
if (!EFI_ERROR(status)) {
- snprintf(line, sizeof(line), " %llu blocks",
- (unsigned long long)(blkio->Media->LastBlock + 1));
- if ((ret = pager_output(line)) != 0)
+ printf(" %llu",
+ blkio->Media->LastBlock == 0? 0:
+ (unsigned long long) (blkio->Media->LastBlock + 1));
+ if (blkio->Media->LastBlock != 0) {
+ printf(" X %u", blkio->Media->BlockSize);
+ }
+ printf(" blocks");
+ if (blkio->Media->MediaPresent) {
+ if (blkio->Media->RemovableMedia)
+ printf(" (removable)");
+ } else
+ printf(" (no media)");
+ if ((ret = pager_output("\n")) != 0)
+ break;
+ if (!blkio->Media->MediaPresent)
+ continue;
+
+ pd->pd_blkio = blkio;
+ pd_dev.d_dev = dev;
+ pd_dev.d_unit = pd->pd_unit;
+ pd_dev.d_slice = -1;
+ pd_dev.d_partition = -1;
+ pd_dev.d_opendata = blkio;
+ ret = disk_open(&pd_dev, blkio->Media->BlockSize *
+ (blkio->Media->LastBlock + 1),
+ blkio->Media->BlockSize,
+ blkio->Media->RemovableMedia? DISK_F_NOCACHE: 0);
+ 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 {
+ if ((ret = pager_output("\n")) != 0)
break;
- if (blkio->Media->RemovableMedia)
- if ((ret = pager_output(" (removable)")) != 0)
- break;
}
- if ((ret = pager_output("\n")) != 0)
- break;
}
return (ret);
}
static int
+efipart_printfd(int verbose)
+{
+ return (efipart_print_common(&efipart_fddev, &fdinfo, verbose));
+}
+
+static int
+efipart_printcd(int verbose)
+{
+ return (efipart_print_common(&efipart_cddev, &cdinfo, verbose));
+}
+
+static int
+efipart_printhd(int verbose)
+{
+ return (efipart_print_common(&efipart_hddev, &hdinfo, verbose));
+}
+
+pdinfo_list_t *
+efiblk_get_pdinfo_list(struct devsw *dev)
+{
+ if (dev->dv_type == DEVT_DISK)
+ return (&hdinfo);
+ if (dev->dv_type == DEVT_CD)
+ return (&cdinfo);
+ if (dev->dv_type == DEVT_FD)
+ return (&fdinfo);
+ return (NULL);
+}
+
+static int
efipart_open(struct open_file *f, ...)
{
va_list args;
- struct devdesc *dev;
+ struct disk_devdesc *dev;
+ pdinfo_list_t *pdi;
+ pdinfo_t *pd;
EFI_BLOCK_IO *blkio;
- EFI_HANDLE h;
EFI_STATUS status;
va_start(args, f);
- dev = va_arg(args, struct devdesc*);
+ dev = va_arg(args, struct disk_devdesc*);
va_end(args);
+ if (dev == NULL)
+ return (EINVAL);
- h = efi_find_handle(&efipart_dev, dev->d_unit);
- if (h == NULL)
+ pdi = efiblk_get_pdinfo_list(dev->d_dev);
+ if (pdi == NULL)
return (EINVAL);
- status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio);
- if (EFI_ERROR(status))
- return (efi_status_to_errno(status));
+ pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+ if (pd == NULL)
+ return (EIO);
+
+ 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));
+ }
+ blkio = pd->pd_blkio;
if (!blkio->Media->MediaPresent)
return (EAGAIN);
- dev->d_opendata = blkio;
- PD(dev).pd_open++;
- if (PD(dev).pd_bcache == NULL)
- PD(dev).pd_bcache = bcache_allocate();
+ pd->pd_open++;
+ if (pd->pd_bcache == NULL)
+ pd->pd_bcache = bcache_allocate();
+
+ if (dev->d_dev->dv_type == DEVT_DISK) {
+ return (disk_open(dev,
+ blkio->Media->BlockSize * (blkio->Media->LastBlock + 1),
+ blkio->Media->BlockSize,
+ blkio->Media->RemovableMedia? DISK_F_NOCACHE: 0));
+ }
return (0);
}
static int
efipart_close(struct open_file *f)
{
- struct devdesc *dev;
+ struct disk_devdesc *dev;
+ pdinfo_list_t *pdi;
+ pdinfo_t *pd;
- dev = (struct devdesc *)(f->f_devdata);
- if (dev->d_opendata == NULL)
+ dev = (struct disk_devdesc *)(f->f_devdata);
+ if (dev == NULL)
+ return (EINVAL);
+ pdi = efiblk_get_pdinfo_list(dev->d_dev);
+ if (pdi == NULL)
return (EINVAL);
- dev->d_opendata = NULL;
- PD(dev).pd_open--;
- if (PD(dev).pd_open == 0) {
- bcache_free(PD(dev).pd_bcache);
- PD(dev).pd_bcache = NULL;
+ pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+ if (pd == NULL)
+ return (EINVAL);
+
+ pd->pd_open--;
+ if (pd->pd_open == 0) {
+ pd->pd_blkio = NULL;
+ bcache_free(pd->pd_bcache);
+ pd->pd_bcache = NULL;
}
+ if (dev->d_dev->dv_type == DEVT_DISK)
+ return (disk_close(dev));
+ return (0);
+}
+
+static int
+efipart_ioctl(struct open_file *f, u_long cmd, void *data)
+{
+ struct disk_devdesc *dev;
+ pdinfo_list_t *pdi;
+ pdinfo_t *pd;
+ int rc;
+
+ dev = (struct disk_devdesc *)(f->f_devdata);
+ if (dev == NULL)
+ return (EINVAL);
+ pdi = efiblk_get_pdinfo_list(dev->d_dev);
+ if (pdi == NULL)
+ return (EINVAL);
+
+ pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+ if (pd == NULL)
+ return (EINVAL);
+
+ if (dev->d_dev->dv_type == DEVT_DISK) {
+ rc = disk_ioctl(dev, cmd, data);
+ if (rc != ENOTTY)
+ return (rc);
+ }
+
+ switch (cmd) {
+ case DIOCGSECTORSIZE:
+ *(u_int *)data = pd->pd_blkio->Media->BlockSize;
+ break;
+ case DIOCGMEDIASIZE:
+ *(off_t *)data = pd->pd_blkio->Media->BlockSize *
+ (pd->pd_blkio->Media->LastBlock + 1);
+ break;
+ default:
+ return (ENOTTY);
+ }
+
return (0);
}
@@ -294,12 +755,29 @@ efipart_strategy(void *devdata, int rw,
char *buf, size_t *rsize)
{
struct bcache_devdata bcd;
- struct devdesc *dev;
+ struct disk_devdesc *dev;
+ pdinfo_list_t *pdi;
+ pdinfo_t *pd;
+
+ dev = (struct disk_devdesc *)devdata;
+ if (dev == NULL)
+ return (EINVAL);
+ pdi = efiblk_get_pdinfo_list(dev->d_dev);
+ if (pdi == NULL)
+ return (EINVAL);
+
+ pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+ if (pd == NULL)
+ return (EINVAL);
- dev = (struct devdesc *)devdata;
bcd.dv_strategy = efipart_realstrategy;
bcd.dv_devdata = devdata;
- bcd.dv_cache = PD(dev).pd_bcache;
+ bcd.dv_cache = pd->pd_bcache;
+
+ if (dev->d_dev->dv_type == DEVT_DISK) {
+ return (bcache_strategy(&bcd, rw, blk + dev->d_offset,
+ size, buf, rsize));
+ }
return (bcache_strategy(&bcd, rw, blk, size, buf, rsize));
}
@@ -307,7 +785,9 @@ static int
efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t size,
char *buf, size_t *rsize)
{
- struct devdesc *dev = (struct devdesc *)devdata;
+ struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
+ pdinfo_list_t *pdi;
+ pdinfo_t *pd;
EFI_BLOCK_IO *blkio;
off_t off;
char *blkbuf;
@@ -317,7 +797,15 @@ efipart_realstrategy(void *devdata, int
if (dev == NULL || blk < 0)
return (EINVAL);
- blkio = dev->d_opendata;
+ pdi = efiblk_get_pdinfo_list(dev->d_dev);
+ if (pdi == NULL)
+ return (EINVAL);
+
+ pd = efiblk_get_pdinfo(pdi, dev->d_unit);
+ if (pd == NULL)
+ return (EINVAL);
+
+ blkio = pd->pd_blkio;
if (blkio == NULL)
return (ENXIO);
Modified: head/sys/boot/efi/loader/conf.c
==============================================================================
--- head/sys/boot/efi/loader/conf.c Mon Feb 6 08:58:40 2017 (r313332)
+++ head/sys/boot/efi/loader/conf.c Mon Feb 6 09:18:47 2017 (r313333)
@@ -36,7 +36,9 @@ __FBSDID("$FreeBSD$");
#endif
struct devsw *devsw[] = {
- &efipart_dev,
+ &efipart_fddev,
+ &efipart_cddev,
+ &efipart_hddev,
&efinet_dev,
#ifdef EFI_ZFS_BOOT
&zfs_dev,
Modified: head/sys/boot/efi/loader/devicename.c
==============================================================================
--- head/sys/boot/efi/loader/devicename.c Mon Feb 6 08:58:40 2017 (r313332)
+++ head/sys/boot/efi/loader/devicename.c Mon Feb 6 09:18:47 2017 (r313333)
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/disklabel.h>
#include <sys/param.h>
#include <bootstrap.h>
+#include <disk.h>
#ifdef EFI_ZFS_BOOT
#include <libzfs.h>
#endif
@@ -90,7 +91,7 @@ efi_parsedev(struct devdesc **dev, const
struct devsw *dv;
char *cp;
const char *np;
- int i;
+ int i, err;
/* minimum length check */
if (strlen(devspec) < 2)
@@ -106,11 +107,26 @@ efi_parsedev(struct devdesc **dev, const
return (ENOENT);
np = devspec + strlen(dv->dv_name);
+ err = 0;
-#ifdef EFI_ZFS_BOOT
- if (dv->dv_type == DEVT_ZFS) {
- int err;
+ switch (dv->dv_type) {
+ case DEVT_NONE:
+ break;
+
+ case DEVT_DISK:
+ idev = malloc(sizeof(struct disk_devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
+
+ err = disk_parsedev((struct disk_devdesc *)idev, np, path);
+ if (err != 0) {
+ free(idev);
+ return (err);
+ }
+ break;
+#ifdef EFI_ZFS_BOOT
+ case DEVT_ZFS:
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list