Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143725014
D13497.id54425.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D13497.id54425.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D13497: Dual-purpose loader.efi
Attached
Detach File
Event Timeline
Log In to Comment