Be explicit in order of evaluation in the reiserfs code
[yaboot.git] / second / yaboot.c
index 0232d33153b58da3c9c0fafecde8016437324f17..1f3f1518845aa67b0a81847f226a775a2ea9c34d 100644 (file)
@@ -58,6 +58,8 @@
 #define CONFIG_FILE_NAME       "yaboot.conf"
 #define CONFIG_FILE_MAX                0x8000          /* 32k */
 
+#define MESSAGE_FILE_MAX       2048
+
 #ifdef USE_MD5_PASSWORDS
 #include "md5.h"
 #endif /* USE_MD5_PASSWORDS */
@@ -114,6 +116,9 @@ int useconf = 0;
 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;
@@ -151,10 +156,6 @@ int fgcolor = 15;
 int bgcolor = 0;
 #endif /* CONFIG_COLOR_TEXT */
 
-#if DEBUG
-static int test_bss;
-static int test_data = 0;
-#endif
 static int pause_after;
 static char *pause_message = "Type go<return> to continue.\n";
 static char given_bootargs[1024];
@@ -166,13 +167,6 @@ extern unsigned char linux_logo_blue[];
 
 #define DEFAULT_TIMEOUT                -1
 
-/* Entry, currently called directly by crt0 (bss not inited) */
-
-extern char* __bss_start;
-extern char* _end;
-
-static struct first_info *quik_fip = NULL;
-
 int
 yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
 {
@@ -180,26 +174,16 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
      void* malloc_base = NULL;
      prom_handle root;
 
-     /* OF seems to do it, but I'm not very confident */
-     memset(&__bss_start, 0, &_end - &__bss_start);
-
-     /* Check for quik first stage bootloader (but I don't think we are
-      * compatible with it anyway, I'll look into backporting to older OF
-      * versions later
-      */
-     if (r5 == 0xdeadbeef) {
-         r5 = r3;
-         quik_fip = (struct first_info *)r4;
-     }
-
      /* Initialize OF interface */
      prom_init ((prom_entry) r5);
 
+     prom_print_available();
+
      /* Allocate some memory for malloc'ator */
-     malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
+     malloc_base = prom_claim_chunk_top(MALLOCSIZE, 0);
      if (malloc_base == (void *)-1) {
-         prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
-                     MALLOCSIZE, MALLOCADDR);
+         prom_printf("Can't claim malloc buffer of %d bytes\n",
+                     MALLOCSIZE);
          return -1;
      }
      malloc_init(malloc_base, MALLOCSIZE);
@@ -208,10 +192,6 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
 
      /* A few useless DEBUG_F's */
      DEBUG_F("reloc_offset :  %ld         (should be 0)\n", reloc_offset());
-     DEBUG_F("test_bss     :  %d         (should be 0)\n", test_bss);
-     DEBUG_F("test_data    :  %d         (should be 0)\n", test_data);
-     DEBUG_F("&test_data   :  %p\n", &test_data);
-     DEBUG_F("&test_bss    :  %p\n", &test_bss);
      DEBUG_F("linked at    :  0x%08x\n", TEXTADDR);
 
      /* ask the OF info if we're a chrp or pmac */
