Page MenuHomeFreeBSD

D13497.id37615.diff
No OneTemporary

D13497.id37615.diff

Index: stand/efi/loader/main.c
===================================================================
--- stand/efi/loader/main.c
+++ stand/efi/loader/main.c
@@ -73,14 +73,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)
@@ -164,153 +158,197 @@
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_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_vars(&currdev);
}
+/* Directly check a devdesc for an installed system */
static int
-find_currdev(EFI_LOADED_IMAGE *img)
-{
- pdinfo_list_t *pdi_list;
- pdinfo_t *dp, *pp;
- EFI_DEVICE_PATH *devpath, *copy;
- EFI_HANDLE h;
- char *devname;
- struct devsw *dev;
- int unit;
- uint64_t extra;
-
-#ifdef EFI_ZFS_BOOT
- /* Did efi_zfs_probe() detect the boot pool? */
- 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;
- 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);
- }
-#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);
- 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);
- }
- }
- }
-
- 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);
- }
- }
+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);
+}
- 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);
- }
- }
+/* Set up a dev and then check it for an installed system */
+static int
+check_dev(struct devsw *dev, int unit) {
+ struct devdesc currdev;
- /*
- * 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.
- */
- if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &extra) == 0) {
- set_devdesc_currdev(dev, unit);
- return (0);
- }
+ currdev.d_dev = dev;
+ currdev.d_type = currdev.d_dev->dv_type;
+ currdev.d_unit = unit;
+ currdev.d_opendata = NULL;
+ set_vars(&currdev);
- copy = NULL;
- devpath = efi_lookup_image_devpath(IH);
- while (devpath != NULL) {
- h = efi_devpath_handle(devpath);
- if (h == NULL)
- break;
+ return (check_devdesc(&currdev));
+}
- free(copy);
- copy = NULL;
+static int
+find_currdev(void)
+{
+ pdinfo_list_t *pdi_list;
+ pdinfo_t *dp, *pp;
+ zfsinfo_list_t *zfsi_list;
+ zfsinfo_t *zi;
+ char *devname;
- if (efi_handle_lookup(h, &dev, &unit, &extra) == 0) {
- set_devdesc_currdev(dev, unit);
- return (0);
- }
+#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);
+}
- devpath = efi_lookup_devpath(h);
- if (devpath != NULL) {
- copy = efi_devpath_trim(devpath);
- devpath = copy;
- }
- }
- free(copy);
- return (ENOENT);
+#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;
@@ -349,10 +387,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
@@ -482,7 +534,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, 6:25 AM (19 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28295956
Default Alt Text
D13497.id37615.diff (10 KB)

Event Timeline