audk/Tools/CCode/Source/GenCRC32Section/GenCRC32Section.c

287 lines
7.6 KiB
C
Raw Normal View History

/*++
Copyright (c) 2004, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
GenCRC32Section.c
Abstract:
This file contains functions required to generate a Firmware File System
file. The code is compliant with the Tiano C Coding standards.
--*/
#include "GenCRC32Section.h"
#define TOOLVERSION "0.2"
#define UTILITY_NAME "GenCrc32Section"
EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
EFI_STATUS
SignSectionWithCrc32 (
IN OUT UINT8 *FileBuffer,
IN OUT UINT32 *BufferSize,
IN UINT32 DataSize
)
/*++
Routine Description:
Signs the section with CRC32 and add GUIDed section header for the
signed data. data stays in same location (overwrites source data).
Arguments:
FileBuffer - Buffer containing data to sign
BufferSize - On input, the size of FileBuffer. On output, the size of
actual section data (including added section header).
DataSize - Length of data to Sign
Key - Key to use when signing. Currently only CRC32 is supported.
Returns:
EFI_SUCCESS - Successful
EFI_OUT_OF_RESOURCES - Not enough resource to complete the operation.
--*/
{
UINT32 Crc32Checksum;
EFI_STATUS Status;
UINT32 TotalSize;
CRC32_SECTION_HEADER Crc32Header;
UINT8 *SwapBuffer;
Crc32Checksum = 0;
SwapBuffer = NULL;
if (DataSize == 0) {
*BufferSize = 0;
return EFI_SUCCESS;
}
Status = CalculateCrc32 (FileBuffer, DataSize, &Crc32Checksum);
if (EFI_ERROR (Status)) {
return Status;
}
TotalSize = DataSize + CRC32_SECTION_HEADER_SIZE;
Crc32Header.GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
Crc32Header.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);
Crc32Header.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);
Crc32Header.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);
memcpy (&(Crc32Header.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
Crc32Header.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
Crc32Header.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE;
Crc32Header.CRC32Checksum = Crc32Checksum;
SwapBuffer = (UINT8 *) malloc (DataSize);
if (SwapBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
memcpy (SwapBuffer, FileBuffer, DataSize);
memcpy (FileBuffer, &Crc32Header, CRC32_SECTION_HEADER_SIZE);
memcpy (FileBuffer + CRC32_SECTION_HEADER_SIZE, SwapBuffer, DataSize);
//
// Make sure section ends on a DWORD boundary
//
while ((TotalSize & 0x03) != 0) {
FileBuffer[TotalSize] = 0;
TotalSize++;
}
*BufferSize = TotalSize;
if (SwapBuffer != NULL) {
free (SwapBuffer);
}
return EFI_SUCCESS;
}
VOID
PrintUsage (
VOID
)
{
printf ("Usage:\n");
printf (UTILITY_NAME " -i \"inputfile1\" \"inputfile2\" -o \"outputfile\" \n");
printf (" -i \"inputfile\":\n ");
printf (" specifies the input files that would be signed to CRC32 Guided section.\n");
printf (" -o \"outputfile\":\n");
printf (" specifies the output file that is a CRC32 Guided section.\n");
}
INT32
ReadFilesContentsIntoBuffer (
IN CHAR8 *argv[],
IN INT32 Start,
IN OUT UINT8 **FileBuffer,
IN OUT UINT32 *BufferSize,
OUT UINT32 *ContentSize,
IN INT32 MaximumArguments
)
{
INT32 Index;
CHAR8 *FileName;
FILE *InputFile;
UINT8 Temp;
UINT32 Size;
FileName = NULL;
InputFile = NULL;
Size = 0;
Index = 0;
//
// read all input files into one file buffer
//
while (argv[Start + Index][0] != '-') {
FileName = argv[Start + Index];
InputFile = fopen (FileName, "rb");
if (InputFile == NULL) {
Error (NULL, 0, 0, FileName, "failed to open input binary file");
return -1;
}
fread (&Temp, sizeof (UINT8), 1, InputFile);
while (!feof (InputFile)) {
(*FileBuffer)[Size++] = Temp;
fread (&Temp, sizeof (UINT8), 1, InputFile);
}
fclose (InputFile);
InputFile = NULL;
//
// Make sure section ends on a DWORD boundary
//
while ((Size & 0x03) != 0) {
(*FileBuffer)[Size] = 0;
Size++;
}
Index++;
if (Index == MaximumArguments) {
break;
}
}
*ContentSize = Size;
return Index;
}
int
main (
INT32 argc,
CHAR8 *argv[]
)
{
FILE *OutputFile;
UINT8 *FileBuffer;
UINT32 BufferSize;
EFI_STATUS Status;
UINT32 ContentSize;
CHAR8 *OutputFileName;
INT32 ReturnValue;
INT32 Index;
OutputFile = NULL;
FileBuffer = NULL;
ContentSize = 0;
OutputFileName = NULL;
SetUtilityName (UTILITY_NAME);
if (argc == 1) {
PrintUsage ();
return -1;
}
BufferSize = 1024 * 1024 * 16;
FileBuffer = (UINT8 *) malloc (BufferSize * sizeof (UINT8));
if (FileBuffer == NULL) {
Error (NULL, 0, 0, "memory allocation failed", NULL);
return -1;
}
ZeroMem (FileBuffer, BufferSize);
for (Index = 0; Index < argc; Index++) {
if (strcmpi (argv[Index], "-i") == 0) {
ReturnValue = ReadFilesContentsIntoBuffer (
argv,
(Index + 1),
&FileBuffer,
&BufferSize,
&ContentSize,
(argc - (Index + 1))
);
if (ReturnValue == -1) {
Error (NULL, 0, 0, "failed to read file contents", NULL);
return -1;
}
Index += ReturnValue;
}
if (strcmpi (argv[Index], "-o") == 0) {
OutputFileName = argv[Index + 1];
}
}
OutputFile = fopen (OutputFileName, "wb");
if (OutputFile == NULL) {
Error (NULL, 0, 0, OutputFileName, "failed to open output binary file");
free (FileBuffer);
return -1;
}
/*
//
// make sure section ends on a DWORD boundary ??
//
while ( (Size & 0x03) != 0 ) {
FileBuffer[Size] = 0;
Size ++;
}
*/
Status = SignSectionWithCrc32 (FileBuffer, &BufferSize, ContentSize);
if (EFI_ERROR (Status)) {
Error (NULL, 0, 0, "failed to sign section", NULL);
free (FileBuffer);
fclose (OutputFile);
return -1;
}
ContentSize = fwrite (FileBuffer, sizeof (UINT8), BufferSize, OutputFile);
if (ContentSize != BufferSize) {
Error (NULL, 0, 0, "failed to write output buffer", NULL);
ReturnValue = -1;
} else {
ReturnValue = 0;
}
free (FileBuffer);
fclose (OutputFile);
return ReturnValue;
}