allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / arch / ppc / boot / utils / mkprep.c
blob192bb397126fac25f5eae2901316252dc19803e6
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
14 * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
15 * Modified for Sparc hosted builds by Peter Wahl <PeterWahl@web.de>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
22 /* size of read buffer */
23 #define SIZE 0x1000
26 * Partition table entry
27 * - from the PReP spec
29 typedef struct partition_entry {
30 unsigned char boot_indicator;
31 unsigned char starting_head;
32 unsigned char starting_sector;
33 unsigned char starting_cylinder;
35 unsigned char system_indicator;
36 unsigned char ending_head;
37 unsigned char ending_sector;
38 unsigned char ending_cylinder;
40 unsigned char beginning_sector[4];
41 unsigned char number_of_sectors[4];
42 } partition_entry_t;
44 #define BootActive 0x80
45 #define SystemPrep 0x41
47 void copy_image(FILE *, FILE *);
48 void write_prep_partition(FILE *, FILE *);
49 void write_asm_data(FILE *, FILE *);
51 unsigned int elfhdr_size = 65536;
53 int main(int argc, char *argv[])
55 FILE *in, *out;
56 int argptr = 1;
57 int prep = 0;
58 int asmoutput = 0;
60 if (argc < 3 || argc > 4) {
61 fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",
62 argv[0]);
63 exit(-1);
66 /* needs to handle args more elegantly -- but this is a small/simple program */
68 /* check for -pbp */
69 if (!strcmp(argv[argptr], "-pbp")) {
70 prep = 1;
71 argptr++;
74 /* check for -asm */
75 if (!strcmp(argv[argptr], "-asm")) {
76 asmoutput = 1;
77 argptr++;
80 /* input file */
81 if (!strcmp(argv[argptr], "-"))
82 in = stdin;
83 else if (!(in = fopen(argv[argptr], "r")))
84 exit(-1);
85 argptr++;
87 /* output file */
88 if (!strcmp(argv[argptr], "-"))
89 out = stdout;
90 else if (!(out = fopen(argv[argptr], "w")))
91 exit(-1);
92 argptr++;
94 /* skip elf header in input file */
95 /*if ( !prep )*/
96 fseek(in, elfhdr_size, SEEK_SET);
98 /* write prep partition if necessary */
99 if (prep)
100 write_prep_partition(in, out);
102 /* write input image to bootimage */
103 if (asmoutput)
104 write_asm_data(in, out);
105 else
106 copy_image(in, out);
108 return 0;
111 void store_le32(unsigned int v, unsigned char *p)
113 p[0] = v;
114 p[1] = v >>= 8;
115 p[2] = v >>= 8;
116 p[3] = v >> 8;
119 void write_prep_partition(FILE *in, FILE *out)
121 unsigned char block[512];
122 partition_entry_t pe;
123 unsigned char *entry = block;
124 unsigned char *length = block + 4;
125 long pos = ftell(in), size;
127 if (fseek(in, 0, SEEK_END) < 0) {
128 fprintf(stderr,"info failed\n");
129 exit(-1);
131 size = ftell(in);
132 if (fseek(in, pos, SEEK_SET) < 0) {
133 fprintf(stderr,"info failed\n");
134 exit(-1);
137 memset(block, '\0', sizeof(block));
139 /* set entry point and boot image size skipping over elf header */
140 store_le32(0x400/*+65536*/, entry);
141 store_le32(size-elfhdr_size+0x400, length);
143 /* sets magic number for msdos partition (used by linux) */
144 block[510] = 0x55;
145 block[511] = 0xAA;
148 * Build a "PReP" partition table entry in the boot record
149 * - "PReP" may only look at the system_indicator
151 pe.boot_indicator = BootActive;
152 pe.system_indicator = SystemPrep;
154 * The first block of the diskette is used by this "boot record" which
155 * actually contains the partition table. (The first block of the
156 * partition contains the boot image, but I digress...) We'll set up
157 * one partition on the diskette and it shall contain the rest of the
158 * diskette.
160 pe.starting_head = 0; /* zero-based */
161 pe.starting_sector = 2; /* one-based */
162 pe.starting_cylinder = 0; /* zero-based */
163 pe.ending_head = 1; /* assumes two heads */
164 pe.ending_sector = 18; /* assumes 18 sectors/track */
165 pe.ending_cylinder = 79; /* assumes 80 cylinders/diskette */
168 * The "PReP" software ignores the above fields and just looks at
169 * the next two.
170 * - size of the diskette is (assumed to be)
171 * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
172 * - unlike the above sector numbers, the beginning sector is zero-based!
174 #if 0
175 store_le32(1, pe.beginning_sector);
176 #else
177 /* This has to be 0 on the PowerStack? */
178 store_le32(0, pe.beginning_sector);
179 #endif
181 store_le32(2*18*80-1, pe.number_of_sectors);
183 memcpy(&block[0x1BE], &pe, sizeof(pe));
185 fwrite(block, sizeof(block), 1, out);
186 fwrite(entry, 4, 1, out);
187 fwrite(length, 4, 1, out);
188 /* set file position to 2nd sector where image will be written */
189 fseek( out, 0x400, SEEK_SET );
194 void copy_image(FILE *in, FILE *out)
196 char buf[SIZE];
197 int n;
199 while ( (n = fread(buf, 1, SIZE, in)) > 0 )
200 fwrite(buf, 1, n, out);
204 void
205 write_asm_data(FILE *in, FILE *out)
207 int i, cnt, pos = 0;
208 unsigned int cksum = 0, val;
209 unsigned char *lp;
210 unsigned char buf[SIZE];
211 size_t len;
213 fputs("\t.data\n\t.globl input_data\ninput_data:\n", out);
214 while ((len = fread(buf, 1, sizeof(buf), in)) > 0) {
215 cnt = 0;
216 lp = buf;
217 /* Round up to longwords */
218 while (len & 3)
219 buf[len++] = '\0';
220 for (i = 0; i < len; i += 4) {
221 if (cnt == 0)
222 fputs("\t.long\t", out);
223 fprintf(out, "0x%02X%02X%02X%02X",
224 lp[0], lp[1], lp[2], lp[3]);
225 val = *(unsigned long *)lp;
226 cksum ^= val;
227 lp += 4;
228 if (++cnt == 4) {
229 cnt = 0;
230 fprintf(out, " # %x \n", pos+i-12);
231 } else {
232 fputs(",", out);
235 if (cnt)
236 fputs("0\n", out);
237 pos += len;
239 fprintf(out, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos);
240 fprintf(stderr, "cksum = %x\n", cksum);