diff -urN yaboot-1.3.14/include/prom.h yaboot-1.3.14-fixes/include/prom.h
--- yaboot-1.3.14/include/prom.h	2007-08-17 10:29:26.000000000 -0400
+++ yaboot-1.3.14-fixes/include/prom.h	2008-05-05 13:40:11.000000000 -0400
@@ -37,6 +37,9 @@
 #define PROM_INVALID_HANDLE	((prom_handle)-1UL)
 #define BOOTDEVSZ               (2048) /* iscsi args can be in excess of 1040 bytes */
 #define TOK_ISCSI               "iscsi"
+#define PROM_CLAIM_MAX_ADDR	0x8000000
+#define BOOTLASTSZ		1024
+#define FW_NBR_REBOOTSZ		4
 
 struct prom_args;
 typedef int (*prom_entry)(struct prom_args *);
@@ -85,6 +88,7 @@
 
 /* memory */
 
+void *prom_claim_chunk(void *virt, unsigned int size, unsigned int align);
 void *prom_claim (void *virt, unsigned int size, unsigned int align);
 void prom_release(void *virt, unsigned int size);
 void prom_map (void *phys, void *virt, int size);
@@ -154,5 +158,8 @@
 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 -urN yaboot-1.3.14/second/fs_of.c yaboot-1.3.14-fixes/second/fs_of.c
--- yaboot-1.3.14/second/fs_of.c	2007-08-17 10:29:26.000000000 -0400
+++ yaboot-1.3.14-fixes/second/fs_of.c	2008-05-05 13:41:53.000000000 -0400
@@ -44,9 +44,8 @@
 #include "errors.h"
 #include "debug.h"
 
-#define LOAD_BUFFER_POS		0x600000
-/* this cannot be safely increased any further */
-#define LOAD_BUFFER_SIZE	0x600000
+#define LOAD_BUFFER_POS		0x1000000
+#define LOAD_BUFFER_SIZE	0x1000000
 
 static int of_open(struct boot_file_t* file, const char* dev_name,
 		   struct partition_t* part, const char* file_name);
@@ -60,6 +59,8 @@
 static int of_net_read(struct boot_file_t* file, unsigned int size, void* buffer);
 static int of_net_seek(struct boot_file_t* file, unsigned int newpos);
 
+static int of_supports_real_tftp(void);
+static int of_net_use_tftp = -1;
 
 struct fs_t of_filesystem =
 {
@@ -131,6 +132,34 @@
      return FILE_ERR_OK;
 }
 
+/* 
+ *  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 with new firmwares.
+ *
+ *  This function should return 1 if the running firmware fully supports
+ *  tftp and 0 if not.
+ */
+static int of_supports_real_tftp() {
+   of_net_use_tftp=1;
+   return(of_net_use_tftp);
+/*
+     prom_handle h;
+     if(of_net_use_tftp>=0) return(of_net_use_tftp);
+
+     h=prom_open("/packages/cas");
+     if(h) {
+          prom_close(h);
+          of_net_use_tftp=1;
+     } else {
+          of_net_use_tftp=0;
+     }
+     return(of_net_use_tftp);
+*/
+}
+
+
 static int
 of_net_open(struct boot_file_t* file, const char* dev_name,
 	    struct partition_t* part, const char* file_name)
@@ -138,18 +167,34 @@
      static char	buffer[1024];
      char               *filename;
      char               *p;
+     struct bootp_packet *packet;
 
      DEBUG_ENTER;
      DEBUG_OPEN;
 
+
      strncpy(buffer, dev_name, 768);
      if (file_name && strlen(file_name)) {
+       if(of_supports_real_tftp()){
+          packet = prom_get_netinfo();
+	     strcat(buffer, prom_get_siaddr(packet));
+       }
 	  strcat(buffer, ",");
 	  filename = strdup(file_name);
 	  for (p = filename; *p; p++)
 	       if (*p == '/')
 		    *p = '\\';
 	  strcat(buffer, filename);
+       if(of_supports_real_tftp()) {
+	     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));
+       }
+       strcat(buffer,",,100");
 	  free(filename);
      }
 
