Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164148672
D13784.id37591.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D13784.id37591.diff
View Options
Index: stand/efi/include/efilib.h
===================================================================
--- stand/efi/include/efilib.h
+++ stand/efi/include/efilib.h
@@ -59,10 +59,13 @@
uint32_t pd_unit; /* unit number */
uint32_t pd_open; /* reference counter */
void *pd_bcache; /* buffer cache data */
+ struct pdinfo *pd_parent; /* Linked items (eg partitions) */
+ struct devsw *pd_devsw; /* Back pointer to devsw */
} pdinfo_t;
pdinfo_list_t *efiblk_get_pdinfo_list(struct devsw *dev);
pdinfo_t *efiblk_get_pdinfo(struct devdesc *dev);
+pdinfo_t *efiblk_get_pdinfo_by_handle(EFI_HANDLE h);
void *efi_get_table(EFI_GUID *tbl);
Index: stand/efi/libefi/devicename.c
===================================================================
--- stand/efi/libefi/devicename.c
+++ stand/efi/libefi/devicename.c
@@ -161,7 +161,6 @@
}
idev->d_dev = dv;
- idev->d_type = dv->dv_type;
if (dev != NULL)
*dev = idev;
@@ -180,7 +179,7 @@
struct devdesc *dev = (struct devdesc *)vdev;
static char buf[SPECNAMELEN + 1];
- switch(dev->d_type) {
+ switch(dev->d_dev->dv_type) {
case DEVT_NONE:
strcpy(buf, "(no device)");
break;
Index: stand/efi/libefi/efipart.c
===================================================================
--- stand/efi/libefi/efipart.c
+++ stand/efi/libefi/efipart.c
@@ -136,6 +136,40 @@
return (pd);
}
+static bool
+same_handle(pdinfo_t *pd, EFI_HANDLE h)
+{
+
+ return (pd->pd_handle == h || pd->pd_alias == h);
+}
+
+pdinfo_t *
+efiblk_get_pdinfo_by_handle(EFI_HANDLE h)
+{
+ pdinfo_t *dp, *pp;
+
+ /*
+ * Check hard disks, then cd, then floppy
+ */
+ STAILQ_FOREACH(dp, &hdinfo, 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, &cdinfo, pd_link) {
+ if (same_handle(dp, h))
+ return (dp);
+ }
+ STAILQ_FOREACH(dp, &fdinfo, pd_link) {
+ if (same_handle(dp, h))
+ return (dp);
+ }
+ return (NULL);
+}
+
static int
efiblk_pdinfo_count(pdinfo_list_t *pdi)
{
@@ -290,6 +324,8 @@
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);
}
@@ -364,6 +400,8 @@
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);
}
@@ -493,6 +531,8 @@
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);
}
@@ -509,6 +549,8 @@
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)
@@ -525,6 +567,8 @@
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);
@@ -583,6 +627,8 @@
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);
free(pathname);
return (0);
@@ -613,6 +659,8 @@
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);
free(pathname);
return (0);
Index: stand/efi/loader/main.c
===================================================================
--- stand/efi/loader/main.c
+++ stand/efi/loader/main.c
@@ -165,20 +165,62 @@
}
static void
-set_devdesc_currdev(struct devsw *dev, int unit)
+set_currdev_devdesc(struct devdesc *currdev)
{
- struct devdesc currdev;
char *devname;
+ devname = efi_fmtdev(currdev);
+
+ env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, devname, env_noset, env_nounset);
+}
+
+static void
+set_currdev_devsw(struct devsw *dev, int unit)
+{
+ struct devdesc currdev;
+
currdev.d_dev = dev;
- currdev.d_type = currdev.d_dev->dv_type;
currdev.d_unit = unit;
currdev.d_opendata = NULL;
- devname = efi_fmtdev(&currdev);
- env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
- env_nounset);
- env_setenv("loaddev", EV_VOLATILE, devname, env_noset, env_nounset);
+ set_currdev_devdesc(&currdev);
+}
+
+static void
+set_currdev_pdinfo(pdinfo_t *dp)
+{
+
+ /*
+ * Disks are special: they have partitions. if the parent
+ * pointer is non-null, we're a partition not a full disk
+ * and we need to adjust currdev appropriately.
+ */
+ if (dp->pd_devsw->dv_type == DEVT_DISK) {
+ struct disk_devdesc currdev;
+
+ currdev.d_dev = dp->pd_devsw;
+ currdev.d_opendata = NULL;
+ currdev.d_partition = -1;
+ if (dp->pd_parent == NULL) {
+ currdev.d_unit = dp->pd_unit;
+ currdev.d_slice = -1;
+ } else {
+ currdev.d_unit = dp->pd_parent->pd_unit;
+ currdev.d_slice = dp->pd_unit;
+ }
+ set_currdev_devdesc((struct devdesc *)&currdev);
+ } else {
+ set_currdev_devsw(dp->pd_devsw, dp->pd_unit);
+ }
+}
+
+static bool
+sanity_check_currdev(void)
+{
+ struct stat st;
+
+ return (stat("/boot/laoder.conf", &st) == 0);
}
static int
@@ -194,90 +236,62 @@
uint64_t extra;
#ifdef EFI_ZFS_BOOT
- /* Did efi_zfs_probe() detect the boot pool? */
+ /*
+ * Did efi_zfs_probe() detect the boot pool? If so, use the zpool
+ * it found, if it's sane. ZFS is the only thing that looks for
+ * disks and pools to boot. This may change in the future, however,
+ * if we allow specifying which pool to boot from via UEFI variables
+ * rather than the bootenv stuff that FreeBSD uses today.
+ */
if (pool_guid != 0) {
struct zfs_devdesc currdev;
currdev.d_dev = &zfs_dev;
currdev.d_unit = 0;
- currdev.d_type = currdev.d_dev->dv_type;
currdev.d_opendata = NULL;
currdev.pool_guid = pool_guid;
currdev.root_guid = 0;
+ set_currdev_devdesc((struct devdesc *)&currdev);
devname = efi_fmtdev(&currdev);
-
- env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
- env_nounset);
- env_setenv("loaddev", EV_VOLATILE, devname, env_noset,
- env_nounset);
init_zfs_bootenv(devname);
- return (0);
+ if (sanity_check_currdev())
+ return (0);
}
#endif /* EFI_ZFS_BOOT */
- /* We have device lists for hd, cd, fd, walk them all. */
- pdi_list = efiblk_get_pdinfo_list(&efipart_hddev);
- STAILQ_FOREACH(dp, pdi_list, pd_link) {
- struct disk_devdesc currdev;
-
- currdev.d_dev = &efipart_hddev;
- currdev.d_type = currdev.d_dev->dv_type;
- currdev.d_unit = dp->pd_unit;
- currdev.d_opendata = NULL;
- currdev.d_slice = -1;
- currdev.d_partition = -1;
-
- if (dp->pd_handle == img->DeviceHandle) {
- devname = efi_fmtdev(&currdev);
-
- env_setenv("currdev", EV_VOLATILE, devname,
- efi_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, devname,
- env_noset, env_nounset);
+ /*
+ * Try to find the block device by its handle based on the
+ * image we're booting. If we can't find a sane partition,
+ * search all the other partitions of the disk. We do not
+ * search other disks because it's a violation of the UEFI
+ * boot protocol to do so. We fail and let UEFI go on to
+ * the next candidate.
+ */
+ dp = efiblk_get_pdinfo_by_handle(img->DeviceHandle);
+ if (dp != NULL) {
+ set_currdev_pdinfo(dp);
+ if (sanity_check_currdev())
return (0);
- }
- /* Assuming GPT partitioning. */
- STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
- if (pp->pd_handle == img->DeviceHandle) {
- currdev.d_slice = pp->pd_unit;
- currdev.d_partition = 255;
- devname = efi_fmtdev(&currdev);
-
- env_setenv("currdev", EV_VOLATILE, devname,
- efi_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, devname,
- env_noset, env_nounset);
- return (0);
+ if (dp->pd_parent != NULL) {
+ dp = dp->pd_parent;
+ STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
+ set_currdev_pdinfo(dp);
+ if (sanity_check_currdev())
+ return (0);
}
}
}
- pdi_list = efiblk_get_pdinfo_list(&efipart_cddev);
- STAILQ_FOREACH(dp, pdi_list, pd_link) {
- if (dp->pd_handle == img->DeviceHandle ||
- dp->pd_alias == img->DeviceHandle) {
- set_devdesc_currdev(&efipart_cddev, dp->pd_unit);
- return (0);
- }
- }
-
- pdi_list = efiblk_get_pdinfo_list(&efipart_fddev);
- STAILQ_FOREACH(dp, pdi_list, pd_link) {
- if (dp->pd_handle == img->DeviceHandle) {
- set_devdesc_currdev(&efipart_fddev, dp->pd_unit);
- return (0);
- }
- }
-
/*
* Try the device handle from our loaded image first. If that
* fails, use the device path from the loaded image and see if
* any of the nodes in that path match one of the enumerated
- * handles.
+ * handles. Currently, this handle list is only for netboot.
*/
if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &extra) == 0) {
- set_devdesc_currdev(dev, unit);
- return (0);
+ set_currdev_devsw(dev, unit);
+ if (sanity_check_currdev())
+ return (0);
}
copy = NULL;
@@ -291,8 +305,9 @@
copy = NULL;
if (efi_handle_lookup(h, &dev, &unit, &extra) == 0) {
- set_devdesc_currdev(dev, unit);
- return (0);
+ set_currdev_devsw(dev, unit);
+ if (sanity_check_currdev())
+ return (0);
}
devpath = efi_lookup_devpath(h);
@@ -306,6 +321,14 @@
return (ENOENT);
}
+static bool
+interactive_interrupt(const char *msg, int timeout __unused)
+{
+
+ printf("%s\n", msg);
+ return (false);
+}
+
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
@@ -352,12 +375,15 @@
/*
* Parse the args to set the console settings, etc
* boot1.efi passes these in, if it can read /boot.config or /boot/config
- * or iPXE may be setup to pass these in.
+ * or iPXE may be setup to pass these in. Or the optional argument in the
+ * boot environment was used to pass these arguments in (in which case
+ * neither /boot.config nor /boot/config are consulted).
*
* Loop through the args, and for each one that contains an '=' that is
* not the first character, add it to the environment. This allows
* loader and kernel env vars to be passed on the command line. Convert
- * args from UCS-2 to ASCII (16 to 8 bit) as they are copied.
+ * args from UCS-2 to ASCII (16 to 8 bit) as they are copied (though this
+ * method is flawed for non-ASCII characters).
*/
howto = 0;
for (i = 1; i < argc; i++) {
@@ -437,6 +463,9 @@
for (i = 0; howto_names[i].ev != NULL; i++)
if (howto & howto_names[i].mask)
setenv(howto_names[i].ev, "YES", 1);
+ /*
+ * XXX we need fallback to this stuff after looking at the ConIn, ConOut and ConErr variables
+ */
if (howto & RB_MULTIPLE) {
if (howto & RB_SERIAL)
setenv("console", "comconsole efi" , 1);
@@ -482,8 +511,16 @@
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
+ /*
+ * Try and find a good currdev based on the image that was booted.
+ * It might be desirable here to have a short pause to allow falling
+ * through to the boot loader instead of returning instantly to follow
+ * the boot protocol and also allow an escape hatch for users wishing
+ * to try something different.
+ */
if (find_currdev(img) != 0)
- return (EFI_NOT_FOUND);
+ if (!interactive_interrupt("Failed to find bootable partition", 5))
+ return (EFI_NOT_FOUND);
efi_init_environment();
setenv("LINES", "24", 1); /* optional */
@@ -887,7 +924,7 @@
struct disk_devdesc *d_dev;
pdinfo_t *hd, *pd;
- switch (dev->d_type) {
+ switch (dev->d_dev->dv_type) {
#ifdef EFI_ZFS_BOOT
case DEVT_ZFS:
z_dev = (struct zfs_devdesc *)dev;
Index: stand/libsa/stand.h
===================================================================
--- stand/libsa/stand.h
+++ stand/libsa/stand.h
@@ -137,6 +137,12 @@
struct devsw {
const char dv_name[8];
int dv_type; /* opaque type constant, arch-dependant */
+#define DEVT_NONE 0
+#define DEVT_DISK 1
+#define DEVT_NET 2
+#define DEVT_CD 3
+#define DEVT_ZFS 4
+#define DEVT_FD 5
int (*dv_init)(void); /* early probe call */
int (*dv_strategy)(void *devdata, int rw, daddr_t blk,
size_t size, char *buf, size_t *rsize);
@@ -162,13 +168,6 @@
struct devdesc
{
struct devsw *d_dev;
- int d_type;
-#define DEVT_NONE 0
-#define DEVT_DISK 1
-#define DEVT_NET 2
-#define DEVT_CD 3
-#define DEVT_ZFS 4
-#define DEVT_FD 5
int d_unit;
void *d_opendata;
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 30, 4:12 AM (10 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35707618
Default Alt Text
D13784.id37591.diff (12 KB)
Attached To
Mode
D13784: Make loader.efi dual boot, step 1
Attached
Detach File
Event Timeline
Log In to Comment