Page MenuHomeFreeBSD

D13497.id54425.diff
No OneTemporary

D13497.id54425.diff

Index: stand/efi/loader/main.c
===================================================================
--- stand/efi/loader/main.c
+++ stand/efi/loader/main.c
@@ -77,14 +77,8 @@
EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
static EFI_LOADED_IMAGE *img;
-
-#ifdef EFI_ZFS_BOOT
-bool
-efi_zfs_is_preferred(EFI_HANDLE *h)
-{
- return (h == img->DeviceHandle);
-}
-#endif
+static EFI_DEVICE_PATH *imgpath;
+static EFI_DEVICE_PATH *imgprefix;
static int
has_keyboard(void)
@@ -168,23 +162,185 @@
return retval;
}
+/* Check if this is a preferred device */
+#ifndef LOADER_CHECK_ALL_DEVS
+static bool
+check_preferred(EFI_HANDLE *h)
+{
+ EFI_DEVICE_PATH *path = efi_lookup_devpath(h);
+ bool out;
+
+ if ((path = efi_lookup_devpath(h)) == NULL)
+ return (false);
+
+ out = efi_devpath_is_prefix(imgpath, path) ||
+ efi_devpath_is_prefix(imgprefix, path);
+
+ return (out);
+}
+
+static bool
+zfs_check_preferred(uint64_t check_guid)
+{
+ return (pool_guid != 0 && check_guid == pool_guid);
+}
+#else
+static bool
+check_preferred(EFI_HANDLE *h)
+{
+ return (true);
+}
+
+static bool
+zfs_check_preferred(uint64_t check_guid)
+{
+ return (true);
+}
+#endif
+
+static void
+set_vars(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_devdesc_currdev(struct devsw *dev, int unit)
{
struct devdesc currdev;
- char *devname;
currdev.d_dev = dev;
currdev.d_unit = unit;
devname = efi_fmtdev(&currdev);
+ currdev.d_opendata = NULL;
+ set_vars(&currdev);
+}
- env_setenv("currdev", EV_VOLATILE, devname, efi_setcurrdev,
- env_nounset);
- env_setenv("loaddev", EV_VOLATILE, devname, env_noset, env_nounset);
+/* Directly check a devdesc for an installed system */
+static int
+check_devdesc(struct devdesc *currdev) {
+ /* Files that indicate the presence of an installed system */
+ static const char* paths[] = {
+ "/boot/loader.conf",
+ "/boot/kernel",
+ NULL
+ };
+
+ struct stat sb;
+ int i, err;
+
+ /* Check for the presence of any of the files */
+ for (i = 0; paths[i] != NULL; i++) {
+ err = stat(paths[i], &sb);
+ if (errno != ENOENT) {
+ return (err);
+ }
+ }
+
+ return (err);
+}
+
+/* Set up a dev and then check it for an installed system */
+static int
+check_dev(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;
+ set_vars(&currdev);
+
+ return (check_devdesc(&currdev));
}
static int
-find_currdev(EFI_LOADED_IMAGE *img)
+find_currdev(void)
+{
+ pdinfo_list_t *pdi_list;
+ pdinfo_t *dp, *pp;
+ zfsinfo_list_t *zfsi_list;
+ zfsinfo_t *zi;
+ char *devname;
+
+#ifdef EFI_ZFS_BOOT
+ zfsi_list = efizfs_get_zfsinfo_list();
+ STAILQ_FOREACH(zi, zfsi_list, zi_link) {
+ if (zfs_check_preferred(zi->zi_pool_guid)) {
+ 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 = zi->zi_pool_guid;
+ currdev.root_guid = 0;
+ devname = efi_fmtdev(&currdev);
+ set_vars((struct devdesc*)(&currdev));
+ init_zfs_bootenv(devname);
+
+ if (check_devdesc((struct devdesc*)(&currdev)) == 0)
+ 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;
+ set_vars((struct devdesc*)(&currdev));
+
+ if (check_preferred(dp->pd_handle) &&
+ check_devdesc((struct devdesc*)(&currdev)) == 0)
+ return (0);
+
+ /* Assuming GPT partitioning. */
+ STAILQ_FOREACH(pp, &dp->pd_part, pd_link) {
+ if (check_preferred(pp->pd_handle)) {
+ currdev.d_slice = pp->pd_unit;
+ currdev.d_partition = 255;
+ set_vars((struct devdesc*)(&currdev));
+
+ if (check_devdesc((struct devdesc*)
+ (&currdev)) == 0)
+ return (0);
+ }
+ }
+ }
+
+#ifdef LOADER_CHECK_ALL_DEVS
+ pdi_list = efiblk_get_pdinfo_list(&efipart_cddev);
+ STAILQ_FOREACH(dp, pdi_list, pd_link) {
+ if (check_preferred(dp->pd_handle) &&
+ check_dev(&efipart_cddev, dp->pd_unit) == 0)
+ return (0);
+ }
+
+ pdi_list = efiblk_get_pdinfo_list(&efipart_fddev);
+ STAILQ_FOREACH(dp, pdi_list, pd_link) {
+ if (check_preferred(dp->pd_handle) &&
+ check_dev(&efipart_fddev, dp->pd_unit) == 0)
+ return (0);
+ }
+#endif
+ return (ENOENT);
+}
+
+/* Legacy-mode device search: assume we've been loaded by boot1 */
+static int
+find_currdev_legacy(void)
{
pdinfo_list_t *pdi_list;
pdinfo_t *dp, *pp;
@@ -205,11 +361,7 @@
currdev.pool_guid = pool_guid;
currdev.root_guid = 0;
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_vars((struct devdesc*)(&currdev));
init_zfs_bootenv(devname);
return (0);
}
@@ -226,12 +378,8 @@
currdev.d_partition = -1;
if (dp->pd_handle == img->DeviceHandle) {
- devname = efi_fmtdev(&currdev);
+ set_vars((struct devdesc*)(&currdev));
- env_setenv("currdev", EV_VOLATILE, devname,
- efi_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, devname,
- env_noset, env_nounset);
return (0);
}
/* Assuming GPT partitioning. */
@@ -239,12 +387,8 @@
if (pp->pd_handle == img->DeviceHandle) {
currdev.d_slice = pp->pd_unit;
currdev.d_partition = 255;
- devname = efi_fmtdev(&currdev);
+ set_vars((struct devdesc*)(&currdev));
- env_setenv("currdev", EV_VOLATILE, devname,
- efi_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, devname,
- env_noset, env_nounset);
return (0);
}
}
@@ -304,11 +448,37 @@
return (ENOENT);
}
+static int
+find_currdev(void)
+{
+ int err;
+
+ if ((err = find_currdev_preferred()) != ENOENT) {
+ return (err);
+ }
+
+ if ((err = find_currdev_all()) != ENOENT) {
+ return (err);
+ }
+
+ return find_currdev_legacy();
+
+}
+
+#ifdef EFI_ZFS_BOOT
+bool
+efi_zfs_is_preferred(EFI_HANDLE *h)
+{
+ return (h == img->DeviceHandle || check_preferred(h));
+}
+#endif
+
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
char var[128];
EFI_GUID *guid;
+ EFI_STATUS status;
int i, j, vargood, howto;
UINTN k;
int has_kbd;
@@ -353,10 +523,24 @@
*/
bcache_init(32768, 512);
+ if ((status = BS->HandleProtocol(img->DeviceHandle, &devid,
+ (VOID**)&imgpath)) !=
+ EFI_SUCCESS) {
+ panic("Failed to query LoadedImage (%lu)\n",
+ EFI_ERROR_CODE(status));
+ }
+
+ /* The loaded image device path ends with a partition, then a
+ * file path. Trim them both to get the actual disk.
+ */
+ if ((imgprefix = efi_devpath_trim(imgpath)) == NULL) {
+ panic("Couldn't trim device path");
+ }
+
/*
- * 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.
+ * 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.
*
* Loop through the args, and for each one that contains an '=' that is
* not the first character, add it to the environment. This allows
@@ -520,7 +704,7 @@
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
- if (find_currdev(img) != 0)
+ if (find_currdev() != 0)
return (EFI_NOT_FOUND);
efi_init_environment();

File Metadata

Mime Type
text/plain
Expires
Sun, Feb 1, 9:14 AM (2 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28328977
Default Alt Text
D13497.id54425.diff (9 KB)

Event Timeline