/*++ | |
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; | |
} |