Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
445 theseven 1
/****************************************************************************/
2
/*
3
 *	A simple program to manipulate flat files
4
 *
5
 *	Copyright (C) 2001-2003 SnapGear Inc, davidm@snapgear.com
6
 *	Copyright (C) 2001 Lineo, davidm@lineo.com
7
 *
8
 * This is Free Software, under the GNU Public Licence v2 or greater.
9
 *
10
 */
11
/****************************************************************************/
12
 
13
#include <stdio.h>    /* Userland pieces of the ANSI C standard I/O package  */
14
#include <unistd.h>   /* Userland prototypes of the Unix std system calls    */
15
#include <time.h>
16
#include <stdlib.h>   /* exit() */
17
#include <string.h>   /* strcat(), strcpy() */
18
#include <inttypes.h>
19
#include <assert.h>
20
 
21
#include "compress.h"
22
#include <libiberty.h>
23
 
24
#include "stubs.h"
25
const char *elf2flt_progname;
26
 
27
/* from uClinux-x.x.x/include/linux */
28
#include "flat.h"     /* Binary flat header description                      */
29
 
30
#if defined(__MINGW32__)
31
#include <getopt.h>
32
 
33
#define mkstemp(p) mktemp(p)
34
 
35
#endif
36
 
37
#if defined TARGET_bfin
38
# define flat_get_relocate_addr(addr) (addr & 0x03ffffff)
39
#else
40
# define flat_get_relocate_addr(addr) (addr)
41
#endif
42
 
43
/****************************************************************************/
44
 
45
static int print = 0, print_relocs = 0, docompress = 0, ramload = 0,
46
           stacksize = 0, ktrace = 0, l1stack = 0;
47
 
48
/****************************************************************************/
49
 
