//*****************************************************************************
//
// Purpose: Make a boot-image for EtherBoot
//
//
// Compiler: This source can be compiled with gcc and Watcom C
//
//
// Note: The QNX boot image can be build with any reasonable
// start address, e.g. 0x1000 (default) or 0x10000
// (widespread Boot-Rom address)
//
//
// Author: Anders Larsen
//
//
// Copyright: (C) 1999 by
//
// Anders Larsen
// systems engineer
// Gutleuthausstr. 3
// D-69469 Weinheim
// Germany
// phone: +49-6201-961717
// fax: +49-6201-961718
// e-mail: al@alarsen.net
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
//-----------------------------------------------------------------------------
//
// Change Log:
// V0.2: Sun 1999-12-13 Anders Larsen <al@alarsen.net>
//*****************************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
// max. size of QNX OS boot image is 512K
#define MAXSIZE (512*1024)
typedef unsigned short ushort_t;
typedef unsigned long ulong_t;
// global header of tagged image:
struct initial_t
{
ulong_t magic;
ulong_t length;
ulong_t location;
ulong_t start;
};
// header of each image:
struct header_t
{
ulong_t flags;
ulong_t loadaddr;
ulong_t imgsize;
ulong_t memsize;
};
// global header of the QNX EtherBoot image:
struct qnx_loader_t
{
struct initial_t setup;
struct header_t qnx;
};
// global header:
union
{
struct qnx_loader_t h;
char filler[512];
} header;
char buffer[MAXSIZE];
int usage( char* const* argv )
{
fprintf( stderr, "%s - make a tagged boot image for EtherBoot\n", *argv );
fprintf( stderr, "\nuse:\n" );
fprintf( stderr, "%s [ -<option> ]*\n", *argv );
fprintf( stderr, "\noptions:\n" );
fprintf( stderr, " i <input file> : QNX boot file (default: stdin)\n" );
fprintf( stderr, " o <output file> : tagged image file (default: stdout)\n" );
fprintf( stderr, " v : be verbose\n" );
return EXIT_FAILURE;
}
#ifdef __USAGE
%C - make a tagged boot image for EtherBoot
use:
%C [ -<option> ]*
options:
i <input file> : QNX boot file (default: stdin)
o <output file> : tagged image file (default: stdout)
v : be verbose
#endif
int main( int argc, char* const* argv )
{
int ch, l;
int verbose = 0;
while ( ( ch = getopt( argc, argv, "hi:o:v" ) ) != EOF )
switch ( ch )
{
case 'i':
if ( !freopen( optarg, "r", stdin ) )
{
perror( "can't open input file" );
return EXIT_FAILURE;
}
break;
case 'o':
if ( !freopen( optarg, "w", stdout ) )
{
perror( "can't create output file" );
return EXIT_FAILURE;
}
break;
case 'v':
verbose++;
break;
case 'h':
default:
return usage( argv );
}
if ( optind != argc )
return usage( argv );
memset( &header, 0, sizeof header );
header.h.setup.magic = 0x1b031336; // magic number
header.h.setup.length = 4;
header.h.setup.location = 0x93e00000; // just below the EtherBoot rom
header.h.setup.start = 0; // filled in dynamically
header.h.qnx.flags = 0x04000004; // single image only
header.h.qnx.loadaddr = 0; // filled in dynamically
header.h.qnx.imgsize = 0; // filled in dynamically
header.h.qnx.memsize = 0; // filled in dynamically
// read the QNX image from stdin:
for ( ; ( l = fread( buffer + header.h.qnx.imgsize, 1, 1024, stdin ) ) > 0;
header.h.qnx.imgsize += l
)
;
header.h.qnx.memsize = header.h.qnx.imgsize;
// fill in the real load-address of the QNX boot image:
header.h.setup.start = *(ushort_t*)&buffer[10] << 16;
header.h.qnx.loadaddr = *(ushort_t*)&buffer[10] << 4;
// write the tagged image file to stdout:
fwrite( &header, 1, 512, stdout );
fwrite( buffer, 1, header.h.qnx.imgsize, stdout );
if ( verbose )
{
// print diagnostic information:
fprintf( stderr, "QNX image size: %d bytes (%dK), load addr: 0x%05X\n",
header.h.qnx.imgsize,
header.h.qnx.imgsize / 1024,
header.h.qnx.loadaddr
);
}
return EXIT_SUCCESS;
}