Update addnote for newer pSeries hardware
[yaboot.git] / util / addnote.c
index 90434c8c2a3a63259e115ee8bc82bb5f2e88d038..741bf8a0b76cef0b5e579bd44ad6d5167e9e17f4 100644 (file)
@@ -28,6 +28,7 @@
 #include <unistd.h>
 #include <string.h>
 
+/* CHRP note section */
 char arch[] = "PowerPC";
 
 #define N_DESCR        6
@@ -40,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]))
@@ -77,7 +101,7 @@ 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]);
@@ -89,7 +113,8 @@ main(int ac, char **av)
          exit(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) {
@@ -112,7 +137,7 @@ 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) {
@@ -125,12 +150,12 @@ main(int ac, char **av)
      }
 
      /* 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);
@@ -142,11 +167,26 @@ 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);