Patchwork Power 6 netboot bug/testing

login
register
mail settings
Submitter Manoel
Date Oct. 6, 2008, 8:31 p.m.
Message ID <1223325064.6495.48.camel@manoel-laptop>
Download mbox | patch
Permalink /patch/22977/
State Not Applicable
Headers show

Comments

Manoel - Oct. 6, 2008, 8:31 p.m.
I have done a patch (file attached) to solve the bug described in:
https://bugzilla.redhat.com/show_bug.cgi?id=458438. 

In recent OpenFirmware versions the property "bootpreply-packet" was
replaced by the newer "bootp-response". It contains only the bootp
packet, excluding the encapsulating UDP, IP, and link-layer headers and
trailers that were in the earlier structure. This new Extension
introduced some problems to DHCP environments, which does not correctly
build the tftp request when a discrete file is specified. Due to this 
change on the packet sent, the yaboot fails to boot through network. 

This patch basically works by identifying the OpenFirmare version and
constructing the buffer in the format necessary for it. It was tested in
both older P5 and newer P6 machine OpenFirmware versions and was able to
boot correctly.  

I'm assuming that Chandras' Patches has been applied into git HEAD,
because I'm using some structures purposed by him. I'd like your
opinions and suggestions regarding this patch.


Best Regards,

Manoel Abranches <mrabran@linux.vnet.ibm.com>
IBM Linux Technology Center Brasil

[1] http://pastebin.zurich.ibm.com/mef77758
[2] http://pastebin.zurich.ibm.com/m7b7ba2b5
Manoel - Oct. 7, 2008, 4:35 p.m.
Sorry, I have used a internal pastebin. 
There is the correct reference links.

[1]http://pastebin.com/m345ca7b  --  booting in a P5 machine
[2]http://pastebin.com/m5ce9fe97 --  booting in a P6 machine

Manoel Abranches <mrabran@linux.vnet.ibm.com
IBM Linux Technology Center Brasil

On Mon, 2008-10-06 at 17:31 -0300, Manoel wrote:
> I have done a patch (file attached) to solve the bug described in:
> https://bugzilla.redhat.com/show_bug.cgi?id=458438. 
> 
> In recent OpenFirmware versions the property "bootpreply-packet" was
> replaced by the newer "bootp-response". It contains only the bootp
> packet, excluding the encapsulating UDP, IP, and link-layer headers and
> trailers that were in the earlier structure. This new Extension
> introduced some problems to DHCP environments, which does not correctly
> build the tftp request when a discrete file is specified. Due to this 
> change on the packet sent, the yaboot fails to boot through network. 
> 
> This patch basically works by identifying the OpenFirmare version and
> constructing the buffer in the format necessary for it. It was tested in
> both older P5 and newer P6 machine OpenFirmware versions and was able to
> boot correctly.  
> 
> I'm assuming that Chandras' Patches has been applied into git HEAD,
> because I'm using some structures purposed by him. I'd like your
> opinions and suggestions regarding this patch.
> 
> 
> Best Regards,
> 
> Manoel Abranches <mrabran@linux.vnet.ibm.com>
> IBM Linux Technology Center Brasil
> 
> [1] http://pastebin.zurich.ibm.com/mef77758
> [2] http://pastebin.zurich.ibm.com/m7b7ba2b5
> 
> _______________________________________________
> Yaboot-devel mailing list
> Yaboot-devel@ozlabs.org
> https://ozlabs.org/mailman/listinfo/yaboot-devel

Patch

diff -Naurp yaboot/include/file.h yaboot.new//include/file.h
--- yaboot/include/file.h	2008-10-02 10:03:07.000000000 -0300
+++ yaboot.new//include/file.h	2008-10-06 10:58:22.000000000 -0300
@@ -42,6 +42,7 @@  struct boot_fspec_t {
 	char*	siaddr;		/* Server address */
 	char*	file;		/* File path */
 	char*	ciaddr;		/* Client address */
+	char*   yiaddr;          /* Client address filled in by server*/
 	char*	giaddr;		/* Gateway address */
 	char*	bootp_retries;	/* Bootp retries */
 	char*	tftp_retries;	/* TFTP retries */
@@ -81,5 +82,6 @@  extern int
 parse_device_path(char *imagepath, char *defdevice, int defpart,
 		  char *deffile, struct boot_fspec_t *result);
 
+int bootp_to_fspec(struct bootp_packet *,struct boot_fspec_t *);
 
 #endif
diff -Naurp yaboot/second/file.c yaboot.new//second/file.c
--- yaboot/second/file.c	2008-10-02 10:03:07.000000000 -0300
+++ yaboot.new//second/file.c	2008-10-06 16:16:18.000000000 -0300
@@ -61,6 +61,40 @@  scopy(char **dest, char **source)
      return ret;
 }
 
