[PATCH 1/2] support netbooting on JS21 GA3 and older firmwares

Scott Moser ssmoser at us.ibm.com
Sat Oct 6 01:07:10 EST 2007


The patch below was originally submitted by Andrew Wray under subject
"Patch to allow netbooting with IBM JS21 GA3 firmware" [1].

I'm re-submitting it with the following description.

  modify of_net_open to add support for recent power openfirmware
  implementations.  This includes JS21 ("GA3" level), JS22, and power6
  hardware.  Newer firmware differs on how the following "load" command is
  handled
     <device>:,<file>
   Previous versions would do a bootp request to get the TCP/IP information
  and then tftp the my_file from the returned siaddr.  Newer versions will
  effectively ignore the '<file>', from the open command and simply download
  whatever file was listed in the bootp response.
  
    These changes break yaboot's of_net_open on networks where the bootp
  server is not the same system as the tftp server.  This is implemented
  by dhcpd's 'next-server' keyword.  This is because the older firmwares were
  really not capable of doing a tftp load.  Ie, the 'boot' command line:
    <device>:<siaddr>,<file>,<ciaddr>
    requires that <siaddr> to be running a bootp server, not simply a tftp
  server.  The above syntax works correctly with new firmwares.

  At the moment we do not expect firmware to change in the future.  In
  order to make network booting work on these systems these changes (or
  similar) will be needed.
--
[1] http://ozlabs.org/pipermail/yaboot-devel/2007-August/000156.html

diff --git a/include/prom.h b/include/prom.h
index f5ee88f..b48e230 100644
--- a/include/prom.h
+++ b/include/prom.h
@@ -154,5 +154,8 @@ struct bootp_packet {
 struct bootp_packet * prom_get_netinfo (void);
 char * prom_get_mac (struct bootp_packet * packet);
 char * prom_get_ip (struct bootp_packet * packet);
+char * prom_get_yiaddr (struct bootp_packet * packet);
+char * prom_get_siaddr (struct bootp_packet * packet);
+char * prom_get_giaddr (struct bootp_packet * packet);
 
 #endif
diff --git a/second/fs_of.c b/second/fs_of.c
index 76474ee..a9404f6 100644
--- a/second/fs_of.c
+++ b/second/fs_of.c
@@ -138,18 +138,29 @@ of_net_open(struct boot_file_t* file, const char* dev_name,
      static char	buffer[1024];
      char               *filename;
      char               *p;
+     struct bootp_packet *packet;
 
      DEBUG_ENTER;
      DEBUG_OPEN;
 
+     packet = prom_get_netinfo();
+
      strncpy(buffer, dev_name, 768);
      if (file_name && strlen(file_name)) {
+	  strcat(buffer, prom_get_siaddr(packet));
 	  strcat(buffer, ",");
 	  filename = strdup(file_name);
 	  for (p = filename; *p; p++)
 	       if (*p == '/')
 		    *p = '\\';
 	  strcat(buffer, filename);
+	  strcat(buffer, ",");
+	  strcat(buffer, prom_get_yiaddr(packet));
+	  strcat(buffer, ",");
+	  /* Hack required since giaddr not returned on some systems
+	     and required to boot on those systems.  This should work
+	     for the client and server on the same subnet. */
+	  strcat(buffer, prom_get_siaddr(packet));
 	  free(filename);
      }
 
diff --git a/second/prom.c b/second/prom.c
index e9c5843..bd2451e 100644
--- a/second/prom.c
+++ b/second/prom.c
@@ -752,6 +752,78 @@ char * prom_get_ip (struct bootp_packet * packet)
 }
 
 /*
+ * prom_get_yiaddr()
+ * returns the ip addr of the client in dotted decimal format
+ */
+char * prom_get_yiaddr (struct bootp_packet * packet)
+{
+     char * conf_path;
+
+     if (!packet)
+        return NULL;
+
+     /* 15 chars in yiaddr + \0 */
+     conf_path = malloc(16);
+     if (!conf_path)
+         return NULL;
+     sprintf(conf_path, "%d.%d.%d.%d",
+         packet->yiaddr >> 24,
+         (packet->yiaddr << 8) >> 24,
+         (packet->yiaddr << 16) >> 24,
+         (packet->yiaddr << 24) >> 24);
+
+     return conf_path;
+}
+
+/*
+ * prom_get_siaddr()
+ * returns the ip addr of the server in dotted decimal format
+ */
+char * prom_get_siaddr (struct bootp_packet * packet)
+{
+     char * conf_path;
+
+     if (!packet)
+        return NULL;
+
+     /* 15 chars in siaddr + \0 */
+     conf_path = malloc(16);
+     if (!conf_path)
+         return NULL;
+     sprintf(conf_path, "%d.%d.%d.%d",
+         packet->siaddr >> 24,
+         (packet->siaddr << 8) >> 24,
+         (packet->siaddr << 16) >> 24,
+         (packet->siaddr << 24) >> 24);
+
+     return conf_path;
+}
+
+/*
+ * prom_get_giaddr()
+ * returns the ip addr of the gateway in dotted decimal format
+ */
+char * prom_get_giaddr (struct bootp_packet * packet)
+{
+     char * conf_path;
+
+     if (!packet)
+        return NULL;
+
+     /* 15 chars in giaddr + \0 */
+     conf_path = malloc(16);
+     if (!conf_path)
+         return NULL;
+     sprintf(conf_path, "%d.%d.%d.%d",
+         packet->giaddr >> 24,
+         (packet->giaddr << 8) >> 24,
+         (packet->giaddr << 16) >> 24,
+         (packet->giaddr << 24) >> 24);
+
+     return conf_path;
+}
+
+/*
  * Local variables:
  * c-file-style: "k&r"
  * c-basic-offset: 5




More information about the Yaboot-devel mailing list