50
void
51
process_file(char *ifile, char *ofile)
52
{
53
	int old_flags, old_stack, new_flags, new_stack;
54
	stream ifp, ofp;
55
	struct flat_hdr old_hdr, new_hdr;
56
	char *tfile, tmpbuf[256];
57
	int input_error, output_error;
58
 
59
	*tmpbuf = '\0';
60
 
61
	if (fopen_stream_u(&ifp, ifile, "r" BINARY_FILE_OPTS)) {
62
		fprintf(stderr, "Cannot open %s\n", ifile);
63
		return;
64
	}
65
 
66
	if (fread_stream(&old_hdr, sizeof(old_hdr), 1, &ifp) != 1) {
67
		fprintf(stderr, "Cannot read header of %s\n", ifile);
68
		fclose_stream(&ifp);
69
		return;
70
	}
71
 
72
	if (strncmp(old_hdr.magic, "bFLT", 4) != 0) {
73
		fprintf(stderr, "Cannot read header of %s\n", ifile);
74
		fclose_stream(&ifp);
75
		return;
76
	}
77
 
78
	new_flags = old_flags = ntohl(old_hdr.flags);
79
	new_stack = old_stack = ntohl(old_hdr.stack_size);
80
	new_hdr = old_hdr;
81
 
82
	if (docompress == 1) {
83
		new_flags |= FLAT_FLAG_GZIP;
84
		new_flags &= ~FLAT_FLAG_GZDATA;
85
	} else if (docompress == 2) {
86
		new_flags |= FLAT_FLAG_GZDATA;
87
		new_flags &= ~FLAT_FLAG_GZIP;
88
	} else if (docompress < 0)
89
		new_flags &= ~(FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA);
90
 
91
	if (ramload > 0)
92
		new_flags |= FLAT_FLAG_RAM;
93
	else if (ramload < 0)
94
		new_flags &= ~FLAT_FLAG_RAM;
95
 
96
	if (ktrace > 0)
97
		new_flags |= FLAT_FLAG_KTRACE;
98
	else if (ktrace < 0)
99
		new_flags &= ~FLAT_FLAG_KTRACE;
100
 
101
	if (l1stack > 0)
102
		new_flags |= FLAT_FLAG_L1STK;
103
	else if (l1stack < 0)
104
		new_flags &= ~FLAT_FLAG_L1STK;
105
 
106
	if (stacksize)
107
		new_stack = stacksize;
108
 
109
	if (print == 1) {
110
		time_t t;
111
		uint32_t reloc_count, reloc_start;
112
 
113
		printf("%s\n", ifile);
114
		printf("    Magic:        %4.4s\n", old_hdr.magic);
115
		printf("    Rev:          %d\n",    ntohl(old_hdr.rev));
116
		t = (time_t) htonl(old_hdr.build_date);
117
		printf("    Build Date:   %s",      t?ctime(&t):"not specified\n");
118
		printf("    Entry:        0x%x\n",  ntohl(old_hdr.entry));
119
		printf("    Data Start:   0x%x\n",  ntohl(old_hdr.data_start));
120
		printf("    Data End:     0x%x\n",  ntohl(old_hdr.data_end));
121
		printf("    BSS End:      0x%x\n",  ntohl(old_hdr.bss_end));
122
		printf("    Stack Size:   0x%x\n",  ntohl(old_hdr.stack_size));
123
		reloc_start = ntohl(old_hdr.reloc_start);
124
		printf("    Reloc Start:  0x%x\n",  reloc_start);
125
		reloc_count = ntohl(old_hdr.reloc_count);
126
		printf("    Reloc Count:  0x%x\n",  reloc_count);
127
		printf("    Flags:        0x%x ( ",  ntohl(old_hdr.flags));
128
		if (old_flags) {
129
			if (old_flags & FLAT_FLAG_RAM)
130
				printf("Load-to-Ram ");
131
			if (old_flags & FLAT_FLAG_GOTPIC)
132
				printf("Has-PIC-GOT ");
133
			if (old_flags & FLAT_FLAG_GZIP)
134
				printf("Gzip-Compressed ");
135
			if (old_flags & FLAT_FLAG_GZDATA)
136
				printf("Gzip-Data-Compressed ");
137
			if (old_flags & FLAT_FLAG_KTRACE)
138
				printf("Kernel-Traced-Load ");
139
			if (old_flags & FLAT_FLAG_L1STK)
140
				printf("L1-Scratch-Stack ");
141
			printf(")\n");
142
		}
143
 
144
		if (print_relocs) {
145
			uint32_t *relocs = xcalloc(reloc_count, sizeof(uint32_t));
146
			uint32_t i;
147
			unsigned long r;
148
 
149
			printf("    Relocs:\n");
150
			printf("    #\treloc      (  address )\tdata\n");
151
 
152
			if (old_flags & FLAT_FLAG_GZIP)
153
				reopen_stream_compressed(&ifp);
154
			if (fseek_stream(&ifp, reloc_start, SEEK_SET)) {
155
				fprintf(stderr, "Cannot seek to relocs of %s\n", ifile);
156
				fclose_stream(&ifp);
157
				return;
158
			}
159
			if (fread_stream(relocs, sizeof(uint32_t), reloc_count, &ifp) == -1) {
160
				fprintf(stderr, "Cannot read relocs of %s\n", ifile);
161
				fclose_stream(&ifp);
162
				return;
163
			}
164
 
165
			for (i = 0; i < reloc_count; ++i) {
166
				uint32_t raddr, addr;
167
				r = ntohl(relocs[i]);
168
				raddr = flat_get_relocate_addr(r);
169
				printf("    %u\t0x%08lx (0x%08"PRIx32")\t", i, r, raddr);
170
				fseek_stream(&ifp, sizeof(old_hdr) + raddr, SEEK_SET);
171
				fread_stream(&addr, sizeof(addr), 1, &ifp);
172
				printf("%"PRIx32"\n", addr);
173
			}
174
 
175
			/* reset file position for below */
176
			fseek_stream(&ifp, sizeof(old_hdr), SEEK_SET);
177
		}
178
	} else if (print > 1) {
179
		static int first = 1;
180
		unsigned int text, data, bss, stk, rel, tot;
181
 
182
		if (first) {
183
			printf("Flag Rev   Text   Data    BSS  Stack Relocs    RAM Filename\n");
184
			printf("-----------------------------------------------------------\n");
185
			first = 0;
186
		}
187
		*tmpbuf = '\0';
188
		strcat(tmpbuf, (old_flags & FLAT_FLAG_KTRACE) ? "k" : "");
189
		strcat(tmpbuf, (old_flags & FLAT_FLAG_RAM) ? "r" : "");
190
		strcat(tmpbuf, (old_flags & FLAT_FLAG_GOTPIC) ? "p" : "");
191
		strcat(tmpbuf, (old_flags & FLAT_FLAG_GZIP) ? "z" :
192
					((old_flags & FLAT_FLAG_GZDATA) ? "d" : ""));
193
		printf("-%-3.3s ", tmpbuf);
194
		printf("%3d ", ntohl(old_hdr.rev));
195
		printf("%6d ", text=ntohl(old_hdr.data_start)-sizeof(struct flat_hdr));
196
		printf("%6d ", data=ntohl(old_hdr.data_end)-ntohl(old_hdr.data_start));
197
		printf("%6d ", bss=ntohl(old_hdr.bss_end)-ntohl(old_hdr.data_end));
198
		printf("%6d ", stk=ntohl(old_hdr.stack_size));
199
		printf("%6d ", rel=ntohl(old_hdr.reloc_count) * 4);
200
		/*
201
		 * work out how much RAM is needed per invocation, this
202
		 * calculation is dependent on the binfmt_flat implementation
203
		 */
204
		tot = data; /* always need data */
205
 
206
		if (old_flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))
207
			tot += text + sizeof(struct flat_hdr);
208
 
209
		if (bss + stk > rel) /* which is bigger ? */
210
			tot += bss + stk;
211
		else
212
			tot += rel;
213
 
214
		printf("%6d ", tot);
215
		/*
216
		 * the total depends on whether the relocs are smaller/bigger than
217
		 * the BSS
218
		 */
219
		printf("%s\n", ifile);
220
	}
