]> git.ozlabs.org Git - yaboot.git/blobdiff - second/yaboot.c
These patch provides the function of load a alternative initrd file
[yaboot.git] / second / yaboot.c
index 6eef8d69ccc94a170694106f0dcbe70b40421b8f..4ade0776383399d486a0c517a4fed507847ea0fe 100644 (file)
@@ -455,7 +455,9 @@ 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;
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+     char *cfgpath = (_machine == _MACH_chrp) ? "/etc/" : "";
+     int flen;
+     int minlen;
 
      packet = prom_get_netinfo();
 
@@ -469,34 +471,26 @@ static int load_my_config_file(struct boot_fspec_t *orig_fspec)
      if (!fspec.file)
          goto out;
 
-     if (_machine == _MACH_chrp)
-         sprintf(fspec.file, "/etc/%02x-", packet->htype);
-     else
-         sprintf(fspec.file, "%02x-", 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.
       */
-     free(fspec.file);
-     /* 8 chars in yiaddr + \0 */
-     fspec.file = malloc(9);
-     if (!fspec.file)
-         goto out;
+     /* no need to realloc for /etc/ + 8 chars in yiaddr + \0 */
+     sprintf(fspec.file, "%s%s", cfgpath, prom_get_ip(packet));
 
-     strcat(fspec.file, prom_get_ip(packet));
-
-     while (strlen(fspec.file)) {
+     for (flen = strlen(fspec.file),
+          minlen = strlen(cfgpath); flen > minlen; flen--) {
          rc = load_config_file(&fspec);
          if (rc)
               goto out;
          /* Chop one digit off the end, try again */
-         fspec.file[strlen(fspec.file) - 1] = '\0';
+         fspec.file[flen - 1] = '\0';
      }
 
  out:
@@ -660,6 +654,8 @@ int get_params(struct boot_param_t* params)
      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));
@@ -739,6 +735,46 @@ 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();
@@ -800,6 +836,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."
@@ -929,14 +971,22 @@ int get_params(struct boot_param_t* params)
          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);
               if (!parse_device_path(initrdpath, defdevice, defpart,
                                      "/root.bin", &params->rd)) {
                    prom_printf("%s: Unable to parse\n", imagepath);
@@ -1239,7 +1289,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) {
@@ -1327,13 +1377,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;
@@ -1383,7 +1427,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) {
@@ -1471,13 +1515,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;
@@ -1596,7 +1634,7 @@ setup_display(void)
      }
 
      if (scrn == PROM_INVALID_HANDLE) {
-         prom_printf("No screen device found !/n");
+         prom_printf("No screen device found !\n");
          return;
      }
      for(i=0;i<16;i++) {