Blame view
arch/sparc/boot/piggyback.c
6.59 KB
88278ca27 sparc: remove CVS... |
1 |
/* |
1da177e4c Linux-2.6.12-rc2 |
2 3 |
Simple utility to make a single-image install kernel with initial ramdisk for Sparc tftpbooting without need to set up nfs. |
050855887 sparc: update cop... |
4 |
Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) |
1da177e4c Linux-2.6.12-rc2 |
5 |
Pete Zaitcev <zaitcev@yahoo.com> endian fixes for cross-compiles, 2000. |
050855887 sparc: update cop... |
6 |
Copyright (C) 2011 Sam Ravnborg <sam@ravnborg.org> |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 11 |
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. |
2fe74fa96 sparc: refactor p... |
12 |
|
1da177e4c Linux-2.6.12-rc2 |
13 14 15 16 17 18 19 20 |
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., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
2fe74fa96 sparc: refactor p... |
21 22 23 |
#include <dirent.h> #include <stdlib.h> |
1da177e4c Linux-2.6.12-rc2 |
24 |
#include <string.h> |
2fe74fa96 sparc: refactor p... |
25 |
#include <unistd.h> |
1da177e4c Linux-2.6.12-rc2 |
26 27 28 |
#include <ctype.h> #include <errno.h> #include <fcntl.h> |
2fe74fa96 sparc: refactor p... |
29 |
#include <stdio.h> |
1da177e4c Linux-2.6.12-rc2 |
30 31 32 33 34 35 36 |
#include <sys/types.h> #include <sys/stat.h> /* * Note: run this on an a.out kernel (use elftoaout for it), * as PROM looks for a.out image only. */ |
9c2390530 sparc: additional... |
37 |
#define AOUT_TEXT_OFFSET 32 |
a020bb17b sparc: add $BITS ... |
38 39 40 41 42 43 44 45 46 47 |
static int is64bit = 0; /* align to power-of-two size */ static int align(int n) { if (is64bit) return (n + 0x1fff) & ~0x1fff; else return (n + 0xfff) & ~0xfff; } |
2fe74fa96 sparc: refactor p... |
48 |
/* read two bytes as big endian */ |
c843e3154 arch/sparc/boot/*... |
49 |
static unsigned short ld2(char *p) |
1da177e4c Linux-2.6.12-rc2 |
50 51 52 |
{ return (p[0] << 8) | p[1]; } |
2fe74fa96 sparc: refactor p... |
53 |
/* save 4 bytes as big endian */ |
c843e3154 arch/sparc/boot/*... |
54 |
static void st4(char *p, unsigned int x) |
1da177e4c Linux-2.6.12-rc2 |
55 56 57 58 59 60 |
{ p[0] = x >> 24; p[1] = x >> 16; p[2] = x >> 8; p[3] = x; } |
2fe74fa96 sparc: refactor p... |
61 62 63 64 65 |
static void die(const char *str) { perror(str); exit(1); } |
c843e3154 arch/sparc/boot/*... |
66 |
static void usage(void) |
1da177e4c Linux-2.6.12-rc2 |
67 68 |
{ /* fs_img.gz is an image of initial ramdisk. */ |
a020bb17b sparc: add $BITS ... |
69 70 |
fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz "); |
1da177e4c Linux-2.6.12-rc2 |
71 72 73 74 |
fprintf(stderr, "\tKernel image will be modified in place. "); exit(1); } |
2fe74fa96 sparc: refactor p... |
75 |
static int start_line(const char *line) |
1da177e4c Linux-2.6.12-rc2 |
76 |
{ |
b2a39b0d8 sparc: use _start... |
77 78 |
if (strcmp(line + 8, " T _start ") == 0) |
2fe74fa96 sparc: refactor p... |
79 |
return 1; |
b2a39b0d8 sparc: use _start... |
80 81 |
else if (strcmp(line + 16, " T _start ") == 0) |
2fe74fa96 sparc: refactor p... |
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
return 1; return 0; } static int end_line(const char *line) { if (strcmp(line + 8, " A _end ") == 0) return 1; else if (strcmp (line + 16, " A _end ") == 0) return 1; return 0; } /* * Find address for start and end in System.map. * The file looks like this: |
b2a39b0d8 sparc: use _start... |
100 |
* f0004000 T _start |
2fe74fa96 sparc: refactor p... |
101 102 103 104 105 106 107 |
* f0379f79 A _end * 1234567890123456 * ^coloumn 1 * There is support for 64 bit addresses too. * * Return 0 if either start or end is not found */ |
1075c4ef7 sparc: fix tftpbo... |
108 109 |
static int get_start_end(const char *filename, unsigned int *start, unsigned int *end) |
2fe74fa96 sparc: refactor p... |
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
{ FILE *map; char buffer[1024]; *start = 0; *end = 0; map = fopen(filename, "r"); if (!map) die(filename); while (fgets(buffer, 1024, map)) { if (start_line(buffer)) *start = strtoul(buffer, NULL, 16); else if (end_line(buffer)) *end = strtoul(buffer, NULL, 16); } fclose (map); if (*start == 0 || *end == 0) return 0; return 1; |
1da177e4c Linux-2.6.12-rc2 |
131 |
} |
1075c4ef7 sparc: fix tftpbo... |
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
#define LOOKBACK (128 * 4) #define BUFSIZE 1024 /* * Find the HdrS entry from head_32/head_64. * We check if it is at the beginning of the file (sparc64 case) * and if not we search for it. * When we search do so in steps of 4 as HdrS is on a 4-byte aligned * address (it is on same alignment as sparc instructions) * Return the offset to the HdrS entry (as off_t) */ static off_t get_hdrs_offset(int kernelfd, const char *filename) { char buffer[BUFSIZE]; off_t offset; int i; if (lseek(kernelfd, 0, SEEK_SET) < 0) die("lseek"); if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) die(filename); if (buffer[40] == 'H' && buffer[41] == 'd' && buffer[42] == 'r' && buffer[43] == 'S') { return 40; } else { /* Find the gokernel label */ /* Decode offset from branch instruction */ offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2; /* Go back 512 bytes so we do not miss HdrS */ offset -= LOOKBACK; /* skip a.out header */ offset += AOUT_TEXT_OFFSET; if (lseek(kernelfd, offset, SEEK_SET) < 0) die("lseek"); if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) die(filename); for (i = 0; i < LOOKBACK; i += 4) { if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' && buffer[i + 2] == 'r' && buffer[i + 3] == 'S') { return offset + i; } } } fprintf (stderr, "Couldn't find headers signature in %s ", filename); exit(1); } |
1da177e4c Linux-2.6.12-rc2 |
180 181 182 |
int main(int argc,char **argv) { static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; |
1075c4ef7 sparc: fix tftpbo... |
183 184 185 |
char buffer[1024]; unsigned int i, start, end; off_t offset; |
1da177e4c Linux-2.6.12-rc2 |
186 187 |
struct stat s; int image, tail; |
a020bb17b sparc: add $BITS ... |
188 |
if (argc != 5) |
2fe74fa96 sparc: refactor p... |
189 |
usage(); |
a020bb17b sparc: add $BITS ... |
190 191 192 193 |
if (strcmp(argv[1], "64") == 0) is64bit = 1; if (stat (argv[4], &s) < 0) die(argv[4]); |
2fe74fa96 sparc: refactor p... |
194 |
|
a020bb17b sparc: add $BITS ... |
195 |
if (!get_start_end(argv[3], &start, &end)) { |
1075c4ef7 sparc: fix tftpbo... |
196 197 198 |
fprintf(stderr, "Could not determine start and end from %s ", argv[3]); |
1da177e4c Linux-2.6.12-rc2 |
199 200 |
exit(1); } |
a020bb17b sparc: add $BITS ... |
201 202 |
if ((image = open(argv[2], O_RDWR)) < 0) die(argv[2]); |
2fe74fa96 sparc: refactor p... |
203 |
if (read(image, buffer, 512) != 512) |
a020bb17b sparc: add $BITS ... |
204 |
die(argv[2]); |
571e08f6e sparc: remove obs... |
205 206 207 |
if (memcmp(buffer, aout_magic, 4) != 0) { fprintf (stderr, "Not a.out. Don't blame me. "); |
1da177e4c Linux-2.6.12-rc2 |
208 209 |
exit(1); } |
9c2390530 sparc: additional... |
210 |
/* |
1075c4ef7 sparc: fix tftpbo... |
211 212 |
* We need to fill in values for * sparc_ramdisk_image + sparc_ramdisk_size |
9c2390530 sparc: additional... |
213 214 215 216 |
* To locate these symbols search for the "HdrS" text which appear * in the image a little before the gokernel symbol. * See definition of these in init_32.S */ |
1075c4ef7 sparc: fix tftpbo... |
217 218 219 |
offset = get_hdrs_offset(image, argv[2]); /* skip HdrS + LINUX_VERSION_CODE + HdrS version */ offset += 10; |
2fe74fa96 sparc: refactor p... |
220 221 |
if (lseek(image, offset, 0) < 0) die("lseek"); |
1da177e4c Linux-2.6.12-rc2 |
222 |
|
9c2390530 sparc: additional... |
223 224 225 226 227 228 229 |
/* * root_flags = 0 * root_dev = 1 (RAMDISK_MAJOR) * ram_flags = 0 * sparc_ramdisk_image = "PAGE aligned address after _end") * sparc_ramdisk_size = size of image */ |
1da177e4c Linux-2.6.12-rc2 |
230 231 |
st4(buffer, 0); st4(buffer + 4, 0x01000000); |
a020bb17b sparc: add $BITS ... |
232 |
st4(buffer + 8, align(end + 32)); |
1da177e4c Linux-2.6.12-rc2 |
233 |
st4(buffer + 12, s.st_size); |
2fe74fa96 sparc: refactor p... |
234 |
if (write(image, buffer + 2, 14) != 14) |
a020bb17b sparc: add $BITS ... |
235 |
die(argv[2]); |
9c2390530 sparc: additional... |
236 |
|
1075c4ef7 sparc: fix tftpbo... |
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
/* For sparc64 update a_text and clear a_data + a_bss */ if (is64bit) { if (lseek(image, 4, 0) < 0) die("lseek"); /* a_text */ st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) + s.st_size); /* a_data */ st4(buffer + 4, 0); /* a_bss */ st4(buffer + 8, 0); if (write(image, buffer, 12) != 12) die(argv[2]); } |
9c2390530 sparc: additional... |
252 |
/* seek page aligned boundary in the image file and add boot image */ |
a020bb17b sparc: add $BITS ... |
253 |
if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) |
2fe74fa96 sparc: refactor p... |
254 |
die("lseek"); |
a020bb17b sparc: add $BITS ... |
255 256 |
if ((tail = open(argv[4], O_RDONLY)) < 0) die(argv[4]); |
9c2390530 sparc: additional... |
257 |
while ((i = read(tail, buffer, 1024)) > 0) |
2fe74fa96 sparc: refactor p... |
258 |
if (write(image, buffer, i) != i) |
a020bb17b sparc: add $BITS ... |
259 |
die(argv[2]); |
2fe74fa96 sparc: refactor p... |
260 261 262 263 264 |
if (close(image) < 0) die("close"); if (close(tail) < 0) die("close"); return 0; |
1da177e4c Linux-2.6.12-rc2 |
265 |
} |