221
 
222
	/* if there is nothing else to do, leave */
223
	if (new_flags == old_flags && new_stack == old_stack) {
224
		fclose_stream(&ifp);
225
		return;
226
	}
227
 
228
	new_hdr.flags = htonl(new_flags);
229
	new_hdr.stack_size = htonl(new_stack);
230
 
231
	tfile = make_temp_file("flthdr");
232
 
233
	if (fopen_stream_u(&ofp, tfile, "w" BINARY_FILE_OPTS)) {
234
		unlink(tfile);
235
		fatal("Failed to open %s for writing\n", tfile);
236
	}
237
 
238
	/* Copy header (always uncompressed).  */
239
	if (fwrite_stream(&new_hdr, sizeof(new_hdr), 1, &ofp) != 1) {
240
		unlink(tfile);
241
		fatal("Failed to write to  %s\n", tfile);
242
	}
243
 
244
	/* Whole input file (including text) is compressed: start decompressing
245
	   now.  */
246
	if (old_flags & FLAT_FLAG_GZIP)
247
		reopen_stream_compressed(&ifp);
248
 
249
	/* Likewise, output file is compressed. Start compressing now.  */
250
	if (new_flags & FLAT_FLAG_GZIP) {
251
		printf("zflat %s --> %s\n", ifile, ofile);
252
		reopen_stream_compressed(&ofp);
253
	}
254
 
255
	transfer(&ifp, &ofp,
256
		  ntohl(old_hdr.data_start) - sizeof(struct flat_hdr));
257
 
258
	/* Only data and relocs were compressed in input.  Start decompressing
259
	   from here.  */
260
	if (old_flags & FLAT_FLAG_GZDATA)
261
		reopen_stream_compressed(&ifp);
262
 
263
	/* Only data/relocs to be compressed in output.  Start compressing
264
	   from here.  */
265
	if (new_flags & FLAT_FLAG_GZDATA) {
266
		printf("zflat-data %s --> %s\n", ifile, ofile);
267
		reopen_stream_compressed(&ofp);
268
	}
269
 
270
	transfer(&ifp, &ofp, -1);
271
 
272
	input_error = ferror_stream(&ifp);