@@ -219,7 +199,10 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
      root = prom_finddevice("/");
      if (root != 0) {
          static char model[256];
-         if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
+         if (prom_getprop(root, "CODEGEN,vendor", model, 256) > 0 &&
+             !strncmp("bplan", model, 5))
+              _machine = _MACH_bplan;
+         else if (prom_getprop(root, "device_type", model, 256 ) > 0 &&
              !strncmp("chrp", model, 4))
               _machine = _MACH_chrp;
          else {
@@ -290,6 +273,7 @@ void print_message_file(char *filename)
          }
 
      strncpy(msgpath, filename, sizeof(msgpath));
+     msgfile = boot; /* Copy all the original paramters */
      if (!parse_device_path(msgpath, defdev, defpart, "/etc/yaboot.msg", &msgfile)) {
          prom_printf("%s: Unable to parse\n", msgpath);
          goto done;
@@ -303,13 +287,13 @@ void print_message_file(char *filename)
      } else
          opened = 1;
 
-     msg = malloc(2001);
+     msg = malloc(MESSAGE_FILE_MAX + 1);
      if (!msg)
          goto done;
      else
-         memset(msg, 0, 2001);
+         memset(msg, 0, MESSAGE_FILE_MAX + 1);
 
-     if (file.fs->read(&file, 2000, msg) <= 0)
+     if (file.fs->read(&file, MESSAGE_FILE_MAX, msg) <= 0)
          goto done;
      else
          prom_printf("%s", msg);
@@ -455,11 +439,13 @@ static int load_my_config_file(struct boot_fspec_t *orig_fspec)
      struct bootp_packet *packet;
      int rc = 0;
      struct boot_fspec_t fspec = *orig_fspec;
-     char *cfgpath = (_machine == _MACH_chrp) ? "/etc/" : "";
+     char *cfgpath = (_machine == _MACH_chrp || _machine == _MACH_bplan) ? "/etc/" : "";
      int flen;
      int minlen;
 
      packet = prom_get_netinfo();
+     if (!packet)
+          goto out;
 
      /*
       * First, try to match on mac address with the hardware type
@@ -653,19 +639,19 @@ int get_params(struct boot_param_t* params)
      static int first = 1;
      static char imagepath[1024];
      static char initrdpath[1024];
-     static char sysmappath[1024];
+     static char manualinitrd[1024];
+     static int definitrd = 1, hasarg = 0;
 
      pause_after = 0;
      memset(params, 0, sizeof(*params));
      params->args = "";
      params->kernel.part = -1;
      params->rd.part = -1;
-     params->sysmap.part = -1;
      defpart = boot.part;
 
      cmdinit();
 
-     if (first) {
+     if (first && !fw_reboot_cnt) {
          first = 0;
          imagename = bootargs;
          word_split(&imagename, &params->args);
@@ -680,6 +666,13 @@ int get_params(struct boot_param_t* params)
               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 +709,10 @@ int get_params(struct boot_param_t* params)
          if (!imagename) {
               if (bootoncelabel[0] != 0)
                    imagename = bootoncelabel;
-              else
+              else if (bootlastlabel[0] != 0) {
+                   imagename = bootlastlabel;
+                   word_split(&imagename, &params->args);
+              } else
                    imagename = cfg_get_default();
          }
          if (imagename)
@@ -733,10 +729,59 @@ int get_params(struct boot_param_t* params)
          word_split(&imagename, &params->args);
      }
 
+     /* initrd setup via cmd console */
+     /* first, check if the user uses it with some label */
+     if (!strncmp(params->args, "initrd=", 7)) {
+         DEBUG_F("params->args: %s\n", params->args);
+         definitrd = 0;
+     }
+     /* after, check if there is the 'initrd=' in the imagename string */
+     if (!strncmp(imagename, "initrd=", 7) || !definitrd) {
+
+         /* return the value of definitrd to 1 */
+         if (!definitrd)
+             definitrd = 1;
+
+         /* args = "initrd=blah" */
+         char *args = NULL;
+
+         if (params->args) {
+            args = params->args;
+            params->args = NULL;
+            hasarg = 1;
+         } else
+            args = imagename;
+
+         if (strlen(args)){
+             /* copy the string after the '=' to manualinitrd */
+             strcpy(manualinitrd, args+7);
+             definitrd = 0;
+             prom_printf("New initrd file specified: %s\n", manualinitrd);
+         } else {
+             prom_printf("ERROR: no initrd specified!\n");
+             return 0;
+         }
+
+         /* set imagename with the default values of the config file */
+         if ((prom_get_devtype(boot.dev) == FILE_DEVICE_NET) && !hasarg)
+             imagename = cfg_get_default();
+         else
+             imagename = cfg_get_default();
+     }
+
      /* chrp gets this wrong, force it -- Cort */
      if ( useconf && (!imagename || imagename[0] == 0 ))
          imagename = cfg_get_default();
 
+     /* write the imagename out so it can be reused on reboot if necessary */
+     strcpy(bootlastlabel, imagename);
+     if (params->args && params->args[0]) {
+         strcat(bootlastlabel, " ");
+         strcat(bootlastlabel, params->args);
+     }
+     prom_set_options("boot-last-label", bootlastlabel,
+                     strlen(bootlastlabel) + 1);
+
      label = 0;
      defdevice = boot.dev;
 
@@ -794,6 +839,12 @@ int get_params(struct boot_param_t* params)
               "resides on, and \"partno\" is the partition number the image resides on.\n"
               "Note that the comma (,) is only required if you specify an OpenFirmware\n"
               "device, if you only specify a filename you should not start it with a \",\"\n\n"
+           "To boot a alternative initrd file rather than specified in the yaboot\n"
+           "configuration file, use the \"initrd\" command on Yaboot's prompt: \n"
+           "\"initrd=[name.img]\". This will load the \"name.img\" file after the default\n"
+           "kernel image. You can, also, specify a different initrd file to any other\n"
+           "label of the yaboot configuration file. Just type \"label initrd=[name.img]\"\n"
+           "and the specified initrd file will be loaded.\n\n"
               "To load an alternative config file rather than /etc/yaboot.conf, enter\n"
               "its device, partno and path, on Open Firmware Prompt:\n"
               "boot conf=device:partno,/path/to/configfile\n."
@@ -918,35 +969,35 @@ int get_params(struct boot_param_t* params)
      if (!label && password)
          check_password ("To boot a custom image you must enter the password.");
 
+     params->kernel = boot; /* Copy all the original paramters */
      if (!parse_device_path(imagepath, defdevice, defpart,
                            "/vmlinux", &params->kernel)) {
          prom_printf("%s: Unable to parse\n", imagepath);
          return 0;
      }
-     DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev,
-            params->kernel.part, params->kernel.file);
-
+     DEBUG_F("after parse_device_path: dev=%s part=%d file=%s\n", params->kernel.dev, params->kernel.part, params->kernel.file);
      if (useconf) {
          p = cfg_get_strg(label, "initrd");
          if (p && *p) {
-              DEBUG_F("Parsing initrd path <%s>\n", p);
-              strncpy(initrdpath, p, 1024);
+
+           /* check if user seted to use a initrd file from boot console */
+           if (!definitrd && p != manualinitrd) {
+               if (manualinitrd[0] != '/' && (prom_get_devtype(defdevice_bak) != FILE_DEVICE_NET)) {
+                   strcpy(initrdpath, "/");
+                   strcat(initrdpath, manualinitrd);
+               } else
+                   strncpy(initrdpath, manualinitrd, 1024);
+           } else
+               strncpy(initrdpath, p, 1024);
+
+              DEBUG_F("Parsing initrd path <%s>\n", initrdpath);
+              params->rd = boot; /* Copy all the original paramters */
               if (!parse_device_path(initrdpath, defdevice, defpart,
                                      "/root.bin", &params->rd)) {
                    prom_printf("%s: Unable to parse\n", imagepath);
                    return 0;
               }
          }
-         p = cfg_get_strg(label, "sysmap");
-         if (p && *p) {
-              DEBUG_F("Parsing sysmap path <%s>\n", p);
-              strncpy(sysmappath, p, 1024);
-              if (!parse_device_path(sysmappath, defdevice, defpart,
-                                     "/boot/System.map", &params->sysmap)) {
-                   prom_printf("%s: Unable to parse\n", imagepath);
-                   return 0;
-              }
-         }
      }
      return 0;
 }
