1 |
/**************************************************************************** |
2 |
/* F i l e D a t a |
3 |
/* |
4 |
/* Module : BootStrap |
5 |
/* C.I. No. : |
6 |
/* $Revision: 1.1.1.1 $ |
7 |
/* $Date: 2003/08/04 09:40:21 $ |
8 |
/* Belonging to : |
9 |
/* : |
10 |
/* $RCSfile: mkprom.c,v $ |
11 |
/* Program Type : |
12 |
/* Sub-modules : |
13 |
/* |
14 |
/**************************************************************************** |
15 |
/* S W D e v e l o p m e n t E n v i r o n m e n t |
16 |
/* |
17 |
/* Host system : |
18 |
/* SW Compiler : |
19 |
/* $Author: sebastiani $ |
20 |
/* : |
21 |
/**************************************************************************** |
22 |
/* U p d a t i n g |
23 |
/* |
24 |
/* $Log: mkprom.c,v $ |
25 |
/* Revision 1.1.1.1 2003/08/04 09:40:21 sebastiani |
26 |
/* Imported sources laben rel. 19.06.2003 integrated with pam2 |
27 |
/* |
28 |
/* Revision 1.2 2002/05/09 08:16:34 zulia |
29 |
/* * acceptance release |
30 |
/* |
31 |
/* |
32 |
/*****************************************************************************/ |
33 |
|
34 |
/* |
35 |
* This file is part of MKPROM. |
36 |
* |
37 |
* MKPROM, ERC32 boot-prom utility. Copyright (C) 1995 Jiri Gaisler, European |
38 |
* Space Agency |
39 |
* |
40 |
* This program is free software; you can redistribute it and/or modify it under |
41 |
* the terms of the GNU General Public License as published by the Free |
42 |
* Software Foundation; either version 2 of the License, or (at your option) |
43 |
* any later version. |
44 |
* |
45 |
* This program is distributed in the hope that it will be useful, but WITHOUT |
46 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
47 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
48 |
* more details. |
49 |
* |
50 |
* You should have received a copy of the GNU General Public License along with |
51 |
* this program; if not, write to the Free Software Foundation, Inc., 675 |
52 |
* Mass Ave, Cambridge, MA 02139, USA. |
53 |
* |
54 |
*/ |
55 |
|
56 |
#include <string.h> |
57 |
#include <stdlib.h> |
58 |
#include <stdio.h> |
59 |
|
60 |
#ifndef fprintf |
61 |
extern fprintf(); |
62 |
#endif |
63 |
|
64 |
#define VAL(x) strtol(x,(char **)NULL,0) |
65 |
#define SECMAX 32 |
66 |
#define SECNAME 16 |
67 |
|
68 |
typedef struct sectype { |
69 |
unsigned int paddr; |
70 |
unsigned int raddr; |
71 |
unsigned int len; |
72 |
unsigned int comp; |
73 |
unsigned char name[SECNAME]; |
74 |
}tt; |
75 |
|
76 |
struct sectype secarr[SECMAX]; |
77 |
char filename[128]; |
78 |
char filecore[128]; |
79 |
char fileload[128]; |
80 |
unsigned int fileSeq =0; |
81 |
|
82 |
#ifdef __sun |
83 |
#define TOOLBASE "/opt/gnu" |
84 |
#else |
85 |
#define TOOLBASE "/usr/local" |
86 |
#endif |
87 |
const char version[] = "v1.2.9"; |
88 |
int secnum = 0; |
89 |
FILE *dumpfile; |
90 |
|
91 |
int verbose = 0; |
92 |
#ifdef LEON |
93 |
int leon = 1; |
94 |
#else |
95 |
int leon = 0; |
96 |
#endif |
97 |
main(argc, argv) |
98 |
int argc; |
99 |
char **argv; |
100 |
|
101 |
{ |
102 |
|
103 |
char cmd[512]; |
104 |
char msg[128]; |
105 |
int baud = 19200; /* 19200 baud */ |
106 |
int edac = 1; |
107 |
int par = 1; |
108 |
#ifdef LEON |
109 |
double freq = 5E7; |
110 |
#else |
111 |
double freq = 1E7; |
112 |
#endif |
113 |
double wdfreq = 0.0; |
114 |
int i; |
115 |
int mctrl = 0x0088001f; |
116 |
int memcfg = 0; |
117 |
int prot = 1; |
118 |
int wrp = 0; |
119 |
int ramcs = 0; |
120 |
int rambanks = 1; |
121 |
int ramsize = 0x200000; /* 2M ram */ |
122 |
int romsize = 0x80000; /* 512K rom */ |
123 |
int ramws = 0; |
124 |
int ramrws = 0; |
125 |
int ramwws = 0; |
126 |
int romws = 2; |
127 |
int romrws = 2; |
128 |
int romwws = 2; |
129 |
int stack = 0; |
130 |
int rom8 = 0; |
131 |
int ram8 = 0; |
132 |
int stat = 1; |
133 |
int bdinit = 0; |
134 |
int waitcfg = 0x33330000; |
135 |
int wdog = 1; |
136 |
int comp = 0; |
137 |
int dump = 0; |
138 |
char ofile[128] = "prom.out"; |
139 |
int tmp, iows, ioarea; |
140 |
|
141 |
|
142 |
printf("\nMKPROM - ERC32 boot-prom builder %s, copyright Jiri Gaisler, ESA/ESTEC 1997\n", version); |
143 |
printf("Bug-reports to jgais@ws.estec.esa.nl\n\n"); |
144 |
if ((dumpfile = fopen("dump.s", "w+")) == NULL) { |
145 |
printf("Failed to open temporary file\n"); |
146 |
exit(1); |
147 |
} |
148 |
while (stat < argc) { |
149 |
if (argv[stat][0] == '-') { |
150 |
if (strcmp(argv[stat], "-v") == 0) { |
151 |
verbose = 1; |
152 |
} else if (strcmp(argv[stat], "-baud") == 0) { |
153 |
if ((stat + 1) < argc) |
154 |
baud = VAL(argv[++stat]); |
155 |
} else if (strcmp(argv[stat], "-wdog") == 0) { |
156 |
wdog = 0; |
157 |
} else if (strcmp(argv[stat], "-dump") == 0) { |
158 |
dump = 1; |
159 |
} else if (strcmp(argv[stat], "-nopar") == 0) { |
160 |
par = 0; |
161 |
} else if (strcmp(argv[stat], "-noedac") == 0) { |
162 |
edac = 0; |
163 |
} else if (strcmp(argv[stat], "-wrp") == 0) { |
164 |
wrp = 1; |
165 |
} else if (strcmp(argv[stat], "-leon") == 0) { |
166 |
leon = 1; |
167 |
} else if (strcmp(argv[stat], "-rom8") == 0) { |
168 |
rom8 = 1; |
169 |
} else if (strcmp(argv[stat], "-ram8") == 0) { |
170 |
ram8 = 1; |
171 |
} else if (strcmp(argv[stat], "-bdinit") == 0) { |
172 |
bdinit = 1; |
173 |
} else if (strcmp(argv[stat], "-freq") == 0) { |
174 |
if ((stat + 1) < argc) |
175 |
freq = atof(argv[++stat]); |
176 |
freq *= 1E6; |
177 |
} else if (strcmp(argv[stat], "-wdfreq") == 0) { |
178 |
if ((stat + 1) < argc) |
179 |
wdfreq = atof(argv[++stat]); |
180 |
wdfreq *= 1E6; |
181 |
} else if (strcmp(argv[stat], "-noprot") == 0) { |
182 |
prot = 0; mctrl &= ~0x8; |
183 |
} else if (strcmp(argv[stat], "-o") == 0) { |
184 |
strncpy(ofile,argv[++stat],127); |
185 |
ofile[127] = 0; |
186 |
} else if (strcmp(argv[stat], "-ramsize") == 0) { |
187 |
if ((stat + 1) < argc) { |
188 |
ramsize = (VAL(argv[++stat])) & 0x03ffff; |
189 |
ramsize *= 1024; |
190 |
} |
191 |
} else if (strcmp(argv[stat], "-romws") == 0) { |
192 |
if ((stat + 1) < argc) |
193 |
romws = (VAL(argv[++stat])) & 0xf; |
194 |
} else if (strcmp(argv[stat], "-romsize") == 0) { |
195 |
if ((stat + 1) < argc) { |
196 |
romsize = (VAL(argv[++stat])) & 0x01ffff; |
197 |
romsize *= 1024; |
198 |
} |
199 |
} else if (strcmp(argv[stat], "-ramcs") == 0) { |
200 |
if ((stat + 1) < argc) |
201 |
rambanks = (VAL(argv[++stat])) & 0x0f; |
202 |
switch (rambanks) { |
203 |
case 1: |
204 |
ramcs = 0; |
205 |
break; |
206 |
case 2: |
207 |
ramcs = 1; |
208 |
break; |
209 |
case 4: |
210 |
ramcs = 2; |
211 |
break; |
212 |
case 8: |
213 |
ramcs = 3; |
214 |
break; |
215 |
default: |
216 |
ramcs = 0; |
217 |
} |
218 |
} else if (strcmp(argv[stat], "-stack") == 0) { |
219 |
if ((stat + 1) < argc) |
220 |
stack = (VAL(argv[++stat])) & ~0x01f; |
221 |
} else if (strcmp(argv[stat], "-ramws") == 0) { |
222 |
if ((stat + 1) < argc) |
223 |
ramws = (VAL(argv[++stat])) & 0x3; |
224 |
} else if (strcmp(argv[stat], "-ramrws") == 0) { |
225 |
if ((stat + 1) < argc) |
226 |
ramrws = (VAL(argv[++stat])) & 0x3; |
227 |
} else if (strcmp(argv[stat], "-ramwws") == 0) { |
228 |
if ((stat + 1) < argc) |
229 |
ramwws = (VAL(argv[++stat])) & 0x3; |
230 |
} else if (strncmp(argv[stat], "-iows", 5) == 0) { |
231 |
if ((stat + 1) < argc) { |
232 |
ioarea = argv[stat][5] - '0'; |
233 |
iows = VAL(argv[++stat]); |
234 |
if ((ioarea >= 0) && (ioarea < 4) && (iows >=0) && (iows <= 14)) { |
235 |
if (verbose) |
236 |
printf("\nI/O area %d: %d waitstates\n", ioarea, iows); |
237 |
iows++; |
238 |
waitcfg &= ~(0x000f0000 << (ioarea * 4)); |
239 |
waitcfg |= iows << (ioarea * 4 + 16); |
240 |
} |
241 |
} |
242 |
} else { |
243 |
printf("unknown option %s\n", argv[stat]); |
244 |
usage(); |
245 |
exit(1); |
246 |
} |
247 |
} else { |
248 |
if (fileSeq == 0) |
249 |
{ |
250 |
strcpy(filecore, argv[stat]); |
251 |
fileSeq++; |
252 |
} |
253 |
else if (fileSeq == 1) |
254 |
{ |
255 |
strcpy(fileload, argv[stat]); |
256 |
fileSeq++; |
257 |
} |
258 |
else if (fileSeq == 2) |
259 |
{ |
260 |
if (secnum == 0) |
261 |
strcpy(filename, argv[stat]); |
262 |
bfd_load(argv[stat], comp); |
263 |
} |
264 |
} |
265 |
stat++; |
266 |
} |
267 |
fprintf(dumpfile, "\n\t.global _filename\n"); |
268 |
fprintf(dumpfile, "_filename:\n"); |
269 |
fprintf(dumpfile, "\t.string\t\"%s\"\n", filename); |
270 |
fprintf(dumpfile, "\n\t.align 32\n"); |
271 |
fprintf(dumpfile, "\t.global _sections\n"); |
272 |
fprintf(dumpfile, "_sections:\n"); |
273 |
for (i = 0; i < secnum; i++) { |
274 |
fprintf(dumpfile, "\t.word\t0x%x\n", secarr[i].paddr); |
275 |
fprintf(dumpfile, "\t.word\t_section%d\n", i); |
276 |
fprintf(dumpfile, "\t.word\t0x%x\n", secarr[i].len); |
277 |
fprintf(dumpfile, "\t.word\t0x%x\n", secarr[i].comp); |
278 |
fprintf(dumpfile, "\t.string\t\"%s\"\n", secarr[i].name); |
279 |
fprintf(dumpfile, "\n\t.align 32\n"); |
280 |
} |
281 |
fprintf(dumpfile, "\t.word\t0\n"); |
282 |
|
283 |
if (leon) { |
284 |
fprintf(dumpfile, "\n\t.global _memcfg1, _memcfg2, _uart, _scaler \n"); |
285 |
} else { |
286 |
fprintf(dumpfile, "\n\t.global _wdog, _mctrl \n"); |
287 |
fprintf(dumpfile, "\t.global _waitcfg, _memcfg, _prot\n"); |
288 |
} |
289 |
fprintf(dumpfile, "\n\t.global _ramsize, _stack\n"); |
290 |
fprintf(dumpfile, "\t.global _freq, _configmsg\n"); |
291 |
fprintf(dumpfile, "_freq:\n"); |
292 |
fprintf(dumpfile, "\t.word\t%d\n", (int) (freq/1000000)); |
293 |
if (leon) { |
294 |
tmp = romsize; tmp >>= 16; i = 0; |
295 |
while (tmp) { i++; tmp >>= 1; } |
296 |
tmp = (i << 14) | romws | (romws << 4); |
297 |
if (!rom8) tmp |= 0x300; |
298 |
if (edac) tmp |= 0x400; |
299 |
fprintf(dumpfile, "_memcfg1:\n"); |
300 |
fprintf(dumpfile, "\t.word\t0x%x\n", tmp); |
301 |
tmp = ramsize; tmp >>= 16; i = 0; |
302 |
while (tmp) { i++; tmp >>= 1; } |
303 |
tmp = (i << 9) | ramrws | (ramwws << 4); |
304 |
if (!ram8) tmp |= 0x30; |
305 |
if (edac) tmp |= 0x80; |
306 |
fprintf(dumpfile, "_memcfg2:\n"); |
307 |
fprintf(dumpfile, "\t.word\t0x%x\n", tmp); |
308 |
tmp = (int)(freq / (8 * baud) - 1); |
309 |
fprintf(dumpfile, "_uart:\n"); |
310 |
fprintf(dumpfile, "\t.word\t%d\n", tmp); |
311 |
if (!stack) stack = 0x40000000 + ramsize - 32; |
312 |
} else { |
313 |
fprintf(dumpfile, "_wdog:\n"); |
314 |
fprintf(dumpfile, "\t.word\t%d\n", wdog); |
315 |
fprintf(dumpfile, "_mctrl:\n"); |
316 |
if (wdfreq > 0.0) { |
317 |
mctrl |= (int)(wdfreq / (32 * baud) - 1) << 24; |
318 |
mctrl &= 0xff7fffff; |
319 |
} else |
320 |
mctrl |= (int)(freq / (32 * baud) - 1) << 24; |
321 |
fprintf(dumpfile, "\t.word\t0x%x\n", mctrl); |
322 |
fprintf(dumpfile, "_waitcfg:\n"); |
323 |
if (romws) |
324 |
romws++; |
325 |
waitcfg |= romws << 4; |
326 |
if (ramws) { |
327 |
waitcfg |= (0x3 & ramws); |
328 |
waitcfg |= (0x3 & ramws) << 2; |
329 |
} else { |
330 |
waitcfg |= (0x3 & ramrws); |
331 |
waitcfg |= (0x3 & ramwws) << 2; |
332 |
} |
333 |
fprintf(dumpfile, "\t.word\t0x%x\n", waitcfg); |
334 |
fprintf(dumpfile, "_prot:\n"); |
335 |
fprintf(dumpfile, "\t.word\t%d\n", prot); |
336 |
if (!stack) stack = 0x2000000 + ramsize - 32; |
337 |
fprintf(dumpfile, "_memcfg:\n"); |
338 |
memcfg |= (memcfg & ~3) | ramcs; |
339 |
i = 0; tmp = ramsize; tmp >>= 18; |
340 |
while (tmp) { i++; tmp >>= 1; } |
341 |
if (i) i--; |
342 |
memcfg |= (memcfg & ~0x1c00) | (i << 10); |
343 |
i = 0; tmp = romsize; tmp >>= 17; |
344 |
while (tmp) { i++; tmp >>= 1; } |
345 |
if (i) i--; |
346 |
memcfg |= (memcfg & ~0x1c0000) | (i << 18); |
347 |
memcfg |= (edac << 14); |
348 |
memcfg |= (par << 13); |
349 |
if (wrp) memcfg |= (1 << 16); |
350 |
fprintf(dumpfile, "\t.word\t0x%x\n", memcfg); |
351 |
} |
352 |
fprintf(dumpfile, "_ramsize:\n"); |
353 |
fprintf(dumpfile, "\t.word\t0x%x\n", ramsize); |
354 |
fprintf(dumpfile, "_stack:\n"); |
355 |
fprintf(dumpfile, "\t.word\t0x%x\n", stack); |
356 |
|
357 |
sprintf(cmd, " system clock : %3.1f MHz\\n\\r", freq/1E6); |
358 |
if (wdfreq > 0.0) { |
359 |
sprintf(msg, " watchdog clock : %4.1f MHz\\n\\r", wdfreq/1E6); |
360 |
strcat(cmd, msg); |
361 |
} |
362 |
sprintf(msg, " baud rate : %d baud\\n\\r", baud); strcat(cmd, msg); |
363 |
sprintf(msg, " prom : %d K, %d ws\\n\\r", romsize>>10, romws); |
364 |
strcat(cmd, msg); |
365 |
if (rambanks > 1) |
366 |
sprintf(msg, " ram : %d K, %d banks,", ramsize>>10, rambanks); |
367 |
else |
368 |
sprintf(msg, " ram : %d K, %d bank,", ramsize>>10, rambanks); |
369 |
strcat(cmd, msg); |
370 |
if (ramws) { |
371 |
sprintf(msg, " %d/%d ws (r/w)\\n\\r", ramws, ramws); |
372 |
} else { |
373 |
sprintf(msg, " %d/", ramrws); |
374 |
strcat(cmd, msg); |
375 |
sprintf(msg, "%d ws (r/w)\\n\\r", ramwws); |
376 |
} |
377 |
strcat(cmd, msg); |
378 |
if (edac) |
379 |
sprintf(msg, " edac : enabled\\n\\r"); |
380 |
else |
381 |
sprintf(msg, " edac : disabled\\n\\r"); |
382 |
strcat(cmd, msg); |
383 |
if (!leon) { |
384 |
if (edac || par) sprintf(msg, " parity : enabled\\n\\r"); |
385 |
else sprintf(msg, " parity : disabled\\n\\r"); |
386 |
strcat(cmd, msg); |
387 |
} |
388 |
if (prot && !leon) |
389 |
sprintf(msg, " write-protect : 0x%08x - 0x%08x\\n\\r", |
390 |
secarr[0].paddr + 0x1000, secarr[0].paddr + secarr[0].len ); |
391 |
else |
392 |
sprintf(msg, " write-protect : disabled\\n\\r"); |
393 |
strcat(cmd, msg); |
394 |
if (!wdog) |
395 |
sprintf(msg, " watchdog : enabled\\n\\r"); |
396 |
else |
397 |
sprintf(msg, " watchdog : disabled\\n\\r"); |
398 |
strcat(cmd, msg); |
399 |
fprintf(dumpfile, "_configmsg:\n"); |
400 |
fprintf(dumpfile, "\t.string\t\"%s\"\n", cmd); |
401 |
fclose(dumpfile); |
402 |
|
403 |
sprintf(cmd,"sparc-rtems-gcc -O2 -g -N -mkprom -nostartfiles -Ttext 0 %s %s -nostdlib dump.s -lmkprom -o",filecore,fileload); |
404 |
// sprintf(cmd,"sparc-rtems-gcc -O2 -g -N -mkprom -nostartfiles -Ttext 0 %s -nostdlib dump.s -lmkprom -o",filecore); |
405 |
strcat(cmd,ofile); |
406 |
if (verbose) printf("\n%s\n", cmd); |
407 |
system(cmd); |
408 |
// if (!dump) system("rm -f dump.s"); |
409 |
|
410 |
exit(0); |
411 |
} |
412 |
|
413 |
|
414 |
usage() |
415 |
{ |
416 |
} |
417 |
|
418 |
|
419 |
#define N 4096 /* size of ring buffer (maximum is 4096 |
420 |
* because the pointer is coded in 12 bits */ |
421 |
#define F 18 /* upper limit for match_length (maximum is |
422 |
* 15 + THRESHOLD + 1 because the length is |
423 |
* coded in 4 bits) */ |
424 |
|
425 |
#define THRESHOLD 2 /* encode string into position and length if |
426 |
* match_length is greater than this |
427 |
* (compression) */ |
428 |
#define NIL N /* index for root of binary search trees */ |
429 |
#define MAGIC_NUMBER '\xaa' |
430 |
#define EOP '\x55' |
431 |
#ifndef SEEK_SET |
432 |
#define SEEK_SET 0 |
433 |
#endif |
434 |
#ifndef SEEK_CUR |
435 |
#define SEEK_CUR 1 |
436 |
#endif |
437 |
#ifndef SEEK_END |
438 |
#define SEEK_END 2 |
439 |
#endif |
440 |
|
441 |
unsigned char |
442 |
text_buf[N + F - 1]; /* ring buffer of size N, with extra |
443 |
* F-1 bytes to facilitate string |
444 |
* comparison */ |
445 |
|
446 |
int |
447 |
match_position, match_length, /* of longest match. These |
448 |
* are set by the |
449 |
* InsertNode() procedure. */ |
450 |
lson[N + 1], rson[N + 257], dad[N + 1]; /* left & right children |
451 |
* & parents -- These |
452 |
* constitute binary |
453 |
* search trees. */ |
454 |
unsigned long |
455 |
textsize = 0, /* text size counter */ |
456 |
codesize = 0, /* code size counter */ |
457 |
printcount = 0; /* counter for reporting progress every 1K |
458 |
* bytes */ |
459 |
|
460 |
|
461 |
unsigned char CHECKSUM; |
462 |
|
463 |
typedef struct { |
464 |
char MAGIC; |
465 |
unsigned char PARAMS; |
466 |
unsigned char CHECKSUM; |
467 |
unsigned char dummy; |
468 |
unsigned char ENCODED_SIZE[4]; |
469 |
unsigned char DECODED_SIZE[4]; |
470 |
} packet_header; |
471 |
|
472 |
#define PH_SIZE 12 |
473 |
|
474 |
int |
475 |
PutPacketInfo(buf) |
476 |
char *buf; |
477 |
{ |
478 |
packet_header PH; |
479 |
|
480 |
PH.MAGIC = MAGIC_NUMBER; |
481 |
PH.PARAMS = (unsigned char) (((N >> 6) & 0xf0) | |
482 |
((((F / 18) % 3) << 2) & 0x0c) | (THRESHOLD - 1)); |
483 |
PH.CHECKSUM = CHECKSUM; |
484 |
PH.ENCODED_SIZE[0] = (codesize >> 24); |
485 |
PH.ENCODED_SIZE[1] = (codesize >> 16); |
486 |
PH.ENCODED_SIZE[2] = (codesize >> 8); |
487 |
PH.ENCODED_SIZE[3] = codesize; |
488 |
PH.DECODED_SIZE[0] = textsize >> 24; |
489 |
PH.DECODED_SIZE[1] = textsize >> 16; |
490 |
PH.DECODED_SIZE[2] = textsize >> 8; |
491 |
PH.DECODED_SIZE[3] = textsize; |
492 |
memcpy(buf, &PH, sizeof(packet_header)); |
493 |
/* |
494 |
printf("Packet info:\n" "params: %x\n" "checksum: %x\n", PH.PARAMS, PH.CHECKSUM); |
495 |
*/ |
496 |
return 0; |
497 |
} |
498 |
|
499 |
void |
500 |
InitTree(void) |
501 |
{ /* initialize trees */ |
502 |
int i; |
503 |
|
504 |
/* |
505 |
* For i = 0 to N - 1, rson[i] and lson[i] will be the right and left |
506 |
* children of node i. These nodes need not be initialized. Also, dad[i] |
507 |
* is the parent of node i. These are initialized to NIL (= N), which |
508 |
* stands for 'not used.' For i = 0 to 255, rson[N + i + 1] is the root |
509 |
* of the tree for strings that begin with character i. These are |
510 |
* initialized to NIL. Note there are 256 trees. |
511 |
*/ |
512 |
|
513 |
for (i = N + 1; i <= N + 256; i++) |
514 |
rson[i] = NIL; |
515 |
for (i = 0; i < N; i++) |
516 |
dad[i] = NIL; |
517 |
} |
518 |
|
519 |
void |
520 |
InsertNode(int r) |
521 |
/* |
522 |
* Inserts string of length F, text_buf[r..r+F-1], into one of the trees |
523 |
* (text_buf[r]'th tree) and returns the longest-match position and length |
524 |
* via the global variables match_position and match_length. If match_length |
525 |
* = F, then removes the old node in favor of the new one, because the old |
526 |
* one will be deleted sooner. Note r plays double role, as tree node and |
527 |
* position in buffer. |
528 |
*/ |
529 |
{ |
530 |
int i, p, cmp; |
531 |
unsigned char *key; |
532 |
|
533 |
cmp = 1; |
534 |
key = &text_buf[r]; |
535 |
p = N + 1 + key[0]; |
536 |
rson[r] = lson[r] = NIL; |
537 |
match_length = 0; |
538 |
for (;;) { |
539 |
if (cmp >= 0) { |
540 |
if (rson[p] != NIL) |
541 |
p = rson[p]; |
542 |
else { |
543 |
rson[p] = r; |
544 |
dad[r] = p; |
545 |
return; |
546 |
} |
547 |
} else { |
548 |
if (lson[p] != NIL) |
549 |
p = lson[p]; |
550 |
else { |
551 |
lson[p] = r; |
552 |
dad[r] = p; |
553 |
return; |
554 |
} |
555 |
} |
556 |
for (i = 1; i < F; i++) |
557 |
if ((cmp = key[i] - text_buf[p + i]) != 0) |
558 |
break; |
559 |
if (i > match_length) { |
560 |
match_position = p; |
561 |
if ((match_length = i) >= F) |
562 |
break; |
563 |
} |
564 |
} |
565 |
dad[r] = dad[p]; |
566 |
lson[r] = lson[p]; |
567 |
rson[r] = rson[p]; |
568 |
dad[lson[p]] = r; |
569 |
dad[rson[p]] = r; |
570 |
if (rson[dad[p]] == p) |
571 |
rson[dad[p]] = r; |
572 |
else |
573 |
lson[dad[p]] = r; |
574 |
dad[p] = NIL; /* remove p */ |
575 |
} |
576 |
|
577 |
void |
578 |
DeleteNode(int p) |
579 |
{ /* deletes node p from tree */ |
580 |
int q; |
581 |
|
582 |
if (dad[p] == NIL) |
583 |
return; /* not in tree */ |
584 |
if (rson[p] == NIL) |
585 |
q = lson[p]; |
586 |
else if (lson[p] == NIL) |
587 |
q = rson[p]; |
588 |
else { |
589 |
q = lson[p]; |
590 |
if (rson[q] != NIL) { |
591 |
do { |
592 |
q = rson[q]; |
593 |
} while (rson[q] != NIL); |
594 |
rson[dad[q]] = lson[q]; |
595 |
dad[lson[q]] = dad[q]; |
596 |
lson[q] = lson[p]; |
597 |
dad[lson[p]] = q; |
598 |
} |
599 |
rson[q] = rson[p]; |
600 |
dad[rson[p]] = q; |
601 |
} |
602 |
dad[q] = dad[p]; |
603 |
if (rson[dad[p]] == p) |
604 |
rson[dad[p]] = q; |
605 |
else |
606 |
lson[dad[p]] = q; |
607 |
dad[p] = NIL; |
608 |
} |
609 |
|
610 |
int |
611 |
Encode(inbuf, outbuf, buflen, oindex) |
612 |
unsigned char *inbuf; |
613 |
unsigned char *outbuf; |
614 |
int buflen, oindex; |
615 |
{ |
616 |
int i, c, len, r, s, last_match_length, code_buf_ptr; |
617 |
unsigned char code_buf[17], mask; |
618 |
|
619 |
int lindex = 0; |
620 |
|
621 |
CHECKSUM = 0xff; |
622 |
InitTree(); /* initialize trees */ |
623 |
code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, |
624 |
* and code_buf[0] works as eight flags, "1" |
625 |
* representing that the unit is an unencoded |
626 |
* letter (1 byte), "0" a position-and-length |
627 |
* pair (2 bytes). Thus, eight units require |
628 |
* at most 16 bytes of code. */ |
629 |
code_buf_ptr = mask = 1; |
630 |
s = 0; |
631 |
r = N - F; |
632 |
for (i = s; i < r; i++) |
633 |
text_buf[i] = ' '; /* Clear the buffer with any character that |
634 |
* will appear often. */ |
635 |
for (len = 0; len < F && (lindex < buflen); len++) { |
636 |
c = inbuf[lindex++]; |
637 |
CHECKSUM ^= c; |
638 |
text_buf[r + len] = c; /* Read F bytes into the last F bytes of the |
639 |
* buffer */ |
640 |
} |
641 |
if ((textsize = len) == 0) |
642 |
return; /* text of size zero */ |
643 |
for (i = 1; i <= F; i++) |
644 |
InsertNode(r - i); /* Insert the F strings, each of which begins |
645 |
* with one or more 'space' characters. Note |
646 |
* the order in which these strings are |
647 |
* inserted. This way, degenerate trees will |
648 |
* be less likely to occur. */ |
649 |
InsertNode(r); /* Finally, insert the whole string just |
650 |
* read. The global variables match_length |
651 |
* and match_position are set. */ |
652 |
do { |
653 |
if (match_length > len) |
654 |
match_length = len; /* match_length may be spuriously long near |
655 |
* the end of text. */ |
656 |
if (match_length <= THRESHOLD) { |
657 |
match_length = 1; /* Not long enough match. Send one byte. */ |
658 |
code_buf[0] |= mask;/* 'send one byte' flag */ |
659 |
code_buf[code_buf_ptr++] = text_buf[r]; /* Send uncoded. */ |
660 |
} else { |
661 |
code_buf[code_buf_ptr++] = (unsigned char) match_position; |
662 |
code_buf[code_buf_ptr++] = (unsigned char) |
663 |
(((match_position >> 4) & 0xf0) |
664 |
| (match_length - (THRESHOLD + 1))); /* Send position and |
665 |
* length pair. Note |
666 |
* match_length > |
667 |
* THRESHOLD. */ |
668 |
} |
669 |
if ((mask <<= 1) == 0) {/* Shift mask left one bit. */ |
670 |
memcpy(&outbuf[oindex], code_buf, code_buf_ptr); |
671 |
oindex += code_buf_ptr; |
672 |
codesize += code_buf_ptr; |
673 |
code_buf[0] = 0; |
674 |
code_buf_ptr = mask = 1; |
675 |
} |
676 |
last_match_length = match_length; |
677 |
for (i = 0; i < last_match_length && (lindex < buflen); i++) { |
678 |
c = inbuf[lindex++]; |
679 |
CHECKSUM ^= c; |
680 |
DeleteNode(s); /* Delete old strings and */ |
681 |
text_buf[s] = c; /* read new bytes */ |
682 |
if (s < F - 1) |
683 |
text_buf[s + N] = c; /* If the position is near the end of |
684 |
* buffer, extend the buffer to make |
685 |
* string comparison easier. */ |
686 |
s = (s + 1) & (N - 1); |
687 |
r = (r + 1) & (N - 1); |
688 |
/* |
689 |
* Since this is a ring buffer, increment the position modulo N. |
690 |
*/ |
691 |
InsertNode(r); /* Register the string in text_buf[r..r+F-1] */ |
692 |
} |
693 |
if ((textsize += i) > printcount) { |
694 |
if (verbose) printf("%12ld\r", textsize); |
695 |
printcount += 1024; |
696 |
/* |
697 |
* Reports progress each time the textsize exceeds multiples of |
698 |
* 1024. |
699 |
*/ |
700 |
} |
701 |
while (i++ < last_match_length) { /* After the end of text, */ |
702 |
DeleteNode(s); /* no need to read, but */ |
703 |
s = (s + 1) & (N - 1); |
704 |
r = (r + 1) & (N - 1); |
705 |
if (--len) |
706 |
InsertNode(r); /* buffer may not be empty. */ |
707 |
} |
708 |
} while (len > 0); /* until length of string to be processed is |
709 |
* zero */ |
710 |
if (code_buf_ptr > 1) { /* Send remaining code. */ |
711 |
memcpy(&outbuf[oindex], code_buf, code_buf_ptr); |
712 |
oindex += code_buf_ptr; |
713 |
codesize += code_buf_ptr; |
714 |
} |
715 |
outbuf[oindex++] = EOP; |
716 |
if (verbose) { |
717 |
printf("Uncoded stream length: %ld bytes\n", textsize); /* Encoding is done. */ |
718 |
printf("Coded stream length: %ld bytes\n", codesize); |
719 |
printf("Compression Ratio: %.3f\n", (double) textsize / codesize); |
720 |
} |
721 |
} |
722 |
|
723 |
|
724 |
int |
725 |
lzss(inbuf, outbuf, len, comp) |
726 |
char *inbuf; |
727 |
char *outbuf; |
728 |
int len; |
729 |
int comp; |
730 |
{ |
731 |
int index; |
732 |
|
733 |
textsize = 0; /* text size counter */ |
734 |
codesize = 0; /* code size counter */ |
735 |
printcount = 0; /* counter for reporting progress every 1K */ |
736 |
|
737 |
if (comp) { |
738 |
index = sizeof(packet_header); |
739 |
Encode(inbuf, outbuf, len, index); |
740 |
if (PutPacketInfo(outbuf)) { |
741 |
printf("Error:couldn't write packet header\n"); |
742 |
} |
743 |
} |
744 |
return (codesize); |
745 |
} |
746 |
|
747 |
#include "ansidecl.h" |
748 |
|
749 |
#ifdef ANSI_PROTOTYPES |
750 |
#include <stdarg.h> |
751 |
#else |
752 |
#include <varargs.h> |
753 |
#endif |
754 |
|
755 |
#include "bfd.h" |
756 |
|
757 |
#define min(A, B) (((A) < (B)) ? (A) : (B)) |
758 |
#define LOAD_ADDRESS 0 |
759 |
|
760 |
|
761 |
dump(section_address, buffer, count) |
762 |
int section_address; |
763 |
unsigned char *buffer; |
764 |
int count; |
765 |
{ |
766 |
int i; |
767 |
|
768 |
for (i = 0; i < count; i += 4) { |
769 |
fprintf(dumpfile, "\t.word\t0x%02x%02x%02x%02x\n", |
770 |
buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3]); |
771 |
} |
772 |
} |
773 |
|
774 |
int |
775 |
bfd_load(fname, comp) |
776 |
char *fname; |
777 |
int comp; |
778 |
{ |
779 |
int cc, c; |
780 |
unsigned char buf[10]; |
781 |
asection *section; |
782 |
bfd *pbfd; |
783 |
unsigned long entry; |
784 |
char *sec_buf; |
785 |
char *lzss_buf; |
786 |
|
787 |
pbfd = bfd_openr(fname, 0); |
788 |
|
789 |
if (pbfd == NULL) { |
790 |
printf("open of %s failed\n", fname); |
791 |
return (0); |
792 |
} |
793 |
if (!bfd_check_format(pbfd, bfd_object)) { |
794 |
printf("file %s doesn't seem to be an object file\n", fname); |
795 |
return (0); |
796 |
} |
797 |
if (verbose) printf("loading %s:", fname); |
798 |
fprintf(dumpfile, "\t .text\n"); |
799 |
for (section = pbfd->sections; section; section = section->next) { |
800 |
if (bfd_get_section_flags(pbfd, section) & SEC_ALLOC) { |
801 |
bfd_vma section_address; |
802 |
unsigned long section_size; |
803 |
const char *section_name; |
804 |
|
805 |
section_name = bfd_get_section_name(pbfd, section); |
806 |
|
807 |
section_address = bfd_get_section_vma(pbfd, section); |
808 |
/* |
809 |
* Adjust sections from a.out files, since they don't carry their |
810 |
* addresses with. |
811 |
*/ |
812 |
if (bfd_get_flavour(pbfd) == bfd_target_aout_flavour) |
813 |
section_address += bfd_get_start_address(pbfd); |
814 |
section_size = bfd_section_size(pbfd, section); |
815 |
|
816 |
if (verbose) printf("\nsection %s at 0x%08lx (%ld bytes)", |
817 |
section_name, section_address, section_size); |
818 |
|
819 |
/* Text, data or lit */ |
820 |
if (bfd_get_section_flags(pbfd, section) & SEC_LOAD) { |
821 |
file_ptr fptr; |
822 |
|
823 |
/* Register section in table */ |
824 |
secarr[secnum].paddr = section_address; |
825 |
secarr[secnum].len = section_size; |
826 |
secarr[secnum].comp = comp; |
827 |
strcpy(secarr[secnum].name, section_name); |
828 |
|
829 |
/* Add section entry in dump file */ |
830 |
fprintf(dumpfile, "\n\t.global _section%1d\n", secnum); |
831 |
fprintf(dumpfile, "_section%1d:\n", secnum); |
832 |
|
833 |
fptr = 0; |
834 |
|
835 |
/* Get buffers if compressing */ |
836 |
if (comp) { |
837 |
sec_buf = (char *) malloc(section_size); |
838 |
lzss_buf = (char *) malloc(section_size + 200); |
839 |
} |
840 |
while (section_size > 0) { |
841 |
char buffer[1024]; |
842 |
int count; |
843 |
|
844 |
count = min(section_size, 1024); |
845 |
|
846 |
bfd_get_section_contents(pbfd, section, buffer, fptr, count); |
847 |
|
848 |
if (comp) |
849 |
memcpy(&sec_buf[fptr], buffer, count); |
850 |
else |
851 |
dump(section_address, buffer, count); |
852 |
|
853 |
section_address += count; |
854 |
fptr += count; |
855 |
section_size -= count; |
856 |
} |
857 |
secnum++; |
858 |
if (comp) { |
859 |
if (verbose) printf("\n"); |
860 |
fptr = lzss(sec_buf, lzss_buf, fptr, 1); |
861 |
dump(section_address, lzss_buf, fptr+13); |
862 |
free(sec_buf); |
863 |
free(lzss_buf); |
864 |
} |
865 |
} else /* BSS */ |
866 |
if (verbose) printf("(not loaded)"); |
867 |
} |
868 |
} |
869 |
if (verbose) printf("\n"); |
870 |
|
871 |
/* |
872 |
* entry = bfd_get_start_address (pbfd); |
873 |
* |
874 |
* printf ("[Starting %s at 0x%lx]\n", fname, entry); |
875 |
*/ |
876 |
return (0); |
877 |
} |