/** @file
Calculate Crc32 value and Verify Crc32 value for input data.
Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include "ParseInf.h"
#include "EfiUtilityMsgs.h"
#include "CommonLib.h"
#include "Crc32.h"
#define UTILITY_NAME "GenCrc32"
#define UTILITY_MAJOR_VERSION 0
#define UTILITY_MINOR_VERSION 2
#define CRC32_NULL 0
#define CRC32_ENCODE 1
#define CRC32_DECODE 2
VOID
Version (
VOID
)
/*++
Routine Description:
Displays the standard utility information to SDTOUT
Arguments:
None
Returns:
None
--*/
{
fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
}
VOID
Usage (
VOID
)
/*++
Routine Description:
Displays the utility usage syntax to STDOUT
Arguments:
None
Returns:
None
--*/
{
//
// Summary usage
//
fprintf (stdout, "Usage: GenCrc32 -e|-d [options] \n\n");
//
// Copyright declaration
//
fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
//
// Details Option
//
fprintf (stdout, "optional arguments:\n");
fprintf (stdout, " -h, --help Show this help message and exit\n");
fprintf (stdout, " --version Show program's version number and exit\n");
fprintf (stdout, " --debug [DEBUG] Output DEBUG statements, where DEBUG_LEVEL is 0 (min)\n\
- 9 (max)\n");
fprintf (stdout, " -v, --verbose Print informational statements\n");
fprintf (stdout, " -q, --quiet Returns the exit code, error messages will be\n\
displayed\n");
fprintf (stdout, " -s, --silent Returns only the exit code; informational and error\n\
messages are not displayed\n");
fprintf (stdout, " -e, --encode Calculate CRC32 value for the input file\n");
fprintf (stdout, " -d, --decode Verify CRC32 value for the input file\n");
fprintf (stdout, " -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\
Output file name\n");
fprintf (stdout, " --sfo Reserved for future use\n");
}
int
main (
int argc,
CHAR8 *argv[]
)
/*++
Routine Description:
Main function.
Arguments:
argc - Number of command line parameters.
argv - Array of pointers to parameter strings.
Returns:
STATUS_SUCCESS - Utility exits successfully.
STATUS_ERROR - Some error occurred during execution.
--*/
{
EFI_STATUS Status;
CHAR8 *OutputFileName;
CHAR8 *InputFileName;
UINT8 *FileBuffer;
UINT32 FileSize;
UINT64 LogLevel;
UINT8 FileAction;
UINT32 Crc32Value;
FILE *InFile;
FILE *OutFile;
//
// Init local variables
//
LogLevel = 0;
Status = EFI_SUCCESS;
InputFileName = NULL;
OutputFileName = NULL;
FileAction = CRC32_NULL;
InFile = NULL;
OutFile = NULL;
Crc32Value = 0;
FileBuffer = NULL;
SetUtilityName (UTILITY_NAME);
if (argc == 1) {
Error (NULL, 0, 1001, "Missing options", "no options input");
Usage ();
return STATUS_ERROR;
}
//
// Parse command line
//
argc --;
argv ++;
if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
Usage ();
return STATUS_SUCCESS;
}
if (stricmp (argv[0], "--version") == 0) {
Version ();
return STATUS_SUCCESS;
}
while (argc > 0) {
if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
if (argv[1] == NULL || argv[1][0] == '-') {
Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option");
goto Finish;
}
OutputFileName = argv[1];
argc -= 2;
argv += 2;
continue;
}
if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--encode") == 0)) {
FileAction = CRC32_ENCODE;
argc --;
argv ++;
continue;
}
if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--decode") == 0)) {
FileAction = CRC32_DECODE;
argc --;
argv ++;
continue;
}
if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
SetPrintLevel (VERBOSE_LOG_LEVEL);
VerboseMsg ("Verbose output Mode Set!");
argc --;
argv ++;
continue;
}
if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
SetPrintLevel (KEY_LOG_LEVEL);
KeyMsg ("Quiet output Mode Set!");
argc --;
argv ++;
continue;
}
if (stricmp (argv[0], "--debug") == 0) {
Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
goto Finish;
}
if (LogLevel > 9) {
Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);
goto Finish;
}
SetPrintLevel (LogLevel);
DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
argc -= 2;
argv += 2;
continue;
}
if (argv[0][0] == '-') {
Error (NULL, 0, 1000, "Unknown option", argv[0]);
goto Finish;
}
//
// Get Input file file name.
//
InputFileName = argv[0];
argc --;
argv ++;
}
VerboseMsg ("%s tool start.", UTILITY_NAME);
//
// Check Input parameters
//
if (FileAction == CRC32_NULL) {
Error (NULL, 0, 1001, "Missing option", "either the encode or the decode option must be specified!");
return STATUS_ERROR;
} else if (FileAction == CRC32_ENCODE) {
VerboseMsg ("File will be encoded by Crc32");
} else if (FileAction == CRC32_DECODE) {
VerboseMsg ("File will be decoded by Crc32");
}
if (InputFileName == NULL) {
Error (NULL, 0, 1001, "Missing option", "Input files are not specified");
goto Finish;
} else {
VerboseMsg ("Input file name is %s", InputFileName);
}
if (OutputFileName == NULL) {
Error (NULL, 0, 1001, "Missing option", "Output file are not specified");
goto Finish;
} else {
VerboseMsg ("Output file name is %s", OutputFileName);
}
//
// Open Input file and read file data.
//
InFile = fopen (LongFilePath (InputFileName), "rb");
if (InFile == NULL) {
Error (NULL, 0, 0001, "Error opening file", InputFileName);
return STATUS_ERROR;
}
fseek (InFile, 0, SEEK_END);
FileSize = ftell (InFile);
fseek (InFile, 0, SEEK_SET);
FileBuffer = (UINT8 *) malloc (FileSize);
if (FileBuffer == NULL) {
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
fclose (InFile);
goto Finish;
}
fread (FileBuffer, 1, FileSize, InFile);
fclose (InFile);
VerboseMsg ("the size of the input file is %u bytes", (unsigned) FileSize);
//
// Open output file
//
OutFile = fopen (LongFilePath (OutputFileName), "wb");
if (OutFile == NULL) {
Error (NULL, 0, 0001, "Error opening file", OutputFileName);
goto Finish;
}
//
// Calculate Crc32 value
//
if (FileAction == CRC32_ENCODE) {
Status = CalculateCrc32 (FileBuffer, FileSize, &Crc32Value);
if (Status != EFI_SUCCESS) {
Error (NULL, 0, 3000, "Invalid", "Calculate CRC32 value failed!");
goto Finish;
}
//
// Done, write output file.
//
fwrite (&Crc32Value, 1, sizeof (Crc32Value), OutFile);
VerboseMsg ("The calculated CRC32 value is 0x%08x", (unsigned) Crc32Value);
fwrite (FileBuffer, 1, FileSize, OutFile);
VerboseMsg ("the size of the encoded file is %u bytes", (unsigned) FileSize + sizeof (UINT32));
} else {
//
// Verify Crc32 Value
//
if (FileSize < sizeof (UINT32)) {
Error (NULL, 0, 3000, "Invalid", "Input file is invalid!");
goto Finish;
}
Status = CalculateCrc32 (FileBuffer + sizeof (UINT32), FileSize - sizeof (UINT32), &Crc32Value);
if (Status != EFI_SUCCESS) {
Error (NULL, 0, 3000, "Invalid", "Calculate CRC32 value failed!");
goto Finish;
}
VerboseMsg ("The calculated CRC32 value is 0x%08x and File Crc32 value is 0x%08x", (unsigned) Crc32Value, (unsigned) (*(UINT32 *)FileBuffer));
if (Crc32Value != *(UINT32 *)FileBuffer) {
Error (NULL, 0, 3000, "Invalid", "CRC32 value of input file is not correct!");
Status = STATUS_ERROR;
goto Finish;
}
//
// Done, write output file.
//
fwrite (FileBuffer + sizeof (UINT32), 1, FileSize - sizeof (UINT32), OutFile);
VerboseMsg ("the size of the decoded file is %u bytes", (unsigned) FileSize - sizeof (UINT32));
}
Finish:
if (FileBuffer != NULL) {
free (FileBuffer);
}
if (OutFile != NULL) {
fclose (OutFile);
}
VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
return GetUtilityStatus ();
}