+#define IPLEN 16
+/*Return ip in xxx.xxx.xxx.xxx string format*/
+
+static char * ipv4_to_str( u32 ip)
+{
+     char * buf = malloc(IPLEN);
+     sprintf(buf,"%u.%u.%u.%u",
+          (ip & 0xff000000) >> 24,
+          (ip & 0x00ff0000) >> 16,
+          (ip & 0x0000ff00) >> 8,
+          (ip & 0x000000ff));
+     return buf;
+}
+
+/*Puts the IP information on boot_packet struct in boot_fspec_t struct
+ * return 1 in success and 0 on fail*/
+int bootp_to_fspec(struct bootp_packet *packet,struct boot_fspec_t *fspec){
+
+     if (packet == NULL || fspec == NULL)
+          return 0;
+       	
+     fspec->siaddr=ipv4_to_str(packet->siaddr);
+     fspec->ciaddr=ipv4_to_str(packet->ciaddr);
+     fspec->giaddr=ipv4_to_str(packet->giaddr);
+     fspec->yiaddr=ipv4_to_str(packet->yiaddr);
+     DEBUG_F("siaddr = <%s>\n",fspec->siaddr);
+     DEBUG_F("ciaddr = <%s>\n",fspec->ciaddr);
+     DEBUG_F("giaddr = <%s>\n",fspec->giaddr);
+     DEBUG_F("yiaddr = <%s>\n",fspec->yiaddr);
+
+     return 1;
+}
+
+
 /*
  * Extract all the ipv4 arguments from the bootpath provided and fill result
  * Returns 1 on success, 0 on failure.
diff -Naurp yaboot/second/fs_of.c yaboot.new//second/fs_of.c
--- yaboot/second/fs_of.c	2008-10-02 10:03:07.000000000 -0300
+++ yaboot.new//second/fs_of.c	2008-10-06 12:26:43.000000000 -0300
@@ -46,7 +46,7 @@ 
 
 #define LOAD_BUFFER_POS		0x00000000
 #define LOAD_BUFFER_SIZE	0x01000000
-
+extern int net_type;
 static int of_open(struct boot_file_t* file,
 		   struct partition_t* part, struct boot_fspec_t* fspec);
 static int of_read(struct boot_file_t* file, unsigned int size, void* buffer);
@@ -137,38 +137,58 @@  of_net_open(struct boot_file_t* file,
      static char	buffer[1024];
      char               *filename = NULL;
      char               *p;
-
+     struct bootp_packet *packet;
      DEBUG_ENTER;
      DEBUG_OPEN;
+/*Newer IBM firmware needs the server ip, client ip and the desired file to be 
+ * set in the buffer, thus broken previus Yaboot network boot.
+ *
+ * The format is <device>:<interfaceoption,interfaceoption,>tftpserver,filename,client,gateway,bootp-retry,tftp-retry,netmask,tftp-blocksize
+ */
+
+     if (net_type){//Use new firmware network interface
+          packet = prom_get_netinfo();
+          if(packet)
+               bootp_to_fspec(packet,fspec);
+     }else
+	     strcpy(fspec->yiaddr,fspec->ciaddr);
 
+     
      if (fspec->file && strlen(fspec->file)) {
 	  filename = strdup(fspec->file);
 	  for (p = filename; *p; p++)
 	       if (*p == '/')
 		    *p = '\\';
      }
-
+     
      DEBUG_F("siaddr <%s>; filename <%s>; ciaddr <%s>; giaddr <%s>; ipv6 <%d>\n",
 		fspec->siaddr, filename, fspec->ciaddr, fspec->giaddr, fspec->is_ipv6);
