]> git.ozlabs.org Git - yaboot.git/blobdiff - util/addnote.c
Allocate kernel and ramdisk as low as possible
[yaboot.git] / util / addnote.c
index 1ae16360dfc658ad4b96288f99e418b5bd0e9281..56de0c75e40058e6b665da8f9c9b68e13b813dd1 100644 (file)
@@ -1,24 +1,34 @@
 /*
- * Program to hack in a PT_NOTE program header entry in an ELF file.
- * This is needed for OF on RS/6000s to load an image correctly.
- * Note that OF needs a program header entry for the note, not an
- * ELF section.
+ *  addnote.c - Program to hack in a PT_NOTE program header entry in an ELF file.
+ *             This is needed for OF on RS/6000s to load an image correctly.
+ *             Note that OF needs a program header entry for the note, not an
+ *             ELF section.
  *
- * Copyright 2000 Paul Mackerras.
+ *  Copyright 2000 Paul Mackerras.
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
  *
- * Usage: addnote zImage
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+/* Usage: addnote zImage */
+
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <string.h>
 
+/* CHRP note section */
 char arch[] = "PowerPC";
 
 #define N_DESCR        6
@@ -31,6 +41,29 @@ unsigned int descr[N_DESCR] = {
      0x4000,                   /* load-base */
 };
 
+/* RPA note section */
+char rpaname[] = "IBM,RPA-Client-Config";
+
+/*
+ * Note: setting ignore_my_client_config *should* mean that OF ignores
+ * all the other fields, but there is a firmware bug which means that
+ * it looks at the splpar field at least.  So these values need to be
+ * reasonable.
+ */
+#define N_RPA_DESCR    8
+unsigned int rpanote[N_RPA_DESCR] = {
+     0,                                /* lparaffinity */
+     64,                       /* min_rmo_size */
+     0,                                /* min_rmo_percent */
+     40,                       /* max_pft_size */
+     1,                                /* splpar */
+     -1,                       /* min_load */
+     0,                                /* new_mem_def */
+     1,                                /* ignore_my_client_config */
+};
+
+#define ROUNDUP(len)   (((len) + 3) & ~3)
+
 unsigned char buf[512];
 
 #define GET_16BE(off)  ((buf[off] << 8) + (buf[(off)+1]))
@@ -68,24 +101,25 @@ main(int ac, char **av)
 {
      int fd, n, i;
      int ph, ps, np;
-     int nnote, ns;
+     int nnote, nnote2, ns;
 
      if (ac != 2) {
          fprintf(stderr, "Usage: %s elf-file\n", av[0]);
-         exit(1);
+         return(1);
      }
      fd = open(av[1], O_RDWR);
      if (fd < 0) {
          perror(av[1]);
-         exit(1);
+         return(1);
      }
 
-     nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4;
+     nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr);
+     nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote);
 
      n = read(fd, buf, sizeof(buf));
      if (n < 0) {
          perror("read");
-         exit(1);
+         return(1);
      }
 
      if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0)
@@ -95,7 +129,7 @@ main(int ac, char **av)
         || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) {
          fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n",
                  av[1]);
-         exit(1);
+         return(1);
      }
 
      ph = GET_32BE(E_PHOFF);
@@ -103,25 +137,25 @@ main(int ac, char **av)
      np = GET_16BE(E_PHNUM);
      if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
          goto notelf;
-     if (ph + (np + 1) * ps + nnote > n)
+     if (ph + (np + 2) * ps + nnote + nnote2 > n)
          goto nospace;
 
      for (i = 0; i < np; ++i) {
          if (GET_32BE(ph + PH_TYPE) == PT_NOTE) {
               fprintf(stderr, "%s already has a note entry\n",
                       av[1]);
-              exit(0);
+              return(0);
          }
          ph += ps;
      }
 
      /* XXX check that the area we want to use is all zeroes */
-     for (i = 0; i < ps + nnote; ++i)
+     for (i = 0; i < 2 * ps + nnote + nnote2; ++i)
          if (buf[ph + i] != 0)
               goto nospace;
 
      /* fill in the program header entry */
-     ns = ph + ps;
+     ns = ph + 2 * ps;
      PUT_32BE(ph + PH_TYPE, PT_NOTE);
      PUT_32BE(ph + PH_OFFSET, ns);
      PUT_32BE(ph + PH_FILESZ, nnote);
@@ -133,39 +167,54 @@ main(int ac, char **av)
      PUT_32BE(ns + 8, 0x1275);
      strcpy(&buf[ns + 12], arch);
      ns += 12 + strlen(arch) + 1;
-     for (i = 0; i < N_DESCR; ++i)
-         PUT_32BE(ns + i * 4, descr[i]);
+     for (i = 0; i < N_DESCR; ++i, ns += 4)
+         PUT_32BE(ns, descr[i]);
+
+     /* fill in the second program header entry and the RPA note area */
+     ph += ps;
+     PUT_32BE(ph + PH_TYPE, PT_NOTE);
+     PUT_32BE(ph + PH_OFFSET, ns);
+     PUT_32BE(ph + PH_FILESZ, nnote2);
+
+     /* fill in the note area we point to */
+     PUT_32BE(ns, strlen(rpaname) + 1);
+     PUT_32BE(ns + 4, sizeof(rpanote));
+     PUT_32BE(ns + 8, 0x12759999);
+     strcpy(&buf[ns + 12], rpaname);
+     ns += 12 + ROUNDUP(strlen(rpaname) + 1);
+     for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
+         PUT_32BE(ns, rpanote[i]);
 
      /* Update the number of program headers */
-     PUT_16BE(E_PHNUM, np + 1);
+     PUT_16BE(E_PHNUM, np + 2);
 
      /* write back */
      lseek(fd, (long) 0, SEEK_SET);
      i = write(fd, buf, n);
      if (i < 0) {
          perror("write");
-         exit(1);
+         return(1);
      }
      if (i < n) {
          fprintf(stderr, "%s: write truncated\n", av[1]);
-         exit(1);
+         return(1);
      }
 
-     exit(0);
+     return(0);
 
 notelf:
      fprintf(stderr, "%s does not appear to be an ELF file\n", av[1]);
-     exit(1);
+     return(1);
 
 nospace:
      fprintf(stderr, "sorry, I can't find space in %s to put the note\n",
             av[1]);
-     exit(1);
+     return(1);
 }
 
-/* 
+/*
  * Local variables:
- * c-file-style: "K&R"
+ * c-file-style: "k&r"
  * c-basic-offset: 5
  * End:
  */