/*-------------------------------------------------------------------------+
| bin2boot.c v1.1 - PC386 BSP - 1997/08/18
+--------------------------------------------------------------------------+
| This file contains the i386 binary to boot image filter.
+--------------------------------------------------------------------------+
| (C) Copyright 1997 -
| - NavIST Group - Real-Time Distributed Systems and Industrial Automation
|
| http://pandora.ist.utl.pt
|
| Instituto Superior Tecnico * Lisboa * PORTUGAL
+--------------------------------------------------------------------------+
| Disclaimer:
|
| This file is provided "AS IS" without warranty of any kind, either
| expressed or implied.
|
| $Id$
+--------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "bytetype.h"
#include "bootimg.h"
/*-------------------------------------------------------------------------+
| Constants
+--------------------------------------------------------------------------*/
#define SEG_MASK 0xffff0000
/* Mask for segment part of seg:off address. */
#define OFF_MASK 0x0000ffff
/* Mask for offset part of seg:off address. */
#define DEFAULT_START_ADDR 0x10200 /* Default start address for binary. */
#define BOOTIMG_HDR_SIZE 0x0200 /* Size of output file header. */
#define BUFFER_BLOCK_SIZE 0x1000 /* Size of transfer buffer size. */
#define LAST_BLOCK_SIZE 0x0200
/* The output file must have a size multiple of this value. */
/*-------------------------------------------------------------------------+
| Macros
+--------------------------------------------------------------------------*/
#define getSeg(x) (Word)((x) >> 16)
/* Return seg part (Word) of a seg:off address (DWord). */
#define getOff(x) (Word)((x) & OFF_MASK)
/* Return off part (Word) of a seg:off address (DWord). */
#define getSegOff(x) ((((x) & SEG_MASK) << 12) + ((x) & OFF_MASK))
/* Converts a flat address to a seg:off address. */
/*-------------------------------------------------------------------------+
| Global Variables
+--------------------------------------------------------------------------*/
const char UsageMsg[] = "\
Usage: bin2boot [<infile> [<outfile>]] [-s <start_address>] [-v]\n\
\n\
<infile> : input file name\n\
<outfile> : output file name\n\
-s <outfile> : start address of binary image\n\
-m <size> : actual size (for compressed images)\n\
-v : verbose output\n"; /* Usage message. */
/*-------------------------------------------------------------------------+
| External Prototypes (for use with getopt)
+--------------------------------------------------------------------------*/
extern char *optarg;
int getopt(int, char *const[], const char *);
/*-------------------------------------------------------------------------+
| Auxiliary Functions
+--------------------------------------------------------------------------*/
static DWord
getNumArg(char *arg)
{
char *dummy;
if (arg[0] == '0')
if ((arg[1] == 'x') || (arg[1] == 'X')) /* Hexadecimal */
return (DWord)strtol(arg, &dummy, 16);
else /* Octal */
return (DWord)strtol(arg, &dummy, 8);
else /* Decimal */
return (DWord)strtol(arg, &dummy, 10);
} /* getNumArg */
/*-------------------------------------------------------------------------+
| Main
+--------------------------------------------------------------------------*/
void main(int argc, char *argv[])
{
FileHeader bootimgFileHdr; /* Output file header. */
LoadingInfo imageInfo; /* Section header. */
Byte auxBuf[BUFFER_BLOCK_SIZE]; /* */
DWord nRead; /* Number of bytes read. */
Word padSize; /* Size of padding at end of file. */
char *progName = argv[0]; /* Program name for errors. */
FILE *fpIn = stdin;
FILE *fpOut = stdout;
DWord binStart = DEFAULT_START_ADDR; /* Start address of image. */
DWord memLen = 0; /* Real length for compressed images. */
char currArg;
int argCount;
int flag; /* general purpose flag */
int verbose = 0; /* flag for verbose output */
while ((currArg = getopt(argc, argv, "hm:s:v")) >= 0) /* parse command line */
switch (currArg)
{
case 'h' :
fprintf(stderr, UsageMsg);
exit(0);
break;
case 'm' :
memLen = getNumArg(optarg);
break;
case 's' :
binStart = getNumArg(optarg);
break;
case 'v' :
verbose = 1;
break;
default :
fprintf(stderr, UsageMsg);
exit(1);
break;
} /* switch */
flag = 0;
for (argCount = 1; argCount < argc; argCount++)
if (argv[argCount][0] == '-')
{
if (argv[argCount][1] == 's')
argCount++;
}
else if (flag) /* we already have the input file => output file */
{
if ((fpOut = fopen(argv[argCount], "w")) == NULL)
{
fprintf(stderr, "%s: can't open %s\n", progName, argv[argCount]);
exit(1);
}
}
else /* input file */
{
if ((fpIn = fopen(argv[argCount], "r")) == NULL)
{
fprintf(stderr, "%s: can't open %s\n", progName, argv[argCount]);
exit(1);
}
flag = 1;
}
/*** begin: Conversion to Bootimg */
/*** File Header */
if (verbose)
fprintf(stderr, "\nBoot Image File Header:\n\n");
bootimgFileHdr.magicNum = BOOT_IMAGE_MAGIC; /* 4 bytes - magic number */
bootimgFileHdr.flagsLen = NON_VENDOR_LEN; /* 4 bytes - flags and length */
bootimgFileHdr.locAddr = getSegOff(binStart - BOOTIMG_HDR_SIZE);
/* 4 bytes - location address in ds:bx format */
bootimgFileHdr.execAddr = getSegOff(binStart);
/* 4 bytes - execute address in cs:ip format */
if (verbose)
{
fprintf(stderr, ">> location address in ds:bx format: %04x:%04x\n",
getSeg(bootimgFileHdr.locAddr), getOff(bootimgFileHdr.locAddr));
fprintf(stderr, ">> execute address in cs:ip format: %04x:%04x\n",
getSeg(bootimgFileHdr.execAddr), getOff(bootimgFileHdr.execAddr));
}
/*** Write File Header to output file */
fwrite((void *)(& bootimgFileHdr), sizeof(FileHeader), 1, fpOut);
/*** Sections */
if (verbose)
fprintf(stderr, "\nCode Section:\n\n");
imageInfo.flagsTagsLens = 0x04000004;
/* flags, vendor's tags, vendor and non-vendor lengths */
imageInfo.loadAddr = binStart; /* load address */
rewind(fpIn);
fseek(fpIn, 0, SEEK_END);
nRead = ftell(fpIn);
rewind(fpIn);
padSize = LAST_BLOCK_SIZE - (nRead % LAST_BLOCK_SIZE);
imageInfo.imageLength = nRead + padSize; /* image length */
imageInfo.memoryLength = (memLen != 0) ? memLen : imageInfo.imageLength;
/* memory length */
fwrite((void *)(&imageInfo), sizeof(LoadingInfo), 1, fpOut);
if (verbose)
{
fprintf(stderr, ">> load address: 0x%08lx\n", imageInfo.loadAddr);
fprintf(stderr, ">> image length: 0x%08lx\n", imageInfo.imageLength);
fprintf(stderr, ">> memory length: 0x%08lx\n\n", imageInfo.memoryLength);
}
nRead = BOOTIMG_HDR_SIZE - sizeof(FileHeader) - sizeof(LoadingInfo);
memset((void *)auxBuf, 0x00, nRead);
fwrite((void *)auxBuf, 1, nRead, fpOut);
nRead = fread((void *)auxBuf, 1, BUFFER_BLOCK_SIZE, fpIn);
while (!feof(fpIn))
{
fwrite((void *)auxBuf, BUFFER_BLOCK_SIZE, 1, fpOut);
nRead = fread((void *)auxBuf, 1, BUFFER_BLOCK_SIZE, fpIn);
}
fwrite((void *)auxBuf, 1, nRead, fpOut);
memset((void *)auxBuf, 0x00, padSize);
fwrite((void *)auxBuf, 1, padSize, fpOut);
fclose(fpOut);
fclose(fpIn);
/*** end: Conversion to Bootimg */
exit(0);
} /* main */