Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143456635
D13497.id36746.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D13497.id36746.diff
View Options
Index: stand/efi/loader/main.c
===================================================================
--- stand/efi/loader/main.c
+++ stand/efi/loader/main.c
@@ -73,6 +73,8 @@
EFI_GUID inputid = SIMPLE_TEXT_INPUT_PROTOCOL;
static EFI_LOADED_IMAGE *img;
+static EFI_DEVICE_PATH *imgpath;
+static EFI_DEVICE_PATH *imgprefix;
#ifdef EFI_ZFS_BOOT
bool
@@ -164,146 +166,180 @@
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);
- }
- }
-
- 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.
- */
- if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &extra) == 0) {
- set_devdesc_currdev(dev, 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);
+}
- copy = NULL;
- devpath = efi_lookup_image_devpath(IH);
- while (devpath != NULL) {
- h = efi_devpath_handle(devpath);
- if (h == NULL)
- break;
+/* Set up a dev and then check it for an installed system */
+static int
+check_dev(struct devsw *dev, int unit) {
+ struct devdesc currdev;
- free(copy);
- copy = NULL;
+ currdev.d_dev = dev;
+ currdev.d_type = currdev.d_dev->dv_type;
+ currdev.d_unit = unit;
+ currdev.d_opendata = NULL;
+ set_vars(&currdev);
- if (efi_handle_lookup(h, &dev, &unit, &extra) == 0) {
- set_devdesc_currdev(dev, unit);
- return (0);
- }
+ return (check_devdesc(&currdev));
+}
- devpath = efi_lookup_devpath(h);
- if (devpath != NULL) {
- copy = efi_devpath_trim(devpath);
- devpath = copy;
- }
- }
- free(copy);
+static int
+find_currdev(void)
+{
+ pdinfo_list_t *pdi_list;
+ pdinfo_t *dp, *pp;
+ zfsinfo_list_t *zfsi_list;
+ zfsinfo_t *zi;
+ char *devname;
- return (ENOENT);
+#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);
}
EFI_STATUS
@@ -311,6 +347,7 @@
{
char var[128];
EFI_GUID *guid;
+ EFI_STATUS status;
int i, j, vargood, howto;
UINTN k;
int has_kbd;
@@ -349,10 +386,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 +533,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
Sat, Jan 31, 4:05 PM (5 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28122112
Default Alt Text
D13497.id36746.diff (10 KB)
Attached To
Mode
D13497: Dual-purpose loader.efi
Attached
Detach File
Event Timeline
Log In to Comment