diff options
Diffstat (limited to 'arch/ppc/boot/utils')
-rw-r--r-- | arch/ppc/boot/utils/addRamDisk.c | 203 | ||||
-rw-r--r-- | arch/ppc/boot/utils/addSystemMap.c | 186 | ||||
-rw-r--r-- | arch/ppc/boot/utils/addnote.c | 175 | ||||
-rw-r--r-- | arch/ppc/boot/utils/elf.pl | 33 | ||||
-rw-r--r-- | arch/ppc/boot/utils/hack-coff.c | 84 | ||||
-rw-r--r-- | arch/ppc/boot/utils/mkbugboot.c | 187 | ||||
-rw-r--r-- | arch/ppc/boot/utils/mknote.c | 44 | ||||
-rw-r--r-- | arch/ppc/boot/utils/mkprep.c | 293 | ||||
-rw-r--r-- | arch/ppc/boot/utils/mktree.c | 152 |
9 files changed, 1357 insertions, 0 deletions
diff --git a/arch/ppc/boot/utils/addRamDisk.c b/arch/ppc/boot/utils/addRamDisk.c new file mode 100644 index 000000000000..93400dfcce7f --- /dev/null +++ b/arch/ppc/boot/utils/addRamDisk.c | |||
@@ -0,0 +1,203 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <netinet/in.h> | ||
4 | #include <unistd.h> | ||
5 | #include <sys/types.h> | ||
6 | #include <sys/stat.h> | ||
7 | #include <string.h> | ||
8 | |||
9 | #define ElfHeaderSize (64 * 1024) | ||
10 | #define ElfPages (ElfHeaderSize / 4096) | ||
11 | #define KERNELBASE (0xc0000000) | ||
12 | |||
13 | void get4k(FILE *file, char *buf ) | ||
14 | { | ||
15 | unsigned j; | ||
16 | unsigned num = fread(buf, 1, 4096, file); | ||
17 | for ( j=num; j<4096; ++j ) | ||
18 | buf[j] = 0; | ||
19 | } | ||
20 | |||
21 | void put4k(FILE *file, char *buf ) | ||
22 | { | ||
23 | fwrite(buf, 1, 4096, file); | ||
24 | } | ||
25 | |||
26 | void death(const char *msg, FILE *fdesc, const char *fname) | ||
27 | { | ||
28 | printf(msg); | ||
29 | fclose(fdesc); | ||
30 | unlink(fname); | ||
31 | exit(1); | ||
32 | } | ||
33 | |||
34 | int main(int argc, char **argv) | ||
35 | { | ||
36 | char inbuf[4096]; | ||
37 | FILE *ramDisk = NULL; | ||
38 | FILE *inputVmlinux = NULL; | ||
39 | FILE *outputVmlinux = NULL; | ||
40 | unsigned i = 0; | ||
41 | u_int32_t ramFileLen = 0; | ||
42 | u_int32_t ramLen = 0; | ||
43 | u_int32_t roundR = 0; | ||
44 | u_int32_t kernelLen = 0; | ||
45 | u_int32_t actualKernelLen = 0; | ||
46 | u_int32_t round = 0; | ||
47 | u_int32_t roundedKernelLen = 0; | ||
48 | u_int32_t ramStartOffs = 0; | ||
49 | u_int32_t ramPages = 0; | ||
50 | u_int32_t roundedKernelPages = 0; | ||
51 | u_int32_t hvReleaseData = 0; | ||
52 | u_int32_t eyeCatcher = 0xc8a5d9c4; | ||
53 | u_int32_t naca = 0; | ||
54 | u_int32_t xRamDisk = 0; | ||
55 | u_int32_t xRamDiskSize = 0; | ||
56 | if ( argc < 2 ) { | ||
57 | printf("Name of RAM disk file missing.\n"); | ||
58 | exit(1); | ||
59 | } | ||
60 | |||
61 | if ( argc < 3 ) { | ||
62 | printf("Name of vmlinux file missing.\n"); | ||
63 | exit(1); | ||
64 | } | ||
65 | |||
66 | if ( argc < 4 ) { | ||
67 | printf("Name of vmlinux output file missing.\n"); | ||
68 | exit(1); | ||
69 | } | ||
70 | |||
71 | ramDisk = fopen(argv[1], "r"); | ||
72 | if ( ! ramDisk ) { | ||
73 | printf("RAM disk file \"%s\" failed to open.\n", argv[1]); | ||
74 | exit(1); | ||
75 | } | ||
76 | inputVmlinux = fopen(argv[2], "r"); | ||
77 | if ( ! inputVmlinux ) { | ||
78 | printf("vmlinux file \"%s\" failed to open.\n", argv[2]); | ||
79 | exit(1); | ||
80 | } | ||
81 | outputVmlinux = fopen(argv[3], "w+"); | ||
82 | if ( ! outputVmlinux ) { | ||
83 | printf("output vmlinux file \"%s\" failed to open.\n", argv[3]); | ||
84 | exit(1); | ||
85 | } | ||
86 | fseek(ramDisk, 0, SEEK_END); | ||
87 | ramFileLen = ftell(ramDisk); | ||
88 | fseek(ramDisk, 0, SEEK_SET); | ||
89 | printf("%s file size = %d\n", argv[1], ramFileLen); | ||
90 | |||
91 | ramLen = ramFileLen; | ||
92 | |||
93 | roundR = 4096 - (ramLen % 4096); | ||
94 | if ( roundR ) { | ||
95 | printf("Rounding RAM disk file up to a multiple of 4096, adding %d\n", roundR); | ||
96 | ramLen += roundR; | ||
97 | } | ||
98 | |||
99 | printf("Rounded RAM disk size is %d\n", ramLen); | ||
100 | fseek(inputVmlinux, 0, SEEK_END); | ||
101 | kernelLen = ftell(inputVmlinux); | ||
102 | fseek(inputVmlinux, 0, SEEK_SET); | ||
103 | printf("kernel file size = %d\n", kernelLen); | ||
104 | if ( kernelLen == 0 ) { | ||
105 | printf("You must have a linux kernel specified as argv[2]\n"); | ||
106 | exit(1); | ||
107 | } | ||
108 | |||
109 | actualKernelLen = kernelLen - ElfHeaderSize; | ||
110 | |||
111 | printf("actual kernel length (minus ELF header) = %d\n", actualKernelLen); | ||
112 | |||
113 | round = actualKernelLen % 4096; | ||
114 | roundedKernelLen = actualKernelLen; | ||
115 | if ( round ) | ||
116 | roundedKernelLen += (4096 - round); | ||
117 | |||
118 | printf("actual kernel length rounded up to a 4k multiple = %d\n", roundedKernelLen); | ||
119 | |||
120 | ramStartOffs = roundedKernelLen; | ||
121 | ramPages = ramLen / 4096; | ||
122 | |||
123 | printf("RAM disk pages to copy = %d\n", ramPages); | ||
124 | |||
125 | // Copy 64K ELF header | ||
126 | for (i=0; i<(ElfPages); ++i) { | ||
127 | get4k( inputVmlinux, inbuf ); | ||
128 | put4k( outputVmlinux, inbuf ); | ||
129 | } | ||
130 | |||
131 | roundedKernelPages = roundedKernelLen / 4096; | ||
132 | |||
133 | fseek(inputVmlinux, ElfHeaderSize, SEEK_SET); | ||
134 | |||
135 | for ( i=0; i<roundedKernelPages; ++i ) { | ||
136 | get4k( inputVmlinux, inbuf ); | ||
137 | put4k( outputVmlinux, inbuf ); | ||
138 | } | ||
139 | |||
140 | for ( i=0; i<ramPages; ++i ) { | ||
141 | get4k( ramDisk, inbuf ); | ||
142 | put4k( outputVmlinux, inbuf ); | ||
143 | } | ||
144 | |||
145 | /* Close the input files */ | ||
146 | fclose(ramDisk); | ||
147 | fclose(inputVmlinux); | ||
148 | /* And flush the written output file */ | ||
149 | fflush(outputVmlinux); | ||
150 | |||
151 | /* fseek to the hvReleaseData pointer */ | ||
152 | fseek(outputVmlinux, ElfHeaderSize + 0x24, SEEK_SET); | ||
153 | if (fread(&hvReleaseData, 4, 1, outputVmlinux) != 1) { | ||
154 | death("Could not read hvReleaseData pointer\n", outputVmlinux, argv[3]); | ||
155 | } | ||
156 | hvReleaseData = ntohl(hvReleaseData); /* Convert to native int */ | ||
157 | printf("hvReleaseData is at %08x\n", hvReleaseData); | ||
158 | |||
159 | /* fseek to the hvReleaseData */ | ||
160 | fseek(outputVmlinux, ElfHeaderSize + hvReleaseData, SEEK_SET); | ||
161 | if (fread(inbuf, 0x40, 1, outputVmlinux) != 1) { | ||
162 | death("Could not read hvReleaseData\n", outputVmlinux, argv[3]); | ||
163 | } | ||
164 | /* Check hvReleaseData sanity */ | ||
165 | if (memcmp(inbuf, &eyeCatcher, 4) != 0) { | ||
166 | death("hvReleaseData is invalid\n", outputVmlinux, argv[3]); | ||
167 | } | ||
168 | /* Get the naca pointer */ | ||
169 | naca = ntohl(*((u_int32_t *) &inbuf[0x0c])) - KERNELBASE; | ||
170 | printf("naca is at %08x\n", naca); | ||
171 | |||
172 | /* fseek to the naca */ | ||
173 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); | ||
174 | if (fread(inbuf, 0x18, 1, outputVmlinux) != 1) { | ||
175 | death("Could not read naca\n", outputVmlinux, argv[3]); | ||
176 | } | ||
177 | xRamDisk = ntohl(*((u_int32_t *) &inbuf[0x0c])); | ||
178 | xRamDiskSize = ntohl(*((u_int32_t *) &inbuf[0x14])); | ||
179 | /* Make sure a RAM disk isn't already present */ | ||
180 | if ((xRamDisk != 0) || (xRamDiskSize != 0)) { | ||
181 | death("RAM disk is already attached to this kernel\n", outputVmlinux, argv[3]); | ||
182 | } | ||
183 | /* Fill in the values */ | ||
184 | *((u_int32_t *) &inbuf[0x0c]) = htonl(ramStartOffs); | ||
185 | *((u_int32_t *) &inbuf[0x14]) = htonl(ramPages); | ||
186 | |||
187 | /* Write out the new naca */ | ||
188 | fflush(outputVmlinux); | ||
189 | fseek(outputVmlinux, ElfHeaderSize + naca, SEEK_SET); | ||
190 | if (fwrite(inbuf, 0x18, 1, outputVmlinux) != 1) { | ||
191 | death("Could not write naca\n", outputVmlinux, argv[3]); | ||
192 | } | ||
193 | printf("RAM Disk of 0x%x pages size is attached to the kernel at offset 0x%08x\n", | ||
194 | ramPages, ramStartOffs); | ||
195 | |||
196 | /* Done */ | ||
197 | fclose(outputVmlinux); | ||
198 | /* Set permission to executable */ | ||
199 | chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
diff --git a/arch/ppc/boot/utils/addSystemMap.c b/arch/ppc/boot/utils/addSystemMap.c new file mode 100644 index 000000000000..4654f891b274 --- /dev/null +++ b/arch/ppc/boot/utils/addSystemMap.c | |||
@@ -0,0 +1,186 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <byteswap.h> | ||
4 | #include <sys/types.h> | ||
5 | #include <sys/stat.h> | ||
6 | |||
7 | void xlate( char * inb, char * trb, unsigned len ) | ||
8 | { | ||
9 | unsigned i; | ||
10 | for ( i=0; i<len; ++i ) { | ||
11 | char c = *inb++; | ||
12 | char c1 = c >> 4; | ||
13 | char c2 = c & 0xf; | ||
14 | if ( c1 > 9 ) | ||
15 | c1 = c1 + 'A' - 10; | ||
16 | else | ||
17 | c1 = c1 + '0'; | ||
18 | if ( c2 > 9 ) | ||
19 | c2 = c2 + 'A' - 10; | ||
20 | else | ||
21 | c2 = c2 + '0'; | ||
22 | *trb++ = c1; | ||
23 | *trb++ = c2; | ||
24 | } | ||
25 | *trb = 0; | ||
26 | } | ||
27 | |||
28 | #define ElfHeaderSize (64 * 1024) | ||
29 | #define ElfPages (ElfHeaderSize / 4096) | ||
30 | #define KERNELBASE (0xc0000000) | ||
31 | |||
32 | void get4k( /*istream *inf*/FILE *file, char *buf ) | ||
33 | { | ||
34 | unsigned j; | ||
35 | unsigned num = fread(buf, 1, 4096, file); | ||
36 | for ( j=num; j<4096; ++j ) | ||
37 | buf[j] = 0; | ||
38 | } | ||
39 | |||
40 | void put4k( /*ostream *outf*/FILE *file, char *buf ) | ||
41 | { | ||
42 | fwrite(buf, 1, 4096, file); | ||
43 | } | ||
44 | |||
45 | int main(int argc, char **argv) | ||
46 | { | ||
47 | char inbuf[4096]; | ||
48 | FILE *ramDisk = NULL; | ||
49 | FILE *inputVmlinux = NULL; | ||
50 | FILE *outputVmlinux = NULL; | ||
51 | unsigned i = 0; | ||
52 | unsigned long ramFileLen = 0; | ||
53 | unsigned long ramLen = 0; | ||
54 | unsigned long roundR = 0; | ||
55 | unsigned long kernelLen = 0; | ||
56 | unsigned long actualKernelLen = 0; | ||
57 | unsigned long round = 0; | ||
58 | unsigned long roundedKernelLen = 0; | ||
59 | unsigned long ramStartOffs = 0; | ||
60 | unsigned long ramPages = 0; | ||
61 | unsigned long roundedKernelPages = 0; | ||
62 | if ( argc < 2 ) { | ||
63 | printf("Name of System Map file missing.\n"); | ||
64 | exit(1); | ||
65 | } | ||
66 | |||
67 | if ( argc < 3 ) { | ||
68 | printf("Name of vmlinux file missing.\n"); | ||
69 | exit(1); | ||
70 | } | ||
71 | |||
72 | if ( argc < 4 ) { | ||
73 | printf("Name of vmlinux output file missing.\n"); | ||
74 | exit(1); | ||
75 | } | ||
76 | |||
77 | ramDisk = fopen(argv[1], "r"); | ||
78 | if ( ! ramDisk ) { | ||
79 | printf("System Map file \"%s\" failed to open.\n", argv[1]); | ||
80 | exit(1); | ||
81 | } | ||
82 | inputVmlinux = fopen(argv[2], "r"); | ||
83 | if ( ! inputVmlinux ) { | ||
84 | printf("vmlinux file \"%s\" failed to open.\n", argv[2]); | ||
85 | exit(1); | ||
86 | } | ||
87 | outputVmlinux = fopen(argv[3], "w"); | ||
88 | if ( ! outputVmlinux ) { | ||
89 | printf("output vmlinux file \"%s\" failed to open.\n", argv[3]); | ||
90 | exit(1); | ||
91 | } | ||
92 | fseek(ramDisk, 0, SEEK_END); | ||
93 | ramFileLen = ftell(ramDisk); | ||
94 | fseek(ramDisk, 0, SEEK_SET); | ||
95 | printf("%s file size = %ld\n", argv[1], ramFileLen); | ||
96 | |||
97 | ramLen = ramFileLen; | ||
98 | |||
99 | roundR = 4096 - (ramLen % 4096); | ||
100 | if ( roundR ) { | ||
101 | printf("Rounding System Map file up to a multiple of 4096, adding %ld\n", roundR); | ||
102 | ramLen += roundR; | ||
103 | } | ||
104 | |||
105 | printf("Rounded System Map size is %ld\n", ramLen); | ||
106 | fseek(inputVmlinux, 0, SEEK_END); | ||
107 | kernelLen = ftell(inputVmlinux); | ||
108 | fseek(inputVmlinux, 0, SEEK_SET); | ||
109 | printf("kernel file size = %ld\n", kernelLen); | ||
110 | if ( kernelLen == 0 ) { | ||
111 | printf("You must have a linux kernel specified as argv[2]\n"); | ||
112 | exit(1); | ||
113 | } | ||
114 | |||
115 | actualKernelLen = kernelLen - ElfHeaderSize; | ||
116 | |||
117 | printf("actual kernel length (minus ELF header) = %ld\n", actualKernelLen); | ||
118 | |||
119 | round = actualKernelLen % 4096; | ||
120 | roundedKernelLen = actualKernelLen; | ||
121 | if ( round ) | ||
122 | roundedKernelLen += (4096 - round); | ||
123 | |||
124 | printf("actual kernel length rounded up to a 4k multiple = %ld\n", roundedKernelLen); | ||
125 | |||
126 | ramStartOffs = roundedKernelLen; | ||
127 | ramPages = ramLen / 4096; | ||
128 | |||
129 | printf("System map pages to copy = %ld\n", ramPages); | ||
130 | |||
131 | // Copy 64K ELF header | ||
132 | for (i=0; i<(ElfPages); ++i) { | ||
133 | get4k( inputVmlinux, inbuf ); | ||
134 | put4k( outputVmlinux, inbuf ); | ||
135 | } | ||
136 | |||
137 | |||
138 | |||
139 | roundedKernelPages = roundedKernelLen / 4096; | ||
140 | |||
141 | fseek(inputVmlinux, ElfHeaderSize, SEEK_SET); | ||
142 | |||
143 | { | ||
144 | for ( i=0; i<roundedKernelPages; ++i ) { | ||
145 | get4k( inputVmlinux, inbuf ); | ||
146 | if ( i == 0 ) { | ||
147 | unsigned long * p; | ||
148 | printf("Storing embedded_sysmap_start at 0x3c\n"); | ||
149 | p = (unsigned long *)(inbuf + 0x3c); | ||
150 | |||
151 | #if (BYTE_ORDER == __BIG_ENDIAN) | ||
152 | *p = ramStartOffs; | ||
153 | #else | ||
154 | *p = bswap_32(ramStartOffs); | ||
155 | #endif | ||
156 | |||
157 | printf("Storing embedded_sysmap_end at 0x44\n"); | ||
158 | p = (unsigned long *)(inbuf + 0x44); | ||
159 | #if (BYTE_ORDER == __BIG_ENDIAN) | ||
160 | *p = ramStartOffs + ramFileLen; | ||
161 | #else | ||
162 | *p = bswap_32(ramStartOffs + ramFileLen); | ||
163 | #endif | ||
164 | } | ||
165 | put4k( outputVmlinux, inbuf ); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | { | ||
170 | for ( i=0; i<ramPages; ++i ) { | ||
171 | get4k( ramDisk, inbuf ); | ||
172 | put4k( outputVmlinux, inbuf ); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | |||
177 | fclose(ramDisk); | ||
178 | fclose(inputVmlinux); | ||
179 | fclose(outputVmlinux); | ||
180 | /* Set permission to executable */ | ||
181 | chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); | ||
182 | |||
183 | return 0; | ||
184 | |||
185 | } | ||
186 | |||
diff --git a/arch/ppc/boot/utils/addnote.c b/arch/ppc/boot/utils/addnote.c new file mode 100644 index 000000000000..6c52b18f2d04 --- /dev/null +++ b/arch/ppc/boot/utils/addnote.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * Program to hack in a PT_NOTE program header entry in an ELF file. | ||
3 | * This is needed for OF on RS/6000s to load an image correctly. | ||
4 | * Note that OF needs a program header entry for the note, not an | ||
5 | * ELF section. | ||
6 | * | ||
7 | * Copyright 2000 Paul Mackerras. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | * | ||
14 | * Usage: addnote zImage | ||
15 | */ | ||
16 | #include <stdio.h> | ||
17 | #include <stdlib.h> | ||
18 | #include <fcntl.h> | ||
19 | #include <unistd.h> | ||
20 | #include <string.h> | ||
21 | |||
22 | char arch[] = "PowerPC"; | ||
23 | |||
24 | #define N_DESCR 6 | ||
25 | unsigned int descr[N_DESCR] = { | ||
26 | #if 1 | ||
27 | /* values for IBM RS/6000 machines */ | ||
28 | 0xffffffff, /* real-mode = true */ | ||
29 | 0x00c00000, /* real-base, i.e. where we expect OF to be */ | ||
30 | 0xffffffff, /* real-size */ | ||
31 | 0xffffffff, /* virt-base */ | ||
32 | 0xffffffff, /* virt-size */ | ||
33 | 0x4000, /* load-base */ | ||
34 | #else | ||
35 | /* values for longtrail CHRP */ | ||
36 | 0, /* real-mode = false */ | ||
37 | 0xffffffff, /* real-base */ | ||
38 | 0xffffffff, /* real-size */ | ||
39 | 0xffffffff, /* virt-base */ | ||
40 | 0xffffffff, /* virt-size */ | ||
41 | 0x00600000, /* load-base */ | ||
42 | #endif | ||
43 | }; | ||
44 | |||
45 | unsigned char buf[512]; | ||
46 | |||
47 | #define GET_16BE(off) ((buf[off] << 8) + (buf[(off)+1])) | ||
48 | #define GET_32BE(off) ((GET_16BE(off) << 16) + GET_16BE((off)+2)) | ||
49 | |||
50 | #define PUT_16BE(off, v) (buf[off] = ((v) >> 8) & 0xff, \ | ||
51 | buf[(off) + 1] = (v) & 0xff) | ||
52 | #define PUT_32BE(off, v) (PUT_16BE((off), (v) >> 16), \ | ||
53 | PUT_16BE((off) + 2, (v))) | ||
54 | |||
55 | /* Structure of an ELF file */ | ||
56 | #define E_IDENT 0 /* ELF header */ | ||
57 | #define E_PHOFF 28 | ||
58 | #define E_PHENTSIZE 42 | ||
59 | #define E_PHNUM 44 | ||
60 | #define E_HSIZE 52 /* size of ELF header */ | ||
61 | |||
62 | #define EI_MAGIC 0 /* offsets in E_IDENT area */ | ||
63 | #define EI_CLASS 4 | ||
64 | #define EI_DATA 5 | ||
65 | |||
66 | #define PH_TYPE 0 /* ELF program header */ | ||
67 | #define PH_OFFSET 4 | ||
68 | #define PH_FILESZ 16 | ||
69 | #define PH_HSIZE 32 /* size of program header */ | ||
70 | |||
71 | #define PT_NOTE 4 /* Program header type = note */ | ||
72 | |||
73 | #define ELFCLASS32 1 | ||
74 | #define ELFDATA2MSB 2 | ||
75 | |||
76 | unsigned char elf_magic[4] = { 0x7f, 'E', 'L', 'F' }; | ||
77 | |||
78 | int main(int ac, char **av) | ||
79 | { | ||
80 | int fd, n, i; | ||
81 | int ph, ps, np; | ||
82 | int nnote, ns; | ||
83 | |||
84 | if (ac != 2) { | ||
85 | fprintf(stderr, "Usage: %s elf-file\n", av[0]); | ||
86 | exit(1); | ||
87 | } | ||
88 | fd = open(av[1], O_RDWR); | ||
89 | if (fd < 0) { | ||
90 | perror(av[1]); | ||
91 | exit(1); | ||
92 | } | ||
93 | |||
94 | nnote = strlen(arch) + 1 + (N_DESCR + 3) * 4; | ||
95 | |||
96 | n = read(fd, buf, sizeof(buf)); | ||
97 | if (n < 0) { | ||
98 | perror("read"); | ||
99 | exit(1); | ||
100 | } | ||
101 | |||
102 | if (n < E_HSIZE || memcmp(&buf[E_IDENT+EI_MAGIC], elf_magic, 4) != 0) | ||
103 | goto notelf; | ||
104 | |||
105 | if (buf[E_IDENT+EI_CLASS] != ELFCLASS32 | ||
106 | || buf[E_IDENT+EI_DATA] != ELFDATA2MSB) { | ||
107 | fprintf(stderr, "%s is not a big-endian 32-bit ELF image\n", | ||
108 | av[1]); | ||
109 | exit(1); | ||
110 | } | ||
111 | |||
112 | ph = GET_32BE(E_PHOFF); | ||
113 | ps = GET_16BE(E_PHENTSIZE); | ||
114 | np = GET_16BE(E_PHNUM); | ||
115 | if (ph < E_HSIZE || ps < PH_HSIZE || np < 1) | ||
116 | goto notelf; | ||
117 | if (ph + (np + 1) * ps + nnote > n) | ||
118 | goto nospace; | ||
119 | |||
120 | for (i = 0; i < np; ++i) { | ||
121 | if (GET_32BE(ph + PH_TYPE) == PT_NOTE) { | ||
122 | fprintf(stderr, "%s already has a note entry\n", | ||
123 | av[1]); | ||
124 | exit(0); | ||
125 | } | ||
126 | ph += ps; | ||
127 | } | ||
128 | |||
129 | /* XXX check that the area we want to use is all zeroes */ | ||
130 | for (i = 0; i < ps + nnote; ++i) | ||
131 | if (buf[ph + i] != 0) | ||
132 | goto nospace; | ||
133 | |||
134 | /* fill in the program header entry */ | ||
135 | ns = ph + ps; | ||
136 | PUT_32BE(ph + PH_TYPE, PT_NOTE); | ||
137 | PUT_32BE(ph + PH_OFFSET, ns); | ||
138 | PUT_32BE(ph + PH_FILESZ, nnote); | ||
139 | |||
140 | /* fill in the note area we point to */ | ||
141 | /* XXX we should probably make this a proper section */ | ||
142 | PUT_32BE(ns, strlen(arch) + 1); | ||
143 | PUT_32BE(ns + 4, N_DESCR * 4); | ||
144 | PUT_32BE(ns + 8, 0x1275); | ||
145 | strcpy(&buf[ns + 12], arch); | ||
146 | ns += 12 + strlen(arch) + 1; | ||
147 | for (i = 0; i < N_DESCR; ++i) | ||
148 | PUT_32BE(ns + i * 4, descr[i]); | ||
149 | |||
150 | /* Update the number of program headers */ | ||
151 | PUT_16BE(E_PHNUM, np + 1); | ||
152 | |||
153 | /* write back */ | ||
154 | lseek(fd, (long) 0, SEEK_SET); | ||
155 | i = write(fd, buf, n); | ||
156 | if (i < 0) { | ||
157 | perror("write"); | ||
158 | exit(1); | ||
159 | } | ||
160 | if (i < n) { | ||
161 | fprintf(stderr, "%s: write truncated\n", av[1]); | ||
162 | exit(1); | ||
163 | } | ||
164 | |||
165 | exit(0); | ||
166 | |||
167 | notelf: | ||
168 | fprintf(stderr, "%s does not appear to be an ELF file\n", av[0]); | ||
169 | exit(1); | ||
170 | |||
171 | nospace: | ||
172 | fprintf(stderr, "sorry, I can't find space in %s to put the note\n", | ||
173 | av[0]); | ||
174 | exit(1); | ||
175 | } | ||
diff --git a/arch/ppc/boot/utils/elf.pl b/arch/ppc/boot/utils/elf.pl new file mode 100644 index 000000000000..d3e9d9d5b84e --- /dev/null +++ b/arch/ppc/boot/utils/elf.pl | |||
@@ -0,0 +1,33 @@ | |||
1 | # | ||
2 | # ELF header field numbers | ||
3 | # | ||
4 | |||
5 | $e_ident = 0; # Identification bytes / magic number | ||
6 | $e_type = 1; # ELF file type | ||
7 | $e_machine = 2; # Target machine type | ||
8 | $e_version = 3; # File version | ||
9 | $e_entry = 4; # Start address | ||
10 | $e_phoff = 5; # Program header file offset | ||
11 | $e_shoff = 6; # Section header file offset | ||
12 | $e_flags = 7; # File flags | ||
13 | $e_ehsize = 8; # Size of ELF header | ||
14 | $e_phentsize = 9; # Size of program header | ||
15 | $e_phnum = 10; # Number of program header entries | ||
16 | $e_shentsize = 11; # Size of section header | ||
17 | $e_shnum = 12; # Number of section header entries | ||
18 | $e_shstrndx = 13; # Section header table string index | ||
19 | |||
20 | # | ||
21 | # Section header field numbers | ||
22 | # | ||
23 | |||
24 | $sh_name = 0; # Section name | ||
25 | $sh_type = 1; # Section header type | ||
26 | $sh_flags = 2; # Section header flags | ||
27 | $sh_addr = 3; # Virtual address | ||
28 | $sh_offset = 4; # File offset | ||
29 | $sh_size = 5; # Section size | ||
30 | $sh_link = 6; # Miscellaneous info | ||
31 | $sh_info = 7; # More miscellaneous info | ||
32 | $sh_addralign = 8; # Memory alignment | ||
33 | $sh_entsize = 9; # Entry size if this is a table | ||
diff --git a/arch/ppc/boot/utils/hack-coff.c b/arch/ppc/boot/utils/hack-coff.c new file mode 100644 index 000000000000..5e5a6573a1ef --- /dev/null +++ b/arch/ppc/boot/utils/hack-coff.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * hack-coff.c - hack the header of an xcoff file to fill in | ||
3 | * a few fields needed by the Open Firmware xcoff loader on | ||
4 | * Power Macs but not initialized by objcopy. | ||
5 | * | ||
6 | * Copyright (C) Paul Mackerras 1997. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | #include <stdio.h> | ||
14 | #include <stdlib.h> | ||
15 | #include <unistd.h> | ||
16 | #include <fcntl.h> | ||
17 | #include <string.h> | ||
18 | #include "rs6000.h" | ||
19 | |||
20 | #define AOUT_MAGIC 0x010b | ||
21 | |||
22 | #define get_16be(x) ((((unsigned char *)(x))[0] << 8) \ | ||
23 | + ((unsigned char *)(x))[1]) | ||
24 | #define put_16be(x, v) (((unsigned char *)(x))[0] = (v) >> 8, \ | ||
25 | ((unsigned char *)(x))[1] = (v) & 0xff) | ||
26 | #define get_32be(x) ((((unsigned char *)(x))[0] << 24) \ | ||
27 | + (((unsigned char *)(x))[1] << 16) \ | ||
28 | + (((unsigned char *)(x))[2] << 8) \ | ||
29 | + ((unsigned char *)(x))[3]) | ||
30 | |||
31 | int | ||
32 | main(int ac, char **av) | ||
33 | { | ||
34 | int fd; | ||
35 | int i, nsect; | ||
36 | int aoutsz; | ||
37 | struct external_filehdr fhdr; | ||
38 | AOUTHDR aout; | ||
39 | struct external_scnhdr shdr; | ||
40 | |||
41 | if (ac != 2) { | ||
42 | fprintf(stderr, "Usage: hack-coff coff-file\n"); | ||
43 | exit(1); | ||
44 | } | ||
45 | if ((fd = open(av[1], 2)) == -1) { | ||
46 | perror(av[2]); | ||
47 | exit(1); | ||
48 | } | ||
49 | if (read(fd, &fhdr, sizeof(fhdr)) != sizeof(fhdr)) | ||
50 | goto readerr; | ||
51 | i = get_16be(fhdr.f_magic); | ||
52 | if (i != U802TOCMAGIC && i != U802WRMAGIC && i != U802ROMAGIC) { | ||
53 | fprintf(stderr, "%s: not an xcoff file\n", av[1]); | ||
54 | exit(1); | ||
55 | } | ||
56 | aoutsz = get_16be(fhdr.f_opthdr); | ||
57 | if (read(fd, &aout, aoutsz) != aoutsz) | ||
58 | goto readerr; | ||
59 | nsect = get_16be(fhdr.f_nscns); | ||
60 | for (i = 0; i < nsect; ++i) { | ||
61 | if (read(fd, &shdr, sizeof(shdr)) != sizeof(shdr)) | ||
62 | goto readerr; | ||
63 | if (strcmp(shdr.s_name, ".text") == 0) { | ||
64 | put_16be(aout.o_snentry, i+1); | ||
65 | put_16be(aout.o_sntext, i+1); | ||
66 | } else if (strcmp(shdr.s_name, ".data") == 0) { | ||
67 | put_16be(aout.o_sndata, i+1); | ||
68 | } else if (strcmp(shdr.s_name, ".bss") == 0) { | ||
69 | put_16be(aout.o_snbss, i+1); | ||
70 | } | ||
71 | } | ||
72 | put_16be(aout.magic, AOUT_MAGIC); | ||
73 | if (lseek(fd, (long) sizeof(struct external_filehdr), 0) == -1 | ||
74 | || write(fd, &aout, aoutsz) != aoutsz) { | ||
75 | fprintf(stderr, "%s: write error\n", av[1]); | ||
76 | exit(1); | ||
77 | } | ||
78 | close(fd); | ||
79 | exit(0); | ||
80 | |||
81 | readerr: | ||
82 | fprintf(stderr, "%s: read error or file too short\n", av[1]); | ||
83 | exit(1); | ||
84 | } | ||
diff --git a/arch/ppc/boot/utils/mkbugboot.c b/arch/ppc/boot/utils/mkbugboot.c new file mode 100644 index 000000000000..886122283f39 --- /dev/null +++ b/arch/ppc/boot/utils/mkbugboot.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* | ||
2 | * arch/ppc/boot/utils/mkbugboot.c | ||
3 | * | ||
4 | * Makes a Motorola PPCBUG ROM bootable image which can be flashed | ||
5 | * into one of the FLASH banks on a Motorola PowerPlus board. | ||
6 | * | ||
7 | * Author: Matt Porter <mporter@mvista.com> | ||
8 | * | ||
9 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
10 | * the terms of the GNU General Public License version 2. This program | ||
11 | * is licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | */ | ||
14 | |||
15 | #define ELF_HEADER_SIZE 65536 | ||
16 | |||
17 | #include <unistd.h> | ||
18 | #include <sys/stat.h> | ||
19 | #include <string.h> | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <errno.h> | ||
23 | #include <fcntl.h> | ||
24 | #ifdef __sun__ | ||
25 | #include <inttypes.h> | ||
26 | #else | ||
27 | #include <stdint.h> | ||
28 | #endif | ||
29 | |||
30 | #ifdef __i386__ | ||
31 | #define cpu_to_be32(x) le32_to_cpu(x) | ||
32 | #define cpu_to_be16(x) le16_to_cpu(x) | ||
33 | #else | ||
34 | #define cpu_to_be32(x) (x) | ||
35 | #define cpu_to_be16(x) (x) | ||
36 | #endif | ||
37 | |||
38 | #define cpu_to_le32(x) le32_to_cpu((x)) | ||
39 | unsigned long le32_to_cpu(unsigned long x) | ||
40 | { | ||
41 | return (((x & 0x000000ffU) << 24) | | ||
42 | ((x & 0x0000ff00U) << 8) | | ||
43 | ((x & 0x00ff0000U) >> 8) | | ||
44 | ((x & 0xff000000U) >> 24)); | ||
45 | } | ||
46 | |||
47 | #define cpu_to_le16(x) le16_to_cpu((x)) | ||
48 | unsigned short le16_to_cpu(unsigned short x) | ||
49 | { | ||
50 | return (((x & 0x00ff) << 8) | | ||
51 | ((x & 0xff00) >> 8)); | ||
52 | } | ||
53 | |||
54 | /* size of read buffer */ | ||
55 | #define SIZE 0x1000 | ||
56 | |||
57 | /* PPCBUG ROM boot header */ | ||
58 | typedef struct bug_boot_header { | ||
59 | uint8_t magic_word[4]; /* "BOOT" */ | ||
60 | uint32_t entry_offset; /* Offset from top of header to code */ | ||
61 | uint32_t routine_length; /* Length of code */ | ||
62 | uint8_t routine_name[8]; /* Name of the boot code */ | ||
63 | } bug_boot_header_t; | ||
64 | |||
65 | #define HEADER_SIZE sizeof(bug_boot_header_t) | ||
66 | |||
67 | uint32_t copy_image(int32_t in_fd, int32_t out_fd) | ||
68 | { | ||
69 | uint8_t buf[SIZE]; | ||
70 | int n; | ||
71 | uint32_t image_size = 0; | ||
72 | uint8_t zero = 0; | ||
73 | |||
74 | lseek(in_fd, ELF_HEADER_SIZE, SEEK_SET); | ||
75 | |||
76 | /* Copy an image while recording its size */ | ||
77 | while ( (n = read(in_fd, buf, SIZE)) > 0 ) | ||
78 | { | ||
79 | image_size = image_size + n; | ||
80 | write(out_fd, buf, n); | ||
81 | } | ||
82 | |||
83 | /* BUG romboot requires that our size is divisible by 2 */ | ||
84 | /* align image to 2 byte boundary */ | ||
85 | if (image_size % 2) | ||
86 | { | ||
87 | image_size++; | ||
88 | write(out_fd, &zero, 1); | ||
89 | } | ||
90 | |||
91 | return image_size; | ||
92 | } | ||
93 | |||
94 | void write_bugboot_header(int32_t out_fd, uint32_t boot_size) | ||
95 | { | ||
96 | uint8_t header_block[HEADER_SIZE]; | ||
97 | bug_boot_header_t *bbh = (bug_boot_header_t *)&header_block[0]; | ||
98 | |||
99 | memset(header_block, 0, HEADER_SIZE); | ||
100 | |||
101 | /* Fill in the PPCBUG ROM boot header */ | ||
102 | strncpy(bbh->magic_word, "BOOT", 4); /* PPCBUG magic word */ | ||
103 | bbh->entry_offset = cpu_to_be32(HEADER_SIZE); /* Entry address */ | ||
104 | bbh->routine_length= cpu_to_be32(HEADER_SIZE+boot_size+2); /* Routine length */ | ||
105 | strncpy(bbh->routine_name, "LINUXROM", 8); /* Routine name */ | ||
106 | |||
107 | /* Output the header and bootloader to the file */ | ||
108 | write(out_fd, header_block, HEADER_SIZE); | ||
109 | } | ||
110 | |||
111 | uint16_t calc_checksum(int32_t bug_fd) | ||
112 | { | ||
113 | uint32_t checksum_var = 0; | ||
114 | uint8_t buf[2]; | ||
115 | int n; | ||
116 | |||
117 | /* Checksum loop */ | ||
118 | while ( (n = read(bug_fd, buf, 2) ) ) | ||
119 | { | ||
120 | checksum_var = checksum_var + *(uint16_t *)buf; | ||
121 | |||
122 | /* If we carry out, mask it and add one to the checksum */ | ||
123 | if (checksum_var >> 16) | ||
124 | checksum_var = (checksum_var & 0x0000ffff) + 1; | ||
125 | } | ||
126 | |||
127 | return checksum_var; | ||
128 | } | ||
129 | |||
130 | int main(int argc, char *argv[]) | ||
131 | { | ||
132 | int32_t image_fd, bugboot_fd; | ||
133 | int argptr = 1; | ||
134 | uint32_t kernel_size = 0; | ||
135 | uint16_t checksum = 0; | ||
136 | uint8_t bugbootname[256]; | ||
137 | |||
138 | if ( (argc != 3) ) | ||
139 | { | ||
140 | fprintf(stderr, "usage: %s <kernel_image> <bugboot>\n",argv[0]); | ||
141 | exit(-1); | ||
142 | } | ||
143 | |||
144 | /* Get file args */ | ||
145 | |||
146 | /* kernel image file */ | ||
147 | if ((image_fd = open( argv[argptr] , 0)) < 0) | ||
148 | exit(-1); | ||
149 | argptr++; | ||
150 | |||
151 | /* bugboot file */ | ||
152 | if ( !strcmp( argv[argptr], "-" ) ) | ||
153 | bugboot_fd = 1; /* stdout */ | ||
154 | else | ||
155 | if ((bugboot_fd = creat( argv[argptr] , 0755)) < 0) | ||
156 | exit(-1); | ||
157 | else | ||
158 | strcpy(bugbootname, argv[argptr]); | ||
159 | argptr++; | ||
160 | |||
161 | /* Set file position after ROM header block where zImage will be written */ | ||
162 | lseek(bugboot_fd, HEADER_SIZE, SEEK_SET); | ||
163 | |||
164 | /* Copy kernel image into bugboot image */ | ||
165 | kernel_size = copy_image(image_fd, bugboot_fd); | ||
166 | close(image_fd); | ||
167 | |||
168 | /* Set file position to beginning where header/romboot will be written */ | ||
169 | lseek(bugboot_fd, 0, SEEK_SET); | ||
170 | |||
171 | /* Write out BUG header/romboot */ | ||
172 | write_bugboot_header(bugboot_fd, kernel_size); | ||
173 | |||
174 | /* Close bugboot file */ | ||
175 | close(bugboot_fd); | ||
176 | |||
177 | /* Reopen it as read/write */ | ||
178 | bugboot_fd = open(bugbootname, O_RDWR); | ||
179 | |||
180 | /* Calculate checksum */ | ||
181 | checksum = calc_checksum(bugboot_fd); | ||
182 | |||
183 | /* Write out the calculated checksum */ | ||
184 | write(bugboot_fd, &checksum, 2); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
diff --git a/arch/ppc/boot/utils/mknote.c b/arch/ppc/boot/utils/mknote.c new file mode 100644 index 000000000000..b9fbb2cbfc8f --- /dev/null +++ b/arch/ppc/boot/utils/mknote.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright (C) Cort Dougan 1999. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Generate a note section as per the CHRP specification. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <stdio.h> | ||
14 | #include <string.h> | ||
15 | |||
16 | #define PL(x) printf("%c%c%c%c", ((x)>>24)&0xff, ((x)>>16)&0xff, ((x)>>8)&0xff, (x)&0xff ); | ||
17 | |||
18 | int main(void) | ||
19 | { | ||
20 | /* header */ | ||
21 | /* namesz */ | ||
22 | PL(strlen("PowerPC")+1); | ||
23 | /* descrsz */ | ||
24 | PL(6*4); | ||
25 | /* type */ | ||
26 | PL(0x1275); | ||
27 | /* name */ | ||
28 | printf("PowerPC"); printf("%c", 0); | ||
29 | |||
30 | /* descriptor */ | ||
31 | /* real-mode */ | ||
32 | PL(0xffffffff); | ||
33 | /* real-base */ | ||
34 | PL(0x00c00000); | ||
35 | /* real-size */ | ||
36 | PL(0xffffffff); | ||
37 | /* virt-base */ | ||
38 | PL(0xffffffff); | ||
39 | /* virt-size */ | ||
40 | PL(0xffffffff); | ||
41 | /* load-base */ | ||
42 | PL(0x4000); | ||
43 | return 0; | ||
44 | } | ||
diff --git a/arch/ppc/boot/utils/mkprep.c b/arch/ppc/boot/utils/mkprep.c new file mode 100644 index 000000000000..f6d5a2f2fcf6 --- /dev/null +++ b/arch/ppc/boot/utils/mkprep.c | |||
@@ -0,0 +1,293 @@ | |||
1 | /* | ||
2 | * Makes a prep bootable image which can be dd'd onto | ||
3 | * a disk device to make a bootdisk. Will take | ||
4 | * as input a elf executable, strip off the header | ||
5 | * and write out a boot image as: | ||
6 | * 1) default - strips elf header | ||
7 | * suitable as a network boot image | ||
8 | * 2) -pbp - strips elf header and writes out prep boot partition image | ||
9 | * cat or dd onto disk for booting | ||
10 | * 3) -asm - strips elf header and writes out as asm data | ||
11 | * useful for generating data for a compressed image | ||
12 | * -- Cort | ||
13 | * | ||
14 | * Modified for x86 hosted builds by Matt Porter <porter@neta.com> | ||
15 | * Modified for Sparc hosted builds by Peter Wahl <PeterWahl@web.de> | ||
16 | */ | ||
17 | |||
18 | #include <fcntl.h> | ||
19 | #include <stdio.h> | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <strings.h> | ||
23 | #include <sys/stat.h> | ||
24 | #include <unistd.h> | ||
25 | |||
26 | #define cpu_to_le32(x) le32_to_cpu((x)) | ||
27 | unsigned long le32_to_cpu(unsigned long x) | ||
28 | { | ||
29 | return (((x & 0x000000ffU) << 24) | | ||
30 | ((x & 0x0000ff00U) << 8) | | ||
31 | ((x & 0x00ff0000U) >> 8) | | ||
32 | ((x & 0xff000000U) >> 24)); | ||
33 | } | ||
34 | |||
35 | |||
36 | #define cpu_to_le16(x) le16_to_cpu((x)) | ||
37 | unsigned short le16_to_cpu(unsigned short x) | ||
38 | { | ||
39 | return (((x & 0x00ff) << 8) | | ||
40 | ((x & 0xff00) >> 8)); | ||
41 | } | ||
42 | |||
43 | #define cpu_to_be32(x) (x) | ||
44 | #define be32_to_cpu(x) (x) | ||
45 | #define cpu_to_be16(x) (x) | ||
46 | #define be16_to_cpu(x) (x) | ||
47 | |||
48 | /* size of read buffer */ | ||
49 | #define SIZE 0x1000 | ||
50 | |||
51 | |||
52 | typedef unsigned long dword_t; | ||
53 | typedef unsigned short word_t; | ||
54 | typedef unsigned char byte_t; | ||
55 | typedef byte_t block_t[512]; | ||
56 | typedef byte_t page_t[4096]; | ||
57 | |||
58 | |||
59 | /* | ||
60 | * Partition table entry | ||
61 | * - from the PReP spec | ||
62 | */ | ||
63 | typedef struct partition_entry { | ||
64 | byte_t boot_indicator; | ||
65 | byte_t starting_head; | ||
66 | byte_t starting_sector; | ||
67 | byte_t starting_cylinder; | ||
68 | |||
69 | byte_t system_indicator; | ||
70 | byte_t ending_head; | ||
71 | byte_t ending_sector; | ||
72 | byte_t ending_cylinder; | ||
73 | |||
74 | dword_t beginning_sector; | ||
75 | dword_t number_of_sectors; | ||
76 | } partition_entry_t; | ||
77 | |||
78 | #define BootActive 0x80 | ||
79 | #define SystemPrep 0x41 | ||
80 | |||
81 | void copy_image(int , int); | ||
82 | void write_prep_partition(int , int ); | ||
83 | void write_asm_data( int in, int out ); | ||
84 | |||
85 | unsigned int elfhdr_size = 65536; | ||
86 | |||
87 | int main(int argc, char *argv[]) | ||
88 | { | ||
89 | int in_fd, out_fd; | ||
90 | int argptr = 1; | ||
91 | unsigned int prep = 0; | ||
92 | unsigned int asmoutput = 0; | ||
93 | |||
94 | if ( (argc < 3) || (argc > 4) ) | ||
95 | { | ||
96 | fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",argv[0]); | ||
97 | exit(-1); | ||
98 | } | ||
99 | |||
100 | /* needs to handle args more elegantly -- but this is a small/simple program */ | ||
101 | |||
102 | /* check for -pbp */ | ||
103 | if ( !strcmp( argv[argptr], "-pbp" ) ) | ||
104 | { | ||
105 | prep = 1; | ||
106 | argptr++; | ||
107 | } | ||
108 | |||
109 | /* check for -asm */ | ||
110 | if ( !strcmp( argv[argptr], "-asm" ) ) | ||
111 | { | ||
112 | asmoutput = 1; | ||
113 | argptr++; | ||
114 | } | ||
115 | |||
116 | /* input file */ | ||
117 | if ( !strcmp( argv[argptr], "-" ) ) | ||
118 | in_fd = 0; /* stdin */ | ||
119 | else | ||
120 | if ((in_fd = open( argv[argptr] , 0)) < 0) | ||
121 | exit(-1); | ||
122 | argptr++; | ||
123 | |||
124 | /* output file */ | ||
125 | if ( !strcmp( argv[argptr], "-" ) ) | ||
126 | out_fd = 1; /* stdout */ | ||
127 | else | ||
128 | if ((out_fd = creat( argv[argptr] , 0755)) < 0) | ||
129 | exit(-1); | ||
130 | argptr++; | ||
131 | |||
132 | /* skip elf header in input file */ | ||
133 | /*if ( !prep )*/ | ||
134 | lseek(in_fd, elfhdr_size, SEEK_SET); | ||
135 | |||
136 | /* write prep partition if necessary */ | ||
137 | if ( prep ) | ||
138 | write_prep_partition( in_fd, out_fd ); | ||
139 | |||
140 | /* write input image to bootimage */ | ||
141 | if ( asmoutput ) | ||
142 | write_asm_data( in_fd, out_fd ); | ||
143 | else | ||
144 | copy_image(in_fd, out_fd); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | void write_prep_partition(int in, int out) | ||
150 | { | ||
151 | unsigned char block[512]; | ||
152 | partition_entry_t pe; | ||
153 | dword_t *entry = (dword_t *)&block[0]; | ||
154 | dword_t *length = (dword_t *)&block[sizeof(long)]; | ||
155 | struct stat info; | ||
156 | |||
157 | if (fstat(in, &info) < 0) | ||
158 | { | ||
159 | fprintf(stderr,"info failed\n"); | ||
160 | exit(-1); | ||
161 | } | ||
162 | |||
163 | bzero( block, sizeof block ); | ||
164 | |||
165 | /* set entry point and boot image size skipping over elf header */ | ||
166 | #ifdef __i386__ | ||
167 | *entry = 0x400/*+65536*/; | ||
168 | *length = info.st_size-elfhdr_size+0x400; | ||
169 | #else | ||
170 | *entry = cpu_to_le32(0x400/*+65536*/); | ||
171 | *length = cpu_to_le32(info.st_size-elfhdr_size+0x400); | ||
172 | #endif /* __i386__ */ | ||
173 | |||
174 | /* sets magic number for msdos partition (used by linux) */ | ||
175 | block[510] = 0x55; | ||
176 | block[511] = 0xAA; | ||
177 | |||
178 | /* | ||
179 | * Build a "PReP" partition table entry in the boot record | ||
180 | * - "PReP" may only look at the system_indicator | ||
181 | */ | ||
182 | pe.boot_indicator = BootActive; | ||
183 | pe.system_indicator = SystemPrep; | ||
184 | /* | ||
185 | * The first block of the diskette is used by this "boot record" which | ||
186 | * actually contains the partition table. (The first block of the | ||
187 | * partition contains the boot image, but I digress...) We'll set up | ||
188 | * one partition on the diskette and it shall contain the rest of the | ||
189 | * diskette. | ||
190 | */ | ||
191 | pe.starting_head = 0; /* zero-based */ | ||
192 | pe.starting_sector = 2; /* one-based */ | ||
193 | pe.starting_cylinder = 0; /* zero-based */ | ||
194 | pe.ending_head = 1; /* assumes two heads */ | ||
195 | pe.ending_sector = 18; /* assumes 18 sectors/track */ | ||
196 | pe.ending_cylinder = 79; /* assumes 80 cylinders/diskette */ | ||
197 | |||
198 | /* | ||
199 | * The "PReP" software ignores the above fields and just looks at | ||
200 | * the next two. | ||
201 | * - size of the diskette is (assumed to be) | ||
202 | * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette) | ||
203 | * - unlike the above sector numbers, the beginning sector is zero-based! | ||
204 | */ | ||
205 | #if 0 | ||
206 | pe.beginning_sector = cpu_to_le32(1); | ||
207 | #else | ||
208 | /* This has to be 0 on the PowerStack? */ | ||
209 | #ifdef __i386__ | ||
210 | pe.beginning_sector = 0; | ||
211 | #else | ||
212 | pe.beginning_sector = cpu_to_le32(0); | ||
213 | #endif /* __i386__ */ | ||
214 | #endif | ||
215 | |||
216 | #ifdef __i386__ | ||
217 | pe.number_of_sectors = 2*18*80-1; | ||
218 | #else | ||
219 | pe.number_of_sectors = cpu_to_le32(2*18*80-1); | ||
220 | #endif /* __i386__ */ | ||
221 | |||
222 | memcpy(&block[0x1BE], &pe, sizeof(pe)); | ||
223 | |||
224 | write( out, block, sizeof(block) ); | ||
225 | write( out, entry, sizeof(*entry) ); | ||
226 | write( out, length, sizeof(*length) ); | ||
227 | /* set file position to 2nd sector where image will be written */ | ||
228 | lseek( out, 0x400, SEEK_SET ); | ||
229 | } | ||
230 | |||
231 | |||
232 | |||
233 | void | ||
234 | copy_image(int in, int out) | ||
235 | { | ||
236 | char buf[SIZE]; | ||
237 | int n; | ||
238 | |||
239 | while ( (n = read(in, buf, SIZE)) > 0 ) | ||
240 | write(out, buf, n); | ||
241 | } | ||
242 | |||
243 | |||
244 | void | ||
245 | write_asm_data( int in, int out ) | ||
246 | { | ||
247 | int i, cnt, pos, len; | ||
248 | unsigned int cksum, val; | ||
249 | unsigned char *lp; | ||
250 | unsigned char buf[SIZE]; | ||
251 | unsigned char str[256]; | ||
252 | |||
253 | write( out, "\t.data\n\t.globl input_data\ninput_data:\n", | ||
254 | strlen( "\t.data\n\t.globl input_data\ninput_data:\n" ) ); | ||
255 | pos = 0; | ||
256 | cksum = 0; | ||
257 | while ((len = read(in, buf, sizeof(buf))) > 0) | ||
258 | { | ||
259 | cnt = 0; | ||
260 | lp = (unsigned char *)buf; | ||
261 | len = (len + 3) & ~3; /* Round up to longwords */ | ||
262 | for (i = 0; i < len; i += 4) | ||
263 | { | ||
264 | if (cnt == 0) | ||
265 | { | ||
266 | write( out, "\t.long\t", strlen( "\t.long\t" ) ); | ||
267 | } | ||
268 | sprintf( str, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]); | ||
269 | write( out, str, strlen(str) ); | ||
270 | val = *(unsigned long *)lp; | ||
271 | cksum ^= val; | ||
272 | lp += 4; | ||
273 | if (++cnt == 4) | ||
274 | { | ||
275 | cnt = 0; | ||
276 | sprintf( str, " # %x \n", pos+i-12); | ||
277 | write( out, str, strlen(str) ); | ||
278 | } else | ||
279 | { | ||
280 | write( out, ",", 1 ); | ||
281 | } | ||
282 | } | ||
283 | if (cnt) | ||
284 | { | ||
285 | write( out, "0\n", 2 ); | ||
286 | } | ||
287 | pos += len; | ||
288 | } | ||
289 | sprintf(str, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos); | ||
290 | write( out, str, strlen(str) ); | ||
291 | |||
292 | fprintf(stderr, "cksum = %x\n", cksum); | ||
293 | } | ||
diff --git a/arch/ppc/boot/utils/mktree.c b/arch/ppc/boot/utils/mktree.c new file mode 100644 index 000000000000..2be22e28f2b3 --- /dev/null +++ b/arch/ppc/boot/utils/mktree.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * Makes a tree bootable image for IBM Evaluation boards. | ||
3 | * Basically, just take a zImage, skip the ELF header, and stuff | ||
4 | * a 32 byte header on the front. | ||
5 | * | ||
6 | * We use htonl, which is a network macro, to make sure we're doing | ||
7 | * The Right Thing on an LE machine. It's non-obvious, but it should | ||
8 | * work on anything BSD'ish. | ||
9 | */ | ||
10 | |||
11 | #include <fcntl.h> | ||
12 | #include <stdio.h> | ||
13 | #include <stdlib.h> | ||
14 | #include <string.h> | ||
15 | #include <sys/stat.h> | ||
16 | #include <unistd.h> | ||
17 | #include <netinet/in.h> | ||
18 | #ifdef __sun__ | ||
19 | #include <inttypes.h> | ||
20 | #else | ||
21 | #include <stdint.h> | ||
22 | #endif | ||
23 | |||
24 | /* This gets tacked on the front of the image. There are also a few | ||
25 | * bytes allocated after the _start label used by the boot rom (see | ||
26 | * head.S for details). | ||
27 | */ | ||
28 | typedef struct boot_block { | ||
29 | uint32_t bb_magic; /* 0x0052504F */ | ||
30 | uint32_t bb_dest; /* Target address of the image */ | ||
31 | uint32_t bb_num_512blocks; /* Size, rounded-up, in 512 byte blks */ | ||
32 | uint32_t bb_debug_flag; /* Run debugger or image after load */ | ||
33 | uint32_t bb_entry_point; /* The image address to start */ | ||
34 | uint32_t bb_checksum; /* 32 bit checksum including header */ | ||
35 | uint32_t reserved[2]; | ||
36 | } boot_block_t; | ||
37 | |||
38 | #define IMGBLK 512 | ||
39 | char tmpbuf[IMGBLK]; | ||
40 | |||
41 | int main(int argc, char *argv[]) | ||
42 | { | ||
43 | int in_fd, out_fd; | ||
44 | int nblks, i; | ||
45 | uint cksum, *cp; | ||
46 | struct stat st; | ||
47 | boot_block_t bt; | ||
48 | |||
49 | if (argc < 3) { | ||
50 | fprintf(stderr, "usage: %s <zImage-file> <boot-image> [entry-point]\n",argv[0]); | ||
51 | exit(1); | ||
52 | } | ||
53 | |||
54 | if (stat(argv[1], &st) < 0) { | ||
55 | perror("stat"); | ||
56 | exit(2); | ||
57 | } | ||
58 | |||
59 | nblks = (st.st_size + IMGBLK) / IMGBLK; | ||
60 | |||
61 | bt.bb_magic = htonl(0x0052504F); | ||
62 | |||
63 | /* If we have the optional entry point parameter, use it */ | ||
64 | if (argc == 4) | ||
65 | bt.bb_dest = bt.bb_entry_point = htonl(strtoul(argv[3], NULL, 0)); | ||
66 | else | ||
67 | bt.bb_dest = bt.bb_entry_point = htonl(0x500000); | ||
68 | |||
69 | /* We know these from the linker command. | ||
70 | * ...and then move it up into memory a little more so the | ||
71 | * relocation can happen. | ||
72 | */ | ||
73 | bt.bb_num_512blocks = htonl(nblks); | ||
74 | bt.bb_debug_flag = 0; | ||
75 | |||
76 | bt.bb_checksum = 0; | ||
77 | |||
78 | /* To be neat and tidy :-). | ||
79 | */ | ||
80 | bt.reserved[0] = 0; | ||
81 | bt.reserved[1] = 0; | ||
82 | |||
83 | if ((in_fd = open(argv[1], O_RDONLY)) < 0) { | ||
84 | perror("zImage open"); | ||
85 | exit(3); | ||
86 | } | ||
87 | |||
88 | if ((out_fd = open(argv[2], (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) { | ||
89 | perror("bootfile open"); | ||
90 | exit(3); | ||
91 | } | ||
92 | |||
93 | cksum = 0; | ||
94 | cp = (void *)&bt; | ||
95 | for (i=0; i<sizeof(bt)/sizeof(uint); i++) | ||
96 | cksum += *cp++; | ||
97 | |||
98 | /* Assume zImage is an ELF file, and skip the 64K header. | ||
99 | */ | ||
100 | if (read(in_fd, tmpbuf, IMGBLK) != IMGBLK) { | ||
101 | fprintf(stderr, "%s is too small to be an ELF image\n", | ||
102 | argv[1]); | ||
103 | exit(4); | ||
104 | } | ||
105 | |||
106 | if ((*(uint *)tmpbuf) != htonl(0x7f454c46)) { | ||
107 | fprintf(stderr, "%s is not an ELF image\n", argv[1]); | ||
108 | exit(4); | ||
109 | } | ||
110 | |||
111 | if (lseek(in_fd, (64 * 1024), SEEK_SET) < 0) { | ||
112 | fprintf(stderr, "%s failed to seek in ELF image\n", argv[1]); | ||
113 | exit(4); | ||
114 | } | ||
115 | |||
116 | nblks -= (64 * 1024) / IMGBLK; | ||
117 | |||
118 | /* And away we go...... | ||
119 | */ | ||
120 | if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { | ||
121 | perror("boot-image write"); | ||
122 | exit(5); | ||
123 | } | ||
124 | |||
125 | while (nblks-- > 0) { | ||
126 | if (read(in_fd, tmpbuf, IMGBLK) < 0) { | ||
127 | perror("zImage read"); | ||
128 | exit(5); | ||
129 | } | ||
130 | cp = (uint *)tmpbuf; | ||
131 | for (i=0; i<sizeof(tmpbuf)/sizeof(uint); i++) | ||
132 | cksum += *cp++; | ||
133 | if (write(out_fd, tmpbuf, sizeof(tmpbuf)) != sizeof(tmpbuf)) { | ||
134 | perror("boot-image write"); | ||
135 | exit(5); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | /* rewrite the header with the computed checksum. | ||
140 | */ | ||
141 | bt.bb_checksum = htonl(cksum); | ||
142 | if (lseek(out_fd, 0, SEEK_SET) < 0) { | ||
143 | perror("rewrite seek"); | ||
144 | exit(1); | ||
145 | } | ||
146 | if (write(out_fd, &bt, sizeof(bt)) != sizeof(bt)) { | ||
147 | perror("boot-image rewrite"); | ||
148 | exit(1); | ||
149 | } | ||
150 | |||
151 | exit(0); | ||
152 | } | ||