[RFC][PATCH ] Support OFW iSCSI boot over ethernet as a block device.

Doug Maxey dwm at austin.ibm.com
Sat Nov 11 03:46:49 EST 2006


Certain levels of IBM firmware will allow the system to boot from an
iscsi target.  System OFW accomplishes this by setting up a virtual
disk device with parameters.  These parameters, when passed back to
OFW by yaboot, directs the FW to use virtual device over the ethernet
port that will then access iscsi target as a block device.  This patch
extracts those parameters from the property of the virtual device and
passes them back to OFW to indicate the kernel is to be retrieved via
the iscsi protocol.

Signed-off-by: Doug Maxey <dwm at austin.ibm.com>
Cc: Ben Herrenscmidt <benh at kernel.crashing.org>
Cc: Mike Christie <michaelc at cs.wisc.edu>
---
This is a replacement for the previous patches to support iboot on IBM systems.
Please discard the previous version.

++doug
---
commit afcf604b3088d1482e1c463cd0be534d128ad958
tree 3bea4f90edd6984299c6626a42fad386545e0d65
parent 19b1c37ef5cc57f24311a1de997a304714fbfd0e
author Doug Maxey <dwm at bebe.enoyolf.org> Fri, 27 Oct 2006 03:31:32 -0500
committer Doug Maxey <dwm at enoyolf.org> Fri, 10 Nov 2006 10:38:19 -0600

 include/errors.h |    1 +
 include/prom.h   |    2 ++
 second/file.c    |   44 ++++++++++++++++++++++++++++++++++++++------
 second/prom.c    |    3 +++
 second/yaboot.c  |    6 +++---
 5 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/include/errors.h b/include/errors.h
index dfe7e5f..e994dd5 100644
--- a/include/errors.h
+++ b/include/errors.h
@@ -38,3 +38,4 @@ #define FILE_ERR_BADDEV         -12
 /* Device kind */
 #define FILE_DEVICE_BLOCK       1
 #define FILE_DEVICE_NET         2
+#define FILE_DEVICE_ISCSI       3
diff --git a/include/prom.h b/include/prom.h
index 9700803..4bc9159 100644
--- a/include/prom.h
+++ b/include/prom.h
@@ -34,6 +34,8 @@ typedef void *ihandle;
 typedef void *phandle;
 
 #define PROM_INVALID_HANDLE	((prom_handle)-1UL)
+#define BOOTDEVSZ               (2048) /* iscsi args can be in excess of 1040 bytes */
+#define TOK_ISCSI               "iscsi"
 
 struct prom_args;
 typedef int (*prom_entry)(struct prom_args *);
diff --git a/second/file.c b/second/file.c
index 0e58286..4054dd1 100644
--- a/second/file.c
+++ b/second/file.c
@@ -36,7 +36,7 @@ #include "fs.h"
 #include "errors.h"
 #include "debug.h"
 
