Certain levels of IBM firmware will allow the system to boot from an
authorPaul Nasrat <pnasrat@redhat.com>
Fri, 2 Mar 2007 16:26:18 +0000 (16:26 +0000)
committerPaul Nasrat <pauln@enki.eridu>
Fri, 2 Mar 2007 16:26:18 +0000 (16:26 +0000)
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@austin.ibm.com>
Cc: Ben Herrenscmidt <benh@kernel.crashing.org>
Cc: Mike Christie <michaelc@cs.wisc.edu>
include/errors.h
include/prom.h
second/file.c
second/prom.c
second/yaboot.c

index dfe7e5f6b72145efe96724e7c3ab531c085068ad..e994dd571d55dbbc4fe9e8addefa7510aed779da 100644 (file)
@@ -38,3 +38,4 @@
 /* Device kind */
 #define FILE_DEVICE_BLOCK       1
 #define FILE_DEVICE_NET         2
+#define FILE_DEVICE_ISCSI       3
index 97008030d52afbd1aa613b2efd8738bff00c99b0..4bc91597622df219c92fd0423a71f6bf9ff701ca 100644 (file)
@@ -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 *);
index 0e58286e724f1be9c44fd4158cebe21d5e23747c..4054dd18ca24a3746990f3c19bc527a4ee7bfab7 100644 (file)
@@ -36,7 +36,7 @@
 #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 *defdevice, int defpart,
      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 *defdevice, int defpart,
 
      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 *defdevice, int defpart,
      /* 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 *defdevice, int defpart,
 
          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))
index 5ec06b88e7e1426b33e5a04050e4e4c3c607cea3..8cb8a41951a8fc9460d3543a30a46f7acb757a57 100644 (file)
@@ -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) {
index d7a3a20f1c0b0fccca199f4895e983e4d1dbca5e..bf10b01c4db8029c3eaf86b7969576cca8bee6ab 100644 (file)
@@ -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) {