-     strncpy(buffer, fspec->dev, 768);
-     if (fspec->is_ipv6)
-	  strcat(buffer, TOK_IPV6 ",");
-     strcat(buffer, fspec->siaddr);
-     strcat(buffer, ",");
-     if (fspec->is_ipv6 && (strstr(filename, "filename=") == NULL))
-	  strcat(buffer, "filename=");
-     strcat(buffer, filename);
-     strcat(buffer, ",");
-     strcat(buffer, fspec->ciaddr);
-     strcat(buffer, ",");
-     strcat(buffer, fspec->giaddr);
-     strcat(buffer, ",");
-     strcat(buffer, fspec->bootp_retries);
-     strcat(buffer, ",");
-     strcat(buffer, fspec->tftp_retries);
-     strcat(buffer, ",");
-     strcat(buffer, fspec->addl_params);
-
+     if(net_type){
+          strncpy(buffer, fspec->dev, 768);
+          if (fspec->is_ipv6)
+               strcat(buffer, TOK_IPV6 ",");
+          strcat(buffer, fspec->siaddr);
+          strcat(buffer, ",");
+          if (fspec->is_ipv6 && (strstr(filename, "filename=") == NULL))
+               strcat(buffer, "filename=");
+          strcat(buffer, filename);
+          strcat(buffer, ",");
+          strcat(buffer, fspec->yiaddr);
+          strcat(buffer, ",");
+          strcat(buffer, fspec->giaddr);
+          strcat(buffer, ",");
+          strcat(buffer, fspec->bootp_retries);
+          strcat(buffer, ",");
+          strcat(buffer, fspec->tftp_retries);
+          strcat(buffer, ",");
+          strcat(buffer, fspec->addl_params);
+     }
+     else{
+     
+          strncpy(buffer, fspec->dev, (int)strchr(fspec->dev,':'));
+          strcat(buffer, ",");
+          strcat(buffer, filename);
+     }
      DEBUG_F("Opening: \"%s\"\n", buffer);
 
      file->of_device = prom_open(buffer);
diff -Naurp yaboot/second/yaboot.c yaboot.new//second/yaboot.c
--- yaboot/second/yaboot.c	2008-10-02 10:03:07.000000000 -0300
+++ yaboot.new//second/yaboot.c	2008-10-06 10:40:19.000000000 -0300
@@ -121,7 +121,7 @@  char *password = NULL;
 struct boot_fspec_t boot;
 int _machine = _MACH_Pmac;
 int flat_vmlinux;
-
+int net_type = 0;//type of net interface
 #ifdef CONFIG_COLOR_TEXT
 
 /* Color values for text ui */
@@ -183,7 +183,7 @@  yaboot_start (unsigned long r3, unsigned
      void* malloc_base = NULL;
      unsigned long addr;
      prom_handle root;
-
+     ihandle promnet;
      /* OF seems to do it, but I'm not very confident */
      memset(&__bss_start, 0, &_end - &__bss_start);
 
@@ -237,6 +237,11 @@  yaboot_start (unsigned long r3, unsigned
 		   !strncmp(model, "IBM", 3))
 		    _machine = _MACH_chrp;
 	  }
+
+	if (prom_getprop(root, "ibm,fw-net-compatibility",&promnet, sizeof(ihandle)) > 0)
+		net_type = 1;
+
+
      }
 
      DEBUG_F("Running on _machine = %d\n", _machine);
@@ -469,7 +474,8 @@  static int load_my_config_file(struct bo
      char *cfgpath = (_machine == _MACH_chrp || _machine == _MACH_bplan) ? "/etc/" : "";
      int flen;
      int minlen;
-
+     char *macaddress; 
+     
      packet = prom_get_netinfo();
      if (!packet)
 	  return rc;
@@ -483,10 +489,16 @@  static int load_my_config_file(struct bo
      fspec.file = malloc(packet->hlen * 3 + 2 + 6);
      if (!fspec.file)
 	  goto out;
-
-     sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype);
-     strcat(fspec.file, prom_get_mac(packet));
-
+     
+     if (net_type){
+          macaddress = prom_get_mac(packet);
+          fspec.file = malloc(strlen(CONFIG_FILE_NAME) + strlen(macaddress) + 1 );	  
+          sprintf(fspec.file,"%s-%s" ,CONFIG_FILE_NAME,macaddress);// bootp_to_fspec(packet,fspec);
+    } 
+    else{
+          sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype);
+          strcat(fspec.file, prom_get_mac(packet));
+    }
      rc = load_config_file(&fspec);
      if (rc)
 	  goto out;