@@ -166,7 +211,9 @@
 	  return FILE_ERR_BAD_FSYS;
      }
 
-     file->buffer = prom_claim((void *)LOAD_BUFFER_POS, LOAD_BUFFER_SIZE, 0);
+
+     file->buffer = prom_claim_chunk((void *)LOAD_BUFFER_POS,
+                                     LOAD_BUFFER_SIZE, 0);
      if (file->buffer == (void *)-1) {
 	  prom_printf("Can't claim memory for TFTP download\n");
 	  prom_close(file->of_device);
diff -urN yaboot-1.3.14/second/prom.c yaboot-1.3.14-fixes/second/prom.c
--- yaboot-1.3.14/second/prom.c	2007-08-17 10:29:26.000000000 -0400
+++ yaboot-1.3.14-fixes/second/prom.c	2008-05-05 13:40:11.000000000 -0400
@@ -568,6 +568,25 @@
      while (prom_getms() <= end);
 }
 
+/* if address given is claimed look for other addresses to get the needed
+ * space before giving up
+ */
+void *
+prom_claim_chunk(void *virt, unsigned int size, unsigned int align)
+{
+     void *found, *addr;
+     for(addr=virt; addr <= (void*)PROM_CLAIM_MAX_ADDR;
+         addr+=(0x100000/sizeof(addr))) {
+          found = prom_claim(addr, size, 0);
+          if (found != (void *)-1) {
+               DEBUG_F("claimed %i at 0x%x (0x%x)\n",size,(int)found,(int)virt);
+               return(found);
+          }
+     }
+     prom_printf("Claim error, can't allocate %x at 0x%x\n",size,(int)virt);
+     return((void*)-1);
+}
+
 void *
 prom_claim (void *virt, unsigned int size, unsigned int align)
 {
@@ -752,6 +771,78 @@
 }
 
 /*
+ * 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
diff -urN yaboot-1.3.14/second/yaboot.c yaboot-1.3.14-fixes/second/yaboot.c
--- yaboot-1.3.14/second/yaboot.c	2007-08-17 10:29:26.000000000 -0400
+++ yaboot-1.3.14-fixes/second/yaboot.c	2008-05-05 13:43:48.000000000 -0400
@@ -114,6 +114,9 @@
 char bootdevice[BOOTDEVSZ];
 char bootoncelabel[1024];
 char bootargs[1024];
+char bootlastlabel[BOOTLASTSZ] = {0};
+char fw_nbr_reboots[FW_NBR_REBOOTSZ] = {0};
+long  fw_reboot_cnt = 0;
 char *password = NULL;
 struct boot_fspec_t boot;
 int _machine = _MACH_Pmac;
@@ -471,12 +474,13 @@
      if (!fspec.file)
 	  goto out;
 
-     sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype);
+     /* sprintf(fspec.file, "%s%02x-", cfgpath, packet->htype);
      strcat(fspec.file, prom_get_mac(packet));
 
      rc = load_config_file(&fspec);
      if (rc)
 	  goto out;
+     */
 
      /*
       * Now try to match on IP.
@@ -665,7 +669,7 @@
 
      cmdinit();
 
-     if (first) {
+     if (first && !fw_reboot_cnt) {
 	  first = 0;
 	  imagename = bootargs;
 	  word_split(&imagename, &params->args);
@@ -680,6 +684,13 @@
 	       timeout = simple_strtol(q, NULL, 0);
      }
 
+     /* If this is a reboot due to FW detecting CAS changes then 
+      * set timeout to 1.  The last kernel booted will be booted 
+      * again automatically.  It should seem seamless to the user
+     */
+     if (fw_reboot_cnt) 
+          timeout = 1;
+
      prom_printf("boot: ");
      c = -1;
      if (timeout != -1) {
@@ -716,7 +727,9 @@
 	  if (!imagename) {
 	       if (bootoncelabel[0] != 0)
 		    imagename = bootoncelabel;
-	       else
+	       else if (bootlastlabel[0] != 0)
+                         imagename = bootlastlabel;
+               else
 		    imagename = cfg_get_default();
 	  }
 	  if (imagename)
@@ -737,6 +750,9 @@
      if ( useconf && (!imagename || imagename[0] == 0 ))
 	  imagename = cfg_get_default();
 
+     /* write the imagename out so it can be reused on reboot if necessary */
+     prom_set_options("boot-last-label", imagename, strlen(imagename));
+
      label = 0;
      defdevice = boot.dev;
 
@@ -1233,7 +1249,7 @@
      Elf32_Ehdr		*e = &(loadinfo->elf.elf32hdr);
      Elf32_Phdr		*p, *ph;
      int			size = sizeof(Elf32_Ehdr) - sizeof(Elf_Ident);
-     unsigned long	addr, loadaddr;
+     unsigned long	loadaddr;
 
      /* Read the rest of the Elf header... */
      if ((*(file->fs->read))(file, size, &e->e_version) < size) {
@@ -1321,13 +1337,7 @@
           loadaddr = loadinfo->load_loc;
      }
 
-     /* On some systems, loadaddr may already be claimed, so try some
-      * other nearby addresses before giving up.
-      */
-     for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
-	  loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
-	  if (loadinfo->base != (void *)-1) break;
-     }
+     loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
      if (loadinfo->base == (void *)-1) {
 	  prom_printf("Claim error, can't allocate kernel memory\n");
 	  goto bail;
@@ -1377,7 +1387,7 @@
      Elf64_Ehdr		*e = &(loadinfo->elf.elf64hdr);
      Elf64_Phdr		*p, *ph;
      int			size = sizeof(Elf64_Ehdr) - sizeof(Elf_Ident);
-     unsigned long	addr, loadaddr;
+     unsigned long	loadaddr;
 
      /* Read the rest of the Elf header... */
      if ((*(file->fs->read))(file, size, &e->e_version) < size) {
@@ -1465,13 +1475,7 @@
           loadaddr = e->e_entry;
      }
 
-     /* On some systems, loadaddr may already be claimed, so try some
-      * other nearby addresses before giving up.
-      */
-     for(addr=loadaddr; addr <= loadaddr * 8 ;addr+=0x100000) {
-	  loadinfo->base = prom_claim((void *)addr, loadinfo->memsize, 0);
-	  if (loadinfo->base != (void *)-1) break;
-     }
+     loadinfo->base = prom_claim_chunk((void *)loadaddr, loadinfo->memsize, 0);
      if (loadinfo->base == (void *)-1) {
 	  prom_printf("Claim error, can't allocate kernel memory\n");
 	  goto bail;
@@ -1625,8 +1629,10 @@
 yaboot_main(void)
 {
      char *ptype;
+     char *endp;
      int conf_given = 0;
      char conf_path[1024];
+     int ret;
 
      if (_machine == _MACH_Pmac)
 	  setup_display();
@@ -1635,6 +1641,11 @@
      DEBUG_F("/chosen/bootargs = %s\n", bootargs);
      prom_get_chosen("bootpath", bootdevice, BOOTDEVSZ);
      DEBUG_F("/chosen/bootpath = %s\n", bootdevice);
+     if (prom_get_options("ibm,#reconfig-reboots",fw_nbr_reboots, FW_NBR_REBOOTSZ) == -1 )
+        prom_get_options("ibm,fw-nbr-reboots",fw_nbr_reboots, FW_NBR_REBOOTSZ);
+     fw_reboot_cnt = simple_strtol(fw_nbr_reboots,&endp,10);
+     if (fw_reboot_cnt > 0L)
+          prom_get_options("boot-last-label", bootlastlabel, BOOTLASTSZ);
 
      /* If conf= specified on command line, it overrides
         Usage: conf=device:partition,/path/to/conffile
