diff options
Diffstat (limited to 'arch/sparc/boot')
-rw-r--r-- | arch/sparc/boot/piggyback_32.c | 142 |
1 files changed, 102 insertions, 40 deletions
diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index ac944aec7301..cfd95ec01f18 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c | |||
@@ -9,7 +9,7 @@ | |||
9 | it under the terms of the GNU General Public License as published by | 9 | it under the terms of the GNU General Public License as published by |
10 | the Free Software Foundation; either version 2 of the License, or | 10 | the Free Software Foundation; either version 2 of the License, or |
11 | (at your option) any later version. | 11 | (at your option) any later version. |
12 | 12 | ||
13 | This program is distributed in the hope that it will be useful, | 13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
@@ -18,15 +18,16 @@ | |||
18 | You should have received a copy of the GNU General Public License | 18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software | 19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | 20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
21 | 21 | ||
22 | #include <stdio.h> | 22 | #include <dirent.h> |
23 | #include <stdlib.h> | ||
23 | #include <string.h> | 24 | #include <string.h> |
25 | #include <unistd.h> | ||
24 | #include <ctype.h> | 26 | #include <ctype.h> |
25 | #include <errno.h> | 27 | #include <errno.h> |
26 | #include <fcntl.h> | 28 | #include <fcntl.h> |
27 | #include <dirent.h> | 29 | #include <stdio.h> |
28 | #include <unistd.h> | 30 | |
29 | #include <stdlib.h> | ||
30 | #include <sys/types.h> | 31 | #include <sys/types.h> |
31 | #include <sys/stat.h> | 32 | #include <sys/stat.h> |
32 | 33 | ||
@@ -35,16 +36,19 @@ | |||
35 | * as PROM looks for a.out image only. | 36 | * as PROM looks for a.out image only. |
36 | */ | 37 | */ |
37 | 38 | ||
39 | /* read two bytes as big endian */ | ||
38 | static unsigned short ld2(char *p) | 40 | static unsigned short ld2(char *p) |
39 | { | 41 | { |
40 | return (p[0] << 8) | p[1]; | 42 | return (p[0] << 8) | p[1]; |
41 | } | 43 | } |
42 | 44 | ||
45 | /* read 4 bytes as big endian */ | ||
43 | static unsigned int ld4(char *p) | 46 | static unsigned int ld4(char *p) |
44 | { | 47 | { |
45 | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | 48 | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; |
46 | } | 49 | } |
47 | 50 | ||
51 | /* save 4 bytes as big endian */ | ||
48 | static void st4(char *p, unsigned int x) | 52 | static void st4(char *p, unsigned int x) |
49 | { | 53 | { |
50 | p[0] = x >> 24; | 54 | p[0] = x >> 24; |
@@ -53,6 +57,12 @@ static void st4(char *p, unsigned int x) | |||
53 | p[3] = x; | 57 | p[3] = x; |
54 | } | 58 | } |
55 | 59 | ||
60 | static void die(const char *str) | ||
61 | { | ||
62 | perror(str); | ||
63 | exit(1); | ||
64 | } | ||
65 | |||
56 | static void usage(void) | 66 | static void usage(void) |
57 | { | 67 | { |
58 | /* fs_img.gz is an image of initial ramdisk. */ | 68 | /* fs_img.gz is an image of initial ramdisk. */ |
@@ -61,10 +71,57 @@ static void usage(void) | |||
61 | exit(1); | 71 | exit(1); |
62 | } | 72 | } |
63 | 73 | ||
64 | static void die(char *str) | 74 | static int start_line(const char *line) |
65 | { | 75 | { |
66 | perror (str); | 76 | if (strcmp(line + 8, " T start\n") == 0) |
67 | exit(1); | 77 | return 1; |
78 | else if (strcmp(line + 16, " T start\n") == 0) | ||
79 | return 1; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int end_line(const char *line) | ||
84 | { | ||
85 | if (strcmp(line + 8, " A _end\n") == 0) | ||
86 | return 1; | ||
87 | else if (strcmp (line + 16, " A _end\n") == 0) | ||
88 | return 1; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Find address for start and end in System.map. | ||
94 | * The file looks like this: | ||
95 | * f0004000 T start | ||
96 | * f0379f79 A _end | ||
97 | * 1234567890123456 | ||
98 | * ^coloumn 1 | ||
99 | * There is support for 64 bit addresses too. | ||
100 | * | ||
101 | * Return 0 if either start or end is not found | ||
102 | */ | ||
103 | static int get_start_end(const char *filename, unsigned int *start, unsigned int *end) | ||
104 | { | ||
105 | FILE *map; | ||
106 | char buffer[1024]; | ||
107 | |||
108 | *start = 0; | ||
109 | *end = 0; | ||
110 | map = fopen(filename, "r"); | ||
111 | if (!map) | ||
112 | die(filename); | ||
113 | while (fgets(buffer, 1024, map)) { | ||
114 | if (start_line(buffer)) | ||
115 | *start = strtoul(buffer, NULL, 16); | ||
116 | else if (end_line(buffer)) | ||
117 | *end = strtoul(buffer, NULL, 16); | ||
118 | } | ||
119 | fclose (map); | ||
120 | |||
121 | if (*start == 0 || *end == 0) | ||
122 | return 0; | ||
123 | |||
124 | return 1; | ||
68 | } | 125 | } |
69 | 126 | ||
70 | int main(int argc,char **argv) | 127 | int main(int argc,char **argv) |
@@ -72,33 +129,29 @@ int main(int argc,char **argv) | |||
72 | static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; | 129 | static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; |
73 | char buffer[1024], *q, *r; | 130 | char buffer[1024], *q, *r; |
74 | unsigned int i, j, k, start, end, offset; | 131 | unsigned int i, j, k, start, end, offset; |
75 | FILE *map; | ||
76 | struct stat s; | 132 | struct stat s; |
77 | int image, tail; | 133 | int image, tail; |
78 | 134 | ||
79 | if (argc != 4) usage(); | 135 | if (argc != 4) |
80 | start = end = 0; | 136 | usage(); |
81 | if (stat (argv[3], &s) < 0) die (argv[3]); | 137 | if (stat (argv[3], &s) < 0) |
82 | map = fopen (argv[2], "r"); | 138 | die(argv[3]); |
83 | if (!map) die(argv[2]); | 139 | |
84 | while (fgets (buffer, 1024, map)) { | 140 | if (!get_start_end(argv[2], &start, &end)) { |
85 | if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n")) | 141 | fprintf (stderr, "Could not determine start and end from %s\n", argv[2]); |
86 | start = strtoul (buffer, NULL, 16); | ||
87 | else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n")) | ||
88 | end = strtoul (buffer, NULL, 16); | ||
89 | } | ||
90 | fclose (map); | ||
91 | if (!start || !end) { | ||
92 | fprintf (stderr, "Could not determine start and end from System.map\n"); | ||
93 | exit(1); | 142 | exit(1); |
94 | } | 143 | } |
95 | if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]); | 144 | if ((image = open(argv[1], O_RDWR)) < 0) |
96 | if (read(image,buffer,512) != 512) die(argv[1]); | 145 | die(argv[1]); |
146 | if (read(image, buffer, 512) != 512) | ||
147 | die(argv[1]); | ||
97 | if (memcmp (buffer, "\177ELF", 4) == 0) { | 148 | if (memcmp (buffer, "\177ELF", 4) == 0) { |
98 | q = buffer + ld4(buffer + 28); | 149 | q = buffer + ld4(buffer + 28); |
99 | i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8); | 150 | i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8); |
100 | if (lseek(image,i,0) < 0) die("lseek"); | 151 | if (lseek(image, i, 0) < 0) |
101 | if (read(image,buffer,512) != 512) die(argv[1]); | 152 | die("lseek"); |
153 | if (read(image, buffer, 512) != 512) | ||
154 | die(argv[1]); | ||
102 | j = 0; | 155 | j = 0; |
103 | } else if (memcmp(buffer, aout_magic, 4) == 0) { | 156 | } else if (memcmp(buffer, aout_magic, 4) == 0) { |
104 | i = j = 32; | 157 | i = j = 32; |
@@ -107,9 +160,11 @@ int main(int argc,char **argv) | |||
107 | exit(1); | 160 | exit(1); |
108 | } | 161 | } |
109 | k = i; | 162 | k = i; |
110 | i += (ld2(buffer + j + 2)<<2) - 512; | 163 | i += (ld2(buffer + j + 2) << 2) - 512; |
111 | if (lseek(image,i,0) < 0) die("lseek"); | 164 | if (lseek(image, i, 0) < 0) |
112 | if (read(image,buffer,1024) != 1024) die(argv[1]); | 165 | die("lseek"); |
166 | if (read(image, buffer, 1024) != 1024) | ||
167 | die(argv[1]); | ||
113 | for (q = buffer, r = q + 512; q < r; q += 4) { | 168 | for (q = buffer, r = q + 512; q < r; q += 4) { |
114 | if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') | 169 | if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') |
115 | break; | 170 | break; |
@@ -119,19 +174,26 @@ int main(int argc,char **argv) | |||
119 | exit(1); | 174 | exit(1); |
120 | } | 175 | } |
121 | offset = i + (q - buffer) + 10; | 176 | offset = i + (q - buffer) + 10; |
122 | if (lseek(image, offset, 0) < 0) die ("lseek"); | 177 | if (lseek(image, offset, 0) < 0) |
178 | die("lseek"); | ||
123 | 179 | ||
124 | st4(buffer, 0); | 180 | st4(buffer, 0); |
125 | st4(buffer + 4, 0x01000000); | 181 | st4(buffer + 4, 0x01000000); |
126 | st4(buffer + 8, (end + 32 + 4095) & ~4095); | 182 | st4(buffer + 8, (end + 32 + 4095) & ~4095); |
127 | st4(buffer + 12, s.st_size); | 183 | st4(buffer + 12, s.st_size); |
128 | 184 | ||
129 | if (write(image,buffer+2,14) != 14) die (argv[1]); | 185 | if (write(image, buffer + 2, 14) != 14) |
130 | if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek"); | 186 | die(argv[1]); |
131 | if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); | 187 | if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) |
132 | while ((i = read (tail,buffer,1024)) > 0) | 188 | die("lseek"); |
133 | if (write(image,buffer,i) != i) die (argv[1]); | 189 | if ((tail = open(argv[3],O_RDONLY)) < 0) |
134 | if (close(image) < 0) die("close"); | 190 | die(argv[3]); |
135 | if (close(tail) < 0) die("close"); | 191 | while ((i = read (tail, buffer, 1024)) > 0) |
136 | return 0; | 192 | if (write(image, buffer, i) != i) |
193 | die(argv[1]); | ||
194 | if (close(image) < 0) | ||
195 | die("close"); | ||
196 | if (close(tail) < 0) | ||
197 | die("close"); | ||
198 | return 0; | ||
137 | } | 199 | } |