]> git.ozlabs.org Git - yaboot.git/blobdiff - second/yaboot.c
Merge branch 'birecs' into devel
[yaboot.git] / second / yaboot.c
index 4ade0776383399d486a0c517a4fed507847ea0fe..5df07608dacb297eda7352fa03c55013ec3d2f64 100644 (file)
@@ -114,6 +114,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;
@@ -178,6 +181,7 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
 {
      int result;
      void* malloc_base = NULL;
+     unsigned long addr;
      prom_handle root;
 
      /* OF seems to do it, but I'm not very confident */
@@ -196,7 +200,10 @@ yaboot_start (unsigned long r3, unsigned long r4, unsigned long r5)
      prom_init ((prom_entry) r5);
 
      /* Allocate some memory for malloc'ator */
-     malloc_base = prom_claim((void *)MALLOCADDR, MALLOCSIZE, 0);
+     for (addr = MALLOCADDR; addr <= MALLOCADDR * 16 ;addr+=0x100000) {
+         malloc_base = prom_claim((void *)addr, MALLOCSIZE, 0);
+         if (malloc_base != (void *)-1) break;
+     }
      if (malloc_base == (void *)-1) {
          prom_printf("Can't claim malloc buffer (%d bytes at 0x%08x)\n",
                      MALLOCSIZE, MALLOCADDR);
@@ -219,7 +226,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 +300,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;
@@ -455,11 +466,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
@@ -667,7 +680,7 @@ int get_params(struct boot_param_t* params)
 
      cmdinit();
 
-     if (first) {
+     if (first && !fw_reboot_cnt) {
          first = 0;
          imagename = bootargs;
          word_split(&imagename, &params->args);
@@ -682,6 +695,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) {
@@ -718,7 +738,9 @@ int get_params(struct boot_param_t* params)
          if (!imagename) {
               if (bootoncelabel[0] != 0)
                    imagename = bootoncelabel;
-              else
+              else if (bootlastlabel[0] != 0)
+                         imagename = bootlastlabel;
+               else
                    imagename = cfg_get_default();
          }
          if (imagename)
@@ -779,6 +801,9 @@ int get_params(struct boot_param_t* params)
      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;
 
@@ -966,6 +991,7 @@ 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);
@@ -987,6 +1013,7 @@ int get_params(struct boot_param_t* params)
                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);
@@ -997,6 +1024,7 @@ int get_params(struct boot_param_t* params)
          if (p && *p) {
               DEBUG_F("Parsing sysmap path <%s>\n", p);
               strncpy(sysmappath, p, 1024);
+              params->sysmap = boot; /* Copy all the original paramters */
               if (!parse_device_path(sysmappath, defdevice, defpart,
                                      "/boot/System.map", &params->sysmap)) {
                    prom_printf("%s: Unable to parse\n", imagepath);
@@ -1025,7 +1053,6 @@ yaboot_text_ui(void)
      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;
@@ -1217,50 +1244,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;
 
@@ -1498,8 +1481,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);
 
@@ -1584,7 +1566,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);
 }
 
@@ -1669,6 +1651,7 @@ int
 yaboot_main(void)
 {
      char *ptype;
+     char *endp;
      int conf_given = 0;
      char conf_path[1024];
 
@@ -1679,6 +1662,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
@@ -1722,11 +1710,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))