aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2008-10-08 10:03:29 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-10 00:55:19 -0400
commit91a00302959545a9ae423e99732b1e46eb19e877 (patch)
tree180192f6f8d2b97c332d970fc07278010287f3f5
parent58f467ce1476f5b2a347cee3a32275b737fbd667 (diff)
powerpc: Sync RPA note in zImage with kernel's RPA note
Commit 9b09c6d909dfd8de96b99b9b9c808b94b0a71614 ("powerpc: Change the default link address for pSeries zImage kernels") changed the real-base value in the CHRP note added by the addnote program from 12MB to 32MB to give more space for Open Firmware to load the zImage. (The real-base value says where we want OF to position itself in memory.) However, this change was ineffective on most pSeries machines, because the RPA note added by addnote has the "ignore me" flag set to 1. This was intended to tell OF to ignore just the RPA note, but has the side effect of also making OF ignore the CHRP note (at least on most pSeries machines). To solve this we have to set the "ignore me" flag to 0 in the RPA note. (We can't just omit the RPA note because that is equivalent to having an RPA note with default values, and the default values are not what we want.) However, then we have to make sure the values in the zImage's RPA note match up with the values that the kernel supplies later in prom_init.c with either the ibm,client-architecture-support call or the process-elf-header call in prom_send_capabilities(). So this sets the "ignore me" flag in the RPA note in addnote to 0, and adjusts the RPA note values in addnote.c and in prom_init.c to be consistent with each other and with the values in ibm_architecture_vec. However, since the wrapper is independent of the kernel, this doesn't ensure that the notes will stay consistent. To ensure that, this adds code to addnote.c so that it can extract the kernel's RPA note from the kernel binary and put that in the zImage. To that end, we put the kernel's fake ELF header (which contains the kernel's RPA note) into its own section, and arrange for wrapper to pull out that section with objcopy and pass it to addnote, which then extracts the RPA note from it and transfers it to the zImage. Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-rw-r--r--arch/powerpc/boot/addnote.c144
-rwxr-xr-xarch/powerpc/boot/wrapper4
-rw-r--r--arch/powerpc/kernel/prom_init.c10
-rw-r--r--arch/powerpc/kernel/vmlinux.lds.S3
4 files changed, 119 insertions, 42 deletions
diff --git a/arch/powerpc/boot/addnote.c b/arch/powerpc/boot/addnote.c
index b1e5611b2ab1..dcc9ab2ca823 100644
--- a/arch/powerpc/boot/addnote.c
+++ b/arch/powerpc/boot/addnote.c
@@ -11,7 +11,12 @@
11 * as published by the Free Software Foundation; either version 11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version. 12 * 2 of the License, or (at your option) any later version.
13 * 13 *
14 * Usage: addnote zImage 14 * Usage: addnote zImage [note.elf]
15 *
16 * If note.elf is supplied, it is the name of an ELF file that contains
17 * an RPA note to use instead of the built-in one. Alternatively, the
18 * note.elf file may be empty, in which case the built-in RPA note is
19 * used (this is to simplify how this is invoked from the wrapper script).
15 */ 20 */
16#include <stdio.h> 21#include <stdio.h>
17#include <stdlib.h> 22#include <stdlib.h>
@@ -43,27 +48,29 @@ char rpaname[] = "IBM,RPA-Client-Config";
43 */ 48 */
44#define N_RPA_DESCR 8 49#define N_RPA_DESCR 8
45unsigned int rpanote[N_RPA_DESCR] = { 50unsigned int rpanote[N_RPA_DESCR] = {
46 0, /* lparaffinity */ 51 1, /* lparaffinity */
47 64, /* min_rmo_size */ 52 128, /* min_rmo_size */
48 0, /* min_rmo_percent */ 53 0, /* min_rmo_percent */
49 40, /* max_pft_size */ 54 46, /* max_pft_size */
50 1, /* splpar */ 55 1, /* splpar */
51 -1, /* min_load */ 56 -1, /* min_load */
52 0, /* new_mem_def */ 57 1, /* new_mem_def */
53 1, /* ignore_my_client_config */ 58 0, /* ignore_my_client_config */
54}; 59};
55 60
56#define ROUNDUP(len) (((len) + 3) & ~3) 61#define ROUNDUP(len) (((len) + 3) & ~3)
57 62
58unsigned char buf[512]; 63unsigned char buf[512];
64unsigned char notebuf[512];
59 65
60#define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) 66#define GET_16BE(b, off) (((b)[off] << 8) + ((b)[(off)+1]))
61#define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2)) 67#define GET_32BE(b, off) ((GET_16BE((b), (off)) << 16) + \
68 GET_16BE((b), (off)+2))
62 69
63#define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \ 70#define PUT_16BE(b, off, v) ((b)[off] = ((v) >> 8) & 0xff, \
64 buf[(off) + 1] = (v) & 0xff) 71 (b)[(off) + 1] = (v) & 0xff)
65#define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \ 72#define PUT_32BE(b, off, v) (PUT_16BE((b), (off), (v) >> 16), \
66 PUT_16BE((off) + 2, (v))) 73 PUT_16BE((b), (off) + 2, (v)))
67 74
68/* Structure of an ELF file */ 75/* Structure of an ELF file */
69#define E_IDENT 0 /* ELF header */ 76#define E_IDENT 0 /* ELF header */
@@ -88,15 +95,71 @@ unsigned char buf[512];
88 95
89unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' }; 96unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' };
90 97
98unsigned char *read_rpanote(const char *fname, int *nnp)
99{
100 int notefd, nr, i;
101 int ph, ps, np;
102 int note, notesize;
103
104 notefd = open(fname, O_RDONLY);
105 if (notefd < 0) {
106 perror(fname);
107 exit(1);
108 }
109 nr = read(notefd, notebuf, sizeof(notebuf));
110 if (nr < 0) {
111 perror("read note");
112 exit(1);
113 }
114 if (nr == 0) /* empty file */
115 return NULL;
116 if (nr < E_HSIZE ||
117 memcmp(&notebuf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0 ||
118 notebuf[E_IDENT+EI_CLASS] != ELFCLASS32 ||
119 notebuf[E_IDENT+EI_DATA] != ELFDATA2MSB)
120 goto notelf;
121 close(notefd);
122
123 /* now look for the RPA-note */
124 ph = GET_32BE(notebuf, E_PHOFF);
125 ps = GET_16BE(notebuf, E_PHENTSIZE);
126 np = GET_16BE(notebuf, E_PHNUM);
127 if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
128 goto notelf;
129
130 for (i = 0; i < np; ++i, ph += ps) {
131 if (GET_32BE(notebuf, ph + PH_TYPE) != PT_NOTE)
132 continue;
133 note = GET_32BE(notebuf, ph + PH_OFFSET);
134 notesize = GET_32BE(notebuf, ph + PH_FILESZ);
135 if (notesize < 34 || note + notesize > nr)
136 continue;
137 if (GET_32BE(notebuf, note) != strlen(rpaname) + 1 ||
138 GET_32BE(notebuf, note + 8) != 0x12759999 ||
139 strcmp((char *)&notebuf[note + 12], rpaname) != 0)
140 continue;
141 /* looks like an RPA note, return it */
142 *nnp = notesize;
143 return &notebuf[note];
144 }
145 /* no RPA note found */
146 return NULL;
147
148 notelf:
149 fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n", fname);
150 exit(1);
151}
152
91int 153int
92main(int ac, char **av) 154main(int ac, char **av)
93{ 155{
94 int fd, n, i; 156 int fd, n, i;
95 int ph, ps, np; 157 int ph, ps, np;
96 int nnote, nnote2, ns; 158 int nnote, nnote2, ns;
159 unsigned char *rpap;
97 160
98 if (ac != 2) { 161 if (ac != 2 && ac != 3) {
99 fprintf(stderr, "Usage: %s elf-file\n", av[0]); 162 fprintf(stderr, "Usage: %s elf-file [rpanote.elf]\n", av[0]);
100 exit(1); 163 exit(1);
101 } 164 }
102 fd = open(av[1], O_RDWR); 165 fd = open(av[1], O_RDWR);
@@ -107,6 +170,7 @@ main(int ac, char **av)
107 170
108 nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr); 171 nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr);
109 nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote); 172 nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote);
173 rpap = NULL;
110 174
111 n = read(fd, buf, sizeof(buf)); 175 n = read(fd, buf, sizeof(buf));
112 if (n < 0) { 176 if (n < 0) {
@@ -124,16 +188,19 @@ main(int ac, char **av)
124 exit(1); 188 exit(1);
125 } 189 }
126 190
127 ph = GET_32BE(E_PHOFF); 191 if (ac == 3)
128 ps = GET_16BE(E_PHENTSIZE); 192 rpap = read_rpanote(av[2], &nnote2);
129 np = GET_16BE(E_PHNUM); 193
194 ph = GET_32BE(buf, E_PHOFF);
195 ps = GET_16BE(buf, E_PHENTSIZE);
196 np = GET_16BE(buf, E_PHNUM);
130 if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) 197 if (ph < E_HSIZE || ps < PH_HSIZE || np < 1)
131 goto notelf; 198 goto notelf;
132 if (ph + (np + 2) * ps + nnote + nnote2 > n) 199 if (ph + (np + 2) * ps + nnote + nnote2 > n)
133 goto nospace; 200 goto nospace;
134 201
135 for (i = 0; i < np; ++i) { 202 for (i = 0; i < np; ++i) {
136 if (GET_32BE(ph + PH_TYPE) == PT_NOTE) { 203 if (GET_32BE(buf, ph + PH_TYPE) == PT_NOTE) {
137 fprintf(stderr, "%s already has a note entry\n", 204 fprintf(stderr, "%s already has a note entry\n",
138 av[1]); 205 av[1]);
139 exit(0); 206 exit(0);
@@ -148,37 +215,42 @@ main(int ac, char **av)
148 215
149 /* fill in the program header entry */ 216 /* fill in the program header entry */
150 ns = ph + 2 * ps; 217 ns = ph + 2 * ps;
151 PUT_32BE(ph + PH_TYPE, PT_NOTE); 218 PUT_32BE(buf, ph + PH_TYPE, PT_NOTE);
152 PUT_32BE(ph + PH_OFFSET, ns); 219 PUT_32BE(buf, ph + PH_OFFSET, ns);
153 PUT_32BE(ph + PH_FILESZ, nnote); 220 PUT_32BE(buf, ph + PH_FILESZ, nnote);
154 221
155 /* fill in the note area we point to */ 222 /* fill in the note area we point to */
156 /* XXX we should probably make this a proper section */ 223 /* XXX we should probably make this a proper section */
157 PUT_32BE(ns, strlen(arch) + 1); 224 PUT_32BE(buf, ns, strlen(arch) + 1);
158 PUT_32BE(ns + 4, N_DESCR * 4); 225 PUT_32BE(buf, ns + 4, N_DESCR * 4);
159 PUT_32BE(ns + 8, 0x1275); 226 PUT_32BE(buf, ns + 8, 0x1275);
160 strcpy((char *) &buf[ns + 12], arch); 227 strcpy((char *) &buf[ns + 12], arch);
161 ns += 12 + strlen(arch) + 1; 228 ns += 12 + strlen(arch) + 1;
162 for (i = 0; i < N_DESCR; ++i, ns += 4) 229 for (i = 0; i < N_DESCR; ++i, ns += 4)
163 PUT_32BE(ns, descr[i]); 230 PUT_32BE(buf, ns, descr[i]);
164 231
165 /* fill in the second program header entry and the RPA note area */ 232 /* fill in the second program header entry and the RPA note area */
166 ph += ps; 233 ph += ps;
167 PUT_32BE(ph + PH_TYPE, PT_NOTE); 234 PUT_32BE(buf, ph + PH_TYPE, PT_NOTE);
168 PUT_32BE(ph + PH_OFFSET, ns); 235 PUT_32BE(buf, ph + PH_OFFSET, ns);
169 PUT_32BE(ph + PH_FILESZ, nnote2); 236 PUT_32BE(buf, ph + PH_FILESZ, nnote2);
170 237
171 /* fill in the note area we point to */ 238 /* fill in the note area we point to */
172 PUT_32BE(ns, strlen(rpaname) + 1); 239 if (rpap) {
173 PUT_32BE(ns + 4, sizeof(rpanote)); 240 /* RPA note supplied in file, just copy the whole thing over */
174 PUT_32BE(ns + 8, 0x12759999); 241 memcpy(buf + ns, rpap, nnote2);
175 strcpy((char *) &buf[ns + 12], rpaname); 242 } else {
176 ns += 12 + ROUNDUP(strlen(rpaname) + 1); 243 PUT_32BE(buf, ns, strlen(rpaname) + 1);
177 for (i = 0; i < N_RPA_DESCR; ++i, ns += 4) 244 PUT_32BE(buf, ns + 4, sizeof(rpanote));
178 PUT_32BE(ns, rpanote[i]); 245 PUT_32BE(buf, ns + 8, 0x12759999);
246 strcpy((char *) &buf[ns + 12], rpaname);
247 ns += 12 + ROUNDUP(strlen(rpaname) + 1);
248 for (i = 0; i < N_RPA_DESCR; ++i, ns += 4)
249 PUT_32BE(buf, ns, rpanote[i]);
250 }
179 251
180 /* Update the number of program headers */ 252 /* Update the number of program headers */
181 PUT_16BE(E_PHNUM, np + 2); 253 PUT_16BE(buf, E_PHNUM, np + 2);
182 254
183 /* write back */ 255 /* write back */
184 lseek(fd, (long) 0, SEEK_SET); 256 lseek(fd, (long) 0, SEEK_SET);
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 965c237c122d..ee0dc41d7c56 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -307,7 +307,9 @@ fi
307# post-processing needed for some platforms 307# post-processing needed for some platforms
308case "$platform" in 308case "$platform" in
309pseries|chrp) 309pseries|chrp)
310 $objbin/addnote "$ofile" 310 ${CROSS}objcopy -O binary -j .fakeelf "$kernel" "$ofile".rpanote
311 $objbin/addnote "$ofile" "$ofile".rpanote
312 rm -r "$ofile".rpanote
311 ;; 313 ;;
312coff) 314coff)
313 ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile" 315 ${CROSS}objcopy -O aixcoff-rs6000 --set-start "$entry" "$ofile"
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 7cf274a2b334..2fdbc18ae94a 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -732,7 +732,7 @@ static struct fake_elf {
732 u32 ignore_me; 732 u32 ignore_me;
733 } rpadesc; 733 } rpadesc;
734 } rpanote; 734 } rpanote;
735} fake_elf = { 735} fake_elf __section(.fakeelf) = {
736 .elfhdr = { 736 .elfhdr = {
737 .e_ident = { 0x7f, 'E', 'L', 'F', 737 .e_ident = { 0x7f, 'E', 'L', 'F',
738 ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, 738 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
@@ -774,13 +774,13 @@ static struct fake_elf {
774 .type = 0x12759999, 774 .type = 0x12759999,
775 .name = "IBM,RPA-Client-Config", 775 .name = "IBM,RPA-Client-Config",
776 .rpadesc = { 776 .rpadesc = {
777 .lpar_affinity = 0, 777 .lpar_affinity = 1,
778 .min_rmo_size = 64, /* in megabytes */ 778 .min_rmo_size = 128, /* in megabytes */
779 .min_rmo_percent = 0, 779 .min_rmo_percent = 0,
780 .max_pft_size = 48, /* 2^48 bytes max PFT size */ 780 .max_pft_size = 46, /* 2^46 bytes max PFT size */
781 .splpar = 1, 781 .splpar = 1,
782 .min_load = ~0U, 782 .min_load = ~0U,
783 .new_mem_def = 0 783 .new_mem_def = 1
784 } 784 }
785 } 785 }
786}; 786};
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index e6927fb2e655..b39c27ed7919 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -203,6 +203,9 @@ SECTIONS
203 *(.rela*) 203 *(.rela*)
204 } 204 }
205 205
206 /* Fake ELF header containing RPA note; for addnote */
207 .fakeelf : AT(ADDR(.fakeelf) - LOAD_OFFSET) { *(.fakeelf) }
208
206 /* freed after init ends here */ 209 /* freed after init ends here */
207 . = ALIGN(PAGE_SIZE); 210 . = ALIGN(PAGE_SIZE);
208 __init_end = .; 211 __init_end = .;