352 lines
8.5 KiB
C
352 lines
8.5 KiB
C
/*++
|
||
|
||
Copyright (c) 1992, 1993 Digital Equipment Corporation
|
||
|
||
Module Name:
|
||
|
||
fwpack.c
|
||
|
||
Abstract:
|
||
|
||
This module is the program that takes binary firmware image
|
||
(created by fwimagen.exe) and creates a packed firmware
|
||
update file for the JNUPDATE.EXE program.
|
||
|
||
The format of the update file is:
|
||
|
||
+------------------------------------------------+
|
||
| A zero-terminated string that identifies this |
|
||
| file. Must be < = 400 characters in length |
|
||
| and should print out in < = 10 screen rows. |
|
||
| Jnupdate gives this string to a printf. |
|
||
+------------------------------------------------+
|
||
| A single byte indicating which block to start |
|
||
| updating. (0 -- F) |
|
||
+------------------------------------------------+
|
||
| Binary data for the FlashFile ROM, starting |
|
||
| at the starting block, padded with 0's to an |
|
||
| even multiple of 64KB, with a production |
|
||
| ROL-and-ADD checksum in the last byte. |
|
||
| (The checksum will be ignored by a J0/AX02 |
|
||
| SROM.) |
|
||
+------------------------------------------------+
|
||
| A longword additive-zero checksum |
|
||
+------------------------------------------------+
|
||
|
||
Notes:
|
||
|
||
1. The ASCIZ identifying string will be printed out on the users's
|
||
screen to identify the update. It is given to a printf. This should
|
||
contain the name of the update, manufacturing date, copyright notice, etc.
|
||
|
||
2. This program has the capability to package the binary data for the
|
||
Carey McMaster J0/AX02 SROM, which requires a special header at the beginning
|
||
of the firmware image.
|
||
|
||
3. There are three checksums:
|
||
a) A rotate-and-add byte checksum is written out as the last byte in
|
||
the binary data section. The Ayr SROM and POST requires this.
|
||
b) If we are making a J0/AX02 file, a checksum is included in the
|
||
firmware image header.
|
||
c) The entire file is covered by an additive-zero checksum.
|
||
|
||
|
||
Arguments:
|
||
|
||
argv[1] The ASCIZ identification string.
|
||
|
||
argv[2] The starting block number, in the range 0 -- F.
|
||
|
||
argv[3] The filespec of the firmware binary image. This
|
||
is the output of the fwimagen.exe program.
|
||
|
||
argv[4] The filespec of the output file. Convention:
|
||
|
||
jensfw.bin is a production update file.
|
||
|
||
jensfwj0.bin is a McMaster update file.
|
||
|
||
argv[5] If present, we product a binary file that is
|
||
compatible with the Carey McMaster J0 SROM.
|
||
(The value of this argument is not checked).
|
||
|
||
Outputs:
|
||
|
||
The output file receives the packed firmware upgrade data.
|
||
|
||
|
||
Author:
|
||
|
||
John DeRosa 21-October-1992
|
||
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include <stdio.h>
|
||
|
||
|
||
// Typedefs, and define truth
|
||
typedef unsigned char UCHAR;
|
||
typedef char CHAR;
|
||
typedef long LONG;
|
||
typedef unsigned long ULONG;
|
||
typedef int BOOLEAN;
|
||
typedef void VOID;
|
||
typedef int INT;
|
||
typedef char* PCHAR;
|
||
|
||
#define FALSE 0
|
||
#define TRUE 1
|
||
|
||
|
||
// This is more convenient as a static variable.
|
||
FILE *FirmwareOutFile;
|
||
|
||
UCHAR
|
||
RotateLeft (
|
||
UCHAR Data
|
||
)
|
||
/*++
|
||
|
||
This returns the Data parameter barrel rotated left by 1.
|
||
|
||
--*/
|
||
{
|
||
return (((Data & 0x7f) << 1) + ((Data & 0x80) >> 7));
|
||
}
|
||
|
||
VOID
|
||
WriteAByte (
|
||
UCHAR OutData
|
||
)
|
||
/*++
|
||
|
||
Writes a byte to the output file, and exits if error.
|
||
|
||
--*/
|
||
{
|
||
if (((fwrite(&OutData, 1, 1, FirmwareOutFile)) != 1) ||
|
||
ferror(FirmwareOutFile)) {
|
||
fprintf(stderr, "?ERROR on output file.\n");
|
||
exit(0);
|
||
}
|
||
}
|
||
|
||
INT
|
||
main (
|
||
INT argc,
|
||
PCHAR argv[]
|
||
)
|
||
{
|
||
FILE *FirmwareInFile;
|
||
PCHAR Terminator;
|
||
UCHAR InputData;
|
||
UCHAR TempChar;
|
||
ULONG TempULong;
|
||
UCHAR ROMChecksum;
|
||
ULONG Checksum = 0;
|
||
LONG FileChecksum;
|
||
LONG Index;
|
||
BOOLEAN J0SROM = FALSE;
|
||
|
||
|
||
printf("fsb experimental pack v1.1x\n");
|
||
|
||
// Check for bad command line
|
||
if ((argc != 5) && (argc != 6)) {
|
||
printf("Usage: %s string decimal-starting-block infile outfile [J0SROM-flag]\n", argv[0] );
|
||
printf(" Use jensfw.bin for production output file.\n");
|
||
printf(" Use jensfwj0.bin for McMaster output file.\n");
|
||
exit(0);
|
||
}
|
||
|
||
|
||
// What kind of binary file are we to product?
|
||
if (argc == 6) {
|
||
J0SROM = TRUE; // make a McM J0SROM file...
|
||
}
|
||
|
||
|
||
// Open the firmware input binary file
|
||
printf("Opening %s for reading.\n", argv[3]);
|
||
if ((FirmwareInFile = fopen(argv[3], "rb")) == NULL ) {
|
||
fprintf(stderr, "Error opening %s\n", argv[3]);
|
||
exit(0);
|
||
}
|
||
|
||
|
||
// Open the output file
|
||
printf("Opening %s for writing.\n", argv[4]);
|
||
if ((FirmwareOutFile = fopen(argv[4], "wb")) == NULL ) {
|
||
fprintf(stderr, "Error opening %s\n", argv[4]);
|
||
exit(0);
|
||
}
|
||
|
||
|
||
printf("Writing the identification string.\n");
|
||
Index = 0;
|
||
do {
|
||
TempChar = *(argv[1]+Index);
|
||
Checksum += TempChar;
|
||
WriteAByte(TempChar);
|
||
Index++;
|
||
} while(*(argv[1]+Index-1) != 0); // Output string will be 0-terminated
|
||
|
||
|
||
printf("Writing the starting block number of %s.\n", argv[2]);
|
||
TempULong = strtoul(argv[2], &Terminator, 10);
|
||
TempChar = TempULong;
|
||
Checksum += TempChar;
|
||
WriteAByte(TempChar);
|
||
|
||
printf("Writing the firmware data...\n");
|
||
|
||
Index = 0;
|
||
|
||
//
|
||
// If this is a J0SROM -type file, we have to write the 16-byte header
|
||
// first. As this contains a checksum, we will read the input file
|
||
// and then reset it back to the beginning.
|
||
//
|
||
|
||
if (J0SROM) {
|
||
UCHAR InputData;
|
||
ULONG J0Checksum = 0;
|
||
ULONG Length = 0;
|
||
ULONG TempX;
|
||
ULONG TempY;
|
||
UCHAR J0Signatures[8] = {0xc3, 0xc3, 0x5a, 0x5a,
|
||
0x3c, 0x3c, 0xa5, 0xa5};
|
||
|
||
printf("Writing the J0SROM header...\n");
|
||
|
||
Index += 16;
|
||
|
||
do {
|
||
fread(&InputData, 1, 1, FirmwareInFile);
|
||
|
||
if (ferror(FirmwareInFile)) {
|
||
fprintf(stderr, "?ERROR on input file.\n");
|
||
exit(0);
|
||
}
|
||
|
||
if (feof(FirmwareInFile) == 0) {
|
||
J0Checksum += InputData;
|
||
Length++;
|
||
}
|
||
} while(feof(FirmwareInFile) == 0);
|
||
|
||
//
|
||
// J0Checksum = the J0SROM-required checksum.
|
||
// Length = the number of bytes in the input file. Although
|
||
// we will pad the binary data in the output file to
|
||
// a multiple of 64KB, the padding is of course unused
|
||
// data, and so Length is what we will write to the
|
||
// header.
|
||
//
|
||
|
||
// Reset the input file to the beginning
|
||
if (fseek(FirmwareInFile, 0, SEEK_SET)) {
|
||
fprintf(stderr, "?ERROR resetting binary file to the beginning.\n");
|
||
exit(0);
|
||
}
|
||
|
||
|
||
// Write the J0SROM Checksum.
|
||
for (TempX = 0; TempX < 4; TempX++) {
|
||
InputData = J0Checksum & 0xff;
|
||
WriteAByte(InputData);
|
||
Checksum += InputData;
|
||
J0Checksum = J0Checksum >> 8;
|
||
}
|
||
|
||
|
||
// Write the first and second signatures.
|
||
for (TempX = 0; TempX < 8; TempX++) {
|
||
InputData = J0Signatures[TempX];
|
||
WriteAByte(InputData);
|
||
Checksum += InputData;
|
||
}
|
||
|
||
|
||
// Write the size of the firmware.
|
||
for (TempX = 0; TempX < 4; TempX++) {
|
||
InputData = Length & 0xff;
|
||
WriteAByte(InputData);
|
||
Checksum += InputData;
|
||
Length = Length >> 8;
|
||
}
|
||
|
||
} // if (J0SROM)
|
||
|
||
|
||
printf("Transferring input file to output file...\n");
|
||
|
||
ROMChecksum = 0;
|
||
|
||
do {
|
||
fread(&InputData, 1, 1, FirmwareInFile);
|
||
|
||
if (ferror(FirmwareInFile)) {
|
||
printf("?ERROR on input file, %d. bytes written.\n", Index);
|
||
exit(0);
|
||
}
|
||
|
||
if (feof(FirmwareInFile) == 0) {
|
||
|
||
// For the additive-zero checksum covering this file.
|
||
Checksum += InputData;
|
||
|
||
// For a production checksum in the ROM. Barrel-rotate and add.
|
||
ROMChecksum = RotateLeft(ROMChecksum) + InputData;
|
||
|
||
WriteAByte(InputData);
|
||
Index++;
|
||
}
|
||
|
||
} while(feof(FirmwareInFile) == 0);
|
||
|
||
// Index now contains the number of firmware binary data bytes that were
|
||
// written to the output file.
|
||
printf ("%d. firmware bytes written.\n", Index);
|
||
|
||
|
||
printf("Padding the binary data to an even multiple of 5 * 64kb.\n");
|
||
|
||
// Bump Index to account for our having to write the production
|
||
// checksum.
|
||
Index++;
|
||
|
||
TempULong = 0;
|
||
while ((Index % 0x50000) != 0) {
|
||
// "Add zero" to the the ROL running checksum.
|
||
ROMChecksum = RotateLeft(ROMChecksum);
|
||
WriteAByte(TempULong);
|
||
Index++;
|
||
}
|
||
|
||
// Now write the production checksum.
|
||
Checksum += ROMChecksum;
|
||
WriteAByte(ROMChecksum);
|
||
|
||
FileChecksum = 0 - Checksum;
|
||
printf ("Writing the checksum. Sum of all bytes = 0x%x, FileChecksum = 0x%x\n",
|
||
Checksum, FileChecksum);
|
||
if ((fwrite(&FileChecksum, sizeof(FileChecksum), 1, FirmwareOutFile)) != 1) {
|
||
fprintf(stderr, "?ERROR writing to output file.\n");
|
||
exit(0);
|
||
}
|
||
|
||
if (fclose(FirmwareOutFile) == EOF) {
|
||
fprintf(stderr, "?ERROR closing output file.\n");
|
||
exit(0);
|
||
}
|
||
|
||
fclose(FirmwareInFile);
|
||
|
||
exit(0);
|
||
}
|
||
|