352 lines
8.5 KiB
C
Raw Permalink Normal View History

2001-01-01 00:00:00 +01:00
/*++
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);
}