diff options
Diffstat (limited to 'arch/sparc/boot/piggyback_32.c')
-rw-r--r-- | arch/sparc/boot/piggyback_32.c | 97 |
1 files changed, 77 insertions, 20 deletions
diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index c4b0843f56ad..d56e9de85d27 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c | |||
@@ -107,7 +107,8 @@ static int end_line(const char *line) | |||
107 | * | 107 | * |
108 | * Return 0 if either start or end is not found | 108 | * Return 0 if either start or end is not found |
109 | */ | 109 | */ |
110 | static int get_start_end(const char *filename, unsigned int *start, unsigned int *end) | 110 | static int get_start_end(const char *filename, unsigned int *start, |
111 | unsigned int *end) | ||
111 | { | 112 | { |
112 | FILE *map; | 113 | FILE *map; |
113 | char buffer[1024]; | 114 | char buffer[1024]; |
@@ -131,11 +132,60 @@ static int get_start_end(const char *filename, unsigned int *start, unsigned int | |||
131 | return 1; | 132 | return 1; |
132 | } | 133 | } |
133 | 134 | ||
135 | #define LOOKBACK (128 * 4) | ||
136 | #define BUFSIZE 1024 | ||
137 | /* | ||
138 | * Find the HdrS entry from head_32/head_64. | ||
139 | * We check if it is at the beginning of the file (sparc64 case) | ||
140 | * and if not we search for it. | ||
141 | * When we search do so in steps of 4 as HdrS is on a 4-byte aligned | ||
142 | * address (it is on same alignment as sparc instructions) | ||
143 | * Return the offset to the HdrS entry (as off_t) | ||
144 | */ | ||
145 | static off_t get_hdrs_offset(int kernelfd, const char *filename) | ||
146 | { | ||
147 | char buffer[BUFSIZE]; | ||
148 | off_t offset; | ||
149 | int i; | ||
150 | |||
151 | if (lseek(kernelfd, 0, SEEK_SET) < 0) | ||
152 | die("lseek"); | ||
153 | if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) | ||
154 | die(filename); | ||
155 | |||
156 | if (buffer[40] == 'H' && buffer[41] == 'd' && | ||
157 | buffer[42] == 'r' && buffer[43] == 'S') { | ||
158 | return 40; | ||
159 | } else { | ||
160 | /* Find the gokernel label */ | ||
161 | /* Decode offset from branch instruction */ | ||
162 | offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2; | ||
163 | /* Go back 512 bytes so we do not miss HdrS */ | ||
164 | offset -= LOOKBACK; | ||
165 | /* skip a.out header */ | ||
166 | offset += AOUT_TEXT_OFFSET; | ||
167 | if (lseek(kernelfd, offset, SEEK_SET) < 0) | ||
168 | die("lseek"); | ||
169 | if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) | ||
170 | die(filename); | ||
171 | |||
172 | for (i = 0; i < LOOKBACK; i += 4) { | ||
173 | if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' && | ||
174 | buffer[i + 2] == 'r' && buffer[i + 3] == 'S') { | ||
175 | return offset + i; | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | fprintf (stderr, "Couldn't find headers signature in %s\n", filename); | ||
180 | exit(1); | ||
181 | } | ||
182 | |||
134 | int main(int argc,char **argv) | 183 | int main(int argc,char **argv) |
135 | { | 184 | { |
136 | static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; | 185 | static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; |
137 | char buffer[1024], *q, *r; | 186 | char buffer[1024]; |
138 | unsigned int i, start, end, offset; | 187 | unsigned int i, start, end; |
188 | off_t offset; | ||
139 | struct stat s; | 189 | struct stat s; |
140 | int image, tail; | 190 | int image, tail; |
141 | 191 | ||
@@ -147,7 +197,8 @@ int main(int argc,char **argv) | |||
147 | die(argv[4]); | 197 | die(argv[4]); |
148 | 198 | ||
149 | if (!get_start_end(argv[3], &start, &end)) { | 199 | if (!get_start_end(argv[3], &start, &end)) { |
150 | fprintf (stderr, "Could not determine start and end from %s\n", argv[3]); | 200 | fprintf(stderr, "Could not determine start and end from %s\n", |
201 | argv[3]); | ||
151 | exit(1); | 202 | exit(1); |
152 | } | 203 | } |
153 | if ((image = open(argv[2], O_RDWR)) < 0) | 204 | if ((image = open(argv[2], O_RDWR)) < 0) |
@@ -159,27 +210,17 @@ int main(int argc,char **argv) | |||
159 | exit(1); | 210 | exit(1); |
160 | } | 211 | } |
161 | /* | 212 | /* |
162 | * We need to fill in values for sparc_ramdisk_image + sparc_ramdisk_size | 213 | * We need to fill in values for |
214 | * sparc_ramdisk_image + sparc_ramdisk_size | ||
163 | * To locate these symbols search for the "HdrS" text which appear | 215 | * To locate these symbols search for the "HdrS" text which appear |
164 | * in the image a little before the gokernel symbol. | 216 | * in the image a little before the gokernel symbol. |
165 | * See definition of these in init_32.S | 217 | * See definition of these in init_32.S |
166 | */ | 218 | */ |
167 | 219 | ||
168 | /* Find the gokernel label */ | 220 | offset = get_hdrs_offset(image, argv[2]); |
169 | i = AOUT_TEXT_OFFSET + (ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2) - 512; | 221 | /* skip HdrS + LINUX_VERSION_CODE + HdrS version */ |
170 | if (lseek(image, i, 0) < 0) | 222 | offset += 10; |
171 | die("lseek"); | 223 | |
172 | if (read(image, buffer, 1024) != 1024) | ||
173 | die(argv[2]); | ||
174 | for (q = buffer, r = q + 512; q < r; q += 4) { | ||
175 | if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') | ||
176 | break; | ||
177 | } | ||
178 | if (q == r) { | ||
179 | fprintf (stderr, "Couldn't find headers signature in the kernel.\n"); | ||
180 | exit(1); | ||
181 | } | ||
182 | offset = i + (q - buffer) + 10; | ||
183 | if (lseek(image, offset, 0) < 0) | 224 | if (lseek(image, offset, 0) < 0) |
184 | die("lseek"); | 225 | die("lseek"); |
185 | 226 | ||
@@ -198,6 +239,22 @@ int main(int argc,char **argv) | |||
198 | if (write(image, buffer + 2, 14) != 14) | 239 | if (write(image, buffer + 2, 14) != 14) |
199 | die(argv[2]); | 240 | die(argv[2]); |
200 | 241 | ||
242 | /* For sparc64 update a_text and clear a_data + a_bss */ | ||
243 | if (is64bit) | ||
244 | { | ||
245 | if (lseek(image, 4, 0) < 0) | ||
246 | die("lseek"); | ||
247 | /* a_text */ | ||
248 | st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) + | ||
249 | s.st_size); | ||
250 | /* a_data */ | ||
251 | st4(buffer + 4, 0); | ||
252 | /* a_bss */ | ||
253 | st4(buffer + 8, 0); | ||
254 | if (write(image, buffer, 12) != 12) | ||
255 | die(argv[2]); | ||
256 | } | ||
257 | |||
201 | /* seek page aligned boundary in the image file and add boot image */ | 258 | /* seek page aligned boundary in the image file and add boot image */ |
202 | if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) | 259 | if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) |
203 | die("lseek"); | 260 | die("lseek"); |