273
	output_error = ferror_stream(&ofp);
274
 
275
	if (input_error || output_error) {
276
		unlink(tfile);
277
		fatal("Error on file pointer%s%s\n",
278
				input_error ? " input" : "",
279
				output_error ? " output" : "");
280
	}
281
 
282
	fclose_stream(&ifp);
283
	fclose_stream(&ofp);
284
 
285
	/* Copy temporary file to output location.  */
286
	fopen_stream_u(&ifp, tfile, "r" BINARY_FILE_OPTS);
287
	fopen_stream_u(&ofp, ofile, "w" BINARY_FILE_OPTS);
288
 
289
	transfer(&ifp, &ofp, -1);
290
 
291
	fclose_stream(&ifp);
292
	fclose_stream(&ofp);
293
 
294
	unlink(tfile);
295
	free(tfile);
296
}
297
 
298
/****************************************************************************/
299
 
300
void
301
usage(char *s)
302
{
303
	if (s)
304
		fprintf(stderr, "%s\n", s);
305
	fprintf(stderr, "usage: %s [options] flat-file\n", elf2flt_progname);
306
	fprintf(stderr, "       Allows you to change an existing flat file\n\n");
307
	fprintf(stderr, "       -p      : print current settings\n");
308
	fprintf(stderr, "       -P      : print relocations\n");
309
	fprintf(stderr, "       -z      : compressed flat file\n");
310
	fprintf(stderr, "       -d      : compressed data-only flat file\n");
311
	fprintf(stderr, "       -Z      : un-compressed flat file\n");
312
	fprintf(stderr, "       -r      : ram load\n");
313
	fprintf(stderr, "       -R      : do not RAM load\n");
314
	fprintf(stderr, "       -k      : kernel traced load (for debug)\n");
315
	fprintf(stderr, "       -K      : normal non-kernel traced load\n");
316
	fprintf(stderr, "       -u      : place stack in L1 scratchpad memory\n");
317
	fprintf(stderr, "       -U      : place stack in normal SDRAM memory\n");
318
	fprintf(stderr, "       -s size : stack size\n");
319
	fprintf(stderr, "       -o file : output-file\n"
320
	                "                 (default is to modify input file)\n");
321
	exit(1);
322
}
323
 
324
/****************************************************************************/
325
 
326
int
327
main(int argc, char *argv[])
328
{
329
	int c, noargs;
330
	char *ofile = NULL, *ifile;
331
 
332
	elf2flt_progname = argv[0];
333
 
334
	noargs = 1;
335
	while ((c = getopt(argc, argv, "pPdzZrRuUkKs:o:")) != EOF) {
336
		switch (c) {
337
		case 'p': print = 1;                break;
338
		case 'P': print_relocs = 1;         break;
339
		case 'z': docompress = 1;           break;
340
		case 'd': docompress = 2;           break;
341
		case 'Z': docompress = -1;          break;
342
		case 'r': ramload = 1;              break;
343
		case 'R': ramload = -1;             break;
344
		case 'k': ktrace = 1;               break;
345
		case 'K': ktrace = -1;              break;
346
		case 'u': l1stack = 1;              break;
347
		case 'U': l1stack = -1;             break;
348
		case 'o': ofile = optarg;           break;
349
		case 's':
350
			if (sscanf(optarg, "%i", &stacksize) != 1)
351
				usage("invalid stack size");
352
			break;
353
		default:
354
			usage("invalid option");
355
			break;
356
		}
357
		noargs = 0;
358
	}
359
 
360
	if (optind >= argc)
361
		usage("No input files provided");
362
 
363
	if (ofile && argc - optind > 1)
364
		usage("-o can only be used with a single file");
365
 
366
	if (!print && noargs) /* no args == print */
367
		print = argc - optind; /* greater than 1 is short format */
368
 
369
	for (c = optind; c < argc; c++) {
370
		ifile = argv[c];
371
		if (!ofile)
372
			ofile = ifile;
373
		process_file(ifile, ofile);
374
		ofile = NULL;
375
	}
376
 
377
	exit(0);
378
}
379
 
380
/****************************************************************************/