1
0
Files
2022-09-29 17:59:04 +03:00

577 lines
13 KiB
C

/* $Header: /proj/irix6.5.7m/isms/stand/arcs/tools/convert/RCS/convert.c,v 1.9 1996/08/13 18:36:59 poist Exp $ */
/* $Log: convert.c,v $
* Revision 1.9 1996/08/13 18:36:59 poist
* addition of IP30 formats, version number support on command line.
*
* Revision 1.8 1995/11/23 21:13:39 pap
* added support to read in pure binary files (-p option)
*
* Revision 1.7 1995/09/16 00:47:12 csm
* Add pure to list of supported formats
*
* Revision 1.6 1994/11/09 22:03:01 sfc
* Merge sherwood/redwood up and including redwood version 1.8
* > ----------------------------
* > revision 1.8
* > date: 93/10/12 00:33:44; author: jeffs; state: ; lines: +11 -7
* > Minor clean-ups for -fullwarn.
* > ----------------------------
* > revision 1.7
* > date: 93/07/21 22:22:17; author: igehy; state: ; lines: +3 -3
* > Lines on open were written incorrectly.
* > ----------------------------
* > revision 1.6
* > date: 93/07/15 19:45:52; author: igehy; state: ; lines: +60 -106
* > Added ELF capabilities.
* > ----------------------------
* > revision 1.5
* > date: 93/07/09 23:35:45; author: travis; state: ; lines: +28 -6
* > Added -Z option (similiar to EVEREST -z but different ;-) which was how
* > it was before. Remember to change those command files!
* > ----------------------------
*
* Revision 1.8 1993/10/12 00:33:44 jeffs
* Minor clean-ups for -fullwarn.
*
* Revision 1.7 1993/07/21 22:22:17 igehy
* Lines on open were written incorrectly.
*
* Revision 1.5 1993/07/09 23:35:45 travis
* Added -Z option (similiar to EVEREST -z but different ;-) which was how
* it was before. Remember to change those command files!
*
* Revision 1.4 1992/09/30 17:55:36 jfk
* Added support for the binary record format.
*
* Revision 1.1 87/09/21 11:13:48 huy
* Initial revision
* */
/*******************************************************************************
*
* convert - Convert object files to downloadable format.
*
* convert -z -Z -p -f <format> -b <byte number> file ...
*
* where <format> is either "intelhex", "step" or "srec"
* -z swizzles all words in the file before formatting)
* -Z swizzles bytes within shorts in the file before formatting)
* -p read file in as pure binary, don't try to read the format
*
* This program converts BSD4.2 a.out or mips object files to downloadable
* format suitable for the prom programmers. The program is designed to
* be easily expanadble for other output formats.
*
******************************************************************************/
#define LANGUAGE_C 1
#define mips 1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <stdlib.h>
#include <unistd.h>
#include "a.out.h"
#include "convert.h"
#include "stubs.h"
#include "elf.h"
#include "mips.h"
#include "intel_hex.h"
#include "s_rec.h"
#include "sex.h"
#include "binary.h"
#include "pure.h"
#include "racer.h"
extern int errno;
extern int sys_nerr;
extern char *sys_errlist[];
char bad_flag[] = "%s: %c is not a valid flag.\n";
char *progname;
/*
* Foward declarations
*/
static int Convert(int, int);
static int GetObjectType(enum object_file_type *, int);
static int Match(char *, char *, int);
static int MatchArg(char *, char *[], int);
/*
* Object file type control structures
*/
struct object_file_type_table_descriptor object_file_type_table[] = {
MIPSEBMAGIC, MIPS, /* headers: BE - target: BE */
MIPSELMAGIC, MIPS, /* headers: LE - target: LE */
MIPSEBMAGIC_2, MIPS, /* MIPS2 BE -> BE */
MIPSELMAGIC_2, MIPS, /* MIPS2 LE -> LE */
MIPSEBMAGIC_3, MIPS, /* MIPS3 BE -> BE */
MIPSELMAGIC_3, MIPS, /* MIPS3 LE -> LE */
SMIPSEBMAGIC, MIPS, /* headers: LE - target: BE */
SMIPSELMAGIC, MIPS, /* headers: BE - target: LE */
OMAGIC, BERKELEY,
NMAGIC, BERKELEY,
ZMAGIC, BERKELEY,
0x0550, COFF,
0x0551, COFF,
0x0570, COFF,
0x0575, COFF,
0x7f45, ELF
};
#define N_MAGICS (sizeof( object_file_type_table) / \
sizeof(struct object_file_type_table_descriptor) )
struct object_file_descriptor object_files[] = {
BERKELEY, StubObjInitialize, StubObjRead, StubObjClose,
COFF, StubObjInitialize, StubObjRead, StubObjClose,
ELF, ElfInitialize, ElfRead, ElfClose,
PURE, PureInitialize, PureRead, PureClose,
MIPS, MipsInitialize, MipsRead, MipsClose
};
#define N_OBJECT_TYPES (sizeof(object_files)/sizeof(struct object_file_descriptor))
struct object_file_descriptor *object;
/*
* Output format control structures
*/
char *format_names[] = {
"intelhex", "step", "srec", "s1rec","s2rec", "s3rec", "stub",
"binary", "pure", "rprom", "fprom", 0
};
#define N_FORMATS ((sizeof( format_names ) / sizeof( char *)) )
struct format_descriptor formats[ N_FORMATS ] = {
16,
IntelhexInitialize,
IntelhexConvert,
IntelhexWrite,
IntelhexTerminate,
StubFmtSetVersion,
4,
IntelhexInitialize,
StepConvert,
IntelhexWrite,
IntelhexTerminate,
StubFmtSetVersion,
16,
S2RecordInitialize,
SRecordConvert,
SRecordWrite,
SRecordTerminate,
StubFmtSetVersion,
16,
S1RecordInitialize,
SRecordConvert,
SRecordWrite,
SRecordTerminate,
StubFmtSetVersion,
16,
S2RecordInitialize,
SRecordConvert,
SRecordWrite,
SRecordTerminate,
StubFmtSetVersion,
32,
S3RecordInitialize,
SRecordConvert,
SRecordWrite,
SRecordTerminate,
StubFmtSetVersion,
16,
StubFmtInitialize,
StubFmtConvert,
StubFmtWrite,
StubFmtTerminate,
StubFmtSetVersion,
4096,
BinInitialize,
BinConvert,
BinWrite,
BinTerminate,
StubFmtSetVersion,
4096,
PureInitialize,
PureConvert,
PureWrite,
PureTerminate,
StubFmtSetVersion,
4096,
RacerRpromInitialize,
RacerConvert,
RacerRpromWrite,
RacerRpromTerminate,
RacerSetVersion,
4096,
RacerFpromInitialize,
RacerConvert,
RacerFpromWrite,
RacerFpromTerminate,
RacerSetVersion,
};
struct format_descriptor *format = formats;
int byte_number = -1;
int short_number= -1; /* added to allow split short HN 7/87 */
/*
* Object file section globals
*/
unsigned long load_address; /* Code loaded here */
unsigned long start_address; /* Control passed here on execution */
long version = 0; /* provided version number */
/*
* Sex variables
*/
int my_sex; /* Host byte sex */
int swap; /* True if headers and object of opposite sex */
int swizzle = 0; /* Set to swizzle bytes with words */
int Swizzle = 0; /* Set to swizzle bytes with shorts */
int buffer[ 1024 ];
main(int argc, char **argv)
{
register int i = 1;
register int j;
char *cp;
int status;
int fd; /* file descriptor */
int pure = 0;
/* Initialize */
my_sex = gethostsex();
progname = argv[ 0 ];
/* Parse the flags - Note that all flags must precede all filenames */
while ( i < argc ) {
/* No flags - start processing filenames */
if ( argv[i][0] != '-' ) {
break;
}
/* process each flag */
switch ( argv[i][1] ) {
case 's':
/* Allow the short number to be separated from the
* flag by zero or more blanks
* 0 means Most significant 16 bits
* 2 means Least significant 16 bits
*/
cp = (argv[i][2] ? &argv[i][2]
: argv[ (++i < argc ? i :--i) ]);
short_number = atoi( cp );
break;
case 'p':
/* read the input as pure binary, forget about file format */
pure = 1;
break;
case 'b':
/* Allow the byte number to be separated from the
* flag by zero or more blanks
*/
cp = (argv[i][2] ? &argv[i][2]
: argv[ (++i < argc ? i :--i) ]);
byte_number = atoi( cp );
break;
case 'f':
/* Allow the format specifier to separated from the
* flag by zero or more blanks
*/
cp = (argv[i][2] ? &argv[i][2]
: argv[ (++i < argc ? i :--i) ]);
/* Check for legal format specifier */
if ((j = MatchArg(cp, format_names, IGNORECASE)) >= 0) {
format = &formats[ j ];
break;
}
else {
fprintf( stderr,
"%s: Invalid format specification.\n",
progname );
fprintf( stderr, "%s: Try ", progname );
for ( j = N_FORMATS - 2; j >= 0; j-- ) {
switch ( j ) {
case 0:
cp = "%s(default).\n";
break;
case 1:
cp = "%s or ";
break;
default:
cp = "%s, ";
}
fprintf(stderr, cp, format_names[ j ]);
}
exit( 1 );
}
break;
case 'z':
/* Swizzle data (and instructions) before formatting.
* The IP19 prom likes all bytes in little endian
* order. Don't do any doubleword loads, though.
*/
swizzle = 1;
break;
case 'Z':
/* Swizzle data (and instructions) before formatting.
* The IP19 prom likes all bytes in little endian
* order. Don't do any doubleword loads, though.
*/
Swizzle = 1;
break;
case 'v':
/* Set the version number of the output file.
* the command line argument is X.Y, where
* X takes the high 24 bits, and Y takes the
* low 8 bits
*/
{
char * ptr;
cp = (argv[i][2] ? &argv[i][2]
: argv[ (++i < argc ? i :--i) ]);
version = strtol( cp, &ptr, 10 );
version <<= 8;
if ((*ptr != NULL) && (*++ptr != NULL)) {
long t;
t = strtol( ptr, NULL, 10 );
version |= t & 0xff;
}
}
break;
default:
fprintf( stderr, bad_flag, progname, argv[ i ][ 1 ] );
exit(1);
}
/* Pick up next command line arg */
i++;
}
/* Process each filename */
if ( i >= argc ) {
/* no file arguments - process contents of stdin */
status = Convert(0, pure);
}
else {
for ( ; i < argc; i++ ) {
/* Open the next file */
if ((fd = open( argv[i], O_RDONLY)) == -1) {
fprintf(stderr, "Could not open %s.\n", argv[i]);
break;
}
/* Do it */
status = Convert(fd, pure);
close(fd);
}
}
/* Clean code here */
exit( status );
} /* end of main */
static int
Convert(int fd, int pure)
{
register int error;
enum object_file_type type;
int input_blocking_factor;
int output_blocking_factor;
int length;
int convlen;
int i;
unsigned int temp;
/* Obtain the type file type */
if (pure)
type = PURE;
else if (error = GetObjectType(&type, fd))
return error;
object = &object_files[ (int)type ];
/* Obtain blocking factor from output format */
output_blocking_factor = format->blocking_factor;
input_blocking_factor = byte_number < 0 ? output_blocking_factor
: 4 * output_blocking_factor;
input_blocking_factor = short_number < 0 ? input_blocking_factor
: 2 * output_blocking_factor;
(*format->setVersion)(version);
/* Initialize the output conversion routines */
if (error = (*format->initialize)(output_blocking_factor))
return error;
/* Obtain the lengths and addresses of the text and data sections */
if (error = (*object->initialize)(fd))
return error;
/* Main processing loop */
while ((length=(*object->read)((char *)buffer, input_blocking_factor,
fd)) > 0) {
if (swizzle) {
for (i = 0; i < input_blocking_factor; i+=4) {
/* Swizzle for EVEREST */
temp = ((char *)buffer)[i + 0];
temp |= ((char *)buffer)[i + 1] << 8;
temp |= ((char *)buffer)[i + 2] << 16;
temp |= ((char *)buffer)[i + 3] << 24;
buffer[i/4] = temp;
}
}
if (Swizzle) {
for (i = 0; i < input_blocking_factor; i+=4) {
/* Swizzle for IP22/IP24 */
temp = ((char *)buffer)[i + 0] << 16;
temp |= ((char *)buffer)[i + 1] << 24;
temp |= ((char *)buffer)[i + 2] << 0;
temp |= ((char *)buffer)[i + 3] << 8;
buffer[i/4] = temp;
}
}
/* Convert the the last record read to the output format */
convlen = (byte_number < 0) ? length : length/4;
convlen = (short_number < 0) ? convlen: length/2;
if ((error = (*format->convert)((char *)buffer, convlen)))
return error;
/* Write the record out to the out file */
if (error = (*format->write)())
return error;
}
if (error = (*format->terminate)())
return error;
return ((length < 0) ? length : (*object->close)(fd));
} /* end of Convert */
static int
GetObjectType(enum object_file_type *type, int fd)
{
register int i;
union {
short number;
char c;
} magic;
int error;
/* Get the magic number from the object file */
if ( (error = read(fd, (char *)&magic, sizeof(magic))) == 0) {
fprintf(stderr,"Could not read file.\n");
return(1);
}
if ( (error = lseek(fd, 0, SEEK_SET)) != 0) {
fprintf(stderr,"Could not seek file.\n");
return(1);
}
/* find the type of the the object file */
for ( i = 0; i < N_MAGICS; i++ ) {
if ( object_file_type_table[ i ].magic == magic.number) {
*type = object_file_type_table[ i ].type;
return OK;
}
}
fprintf(stderr,
"%s: Unrecognized magic number: 0x%x\n",
progname,
magic.number);
return NOT_OK;
} /* GetObjectType */
static int
MatchArg(register char *arg, register char *table[], int flags)
{
register int i;
/* Loop thru each entry in the table */
for ( i = 0; table[ i ]; i++) {
if ( Match( arg, table[ i ], flags ) ) return i;
}
/* Here on mismatch */
return -1;
} /* end MatchArg */
static int
Match(register char *a, register char *b, int flags)
{
register char c, d;
/* Loop until end of shorter string */
for ( ; *a && *b; a++, b++ ) {
/* Use temps to avoid trashing passed parms */
c = *a;
d = *b;
/* Perform case insensitivity if needed */
if ( flags & IGNORECASE ) {
if ( isupper( c ) )
c = tolower( c );
if ( isupper( d ) )
d = tolower( d );
}
/* Compare strings */
if ( c != d ) return FALSE;
}
/* Here on match - check for extact match */
return (flags & EXACTMATCH? *a == *b : TRUE);
} /* end Match */