-extern char bootdevice[1024];
+extern char bootdevice[];
 
 static char *netdev_path_to_filename(const char *path)
 {
@@ -177,7 +177,7 @@ parse_device_path(char *imagepath, char 
      char *ptr;
      char *ipath = NULL;
      char *defdev = NULL;
-     int device_kind;
+     int device_kind = -1;
 
      result->dev = NULL;
      result->part = -1;
@@ -185,16 +185,45 @@ parse_device_path(char *imagepath, char 
 
      if (!imagepath)
 	  return 0;
+
+      /*
+       * Do preliminary checking for an iscsi device; it may appear as
+       * pure a network device (device_type == "network") if this is
+       * ISWI.  This is the case on IBM systems doing an iscsi OFW
+       * boot.
+       */
+     if (strstr(imagepath, TOK_ISCSI)) {
+ 	  /*
+	   * get the virtual device information from the
+	   * "nas-bootdevice" property.
+	   */
+ 	  if (prom_get_chosen("nas-bootdevice", bootdevice, BOOTDEVSZ)) {
+	       DEBUG_F("reset boot-device to"
+		       " /chosen/nas-bootdevice = %s\n", bootdevice);
+	       device_kind = FILE_DEVICE_ISCSI;
+	       ipath = strdup(bootdevice);
+	       if (!ipath)
+		    return 0;
+ 	  }
+ 	  else
+ 	       return 0;
+     }
      else if (!(ipath = strdup(imagepath)))
 	  return 0;
 
      if (defdevice) {
 	  defdev = strdup(defdevice);
 	  device_kind = prom_get_devtype(defdev);
-     } else
+     } else if (device_kind == -1)
 	  device_kind = prom_get_devtype(ipath);
 
-     if (device_kind != FILE_DEVICE_NET && strchr(defdev, ':') != NULL) {
+     /*
+      * When an iscsi iqn is present, it may have embedded colons, so
+      * don't parse off anything.
+      */
+     if (device_kind != FILE_DEVICE_NET &&
+	 device_kind != FILE_DEVICE_ISCSI &&
+	 strchr(defdev, ':') != NULL) {
            if ((ptr = strrchr(defdev, ':')) != NULL)
                 *ptr = 0; /* remove trailing : from defdevice if necessary */
      }
@@ -202,7 +231,9 @@ parse_device_path(char *imagepath, char 
      /* This will not properly handle an obp-tftp argument list
       * with elements after the filename; that is handled below.
       */
-     if (device_kind != FILE_DEVICE_NET && strchr(ipath, ':') != NULL) {
+     if (device_kind != FILE_DEVICE_NET &&
+	 device_kind != FILE_DEVICE_ISCSI &&
+	 strchr(ipath, ':') != NULL) {
 	  if ((ptr = strrchr(ipath, ',')) != NULL) {
 	       char *colon = strrchr(ipath, ':');
 	       /* If a ':' occurs *after* a ',', then we assume that there is
@@ -223,7 +254,8 @@ parse_device_path(char *imagepath, char 
 
 	  if (!defdev)
 	       result->dev = netdev_path_to_dev(ipath);
-     } else if ((ptr = strchr(ipath, ':')) != NULL) {
+     } else if (device_kind != FILE_DEVICE_ISCSI &&
+		(ptr = strrchr(ipath, ':')) != NULL) {
 	  *ptr = 0;
 	  result->dev = strdup(ipath);
 	  if (*(ptr+1))
diff --git a/second/prom.c b/second/prom.c
index 5ec06b8..8cb8a41 100644
--- a/second/prom.c
+++ b/second/prom.c
@@ -174,6 +174,9 @@ prom_get_devtype (char *device)
      int        result;
      char       tmp[64];
 
+     if (strstr(device, TOK_ISCSI))
+	  device = strcpy(tmp, "/vdevice/gscsi/disk");
+
      /* Find OF device phandle */
      dev = prom_finddevice(device);
      if (dev == PROM_INVALID_HANDLE) {
diff --git a/second/yaboot.c b/second/yaboot.c
index d7a3a20..bf10b01 100644
--- a/second/yaboot.c
+++ b/second/yaboot.c
@@ -111,7 +111,7 @@ static void     setup_display(void);
 /* Locals & globals */
 
 int useconf = 0;
-char bootdevice[1024];
+char bootdevice[BOOTDEVSZ];
 char *password = NULL;
 struct boot_fspec_t boot;
 int _machine = _MACH_Pmac;
@@ -1474,10 +1474,10 @@ yaboot_main(void)
      if (_machine == _MACH_Pmac)
 	  setup_display();
 
-     prom_get_chosen("bootpath", bootdevice, sizeof(bootdevice));
+     prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ);
      DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
      if (bootdevice[0] == 0) {
-	  prom_get_options("boot-device", bootdevice, sizeof(bootdevice));
+	  prom_get_options("boot-device", bootdevice, BOOTDEVSZ);
 	  DEBUG_F("boot-device = %s\n", bootdevice);
      }
      if (bootdevice[0] == 0) {





More information about the Yaboot-devel mailing list