diff options
Diffstat (limited to 'arch/ppc64/boot/addnote.c')
-rw-r--r-- | arch/ppc64/boot/addnote.c | 60 |
1 files changed, 50 insertions, 10 deletions
diff --git a/arch/ppc64/boot/addnote.c b/arch/ppc64/boot/addnote.c index 66ff8103bf4d..719663a694bb 100644 --- a/arch/ppc64/boot/addnote.c +++ b/arch/ppc64/boot/addnote.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <unistd.h> | 19 | #include <unistd.h> |
20 | #include <string.h> | 20 | #include <string.h> |
21 | 21 | ||
22 | /* CHRP note section */ | ||
22 | char arch[] = "PowerPC"; | 23 | char arch[] = "PowerPC"; |
23 | 24 | ||
24 | #define N_DESCR 6 | 25 | #define N_DESCR 6 |
@@ -31,6 +32,29 @@ unsigned int descr[N_DESCR] = { | |||
31 | 0x4000, /* load-base */ | 32 | 0x4000, /* load-base */ |
32 | }; | 33 | }; |
33 | 34 | ||
35 | /* RPA note section */ | ||
36 | char rpaname[] = "IBM,RPA-Client-Config"; | ||
37 | |||
38 | /* | ||
39 | * Note: setting ignore_my_client_config *should* mean that OF ignores | ||
40 | * all the other fields, but there is a firmware bug which means that | ||
41 | * it looks at the splpar field at least. So these values need to be | ||
42 | * reasonable. | ||
43 | */ | ||
44 | #define N_RPA_DESCR 8 | ||
45 | unsigned int rpanote[N_RPA_DESCR] = { | ||
46 | 0, /* lparaffinity */ | ||
47 | 64, /* min_rmo_size */ | ||
48 | 0, /* min_rmo_percent */ | ||
49 | 40, /* max_pft_size */ | ||
50 | 1, /* splpar */ | ||
51 | -1, /* min_load */ | ||
52 | 0, /* new_mem_def */ | ||
53 | 1, /* ignore_my_client_config */ | ||
54 | }; | ||
55 | |||
56 | #define ROUNDUP(len) (((len) + 3) & ~3) | ||
57 | |||
34 | unsigned char buf[512]; | 58 | unsigned char buf[512]; |
35 | 59 | ||
36 | #define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) | 60 | #define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) |
@@ -69,7 +93,7 @@ main(int ac, char **av) | |||
69 | { | 93 | { |
70 | int fd, n, i; | 94 | int fd, n, i; |
71 | int ph, ps, np; | 95 | int ph, ps, np; |
72 | int nnote, ns; | 96 | int nnote, nnote2, ns; |
73 | 97 | ||
74 | if (ac != 2) { | 98 | if (ac != 2) { |
75 | fprintf(stderr, "Usage: %s elf-file\n", av[0]); | 99 | fprintf(stderr, "Usage: %s elf-file\n", av[0]); |
@@ -81,7 +105,8 @@ main(int ac, char **av) | |||
81 | exit(1); | 105 | exit(1); |
82 | } | 106 | } |
83 | 107 | ||
84 | nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4; | 108 | nnote = 12 + ROUNDUP(strlen(arch) + 1) + sizeof(descr); |
109 | nnote2 = 12 + ROUNDUP(strlen(rpaname) + 1) + sizeof(rpanote); | ||
85 | 110 | ||
86 | n = read(fd, buf, sizeof(buf)); | 111 | n = read(fd, buf, sizeof(buf)); |
87 | if (n < 0) { | 112 | if (n < 0) { |
@@ -104,7 +129,7 @@ main(int ac, char **av) | |||
104 | np = GET_16BE(E_PHNUM); | 129 | np = GET_16BE(E_PHNUM); |
105 | if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) | 130 | if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) |
106 | goto notelf; | 131 | goto notelf; |
107 | if (ph + (np + 1) * ps + nnote > n) | 132 | if (ph + (np + 2) * ps + nnote + nnote2 > n) |
108 | goto nospace; | 133 | goto nospace; |
109 | 134 | ||
110 | for (i = 0; i < np; ++i) { | 135 | for (i = 0; i < np; ++i) { |
@@ -117,12 +142,12 @@ main(int ac, char **av) | |||
117 | } | 142 | } |
118 | 143 | ||
119 | /* XXX check that the area we want to use is all zeroes */ | 144 | /* XXX check that the area we want to use is all zeroes */ |
120 | for (i = 0; i < ps + nnote; ++i) | 145 | for (i = 0; i < 2 * ps + nnote + nnote2; ++i) |
121 | if (buf[ph + i] != 0) | 146 | if (buf[ph + i] != 0) |
122 | goto nospace; | 147 | goto nospace; |
123 | 148 | ||
124 | /* fill in the program header entry */ | 149 | /* fill in the program header entry */ |
125 | ns = ph + ps; | 150 | ns = ph + 2 * ps; |
126 | PUT_32BE(ph + PH_TYPE, PT_NOTE); | 151 | PUT_32BE(ph + PH_TYPE, PT_NOTE); |
127 | PUT_32BE(ph + PH_OFFSET, ns); | 152 | PUT_32BE(ph + PH_OFFSET, ns); |
128 | PUT_32BE(ph + PH_FILESZ, nnote); | 153 | PUT_32BE(ph + PH_FILESZ, nnote); |
@@ -134,11 +159,26 @@ main(int ac, char **av) | |||
134 | PUT_32BE(ns + 8, 0x1275); | 159 | PUT_32BE(ns + 8, 0x1275); |
135 | strcpy(&buf[ns + 12], arch); | 160 | strcpy(&buf[ns + 12], arch); |
136 | ns += 12 + strlen(arch) + 1; | 161 | ns += 12 + strlen(arch) + 1; |
137 | for (i = 0; i < N_DESCR; ++i) | 162 | for (i = 0; i < N_DESCR; ++i, ns += 4) |
138 | PUT_32BE(ns + i * 4, descr[i]); | 163 | PUT_32BE(ns, descr[i]); |
164 | |||
165 | /* fill in the second program header entry and the RPA note area */ | ||
166 | ph += ps; | ||
167 | PUT_32BE(ph + PH_TYPE, PT_NOTE); | ||
168 | PUT_32BE(ph + PH_OFFSET, ns); | ||
169 | PUT_32BE(ph + PH_FILESZ, nnote2); | ||
170 | |||
171 | /* fill in the note area we point to */ | ||
172 | PUT_32BE(ns, strlen(rpaname) + 1); | ||
173 | PUT_32BE(ns + 4, sizeof(rpanote)); | ||
174 | PUT_32BE(ns + 8, 0x12759999); | ||
175 | strcpy(&buf[ns + 12], rpaname); | ||
176 | ns += 12 + ROUNDUP(strlen(rpaname) + 1); | ||
177 | for (i = 0; i < N_RPA_DESCR; ++i, ns += 4) | ||
178 | PUT_32BE(ns, rpanote[i]); | ||
139 | 179 | ||
140 | /* Update the number of program headers */ | 180 | /* Update the number of program headers */ |
141 | PUT_16BE(E_PHNUM, np + 1); | 181 | PUT_16BE(E_PHNUM, np + 2); |
142 | 182 | ||
143 | /* write back */ | 183 | /* write back */ |
144 | lseek(fd, (long) 0, SEEK_SET); | 184 | lseek(fd, (long) 0, SEEK_SET); |
@@ -155,11 +195,11 @@ main(int ac, char **av) | |||
155 | exit(0); | 195 | exit(0); |
156 | 196 | ||
157 | notelf: | 197 | notelf: |
158 | fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]); | 198 | fprintf(stderr, "%s does not appear to be an ELF file\n", av[1]); |
159 | exit(1); | 199 | exit(1); |
160 | 200 | ||
161 | nospace: | 201 | nospace: |
162 | fprintf(stderr, "sorry, I can't find space in %s to put the note\n", | 202 | fprintf(stderr, "sorry, I can't find space in %s to put the note\n", |
163 | av[0]); | 203 | av[1]); |
164 | exit(1); | 204 | exit(1); |
165 | } | 205 | } |