@@ -959,17 +1010,12 @@ int get_params(struct boot_param_t* params)
 void
 yaboot_text_ui(void)
 {
-#define MAX_HEADERS    32
-
      struct boot_file_t        file;
      int                       result;
      static struct boot_param_t        params;
      void              *initrd_base;
      unsigned long     initrd_size;
-     void                *sysmap_base;
-     unsigned long     sysmap_size;
      kernel_entry_t      kernel_entry;
-     struct bi_record* birec;
      char*               loc=NULL;
      loadinfo_t          loadinfo;
      void                *initrd_more,*initrd_want;
@@ -980,8 +1026,6 @@ yaboot_text_ui(void)
      for (;;) {
          initrd_size = 0;
          initrd_base = 0;
-         sysmap_base = 0;
-         sysmap_size = 0;
 
          if (get_params(&params))
               return;
@@ -1044,55 +1088,6 @@ yaboot_text_ui(void)
          file.fs->close(&file);
          memset(&file, 0, sizeof(file));
 
-         /* If sysmap, load it (only if booting a vmlinux).
-          */
-         if (flat_vmlinux && params.sysmap.file) {
-              prom_printf("Loading System.map ...\n");
-              if(strlen(boot.file) && !strcmp(boot.file,"\\\\") && params.sysmap.file[0] != '/'
-                 && params.sysmap.file[0] != '\\') {
-                   if (loc) free(loc);
-                   loc=(char*)malloc(strlen(params.sysmap.file)+3);
-                   if (!loc) {
-                        prom_printf ("malloc error\n");
-                        goto next;
-                   }
-                   strcpy(loc,boot.file);
-                   strcat(loc,params.sysmap.file);
-                   free(params.sysmap.file);
-                   params.sysmap.file=loc;
-              }
-
-              result = open_file(&params.sysmap, &file);
-              if (result != FILE_ERR_OK) {
-                   prom_printf("%s:%d,", params.sysmap.dev, params.sysmap.part);
-                   prom_perror(result, params.sysmap.file);
-              }
-              else {
-                   sysmap_base = prom_claim(loadinfo.base+loadinfo.memsize, 0x100000, 0);
-                   if (sysmap_base == (void *)-1) {
-                        prom_printf("Claim failed for sysmap memory\n");
-                        prom_pause();
-                        sysmap_base = 0;
-                   } else {
-                        sysmap_size = file.fs->read(&file, 0xfffff, sysmap_base);
-                        if (sysmap_size == 0)
-                             sysmap_base = 0;
-                        else
-                             ((char *)sysmap_base)[sysmap_size++] = 0;
-                   }
-                   file.fs->close(&file);
-                   memset(&file, 0, sizeof(file));
-              }
-              if (sysmap_base) {
-                   prom_printf("System.map loaded at %p, size: %lu Kbytes\n",
-                               sysmap_base, sysmap_size >> 10);
-                   loadinfo.memsize += _ALIGN(0x100000, 0x1000);
-              } else {
-                   prom_printf("System.map load failed !\n");
-                   prom_pause();
-              }
-         }
-
          /* If ramdisk, load it (only if booting a vmlinux).  For now, we
           * can't tell the size it will be so we claim an arbitrary amount
           * of 4Mb.
@@ -1120,25 +1115,33 @@ yaboot_text_ui(void)
               }
               else {
 #define INITRD_CHUNKSIZE 0x100000
-                   initrd_base = prom_claim(loadinfo.base+loadinfo.memsize, INITRD_CHUNKSIZE, 0);
+                   unsigned int len = INITRD_CHUNKSIZE;
+
+                   /* We add a bit to the actual size so the loop below doesn't think
+                    * there is more to load.
+                    */
+                   if (file.fs->ino_size && file.fs->ino_size(&file) > 0)
+                        len = file.fs->ino_size(&file) + 0x1000;
+
+                   initrd_base = prom_claim_chunk(loadinfo.base+loadinfo.memsize, len, 0);
                    if (initrd_base == (void *)-1) {
                         prom_printf("Claim failed for initrd memory\n");
                         initrd_base = 0;
                    } else {
-                        initrd_size = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_base);
+                        initrd_size = file.fs->read(&file, len, initrd_base);
                         if (initrd_size == 0)
                              initrd_base = 0;
                         initrd_read = initrd_size;
                         initrd_more = initrd_base;
-                        while (initrd_read == INITRD_CHUNKSIZE ) { /* need to read more? */
-                             initrd_want = (void *)((unsigned long)initrd_more+INITRD_CHUNKSIZE);
-                             initrd_more = prom_claim(initrd_want, INITRD_CHUNKSIZE, 0);
+                        while (initrd_read == len ) { /* need to read more? */
+                             initrd_want = (void *)((unsigned long)initrd_more+len);
+                             initrd_more = prom_claim(initrd_want, len, 0);
                              if (initrd_more != initrd_want) {
                                   prom_printf("Claim failed for initrd memory at %p rc=%p\n",initrd_want,initrd_more);
                                   prom_pause();
                                   break;
                              }
-                             initrd_read = file.fs->read(&file, INITRD_CHUNKSIZE, initrd_more);
+                             initrd_read = file.fs->read(&file, len, initrd_more);
                              DEBUG_F("  block at %p rc=%lu\n",initrd_more,initrd_read);
                              initrd_size += initrd_read;
                         }
@@ -1161,50 +1164,6 @@ yaboot_text_ui(void)
          flush_icache_range ((long)loadinfo.base, (long)loadinfo.base+loadinfo.memsize);
          DEBUG_F(" done\n");
 
-         if (flat_vmlinux) {
-              /*
-               * Fill new boot infos (only if booting a vmlinux).
-               *
-               * The birec is low on memory, probably inside the malloc pool,
-               * so we don't write it earlier. At this point, we should not
-               * use anything coming from the malloc pool.
-               */
-              birec = (struct bi_record *)_ALIGN(loadinfo.filesize+(1<<20)-1,(1<<20));
-
-              /* We make sure it's mapped. We map only 64k for now, it's
-               * plenty enough we don't claim since this precise memory
-               * range may already be claimed by the malloc pool.
-               */
-              prom_map (birec, birec, 0x10000);
-              DEBUG_F("birec at %p\n", birec);
-              DEBUG_SLEEP;
-
-              birec->tag = BI_FIRST;
-              birec->size = sizeof(struct bi_record);
-              birec = (struct bi_record *)((ulong)birec + birec->size);
-
-              birec->tag = BI_BOOTLOADER_ID;
-              sprintf( (char *)birec->data, "yaboot");
-              birec->size = sizeof(struct bi_record) + strlen("yaboot") + 1;
-              birec = (struct bi_record *)((ulong)birec + birec->size);
-
-              birec->tag = BI_MACHTYPE;
-              birec->data[0] = _machine;
-              birec->size = sizeof(struct bi_record) + sizeof(ulong);
-              birec = (struct bi_record *)((ulong)birec + birec->size);
-
-              if (sysmap_base) {
-                   birec->tag = BI_SYSMAP;
-                   birec->data[0] = (ulong)sysmap_base;
-                   birec->data[1] = sysmap_size;
-                   birec->size = sizeof(struct bi_record) + sizeof(ulong)*2;
-                   birec = (struct bi_record *)((ulong)birec + birec->size);
-              }
-              birec->tag = BI_LAST;
-              birec->size = sizeof(struct bi_record);
-              birec = (struct bi_record *)((ulong)birec + birec->size);
-          }
-
           /* compute the kernel's entry point. */
          kernel_entry = loadinfo.base + loadinfo.entry - loadinfo.load_loc;
 
@@ -1218,6 +1177,8 @@ yaboot_text_ui(void)
 
          DEBUG_F("Entering kernel...\n");
 
+         prom_print_available();
+
           /* call the kernel with our stack. */
          kernel_entry(initrd_base + loadinfo.load_loc, initrd_size, prom, 0, 0);
          continue;
@@ -1233,7 +1194,7 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
      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) {
@@ -1255,11 +1216,6 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
 
      loadinfo->entry = e->e_entry;
 
-     if (e->e_phnum > MAX_HEADERS) {
-         prom_printf ("Can only load kernels with one program header\n");
-         goto bail;
-     }
-
      ph = (Elf32_Phdr *)malloc(sizeof(Elf32_Phdr) * e->e_phnum);
      if (!ph) {
          prom_printf ("Malloc error\n");
@@ -1321,13 +1277,7 @@ load_elf32(struct boot_file_t *file, loadinfo_t *loadinfo)
           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 +1327,7 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
      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) {
@@ -1399,11 +1349,6 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
 
      loadinfo->entry = e->e_entry;
 
-     if (e->e_phnum > MAX_HEADERS) {
-         prom_printf ("Can only load kernels with one program header\n");
-         goto bail;
-     }
-
      ph = (Elf64_Phdr *)malloc(sizeof(Elf64_Phdr) * e->e_phnum);
      if (!ph) {
          prom_printf ("Malloc error\n");
@@ -1448,8 +1393,7 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
          goto bail;
      }
 
-     /* leave some room (1Mb) for boot infos */
-     loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20)) + 0x100000;
+     loadinfo->memsize = _ALIGN(loadinfo->memsize,(1<<20));
      /* Claim OF memory */
      DEBUG_F("Before prom_claim, mem_sz: 0x%08lx\n", loadinfo->memsize);
 
@@ -1465,13 +1409,7 @@ load_elf64(struct boot_file_t *file, loadinfo_t *loadinfo)
           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;
@@ -1540,7 +1478,7 @@ is_elf64(loadinfo_t *loadinfo)
             e->e_ident[EI_MAG3]  == ELFMAG3        &&
             e->e_ident[EI_CLASS] == ELFCLASS64  &&
             e->e_ident[EI_DATA]  == ELFDATA2MSB &&
-            e->e_type            == ET_EXEC        &&
+            (e->e_type == ET_EXEC || e->e_type == ET_DYN) &&
             e->e_machine         == EM_PPC64);
 }
 
@@ -1625,6 +1563,7 @@ int
 yaboot_main(void)
 {
      char *ptype;
+     char *endp;
      int conf_given = 0;
      char conf_path[1024];
 
@@ -1635,6 +1574,11 @@ yaboot_main(void)
      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,client-architecture-support-reboot",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
@@ -1678,11 +1622,13 @@ yaboot_main(void)
          prom_printf("%s: Unable to parse\n", bootdevice);
          return -1;
      }
+     if (_machine == _MACH_bplan && !conf_given)
+        boot.part++;
      DEBUG_F("After parse_device_path: dev=%s, part=%d, file=%s\n",
             boot.dev, boot.part, boot.file);
 
      if (!conf_given) {
-         if (_machine == _MACH_chrp)
+         if (_machine == _MACH_chrp || _machine == _MACH_bplan)
              boot.file = "/etc/";
          else if (strlen(boot.file)) {
              if (!strncmp(boot.file, "\\\\", 2))