Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Feb 2014 17:51:10 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r262337 - head/sys/boot/uboot/common
Message-ID:  <201402221751.s1MHpAn8070498@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ian
Date: Sat Feb 22 17:51:10 2014
New Revision: 262337
URL: http://svnweb.freebsd.org/changeset/base/262337

Log:
  Allow the ubldr boot device to be choosen by a u-boot environment variable.
  
  If a "loaderdev=<device>" env variable is set and the named device
  exists, it is used.  If the device doesn't exist, fall back to the
  historic "probe" loop that prefers disk devices over network devices.
  
  If the env var is not set, preserve the historic behavior of using the
  first working disk device provided by u-boot, or a network device if no
  functional disk device is found and a network device exists.
  
  The old probe loop is reworked so that it checks all bootable devices
  provided by u-boot rather than taking an early-out on the first device
  found.  This results in the cosmetic change of listing all potential boot
  devices for the user, but the behavior of which device it chooses is the
  same as it has always been.

Modified:
  head/sys/boot/uboot/common/main.c

Modified: head/sys/boot/uboot/common/main.c
==============================================================================
--- head/sys/boot/uboot/common/main.c	Sat Feb 22 13:07:38 2014	(r262336)
+++ head/sys/boot/uboot/common/main.c	Sat Feb 22 17:51:10 2014	(r262337)
@@ -120,8 +120,9 @@ int
 main(void)
 {
 	struct api_signature *sig = NULL;
-	int i;
+	int diskdev, i, netdev, usedev;
 	struct open_file f;
+	const char * loaderdev;
 
 	if (!api_search_sig(&sig))
 		return (-1);
@@ -167,8 +168,49 @@ main(void)
 	meminfo();
 
 	/*
-	 * March through the device switch probing for things.
+	 * March through the device switch probing for things -- sort of.
+	 *
+	 * The devsw array will have one or two items in it. If
+	 * LOADER_DISK_SUPPORT is defined the first item will be a disk (which
+	 * may not actually work if u-boot didn't supply one). If
+	 * LOADER_NET_SUPPORT is defined the next item will be a network
+	 * interface.  Again it may not actually work at the u-boot level.
+	 *
+	 * The original logic was to always use a disk if it could be
+	 * successfully opened, otherwise use the network interface.  Now that
+	 * logic is amended to first check whether the u-boot environment
+	 * contains a loaderdev variable which tells us which device to use.  If
+	 * it does, we use it and skip the original (second) loop which "probes"
+	 * for a device. We still loop over the devsw just in case it ever gets
+	 * expanded to hold more than 2 devices (but then unit numbers, which
+	 * don't currently exist, may come into play).  If the device named by
+	 * loaderdev isn't found, fall back using to the old "probe" loop.
+	 *
+	 * The original probe loop still effectively behaves as it always has:
+	 * the first usable disk device is choosen, and a network device is used
+	 * only if no disk device is found.  The logic has been reworked so that
+	 * it examines (and thus lists) every potential device along the way
+	 * instead of breaking out of the loop when the first device is found.
 	 */
+	loaderdev = ub_env_get("loaderdev");
+	usedev = -1;
+	if (loaderdev != NULL) {
+		for (i = 0; devsw[i] != NULL; i++) {
+			if (strcmp(loaderdev, devsw[i]->dv_name) == 0) {
+				if (devsw[i]->dv_init == NULL)
+					continue;
+				if ((devsw[i]->dv_init)() != 0)
+					continue;
+				usedev = i;
+				goto have_device;
+			}
+		}
+		printf("U-Boot env contains 'loaderdev=%s', "
+		    "device not found.\n", loaderdev);
+	}
+	printf("Probing for bootable devices...\n");
+	diskdev = -1;
+	netdev = -1;
 	for (i = 0; devsw[i] != NULL; i++) {
 
 		if (devsw[i]->dv_init == NULL)
@@ -176,27 +218,43 @@ main(void)
 		if ((devsw[i]->dv_init)() != 0)
 			continue;
 
-		printf("\nDevice: %s\n", devsw[i]->dv_name);
-
-		currdev.d_dev = devsw[i];
-		currdev.d_type = currdev.d_dev->dv_type;
-		currdev.d_unit = 0;
+		printf("Bootable device: %s\n", devsw[i]->dv_name);
 
 		if (strncmp(devsw[i]->dv_name, "disk",
 		    strlen(devsw[i]->dv_name)) == 0) {
 			f.f_devdata = &currdev;
+			currdev.d_dev = devsw[i];
+			currdev.d_type = currdev.d_dev->dv_type;
+			currdev.d_unit = 0;
 			currdev.d_disk.slice = 0;
-			if (devsw[i]->dv_open(&f,&currdev) == 0)
-				break;
+			if (devsw[i]->dv_open(&f, &currdev) == 0) {
+				devsw[i]->dv_close(&f);
+				if (diskdev == -1)
+					diskdev = i;
+			}
+		} else if (strncmp(devsw[i]->dv_name, "net",
+		    strlen(devsw[i]->dv_name)) == 0) {
+			if (netdev == -1)
+				netdev = i;
 		}
-
-		if (strncmp(devsw[i]->dv_name, "net",
-		    strlen(devsw[i]->dv_name)) == 0)
-			break;
 	}
 
-	if (devsw[i] == NULL)
-		panic("No boot device found!");
+	if (diskdev != -1)
+		usedev = diskdev;
+	else if (netdev != -1)
+		usedev = netdev;
+	else
+		panic("No bootable devices found!\n");
+
+have_device:
+
+	currdev.d_dev = devsw[usedev];
+	currdev.d_type = devsw[usedev]->dv_type;
+	currdev.d_unit = 0;
+	if (currdev.d_type == DEV_TYP_STOR)
+		currdev.d_disk.slice = 0;
+
+	printf("Current device: %s\n", currdev.d_dev->dv_name);
 
 	env_setenv("currdev", EV_VOLATILE, uboot_fmtdev(&currdev),
 	    uboot_setcurrdev, env_nounset);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201402221751.s1MHpAn8070498>