summaryrefslogtreecommitdiff
path: root/BaseTools/Source/C/Common
diff options
context:
space:
mode:
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2009-07-17 09:10:31 +0000
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>2009-07-17 09:10:31 +0000
commit30fdf1140b8d1ce93f3821d986fa165552023440 (patch)
treec45c336a8955b1d03ea56d6c915a0e68a43b4ee9 /BaseTools/Source/C/Common
parent577e30cdb473e4af8e65fd6f75236691d0c8dfb3 (diff)
downloadedk2-platforms-30fdf1140b8d1ce93f3821d986fa165552023440.tar.xz
Check In tool source code based on Build tool project revision r1655.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'BaseTools/Source/C/Common')
-rw-r--r--BaseTools/Source/C/Common/BasePeCoff.c1386
-rw-r--r--BaseTools/Source/C/Common/BinderFuncs.c87
-rw-r--r--BaseTools/Source/C/Common/BinderFuncs.h75
-rw-r--r--BaseTools/Source/C/Common/CommonLib.c584
-rw-r--r--BaseTools/Source/C/Common/CommonLib.h172
-rw-r--r--BaseTools/Source/C/Common/Compress.h95
-rw-r--r--BaseTools/Source/C/Common/Crc32.c326
-rw-r--r--BaseTools/Source/C/Common/Crc32.h54
-rw-r--r--BaseTools/Source/C/Common/Decompress.c982
-rw-r--r--BaseTools/Source/C/Common/Decompress.h172
-rw-r--r--BaseTools/Source/C/Common/EfiCompress.c1598
-rw-r--r--BaseTools/Source/C/Common/EfiUtilityMsgs.c929
-rw-r--r--BaseTools/Source/C/Common/EfiUtilityMsgs.h166
-rw-r--r--BaseTools/Source/C/Common/FirmwareVolumeBuffer.c1667
-rw-r--r--BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h166
-rw-r--r--BaseTools/Source/C/Common/FvLib.c850
-rw-r--r--BaseTools/Source/C/Common/FvLib.h178
-rw-r--r--BaseTools/Source/C/Common/GNUmakefile28
-rw-r--r--BaseTools/Source/C/Common/Makefile30
-rw-r--r--BaseTools/Source/C/Common/MemoryFile.c260
-rw-r--r--BaseTools/Source/C/Common/MemoryFile.h122
-rw-r--r--BaseTools/Source/C/Common/MyAlloc.c516
-rw-r--r--BaseTools/Source/C/Common/MyAlloc.h222
-rw-r--r--BaseTools/Source/C/Common/OsPath.c307
-rw-r--r--BaseTools/Source/C/Common/OsPath.h146
-rw-r--r--BaseTools/Source/C/Common/ParseGuidedSectionTools.c210
-rw-r--r--BaseTools/Source/C/Common/ParseGuidedSectionTools.h133
-rw-r--r--BaseTools/Source/C/Common/ParseInf.c665
-rw-r--r--BaseTools/Source/C/Common/ParseInf.h230
-rw-r--r--BaseTools/Source/C/Common/PeCoffLib.h137
-rw-r--r--BaseTools/Source/C/Common/PeCoffLoaderEx.c317
-rw-r--r--BaseTools/Source/C/Common/SimpleFileParsing.c1443
-rw-r--r--BaseTools/Source/C/Common/SimpleFileParsing.h117
-rw-r--r--BaseTools/Source/C/Common/StringFuncs.c426
-rw-r--r--BaseTools/Source/C/Common/StringFuncs.h257
-rw-r--r--BaseTools/Source/C/Common/TianoCompress.c1753
-rw-r--r--BaseTools/Source/C/Common/WinNtInclude.h73
37 files changed, 16879 insertions, 0 deletions
diff --git a/BaseTools/Source/C/Common/BasePeCoff.c b/BaseTools/Source/C/Common/BasePeCoff.c
new file mode 100644
index 0000000000..72b6a52f89
--- /dev/null
+++ b/BaseTools/Source/C/Common/BasePeCoff.c
@@ -0,0 +1,1386 @@
+/** @file
+
+ Functions to get info and load PE/COFF image.
+
+Copyright (c) 2004 - 2008, 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.
+
+**/
+
+#include <Common/UefiBaseTypes.h>
+#include <CommonLib.h>
+#include <IndustryStandard/PeImage.h>
+#include "PeCoffLib.h"
+
+typedef union {
+ VOID *Header;
+ EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;
+ EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;
+} EFI_IMAGE_OPTIONAL_HEADER_POINTER;
+
+STATIC
+RETURN_STATUS
+PeCoffLoaderGetPeHeader (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_IMAGE_OPTIONAL_HEADER_UNION **PeHdr,
+ OUT EFI_TE_IMAGE_HEADER **TeHdr
+ );
+
+STATIC
+RETURN_STATUS
+PeCoffLoaderCheckImageType (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr,
+ IN EFI_TE_IMAGE_HEADER *TeHdr
+ );
+
+STATIC
+VOID *
+PeCoffLoaderImageAddress (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN UINTN Address
+ );
+
+RETURN_STATUS
+PeCoffLoaderRelocateIa32Image (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ );
+
+RETURN_STATUS
+PeCoffLoaderRelocateX64Image (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ );
+
+RETURN_STATUS
+PeCoffLoaderRelocateIpfImage (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ );
+
+STATIC
+RETURN_STATUS
+PeCoffLoaderGetPeHeader (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_IMAGE_OPTIONAL_HEADER_UNION **PeHdr,
+ OUT EFI_TE_IMAGE_HEADER **TeHdr
+ )
+/*++
+
+Routine Description:
+
+ Retrieves the PE or TE Header from a PE/COFF or TE image
+
+Arguments:
+
+ ImageContext - The context of the image being loaded
+
+ PeHdr - The buffer in which to return the PE header
+
+ TeHdr - The buffer in which to return the TE header
+
+Returns:
+
+ RETURN_SUCCESS if the PE or TE Header is read,
+ Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.
+
+--*/
+{
+ RETURN_STATUS Status;
+ EFI_IMAGE_DOS_HEADER DosHdr;
+ UINTN Size;
+
+ ImageContext->IsTeImage = FALSE;
+ //
+ // Read the DOS image headers
+ //
+ Size = sizeof (EFI_IMAGE_DOS_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &Size,
+ &DosHdr
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ ImageContext->PeCoffHeaderOffset = 0;
+ if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // DOS image header is present, so read the PE header after the DOS image header
+ //
+ ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;
+ }
+ //
+ // Get the PE/COFF Header pointer
+ //
+ *PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);
+ if ((*PeHdr)->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ //
+ // Check the PE/COFF Header Signature. If not, then try to get a TE header
+ //
+ *TeHdr = (EFI_TE_IMAGE_HEADER *)*PeHdr;
+ if ((*TeHdr)->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ return RETURN_UNSUPPORTED;
+ }
+ ImageContext->IsTeImage = TRUE;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+STATIC
+RETURN_STATUS
+PeCoffLoaderCheckImageType (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr,
+ IN EFI_TE_IMAGE_HEADER *TeHdr
+ )
+/*++
+
+Routine Description:
+
+ Checks the PE or TE header of a PE/COFF or TE image to determine if it supported
+
+Arguments:
+
+ ImageContext - The context of the image being loaded
+
+ PeHdr - The buffer in which to return the PE header
+
+ TeHdr - The buffer in which to return the TE header
+
+Returns:
+
+ RETURN_SUCCESS if the PE/COFF or TE image is supported
+ RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported.
+
+--*/
+{
+ //
+ // See if the machine type is supported.
+ // We support a native machine type (IA-32/Itanium-based)
+ //
+ if (ImageContext->IsTeImage == FALSE) {
+ ImageContext->Machine = PeHdr->Pe32.FileHeader.Machine;
+ } else {
+ ImageContext->Machine = TeHdr->Machine;
+ }
+
+ if (ImageContext->Machine != EFI_IMAGE_MACHINE_IA32 && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_IA64 && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_X64 && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_ARMT && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_EBC) {
+ if (ImageContext->Machine == IMAGE_FILE_MACHINE_ARM) {
+ //
+ // There are two types of ARM images. Pure ARM and ARM/Thumb.
+ // If we see the ARM say it is the ARM/Thumb so there is only
+ // a single machine type we need to check for ARM.
+ //
+ ImageContext->Machine = EFI_IMAGE_MACHINE_ARMT;
+ if (ImageContext->IsTeImage == FALSE) {
+ PeHdr->Pe32.FileHeader.Machine = ImageContext->Machine;
+ } else {
+ TeHdr->Machine = ImageContext->Machine;
+ }
+
+ } else {
+ //
+ // unsupported PeImage machine type
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ }
+
+ //
+ // See if the image type is supported. We support EFI Applications,
+ // EFI Boot Service Drivers, EFI Runtime Drivers and EFI SAL Drivers.
+ //
+ if (ImageContext->IsTeImage == FALSE) {
+ ImageContext->ImageType = PeHdr->Pe32.OptionalHeader.Subsystem;
+ } else {
+ ImageContext->ImageType = (UINT16) (TeHdr->Subsystem);
+ }
+
+ if (ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION && \
+ ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER && \
+ ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER && \
+ ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER) {
+ //
+ // upsupported PeImage subsystem type
+ //
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderGetImageInfo (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+
+ Retrieves information on a PE/COFF image
+
+Arguments:
+
+ This - Calling context
+ ImageContext - The context of the image being loaded
+
+Returns:
+
+ RETURN_SUCCESS - The information on the PE/COFF image was collected.
+ RETURN_INVALID_PARAMETER - ImageContext is NULL.
+ RETURN_UNSUPPORTED - The PE/COFF image is not supported.
+ Otherwise - The error status from reading the PE/COFF image using the
+ ImageContext->ImageRead() function
+
+--*/
+{
+ RETURN_STATUS Status;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
+ EFI_TE_IMAGE_HEADER *TeHdr;
+ EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry;
+ UINTN Size;
+ UINTN Index;
+ UINTN DebugDirectoryEntryRva;
+ UINTN DebugDirectoryEntryFileOffset;
+ UINTN SectionHeaderOffset;
+ EFI_IMAGE_SECTION_HEADER SectionHeader;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;
+ EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader;
+
+ PeHdr = NULL;
+ TeHdr = NULL;
+ DebugDirectoryEntry = NULL;
+ DebugDirectoryEntryRva = 0;
+
+ if (NULL == ImageContext) {
+ return RETURN_INVALID_PARAMETER;
+ }
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ Status = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify machine type
+ //
+ Status = PeCoffLoaderCheckImageType (ImageContext, PeHdr, TeHdr);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+ OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader);
+
+ //
+ // Retrieve the base address of the image
+ //
+ if (!(ImageContext->IsTeImage)) {
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ ImageContext->ImageAddress = (PHYSICAL_ADDRESS) OptionHeader.Optional32->ImageBase;
+ } else {
+ ImageContext->ImageAddress = (PHYSICAL_ADDRESS) OptionHeader.Optional64->ImageBase;
+ }
+ } else {
+ ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr->ImageBase + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
+ }
+ //
+ // Initialize the alternate destination address to 0 indicating that it
+ // should not be used.
+ //
+ ImageContext->DestinationAddress = 0;
+
+ //
+ // Initialize the codeview pointer.
+ //
+ ImageContext->CodeView = NULL;
+ ImageContext->PdbPointer = NULL;
+
+ //
+ // Three cases with regards to relocations:
+ // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
+ // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
+ // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
+ // has no base relocs to apply
+ // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
+ //
+ // Look at the file header to determine if relocations have been stripped, and
+ // save this info in the image context for later use.
+ //
+ if ((!(ImageContext->IsTeImage)) && ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
+ ImageContext->RelocationsStripped = TRUE;
+ } else if ((ImageContext->IsTeImage) && (TeHdr->DataDirectory[0].Size == 0)) {
+ ImageContext->RelocationsStripped = TRUE;
+ } else {
+ ImageContext->RelocationsStripped = FALSE;
+ }
+
+ if (!(ImageContext->IsTeImage)) {
+
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ ImageContext->ImageSize = (UINT64) OptionHeader.Optional32->SizeOfImage;
+ ImageContext->SectionAlignment = OptionHeader.Optional32->SectionAlignment;
+ ImageContext->SizeOfHeaders = OptionHeader.Optional32->SizeOfHeaders;
+
+ //
+ // Modify ImageSize to contain .PDB file name if required and initialize
+ // PdbRVA field...
+ //
+ if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
+ }
+ } else {
+ ImageContext->ImageSize = (UINT64) OptionHeader.Optional64->SizeOfImage;
+ ImageContext->SectionAlignment = OptionHeader.Optional64->SectionAlignment;
+ ImageContext->SizeOfHeaders = OptionHeader.Optional64->SizeOfHeaders;
+
+ //
+ // Modify ImageSize to contain .PDB file name if required and initialize
+ // PdbRVA field...
+ //
+ if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
+ }
+ }
+
+ if (DebugDirectoryEntryRva != 0) {
+ //
+ // Determine the file offset of the debug directory... This means we walk
+ // the sections to find which section contains the RVA of the debug
+ // directory
+ //
+ DebugDirectoryEntryFileOffset = 0;
+
+ SectionHeaderOffset = (UINTN)(
+ ImageContext->PeCoffHeaderOffset +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ PeHdr->Pe32.FileHeader.SizeOfOptionalHeader
+ );
+
+ for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
+ //
+ // Read section header from file
+ //
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ SectionHeaderOffset,
+ &Size,
+ &SectionHeader
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
+ DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
+ DebugDirectoryEntryFileOffset =
+ DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;
+ break;
+ }
+
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+ }
+
+ if (DebugDirectoryEntryFileOffset != 0) {
+ for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
+ //
+ // Read next debug directory entry
+ //
+ Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugDirectoryEntryFileOffset + Index,
+ &Size,
+ &DebugEntry
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);
+ if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {
+ ImageContext->ImageSize += DebugEntry.SizeOfData;
+ }
+
+ return RETURN_SUCCESS;
+ }
+ }
+ }
+ }
+ } else {
+ ImageContext->ImageSize = 0;
+ ImageContext->SectionAlignment = 4096;
+ ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr->BaseOfCode - (UINTN) TeHdr->StrippedSize;
+
+ DebugDirectoryEntry = &TeHdr->DataDirectory[1];
+ DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
+ SectionHeaderOffset = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER));
+
+ DebugDirectoryEntryFileOffset = 0;
+
+ for (Index = 0; Index < TeHdr->NumberOfSections;) {
+ //
+ // Read section header from file
+ //
+ Size = sizeof (EFI_IMAGE_SECTION_HEADER);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ SectionHeaderOffset,
+ &Size,
+ &SectionHeader
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&
+ DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {
+ DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -
+ SectionHeader.VirtualAddress +
+ SectionHeader.PointerToRawData +
+ sizeof (EFI_TE_IMAGE_HEADER) -
+ TeHdr->StrippedSize;
+
+ //
+ // File offset of the debug directory was found, if this is not the last
+ // section, then skip to the last section for calculating the image size.
+ //
+ if (Index < (UINTN) TeHdr->NumberOfSections - 1) {
+ SectionHeaderOffset += (TeHdr->NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);
+ Index = TeHdr->NumberOfSections - 1;
+ continue;
+ }
+ }
+
+ //
+ // In Te image header there is not a field to describe the ImageSize.
+ // Actually, the ImageSize equals the RVA plus the VirtualSize of
+ // the last section mapped into memory (Must be rounded up to
+ // a mulitple of Section Alignment). Per the PE/COFF specification, the
+ // section headers in the Section Table must appear in order of the RVA
+ // values for the corresponding sections. So the ImageSize can be determined
+ // by the RVA and the VirtualSize of the last section header in the
+ // Section Table.
+ //
+ if ((++Index) == (UINTN) TeHdr->NumberOfSections) {
+ ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize +
+ ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1);
+ }
+
+ SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
+ }
+
+ if (DebugDirectoryEntryFileOffset != 0) {
+ for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
+ //
+ // Read next debug directory entry
+ //
+ Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugDirectoryEntryFileOffset,
+ &Size,
+ &DebugEntry
+ );
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+
+ if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+ ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index);
+ return RETURN_SUCCESS;
+ }
+ }
+ }
+ }
+
+ return RETURN_SUCCESS;
+}
+
+STATIC
+VOID *
+PeCoffLoaderImageAddress (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN UINTN Address
+ )
+/*++
+
+Routine Description:
+
+ Converts an image address to the loaded address
+
+Arguments:
+
+ ImageContext - The context of the image being loaded
+
+ Address - The address to be converted to the loaded address
+
+Returns:
+
+ NULL if the address can not be converted, otherwise, the converted address
+
+--*/
+{
+ if (Address >= ImageContext->ImageSize) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
+ return NULL;
+ }
+
+ return (UINT8 *) ((UINTN) ImageContext->ImageAddress + Address);
+}
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderRelocateImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+
+ Relocates a PE/COFF image in memory
+
+Arguments:
+
+ This - Calling context
+
+ ImageContext - Contains information on the loaded image to relocate
+
+Returns:
+
+ RETURN_SUCCESS if the PE/COFF image was relocated
+ RETURN_LOAD_ERROR if the image is not a valid PE/COFF image
+ RETURN_UNSUPPORTED not support
+
+--*/
+{
+ RETURN_STATUS Status;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
+ EFI_TE_IMAGE_HEADER *TeHdr;
+ EFI_IMAGE_DATA_DIRECTORY *RelocDir;
+ UINT64 Adjust;
+ EFI_IMAGE_BASE_RELOCATION *RelocBase;
+ EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;
+ UINT16 *Reloc;
+ UINT16 *RelocEnd;
+ CHAR8 *Fixup;
+ CHAR8 *FixupBase;
+ UINT16 *F16;
+ UINT32 *F32;
+ CHAR8 *FixupData;
+ PHYSICAL_ADDRESS BaseAddress;
+ UINT16 MachineType;
+ EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader;
+
+ PeHdr = NULL;
+ TeHdr = NULL;
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ //
+ // If there are no relocation entries, then we are done
+ //
+ if (ImageContext->RelocationsStripped) {
+ return RETURN_SUCCESS;
+ }
+
+ //
+ // If the destination address is not 0, use that rather than the
+ // image address as the relocation target.
+ //
+ if (ImageContext->DestinationAddress) {
+ BaseAddress = ImageContext->DestinationAddress;
+ } else {
+ BaseAddress = ImageContext->ImageAddress;
+ }
+
+ if (!(ImageContext->IsTeImage)) {
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN)ImageContext->ImageAddress +
+ ImageContext->PeCoffHeaderOffset);
+ OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader);
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ Adjust = (UINT64) BaseAddress - OptionHeader.Optional32->ImageBase;
+ OptionHeader.Optional32->ImageBase = (UINT32) BaseAddress;
+ MachineType = ImageContext->Machine;
+ //
+ // Find the relocation block
+ //
+ // Per the PE/COFF spec, you can't assume that a given data directory
+ // is present in the image. You have to check the NumberOfRvaAndSizes in
+ // the optional header to verify a desired directory entry is there.
+ //
+ if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ RelocDir = &OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
+ RelocBaseEnd = PeCoffLoaderImageAddress (
+ ImageContext,
+ RelocDir->VirtualAddress + RelocDir->Size - 1
+ );
+ } else {
+ //
+ // Set base and end to bypass processing below.
+ //
+ RelocBase = RelocBaseEnd = 0;
+ }
+ } else {
+ Adjust = (UINT64) BaseAddress - OptionHeader.Optional64->ImageBase;
+ OptionHeader.Optional64->ImageBase = BaseAddress;
+ MachineType = ImageContext->Machine;
+ //
+ // Find the relocation block
+ //
+ // Per the PE/COFF spec, you can't assume that a given data directory
+ // is present in the image. You have to check the NumberOfRvaAndSizes in
+ // the optional header to verify a desired directory entry is there.
+ //
+ if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ RelocDir = &OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
+ RelocBaseEnd = PeCoffLoaderImageAddress (
+ ImageContext,
+ RelocDir->VirtualAddress + RelocDir->Size - 1
+ );
+ } else {
+ //
+ // Set base and end to bypass processing below.
+ //
+ RelocBase = RelocBaseEnd = 0;
+ }
+ }
+ } else {
+ TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);
+ Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase);
+ TeHdr->ImageBase = (UINT64) (BaseAddress);
+ MachineType = TeHdr->Machine;
+
+ //
+ // Find the relocation block
+ //
+ RelocDir = &TeHdr->DataDirectory[0];
+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(
+ ImageContext->ImageAddress +
+ RelocDir->VirtualAddress +
+ sizeof(EFI_TE_IMAGE_HEADER) -
+ TeHdr->StrippedSize
+ );
+ RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);
+ }
+
+ //
+ // Run the relocation information and apply the fixups
+ //
+ FixupData = ImageContext->FixupData;
+ while (RelocBase < RelocBaseEnd) {
+
+ Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));
+ RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
+ if (!(ImageContext->IsTeImage)) {
+ FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);
+ } else {
+ FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +
+ RelocBase->VirtualAddress +
+ sizeof(EFI_TE_IMAGE_HEADER) -
+ TeHdr->StrippedSize
+ );
+ }
+
+ if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||
+ (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress +
+ (UINTN)ImageContext->ImageSize)) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_LOAD_ERROR;
+ }
+
+ //
+ // Run this relocation record
+ //
+ while (Reloc < RelocEnd) {
+
+ Fixup = FixupBase + (*Reloc & 0xFFF);
+ switch ((*Reloc) >> 12) {
+ case EFI_IMAGE_REL_BASED_ABSOLUTE:
+ break;
+
+ case EFI_IMAGE_REL_BASED_HIGH:
+ F16 = (UINT16 *) Fixup;
+ *F16 = (UINT16) (*F16 + ((UINT16) ((UINT32) Adjust >> 16)));
+ if (FixupData != NULL) {
+ *(UINT16 *) FixupData = *F16;
+ FixupData = FixupData + sizeof (UINT16);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_LOW:
+ F16 = (UINT16 *) Fixup;
+ *F16 = (UINT16) (*F16 + (UINT16) Adjust);
+ if (FixupData != NULL) {
+ *(UINT16 *) FixupData = *F16;
+ FixupData = FixupData + sizeof (UINT16);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_HIGHLOW:
+ F32 = (UINT32 *) Fixup;
+ *F32 = *F32 + (UINT32) Adjust;
+ if (FixupData != NULL) {
+ FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
+ *(UINT32 *) FixupData = *F32;
+ FixupData = FixupData + sizeof (UINT32);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_HIGHADJ:
+ //
+ // Return the same EFI_UNSUPPORTED return code as
+ // PeCoffLoaderRelocateImageEx() returns if it does not recognize
+ // the relocation type.
+ //
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_UNSUPPORTED;
+
+ default:
+ switch (MachineType) {
+ case EFI_IMAGE_MACHINE_IA32:
+ case EFI_IMAGE_MACHINE_ARMT:
+ Status = PeCoffLoaderRelocateIa32Image (Reloc, Fixup, &FixupData, Adjust);
+ break;
+ case EFI_IMAGE_MACHINE_X64:
+ Status = PeCoffLoaderRelocateX64Image (Reloc, Fixup, &FixupData, Adjust);
+ break;
+ case EFI_IMAGE_MACHINE_IA64:
+ Status = PeCoffLoaderRelocateIpfImage (Reloc, Fixup, &FixupData, Adjust);
+ break;
+ default:
+ Status = RETURN_UNSUPPORTED;
+ break;
+ }
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return Status;
+ }
+ }
+
+ //
+ // Next relocation record
+ //
+ Reloc += 1;
+ }
+
+ //
+ // Next reloc block
+ //
+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderLoadImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+/*++
+
+Routine Description:
+
+ Loads a PE/COFF image into memory
+
+Arguments:
+
+ This - Calling context
+
+ ImageContext - Contains information on image to load into memory
+
+Returns:
+
+ RETURN_SUCCESS if the PE/COFF image was loaded
+ RETURN_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
+ RETURN_LOAD_ERROR if the image is a runtime driver with no relocations
+ RETURN_INVALID_PARAMETER if the image address is invalid
+
+--*/
+{
+ RETURN_STATUS Status;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
+ EFI_TE_IMAGE_HEADER *TeHdr;
+ PE_COFF_LOADER_IMAGE_CONTEXT CheckContext;
+ EFI_IMAGE_SECTION_HEADER *FirstSection;
+ EFI_IMAGE_SECTION_HEADER *Section;
+ UINTN NumberOfSections;
+ UINTN Index;
+ CHAR8 *Base;
+ CHAR8 *End;
+ CHAR8 *MaxEnd;
+ EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+ UINTN Size;
+ UINT32 TempDebugEntryRva;
+ EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader;
+
+ PeHdr = NULL;
+ TeHdr = NULL;
+ //
+ // Assume success
+ //
+ ImageContext->ImageError = IMAGE_ERROR_SUCCESS;
+
+ //
+ // Copy the provided context info into our local version, get what we
+ // can from the original image, and then use that to make sure everything
+ // is legit.
+ //
+ CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+
+ Status = PeCoffLoaderGetImageInfo (&CheckContext);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Make sure there is enough allocated space for the image being loaded
+ //
+ if (ImageContext->ImageSize < CheckContext.ImageSize) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // If there's no relocations, then make sure it's not a runtime driver,
+ // and that it's being loaded at the linked address.
+ //
+ if (CheckContext.RelocationsStripped) {
+ //
+ // If the image does not contain relocations and it is a runtime driver
+ // then return an error.
+ //
+ if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
+ return RETURN_LOAD_ERROR;
+ }
+ //
+ // If the image does not contain relocations, and the requested load address
+ // is not the linked address, then return an error.
+ //
+ if (CheckContext.ImageAddress != ImageContext->ImageAddress) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
+ return RETURN_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Make sure the allocated space has the proper section alignment
+ //
+ if (!(ImageContext->IsTeImage)) {
+ if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {
+ ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;
+ return RETURN_INVALID_PARAMETER;
+ }
+ }
+ //
+ // Read the entire PE/COFF or TE header into memory
+ //
+ if (!(ImageContext->IsTeImage)) {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &ImageContext->SizeOfHeaders,
+ (VOID *) (UINTN) ImageContext->ImageAddress
+ );
+
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)
+ ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
+
+ OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader);
+
+ FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN)ImageContext->ImageAddress +
+ ImageContext->PeCoffHeaderOffset +
+ sizeof(UINT32) +
+ sizeof(EFI_IMAGE_FILE_HEADER) +
+ PeHdr->Pe32.FileHeader.SizeOfOptionalHeader
+ );
+ NumberOfSections = (UINTN) (PeHdr->Pe32.FileHeader.NumberOfSections);
+ } else {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ 0,
+ &ImageContext->SizeOfHeaders,
+ (VOID *) (UINTN) ImageContext->ImageAddress
+ );
+
+ TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);
+
+ FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINTN)ImageContext->ImageAddress +
+ sizeof(EFI_TE_IMAGE_HEADER)
+ );
+ NumberOfSections = (UINTN) (TeHdr->NumberOfSections);
+
+ }
+
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return RETURN_LOAD_ERROR;
+ }
+
+ //
+ // Load each section of the image
+ //
+ Section = FirstSection;
+ for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {
+
+ //
+ // Compute sections address
+ //
+ Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);
+ End = PeCoffLoaderImageAddress (
+ ImageContext,
+ Section->VirtualAddress + Section->Misc.VirtualSize - 1
+ );
+ if (ImageContext->IsTeImage) {
+ Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);
+ End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);
+ }
+
+ if (End > MaxEnd) {
+ MaxEnd = End;
+ }
+ //
+ // If the base start or end address resolved to 0, then fail.
+ //
+ if ((Base == NULL) || (End == NULL)) {
+ ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;
+ return RETURN_LOAD_ERROR;
+ }
+
+ //
+ // Read the section
+ //
+ Size = (UINTN) Section->Misc.VirtualSize;
+ if ((Size == 0) || (Size > Section->SizeOfRawData)) {
+ Size = (UINTN) Section->SizeOfRawData;
+ }
+
+ if (Section->SizeOfRawData) {
+ if (!(ImageContext->IsTeImage)) {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ Section->PointerToRawData,
+ &Size,
+ Base
+ );
+ } else {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize,
+ &Size,
+ Base
+ );
+ }
+
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return Status;
+ }
+ }
+
+ //
+ // If raw size is less then virt size, zero fill the remaining
+ //
+
+ if (Size < Section->Misc.VirtualSize) {
+ ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);
+ }
+
+ //
+ // Next Section
+ //
+ Section += 1;
+ }
+
+ //
+ // Get image's entry point
+ //
+ if (!(ImageContext->IsTeImage)) {
+ ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (
+ ImageContext,
+ PeHdr->Pe32.OptionalHeader.AddressOfEntryPoint
+ );
+ } else {
+ ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (
+ (UINTN)ImageContext->ImageAddress +
+ (UINTN)TeHdr->AddressOfEntryPoint +
+ (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -
+ (UINTN) TeHdr->StrippedSize
+ );
+ }
+
+ //
+ // Determine the size of the fixup data
+ //
+ // Per the PE/COFF spec, you can't assume that a given data directory
+ // is present in the image. You have to check the NumberOfRvaAndSizes in
+ // the optional header to verify a desired directory entry is there.
+ //
+ if (!(ImageContext->IsTeImage)) {
+ if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)
+ &OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
+ } else {
+ ImageContext->FixupDataSize = 0;
+ }
+ } else {
+ if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)
+ &OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
+ ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
+ } else {
+ ImageContext->FixupDataSize = 0;
+ }
+ }
+ } else {
+ DirectoryEntry = &TeHdr->DataDirectory[0];
+ ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);
+ }
+ //
+ // Consumer must allocate a buffer for the relocation fixup log.
+ // Only used for runtime drivers.
+ //
+ ImageContext->FixupData = NULL;
+
+ //
+ // Load the Codeview info if present
+ //
+ if (ImageContext->DebugDirectoryEntryRva != 0) {
+ if (!(ImageContext->IsTeImage)) {
+ DebugEntry = PeCoffLoaderImageAddress (
+ ImageContext,
+ ImageContext->DebugDirectoryEntryRva
+ );
+ } else {
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
+ ImageContext->ImageAddress +
+ ImageContext->DebugDirectoryEntryRva +
+ sizeof(EFI_TE_IMAGE_HEADER) -
+ TeHdr->StrippedSize
+ );
+ }
+
+ if (DebugEntry != NULL) {
+ TempDebugEntryRva = DebugEntry->RVA;
+ if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {
+ Section--;
+ if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) {
+ TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;
+ } else {
+ TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;
+ }
+ }
+
+ if (TempDebugEntryRva != 0) {
+ if (!(ImageContext->IsTeImage)) {
+ ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);
+ } else {
+ ImageContext->CodeView = (VOID *)(
+ (UINTN)ImageContext->ImageAddress +
+ (UINTN)TempDebugEntryRva +
+ (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -
+ (UINTN) TeHdr->StrippedSize
+ );
+ }
+
+ if (ImageContext->CodeView == NULL) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return RETURN_LOAD_ERROR;
+ }
+
+ if (DebugEntry->RVA == 0) {
+ Size = DebugEntry->SizeOfData;
+ if (!(ImageContext->IsTeImage)) {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugEntry->FileOffset,
+ &Size,
+ ImageContext->CodeView
+ );
+ } else {
+ Status = ImageContext->ImageRead (
+ ImageContext->Handle,
+ DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize,
+ &Size,
+ ImageContext->CodeView
+ );
+ //
+ // Should we apply fix up to this field according to the size difference between PE and TE?
+ // Because now we maintain TE header fields unfixed, this field will also remain as they are
+ // in original PE image.
+ //
+ }
+
+ if (RETURN_ERROR (Status)) {
+ ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ;
+ return RETURN_LOAD_ERROR;
+ }
+
+ DebugEntry->RVA = TempDebugEntryRva;
+ }
+
+ switch (*(UINT32 *) ImageContext->CodeView) {
+ case CODEVIEW_SIGNATURE_NB10:
+ ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+ break;
+
+ case CODEVIEW_SIGNATURE_RSDS:
+ ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Returns a pointer to the PDB file name for a raw PE/COFF image that is not
+ loaded into system memory with the PE/COFF Loader Library functions.
+
+ Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
+ the PE/COFF image specified by Pe32Data is not a valid, then NULL is
+ returned. If the PE/COFF image specified by Pe32Data does not contain a
+ debug directory entry, then NULL is returned. If the debug directory entry
+ in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
+ then NULL is returned.
+ If Pe32Data is NULL, then return NULL.
+
+ @param Pe32Data Pointer to the PE/COFF image that is loaded in system
+ memory.
+
+ @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
+ if it cannot be retrieved.
+
+**/
+VOID *
+EFIAPI
+PeCoffLoaderGetPdbPointer (
+ IN VOID *Pe32Data
+ )
+{
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
+ EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
+ EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+ UINTN DirCount;
+ VOID *CodeViewEntryPointer;
+ INTN TEImageAdjust;
+ UINT32 NumberOfRvaAndSizes;
+ UINT16 Magic;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ UINT32 Index, Index1;
+
+ if (Pe32Data == NULL) {
+ return NULL;
+ }
+
+ TEImageAdjust = 0;
+ DirectoryEntry = NULL;
+ DebugEntry = NULL;
+ NumberOfRvaAndSizes = 0;
+ Index = 0;
+ Index1 = 0;
+ SectionHeader = NULL;
+
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
+ if (EFI_IMAGE_DOS_SIGNATURE == DosHdr->e_magic) {
+ //
+ // DOS image header is present, so read the PE header after the DOS image header.
+ //
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
+ } else {
+ //
+ // DOS image header is not present, so PE header is at the image base.
+ //
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
+ }
+
+ if (EFI_TE_IMAGE_HEADER_SIGNATURE == Hdr.Te->Signature) {
+ if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
+ DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
+ TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
+
+ //
+ // Get the DebugEntry offset in the raw data image.
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (Hdr.Te + 1);
+ Index = Hdr.Te->NumberOfSections;
+ for (Index1 = 0; Index1 < Index; Index1 ++) {
+ if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) &&
+ (DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +
+ DirectoryEntry->VirtualAddress -
+ SectionHeader [Index1].VirtualAddress +
+ SectionHeader [Index1].PointerToRawData +
+ TEImageAdjust);
+ break;
+ }
+ }
+ }
+ } else if (EFI_IMAGE_NT_SIGNATURE == Hdr.Pe32->Signature) {
+ //
+ // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
+ // It is due to backward-compatibility, for some system might
+ // generate PE32+ image with PE32 Magic.
+ //
+ switch (Hdr.Pe32->FileHeader.Machine) {
+ case EFI_IMAGE_MACHINE_IA32:
+ case EFI_IMAGE_MACHINE_ARMT:
+ //
+ // Assume PE32 image with IA32 Machine field.
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ break;
+ case EFI_IMAGE_MACHINE_X64:
+ case EFI_IMAGE_MACHINE_IPF:
+ //
+ // Assume PE32+ image with X64 or IPF Machine field
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ break;
+ default:
+ //
+ // For unknow Machine field, use Magic in optional Header
+ //
+ Magic = Hdr.Pe32->OptionalHeader.Magic;
+ }
+
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
+ (UINT8 *) Hdr.Pe32 +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ Hdr.Pe32->FileHeader.SizeOfOptionalHeader
+ );
+ Index = Hdr.Pe32->FileHeader.NumberOfSections;
+
+ if (EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC == Magic) {
+ //
+ // Use PE32 offset get Debug Directory Entry
+ //
+ NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ //
+ // Use PE32+ offset get Debug Directory Entry
+ //
+ NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
+ DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+ }
+
+ if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG || DirectoryEntry->VirtualAddress == 0) {
+ DirectoryEntry = NULL;
+ DebugEntry = NULL;
+ } else {
+ //
+ // Get the DebugEntry offset in the raw data image.
+ //
+ for (Index1 = 0; Index1 < Index; Index1 ++) {
+ if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) &&
+ (DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {
+ DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (
+ (UINTN) Pe32Data +
+ DirectoryEntry->VirtualAddress -
+ SectionHeader[Index1].VirtualAddress +
+ SectionHeader[Index1].PointerToRawData);
+ break;
+ }
+ }
+ }
+ } else {
+ return NULL;
+ }
+
+ if (NULL == DebugEntry || NULL == DirectoryEntry) {
+ return NULL;
+ }
+
+ //
+ // Scan the directory to find the debug entry.
+ //
+ for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
+ if (EFI_IMAGE_DEBUG_TYPE_CODEVIEW == DebugEntry->Type) {
+ if (DebugEntry->SizeOfData > 0) {
+ //
+ // Get the DebugEntry offset in the raw data image.
+ //
+ for (Index1 = 0; Index1 < Index; Index1 ++) {
+ if ((DebugEntry->RVA >= SectionHeader[Index1].VirtualAddress) &&
+ (DebugEntry->RVA < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {
+ CodeViewEntryPointer = (VOID *) (
+ ((UINTN)Pe32Data) +
+ (UINTN) DebugEntry->RVA -
+ SectionHeader[Index1].VirtualAddress +
+ SectionHeader[Index1].PointerToRawData +
+ (UINTN)TEImageAdjust);
+ break;
+ }
+ }
+ if (Index1 >= Index) {
+ //
+ // Can't find CodeViewEntryPointer in raw PE/COFF image.
+ //
+ continue;
+ }
+ switch (* (UINT32 *) CodeViewEntryPointer) {
+ case CODEVIEW_SIGNATURE_NB10:
+ return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));
+ case CODEVIEW_SIGNATURE_RSDS:
+ return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
diff --git a/BaseTools/Source/C/Common/BinderFuncs.c b/BaseTools/Source/C/Common/BinderFuncs.c
new file mode 100644
index 0000000000..89e75efa3d
--- /dev/null
+++ b/BaseTools/Source/C/Common/BinderFuncs.c
@@ -0,0 +1,87 @@
+/** @file
+
+Copyright (c) 1999 - 2008, 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:
+
+ BinderFuncs.c
+
+Abstract:
+
+ Binder function implementations for ANSI C libraries.
+
+**/
+
+#include "BinderFuncs.h"
+#include "CommonLib.h"
+#include <stdlib.h>
+#include <string.h>
+
+//
+// Binder Function Implementations
+//
+
+VOID *
+CommonLibBinderAllocate (
+ IN UINTN Size
+ )
+{
+ return (VOID *) malloc (Size);
+}
+
+VOID
+CommonLibBinderFree (
+ IN VOID *Pointer
+ )
+{
+ free (Pointer);
+}
+
+VOID
+CommonLibBinderCopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+{
+ memmove (Destination, Source, Length);
+}
+
+VOID
+CommonLibBinderSetMem (
+ IN VOID *Destination,
+ IN UINTN Length,
+ IN UINT8 Value
+ )
+{
+ memset (Destination, Value, Length);
+}
+
+INTN
+CommonLibBinderCompareMem (
+ IN VOID *MemOne,
+ IN VOID *MemTwo,
+ IN UINTN Length
+ )
+{
+ return memcmp (MemOne, MemTwo, Length);
+}
+
+BOOLEAN
+CommonLibBinderCompareGuid (
+ IN EFI_GUID *Guid1,
+ IN EFI_GUID *Guid2
+ )
+{
+ return CompareGuid (Guid1, Guid2) ? FALSE : TRUE;
+}
+
+
+
diff --git a/BaseTools/Source/C/Common/BinderFuncs.h b/BaseTools/Source/C/Common/BinderFuncs.h
new file mode 100644
index 0000000000..779c5a2e06
--- /dev/null
+++ b/BaseTools/Source/C/Common/BinderFuncs.h
@@ -0,0 +1,75 @@
+/** @file
+
+Copyright (c) 1999 - 2008, 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:
+
+ BinderFuncs.h
+
+Abstract:
+
+ Prototypes for binder functions that allow common code to be
+ written which then links to implementation of these functions
+ which is appropriate for the specific environment that they
+ are running under.
+
+**/
+
+#ifndef BinderFuncs_h_INCLUDED
+#define BinderFuncs_h_INCLUDED
+
+#include "Common/UefiBaseTypes.h"
+
+//
+// Binder Function Prototypes
+//
+// These binding functions must be implemented externally as appropriate for
+// the environment that the code will be running under.
+//
+
+VOID *
+CommonLibBinderAllocate (
+ IN UINTN Size
+ );
+
+VOID
+CommonLibBinderFree (
+ IN VOID *Pointer
+ );
+
+VOID
+CommonLibBinderCopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ );
+
+VOID
+CommonLibBinderSetMem (
+ IN VOID *Destination,
+ IN UINTN Length,
+ IN UINT8 Value
+ );
+
+INTN
+CommonLibBinderCompareMem (
+ IN VOID *MemOne,
+ IN VOID *MemTwo,
+ IN UINTN Length
+ );
+
+BOOLEAN
+CommonLibBinderCompareGuid (
+ IN EFI_GUID *Guid1,
+ IN EFI_GUID *Guid2
+ );
+
+#endif // #ifndef CommonLibs_h_INCLUDED
+
diff --git a/BaseTools/Source/C/Common/CommonLib.c b/BaseTools/Source/C/Common/CommonLib.c
new file mode 100644
index 0000000000..970b2af27b
--- /dev/null
+++ b/BaseTools/Source/C/Common/CommonLib.c
@@ -0,0 +1,584 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ CommonLib.c
+
+Abstract:
+
+ Common basic Library Functions
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+VOID
+PeiZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Set Buffer to zero for Size bytes.
+
+Arguments:
+
+ Buffer - Memory to set.
+
+ Size - Number of bytes to set
+
+Returns:
+
+ None
+
+--*/
+{
+ INT8 *Ptr;
+
+ Ptr = Buffer;
+ while (Size--) {
+ *(Ptr++) = 0;
+ }
+}
+
+VOID
+PeiCopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+/*++
+
+Routine Description:
+
+ Copy Length bytes from Source to Destination.
+
+Arguments:
+
+ Destination - Target of copy
+
+ Source - Place to copy from
+
+ Length - Number of bytes to copy
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+
+ Destination8 = Destination;
+ Source8 = Source;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+}
+
+VOID
+ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+{
+ PeiZeroMem (Buffer, Size);
+}
+
+VOID
+CopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+{
+ PeiCopyMem (Destination, Source, Length);
+}
+
+INTN
+CompareGuid (
+ IN EFI_GUID *Guid1,
+ IN EFI_GUID *Guid2
+ )
+/*++
+
+Routine Description:
+
+ Compares to GUIDs
+
+Arguments:
+
+ Guid1 - guid to compare
+ Guid2 - guid to compare
+
+Returns:
+ = 0 if Guid1 == Guid2
+ != 0 if Guid1 != Guid2
+
+--*/
+{
+ INT32 *g1;
+ INT32 *g2;
+ INT32 r;
+
+ //
+ // Compare 32 bits at a time
+ //
+ g1 = (INT32 *) Guid1;
+ g2 = (INT32 *) Guid2;
+
+ r = g1[0] - g2[0];
+ r |= g1[1] - g2[1];
+ r |= g1[2] - g2[2];
+ r |= g1[3] - g2[3];
+
+ return r;
+}
+
+
+EFI_STATUS
+GetFileImage (
+ IN CHAR8 *InputFileName,
+ OUT CHAR8 **InputFileImage,
+ OUT UINT32 *BytesRead
+ )
+/*++
+
+Routine Description:
+
+ This function opens a file and reads it into a memory buffer. The function
+ will allocate the memory buffer and returns the size of the buffer.
+
+Arguments:
+
+ InputFileName The name of the file to read.
+ InputFileImage A pointer to the memory buffer.
+ BytesRead The size of the memory buffer.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+ EFI_OUT_OF_RESOURCES No resource to complete operations.
+
+--*/
+{
+ FILE *InputFile;
+ UINT32 FileSize;
+
+ //
+ // Verify input parameters.
+ //
+ if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Open the file and copy contents into a memory buffer.
+ //
+ //
+ // Open the file
+ //
+ InputFile = fopen (InputFileName, "rb");
+ if (InputFile == NULL) {
+ Error (NULL, 0, 0001, "Error opening the input file", InputFileName);
+ return EFI_ABORTED;
+ }
+ //
+ // Go to the end so that we can determine the file size
+ //
+ if (fseek (InputFile, 0, SEEK_END)) {
+ Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
+ fclose (InputFile);
+ return EFI_ABORTED;
+ }
+ //
+ // Get the file size
+ //
+ FileSize = ftell (InputFile);
+ if (FileSize == -1) {
+ Error (NULL, 0, 0003, "Error parsing the input file", InputFileName);
+ fclose (InputFile);
+ return EFI_ABORTED;
+ }
+ //
+ // Allocate a buffer
+ //
+ *InputFileImage = malloc (FileSize);
+ if (*InputFileImage == NULL) {
+ fclose (InputFile);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Reset to the beginning of the file
+ //
+ if (fseek (InputFile, 0, SEEK_SET)) {
+ Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
+ fclose (InputFile);
+ free (*InputFileImage);
+ *InputFileImage = NULL;
+ return EFI_ABORTED;
+ }
+ //
+ // Read all of the file contents.
+ //
+ *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile);
+ if (*BytesRead != sizeof (UINT8) * FileSize) {
+ Error (NULL, 0, 0004, "Error reading the input file", InputFileName);
+ fclose (InputFile);
+ free (*InputFileImage);
+ *InputFileImage = NULL;
+ return EFI_ABORTED;
+ }
+ //
+ // Close the file
+ //
+ fclose (InputFile);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PutFileImage (
+ IN CHAR8 *OutputFileName,
+ IN CHAR8 *OutputFileImage,
+ IN UINT32 BytesToWrite
+ )
+/*++
+
+Routine Description:
+
+ This function opens a file and writes OutputFileImage into the file.
+
+Arguments:
+
+ OutputFileName The name of the file to write.
+ OutputFileImage A pointer to the memory buffer.
+ BytesToWrite The size of the memory buffer.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+ EFI_OUT_OF_RESOURCES No resource to complete operations.
+
+--*/
+{
+ FILE *OutputFile;
+ UINT32 BytesWrote;
+
+ //
+ // Verify input parameters.
+ //
+ if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Open the file and copy contents into a memory buffer.
+ //
+ //
+ // Open the file
+ //
+ OutputFile = fopen (OutputFileName, "wb");
+ if (OutputFile == NULL) {
+ Error (NULL, 0, 0001, "Error opening the output file", OutputFileName);
+ return EFI_ABORTED;
+ }
+
+ //
+ // Write all of the file contents.
+ //
+ BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile);
+ if (BytesWrote != sizeof (UINT8) * BytesToWrite) {
+ Error (NULL, 0, 0002, "Error writing the output file", OutputFileName);
+ fclose (OutputFile);
+ return EFI_ABORTED;
+ }
+ //
+ // Close the file
+ //
+ fclose (OutputFile);
+
+ return EFI_SUCCESS;
+}
+
+UINT8
+CalculateChecksum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ This function calculates the value needed for a valid UINT8 checksum
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 8 bit checksum value needed.
+
+--*/
+{
+ return (UINT8) (0x100 - CalculateSum8 (Buffer, Size));
+}
+
+UINT8
+CalculateSum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description::
+
+ This function calculates the UINT8 sum for the requested region.
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 8 bit checksum value needed.
+
+--*/
+{
+ UINTN Index;
+ UINT8 Sum;
+
+ Sum = 0;
+
+ //
+ // Perform the byte sum for buffer
+ //
+ for (Index = 0; Index < Size; Index++) {
+ Sum = (UINT8) (Sum + Buffer[Index]);
+ }
+
+ return Sum;
+}
+
+UINT16
+CalculateChecksum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description::
+
+ This function calculates the value needed for a valid UINT16 checksum
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 16 bit checksum value needed.
+
+--*/
+{
+ return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size));
+}
+
+UINT16
+CalculateSum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ This function calculates the UINT16 sum for the requested region.
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 16 bit checksum
+
+--*/
+{
+ UINTN Index;
+ UINT16 Sum;
+
+ Sum = 0;
+
+ //
+ // Perform the word sum for buffer
+ //
+ for (Index = 0; Index < Size; Index++) {
+ Sum = (UINT16) (Sum + Buffer[Index]);
+ }
+
+ return (UINT16) Sum;
+}
+
+EFI_STATUS
+PrintGuid (
+ IN EFI_GUID *Guid
+ )
+/*++
+
+Routine Description:
+
+ This function prints a GUID to STDOUT.
+
+Arguments:
+
+ Guid Pointer to a GUID to print.
+
+Returns:
+
+ EFI_SUCCESS The GUID was printed.
+ EFI_INVALID_PARAMETER The input was NULL.
+
+--*/
+{
+ if (Guid == NULL) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ printf (
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
+ Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PrintGuidToBuffer (
+ IN EFI_GUID *Guid,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 BufferLen,
+ IN BOOLEAN Uppercase
+ )
+/*++
+
+Routine Description:
+
+ This function prints a GUID to a buffer
+
+Arguments:
+
+ Guid - Pointer to a GUID to print.
+ Buffer - Pointer to a user-provided buffer to print to
+ BufferLen - Size of the Buffer
+ Uppercase - If use upper case.
+
+Returns:
+
+ EFI_SUCCESS The GUID was printed.
+ EFI_INVALID_PARAMETER The input was NULL.
+ EFI_BUFFER_TOO_SMALL The input buffer was not big enough
+
+--*/
+{
+ if (Guid == NULL) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferLen < PRINTED_GUID_BUFFER_SIZE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size");
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (Uppercase) {
+ sprintf (
+ (CHAR8 *)Buffer,
+ "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ } else {
+ sprintf (
+ (CHAR8 *)Buffer,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ Guid->Data1,
+ Guid->Data2,
+ Guid->Data3,
+ Guid->Data4[0],
+ Guid->Data4[1],
+ Guid->Data4[2],
+ Guid->Data4[3],
+ Guid->Data4[4],
+ Guid->Data4[5],
+ Guid->Data4[6],
+ Guid->Data4[7]
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+#ifdef __GNUC__
+
+size_t _filelength(int fd)
+{
+ struct stat stat_buf;
+ fstat(fd, &stat_buf);
+ return stat_buf.st_size;
+}
+
+#ifndef __CYGWIN__
+char *strlwr(char *s)
+{
+ char *p = s;
+ for(;*s;s++) {
+ *s = tolower(*s);
+ }
+ return p;
+}
+#endif
+#endif
diff --git a/BaseTools/Source/C/Common/CommonLib.h b/BaseTools/Source/C/Common/CommonLib.h
new file mode 100644
index 0000000000..7e4af036e5
--- /dev/null
+++ b/BaseTools/Source/C/Common/CommonLib.h
@@ -0,0 +1,172 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ CommonLib.h
+
+Abstract:
+
+ Common library assistance routines.
+
+**/
+
+#ifndef _EFI_COMMON_LIB_H
+#define _EFI_COMMON_LIB_H
+
+#include <Common/UefiBaseTypes.h>
+#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination
+//
+// Function declarations
+//
+VOID
+PeiZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+;
+
+VOID
+PeiCopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+;
+
+VOID
+ZeroMem (
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+;
+
+VOID
+CopyMem (
+ IN VOID *Destination,
+ IN VOID *Source,
+ IN UINTN Length
+ )
+;
+
+INTN
+CompareGuid (
+ IN EFI_GUID *Guid1,
+ IN EFI_GUID *Guid2
+ )
+;
+
+EFI_STATUS
+GetFileImage (
+ IN CHAR8 *InputFileName,
+ OUT CHAR8 **InputFileImage,
+ OUT UINT32 *BytesRead
+ )
+;
+
+EFI_STATUS
+PutFileImage (
+ IN CHAR8 *OutputFileName,
+ IN CHAR8 *OutputFileImage,
+ IN UINT32 BytesToWrite
+ )
+;
+/*++
+
+Routine Description:
+
+ This function opens a file and writes OutputFileImage into the file.
+
+Arguments:
+
+ OutputFileName The name of the file to write.
+ OutputFileImage A pointer to the memory buffer.
+ BytesToWrite The size of the memory buffer.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED An error occurred.
+ EFI_OUT_OF_RESOURCES No resource to complete operations.
+
+**/
+
+UINT8
+CalculateChecksum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+;
+
+UINT8
+CalculateSum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+;
+
+UINT16
+CalculateChecksum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+;
+
+UINT16
+CalculateSum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+;
+
+EFI_STATUS
+PrintGuid (
+ IN EFI_GUID *Guid
+ )
+;
+
+#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination
+EFI_STATUS
+PrintGuidToBuffer (
+ IN EFI_GUID *Guid,
+ IN OUT UINT8 *Buffer,
+ IN UINT32 BufferLen,
+ IN BOOLEAN Uppercase
+ )
+;
+
+#define ASSERT(x) assert(x)
+
+#ifdef __GNUC__
+#include <stdio.h>
+#include <sys/stat.h>
+#define stricmp strcasecmp
+#define _stricmp strcasecmp
+#define strnicmp strncasecmp
+#define strcmpi strcasecmp
+size_t _filelength(int fd);
+#ifndef __CYGWIN__
+char *strlwr(char *s);
+#endif
+#endif
+
+//
+// On windows, mkdir only has one parameter.
+// On unix, it has two parameters
+//
+#if defined(__GNUC__)
+#define mkdir(dir, perm) mkdir(dir, perm)
+#else
+#define mkdir(dir, perm) mkdir(dir)
+#endif
+
+#endif
diff --git a/BaseTools/Source/C/Common/Compress.h b/BaseTools/Source/C/Common/Compress.h
new file mode 100644
index 0000000000..10d0c72a16
--- /dev/null
+++ b/BaseTools/Source/C/Common/Compress.h
@@ -0,0 +1,95 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ Compress.h
+
+Abstract:
+
+ Header file for compression routine.
+ Providing both EFI and Tiano Compress algorithms.
+
+**/
+
+#ifndef _COMPRESS_H_
+#define _COMPRESS_H_
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "CommonLib.h"
+#include <Common/UefiBaseTypes.h>
+/*++
+
+Routine Description:
+
+ Tiano compression routine.
+
+--*/
+EFI_STATUS
+TianoCompress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Efi compression routine.
+
+--*/
+EFI_STATUS
+EfiCompress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ )
+;
+
+/*++
+
+Routine Description:
+
+ The compression routine.
+
+Arguments:
+
+ SrcBuffer - The buffer storing the source data
+ SrcSize - The size of source data
+ DstBuffer - The buffer to store the compressed data
+ DstSize - On input, the size of DstBuffer; On output,
+ the size of the actual compressed data.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
+ DstSize contains the size needed.
+ EFI_SUCCESS - Compression is successful.
+ EFI_OUT_OF_RESOURCES - No resource to complete function.
+ EFI_INVALID_PARAMETER - Parameter supplied is wrong.
+
+--*/
+typedef
+EFI_STATUS
+(*COMPRESS_FUNCTION) (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ );
+
+#endif
diff --git a/BaseTools/Source/C/Common/Crc32.c b/BaseTools/Source/C/Common/Crc32.c
new file mode 100644
index 0000000000..f52b51453a
--- /dev/null
+++ b/BaseTools/Source/C/Common/Crc32.c
@@ -0,0 +1,326 @@
+/** @file
+
+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:
+
+ crc32.c
+
+Abstract:
+
+ CalcuateCrc32 routine.
+
+**/
+
+#include <stdlib.h>
+#include "Crc32.h"
+
+UINT32 mCrcTable[256] = {
+ 0x00000000,
+ 0x77073096,
+ 0xEE0E612C,
+ 0x990951BA,
+ 0x076DC419,
+ 0x706AF48F,
+ 0xE963A535,
+ 0x9E6495A3,
+ 0x0EDB8832,
+ 0x79DCB8A4,
+ 0xE0D5E91E,
+ 0x97D2D988,
+ 0x09B64C2B,
+ 0x7EB17CBD,
+ 0xE7B82D07,
+ 0x90BF1D91,
+ 0x1DB71064,
+ 0x6AB020F2,
+ 0xF3B97148,
+ 0x84BE41DE,
+ 0x1ADAD47D,
+ 0x6DDDE4EB,
+ 0xF4D4B551,
+ 0x83D385C7,
+ 0x136C9856,
+ 0x646BA8C0,
+ 0xFD62F97A,
+ 0x8A65C9EC,
+ 0x14015C4F,
+ 0x63066CD9,
+ 0xFA0F3D63,
+ 0x8D080DF5,
+ 0x3B6E20C8,
+ 0x4C69105E,
+ 0xD56041E4,
+ 0xA2677172,
+ 0x3C03E4D1,
+ 0x4B04D447,
+ 0xD20D85FD,
+ 0xA50AB56B,
+ 0x35B5A8FA,
+ 0x42B2986C,
+ 0xDBBBC9D6,
+ 0xACBCF940,
+ 0x32D86CE3,
+ 0x45DF5C75,
+ 0xDCD60DCF,
+ 0xABD13D59,
+ 0x26D930AC,
+ 0x51DE003A,
+ 0xC8D75180,
+ 0xBFD06116,
+ 0x21B4F4B5,
+ 0x56B3C423,
+ 0xCFBA9599,
+ 0xB8BDA50F,
+ 0x2802B89E,
+ 0x5F058808,
+ 0xC60CD9B2,
+ 0xB10BE924,
+ 0x2F6F7C87,
+ 0x58684C11,
+ 0xC1611DAB,
+ 0xB6662D3D,
+ 0x76DC4190,
+ 0x01DB7106,
+ 0x98D220BC,
+ 0xEFD5102A,
+ 0x71B18589,
+ 0x06B6B51F,
+ 0x9FBFE4A5,
+ 0xE8B8D433,
+ 0x7807C9A2,
+ 0x0F00F934,
+ 0x9609A88E,
+ 0xE10E9818,
+ 0x7F6A0DBB,
+ 0x086D3D2D,
+ 0x91646C97,
+ 0xE6635C01,
+ 0x6B6B51F4,
+ 0x1C6C6162,
+ 0x856530D8,
+ 0xF262004E,
+ 0x6C0695ED,
+ 0x1B01A57B,
+ 0x8208F4C1,
+ 0xF50FC457,
+ 0x65B0D9C6,
+ 0x12B7E950,
+ 0x8BBEB8EA,
+ 0xFCB9887C,
+ 0x62DD1DDF,
+ 0x15DA2D49,
+ 0x8CD37CF3,
+ 0xFBD44C65,
+ 0x4DB26158,
+ 0x3AB551CE,
+ 0xA3BC0074,
+ 0xD4BB30E2,
+ 0x4ADFA541,
+ 0x3DD895D7,
+ 0xA4D1C46D,
+ 0xD3D6F4FB,
+ 0x4369E96A,
+ 0x346ED9FC,
+ 0xAD678846,
+ 0xDA60B8D0,
+ 0x44042D73,
+ 0x33031DE5,
+ 0xAA0A4C5F,
+ 0xDD0D7CC9,
+ 0x5005713C,
+ 0x270241AA,
+ 0xBE0B1010,
+ 0xC90C2086,
+ 0x5768B525,
+ 0x206F85B3,
+ 0xB966D409,
+ 0xCE61E49F,
+ 0x5EDEF90E,
+ 0x29D9C998,
+ 0xB0D09822,
+ 0xC7D7A8B4,
+ 0x59B33D17,
+ 0x2EB40D81,
+ 0xB7BD5C3B,
+ 0xC0BA6CAD,
+ 0xEDB88320,
+ 0x9ABFB3B6,
+ 0x03B6E20C,
+ 0x74B1D29A,
+ 0xEAD54739,
+ 0x9DD277AF,
+ 0x04DB2615,
+ 0x73DC1683,
+ 0xE3630B12,
+ 0x94643B84,
+ 0x0D6D6A3E,
+ 0x7A6A5AA8,
+ 0xE40ECF0B,
+ 0x9309FF9D,
+ 0x0A00AE27,
+ 0x7D079EB1,
+ 0xF00F9344,
+ 0x8708A3D2,
+ 0x1E01F268,
+ 0x6906C2FE,
+ 0xF762575D,
+ 0x806567CB,
+ 0x196C3671,
+ 0x6E6B06E7,
+ 0xFED41B76,
+ 0x89D32BE0,
+ 0x10DA7A5A,
+ 0x67DD4ACC,
+ 0xF9B9DF6F,
+ 0x8EBEEFF9,
+ 0x17B7BE43,
+ 0x60B08ED5,
+ 0xD6D6A3E8,
+ 0xA1D1937E,
+ 0x38D8C2C4,
+ 0x4FDFF252,
+ 0xD1BB67F1,
+ 0xA6BC5767,
+ 0x3FB506DD,
+ 0x48B2364B,
+ 0xD80D2BDA,
+ 0xAF0A1B4C,
+ 0x36034AF6,
+ 0x41047A60,
+ 0xDF60EFC3,
+ 0xA867DF55,
+ 0x316E8EEF,
+ 0x4669BE79,
+ 0xCB61B38C,
+ 0xBC66831A,
+ 0x256FD2A0,
+ 0x5268E236,
+ 0xCC0C7795,
+ 0xBB0B4703,
+ 0x220216B9,
+ 0x5505262F,
+ 0xC5BA3BBE,
+ 0xB2BD0B28,
+ 0x2BB45A92,
+ 0x5CB36A04,
+ 0xC2D7FFA7,
+ 0xB5D0CF31,
+ 0x2CD99E8B,
+ 0x5BDEAE1D,
+ 0x9B64C2B0,
+ 0xEC63F226,
+ 0x756AA39C,
+ 0x026D930A,
+ 0x9C0906A9,
+ 0xEB0E363F,
+ 0x72076785,
+ 0x05005713,
+ 0x95BF4A82,
+ 0xE2B87A14,
+ 0x7BB12BAE,
+ 0x0CB61B38,
+ 0x92D28E9B,
+ 0xE5D5BE0D,
+ 0x7CDCEFB7,
+ 0x0BDBDF21,
+ 0x86D3D2D4,
+ 0xF1D4E242,
+ 0x68DDB3F8,
+ 0x1FDA836E,
+ 0x81BE16CD,
+ 0xF6B9265B,
+ 0x6FB077E1,
+ 0x18B74777,
+ 0x88085AE6,
+ 0xFF0F6A70,
+ 0x66063BCA,
+ 0x11010B5C,
+ 0x8F659EFF,
+ 0xF862AE69,
+ 0x616BFFD3,
+ 0x166CCF45,
+ 0xA00AE278,
+ 0xD70DD2EE,
+ 0x4E048354,
+ 0x3903B3C2,
+ 0xA7672661,
+ 0xD06016F7,
+ 0x4969474D,
+ 0x3E6E77DB,
+ 0xAED16A4A,
+ 0xD9D65ADC,
+ 0x40DF0B66,
+ 0x37D83BF0,
+ 0xA9BCAE53,
+ 0xDEBB9EC5,
+ 0x47B2CF7F,
+ 0x30B5FFE9,
+ 0xBDBDF21C,
+ 0xCABAC28A,
+ 0x53B39330,
+ 0x24B4A3A6,
+ 0xBAD03605,
+ 0xCDD70693,
+ 0x54DE5729,
+ 0x23D967BF,
+ 0xB3667A2E,
+ 0xC4614AB8,
+ 0x5D681B02,
+ 0x2A6F2B94,
+ 0xB40BBE37,
+ 0xC30C8EA1,
+ 0x5A05DF1B,
+ 0x2D02EF8D
+};
+
+EFI_STATUS
+CalculateCrc32 (
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN OUT UINT32 *CrcOut
+ )
+/*++
+
+Routine Description:
+
+ The CalculateCrc32 routine.
+
+Arguments:
+
+ Data - The buffer contaning the data to be processed
+ DataSize - The size of data to be processed
+ CrcOut - A pointer to the caller allocated UINT32 that on
+ contains the CRC32 checksum of Data
+
+Returns:
+
+ EFI_SUCCESS - Calculation is successful.
+ EFI_INVALID_PARAMETER - Data / CrcOut = NULL, or DataSize = 0
+
+--*/
+{
+ UINT32 Crc;
+ UINTN Index;
+ UINT8 *Ptr;
+
+ if ((DataSize == 0) || (Data == NULL) || (CrcOut == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Crc = 0xffffffff;
+ for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {
+ Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr];
+ }
+
+ *CrcOut = Crc ^ 0xffffffff;
+
+ return EFI_SUCCESS;
+}
diff --git a/BaseTools/Source/C/Common/Crc32.h b/BaseTools/Source/C/Common/Crc32.h
new file mode 100644
index 0000000000..e598a916a0
--- /dev/null
+++ b/BaseTools/Source/C/Common/Crc32.h
@@ -0,0 +1,54 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ Crc32.h
+
+Abstract:
+
+ Header file for CalcuateCrc32 routine
+
+**/
+
+#ifndef _CRC32_H
+#define _CRC32_H
+
+#include <Common/UefiBaseTypes.h>
+
+EFI_STATUS
+CalculateCrc32 (
+ IN UINT8 *Data,
+ IN UINTN DataSize,
+ IN OUT UINT32 *CrcOut
+ )
+/*++
+
+Routine Description:
+
+ The CalculateCrc32 routine.
+
+Arguments:
+
+ Data - The buffer contaning the data to be processed
+ DataSize - The size of data to be processed
+ CrcOut - A pointer to the caller allocated UINT32 that on
+ contains the CRC32 checksum of Data
+
+Returns:
+
+ EFI_SUCCESS - Calculation is successful.
+ EFI_INVALID_PARAMETER - Data / CrcOut = NULL, or DataSize = 0
+
+--*/
+;
+
+#endif
diff --git a/BaseTools/Source/C/Common/Decompress.c b/BaseTools/Source/C/Common/Decompress.c
new file mode 100644
index 0000000000..8ccb21f211
--- /dev/null
+++ b/BaseTools/Source/C/Common/Decompress.c
@@ -0,0 +1,982 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ Decompress.c
+
+Abstract:
+
+ Decompressor. Algorithm Ported from OPSD code (Decomp.asm)
+ for Efi and Tiano compress algorithm.
+
+--*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "Decompress.h"
+
+//
+// Decompression algorithm begins here
+//
+#define BITBUFSIZ 32
+#define MAXMATCH 256
+#define THRESHOLD 3
+#define CODE_BIT 16
+#define BAD_TABLE - 1
+
+//
+// C: Char&Len Set; P: Position Set; T: exTra Set
+//
+#define NC (0xff + MAXMATCH + 2 - THRESHOLD)
+#define CBIT 9
+#define EFIPBIT 4
+#define MAXPBIT 5
+#define TBIT 5
+#define MAXNP ((1U << MAXPBIT) - 1)
+#define NT (CODE_BIT + 3)
+#if NT > MAXNP
+#define NPT NT
+#else
+#define NPT MAXNP
+#endif
+
+typedef struct {
+ UINT8 *mSrcBase; // Starting address of compressed data
+ UINT8 *mDstBase; // Starting address of decompressed data
+ UINT32 mOutBuf;
+ UINT32 mInBuf;
+
+ UINT16 mBitCount;
+ UINT32 mBitBuf;
+ UINT32 mSubBitBuf;
+ UINT16 mBlockSize;
+ UINT32 mCompSize;
+ UINT32 mOrigSize;
+
+ UINT16 mBadTableFlag;
+
+ UINT16 mLeft[2 * NC - 1];
+ UINT16 mRight[2 * NC - 1];
+ UINT8 mCLen[NC];
+ UINT8 mPTLen[NPT];
+ UINT16 mCTable[4096];
+ UINT16 mPTTable[256];
+} SCRATCH_DATA;
+
+STATIC UINT16 mPbit = EFIPBIT;
+
+STATIC
+VOID
+FillBuf (
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 NumOfBits
+ )
+/*++
+
+Routine Description:
+
+ Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source.
+
+Arguments:
+
+ Sd - The global scratch data
+ NumOfBit - The number of bits to shift and read.
+
+Returns: (VOID)
+
+--*/
+{
+ Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits);
+
+ while (NumOfBits > Sd->mBitCount) {
+
+ Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount)));
+
+ if (Sd->mCompSize > 0) {
+ //
+ // Get 1 byte into SubBitBuf
+ //
+ Sd->mCompSize--;
+ Sd->mSubBitBuf = 0;
+ Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++];
+ Sd->mBitCount = 8;
+
+ } else {
+ //
+ // No more bits from the source, just pad zero bit.
+ //
+ Sd->mSubBitBuf = 0;
+ Sd->mBitCount = 8;
+
+ }
+ }
+
+ Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits);
+ Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount;
+}
+
+STATIC
+UINT32
+GetBits (
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 NumOfBits
+ )
+/*++
+
+Routine Description:
+
+ Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent
+ NumOfBits of bits from source. Returns NumOfBits of bits that are
+ popped out.
+
+Arguments:
+
+ Sd - The global scratch data.
+ NumOfBits - The number of bits to pop and read.
+
+Returns:
+
+ The bits that are popped out.
+
+--*/
+{
+ UINT32 OutBits;
+
+ OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits));
+
+ FillBuf (Sd, NumOfBits);
+
+ return OutBits;
+}
+
+STATIC
+UINT16
+MakeTable (
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 NumOfChar,
+ IN UINT8 *BitLen,
+ IN UINT16 TableBits,
+ OUT UINT16 *Table
+ )
+/*++
+
+Routine Description:
+
+ Creates Huffman Code mapping table according to code length array.
+
+Arguments:
+
+ Sd - The global scratch data
+ NumOfChar - Number of symbols in the symbol set
+ BitLen - Code length array
+ TableBits - The width of the mapping table
+ Table - The table
+
+Returns:
+
+ 0 - OK.
+ BAD_TABLE - The table is corrupted.
+
+--*/
+{
+ UINT16 Count[17];
+ UINT16 Weight[17];
+ UINT16 Start[18];
+ UINT16 *Pointer;
+ UINT16 Index3;
+ UINT16 Index;
+ UINT16 Len;
+ UINT16 Char;
+ UINT16 JuBits;
+ UINT16 Avail;
+ UINT16 NextCode;
+ UINT16 Mask;
+
+ for (Index = 1; Index <= 16; Index++) {
+ Count[Index] = 0;
+ }
+
+ for (Index = 0; Index < NumOfChar; Index++) {
+ Count[BitLen[Index]]++;
+ }
+
+ Start[1] = 0;
+
+ for (Index = 1; Index <= 16; Index++) {
+ Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index)));
+ }
+
+ if (Start[17] != 0) {
+ /*(1U << 16)*/
+ return (UINT16) BAD_TABLE;
+ }
+
+ JuBits = (UINT16) (16 - TableBits);
+
+ for (Index = 1; Index <= TableBits; Index++) {
+ Start[Index] >>= JuBits;
+ Weight[Index] = (UINT16) (1U << (TableBits - Index));
+ }
+
+ while (Index <= 16) {
+ Weight[Index] = (UINT16) (1U << (16 - Index));
+ Index++;
+ }
+
+ Index = (UINT16) (Start[TableBits + 1] >> JuBits);
+
+ if (Index != 0) {
+ Index3 = (UINT16) (1U << TableBits);
+ while (Index != Index3) {
+ Table[Index++] = 0;
+ }
+ }
+
+ Avail = NumOfChar;
+ Mask = (UINT16) (1U << (15 - TableBits));
+
+ for (Char = 0; Char < NumOfChar; Char++) {
+
+ Len = BitLen[Char];
+ if (Len == 0) {
+ continue;
+ }
+
+ NextCode = (UINT16) (Start[Len] + Weight[Len]);
+
+ if (Len <= TableBits) {
+
+ for (Index = Start[Len]; Index < NextCode; Index++) {
+ Table[Index] = Char;
+ }
+
+ } else {
+
+ Index3 = Start[Len];
+ Pointer = &Table[Index3 >> JuBits];
+ Index = (UINT16) (Len - TableBits);
+
+ while (Index != 0) {
+ if (*Pointer == 0) {
+ Sd->mRight[Avail] = Sd->mLeft[Avail] = 0;
+ *Pointer = Avail++;
+ }
+
+ if (Index3 & Mask) {
+ Pointer = &Sd->mRight[*Pointer];
+ } else {
+ Pointer = &Sd->mLeft[*Pointer];
+ }
+
+ Index3 <<= 1;
+ Index--;
+ }
+
+ *Pointer = Char;
+
+ }
+
+ Start[Len] = NextCode;
+ }
+ //
+ // Succeeds
+ //
+ return 0;
+}
+
+STATIC
+UINT32
+DecodeP (
+ IN SCRATCH_DATA *Sd
+ )
+/*++
+
+Routine Description:
+
+ Decodes a position value.
+
+Arguments:
+
+ Sd - the global scratch data
+
+Returns:
+
+ The position value decoded.
+
+--*/
+{
+ UINT16 Val;
+ UINT32 Mask;
+ UINT32 Pos;
+
+ Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
+
+ if (Val >= MAXNP) {
+ Mask = 1U << (BITBUFSIZ - 1 - 8);
+
+ do {
+
+ if (Sd->mBitBuf & Mask) {
+ Val = Sd->mRight[Val];
+ } else {
+ Val = Sd->mLeft[Val];
+ }
+
+ Mask >>= 1;
+ } while (Val >= MAXNP);
+ }
+ //
+ // Advance what we have read
+ //
+ FillBuf (Sd, Sd->mPTLen[Val]);
+
+ Pos = Val;
+ if (Val > 1) {
+ Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1)));
+ }
+
+ return Pos;
+}
+
+STATIC
+UINT16
+ReadPTLen (
+ IN SCRATCH_DATA *Sd,
+ IN UINT16 nn,
+ IN UINT16 nbit,
+ IN UINT16 Special
+ )
+/*++
+
+Routine Description:
+
+ Reads code lengths for the Extra Set or the Position Set
+
+Arguments:
+
+ Sd - The global scratch data
+ nn - Number of symbols
+ nbit - Number of bits needed to represent nn
+ Special - The special symbol that needs to be taken care of
+
+Returns:
+
+ 0 - OK.
+ BAD_TABLE - Table is corrupted.
+
+--*/
+{
+ UINT16 Number;
+ UINT16 CharC;
+ UINT16 Index;
+ UINT32 Mask;
+
+ Number = (UINT16) GetBits (Sd, nbit);
+
+ if (Number == 0) {
+ CharC = (UINT16) GetBits (Sd, nbit);
+
+ for (Index = 0; Index < 256; Index++) {
+ Sd->mPTTable[Index] = CharC;
+ }
+
+ for (Index = 0; Index < nn; Index++) {
+ Sd->mPTLen[Index] = 0;
+ }
+
+ return 0;
+ }
+
+ Index = 0;
+
+ while (Index < Number) {
+
+ CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3));
+
+ if (CharC == 7) {
+ Mask = 1U << (BITBUFSIZ - 1 - 3);
+ while (Mask & Sd->mBitBuf) {
+ Mask >>= 1;
+ CharC += 1;
+ }
+ }
+
+ FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3));
+
+ Sd->mPTLen[Index++] = (UINT8) CharC;
+
+ if (Index == Special) {
+ CharC = (UINT16) GetBits (Sd, 2);
+ CharC--;
+ while ((INT16) (CharC) >= 0) {
+ Sd->mPTLen[Index++] = 0;
+ CharC--;
+ }
+ }
+ }
+
+ while (Index < nn) {
+ Sd->mPTLen[Index++] = 0;
+ }
+
+ return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable);
+}
+
+STATIC
+VOID
+ReadCLen (
+ SCRATCH_DATA *Sd
+ )
+/*++
+
+Routine Description:
+
+ Reads code lengths for Char&Len Set.
+
+Arguments:
+
+ Sd - the global scratch data
+
+Returns: (VOID)
+
+--*/
+{
+ UINT16 Number;
+ UINT16 CharC;
+ UINT16 Index;
+ UINT32 Mask;
+
+ Number = (UINT16) GetBits (Sd, CBIT);
+
+ if (Number == 0) {
+ CharC = (UINT16) GetBits (Sd, CBIT);
+
+ for (Index = 0; Index < NC; Index++) {
+ Sd->mCLen[Index] = 0;
+ }
+
+ for (Index = 0; Index < 4096; Index++) {
+ Sd->mCTable[Index] = CharC;
+ }
+
+ return ;
+ }
+
+ Index = 0;
+ while (Index < Number) {
+
+ CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)];
+ if (CharC >= NT) {
+ Mask = 1U << (BITBUFSIZ - 1 - 8);
+
+ do {
+
+ if (Mask & Sd->mBitBuf) {
+ CharC = Sd->mRight[CharC];
+ } else {
+ CharC = Sd->mLeft[CharC];
+ }
+
+ Mask >>= 1;
+
+ } while (CharC >= NT);
+ }
+ //
+ // Advance what we have read
+ //
+ FillBuf (Sd, Sd->mPTLen[CharC]);
+
+ if (CharC <= 2) {
+
+ if (CharC == 0) {
+ CharC = 1;
+ } else if (CharC == 1) {
+ CharC = (UINT16) (GetBits (Sd, 4) + 3);
+ } else if (CharC == 2) {
+ CharC = (UINT16) (GetBits (Sd, CBIT) + 20);
+ }
+
+ CharC--;
+ while ((INT16) (CharC) >= 0) {
+ Sd->mCLen[Index++] = 0;
+ CharC--;
+ }
+
+ } else {
+
+ Sd->mCLen[Index++] = (UINT8) (CharC - 2);
+
+ }
+ }
+
+ while (Index < NC) {
+ Sd->mCLen[Index++] = 0;
+ }
+
+ MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable);
+
+ return ;
+}
+
+STATIC
+UINT16
+DecodeC (
+ SCRATCH_DATA *Sd
+ )
+/*++
+
+Routine Description:
+
+ Decode a character/length value.
+
+Arguments:
+
+ Sd - The global scratch data.
+
+Returns:
+
+ The value decoded.
+
+--*/
+{
+ UINT16 Index2;
+ UINT32 Mask;
+
+ if (Sd->mBlockSize == 0) {
+ //
+ // Starting a new block
+ //
+ Sd->mBlockSize = (UINT16) GetBits (Sd, 16);
+ Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3);
+ if (Sd->mBadTableFlag != 0) {
+ return 0;
+ }
+
+ ReadCLen (Sd);
+
+ Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, mPbit, (UINT16) (-1));
+ if (Sd->mBadTableFlag != 0) {
+ return 0;
+ }
+ }
+
+ Sd->mBlockSize--;
+ Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)];
+
+ if (Index2 >= NC) {
+ Mask = 1U << (BITBUFSIZ - 1 - 12);
+
+ do {
+ if (Sd->mBitBuf & Mask) {
+ Index2 = Sd->mRight[Index2];
+ } else {
+ Index2 = Sd->mLeft[Index2];
+ }
+
+ Mask >>= 1;
+ } while (Index2 >= NC);
+ }
+ //
+ // Advance what we have read
+ //
+ FillBuf (Sd, Sd->mCLen[Index2]);
+
+ return Index2;
+}
+
+STATIC
+VOID
+Decode (
+ SCRATCH_DATA *Sd
+ )
+/*++
+
+Routine Description:
+
+ Decode the source data and put the resulting data into the destination buffer.
+
+Arguments:
+
+ Sd - The global scratch data
+
+Returns: (VOID)
+
+ --*/
+{
+ UINT16 BytesRemain;
+ UINT32 DataIdx;
+ UINT16 CharC;
+
+ BytesRemain = (UINT16) (-1);
+
+ DataIdx = 0;
+
+ for (;;) {
+ CharC = DecodeC (Sd);
+ if (Sd->mBadTableFlag != 0) {
+ return ;
+ }
+
+ if (CharC < 256) {
+ //
+ // Process an Original character
+ //
+ Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC;
+ if (Sd->mOutBuf >= Sd->mOrigSize) {
+ return ;
+ }
+
+ } else {
+ //
+ // Process a Pointer
+ //
+ CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD));
+
+ BytesRemain = CharC;
+
+ DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1;
+
+ BytesRemain--;
+ while ((INT16) (BytesRemain) >= 0) {
+ Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
+ if (Sd->mOutBuf >= Sd->mOrigSize) {
+ return ;
+ }
+
+ BytesRemain--;
+ }
+ }
+ }
+
+ return ;
+}
+
+EFI_STATUS
+GetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ UINT8 *Src;
+
+ *ScratchSize = sizeof (SCRATCH_DATA);
+
+ Src = Source;
+ if (SrcSize < 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+Decompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation Efi and Tiano Decompress().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ UINT32 Index;
+ UINT32 CompSize;
+ UINT32 OrigSize;
+ EFI_STATUS Status;
+ SCRATCH_DATA *Sd;
+ UINT8 *Src;
+ UINT8 *Dst;
+
+ Status = EFI_SUCCESS;
+ Src = Source;
+ Dst = Destination;
+
+ if (ScratchSize < sizeof (SCRATCH_DATA)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Sd = (SCRATCH_DATA *) Scratch;
+
+ if (SrcSize < 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
+ OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
+
+ if (SrcSize < CompSize + 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DstSize != OrigSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Src = Src + 8;
+
+ for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) {
+ ((UINT8 *) Sd)[Index] = 0;
+ }
+
+ Sd->mSrcBase = Src;
+ Sd->mDstBase = Dst;
+ Sd->mCompSize = CompSize;
+ Sd->mOrigSize = OrigSize;
+
+ //
+ // Fill the first BITBUFSIZ bits
+ //
+ FillBuf (Sd, BITBUFSIZ);
+
+ //
+ // Decompress it
+ //
+ Decode (Sd);
+
+ if (Sd->mBadTableFlag != 0) {
+ //
+ // Something wrong with the source
+ //
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+EfiGetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation Efi Decompress GetInfo().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ return GetInfo (Source, SrcSize, DstSize, ScratchSize);
+}
+
+EFI_STATUS
+TianoGetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation Tiano Decompress GetInfo().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ return GetInfo (Source, SrcSize, DstSize, ScratchSize);
+}
+
+EFI_STATUS
+EfiDecompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation of Efi Decompress().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ mPbit = EFIPBIT;
+ return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize);
+}
+
+EFI_STATUS
+TianoDecompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ )
+/*++
+
+Routine Description:
+
+ The implementation of Tiano Decompress().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ mPbit = MAXPBIT;
+ return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize);
+}
+
+EFI_STATUS
+Extract (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT VOID **Destination,
+ OUT UINT32 *DstSize,
+ IN UINTN Algorithm
+ )
+{
+ VOID *Scratch;
+ UINT32 ScratchSize;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ switch (Algorithm) {
+ case 0:
+ *Destination = (VOID *)malloc(SrcSize);
+ if (*Destination != NULL) {
+ memcpy(*Destination, Source, SrcSize);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ break;
+ case 1:
+ Status = EfiGetInfo(Source, SrcSize, DstSize, &ScratchSize);
+ if (Status == EFI_SUCCESS) {
+ Scratch = (VOID *)malloc(ScratchSize);
+ *Destination = (VOID *)malloc(*DstSize);
+ if (Scratch != NULL && *Destination != NULL) {
+ Status = EfiDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+ break;
+ case 2:
+ Status = TianoGetInfo(Source, SrcSize, DstSize, &ScratchSize);
+ if (Status == EFI_SUCCESS) {
+ Scratch = (VOID *)malloc(ScratchSize);
+ *Destination = (VOID *)malloc(*DstSize);
+ if (Scratch != NULL && *Destination != NULL) {
+ Status = TianoDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+ break;
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+
diff --git a/BaseTools/Source/C/Common/Decompress.h b/BaseTools/Source/C/Common/Decompress.h
new file mode 100644
index 0000000000..3d5c0cd54d
--- /dev/null
+++ b/BaseTools/Source/C/Common/Decompress.h
@@ -0,0 +1,172 @@
+/** @file
+
+Copyright (c) 2006 - 2008, 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:
+
+ Decompress.h
+
+Abstract:
+
+ Header file for compression routine
+
+**/
+
+#ifndef _EFI_DECOMPRESS_H
+#define _EFI_DECOMPRESS_H
+
+#include <Common/UefiBaseTypes.h>
+
+EFI_STATUS
+EfiGetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ );
+/**
+
+Routine Description:
+
+ The implementation Efi Decompress GetInfo().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+**/
+
+EFI_STATUS
+EfiDecompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ );
+/**
+
+Routine Description:
+
+ The implementation of Efi Decompress().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+**/
+
+EFI_STATUS
+TianoGetInfo (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ );
+/**
+
+Routine Description:
+
+ The implementation Tiano Decompress GetInfo().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ DstSize - The size of destination buffer.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+**/
+
+EFI_STATUS
+TianoDecompress (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ );
+/**
+
+Routine Description:
+
+ The implementation of Tiano Decompress().
+
+Arguments:
+
+ Source - The source buffer containing the compressed data.
+ SrcSize - The size of source buffer
+ Destination - The destination buffer to store the decompressed data
+ DstSize - The size of destination buffer.
+ Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
+ ScratchSize - The size of scratch buffer.
+
+Returns:
+
+ EFI_SUCCESS - Decompression is successfull
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+**/
+
+typedef
+EFI_STATUS
+(*GETINFO_FUNCTION) (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT UINT32 *DstSize,
+ OUT UINT32 *ScratchSize
+ );
+
+typedef
+EFI_STATUS
+(*DECOMPRESS_FUNCTION) (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ IN OUT VOID *Destination,
+ IN UINT32 DstSize,
+ IN OUT VOID *Scratch,
+ IN UINT32 ScratchSize
+ );
+
+EFI_STATUS
+Extract (
+ IN VOID *Source,
+ IN UINT32 SrcSize,
+ OUT VOID **Destination,
+ OUT UINT32 *DstSize,
+ IN UINTN Algorithm
+ );
+
+#endif
diff --git a/BaseTools/Source/C/Common/EfiCompress.c b/BaseTools/Source/C/Common/EfiCompress.c
new file mode 100644
index 0000000000..aafa9c6e24
--- /dev/null
+++ b/BaseTools/Source/C/Common/EfiCompress.c
@@ -0,0 +1,1598 @@
+/** @file
+
+Copyright (c) 2006 - 2008, 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:
+
+ EfiCompress.c
+
+Abstract:
+
+ Compression routine. The compression algorithm is a mixture of
+ LZ77 and Huffman coding. LZ77 transforms the source data into a
+ sequence of Original Characters and Pointers to repeated strings.
+ This sequence is further divided into Blocks and Huffman codings
+ are applied to each Block.
+
+**/
+
+#include "Compress.h"
+
+
+//
+// Macro Definitions
+//
+
+#undef UINT8_MAX
+typedef INT16 NODE;
+#define UINT8_MAX 0xff
+#define UINT8_BIT 8
+#define THRESHOLD 3
+#define INIT_CRC 0
+#define WNDBIT 13
+#define WNDSIZ (1U << WNDBIT)
+#define MAXMATCH 256
+#define PERC_FLAG 0x8000U
+#define CODE_BIT 16
+#define NIL 0
+#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
+#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
+#define CRCPOLY 0xA001
+#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
+
+//
+// C: the Char&Len Set; P: the Position Set; T: the exTra Set
+//
+
+#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
+#define CBIT 9
+#define NP (WNDBIT + 1)
+#define PBIT 4
+#define NT (CODE_BIT + 3)
+#define TBIT 5
+#if NT > NP
+ #define NPT NT
+#else
+ #define NPT NP
+#endif
+
+//
+// Function Prototypes
+//
+
+STATIC
+VOID
+PutDword(
+ IN UINT32 Data
+ );
+
+STATIC
+EFI_STATUS
+AllocateMemory (
+ );
+
+STATIC
+VOID
+FreeMemory (
+ );
+
+STATIC
+VOID
+InitSlide (
+ );
+
+STATIC
+NODE
+Child (
+ IN NODE q,
+ IN UINT8 c
+ );
+
+STATIC
+VOID
+MakeChild (
+ IN NODE q,
+ IN UINT8 c,
+ IN NODE r
+ );
+
+STATIC
+VOID
+Split (
+ IN NODE Old
+ );
+
+STATIC
+VOID
+InsertNode (
+ );
+
+STATIC
+VOID
+DeleteNode (
+ );
+
+STATIC
+VOID
+GetNextMatch (
+ );
+
+STATIC
+EFI_STATUS
+Encode (
+ );
+
+STATIC
+VOID
+CountTFreq (
+ );
+
+STATIC
+VOID
+WritePTLen (
+ IN INT32 n,
+ IN INT32 nbit,
+ IN INT32 Special
+ );
+
+STATIC
+VOID
+WriteCLen (
+ );
+
+STATIC
+VOID
+EncodeC (
+ IN INT32 c
+ );
+
+STATIC
+VOID
+EncodeP (
+ IN UINT32 p
+ );
+
+STATIC
+VOID
+SendBlock (
+ );
+
+STATIC
+VOID
+Output (
+ IN UINT32 c,
+ IN UINT32 p
+ );
+
+STATIC
+VOID
+HufEncodeStart (
+ );
+
+STATIC
+VOID
+HufEncodeEnd (
+ );
+
+STATIC
+VOID
+MakeCrcTable (
+ );
+
+STATIC
+VOID
+PutBits (
+ IN INT32 n,
+ IN UINT32 x
+ );
+
+STATIC
+INT32
+FreadCrc (
+ OUT UINT8 *p,
+ IN INT32 n
+ );
+
+STATIC
+VOID
+InitPutBits (
+ );
+
+STATIC
+VOID
+CountLen (
+ IN INT32 i
+ );
+
+STATIC
+VOID
+MakeLen (
+ IN INT32 Root
+ );
+
+STATIC
+VOID
+DownHeap (
+ IN INT32 i
+ );
+
+STATIC
+VOID
+MakeCode (
+ IN INT32 n,
+ IN UINT8 Len[],
+ OUT UINT16 Code[]
+ );
+
+STATIC
+INT32
+MakeTree (
+ IN INT32 NParm,
+ IN UINT16 FreqParm[],
+ OUT UINT8 LenParm[],
+ OUT UINT16 CodeParm[]
+ );
+
+
+//
+// Global Variables
+//
+
+STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
+
+STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;
+STATIC INT16 mHeap[NC + 1];
+STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
+STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
+STATIC UINT32 mCompSize, mOrigSize;
+
+STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1],
+ mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1],mCCode[NC],
+ mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
+
+STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
+
+
+//
+// functions
+//
+
+EFI_STATUS
+EfiCompress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ )
+/*++
+
+Routine Description:
+
+ The main compression routine.
+
+Arguments:
+
+ SrcBuffer - The buffer storing the source data
+ SrcSize - The size of source data
+ DstBuffer - The buffer to store the compressed data
+ DstSize - On input, the size of DstBuffer; On output,
+ the size of the actual compressed data.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
+ DstSize contains the size needed.
+ EFI_SUCCESS - Compression is successful.
+
+--*/
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // Initializations
+ //
+ mBufSiz = 0;
+ mBuf = NULL;
+ mText = NULL;
+ mLevel = NULL;
+ mChildCount = NULL;
+ mPosition = NULL;
+ mParent = NULL;
+ mPrev = NULL;
+ mNext = NULL;
+
+
+ mSrc = SrcBuffer;
+ mSrcUpperLimit = mSrc + SrcSize;
+ mDst = DstBuffer;
+ mDstUpperLimit = mDst + *DstSize;
+
+ PutDword(0L);
+ PutDword(0L);
+
+ MakeCrcTable ();
+
+ mOrigSize = mCompSize = 0;
+ mCrc = INIT_CRC;
+
+ //
+ // Compress it
+ //
+
+ Status = Encode();
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Null terminate the compressed data
+ //
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = 0;
+ }
+
+ //
+ // Fill in compressed size and original size
+ //
+ mDst = DstBuffer;
+ PutDword(mCompSize+1);
+ PutDword(mOrigSize);
+
+ //
+ // Return
+ //
+
+ if (mCompSize + 1 + 8 > *DstSize) {
+ *DstSize = mCompSize + 1 + 8;
+ return EFI_BUFFER_TOO_SMALL;
+ } else {
+ *DstSize = mCompSize + 1 + 8;
+ return EFI_SUCCESS;
+ }
+
+}
+
+STATIC
+VOID
+PutDword(
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ Put a dword to output stream
+
+Arguments:
+
+ Data - the dword to put
+
+Returns: (VOID)
+
+--*/
+{
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8)(((UINT8)(Data )) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff);
+ }
+}
+
+STATIC
+EFI_STATUS
+AllocateMemory ()
+/*++
+
+Routine Description:
+
+ Allocate memory spaces for data structures used in compression process
+
+Argements: (VOID)
+
+Returns:
+
+ EFI_SUCCESS - Memory is allocated successfully
+ EFI_OUT_OF_RESOURCES - Allocation fails
+
+--*/
+{
+ UINT32 i;
+
+ mText = malloc (WNDSIZ * 2 + MAXMATCH);
+ for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) {
+ mText[i] = 0;
+ }
+
+ mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel));
+ mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount));
+ mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition));
+ mParent = malloc (WNDSIZ * 2 * sizeof(*mParent));
+ mPrev = malloc (WNDSIZ * 2 * sizeof(*mPrev));
+ mNext = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext));
+
+ mBufSiz = 16 * 1024U;
+ while ((mBuf = malloc(mBufSiz)) == NULL) {
+ mBufSiz = (mBufSiz / 10U) * 9U;
+ if (mBufSiz < 4 * 1024U) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ mBuf[0] = 0;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+FreeMemory ()
+/*++
+
+Routine Description:
+
+ Called when compression is completed to free memory previously allocated.
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ if (mText) {
+ free (mText);
+ }
+
+ if (mLevel) {
+ free (mLevel);
+ }
+
+ if (mChildCount) {
+ free (mChildCount);
+ }
+
+ if (mPosition) {
+ free (mPosition);
+ }
+
+ if (mParent) {
+ free (mParent);
+ }
+
+ if (mPrev) {
+ free (mPrev);
+ }
+
+ if (mNext) {
+ free (mNext);
+ }
+
+ if (mBuf) {
+ free (mBuf);
+ }
+
+ return;
+}
+
+
+STATIC
+VOID
+InitSlide ()
+/*++
+
+Routine Description:
+
+ Initialize String Info Log data structures
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE i;
+
+ for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) {
+ mLevel[i] = 1;
+ mPosition[i] = NIL; /* sentinel */
+ }
+ for (i = WNDSIZ; i < WNDSIZ * 2; i++) {
+ mParent[i] = NIL;
+ }
+ mAvail = 1;
+ for (i = 1; i < WNDSIZ - 1; i++) {
+ mNext[i] = (NODE)(i + 1);
+ }
+
+ mNext[WNDSIZ - 1] = NIL;
+ for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) {
+ mNext[i] = NIL;
+ }
+}
+
+
+STATIC
+NODE
+Child (
+ IN NODE q,
+ IN UINT8 c
+ )
+/*++
+
+Routine Description:
+
+ Find child node given the parent node and the edge character
+
+Arguments:
+
+ q - the parent node
+ c - the edge character
+
+Returns:
+
+ The child node (NIL if not found)
+
+--*/
+{
+ NODE r;
+
+ r = mNext[HASH(q, c)];
+ mParent[NIL] = q; /* sentinel */
+ while (mParent[r] != q) {
+ r = mNext[r];
+ }
+
+ return r;
+}
+
+STATIC
+VOID
+MakeChild (
+ IN NODE q,
+ IN UINT8 c,
+ IN NODE r
+ )
+/*++
+
+Routine Description:
+
+ Create a new child for a given parent node.
+
+Arguments:
+
+ q - the parent node
+ c - the edge character
+ r - the child node
+
+Returns: (VOID)
+
+--*/
+{
+ NODE h, t;
+
+ h = (NODE)HASH(q, c);
+ t = mNext[h];
+ mNext[h] = r;
+ mNext[r] = t;
+ mPrev[t] = r;
+ mPrev[r] = h;
+ mParent[r] = q;
+ mChildCount[q]++;
+}
+
+STATIC
+VOID
+Split (
+ NODE Old
+ )
+/*++
+
+Routine Description:
+
+ Split a node.
+
+Arguments:
+
+ Old - the node to split
+
+Returns: (VOID)
+
+--*/
+{
+ NODE New, t;
+
+ New = mAvail;
+ mAvail = mNext[New];
+ mChildCount[New] = 0;
+ t = mPrev[Old];
+ mPrev[New] = t;
+ mNext[t] = New;
+ t = mNext[Old];
+ mNext[New] = t;
+ mPrev[t] = New;
+ mParent[New] = mParent[Old];
+ mLevel[New] = (UINT8)mMatchLen;
+ mPosition[New] = mPos;
+ MakeChild(New, mText[mMatchPos + mMatchLen], Old);
+ MakeChild(New, mText[mPos + mMatchLen], mPos);
+}
+
+STATIC
+VOID
+InsertNode ()
+/*++
+
+Routine Description:
+
+ Insert string info for current position into the String Info Log
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE q, r, j, t;
+ UINT8 c, *t1, *t2;
+
+ if (mMatchLen >= 4) {
+
+ //
+ // We have just got a long match, the target tree
+ // can be located by MatchPos + 1. Travese the tree
+ // from bottom up to get to a proper starting point.
+ // The usage of PERC_FLAG ensures proper node deletion
+ // in DeleteNode() later.
+ //
+
+ mMatchLen--;
+ r = (INT16)((mMatchPos + 1) | WNDSIZ);
+ while ((q = mParent[r]) == NIL) {
+ r = mNext[r];
+ }
+ while (mLevel[q] >= mMatchLen) {
+ r = q; q = mParent[q];
+ }
+ t = q;
+ while (mPosition[t] < 0) {
+ mPosition[t] = mPos;
+ t = mParent[t];
+ }
+ if (t < WNDSIZ) {
+ mPosition[t] = (NODE)(mPos | PERC_FLAG);
+ }
+ } else {
+
+ //
+ // Locate the target tree
+ //
+
+ q = (INT16)(mText[mPos] + WNDSIZ);
+ c = mText[mPos + 1];
+ if ((r = Child(q, c)) == NIL) {
+ MakeChild(q, c, mPos);
+ mMatchLen = 1;
+ return;
+ }
+ mMatchLen = 2;
+ }
+
+ //
+ // Traverse down the tree to find a match.
+ // Update Position value along the route.
+ // Node split or creation is involved.
+ //
+
+ for ( ; ; ) {
+ if (r >= WNDSIZ) {
+ j = MAXMATCH;
+ mMatchPos = r;
+ } else {
+ j = mLevel[r];
+ mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG);
+ }
+ if (mMatchPos >= mPos) {
+ mMatchPos -= WNDSIZ;
+ }
+ t1 = &mText[mPos + mMatchLen];
+ t2 = &mText[mMatchPos + mMatchLen];
+ while (mMatchLen < j) {
+ if (*t1 != *t2) {
+ Split(r);
+ return;
+ }
+ mMatchLen++;
+ t1++;
+ t2++;
+ }
+ if (mMatchLen >= MAXMATCH) {
+ break;
+ }
+ mPosition[r] = mPos;
+ q = r;
+ if ((r = Child(q, *t1)) == NIL) {
+ MakeChild(q, *t1, mPos);
+ return;
+ }
+ mMatchLen++;
+ }
+ t = mPrev[r];
+ mPrev[mPos] = t;
+ mNext[t] = mPos;
+ t = mNext[r];
+ mNext[mPos] = t;
+ mPrev[t] = mPos;
+ mParent[mPos] = q;
+ mParent[r] = NIL;
+
+ //
+ // Special usage of 'next'
+ //
+ mNext[r] = mPos;
+
+}
+
+STATIC
+VOID
+DeleteNode ()
+/*++
+
+Routine Description:
+
+ Delete outdated string info. (The Usage of PERC_FLAG
+ ensures a clean deletion)
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE q, r, s, t, u;
+
+ if (mParent[mPos] == NIL) {
+ return;
+ }
+
+ r = mPrev[mPos];
+ s = mNext[mPos];
+ mNext[r] = s;
+ mPrev[s] = r;
+ r = mParent[mPos];
+ mParent[mPos] = NIL;
+ if (r >= WNDSIZ || --mChildCount[r] > 1) {
+ return;
+ }
+ t = (NODE)(mPosition[r] & ~PERC_FLAG);
+ if (t >= mPos) {
+ t -= WNDSIZ;
+ }
+ s = t;
+ q = mParent[r];
+ while ((u = mPosition[q]) & PERC_FLAG) {
+ u &= ~PERC_FLAG;
+ if (u >= mPos) {
+ u -= WNDSIZ;
+ }
+ if (u > s) {
+ s = u;
+ }
+ mPosition[q] = (INT16)(s | WNDSIZ);
+ q = mParent[q];
+ }
+ if (q < WNDSIZ) {
+ if (u >= mPos) {
+ u -= WNDSIZ;
+ }
+ if (u > s) {
+ s = u;
+ }
+ mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG);
+ }
+ s = Child(r, mText[t + mLevel[r]]);
+ t = mPrev[s];
+ u = mNext[s];
+ mNext[t] = u;
+ mPrev[u] = t;
+ t = mPrev[r];
+ mNext[t] = s;
+ mPrev[s] = t;
+ t = mNext[r];
+ mPrev[t] = s;
+ mNext[s] = t;
+ mParent[s] = mParent[r];
+ mParent[r] = NIL;
+ mNext[r] = mAvail;
+ mAvail = r;
+}
+
+STATIC
+VOID
+GetNextMatch ()
+/*++
+
+Routine Description:
+
+ Advance the current position (read in new data if needed).
+ Delete outdated string info. Find a match string for current position.
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 n;
+
+ mRemainder--;
+ if (++mPos == WNDSIZ * 2) {
+ memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
+ n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ);
+ mRemainder += n;
+ mPos = WNDSIZ;
+ }
+ DeleteNode();
+ InsertNode();
+}
+
+STATIC
+EFI_STATUS
+Encode ()
+/*++
+
+Routine Description:
+
+ The main controlling routine for compression process.
+
+Arguments: (VOID)
+
+Returns:
+
+ EFI_SUCCESS - The compression is successful
+ EFI_OUT_0F_RESOURCES - Not enough memory for compression process
+
+--*/
+{
+ EFI_STATUS Status;
+ INT32 LastMatchLen;
+ NODE LastMatchPos;
+
+ Status = AllocateMemory();
+ if (EFI_ERROR(Status)) {
+ FreeMemory();
+ return Status;
+ }
+
+ InitSlide();
+
+ HufEncodeStart();
+
+ mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH);
+
+ mMatchLen = 0;
+ mPos = WNDSIZ;
+ InsertNode();
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+ while (mRemainder > 0) {
+ LastMatchLen = mMatchLen;
+ LastMatchPos = mMatchPos;
+ GetNextMatch();
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+
+ if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
+
+ //
+ // Not enough benefits are gained by outputting a pointer,
+ // so just output the original character
+ //
+
+ Output(mText[mPos - 1], 0);
+ } else {
+
+ //
+ // Outputting a pointer is beneficial enough, do it.
+ //
+
+ Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
+ (mPos - LastMatchPos - 2) & (WNDSIZ - 1));
+ while (--LastMatchLen > 0) {
+ GetNextMatch();
+ }
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+ }
+ }
+
+ HufEncodeEnd();
+ FreeMemory();
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+CountTFreq ()
+/*++
+
+Routine Description:
+
+ Count the frequencies for the Extra Set
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 i, k, n, Count;
+
+ for (i = 0; i < NT; i++) {
+ mTFreq[i] = 0;
+ }
+ n = NC;
+ while (n > 0 && mCLen[n - 1] == 0) {
+ n--;
+ }
+ i = 0;
+ while (i < n) {
+ k = mCLen[i++];
+ if (k == 0) {
+ Count = 1;
+ while (i < n && mCLen[i] == 0) {
+ i++;
+ Count++;
+ }
+ if (Count <= 2) {
+ mTFreq[0] = (UINT16)(mTFreq[0] + Count);
+ } else if (Count <= 18) {
+ mTFreq[1]++;
+ } else if (Count == 19) {
+ mTFreq[0]++;
+ mTFreq[1]++;
+ } else {
+ mTFreq[2]++;
+ }
+ } else {
+ mTFreq[k + 2]++;
+ }
+ }
+}
+
+STATIC
+VOID
+WritePTLen (
+ IN INT32 n,
+ IN INT32 nbit,
+ IN INT32 Special
+ )
+/*++
+
+Routine Description:
+
+ Outputs the code length array for the Extra Set or the Position Set.
+
+Arguments:
+
+ n - the number of symbols
+ nbit - the number of bits needed to represent 'n'
+ Special - the special symbol that needs to be take care of
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 i, k;
+
+ while (n > 0 && mPTLen[n - 1] == 0) {
+ n--;
+ }
+ PutBits(nbit, n);
+ i = 0;
+ while (i < n) {
+ k = mPTLen[i++];
+ if (k <= 6) {
+ PutBits(3, k);
+ } else {
+ PutBits(k - 3, (1U << (k - 3)) - 2);
+ }
+ if (i == Special) {
+ while (i < 6 && mPTLen[i] == 0) {
+ i++;
+ }
+ PutBits(2, (i - 3) & 3);
+ }
+ }
+}
+
+STATIC
+VOID
+WriteCLen ()
+/*++
+
+Routine Description:
+
+ Outputs the code length array for Char&Length Set
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 i, k, n, Count;
+
+ n = NC;
+ while (n > 0 && mCLen[n - 1] == 0) {
+ n--;
+ }
+ PutBits(CBIT, n);
+ i = 0;
+ while (i < n) {
+ k = mCLen[i++];
+ if (k == 0) {
+ Count = 1;
+ while (i < n && mCLen[i] == 0) {
+ i++;
+ Count++;
+ }
+ if (Count <= 2) {
+ for (k = 0; k < Count; k++) {
+ PutBits(mPTLen[0], mPTCode[0]);
+ }
+ } else if (Count <= 18) {
+ PutBits(mPTLen[1], mPTCode[1]);
+ PutBits(4, Count - 3);
+ } else if (Count == 19) {
+ PutBits(mPTLen[0], mPTCode[0]);
+ PutBits(mPTLen[1], mPTCode[1]);
+ PutBits(4, 15);
+ } else {
+ PutBits(mPTLen[2], mPTCode[2]);
+ PutBits(CBIT, Count - 20);
+ }
+ } else {
+ PutBits(mPTLen[k + 2], mPTCode[k + 2]);
+ }
+ }
+}
+
+STATIC
+VOID
+EncodeC (
+ IN INT32 c
+ )
+{
+ PutBits(mCLen[c], mCCode[c]);
+}
+
+STATIC
+VOID
+EncodeP (
+ IN UINT32 p
+ )
+{
+ UINT32 c, q;
+
+ c = 0;
+ q = p;
+ while (q) {
+ q >>= 1;
+ c++;
+ }
+ PutBits(mPTLen[c], mPTCode[c]);
+ if (c > 1) {
+ PutBits(c - 1, p & (0xFFFFU >> (17 - c)));
+ }
+}
+
+STATIC
+VOID
+SendBlock ()
+/*++
+
+Routine Description:
+
+ Huffman code the block and output it.
+
+Argument: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ UINT32 i, k, Flags, Root, Pos, Size;
+ Flags = 0;
+
+ Root = MakeTree(NC, mCFreq, mCLen, mCCode);
+ Size = mCFreq[Root];
+ PutBits(16, Size);
+ if (Root >= NC) {
+ CountTFreq();
+ Root = MakeTree(NT, mTFreq, mPTLen, mPTCode);
+ if (Root >= NT) {
+ WritePTLen(NT, TBIT, 3);
+ } else {
+ PutBits(TBIT, 0);
+ PutBits(TBIT, Root);
+ }
+ WriteCLen();
+ } else {
+ PutBits(TBIT, 0);
+ PutBits(TBIT, 0);
+ PutBits(CBIT, 0);
+ PutBits(CBIT, Root);
+ }
+ Root = MakeTree(NP, mPFreq, mPTLen, mPTCode);
+ if (Root >= NP) {
+ WritePTLen(NP, PBIT, -1);
+ } else {
+ PutBits(PBIT, 0);
+ PutBits(PBIT, Root);
+ }
+ Pos = 0;
+ for (i = 0; i < Size; i++) {
+ if (i % UINT8_BIT == 0) {
+ Flags = mBuf[Pos++];
+ } else {
+ Flags <<= 1;
+ }
+ if (Flags & (1U << (UINT8_BIT - 1))) {
+ EncodeC(mBuf[Pos++] + (1U << UINT8_BIT));
+ k = mBuf[Pos++] << UINT8_BIT;
+ k += mBuf[Pos++];
+ EncodeP(k);
+ } else {
+ EncodeC(mBuf[Pos++]);
+ }
+ }
+ for (i = 0; i < NC; i++) {
+ mCFreq[i] = 0;
+ }
+ for (i = 0; i < NP; i++) {
+ mPFreq[i] = 0;
+ }
+}
+
+
+STATIC
+VOID
+Output (
+ IN UINT32 c,
+ IN UINT32 p
+ )
+/*++
+
+Routine Description:
+
+ Outputs an Original Character or a Pointer
+
+Arguments:
+
+ c - The original character or the 'String Length' element of a Pointer
+ p - The 'Position' field of a Pointer
+
+Returns: (VOID)
+
+--*/
+{
+ STATIC UINT32 CPos;
+
+ if ((mOutputMask >>= 1) == 0) {
+ mOutputMask = 1U << (UINT8_BIT - 1);
+ if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) {
+ SendBlock();
+ mOutputPos = 0;
+ }
+ CPos = mOutputPos++;
+ mBuf[CPos] = 0;
+ }
+ mBuf[mOutputPos++] = (UINT8) c;
+ mCFreq[c]++;
+ if (c >= (1U << UINT8_BIT)) {
+ mBuf[CPos] |= mOutputMask;
+ mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT);
+ mBuf[mOutputPos++] = (UINT8) p;
+ c = 0;
+ while (p) {
+ p >>= 1;
+ c++;
+ }
+ mPFreq[c]++;
+ }
+}
+
+STATIC
+VOID
+HufEncodeStart ()
+{
+ INT32 i;
+
+ for (i = 0; i < NC; i++) {
+ mCFreq[i] = 0;
+ }
+ for (i = 0; i < NP; i++) {
+ mPFreq[i] = 0;
+ }
+ mOutputPos = mOutputMask = 0;
+ InitPutBits();
+ return;
+}
+
+STATIC
+VOID
+HufEncodeEnd ()
+{
+ SendBlock();
+
+ //
+ // Flush remaining bits
+ //
+ PutBits(UINT8_BIT - 1, 0);
+
+ return;
+}
+
+
+STATIC
+VOID
+MakeCrcTable ()
+{
+ UINT32 i, j, r;
+
+ for (i = 0; i <= UINT8_MAX; i++) {
+ r = i;
+ for (j = 0; j < UINT8_BIT; j++) {
+ if (r & 1) {
+ r = (r >> 1) ^ CRCPOLY;
+ } else {
+ r >>= 1;
+ }
+ }
+ mCrcTable[i] = (UINT16)r;
+ }
+}
+
+STATIC
+VOID
+PutBits (
+ IN INT32 n,
+ IN UINT32 x
+ )
+/*++
+
+Routine Description:
+
+ Outputs rightmost n bits of x
+
+Argments:
+
+ n - the rightmost n bits of the data is used
+ x - the data
+
+Returns: (VOID)
+
+--*/
+{
+ UINT8 Temp;
+
+ if (n < mBitCount) {
+ mSubBitBuf |= x << (mBitCount -= n);
+ } else {
+
+ Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount)));
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = Temp;
+ }
+ mCompSize++;
+
+ if (n < UINT8_BIT) {
+ mSubBitBuf = x << (mBitCount = UINT8_BIT - n);
+ } else {
+
+ Temp = (UINT8)(x >> (n - UINT8_BIT));
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = Temp;
+ }
+ mCompSize++;
+
+ mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n);
+ }
+ }
+}
+
+STATIC
+INT32
+FreadCrc (
+ OUT UINT8 *p,
+ IN INT32 n
+ )
+/*++
+
+Routine Description:
+
+ Read in source data
+
+Arguments:
+
+ p - the buffer to hold the data
+ n - number of bytes to read
+
+Returns:
+
+ number of bytes actually read
+
+--*/
+{
+ INT32 i;
+
+ for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) {
+ *p++ = *mSrc++;
+ }
+ n = i;
+
+ p -= n;
+ mOrigSize += n;
+ while (--i >= 0) {
+ UPDATE_CRC(*p++);
+ }
+ return n;
+}
+
+
+STATIC
+VOID
+InitPutBits ()
+{
+ mBitCount = UINT8_BIT;
+ mSubBitBuf = 0;
+}
+
+STATIC
+VOID
+CountLen (
+ IN INT32 i
+ )
+/*++
+
+Routine Description:
+
+ Count the number of each code length for a Huffman tree.
+
+Arguments:
+
+ i - the top node
+
+Returns: (VOID)
+
+--*/
+{
+ STATIC INT32 Depth = 0;
+
+ if (i < mN) {
+ mLenCnt[(Depth < 16) ? Depth : 16]++;
+ } else {
+ Depth++;
+ CountLen(mLeft [i]);
+ CountLen(mRight[i]);
+ Depth--;
+ }
+}
+
+STATIC
+VOID
+MakeLen (
+ IN INT32 Root
+ )
+/*++
+
+Routine Description:
+
+ Create code length array for a Huffman tree
+
+Arguments:
+
+ Root - the root of the tree
+
+--*/
+{
+ INT32 i, k;
+ UINT32 Cum;
+
+ for (i = 0; i <= 16; i++) {
+ mLenCnt[i] = 0;
+ }
+ CountLen(Root);
+
+ //
+ // Adjust the length count array so that
+ // no code will be generated longer than its designated length
+ //
+
+ Cum = 0;
+ for (i = 16; i > 0; i--) {
+ Cum += mLenCnt[i] << (16 - i);
+ }
+ while (Cum != (1U << 16)) {
+ mLenCnt[16]--;
+ for (i = 15; i > 0; i--) {
+ if (mLenCnt[i] != 0) {
+ mLenCnt[i]--;
+ mLenCnt[i+1] += 2;
+ break;
+ }
+ }
+ Cum--;
+ }
+ for (i = 16; i > 0; i--) {
+ k = mLenCnt[i];
+ while (--k >= 0) {
+ mLen[*mSortPtr++] = (UINT8)i;
+ }
+ }
+}
+
+STATIC
+VOID
+DownHeap (
+ IN INT32 i
+ )
+{
+ INT32 j, k;
+
+ //
+ // priority queue: send i-th entry down heap
+ //
+
+ k = mHeap[i];
+ while ((j = 2 * i) <= mHeapSize) {
+ if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) {
+ j++;
+ }
+ if (mFreq[k] <= mFreq[mHeap[j]]) {
+ break;
+ }
+ mHeap[i] = mHeap[j];
+ i = j;
+ }
+ mHeap[i] = (INT16)k;
+}
+
+STATIC
+VOID
+MakeCode (
+ IN INT32 n,
+ IN UINT8 Len[],
+ OUT UINT16 Code[]
+ )
+/*++
+
+Routine Description:
+
+ Assign code to each symbol based on the code length array
+
+Arguments:
+
+ n - number of symbols
+ Len - the code length array
+ Code - stores codes for each symbol
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 i;
+ UINT16 Start[18];
+
+ Start[1] = 0;
+ for (i = 1; i <= 16; i++) {
+ Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1);
+ }
+ for (i = 0; i < n; i++) {
+ Code[i] = Start[Len[i]]++;
+ }
+}
+
+STATIC
+INT32
+MakeTree (
+ IN INT32 NParm,
+ IN UINT16 FreqParm[],
+ OUT UINT8 LenParm[],
+ OUT UINT16 CodeParm[]
+ )
+/*++
+
+Routine Description:
+
+ Generates Huffman codes given a frequency distribution of symbols
+
+Arguments:
+
+ NParm - number of symbols
+ FreqParm - frequency of each symbol
+ LenParm - code length for each symbol
+ CodeParm - code for each symbol
+
+Returns:
+
+ Root of the Huffman tree.
+
+--*/
+{
+ INT32 i, j, k, Avail;
+
+ //
+ // make tree, calculate len[], return root
+ //
+
+ mN = NParm;
+ mFreq = FreqParm;
+ mLen = LenParm;
+ Avail = mN;
+ mHeapSize = 0;
+ mHeap[1] = 0;
+ for (i = 0; i < mN; i++) {
+ mLen[i] = 0;
+ if (mFreq[i]) {
+ mHeap[++mHeapSize] = (INT16)i;
+ }
+ }
+ if (mHeapSize < 2) {
+ CodeParm[mHeap[1]] = 0;
+ return mHeap[1];
+ }
+ for (i = mHeapSize / 2; i >= 1; i--) {
+
+ //
+ // make priority queue
+ //
+ DownHeap(i);
+ }
+ mSortPtr = CodeParm;
+ do {
+ i = mHeap[1];
+ if (i < mN) {
+ *mSortPtr++ = (UINT16)i;
+ }
+ mHeap[1] = mHeap[mHeapSize--];
+ DownHeap(1);
+ j = mHeap[1];
+ if (j < mN) {
+ *mSortPtr++ = (UINT16)j;
+ }
+ k = Avail++;
+ mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]);
+ mHeap[1] = (INT16)k;
+ DownHeap(1);
+ mLeft[k] = (UINT16)i;
+ mRight[k] = (UINT16)j;
+ } while (mHeapSize > 1);
+
+ mSortPtr = CodeParm;
+ MakeLen(k);
+ MakeCode(NParm, LenParm, CodeParm);
+
+ //
+ // return root
+ //
+ return k;
+}
+
diff --git a/BaseTools/Source/C/Common/EfiUtilityMsgs.c b/BaseTools/Source/C/Common/EfiUtilityMsgs.c
new file mode 100644
index 0000000000..9d697da82d
--- /dev/null
+++ b/BaseTools/Source/C/Common/EfiUtilityMsgs.c
@@ -0,0 +1,929 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ EfiUtilityMsgs.c
+
+Abstract:
+
+ EFI tools utility functions to display warning, error, and informational
+ messages.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <time.h>
+
+#include "EfiUtilityMsgs.h"
+
+//
+// Declare module globals for keeping track of the the utility's
+// name and other settings.
+//
+STATIC STATUS mStatus = STATUS_SUCCESS;
+STATIC CHAR8 mUtilityName[50] = { 0 };
+STATIC UINT32 mPrintLogLevel = INFO_LOG_LEVEL;
+STATIC CHAR8 *mSourceFileName = NULL;
+STATIC UINT32 mSourceFileLineNum = 0;
+STATIC UINT32 mErrorCount = 0;
+STATIC UINT32 mWarningCount = 0;
+STATIC UINT32 mMaxErrors = 0;
+STATIC UINT32 mMaxWarnings = 0;
+STATIC UINT32 mMaxWarningsPlusErrors = 0;
+STATIC INT8 mPrintLimitsSet = 0;
+
+STATIC
+VOID
+PrintMessage (
+ CHAR8 *Type,
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ va_list List
+ );
+
+STATIC
+VOID
+PrintLimitExceeded (
+ VOID
+ );
+
+VOID
+Error (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Prints an error message.
+
+Arguments:
+ All arguments are optional, though the printed message may be useless if
+ at least something valid is not specified.
+
+ FileName - name of the file or application. If not specified, then the
+ utilty name (as set by the utility calling SetUtilityName()
+ earlier) is used. Otherwise "Unknown utility" is used.
+
+ LineNumber - the line number of error, typically used by parsers. If the
+ utility is not a parser, then 0 should be specified. Otherwise
+ the FileName and LineNumber info can be used to cause
+ MS Visual Studio to jump to the error.
+
+ MessageCode - an application-specific error code that can be referenced in
+ other documentation.
+
+ Text - the text in question, typically used by parsers.
+
+ MsgFmt - the format string for the error message. Can contain formatting
+ controls for use with the varargs.
+
+Returns:
+ None.
+
+Notes:
+ We print the following (similar to the Warn() and Debug()
+ W
+ Typical error/warning message format:
+
+ bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
+
+ BUGBUG -- these three utility functions are almost identical, and
+ should be modified to share code.
+
+ Visual Studio does not find error messages with:
+
+ " error :"
+ " error 1:"
+ " error c1:"
+ " error 1000:"
+ " error c100:"
+
+ It does find:
+ " error c1000:"
+--*/
+{
+ va_list List;
+ //
+ // If limits have been set, then check that we have not exceeded them
+ //
+ if (mPrintLimitsSet) {
+ //
+ // See if we've exceeded our total count
+ //
+ if (mMaxWarningsPlusErrors != 0) {
+ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ //
+ // See if we've exceeded our error count
+ //
+ if (mMaxErrors != 0) {
+ if (mErrorCount > mMaxErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ }
+
+ mErrorCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("ERROR", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_ERROR) {
+ mStatus = STATUS_ERROR;
+ }
+}
+
+VOID
+ParserError (
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a parser error, using the source file name and line number
+ set by a previous call to SetParserPosition().
+
+Arguments:
+ MessageCode - application-specific error code
+ Text - text to print in the error message
+ MsgFmt - format string to print at the end of the error message
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ //
+ // If limits have been set, then check them
+ //
+ if (mPrintLimitsSet) {
+ //
+ // See if we've exceeded our total count
+ //
+ if (mMaxWarningsPlusErrors != 0) {
+ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ //
+ // See if we've exceeded our error count
+ //
+ if (mMaxErrors != 0) {
+ if (mErrorCount > mMaxErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ }
+
+ mErrorCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("ERROR", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+ //
+ // Set status accordingly
+ //
+ if (mStatus < STATUS_ERROR) {
+ mStatus = STATUS_ERROR;
+ }
+}
+
+VOID
+ParserWarning (
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a parser warning, using the source file name and line number
+ set by a previous call to SetParserPosition().
+
+Arguments:
+ ErrorCode - application-specific error code
+ OffendingText - text to print in the warning message
+ MsgFmt - format string to print at the end of the warning message
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ //
+ // If limits have been set, then check them
+ //
+ if (mPrintLimitsSet) {
+ //
+ // See if we've exceeded our total count
+ //
+ if (mMaxWarningsPlusErrors != 0) {
+ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ //
+ // See if we've exceeded our warning count
+ //
+ if (mMaxWarnings != 0) {
+ if (mWarningCount > mMaxWarnings) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ }
+
+ mWarningCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("WARNING", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);
+ va_end (List);
+ //
+ // Don't set warning status accordingly
+ //
+ // if (mStatus < STATUS_WARNING) {
+ // mStatus = STATUS_WARNING;
+ // }
+}
+
+VOID
+Warning (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a warning message.
+
+Arguments:
+ FileName - name of the file where the warning was detected, or the name
+ of the application that detected the warning
+
+ LineNumber - the line number where the warning was detected (parsers).
+ 0 should be specified if the utility is not a parser.
+
+ MessageCode - an application-specific warning code that can be referenced in
+ other documentation.
+
+ Text - the text in question (parsers)
+
+ MsgFmt - the format string for the warning message. Can contain formatting
+ controls for use with varargs.
+
+Returns:
+ None.
+
+--*/
+{
+ va_list List;
+
+ //
+ // Current Print Level not output warning information.
+ //
+ if (WARNING_LOG_LEVEL < mPrintLogLevel) {
+ return;
+ }
+ //
+ // If limits have been set, then check them
+ //
+ if (mPrintLimitsSet) {
+ //
+ // See if we've exceeded our total count
+ //
+ if (mMaxWarningsPlusErrors != 0) {
+ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ //
+ // See if we've exceeded our warning count
+ //
+ if (mMaxWarnings != 0) {
+ if (mWarningCount > mMaxWarnings) {
+ PrintLimitExceeded ();
+ return ;
+ }
+ }
+ }
+
+ mWarningCount++;
+ va_start (List, MsgFmt);
+ PrintMessage ("WARNING", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
+ va_end (List);
+}
+
+VOID
+DebugMsg (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MsgLevel,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a Debug message.
+
+Arguments:
+ FileName - typically the name of the utility printing the debug message, but
+ can be the name of a file being parsed.
+
+ LineNumber - the line number in FileName (parsers)
+
+ MsgLevel - Debug message print level (0~9)
+
+ Text - the text in question (parsers)
+
+ MsgFmt - the format string for the debug message. Can contain formatting
+ controls for use with varargs.
+
+Returns:
+ None.
+
+--*/
+{
+ va_list List;
+ //
+ // If the debug level is less than current print level, then do nothing.
+ //
+ if (MsgLevel < mPrintLogLevel) {
+ return ;
+ }
+
+ va_start (List, MsgFmt);
+ PrintMessage ("DEBUG", FileName, LineNumber, 0, Text, MsgFmt, List);
+ va_end (List);
+}
+
+STATIC
+VOID
+PrintMessage (
+ CHAR8 *Type,
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ va_list List
+ )
+/*++
+
+Routine Description:
+ Worker routine for all the utility printing services. Prints the message in
+ a format that Visual Studio will find when scanning build outputs for
+ errors or warnings.
+
+Arguments:
+ Type - "warning" or "error" string to insert into the message to be
+ printed. The first character of this string (converted to uppercase)
+ is used to preceed the MessageCode value in the output string.
+
+ FileName - name of the file where the warning was detected, or the name
+ of the application that detected the warning
+
+ LineNumber - the line number where the warning was detected (parsers).
+ 0 should be specified if the utility is not a parser.
+
+ MessageCode - an application-specific warning code that can be referenced in
+ other documentation.
+
+ Text - part of the message to print
+
+ MsgFmt - the format string for the message. Can contain formatting
+ controls for use with varargs.
+ List - the variable list.
+
+Returns:
+ None.
+
+Notes:
+ If FileName == NULL then this utility will use the string passed into SetUtilityName().
+
+ LineNumber is only used if the caller is a parser, in which case FileName refers to the
+ file being parsed.
+
+ Text and MsgFmt are both optional, though it would be of little use calling this function with
+ them both NULL.
+
+ Output will typically be of the form:
+ <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
+
+ Parser (LineNumber != 0)
+ VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
+ Generic utility (LineNumber == 0)
+ UtilityName : error E1234 : Text string : MsgFmt string and args
+
+--*/
+{
+ CHAR8 Line[MAX_LINE_LEN];
+ CHAR8 Line2[MAX_LINE_LEN];
+ CHAR8 *Cptr;
+ struct tm *NewTime;
+ time_t CurrentTime;
+
+ //
+ // init local variable
+ //
+ Line[0] = '\0';
+ Line2[0] = '\0';
+
+ //
+ // If given a filename, then add it (and the line number) to the string.
+ // If there's no filename, then use the program name if provided.
+ //
+ if (FileName != NULL) {
+ Cptr = FileName;
+ } else {
+ Cptr = NULL;
+ }
+
+ if (strcmp (Type, "DEBUG") == 0) {
+ //
+ // Debug Message requires current time.
+ //
+ time (&CurrentTime);
+ NewTime = localtime (&CurrentTime);
+ fprintf (stdout, "%04d-%02d-%02d %02d:%02d:%02d",
+ NewTime->tm_year + 1900,
+ NewTime->tm_mon + 1,
+ NewTime->tm_mday,
+ NewTime->tm_hour,
+ NewTime->tm_min,
+ NewTime->tm_sec
+ );
+ if (Cptr != NULL) {
+ sprintf (Line, ": %s", Cptr);
+ if (LineNumber != 0) {
+ sprintf (Line2, "(%d)", LineNumber);
+ strcat (Line, Line2);
+ }
+ }
+ } else {
+ //
+ // Error and Warning Information.
+ //
+ if (Cptr != NULL) {
+ if (mUtilityName[0] != '\0') {
+ fprintf (stdout, "%s...\n", mUtilityName);
+ }
+ sprintf (Line, "%s", Cptr);
+ if (LineNumber != 0) {
+ sprintf (Line2, "(%d)", LineNumber);
+ strcat (Line, Line2);
+ }
+ } else {
+ if (mUtilityName[0] != '\0') {
+ sprintf (Line, "%s", mUtilityName);
+ }
+ }
+ }
+
+ //
+ // Have to print an error code or Visual Studio won't find the
+ // message for you. It has to be decimal digits too.
+ //
+ if (MessageCode != 0) {
+ sprintf (Line2, ": %s %04d", Type, MessageCode);
+ } else {
+ sprintf (Line2, ": %s", Type);
+ }
+ strcat (Line, Line2);
+ fprintf (stdout, "%s", Line);
+ //
+ // If offending text was provided, then print it
+ //
+ if (Text != NULL) {
+ fprintf (stdout, ": %s", Text);
+ }
+ fprintf (stdout, "\n");
+
+ //
+ // Print formatted message if provided
+ //
+ if (MsgFmt != NULL) {
+ vsprintf (Line2, MsgFmt, List);
+ fprintf (stdout, " %s\n", Line2);
+ }
+}
+
+STATIC
+VOID
+PrintSimpleMessage (
+ CHAR8 *MsgFmt,
+ va_list List
+ )
+/*++
+Routine Description:
+ Print message into stdout.
+
+Arguments:
+ MsgFmt - the format string for the message. Can contain formatting
+ controls for use with varargs.
+ List - the variable list.
+
+Returns:
+ None.
+--*/
+{
+ CHAR8 Line[MAX_LINE_LEN];
+ //
+ // Print formatted message if provided
+ //
+ if (MsgFmt != NULL) {
+ vsprintf (Line, MsgFmt, List);
+ fprintf (stdout, "%s\n", Line);
+ }
+}
+
+VOID
+ParserSetPosition (
+ CHAR8 *SourceFileName,
+ UINT32 LineNum
+ )
+/*++
+
+Routine Description:
+ Set the position in a file being parsed. This can be used to
+ print error messages deeper down in a parser.
+
+Arguments:
+ SourceFileName - name of the source file being parsed
+ LineNum - line number of the source file being parsed
+
+Returns:
+ NA
+
+--*/
+{
+ mSourceFileName = SourceFileName;
+ mSourceFileLineNum = LineNum;
+}
+
+VOID
+SetUtilityName (
+ CHAR8 *UtilityName
+ )
+/*++
+
+Routine Description:
+ All printed error/warning/debug messages follow the same format, and
+ typically will print a filename or utility name followed by the error
+ text. However if a filename is not passed to the print routines, then
+ they'll print the utility name if you call this function early in your
+ app to set the utility name.
+
+Arguments:
+ UtilityName - name of the utility, which will be printed with all
+ error/warning/debug messags.
+
+Returns:
+ NA
+
+--*/
+{
+ //
+ // Save the name of the utility in our local variable. Make sure its
+ // length does not exceed our buffer.
+ //
+ if (UtilityName != NULL) {
+ if (strlen (UtilityName) >= sizeof (mUtilityName)) {
+ Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size");
+ strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1);
+ mUtilityName[sizeof (mUtilityName) - 1] = 0;
+ return ;
+ } else {
+ strcpy (mUtilityName, UtilityName);
+ }
+ } else {
+ Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
+ }
+}
+
+STATUS
+GetUtilityStatus (
+ VOID
+ )
+/*++
+
+Routine Description:
+ When you call Error() or Warning(), this module keeps track of it and
+ sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
+ exits, it can call this function to get the status and use it as a return
+ value.
+
+Arguments:
+ None.
+
+Returns:
+ Worst-case status reported, as defined by which print function was called.
+
+--*/
+{
+ return mStatus;
+}
+
+VOID
+SetPrintLevel (
+ UINT32 LogLevel
+ )
+/*++
+
+Routine Description:
+ Set the printing message Level. This is used by the PrintMsg() function
+ to determine when/if a message should be printed.
+
+Arguments:
+ LogLevel - 0~50 to specify the different level message.
+
+Returns:
+ NA
+
+--*/
+{
+ mPrintLogLevel = LogLevel;
+}
+
+VOID
+VerboseMsg (
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a verbose level message.
+
+Arguments:
+ MsgFmt - the format string for the message. Can contain formatting
+ controls for use with varargs.
+ List - the variable list.
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ //
+ // If the debug level is less than current print level, then do nothing.
+ //
+ if (VERBOSE_LOG_LEVEL < mPrintLogLevel) {
+ return ;
+ }
+
+ va_start (List, MsgFmt);
+ PrintSimpleMessage (MsgFmt, List);
+ va_end (List);
+}
+
+VOID
+NormalMsg (
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a default level message.
+
+Arguments:
+ MsgFmt - the format string for the message. Can contain formatting
+ controls for use with varargs.
+ List - the variable list.
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ //
+ // If the debug level is less than current print level, then do nothing.
+ //
+ if (INFO_LOG_LEVEL < mPrintLogLevel) {
+ return ;
+ }
+
+ va_start (List, MsgFmt);
+ PrintSimpleMessage (MsgFmt, List);
+ va_end (List);
+}
+
+VOID
+KeyMsg (
+ CHAR8 *MsgFmt,
+ ...
+ )
+/*++
+
+Routine Description:
+ Print a key level message.
+
+Arguments:
+ MsgFmt - the format string for the message. Can contain formatting
+ controls for use with varargs.
+ List - the variable list.
+
+Returns:
+ NA
+
+--*/
+{
+ va_list List;
+ //
+ // If the debug level is less than current print level, then do nothing.
+ //
+ if (KEY_LOG_LEVEL < mPrintLogLevel) {
+ return ;
+ }
+
+ va_start (List, MsgFmt);
+ PrintSimpleMessage (MsgFmt, List);
+ va_end (List);
+}
+
+VOID
+SetPrintLimits (
+ UINT32 MaxErrors,
+ UINT32 MaxWarnings,
+ UINT32 MaxWarningsPlusErrors
+ )
+/*++
+
+Routine Description:
+ Set the limits of how many errors, warnings, and errors+warnings
+ we will print.
+
+Arguments:
+ MaxErrors - maximum number of error messages to print
+ MaxWarnings - maximum number of warning messages to print
+ MaxWarningsPlusErrors
+ - maximum number of errors+warnings to print
+
+Returns:
+ NA
+
+--*/
+{
+ mMaxErrors = MaxErrors;
+ mMaxWarnings = MaxWarnings;
+ mMaxWarningsPlusErrors = MaxWarningsPlusErrors;
+ mPrintLimitsSet = 1;
+}
+
+STATIC
+VOID
+PrintLimitExceeded (
+ VOID
+ )
+{
+ STATIC INT8 mPrintLimitExceeded = 0;
+ //
+ // If we've already printed the message, do nothing. Otherwise
+ // temporarily increase our print limits so we can pass one
+ // more message through.
+ //
+ if (mPrintLimitExceeded == 0) {
+ mPrintLimitExceeded++;
+ mMaxErrors++;
+ mMaxWarnings++;
+ mMaxWarningsPlusErrors++;
+ Error (NULL, 0, 0, "error/warning print limit exceeded", NULL);
+ mMaxErrors--;
+ mMaxWarnings--;
+ mMaxWarningsPlusErrors--;
+ }
+}
+
+#if 0
+VOID
+TestUtilityMessages (
+ VOID
+ )
+{
+ CHAR8 *ArgStr = "ArgString";
+ INTN ArgInt;
+
+ ArgInt = 0x12345678;
+ //
+ // Test without setting utility name
+ //
+ fprintf (stdout, "* Testing without setting utility name\n");
+ fprintf (stdout, "** Test debug message not printed\n");
+ DebugMsg (NULL, 0, 0x00000001, NULL, NULL);
+ fprintf (stdout, "** Test warning with two strings and two args\n");
+ Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ fprintf (stdout, "** Test error with two strings and two args\n");
+ Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ fprintf (stdout, "** Test parser warning with nothing\n");
+ ParserWarning (0, NULL, NULL);
+ fprintf (stdout, "** Test parser error with nothing\n");
+ ParserError (0, NULL, NULL);
+ //
+ // Test with utility name set now
+ //
+ fprintf (stdout, "** Testingin with utility name set\n");
+ SetUtilityName ("MyUtilityName");
+ //
+ // Test debug prints
+ //
+ SetDebugMsgMask (2);
+ fprintf (stdout, "** Test debug message with one string\n");
+ DebugMsg (NULL, 0, 0x00000002, "Text1", NULL);
+ fprintf (stdout, "** Test debug message with one string\n");
+ DebugMsg (NULL, 0, 0x00000002, NULL, "Text2");
+ fprintf (stdout, "** Test debug message with two strings\n");
+ DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2");
+ fprintf (stdout, "** Test debug message with two strings and two args\n");
+ DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ //
+ // Test warning prints
+ //
+ fprintf (stdout, "** Test warning with no strings\n");
+ Warning (NULL, 0, 1234, NULL, NULL);
+ fprintf (stdout, "** Test warning with one string\n");
+ Warning (NULL, 0, 1234, "Text1", NULL);
+ fprintf (stdout, "** Test warning with one string\n");
+ Warning (NULL, 0, 1234, NULL, "Text2");
+ fprintf (stdout, "** Test warning with two strings and two args\n");
+ Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ //
+ // Test error prints
+ //
+ fprintf (stdout, "** Test error with no strings\n");
+ Error (NULL, 0, 1234, NULL, NULL);
+ fprintf (stdout, "** Test error with one string\n");
+ Error (NULL, 0, 1234, "Text1", NULL);
+ fprintf (stdout, "** Test error with one string\n");
+ Error (NULL, 0, 1234, NULL, "Text2");
+ fprintf (stdout, "** Test error with two strings and two args\n");
+ Error (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+ //
+ // Test parser prints
+ //
+ fprintf (stdout, "** Test parser errors\n");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, NULL, NULL);
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, "Text1", NULL);
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, NULL, "Text2");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, "Text1", "Text2");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+
+ fprintf (stdout, "** Test parser warnings\n");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, NULL, NULL);
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, "Text1", NULL);
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, NULL, "Text2");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, "Text1", "Text2");
+ ParserSetPosition (__FILE__, __LINE__ + 1);
+ ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);
+}
+#endif
diff --git a/BaseTools/Source/C/Common/EfiUtilityMsgs.h b/BaseTools/Source/C/Common/EfiUtilityMsgs.h
new file mode 100644
index 0000000000..6c2f9d2989
--- /dev/null
+++ b/BaseTools/Source/C/Common/EfiUtilityMsgs.h
@@ -0,0 +1,166 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ EfiUtilityMsgs.h
+
+Abstract:
+
+ Defines and prototypes for common EFI utility error and debug messages.
+
+**/
+
+#ifndef _EFI_UTILITY_MSGS_H_
+#define _EFI_UTILITY_MSGS_H_
+
+#include <Common/UefiBaseTypes.h>
+
+//
+// Log message print Level
+//
+#define VERBOSE_LOG_LEVEL 15
+#define WARNING_LOG_LEVEL 15
+#define INFO_LOG_LEVEL 20
+#define KEY_LOG_LEVEL 40
+#define ERROR_LOG_LEVLE 50
+
+//
+// Status codes returned by EFI utility programs and functions
+//
+#define STATUS_SUCCESS 0
+#define STATUS_WARNING 1
+#define STATUS_ERROR 2
+#define VOID void
+
+typedef int STATUS;
+
+#define MAX_LINE_LEN 0x200
+#define MAXIMUM_INPUT_FILE_NUM 10
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+//
+// When we call Error() or Warning(), the module keeps track of the worst
+// case reported. GetUtilityStatus() will get the worst-case results, which
+// can be used as the return value from the app.
+//
+STATUS
+GetUtilityStatus (
+ VOID
+ );
+
+//
+// If someone prints an error message and didn't specify a source file name,
+// then we print the utility name instead. However they must tell us the
+// utility name early on via this function.
+//
+VOID
+SetUtilityName (
+ CHAR8 *ProgramName
+ )
+;
+
+VOID
+Error (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+VOID
+Warning (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 WarningCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+VOID
+DebugMsg (
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MsgLevel,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+VOID
+VerboseMsg (
+ CHAR8 *MsgFmt,
+ ...
+ );
+
+VOID
+NormalMsg (
+ CHAR8 *MsgFmt,
+ ...
+ );
+
+VOID
+KeyMsg (
+ CHAR8 *MsgFmt,
+ ...
+ );
+
+VOID
+SetPrintLevel (
+ UINT32 LogLevel
+ );
+
+VOID
+ParserSetPosition (
+ CHAR8 *SourceFileName,
+ UINT32 LineNum
+ )
+;
+
+VOID
+ParserError (
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+VOID
+ParserWarning (
+ UINT32 ErrorCode,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+VOID
+SetPrintLimits (
+ UINT32 NumErrors,
+ UINT32 NumWarnings,
+ UINT32 NumWarningsPlusErrors
+ )
+;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _EFI_UTILITY_MSGS_H_
diff --git a/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c b/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c
new file mode 100644
index 0000000000..d51e359043
--- /dev/null
+++ b/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c
@@ -0,0 +1,1667 @@
+/** @file
+
+Copyright (c) 1999 - 2008, 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:
+
+ FirmwareVolumeBuffer.c
+
+Abstract:
+
+ EFI Firmware Volume routines which work on a Fv image in buffers.
+
+**/
+
+#include "FirmwareVolumeBufferLib.h"
+#include "BinderFuncs.h"
+
+//
+// Local macros
+//
+#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
+ ( \
+ (BOOLEAN) ( \
+ (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
+ ) \
+ )
+
+
+//
+// Local prototypes
+//
+
+STATIC
+UINT16
+FvBufCalculateChecksum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ );
+
+STATIC
+UINT8
+FvBufCalculateChecksum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ );
+
+//
+// Procedures start
+//
+
+EFI_STATUS
+FvBufRemoveFileNew (
+ IN OUT VOID *Fv,
+ IN EFI_GUID *Name
+ )
+/*++
+
+Routine Description:
+
+ Clears out all files from the Fv buffer in memory
+
+Arguments:
+
+ SourceFv - Address of the Fv in memory, this firmware volume volume will
+ be modified, if SourceFfsFile exists
+ SourceFfsFile - Input FFS file to replace
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER* FileToRm;
+ UINTN FileToRmLength;
+
+ Status = FvBufFindFileByName(
+ Fv,
+ Name,
+ (VOID **)&FileToRm
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FileToRmLength = FvBufExpand3ByteSize (FileToRm->Size);
+
+ CommonLibBinderSetMem (
+ FileToRm,
+ FileToRmLength,
+ (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY)
+ ? 0xFF : 0
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufRemoveFile (
+ IN OUT VOID *Fv,
+ IN EFI_GUID *Name
+ )
+/*++
+
+Routine Description:
+
+ Clears out all files from the Fv buffer in memory
+
+Arguments:
+
+ SourceFv - Address of the Fv in memory, this firmware volume volume will
+ be modified, if SourceFfsFile exists
+ SourceFfsFile - Input FFS file to replace
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *NextFile;
+ EFI_FIRMWARE_VOLUME_HEADER *TempFv;
+ UINTN FileKey;
+ UINTN FvLength;
+
+ Status = FvBufFindFileByName(
+ Fv,
+ Name,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FvBufGetSize (Fv, &FvLength);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ TempFv = NULL;
+ Status = FvBufDuplicate (Fv, (VOID **)&TempFv);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FvBufClearAllFiles (TempFv);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // TempFv has been allocated. It must now be freed
+ // before returning.
+
+ FileKey = 0;
+ while (TRUE) {
+
+ Status = FvBufFindNextFile (Fv, &FileKey, (VOID **)&NextFile);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ } else if (EFI_ERROR (Status)) {
+ CommonLibBinderFree (TempFv);
+ return Status;
+ }
+
+ if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {
+ continue;
+ }
+ else {
+ Status = FvBufAddFile (TempFv, NextFile);
+ if (EFI_ERROR (Status)) {
+ CommonLibBinderFree (TempFv);
+ return Status;
+ }
+ }
+ }
+
+ CommonLibBinderCopyMem (Fv, TempFv, FvLength);
+ CommonLibBinderFree (TempFv);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufChecksumFile (
+ IN OUT VOID *FfsFile
+ )
+/*++
+
+Routine Description:
+
+ Clears out all files from the Fv buffer in memory
+
+Arguments:
+
+ SourceFfsFile - Input FFS file to update the checksum for
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+
+--*/
+{
+ EFI_FFS_FILE_HEADER* File = (EFI_FFS_FILE_HEADER*)FfsFile;
+ EFI_FFS_FILE_STATE StateBackup;
+ UINT32 FileSize;
+
+ FileSize = FvBufExpand3ByteSize (File->Size);
+
+ //
+ // Fill in checksums and state, they must be 0 for checksumming.
+ //
+ File->IntegrityCheck.Checksum.Header = 0;
+ File->IntegrityCheck.Checksum.File = 0;
+ StateBackup = File->State;
+ File->State = 0;
+
+ File->IntegrityCheck.Checksum.Header =
+ FvBufCalculateChecksum8 (
+ (UINT8 *) File,
+ sizeof (EFI_FFS_FILE_HEADER)
+ );
+
+ if (File->Attributes & FFS_ATTRIB_CHECKSUM) {
+ File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 (
+ (VOID*)File,
+ FileSize
+ );
+ } else {
+ File->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ File->State = StateBackup;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufChecksumHeader (
+ IN OUT VOID *Fv
+ )
+/*++
+
+Routine Description:
+
+ Clears out all files from the Fv buffer in memory
+
+Arguments:
+
+ SourceFv - Address of the Fv in memory, this firmware volume volume will
+ be modified, if SourceFfsFile exists
+ SourceFfsFile - Input FFS file to replace
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER* FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
+
+ FvHeader->Checksum = 0;
+ FvHeader->Checksum =
+ FvBufCalculateChecksum16 (
+ (UINT16*) FvHeader,
+ FvHeader->HeaderLength / sizeof (UINT16)
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufDuplicate (
+ IN VOID *SourceFv,
+ IN OUT VOID **DestinationFv
+ )
+/*++
+
+Routine Description:
+
+ Clears out all files from the Fv buffer in memory
+
+Arguments:
+
+ SourceFv - Address of the Fv in memory
+ DestinationFv - Output for destination Fv
+ DestinationFv == NULL - invalid parameter
+ *DestinationFv == NULL - memory will be allocated
+ *DestinationFv != NULL - this address will be the destination
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN size;
+
+ if (DestinationFv == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = FvBufGetSize (SourceFv, &size);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (*DestinationFv == NULL) {
+ *DestinationFv = CommonLibBinderAllocate (size);
+ }
+
+ CommonLibBinderCopyMem (*DestinationFv, SourceFv, size);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufExtend (
+ IN VOID **Fv,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ Extends a firmware volume by the given number of bytes.
+
+ BUGBUG: Does not handle the case where the firmware volume has a
+ VTF (Volume Top File). The VTF will not be moved to the
+ end of the extended FV.
+
+Arguments:
+
+ Fv - Source and destination firmware volume.
+ Note: The original firmware volume buffer is freed!
+
+ Size - The minimum size that the firmware volume is to be extended by.
+ The FV may be extended more than this size.
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN OldSize;
+ UINTN NewSize;
+ UINTN BlockCount;
+ VOID* NewFv;
+
+ EFI_FIRMWARE_VOLUME_HEADER* hdr;
+ EFI_FV_BLOCK_MAP_ENTRY* blk;
+
+ Status = FvBufGetSize (*Fv, &OldSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Locate the block map in the fv header
+ //
+ hdr = (EFI_FIRMWARE_VOLUME_HEADER*)*Fv;
+ blk = hdr->BlockMap;
+
+ //
+ // Calculate the number of blocks needed to achieve the requested
+ // size extension
+ //
+ BlockCount = ((Size + (blk->Length - 1)) / blk->Length);
+
+ //
+ // Calculate the new size from the number of blocks that will be added
+ //
+ NewSize = OldSize + (BlockCount * blk->Length);
+
+ NewFv = CommonLibBinderAllocate (NewSize);
+ if (NewFv == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Copy the old data
+ //
+ CommonLibBinderCopyMem (NewFv, *Fv, OldSize);
+
+ //
+ // Free the old fv buffer
+ //
+ CommonLibBinderFree (*Fv);
+
+ //
+ // Locate the block map in the new fv header
+ //
+ hdr = (EFI_FIRMWARE_VOLUME_HEADER*)NewFv;
+ hdr->FvLength = NewSize;
+ blk = hdr->BlockMap;
+
+ //
+ // Update the block map for the new fv
+ //
+ blk->NumBlocks += (UINT32)BlockCount;
+
+ //
+ // Update the FV header checksum
+ //
+ FvBufChecksumHeader (NewFv);
+
+ //
+ // Clear out the new area of the FV
+ //
+ CommonLibBinderSetMem (
+ (UINT8*)NewFv + OldSize,
+ (NewSize - OldSize),
+ (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0
+ );
+
+ //
+ // Set output with new fv that was created
+ //
+ *Fv = NewFv;
+
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+FvBufClearAllFiles (
+ IN OUT VOID *Fv
+ )
+/*++
+
+Routine Description:
+
+ Clears out all files from the Fv buffer in memory
+
+Arguments:
+
+ Fv - Address of the Fv in memory
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+
+{
+ EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
+ EFI_STATUS Status;
+ UINTN size = 0;
+
+ Status = FvBufGetSize (Fv, &size);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CommonLibBinderSetMem(
+ (UINT8*)hdr + hdr->HeaderLength,
+ size - hdr->HeaderLength,
+ (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufGetSize (
+ IN VOID *Fv,
+ OUT UINTN *Size
+ )
+/*++
+
+Routine Description:
+
+ Clears out all files from the Fv buffer in memory
+
+Arguments:
+
+ Fv - Address of the Fv in memory
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+
+{
+ EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
+ EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;
+
+ *Size = 0;
+
+ while (blk->Length != 0 || blk->NumBlocks != 0) {
+ *Size = *Size + (blk->Length * blk->NumBlocks);
+ if (*Size >= 0x40000000) {
+ // If size is greater than 1GB, then assume it is corrupted
+ return EFI_VOLUME_CORRUPTED;
+ }
+ blk++;
+ }
+
+ if (*Size == 0) {
+ // If size is 0, then assume the volume is corrupted
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufAddFile (
+ IN OUT VOID *Fv,
+ IN VOID *File
+ )
+/*++
+
+Routine Description:
+
+ Adds a new FFS file
+
+Arguments:
+
+ Fv - Address of the Fv in memory
+ File - FFS file to add to Fv
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
+
+ EFI_FFS_FILE_HEADER *fhdr = NULL;
+ EFI_FVB_ATTRIBUTES FvbAttributes;
+ UINTN offset;
+ UINTN fsize;
+ UINTN newSize;
+ UINTN clearLoop;
+
+ EFI_STATUS Status;
+ UINTN fvSize;
+
+ Status = FvBufGetSize (Fv, &fvSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FvbAttributes = hdr->Attributes;
+ newSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size);
+
+ for(
+ offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8);
+ offset + newSize <= fvSize;
+ offset = (UINTN)ALIGN_POINTER (offset, 8)
+ ) {
+
+ fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset);
+
+ if (EFI_TEST_FFS_ATTRIBUTES_BIT(
+ FvbAttributes,
+ fhdr->State,
+ EFI_FILE_HEADER_VALID
+ )
+ ) {
+ // BUGBUG: Need to make sure that the new file does not already
+ // exist.
+
+ fsize = FvBufExpand3ByteSize (fhdr->Size);
+ if (fsize == 0 || (offset + fsize > fvSize)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ offset = offset + fsize;
+ continue;
+ }
+
+ clearLoop = 0;
+ while ((clearLoop < newSize) &&
+ (((UINT8*)fhdr)[clearLoop] ==
+ (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0)
+ )
+ ) {
+ clearLoop++;
+ }
+
+ //
+ // We found a place in the FV which is empty and big enough for
+ // the new file
+ //
+ if (clearLoop >= newSize) {
+ break;
+ }
+
+ offset = offset + 1; // Make some forward progress
+ }
+
+ if (offset + newSize > fvSize) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CommonLibBinderCopyMem (fhdr, File, newSize);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufAddFileWithExtend (
+ IN OUT VOID **Fv,
+ IN VOID *File
+ )
+/*++
+
+Routine Description:
+
+ Adds a new FFS file. Extends the firmware volume if needed.
+
+Arguments:
+
+ Fv - Source and destination firmware volume.
+ Note: If the FV is extended, then the original firmware volume
+ buffer is freed!
+
+ Size - The minimum size that the firmware volume is to be extended by.
+ The FV may be extended more than this size.
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER* NewFile;
+
+ NewFile = (EFI_FFS_FILE_HEADER*)File;
+
+ //
+ // Try to add to the capsule volume
+ //
+ Status = FvBufAddFile (*Fv, NewFile);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ //
+ // Try to extend the capsule volume by the size of the file
+ //
+ Status = FvBufExtend (Fv, FvBufExpand3ByteSize (NewFile->Size));
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Now, try to add the file again
+ //
+ Status = FvBufAddFile (*Fv, NewFile);
+ }
+
+ return Status;
+}
+
+
+EFI_STATUS
+FvBufAddVtfFile (
+ IN OUT VOID *Fv,
+ IN VOID *File
+ )
+/*++
+
+Routine Description:
+
+ Adds a new FFS VFT (Volume Top File) file. In other words, adds the
+ file to the end of the firmware volume.
+
+Arguments:
+
+ Fv - Address of the Fv in memory
+ File - FFS file to add to Fv
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+
+ EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
+
+ EFI_FFS_FILE_HEADER* NewFile;
+ UINTN NewFileSize;
+
+ UINT8 erasedUint8;
+ UINTN clearLoop;
+
+ EFI_FFS_FILE_HEADER *LastFile;
+ UINTN LastFileSize;
+
+ UINTN fvSize;
+ UINTN Key;
+
+ Status = FvBufGetSize (Fv, &fvSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0);
+ NewFileSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size);
+
+ if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Find the last file in the FV
+ //
+ Key = 0;
+ LastFile = NULL;
+ LastFileSize = 0;
+ do {
+ Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile);
+ LastFileSize = FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)File)->Size);
+ } while (!EFI_ERROR (Status));
+
+ //
+ // If no files were found, then we start at the beginning of the FV
+ //
+ if (LastFile == NULL) {
+ LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength);
+ }
+
+ //
+ // We want to put the new file (VTF) at the end of the FV
+ //
+ NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize));
+
+ //
+ // Check to see if there is enough room for the VTF after the last file
+ // found in the FV
+ //
+ if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Loop to determine if the end of the FV is empty
+ //
+ clearLoop = 0;
+ while ((clearLoop < NewFileSize) &&
+ (((UINT8*)NewFile)[clearLoop] == erasedUint8)
+ ) {
+ clearLoop++;
+ }
+
+ //
+ // Check to see if there was not enough room for the file
+ //
+ if (clearLoop < NewFileSize) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CommonLibBinderCopyMem (NewFile, File, NewFileSize);
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+FvBufCompact3ByteSize (
+ OUT VOID* SizeDest,
+ IN UINT32 Size
+ )
+/*++
+
+Routine Description:
+
+ Expands the 3 byte size commonly used in Firmware Volume data structures
+
+Arguments:
+
+ Size - Address of the 3 byte array representing the size
+
+Returns:
+
+ UINT32
+
+--*/
+{
+ ((UINT8*)SizeDest)[0] = (UINT8)Size;
+ ((UINT8*)SizeDest)[1] = (UINT8)(Size >> 8);
+ ((UINT8*)SizeDest)[2] = (UINT8)(Size >> 16);
+}
+
+UINT32
+FvBufExpand3ByteSize (
+ IN VOID* Size
+ )
+/*++
+
+Routine Description:
+
+ Expands the 3 byte size commonly used in Firmware Volume data structures
+
+Arguments:
+
+ Size - Address of the 3 byte array representing the size
+
+Returns:
+
+ UINT32
+
+--*/
+{
+ return (((UINT8*)Size)[2] << 16) +
+ (((UINT8*)Size)[1] << 8) +
+ ((UINT8*)Size)[0];
+}
+
+EFI_STATUS
+FvBufFindNextFile (
+ IN VOID *Fv,
+ IN OUT UINTN *Key,
+ OUT VOID **File
+ )
+/*++
+
+Routine Description:
+
+ Iterates through the files contained within the firmware volume
+
+Arguments:
+
+ Fv - Address of the Fv in memory
+ Key - Should be 0 to get the first file. After that, it should be
+ passed back in without modifying it's contents to retrieve
+ subsequent files.
+ File - Output file pointer
+ File == NULL - invalid parameter
+ otherwise - *File will be update to the location of the file
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+ EFI_VOLUME_CORRUPTED
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
+
+ EFI_FFS_FILE_HEADER *fhdr = NULL;
+ EFI_FVB_ATTRIBUTES FvbAttributes;
+ UINTN fsize;
+
+ EFI_STATUS Status;
+ UINTN fvSize;
+
+ if (Fv == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = FvBufGetSize (Fv, &fvSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (*Key == 0) {
+ *Key = hdr->HeaderLength;
+ }
+
+ FvbAttributes = hdr->Attributes;
+
+ for(
+ *Key = (UINTN)ALIGN_POINTER (*Key, 8);
+ (*Key + sizeof (*fhdr)) < fvSize;
+ *Key = (UINTN)ALIGN_POINTER (*Key, 8)
+ ) {
+
+ fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key);
+ fsize = FvBufExpand3ByteSize (fhdr->Size);
+
+ if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
+ FvbAttributes,
+ fhdr->State,
+ EFI_FILE_HEADER_VALID
+ ) ||
+ EFI_TEST_FFS_ATTRIBUTES_BIT(
+ FvbAttributes,
+ fhdr->State,
+ EFI_FILE_HEADER_INVALID
+ )
+ ) {
+ *Key = *Key + 1; // Make some forward progress
+ continue;
+ } else if(
+ EFI_TEST_FFS_ATTRIBUTES_BIT(
+ FvbAttributes,
+ fhdr->State,
+ EFI_FILE_MARKED_FOR_UPDATE
+ ) ||
+ EFI_TEST_FFS_ATTRIBUTES_BIT(
+ FvbAttributes,
+ fhdr->State,
+ EFI_FILE_DELETED
+ )
+ ) {
+ *Key = *Key + fsize;
+ continue;
+ } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
+ FvbAttributes,
+ fhdr->State,
+ EFI_FILE_DATA_VALID
+ )
+ ) {
+ *File = (UINT8*)hdr + *Key;
+ *Key = *Key + fsize;
+ return EFI_SUCCESS;
+ }
+
+ *Key = *Key + 1; // Make some forward progress
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+FvBufFindFileByName (
+ IN VOID *Fv,
+ IN EFI_GUID *Name,
+ OUT VOID **File
+ )
+/*++
+
+Routine Description:
+
+ Searches the Fv for a file by its name
+
+Arguments:
+
+ Fv - Address of the Fv in memory
+ Name - Guid filename to search for in the firmware volume
+ File - Output file pointer
+ File == NULL - Only determine if the file exists, based on return
+ value from the function call.
+ otherwise - *File will be update to the location of the file
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+ EFI_VOLUME_CORRUPTED
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Key;
+ EFI_FFS_FILE_HEADER *NextFile;
+
+ Key = 0;
+ while (TRUE) {
+ Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {
+ if (File != NULL) {
+ *File = NextFile;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+FvBufFindFileByType (
+ IN VOID *Fv,
+ IN EFI_FV_FILETYPE Type,
+ OUT VOID **File
+ )
+/*++
+
+Routine Description:
+
+ Searches the Fv for a file by its type
+
+Arguments:
+
+ Fv - Address of the Fv in memory
+ Type - FFS FILE type to search for
+ File - Output file pointer
+ (File == NULL) -> Only determine if the file exists, based on return
+ value from the function call.
+ otherwise -> *File will be update to the location of the file
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+ EFI_VOLUME_CORRUPTED
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Key;
+ EFI_FFS_FILE_HEADER *NextFile;
+
+ Key = 0;
+ while (TRUE) {
+ Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Type == NextFile->Type) {
+ if (File != NULL) {
+ *File = NextFile;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+FvBufGetFileRawData (
+ IN VOID* FfsFile,
+ OUT VOID** RawData,
+ OUT UINTN* RawDataSize
+ )
+/*++
+
+Routine Description:
+
+ Searches the requested file for raw data.
+
+ This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
+ or finds the EFI_SECTION_RAW section within the file and returns its data.
+
+Arguments:
+
+ FfsFile - Address of the FFS file in memory
+ RawData - Pointer to the raw data within the file
+ (This is NOT allocated. It is within the file.)
+ RawDataSize - Size of the raw data within the file
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER* File;
+ EFI_RAW_SECTION* Section;
+
+ File = (EFI_FFS_FILE_HEADER*)FfsFile;
+
+ //
+ // Is the file type == EFI_FV_FILETYPE_RAW?
+ //
+ if (File->Type == EFI_FV_FILETYPE_RAW) {
+ //
+ // Raw filetypes don't have sections, so we just return the raw data
+ //
+ *RawData = (VOID*)(File + 1);
+ *RawDataSize = FvBufExpand3ByteSize (File->Size) - sizeof (*File);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Within the file, we now need to find the EFI_SECTION_RAW section.
+ //
+ Status = FvBufFindSectionByType (File, EFI_SECTION_RAW, (VOID **)&Section);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *RawData = (VOID*)(Section + 1);
+ *RawDataSize =
+ FvBufExpand3ByteSize (Section->Size) - sizeof (*Section);
+
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+FvBufPackageFreeformRawFile (
+ IN EFI_GUID* Filename,
+ IN VOID* RawData,
+ IN UINTN RawDataSize,
+ OUT VOID** FfsFile
+ )
+/*++
+
+Routine Description:
+
+ Packages up a FFS file containing the input raw data.
+
+ The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
+ contain one EFI_FV_FILETYPE_RAW section.
+
+Arguments:
+
+ RawData - Pointer to the raw data to be packed
+ RawDataSize - Size of the raw data to be packed
+ FfsFile - Address of the packaged FFS file.
+ Note: The called must deallocate this memory!
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ EFI_FFS_FILE_HEADER* NewFile;
+ UINT32 NewFileSize;
+ EFI_RAW_SECTION* NewSection;
+ UINT32 NewSectionSize;
+
+ //
+ // The section size is the DataSize + the size of the section header
+ //
+ NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize;
+
+ //
+ // The file size is the size of the file header + the section size
+ //
+ NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize;
+
+ //
+ // Try to allocate a buffer to build the new FFS file in
+ //
+ NewFile = CommonLibBinderAllocate (NewFileSize);
+ if (NewFile == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CommonLibBinderSetMem (NewFile, NewFileSize, 0);
+
+ //
+ // The NewSection follow right after the FFS file header
+ //
+ NewSection = (EFI_RAW_SECTION*)(NewFile + 1);
+ FvBufCompact3ByteSize (NewSection->Size, NewSectionSize);
+ NewSection->Type = EFI_SECTION_RAW;
+
+ //
+ // Copy the actual file data into the buffer
+ //
+ CommonLibBinderCopyMem (NewSection + 1, RawData, RawDataSize);
+
+ //
+ // Initialize the FFS file header
+ //
+ CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID));
+ FvBufCompact3ByteSize (NewFile->Size, NewFileSize);
+ NewFile->Type = EFI_FV_FILETYPE_FREEFORM;
+ NewFile->Attributes = 0;
+ NewFile->IntegrityCheck.Checksum.Header =
+ FvBufCalculateChecksum8 ((UINT8*)NewFile, sizeof (*NewFile));
+ NewFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ NewFile->State = (UINT8)~( EFI_FILE_HEADER_CONSTRUCTION |
+ EFI_FILE_HEADER_VALID |
+ EFI_FILE_DATA_VALID
+ );
+
+ *FfsFile = NewFile;
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FvBufFindNextSection (
+ IN VOID *SectionsStart,
+ IN UINTN TotalSectionsSize,
+ IN OUT UINTN *Key,
+ OUT VOID **Section
+ )
+/*++
+
+Routine Description:
+
+ Iterates through the sections contained within a given array of sections
+
+Arguments:
+
+ SectionsStart - Address of the start of the FFS sections array
+ TotalSectionsSize - Total size of all the sections
+ Key - Should be 0 to get the first section. After that, it should be
+ passed back in without modifying it's contents to retrieve
+ subsequent files.
+ Section - Output section pointer
+ (Section == NULL) -> invalid parameter
+ otherwise -> *Section will be update to the location of the file
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+ EFI_VOLUME_CORRUPTED
+
+--*/
+{
+ EFI_COMMON_SECTION_HEADER *sectionHdr;
+ UINTN sectionSize;
+
+ *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned
+
+ if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) {
+ return EFI_NOT_FOUND;
+ }
+
+ sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key);
+ sectionSize = FvBufExpand3ByteSize (sectionHdr->Size);
+
+ if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) {
+ return EFI_NOT_FOUND;
+ }
+
+ if ((*Key + sectionSize) > TotalSectionsSize) {
+ return EFI_NOT_FOUND;
+ }
+
+ *Section = (UINT8*)sectionHdr;
+ *Key = *Key + sectionSize;
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+FvBufCountSections (
+ IN VOID* FfsFile,
+ IN UINTN* Count
+ )
+/*++
+
+Routine Description:
+
+ Searches the FFS file and counts the number of sections found.
+ The sections are NOT recursed.
+
+Arguments:
+
+ FfsFile - Address of the FFS file in memory
+ Count - The location to store the section count in
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+ EFI_VOLUME_CORRUPTED
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Key;
+ VOID* SectionStart;
+ UINTN TotalSectionsSize;
+ EFI_COMMON_SECTION_HEADER* NextSection;
+
+ SectionStart = (VOID*)((UINTN)FfsFile + sizeof (EFI_FFS_FILE_HEADER));
+ TotalSectionsSize =
+ FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)FfsFile)->Size) -
+ sizeof (EFI_FFS_FILE_HEADER);
+ Key = 0;
+ *Count = 0;
+ while (TRUE) {
+ Status = FvBufFindNextSection (
+ SectionStart,
+ TotalSectionsSize,
+ &Key,
+ (VOID **)&NextSection
+ );
+ if (Status == EFI_NOT_FOUND) {
+ return EFI_SUCCESS;
+ } else if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Increment the section counter
+ //
+ *Count += 1;
+
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+FvBufFindSectionByType (
+ IN VOID *FfsFile,
+ IN UINT8 Type,
+ OUT VOID **Section
+ )
+/*++
+
+Routine Description:
+
+ Searches the FFS file for a section by its type
+
+Arguments:
+
+ FfsFile - Address of the FFS file in memory
+ Type - FFS FILE section type to search for
+ Section - Output section pointer
+ (Section == NULL) -> Only determine if the section exists, based on return
+ value from the function call.
+ otherwise -> *Section will be update to the location of the file
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+ EFI_VOLUME_CORRUPTED
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Key;
+ VOID* SectionStart;
+ UINTN TotalSectionsSize;
+ EFI_COMMON_SECTION_HEADER* NextSection;
+
+ SectionStart = (VOID*)((UINTN)FfsFile + sizeof (EFI_FFS_FILE_HEADER));
+ TotalSectionsSize =
+ FvBufExpand3ByteSize (((EFI_FFS_FILE_HEADER*)FfsFile)->Size) -
+ sizeof (EFI_FFS_FILE_HEADER);
+ Key = 0;
+ while (TRUE) {
+ Status = FvBufFindNextSection (
+ SectionStart,
+ TotalSectionsSize,
+ &Key,
+ (VOID **)&NextSection
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Type == NextSection->Type) {
+ if (Section != NULL) {
+ *Section = NextSection;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+FvBufShrinkWrap (
+ IN VOID *Fv
+ )
+/*++
+
+Routine Description:
+
+ Shrinks a firmware volume (in place) to provide a minimal FV.
+
+ BUGBUG: Does not handle the case where the firmware volume has a
+ VTF (Volume Top File). The VTF will not be moved to the
+ end of the extended FV.
+
+Arguments:
+
+ Fv - Firmware volume.
+
+Returns:
+
+ EFI_SUCCESS
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN OldSize;
+ UINT32 BlockCount;
+ UINT32 NewBlockSize = 128;
+ UINTN Key;
+ EFI_FFS_FILE_HEADER* FileIt;
+ VOID* EndOfLastFile;
+
+ EFI_FIRMWARE_VOLUME_HEADER* FvHdr;
+
+ Status = FvBufGetSize (Fv, &OldSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FvBufUnifyBlockSizes (Fv, NewBlockSize);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Locate the block map in the fv header
+ //
+ FvHdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
+
+ //
+ // Find the end of the last file
+ //
+ Key = 0;
+ EndOfLastFile = (UINT8*)FvHdr + FvHdr->FvLength;
+ while (!EFI_ERROR (FvBufFindNextFile (Fv, &Key, (VOID **)&FileIt))) {
+ EndOfLastFile =
+ (VOID*)((UINT8*)FileIt + FvBufExpand3ByteSize (FileIt->Size));
+ }
+
+ //
+ // Set the BlockCount to have the minimal number of blocks for the Fv.
+ //
+ BlockCount = (UINT32)((UINTN)EndOfLastFile - (UINTN)Fv);
+ BlockCount = BlockCount + NewBlockSize - 1;
+ BlockCount = BlockCount / NewBlockSize;
+
+ //
+ // Adjust the block count to shrink the Fv in place.
+ //
+ FvHdr->BlockMap[0].NumBlocks = BlockCount;
+ FvHdr->FvLength = BlockCount * NewBlockSize;
+
+ //
+ // Update the FV header checksum
+ //
+ FvBufChecksumHeader (Fv);
+
+ return EFI_SUCCESS;
+
+}
+
+
+EFI_STATUS
+FvBufUnifyBlockSizes (
+ IN OUT VOID *Fv,
+ IN UINTN BlockSize
+ )
+/*++
+
+Routine Description:
+
+ Searches the FFS file for a section by its type
+
+Arguments:
+
+ Fv - Address of the Fv in memory
+ BlockSize - The size of the blocks to convert the Fv to. If the total size
+ of the Fv is not evenly divisible by this size, then
+ EFI_INVALID_PARAMETER will be returned.
+
+Returns:
+
+ EFI_SUCCESS
+ EFI_NOT_FOUND
+ EFI_VOLUME_CORRUPTED
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
+ EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;
+ UINT32 Size;
+
+ Size = 0;
+
+ //
+ // Scan through the block map list, performing error checking, and adding
+ // up the total Fv size.
+ //
+ while( blk->Length != 0 ||
+ blk->NumBlocks != 0
+ ) {
+ Size = Size + (blk->Length * blk->NumBlocks);
+ blk++;
+ if ((UINT8*)blk > ((UINT8*)hdr + hdr->HeaderLength)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+ }
+
+ //
+ // Make sure that the Fv size is a multiple of the new block size.
+ //
+ if ((Size % BlockSize) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Zero out the entire block map.
+ //
+ CommonLibBinderSetMem (
+ &hdr->BlockMap,
+ (UINTN)blk - (UINTN)&hdr->BlockMap,
+ 0
+ );
+
+ //
+ // Write out the single block map entry.
+ //
+ hdr->BlockMap[0].Length = (UINT32)BlockSize;
+ hdr->BlockMap[0].NumBlocks = Size / (UINT32)BlockSize;
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+UINT16
+FvBufCalculateSum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description:
+
+ This function calculates the UINT16 sum for the requested region.
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 16 bit checksum
+
+--*/
+{
+ UINTN Index;
+ UINT16 Sum;
+
+ Sum = 0;
+
+ //
+ // Perform the word sum for buffer
+ //
+ for (Index = 0; Index < Size; Index++) {
+ Sum = (UINT16) (Sum + Buffer[Index]);
+ }
+
+ return (UINT16) Sum;
+}
+
+
+STATIC
+UINT16
+FvBufCalculateChecksum16 (
+ IN UINT16 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Routine Description::
+
+ This function calculates the value needed for a valid UINT16 checksum
+
+Arguments:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Returns:
+
+ The 16 bit checksum value needed.
+
+--*/
+{
+ return (UINT16)(0x10000 - FvBufCalculateSum16 (Buffer, Size));
+}
+
+
+STATIC
+UINT8
+FvBufCalculateSum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Description:
+
+ This function calculates the UINT8 sum for the requested region.
+
+Input:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Return:
+
+ The 8 bit checksum value needed.
+
+--*/
+{
+ UINTN Index;
+ UINT8 Sum;
+
+ Sum = 0;
+
+ //
+ // Perform the byte sum for buffer
+ //
+ for (Index = 0; Index < Size; Index++) {
+ Sum = (UINT8) (Sum + Buffer[Index]);
+ }
+
+ return Sum;
+}
+
+
+STATIC
+UINT8
+FvBufCalculateChecksum8 (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+/*++
+
+Description:
+
+ This function calculates the value needed for a valid UINT8 checksum
+
+Input:
+
+ Buffer Pointer to buffer containing byte data of component.
+ Size Size of the buffer
+
+Return:
+
+ The 8 bit checksum value needed.
+
+--*/
+{
+ return (UINT8)(0x100 - FvBufCalculateSum8 (Buffer, Size));
+}
+
+
diff --git a/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h b/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h
new file mode 100644
index 0000000000..5a52695a7f
--- /dev/null
+++ b/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h
@@ -0,0 +1,166 @@
+/** @file
+
+Copyright (c) 1999 - 2008, 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:
+
+ FirmwareVolumeBufferLib.h
+
+Abstract:
+
+ EFI Firmware Volume routines which work on a Fv image in buffers.
+
+**/
+
+#ifndef FirmwareVolumeBuffer_h_INCLUDED
+#define FirmwareVolumeBuffer_h_INCLUDED
+
+#include "Common/UefiBaseTypes.h"
+#include "Common/PiFirmwareFile.h"
+#include "Common/PiFirmwareVolume.h"
+
+EFI_STATUS
+FvBufAddFile (
+ IN OUT VOID *Fv,
+ IN VOID *File
+ );
+
+EFI_STATUS
+FvBufAddFileWithExtend (
+ IN OUT VOID **Fv,
+ IN VOID *File
+ );
+
+EFI_STATUS
+FvBufAddVtfFile (
+ IN OUT VOID *Fv,
+ IN VOID *File
+ );
+
+EFI_STATUS
+FvBufChecksumFile (
+ IN OUT VOID *FfsFile
+ );
+
+EFI_STATUS
+FvBufChecksumHeader (
+ IN OUT VOID *Fv
+ );
+
+EFI_STATUS
+FvBufClearAllFiles (
+ IN OUT VOID *Fv
+ );
+
+VOID
+FvBufCompact3ByteSize (
+ OUT VOID* SizeDest,
+ IN UINT32 Size
+ );
+
+EFI_STATUS
+FvBufCountSections (
+ IN VOID* FfsFile,
+ IN UINTN* Count
+ );
+
+EFI_STATUS
+FvBufDuplicate (
+ IN VOID *SourceFv,
+ IN OUT VOID **DestinationFv
+ );
+
+UINT32
+FvBufExpand3ByteSize (
+ IN VOID* Size
+ );
+
+EFI_STATUS
+FvBufExtend (
+ IN VOID **Fv,
+ IN UINTN Size
+ );
+
+EFI_STATUS
+FvBufFindFileByName (
+ IN VOID *Fv,
+ IN EFI_GUID *Name,
+ OUT VOID **File
+ );
+
+EFI_STATUS
+FvBufFindFileByType (
+ IN VOID *Fv,
+ IN EFI_FV_FILETYPE Type,
+ OUT VOID **File
+ );
+
+EFI_STATUS
+FvBufFindNextFile (
+ IN VOID *Fv,
+ IN OUT UINTN *Key,
+ OUT VOID **File
+ );
+
+EFI_STATUS
+FvBufFindNextSection (
+ IN VOID *SectionsStart,
+ IN UINTN TotalSectionsSize,
+ IN OUT UINTN *Key,
+ OUT VOID **Section
+ );
+
+EFI_STATUS
+FvBufFindSectionByType (
+ IN VOID *FfsFile,
+ IN UINT8 Type,
+ OUT VOID **Section
+ );
+
+EFI_STATUS
+FvBufGetFileRawData (
+ IN VOID* FfsFile,
+ OUT VOID** RawData,
+ OUT UINTN* RawDataSize
+ );
+
+EFI_STATUS
+FvBufGetSize (
+ IN VOID *Fv,
+ OUT UINTN *Size
+ );
+
+EFI_STATUS
+FvBufPackageFreeformRawFile (
+ IN EFI_GUID* Filename,
+ IN VOID* RawData,
+ IN UINTN RawDataSize,
+ OUT VOID** FfsFile
+ );
+
+EFI_STATUS
+FvBufRemoveFile (
+ IN OUT VOID *Fv,
+ IN EFI_GUID *Name
+ );
+
+EFI_STATUS
+FvBufUnifyBlockSizes (
+ IN OUT VOID *Fv,
+ IN UINTN BlockSize
+ );
+
+EFI_STATUS
+FvBufShrinkWrap (
+ IN VOID *Fv
+ );
+
+#endif // #ifndef FirmwareVolumeBuffer_h_INCLUDED
+
diff --git a/BaseTools/Source/C/Common/FvLib.c b/BaseTools/Source/C/Common/FvLib.c
new file mode 100644
index 0000000000..292b077f34
--- /dev/null
+++ b/BaseTools/Source/C/Common/FvLib.c
@@ -0,0 +1,850 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ FvLib.c
+
+Abstract:
+
+ These functions assist in parsing and manipulating a Firmware Volume.
+
+**/
+
+//
+// Include files
+//
+#include "FvLib.h"
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+//
+// Module global variables
+//
+EFI_FIRMWARE_VOLUME_HEADER *mFvHeader = NULL;
+UINT32 mFvLength = 0;
+
+//
+// External function implementations
+//
+EFI_STATUS
+InitializeFvLib (
+ IN VOID *Fv,
+ IN UINT32 FvLength
+ )
+/*++
+
+Routine Description:
+
+ This initializes the FV lib with a pointer to the FV and length. It does not
+ verify the FV in any way.
+
+Arguments:
+
+ Fv Buffer containing the FV.
+ FvLength Length of the FV
+
+Returns:
+
+ EFI_SUCCESS Function Completed successfully.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+
+--*/
+{
+ //
+ // Verify input arguments
+ //
+ if (Fv == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv;
+ mFvLength = FvLength;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFvHeader (
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader,
+ OUT UINT32 *FvLength
+ )
+/*++
+
+Routine Description:
+
+ This function returns a pointer to the current FV and the size.
+
+Arguments:
+
+ FvHeader Pointer to the FV buffer.
+ FvLength Length of the FV
+
+Returns:
+
+ EFI_SUCCESS Function Completed successfully.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+ EFI_ABORTED The library needs to be initialized.
+
+--*/
+{
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input arguments
+ //
+ if (FvHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *FvHeader = mFvHeader;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetNextFile (
+ IN EFI_FFS_FILE_HEADER *CurrentFile,
+ OUT EFI_FFS_FILE_HEADER **NextFile
+ )
+/*++
+
+Routine Description:
+
+ This function returns the next file. If the current file is NULL, it returns
+ the first file in the FV. If the function returns EFI_SUCCESS and the file
+ pointer is NULL, then there are no more files in the FV.
+
+Arguments:
+
+ CurrentFile Pointer to the current file, must be within the current FV.
+ NextFile Pointer to the next file in the FV.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
+ EFI_ABORTED The library needs to be initialized.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input arguments
+ //
+ if (NextFile == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Get first file
+ //
+ if (CurrentFile == NULL) {
+ CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength);
+
+ //
+ // Verify file is valid
+ //
+ Status = VerifyFfsFile (CurrentFile);
+ if (EFI_ERROR (Status)) {
+ //
+ // no files in this FV
+ //
+ *NextFile = NULL;
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Verify file is in this FV.
+ //
+ if ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) {
+ *NextFile = NULL;
+ return EFI_SUCCESS;
+ }
+
+ *NextFile = CurrentFile;
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // Verify current file is in range
+ //
+ if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) ||
+ ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Get next file, compensate for 8 byte alignment if necessary.
+ //
+ *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3));
+
+ //
+ // Verify file is in this FV.
+ //
+ if (((UINTN) *NextFile + sizeof (EFI_FFS_FILE_HEADER) >= (UINTN) mFvHeader + mFvLength) ||
+ ((UINTN) *NextFile + GetLength ((*NextFile)->Size) > (UINTN) mFvHeader + mFvLength)
+ ) {
+ *NextFile = NULL;
+ return EFI_SUCCESS;
+ }
+ //
+ // Verify file is valid
+ //
+ Status = VerifyFfsFile (*NextFile);
+ if (EFI_ERROR (Status)) {
+ //
+ // no more files in this FV
+ //
+ *NextFile = NULL;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFileByName (
+ IN EFI_GUID *FileName,
+ OUT EFI_FFS_FILE_HEADER **File
+ )
+/*++
+
+Routine Description:
+
+ Find a file by name. The function will return NULL if the file is not found.
+
+Arguments:
+
+ FileName The GUID file name of the file to search for.
+ File Return pointer. In the case of an error, contents are undefined.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_ABORTED An error was encountered.
+ EFI_INVALID_PARAMETER One of the parameters was NULL.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *CurrentFile;
+ EFI_STATUS Status;
+ CHAR8 FileGuidString[80];
+
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input parameters
+ //
+ if (FileName == NULL || File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // File Guid String Name
+ //
+ PrintGuidToBuffer (FileName, (UINT8 *)FileGuidString, sizeof (FileGuidString), TRUE);
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Get the first file
+ //
+ Status = GetNextFile (NULL, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString);
+ return EFI_ABORTED;
+ }
+ //
+ // Loop as long as we have a valid file
+ //
+ while (CurrentFile) {
+ if (!CompareGuid (&CurrentFile->Name, FileName)) {
+ *File = CurrentFile;
+ return EFI_SUCCESS;
+ }
+
+ Status = GetNextFile (CurrentFile, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString);
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // File not found in this FV.
+ //
+ *File = NULL;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetFileByType (
+ IN EFI_FV_FILETYPE FileType,
+ IN UINTN Instance,
+ OUT EFI_FFS_FILE_HEADER **File
+ )
+/*++
+
+Routine Description:
+
+ Find a file by type and instance. An instance of 1 is the first instance.
+ The function will return NULL if a matching file cannot be found.
+ File type EFI_FV_FILETYPE_ALL means any file type is valid.
+
+Arguments:
+
+ FileType Type of file to search for.
+ Instance Instace of the file type to return.
+ File Return pointer. In the case of an error, contents are undefined.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_ABORTED An error was encountered.
+ EFI_INVALID_PARAMETER One of the parameters was NULL.
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *CurrentFile;
+ EFI_STATUS Status;
+ UINTN FileCount;
+
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input parameters
+ //
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Initialize the number of matching files found.
+ //
+ FileCount = 0;
+
+ //
+ // Get the first file
+ //
+ Status = GetNextFile (NULL, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType);
+ return EFI_ABORTED;
+ }
+ //
+ // Loop as long as we have a valid file
+ //
+ while (CurrentFile) {
+ if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) {
+ FileCount++;
+ }
+
+ if (FileCount == Instance) {
+ *File = CurrentFile;
+ return EFI_SUCCESS;
+ }
+
+ Status = GetNextFile (CurrentFile, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType);
+ return EFI_ABORTED;
+ }
+ }
+
+ *File = NULL;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+SearchSectionByType (
+ IN EFI_FILE_SECTION_POINTER FirstSection,
+ IN UINT8 *SearchEnd,
+ IN EFI_SECTION_TYPE SectionType,
+ IN OUT UINTN *StartIndex,
+ IN UINTN Instance,
+ OUT EFI_FILE_SECTION_POINTER *Section
+ )
+/*++
+
+Routine Description:
+
+ Helper function to search a sequence of sections from the section pointed
+ by FirstSection to SearchEnd for the Instance-th section of type SectionType.
+ The current counter is saved in StartIndex and when the section is found, it's
+ saved in Section. GUID-defined sections, if special processing is not required,
+ are searched recursively in a depth-first manner.
+
+Arguments:
+
+ FirstSection The first section to start searching from.
+ SearchEnd The end address to stop search.
+ SectionType The type of section to search.
+ StartIndex The current counter is saved.
+ Instance The requested n-th section number.
+ Section The found section returned.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_NOT_FOUND The section is not found.
+--*/
+{
+ EFI_FILE_SECTION_POINTER CurrentSection;
+ EFI_FILE_SECTION_POINTER InnerSection;
+ EFI_STATUS Status;
+ UINTN SectionSize;
+
+ CurrentSection = FirstSection;
+
+ while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) {
+ if (CurrentSection.CommonHeader->Type == SectionType) {
+ (*StartIndex)++;
+ }
+
+ if (*StartIndex == Instance) {
+ *Section = CurrentSection;
+ return EFI_SUCCESS;
+ }
+ //
+ // If the requesting section is not GUID-defined and
+ // we find a GUID-defined section that doesn't need
+ // special processing, go ahead to search the requesting
+ // section inside the GUID-defined section.
+ //
+ if (SectionType != EFI_SECTION_GUID_DEFINED &&
+ CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED &&
+ !(CurrentSection.GuidDefinedSection->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {
+ InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *)
+ ((UINTN) CurrentSection.CommonHeader + CurrentSection.GuidDefinedSection->DataOffset);
+ SectionSize = CurrentSection.CommonHeader->Size[0] +
+ (CurrentSection.CommonHeader->Size[1] << 8) +
+ (CurrentSection.CommonHeader->Size[2] << 16);
+ Status = SearchSectionByType (
+ InnerSection,
+ (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize),
+ SectionType,
+ StartIndex,
+ Instance,
+ Section
+ );
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+ }
+ //
+ // Find next section (including compensating for alignment issues.
+ //
+ CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2));
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+GetSectionByType (
+ IN EFI_FFS_FILE_HEADER *File,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
+ OUT EFI_FILE_SECTION_POINTER *Section
+ )
+/*++
+
+Routine Description:
+
+ Find a section in a file by type and instance. An instance of 1 is the first
+ instance. The function will return NULL if a matching section cannot be found.
+ GUID-defined sections, if special processing is not needed, are handled in a
+ depth-first manner.
+
+Arguments:
+
+ File The file to search.
+ SectionType Type of file to search for.
+ Instance Instace of the section to return.
+ Section Return pointer. In the case of an error, contents are undefined.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_ABORTED An error was encountered.
+ EFI_INVALID_PARAMETER One of the parameters was NULL.
+ EFI_NOT_FOUND No found.
+--*/
+{
+ EFI_FILE_SECTION_POINTER CurrentSection;
+ EFI_STATUS Status;
+ UINTN SectionCount;
+
+ //
+ // Verify input parameters
+ //
+ if (File == NULL || Instance == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Verify FFS header
+ //
+ Status = VerifyFfsFile (File);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0006, "invalid FFS file", NULL);
+ return EFI_ABORTED;
+ }
+ //
+ // Initialize the number of matching sections found.
+ //
+ SectionCount = 0;
+
+ //
+ // Get the first section
+ //
+ CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER));
+
+ //
+ // Depth-first manner to find section file.
+ //
+ Status = SearchSectionByType (
+ CurrentSection,
+ (UINT8 *) ((UINTN) File + GetLength (File->Size)),
+ SectionType,
+ &SectionCount,
+ Instance,
+ Section
+ );
+
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ } else {
+ //
+ // Section not found
+ //
+ (*Section).Code16Section = NULL;
+ return EFI_NOT_FOUND;
+ }
+}
+//
+// will not parse compressed sections
+//
+EFI_STATUS
+VerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+/*++
+
+Routine Description:
+
+ Verify the current pointer points to a valid FV header.
+
+Arguments:
+
+ FvHeader Pointer to an alleged FV file.
+
+Returns:
+
+ EFI_SUCCESS The FV header is valid.
+ EFI_VOLUME_CORRUPTED The FV header is not valid.
+ EFI_INVALID_PARAMETER A required parameter was NULL.
+ EFI_ABORTED Operation aborted.
+
+--*/
+{
+ UINT16 Checksum;
+
+ //
+ // Verify input parameters
+ //
+ if (FvHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
+ Error (NULL, 0, 0006, "invalid FV header signature", NULL);
+ return EFI_VOLUME_CORRUPTED;
+ }
+ //
+ // Verify header checksum
+ //
+ Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
+
+ if (Checksum != 0) {
+ Error (NULL, 0, 0006, "invalid FV header checksum", NULL);
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VerifyFfsFile (
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+
+ Verify the current pointer points to a FFS file header.
+
+Arguments:
+
+ FfsHeader Pointer to an alleged FFS file.
+
+Returns:
+
+ EFI_SUCCESS The Ffs header is valid.
+ EFI_NOT_FOUND This "file" is the beginning of free space.
+ EFI_VOLUME_CORRUPTED The Ffs header is not valid.
+ EFI_ABORTED The erase polarity is not known.
+
+--*/
+{
+ BOOLEAN ErasePolarity;
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER BlankHeader;
+ UINT8 Checksum;
+ UINT32 FileLength;
+ UINT8 SavedChecksum;
+ UINT8 SavedState;
+ UINT8 FileGuidString[80];
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Get the erase polarity.
+ //
+ Status = GetErasePolarity (&ErasePolarity);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Check if we have free space
+ //
+ if (ErasePolarity) {
+ memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));
+ } else {
+ memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
+ }
+
+ if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Convert the GUID to a string so we can at least report which file
+ // if we find an error.
+ //
+ PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);
+ //
+ // Verify file header checksum
+ //
+ SavedState = FfsHeader->State;
+ FfsHeader->State = 0;
+ SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;
+ FfsHeader->IntegrityCheck.Checksum.File = 0;
+ Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
+ FfsHeader->State = SavedState;
+ FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;
+ if (Checksum != 0) {
+ Error (NULL, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString);
+ return EFI_ABORTED;
+ }
+ //
+ // Verify file checksum
+ //
+ if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
+ //
+ // Verify file data checksum
+ //
+ FileLength = GetLength (FfsHeader->Size);
+ Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength);
+ Checksum = (UINT8) (Checksum - FfsHeader->State);
+ if (Checksum != 0) {
+ Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString);
+ return EFI_ABORTED;
+ }
+ } else {
+ //
+ // File does not have a checksum
+ // Verify contents are 0x5A as spec'd
+ //
+ if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
+ Error (NULL, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString);
+ return EFI_ABORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+UINT32
+GetLength (
+ UINT8 *ThreeByteLength
+ )
+/*++
+
+Routine Description:
+
+ Converts a three byte length value into a UINT32.
+
+Arguments:
+
+ ThreeByteLength Pointer to the first of the 3 byte length.
+
+Returns:
+
+ UINT32 Size of the section
+
+--*/
+{
+ UINT32 Length;
+
+ if (ThreeByteLength == NULL) {
+ return 0;
+ }
+
+ Length = *((UINT32 *) ThreeByteLength);
+ Length = Length & 0x00FFFFFF;
+
+ return Length;
+}
+
+EFI_STATUS
+GetErasePolarity (
+ OUT BOOLEAN *ErasePolarity
+ )
+/*++
+
+Routine Description:
+
+ This function returns with the FV erase polarity. If the erase polarity
+ for a bit is 1, the function return TRUE.
+
+Arguments:
+
+ ErasePolarity A pointer to the erase polarity.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+ EFI_ABORTED Operation aborted.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Verify library has been initialized.
+ //
+ if (mFvHeader == NULL || mFvLength == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify FV header
+ //
+ Status = VerifyFv (mFvHeader);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // Verify input parameters.
+ //
+ if (ErasePolarity == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mFvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
+ *ErasePolarity = TRUE;
+ } else {
+ *ErasePolarity = FALSE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+UINT8
+GetFileState (
+ IN BOOLEAN ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+
+ This function returns a the highest state bit in the FFS that is set.
+ It in no way validate the FFS file.
+
+Arguments:
+
+ ErasePolarity The erase polarity for the file state bits.
+ FfsHeader Pointer to a FFS file.
+
+Returns:
+
+ UINT8 The hightest set state of the file.
+
+--*/
+{
+ UINT8 FileState;
+ UINT8 HighestBit;
+
+ FileState = FfsHeader->State;
+
+ if (ErasePolarity) {
+ FileState = (UINT8)~FileState;
+ }
+
+ HighestBit = 0x80;
+ while (HighestBit != 0 && (HighestBit & FileState) == 0) {
+ HighestBit >>= 1;
+ }
+
+ return HighestBit;
+}
diff --git a/BaseTools/Source/C/Common/FvLib.h b/BaseTools/Source/C/Common/FvLib.h
new file mode 100644
index 0000000000..43d3737f68
--- /dev/null
+++ b/BaseTools/Source/C/Common/FvLib.h
@@ -0,0 +1,178 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ FvLib.h
+
+Abstract:
+
+ These functions assist in parsing and manipulating a Firmware Volume.
+
+**/
+
+#ifndef _EFI_FV_LIB_H
+#define _EFI_FV_LIB_H
+
+//
+// Include files
+//
+#include <string.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/PiFirmwareFile.h>
+#include <Common/PiFirmwareVolume.h>
+
+EFI_STATUS
+InitializeFvLib (
+ IN VOID *Fv,
+ IN UINT32 FvLength
+ )
+;
+
+EFI_STATUS
+GetFvHeader (
+ OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader,
+ OUT UINT32 *FvLength
+ )
+;
+
+EFI_STATUS
+GetNextFile (
+ IN EFI_FFS_FILE_HEADER *CurrentFile,
+ OUT EFI_FFS_FILE_HEADER **NextFile
+ )
+;
+
+EFI_STATUS
+GetFileByName (
+ IN EFI_GUID *FileName,
+ OUT EFI_FFS_FILE_HEADER **File
+ )
+;
+
+EFI_STATUS
+GetFileByType (
+ IN EFI_FV_FILETYPE FileType,
+ IN UINTN Instance,
+ OUT EFI_FFS_FILE_HEADER **File
+ )
+;
+
+EFI_STATUS
+GetSectionByType (
+ IN EFI_FFS_FILE_HEADER *File,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
+ OUT EFI_FILE_SECTION_POINTER *Section
+ )
+;
+//
+// will not parse compressed sections
+//
+EFI_STATUS
+VerifyFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
+ )
+;
+
+EFI_STATUS
+VerifyFfsFile (
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Verify the current pointer points to a FFS file header.
+
+Arguments:
+
+ FfsHeader Pointer to an alleged FFS file.
+
+Returns:
+
+ EFI_SUCCESS The Ffs header is valid.
+ EFI_NOT_FOUND This "file" is the beginning of free space.
+ EFI_VOLUME_CORRUPTED The Ffs header is not valid.
+
+--*/
+UINT32
+GetLength (
+ UINT8 *ThreeByteLength
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Converts a three byte length value into a UINT32.
+
+Arguments:
+
+ ThreeByteLength Pointer to the first of the 3 byte length.
+
+Returns:
+
+ UINT32 Size of the section
+
+--*/
+EFI_STATUS
+GetErasePolarity (
+ OUT BOOLEAN *ErasePolarity
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function returns with the FV erase polarity. If the erase polarity
+ for a bit is 1, the function return TRUE.
+
+Arguments:
+
+ ErasePolarity A pointer to the erase polarity.
+
+Returns:
+
+ EFI_SUCCESS The function completed successfully.
+ EFI_INVALID_PARAMETER One of the input parameters was invalid.
+
+--*/
+UINT8
+GetFileState (
+ IN BOOLEAN ErasePolarity,
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function returns a the highest state bit in the FFS that is set.
+ It in no way validate the FFS file.
+
+Arguments:
+
+ ErasePolarity The erase polarity for the file state bits.
+ FfsHeader Pointer to a FFS file.
+
+Returns:
+
+ UINT8 The hightest set state of the file.
+
+--*/
+#endif
diff --git a/BaseTools/Source/C/Common/GNUmakefile b/BaseTools/Source/C/Common/GNUmakefile
new file mode 100644
index 0000000000..df3108d923
--- /dev/null
+++ b/BaseTools/Source/C/Common/GNUmakefile
@@ -0,0 +1,28 @@
+ARCH ?= IA32
+MAKEROOT ?= ..
+
+# VPATH = ..
+
+LIBNAME = Common
+
+OBJECTS = \
+ BasePeCoff.o \
+ BinderFuncs.o \
+ CommonLib.o \
+ Crc32.o \
+ Decompress.o \
+ EfiCompress.o \
+ EfiUtilityMsgs.o \
+ FirmwareVolumeBuffer.o \
+ FvLib.o \
+ MemoryFile.o \
+ MyAlloc.o \
+ OsPath.o \
+ ParseGuidedSectionTools.o \
+ ParseInf.o \
+ PeCoffLoaderEx.o \
+ SimpleFileParsing.o \
+ StringFuncs.o \
+ TianoCompress.o
+
+include $(MAKEROOT)/Makefiles/lib.makefile
diff --git a/BaseTools/Source/C/Common/Makefile b/BaseTools/Source/C/Common/Makefile
new file mode 100644
index 0000000000..cdaa0065f3
--- /dev/null
+++ b/BaseTools/Source/C/Common/Makefile
@@ -0,0 +1,30 @@
+!INCLUDE ..\Makefiles\ms.common
+
+# VPATH = ..
+
+LIBNAME = Common
+
+OBJECTS = \
+ BasePeCoff.obj \
+ BinderFuncs.obj \
+ CommonLib.obj \
+ Crc32.obj \
+ Decompress.obj \
+ EfiCompress.obj \
+ EfiUtilityMsgs.obj \
+ FirmwareVolumeBuffer.obj \
+ FvLib.obj \
+ MemoryFile.obj \
+ MyAlloc.obj \
+ OsPath.obj \
+ ParseGuidedSectionTools.obj \
+ ParseInf.obj \
+ PeCoffLoaderEx.obj \
+ SimpleFileParsing.obj \
+ StringFuncs.obj \
+ TianoCompress.obj
+
+!INCLUDE ..\Makefiles\ms.lib
+
+
+
diff --git a/BaseTools/Source/C/Common/MemoryFile.c b/BaseTools/Source/C/Common/MemoryFile.c
new file mode 100644
index 0000000000..cace6282ac
--- /dev/null
+++ b/BaseTools/Source/C/Common/MemoryFile.c
@@ -0,0 +1,260 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ MemoryFile.c
+
+Abstract:
+
+ This contains some useful functions for accessing files.
+
+**/
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "CommonLib.h"
+#include "MemoryFile.h"
+
+
+//
+// Local (static) function prototypes
+//
+STATIC
+VOID
+CheckMemoryFileState (
+ IN EFI_HANDLE InputMemoryFile
+ );
+
+//
+// Function implementations
+//
+
+EFI_STATUS
+GetMemoryFile (
+ IN CHAR8 *InputFileName,
+ OUT EFI_HANDLE *OutputMemoryFile
+ )
+/*++
+
+Routine Description:
+
+ This opens a file, reads it into memory and returns a memory file
+ object.
+
+Arguments:
+
+ InputFile Memory file image.
+ OutputMemoryFile Handle to memory file
+
+Returns:
+
+ EFI_STATUS
+ OutputMemoryFile is valid if !EFI_ERROR
+
+--*/
+{
+ EFI_STATUS Status;
+ CHAR8 *InputFileImage;
+ UINT32 BytesRead;
+ MEMORY_FILE *NewMemoryFile;
+
+ Status = GetFileImage (InputFileName, &InputFileImage, &BytesRead);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ NewMemoryFile = malloc (sizeof (*NewMemoryFile));
+ if (NewMemoryFile == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewMemoryFile->FileImage = InputFileImage;
+ NewMemoryFile->CurrentFilePointer = InputFileImage;
+ NewMemoryFile->Eof = InputFileImage + BytesRead;
+
+ *OutputMemoryFile = (EFI_HANDLE)NewMemoryFile;
+
+ CheckMemoryFileState (*OutputMemoryFile);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+FreeMemoryFile (
+ IN EFI_HANDLE InputMemoryFile
+ )
+/*++
+
+Routine Description:
+
+ Frees all memory associated with the input memory file.
+
+Arguments:
+
+ InputMemoryFile Handle to memory file
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ MEMORY_FILE *MemoryFile;
+
+ CheckMemoryFileState (InputMemoryFile);
+
+ MemoryFile = (MEMORY_FILE*)InputMemoryFile;
+
+ free (MemoryFile->FileImage);
+
+ //
+ // Invalidate state of MEMORY_FILE structure to catch invalid usage.
+ //
+ memset (MemoryFile, 0xcc, sizeof (*MemoryFile));
+ MemoryFile->Eof -= 1;
+
+ free (MemoryFile);
+
+ return EFI_SUCCESS;
+}
+
+
+CHAR8 *
+ReadMemoryFileLine (
+ IN EFI_HANDLE InputMemoryFile
+ )
+/*++
+
+Routine Description:
+
+ This function reads a line from the memory file. The newline characters
+ are stripped and a null terminated string is returned.
+
+ If the string pointer returned is non-NULL, then the caller must free the
+ memory associated with this string.
+
+Arguments:
+
+ InputMemoryFile Handle to memory file
+
+Returns:
+
+ NULL if error or EOF
+ NULL character termincated string otherwise (MUST BE FREED BY CALLER)
+
+--*/
+{
+ CHAR8 *EndOfLine;
+ UINTN CharsToCopy;
+ MEMORY_FILE *InputFile;
+ UINTN BytesToEof;
+ CHAR8 *OutputString;
+
+ //
+ // Verify input parameters are not null
+ //
+ CheckMemoryFileState (InputMemoryFile);
+
+ InputFile = (MEMORY_FILE*)InputMemoryFile;
+
+ //
+ // Check for end of file condition
+ //
+ if (InputFile->CurrentFilePointer >= InputFile->Eof) {
+ return NULL;
+ }
+
+ //
+ // Determine the number of bytes remaining until the EOF
+ //
+ BytesToEof = InputFile->Eof - InputFile->CurrentFilePointer;
+
+ //
+ // Find the next newline char
+ //
+ EndOfLine = memchr (InputFile->CurrentFilePointer, '\n', BytesToEof);
+
+ //
+ // Determine the number of characters to copy.
+ //
+ if (EndOfLine == 0) {
+ //
+ // If no newline found, copy to the end of the file.
+ //
+ CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
+ } else {
+ //
+ // Newline found in the file.
+ //
+ CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;
+ }
+
+ OutputString = malloc (CharsToCopy);
+ if (OutputString == NULL) {
+ return NULL;
+ }
+
+ //
+ // Copy the line.
+ //
+ memcpy (OutputString, InputFile->CurrentFilePointer, CharsToCopy);
+
+ //
+ // Add the null termination over the 0x0D
+ //
+ if (OutputString[CharsToCopy - 1] == '\r') {
+
+ OutputString[CharsToCopy - 1] = '\0';
+
+ } else {
+
+ OutputString[CharsToCopy] = '\0';
+
+ }
+
+ //
+ // Increment the current file pointer (include the 0x0A)
+ //
+ InputFile->CurrentFilePointer += CharsToCopy + 1;
+ CheckMemoryFileState (InputMemoryFile);
+
+ //
+ // Return the string
+ //
+ return OutputString;
+}
+
+
+STATIC
+VOID
+CheckMemoryFileState (
+ IN EFI_HANDLE InputMemoryFile
+ )
+{
+ MEMORY_FILE *MemoryFile;
+
+ assert (InputMemoryFile != NULL);
+
+ MemoryFile = (MEMORY_FILE*)InputMemoryFile;
+
+ assert (MemoryFile->FileImage != NULL);
+ assert (MemoryFile->CurrentFilePointer != NULL);
+ assert (MemoryFile->Eof != NULL);
+ assert (MemoryFile->Eof >= MemoryFile->FileImage);
+ assert (MemoryFile->CurrentFilePointer >= MemoryFile->FileImage);
+ assert (MemoryFile->CurrentFilePointer <= MemoryFile->Eof);
+}
+
+
diff --git a/BaseTools/Source/C/Common/MemoryFile.h b/BaseTools/Source/C/Common/MemoryFile.h
new file mode 100644
index 0000000000..9148d9d06c
--- /dev/null
+++ b/BaseTools/Source/C/Common/MemoryFile.h
@@ -0,0 +1,122 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ MemoryFile.h
+
+Abstract:
+
+ Header file for helper functions useful for accessing files.
+
+**/
+
+#ifndef _EFI_MEMORY_FILE_H
+#define _EFI_MEMORY_FILE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Common/UefiBaseTypes.h>
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 500
+#endif
+
+//
+// Common data structures
+//
+typedef struct {
+ CHAR8 *FileImage;
+ CHAR8 *Eof;
+ CHAR8 *CurrentFilePointer;
+} MEMORY_FILE;
+
+
+//
+// Functions declarations
+//
+
+EFI_STATUS
+GetMemoryFile (
+ IN CHAR8 *InputFileName,
+ OUT EFI_HANDLE *OutputMemoryFile
+ )
+;
+/**
+
+Routine Description:
+
+ This opens a file, reads it into memory and returns a memory file
+ object.
+
+Arguments:
+
+ InputFile Memory file image.
+ OutputMemoryFile Handle to memory file
+
+Returns:
+
+ EFI_STATUS
+ OutputMemoryFile is valid if !EFI_ERROR
+
+**/
+
+
+EFI_STATUS
+FreeMemoryFile (
+ IN EFI_HANDLE InputMemoryFile
+ )
+;
+/**
+
+Routine Description:
+
+ Frees all memory associated with the input memory file.
+
+Arguments:
+
+ InputMemoryFile Handle to memory file
+
+Returns:
+
+ EFI_STATUS
+
+**/
+
+
+CHAR8 *
+ReadMemoryFileLine (
+ IN EFI_HANDLE InputMemoryFile
+ )
+;
+/**
+
+Routine Description:
+
+ This function reads a line from the memory file. The newline characters
+ are stripped and a null terminated string is returned.
+
+ If the string pointer returned is non-NULL, then the caller must free the
+ memory associated with this string.
+
+Arguments:
+
+ InputMemoryFile Handle to memory file
+
+Returns:
+
+ NULL if error or EOF
+ NULL character termincated string otherwise (MUST BE FREED BY CALLER)
+
+**/
+
+
+#endif
diff --git a/BaseTools/Source/C/Common/MyAlloc.c b/BaseTools/Source/C/Common/MyAlloc.c
new file mode 100644
index 0000000000..b53713941c
--- /dev/null
+++ b/BaseTools/Source/C/Common/MyAlloc.c
@@ -0,0 +1,516 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ MyAlloc.c
+
+Abstract:
+
+ File for memory allocation tracking functions.
+
+**/
+
+#include "MyAlloc.h"
+
+#if USE_MYALLOC
+//
+// Get back to original alloc/free calls.
+//
+#undef malloc
+#undef calloc
+#undef realloc
+#undef free
+//
+// Start of allocation list.
+//
+STATIC MY_ALLOC_STRUCT *MyAllocData = NULL;
+
+//
+//
+//
+STATIC UINT32 MyAllocHeadMagik = MYALLOC_HEAD_MAGIK;
+STATIC UINT32 MyAllocTailMagik = MYALLOC_TAIL_MAGIK;
+
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+//
+VOID
+MyCheck (
+ BOOLEAN Final,
+ UINT8 File[],
+ UINTN Line
+ )
+// *++
+// Description:
+//
+// Check for corruptions in the allocated memory chain. If a corruption
+// is detection program operation stops w/ an exit(1) call.
+//
+// Parameters:
+//
+// Final := When FALSE, MyCheck() returns if the allocated memory chain
+// has not been corrupted. When TRUE, MyCheck() returns if there
+// are no un-freed allocations. If there are un-freed allocations,
+// they are displayed and exit(1) is called.
+//
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// n/a
+//
+// --*/
+//
+{
+ MY_ALLOC_STRUCT *Tmp;
+
+ //
+ // Check parameters.
+ //
+ if (File == NULL || Line == 0) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)"
+ "Invalid parameter(s).\n",
+ Final,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen ((CHAR8 *)File) == 0) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)"
+ "Invalid parameter.\n",
+ Final,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+ //
+ // Check structure contents.
+ //
+ for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
+ if (memcmp(Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik) ||
+ memcmp(&Tmp->Buffer[Tmp->Size + sizeof(UINT32)], &MyAllocTailMagik, sizeof MyAllocTailMagik)) {
+ break;
+ }
+ }
+ //
+ // If Tmp is not NULL, the structure is corrupt.
+ //
+ if (Tmp != NULL) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"
+ "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
+ Final,
+ File,
+ (UINT32)Line,
+ Tmp->File,
+ (UINT32)Tmp->Line,
+ (UINT32)Tmp->Size,
+ *(UINT32 *) (Tmp->Buffer),
+ *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])
+ );
+
+ exit (1);
+ }
+ //
+ // If Final is TRUE, display the state of the structure chain.
+ //
+ if (Final) {
+ if (MyAllocData != NULL) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)"
+ "\nSome allocated items have not been freed.\n",
+ Final,
+ File,
+ (UINT32)Line
+ );
+
+ for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
+ printf (
+ "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
+ Tmp->File,
+ (UINT32)Tmp->Line,
+ (UINT32)Tmp->Size,
+ *(UINT32 *) (Tmp->Buffer),
+ *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])
+ );
+ }
+ }
+ }
+}
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+//
+VOID *
+MyAlloc (
+ UINTN Size,
+ UINT8 File[],
+ UINTN Line
+ )
+// *++
+// Description:
+//
+// Allocate a new link in the allocation chain along with enough storage
+// for the File[] string, requested Size and alignment overhead. If
+// memory cannot be allocated or the allocation chain has been corrupted,
+// exit(1) will be called.
+//
+// Parameters:
+//
+// Size := Number of bytes (UINT8) requested by the called.
+// Size cannot be zero.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// Pointer to the caller's buffer.
+//
+// --*/
+//
+{
+ MY_ALLOC_STRUCT *Tmp;
+ UINTN Len;
+
+ //
+ // Check for invalid parameters.
+ //
+ if (Size == 0 || File == NULL || Line == 0) {
+ printf (
+ "\nMyAlloc(Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ (UINT32)Size,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+
+ Len = strlen ((CHAR8 *)File);
+ if (Len == 0) {
+ printf (
+ "\nMyAlloc(Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ (UINT32)Size,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+ //
+ // Check the allocation list for corruption.
+ //
+ MyCheck (0, (UINT8 *)__FILE__, __LINE__);
+
+ //
+ // Allocate a new entry.
+ //
+ Tmp = calloc (
+ 1,
+ sizeof (MY_ALLOC_STRUCT) + Len + 1 + sizeof (UINT64) + Size + (sizeof MyAllocHeadMagik) + (sizeof MyAllocTailMagik)
+ );
+
+ if (Tmp == NULL) {
+ printf (
+ "\nMyAlloc(Size=%u, File=%s, Line=%u)"
+ "\nOut of memory.\n",
+ (UINT32)Size,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+ //
+ // Fill in the new entry.
+ //
+ Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT);
+ strcpy ((CHAR8 *)Tmp->File, (CHAR8 *)File);
+ Tmp->Line = Line;
+ Tmp->Size = Size;
+ Tmp->Buffer = (UINT8 *) (((UINTN) Tmp + Len + 9) &~7);
+
+ memcpy (Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik);
+
+ memcpy (
+ &Tmp->Buffer[Size + sizeof (UINT32)],
+ &MyAllocTailMagik,
+ sizeof MyAllocTailMagik
+ );
+
+ Tmp->Next = MyAllocData;
+ Tmp->Cksum = (UINTN) Tmp + (UINTN) (Tmp->Next) + Tmp->Line + Tmp->Size + (UINTN) (Tmp->File) + (UINTN) (Tmp->Buffer);
+
+ MyAllocData = Tmp;
+
+ return Tmp->Buffer + sizeof (UINT32);
+}
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+//
+VOID *
+MyRealloc (
+ VOID *Ptr,
+ UINTN Size,
+ UINT8 File[],
+ UINTN Line
+ )
+// *++
+// Description:
+//
+// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
+// for shrinking or expanding buffers. An invalid parameter will cause
+// MyRealloc() to fail with a call to exit(1).
+//
+// Parameters:
+//
+// Ptr := Pointer to the caller's buffer to be re-allocated.
+//
+// Size := Size of new buffer. Size cannot be zero.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// Pointer to new caller's buffer.
+//
+// --*/
+//
+{
+ MY_ALLOC_STRUCT *Tmp;
+ VOID *Buffer;
+
+ //
+ // Check for invalid parameter(s).
+ //
+ if (Size == 0 || File == NULL || Line == 0) {
+ printf (
+ "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Ptr,
+ (UINT32)Size,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen ((CHAR8 *)File) == 0) {
+ printf (
+ "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ Ptr,
+ (UINT32)Size,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+ //
+ // Find existing buffer in allocation list.
+ //
+ if (Ptr == NULL) {
+ Tmp = NULL;
+ } else if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {
+ Tmp = MyAllocData;
+ } else {
+ for (Tmp = MyAllocData;; Tmp = Tmp->Next) {
+ if (Tmp->Next == NULL) {
+ printf (
+ "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
+ "\nCould not find buffer.\n",
+ Ptr,
+ (UINT32)Size,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+
+ Tmp = Tmp->Next;
+ }
+ }
+ //
+ // Allocate new buffer, copy old data, free old buffer.
+ //
+ Buffer = MyAlloc (Size, File, Line);
+
+ if (Buffer != NULL && Tmp != NULL) {
+ memcpy (
+ Buffer,
+ &Tmp->Buffer[sizeof (UINT32)],
+ ((Size <= Tmp->Size) ? Size : Tmp->Size)
+ );
+
+ MyFree (Ptr, (UINT8 *)__FILE__, __LINE__);
+ }
+
+ return Buffer;
+}
+//
+// ////////////////////////////////////////////////////////////////////////////
+//
+//
+VOID
+MyFree (
+ VOID *Ptr,
+ UINT8 File[],
+ UINTN Line
+ )
+// *++
+// Description:
+//
+// Release a previously allocated buffer. Invalid parameters will cause
+// MyFree() to fail with an exit(1) call.
+//
+// Parameters:
+//
+// Ptr := Pointer to the caller's buffer to be freed.
+// A NULL pointer will be ignored.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// n/a
+//
+// --*/
+//
+{
+ MY_ALLOC_STRUCT *Tmp;
+ MY_ALLOC_STRUCT *Tmp2;
+
+ //
+ // Check for invalid parameter(s).
+ //
+ if (File == NULL || Line == 0) {
+ printf (
+ "\nMyFree(Ptr=%p, File=%s, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Ptr,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen ((CHAR8 *)File) == 0) {
+ printf (
+ "\nMyFree(Ptr=%p, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ Ptr,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+ //
+ // Freeing NULL is always valid.
+ //
+ if (Ptr == NULL) {
+ return ;
+ }
+ //
+ // Fail if nothing is allocated.
+ //
+ if (MyAllocData == NULL) {
+ printf (
+ "\nMyFree(Ptr=%p, File=%s, Line=%u)"
+ "\nCalled before memory allocated.\n",
+ Ptr,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+ //
+ // Check for corrupted allocation list.
+ //
+ MyCheck (0, (UINT8 *)__FILE__, __LINE__);
+
+ //
+ // Need special check for first item in list.
+ //
+ if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {
+ //
+ // Unlink first item in list.
+ //
+ Tmp = MyAllocData;
+ MyAllocData = MyAllocData->Next;
+ } else {
+ //
+ // Walk list looking for matching item.
+ //
+ for (Tmp = MyAllocData;; Tmp = Tmp->Next) {
+ //
+ // Fail if end of list is reached.
+ //
+ if (Tmp->Next == NULL) {
+ printf (
+ "\nMyFree(Ptr=%p, File=%s, Line=%u)\n"
+ "\nNot found.\n",
+ Ptr,
+ File,
+ (UINT32)Line
+ );
+
+ exit (1);
+ }
+ //
+ // Leave loop when match is found.
+ //
+ if (&Tmp->Next->Buffer[sizeof (UINT32)] == Ptr) {
+ break;
+ }
+ }
+ //
+ // Unlink item from list.
+ //
+ Tmp2 = Tmp->Next;
+ Tmp->Next = Tmp->Next->Next;
+ Tmp = Tmp2;
+ }
+ //
+ // Release item.
+ //
+ free (Tmp);
+}
+
+#endif /* USE_MYALLOC */
+
+/* eof - MyAlloc.c */
diff --git a/BaseTools/Source/C/Common/MyAlloc.h b/BaseTools/Source/C/Common/MyAlloc.h
new file mode 100644
index 0000000000..9dbe91cd41
--- /dev/null
+++ b/BaseTools/Source/C/Common/MyAlloc.h
@@ -0,0 +1,222 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ MyAlloc.h
+
+Abstract:
+
+ Header file for memory allocation tracking functions.
+
+**/
+
+#ifndef _MYALLOC_H_
+#define _MYALLOC_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <Common/BaseTypes.h>
+
+//
+// Default operation is to use the memory allocation tracking functions.
+// To over-ride add "#define USE_MYALLOC 0" to your program header and/or
+// source files as needed. Or, just do not include this header file in
+// your project.
+//
+#ifndef USE_MYALLOC
+#define USE_MYALLOC 1
+#endif
+
+#if USE_MYALLOC
+//
+// Replace C library allocation routines with MyAlloc routines.
+//
+#define malloc(size) MyAlloc ((size), __FILE__, __LINE__)
+#define calloc(count, size) MyAlloc ((count) * (size), __FILE__, __LINE__)
+#define realloc(ptr, size) MyRealloc ((ptr), (size), __FILE__, __LINE__)
+#define free(ptr) MyFree ((ptr), __FILE__, __LINE__)
+#define alloc_check(final) MyCheck ((final), __FILE__, __LINE__)
+
+//
+// Structure for checking/tracking memory allocations.
+//
+typedef struct MyAllocStruct {
+ UINTN Cksum;
+ struct MyAllocStruct *Next;
+ UINTN Line;
+ UINTN Size;
+ UINT8 *File;
+ UINT8 *Buffer;
+} MY_ALLOC_STRUCT;
+//
+// Cksum := (UINTN)This + (UINTN)Next + Line + Size + (UINTN)File +
+// (UINTN)Buffer;
+//
+// Next := Pointer to next allocation structure in the list.
+//
+// Line := __LINE__
+//
+// Size := Size of allocation request.
+//
+// File := Pointer to __FILE__ string stored immediately following
+// MY_ALLOC_STRUCT in memory.
+//
+// Buffer := Pointer to UINT32 aligned storage immediately following
+// the NULL terminated __FILE__ string. This is UINT32
+// aligned because the underflow signature is 32-bits and
+// this will place the first caller address on a 64-bit
+// boundary.
+//
+//
+// Signatures used to check for buffer overflow/underflow conditions.
+//
+#define MYALLOC_HEAD_MAGIK 0xBADFACED
+#define MYALLOC_TAIL_MAGIK 0xDEADBEEF
+
+VOID
+MyCheck (
+ BOOLEAN Final,
+ UINT8 File[],
+ UINTN Line
+ )
+;
+//
+// *++
+// Description:
+//
+// Check for corruptions in the allocated memory chain. If a corruption
+// is detection program operation stops w/ an exit(1) call.
+//
+// Parameters:
+//
+// Final := When FALSE, MyCheck() returns if the allocated memory chain
+// has not been corrupted. When TRUE, MyCheck() returns if there
+// are no un-freed allocations. If there are un-freed allocations,
+// they are displayed and exit(1) is called.
+//
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// n/a
+//
+// --*/
+//
+VOID *
+MyAlloc (
+ UINTN Size,
+ UINT8 File[],
+ UINTN Line
+ )
+;
+//
+// *++
+// Description:
+//
+// Allocate a new link in the allocation chain along with enough storage
+// for the File[] string, requested Size and alignment overhead. If
+// memory cannot be allocated or the allocation chain has been corrupted,
+// exit(1) will be called.
+//
+// Parameters:
+//
+// Size := Number of bytes (UINT8) requested by the called.
+// Size cannot be zero.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// Pointer to the caller's buffer.
+//
+// --*/
+//
+VOID *
+MyRealloc (
+ VOID *Ptr,
+ UINTN Size,
+ UINT8 File[],
+ UINTN Line
+ )
+;
+//
+// *++
+// Description:
+//
+// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
+// for shrinking or expanding buffers. An invalid parameter will cause
+// MyRealloc() to fail with a call to exit(1).
+//
+// Parameters:
+//
+// Ptr := Pointer to the caller's buffer to be re-allocated.
+// Ptr cannot be NULL.
+//
+// Size := Size of new buffer. Size cannot be zero.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// Pointer to new caller's buffer.
+//
+// --*/
+//
+VOID
+MyFree (
+ VOID *Ptr,
+ UINT8 File[],
+ UINTN Line
+ )
+;
+//
+// *++
+// Description:
+//
+// Release a previously allocated buffer. Invalid parameters will cause
+// MyFree() to fail with an exit(1) call.
+//
+// Parameters:
+//
+// Ptr := Pointer to the caller's buffer to be freed.
+// A NULL pointer will be ignored.
+//
+// File := Set to __FILE__ by macro expansion.
+//
+// Line := Set to __LINE__ by macro expansion.
+//
+// Returns:
+//
+// n/a
+//
+// --*/
+//
+#else /* USE_MYALLOC */
+
+//
+// Nothing to do when USE_MYALLOC is zero.
+//
+#define alloc_check(final)
+
+#endif /* USE_MYALLOC */
+#endif /* _MYALLOC_H_ */
+
+/* eof - MyAlloc.h */
diff --git a/BaseTools/Source/C/Common/OsPath.c b/BaseTools/Source/C/Common/OsPath.c
new file mode 100644
index 0000000000..088730689d
--- /dev/null
+++ b/BaseTools/Source/C/Common/OsPath.c
@@ -0,0 +1,307 @@
+/** @file
+
+Copyright (c) 2007 - 2008, 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:
+
+ StringFuncs.c
+
+Abstract:
+
+ Functions useful to operate file directories by parsing file path.
+
+**/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "OsPath.h"
+
+//
+// Functions implementations
+//
+
+#if 0
+ //
+ // BUGBUG: Not fully implemented yet.
+ //
+CHAR8*
+OsPathDirName (
+ IN CHAR8 *FilePath
+ )
+/*++
+
+Routine Description:
+
+ This function returns the directory path which contains the particular path.
+ Some examples:
+ "a/b/c" -> "a/b"
+ "a/b/c/" -> "a/b"
+ "a" -> "."
+ "." -> ".."
+ "/" -> NULL
+
+ This function does not check for the existence of the file.
+
+ The caller must free the string returned.
+
+Arguments:
+
+ FilePath Path name of file to get the parent directory for.
+
+Returns:
+
+ NULL if error
+
+--*/
+{
+ CHAR8 *Return;
+ CHAR8 *Pos;
+ CHAR8 Char;
+ UINTN Length;
+ INTN Offset;
+
+ Length = strlen (FilePath);
+
+ if (Length == 0) {
+ return NULL;
+ }
+
+ //
+ // Check for the root directory case
+ //
+ if (
+ (Length == 3 && isalpha (FilePath[0]) && (strcmp(FilePath + 1, ":\\") == 0)) ||
+ (strcmp(FilePath, "/") == 0)
+ ) {
+ return NULL;
+ }
+
+ //
+ // If the path ends with a path separator, then just append ".."
+ //
+ Char = FilePath[Length - 1];
+ if (Char == '/' || Char == '\\') {
+ return OsPathJoin (FilePath, "..");
+ }
+
+ //
+ //
+ //
+ for (Offset = Length; Offset > 0; Offset--) {
+ if ((Return[Offset] == '/') || (Return[Offset] == '\\')) {
+ Return[Offset] = '\0';
+ return Return;
+ }
+ }
+}
+#endif
+
+
+#if 0
+ //
+ // BUGBUG: Not fully implemented yet.
+ //
+VOID
+OsPathNormPathInPlace (
+ IN CHAR8 *Path
+ )
+/*++
+
+Routine Description:
+
+ This function returns the directory path which contains the particular path.
+ Some examples:
+ "a/b/../c" -> "a/c"
+ "a/b//c" -> "a/b/c"
+ "a/./b" -> "a/b"
+
+ This function does not check for the existence of the file.
+
+Arguments:
+
+ Path Path name of file to normalize
+
+Returns:
+
+ The string is altered in place.
+
+--*/
+{
+ CHAR8 *Pos;
+ INTN Offset;
+ BOOLEAN TryAgain;
+ UINTN Length;
+ UINTN Remaining;
+ UINTN SubLength;
+
+ do {
+ TryAgain = FALSE;
+ Length = strlen (Path);
+
+ for (Offset = 0; Offset < Length; Offset++) {
+ Remaining = Length - Offset;
+
+ //
+ // Collapse '//' -> '/'
+ //
+ if (
+ (Remaining >= 2) &&
+ ((Offset > 0) || (Path[0] != '\\')) &&
+ IsDirSep (Path[Offset]) && IsDirSep (Path[Offset + 1])
+ ) {
+ memmove (&Path[Offset], &Path[Offset + 1], Remaining);
+ TryAgain = TRUE;
+ break;
+ }
+
+ //
+ // Collapse '/./' -> '/'
+ //
+ if ((Remaining >= 3) && IsDirSep (Path[Offset]) &&
+ (Path[Offset + 1] == '.') && IsDirSep (Path[Offset + 2])
+ ) {
+ memmove (&Path[Offset], &Path[Offset + 1], Remaining);
+ TryAgain = TRUE;
+ break;
+ }
+
+ //
+ // Collapse 'a/../b' -> 'b'
+ //
+ // BUGBUG: Not implemented yet
+
+ }
+
+ } while (TryAgain);
+
+ Return = CloneString (FilePath);
+ if (Return == NULL) {
+ return NULL;
+ }
+
+ Length = strlen (Return);
+
+ //
+ // Check for the root directory case
+ //
+ if (
+ (Length == 3 && isalpha (Return[0]) && (strcmp(Return + 1, ":\\") == 0)) ||
+ (strcmp(Return, "/") == 0)
+ ) {
+ free (Return);
+ return NULL;
+ }
+
+ //
+ //
+ //
+ for (Offset = Length; Offset > 0; Offset--) {
+ if ((Return[Offset] == '/') || (Return[Offset] == '\\')) {
+ Return[Offset] = '\0';
+ return Return;
+ }
+ }
+}
+#endif
+
+
+CHAR8*
+OsPathPeerFilePath (
+ IN CHAR8 *OldPath,
+ IN CHAR8 *Peer
+ )
+/*++
+
+Routine Description:
+
+ This function replaces the final portion of a path with an alternative
+ 'peer' filename. For example:
+ "a/b/../c", "peer" -> "a/b/../peer"
+ "a/b/", "peer" -> "a/b/peer"
+ "/a", "peer" -> "/peer"
+ "a", "peer" -> "peer"
+
+ This function does not check for the existence of the file.
+
+Arguments:
+
+ OldPath Path name of replace the final segment
+ Peer The new path name to concatinate to become the peer path
+
+Returns:
+
+ A CHAR8* string, which must be freed by the caller
+
+--*/
+{
+ CHAR8 *Result;
+ INTN Offset;
+
+ Result = (CHAR8 *) malloc (strlen (OldPath) + strlen (Peer) + 1);
+ if (Result == NULL) {
+ return NULL;
+ }
+
+ strcpy (Result, OldPath);
+
+ //
+ // Search for the last '/' or '\' in the string. If found, replace
+ // everything following it with Peer
+ //
+ for (Offset = strlen (Result); Offset >= 0; Offset--) {
+ if ((Result[Offset] == '/') || (Result[Offset] == '\\')) {
+ Result[Offset + 1] = '\0';
+ strcat (Result, Peer);
+ return Result;
+ }
+ }
+
+ //
+ // Neither a '/' nor a '\' was found. Therefore, we simply return Peer.
+ //
+ strcpy (Result, Peer);
+ return Result;
+}
+
+
+BOOLEAN
+OsPathExists (
+ IN CHAR8 *InputFileName
+ )
+/*++
+
+Routine Description:
+
+ Checks if a file exists
+
+Arguments:
+
+ InputFileName The name of the file to check for existence
+
+Returns:
+
+ TRUE The file exists
+ FALSE The file does not exist
+
+--*/
+{
+ FILE *InputFile;
+ InputFile = fopen (InputFileName, "rb");
+ if (InputFile == NULL) {
+ return FALSE;
+ } else {
+ fclose (InputFile);
+ return TRUE;
+ }
+}
+
+
+
diff --git a/BaseTools/Source/C/Common/OsPath.h b/BaseTools/Source/C/Common/OsPath.h
new file mode 100644
index 0000000000..0386dfa50d
--- /dev/null
+++ b/BaseTools/Source/C/Common/OsPath.h
@@ -0,0 +1,146 @@
+/** @file
+
+Copyright (c) 2007 - 2008, 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:
+
+ OsPath.h
+
+Abstract:
+
+ Header file for helper functions useful to operate file directories
+ by parsing file path.
+
+**/
+
+#ifndef _EFI_OS_PATH_H
+#define _EFI_OS_PATH_H
+
+#include <Common/UefiBaseTypes.h>
+
+//
+// Functions declarations
+//
+
+CHAR8*
+OsPathDirName (
+ IN CHAR8 *FilePath
+ )
+;
+/**
+
+Routine Description:
+
+ This function returns the directory path which contains the particular path.
+ Some examples:
+ "a/b/c" -> "a/b"
+ "a/b/c/" -> "a/b"
+ "a" -> "."
+ "." -> ".."
+ "/" -> NULL
+
+ This function does not check for the existence of the file.
+
+ The caller must free the string returned.
+
+Arguments:
+
+ FilePath Path name of file to get the parent directory for.
+
+Returns:
+
+ NULL if error
+
+**/
+
+
+VOID
+OsPathNormPathInPlace (
+ IN CHAR8 *Path
+ )
+;
+/**
+
+Routine Description:
+
+ This function returns the directory path which contains the particular path.
+ Some examples:
+ "a/b/../c" -> "a/c"
+ "a/b//c" -> "a/b/c"
+ "a/./b" -> "a/b"
+
+ This function does not check for the existence of the file.
+
+Arguments:
+
+ Path Path name of file to normalize
+
+Returns:
+
+ The string is altered in place.
+
+**/
+
+
+CHAR8*
+OsPathPeerFilePath (
+ IN CHAR8 *OldPath,
+ IN CHAR8 *Peer
+ )
+;
+/**
+
+Routine Description:
+
+ This function replaces the final portion of a path with an alternative
+ 'peer' filename. For example:
+ "a/b/../c", "peer" -> "a/b/../peer"
+ "a/b/", "peer" -> "a/b/peer"
+ "/a", "peer" -> "/peer"
+ "a", "peer" -> "peer"
+
+ This function does not check for the existence of the file.
+
+Arguments:
+
+ OldPath Path name of replace the final segment
+ Peer The new path name to concatinate to become the peer path
+
+Returns:
+
+ A CHAR8* string, which must be freed by the caller
+
+**/
+
+
+BOOLEAN
+OsPathExists (
+ IN CHAR8 *InputFileName
+ )
+;
+/**
+
+Routine Description:
+
+ Checks if a file exists
+
+Arguments:
+
+ InputFileName The name of the file to check for existence
+
+Returns:
+
+ TRUE The file exists
+ FALSE The file does not exist
+
+**/
+
+
+#endif
diff --git a/BaseTools/Source/C/Common/ParseGuidedSectionTools.c b/BaseTools/Source/C/Common/ParseGuidedSectionTools.c
new file mode 100644
index 0000000000..02d0b11f0d
--- /dev/null
+++ b/BaseTools/Source/C/Common/ParseGuidedSectionTools.c
@@ -0,0 +1,210 @@
+/** @file
+
+Copyright (c) 2007 - 2008, 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:
+
+ ParseGuidedSectionTools.c
+
+Abstract:
+
+ Helper functions for parsing GuidedSectionTools.txt
+
+**/
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "MemoryFile.h"
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+#include "ParseInf.h"
+#include "ParseGuidedSectionTools.h"
+#include "StringFuncs.h"
+
+
+//
+// Local types / structures
+//
+
+typedef struct _GUID_SEC_TOOL_ENTRY {
+ EFI_GUID Guid;
+ CHAR8* Name;
+ CHAR8* Path;
+ struct _GUID_SEC_TOOL_ENTRY *Next;
+} GUID_SEC_TOOL_ENTRY;
+
+//
+// Functin Implementation
+//
+
+EFI_HANDLE
+ParseGuidedSectionToolsFile (
+ IN CHAR8 *InputFile
+ )
+/*++
+
+Routine Description:
+
+ This function parses the tools_def.txt file. It returns a
+ EFI_HANDLE object which can be used for the other library
+ functions and should be passed to FreeParsedGuidedSectionToolsHandle
+ to free resources when the tools_def.txt information is no
+ longer needed.
+
+Arguments:
+
+ InputFile Path name of file to read
+
+Returns:
+
+ NULL if error parsing
+ A non-NULL EFI_HANDLE otherwise
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE MemoryFile;
+ EFI_HANDLE ParsedGuidedSectionTools;
+
+ Status = GetMemoryFile (InputFile, &MemoryFile);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ ParsedGuidedSectionTools = ParseGuidedSectionToolsMemoryFile (MemoryFile);
+
+ FreeMemoryFile (MemoryFile);
+
+ return ParsedGuidedSectionTools;
+}
+
+
+EFI_HANDLE
+ParseGuidedSectionToolsMemoryFile (
+ IN EFI_HANDLE InputFile
+ )
+/*++
+
+Routine Description:
+
+ This function parses the tools_def.txt file. It returns a
+ EFI_HANDLE object which can be used for the other library
+ functions and should be passed to FreeParsedGuidedSectionToolsHandle
+ to free resources when the tools_def.txt information is no
+ longer needed.
+
+Arguments:
+
+ InputFile Memory file image.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+{
+ EFI_STATUS Status;
+ CHAR8 *NextLine;
+ STRING_LIST *Tool;
+ EFI_GUID Guid;
+ GUID_SEC_TOOL_ENTRY *FirstGuidTool;
+ GUID_SEC_TOOL_ENTRY *LastGuidTool;
+ GUID_SEC_TOOL_ENTRY *NewGuidTool;
+
+ FirstGuidTool = NULL;
+
+ while (TRUE) {
+ NextLine = ReadMemoryFileLine (InputFile);
+ if (NextLine == NULL) {
+ break;
+ }
+
+ Status = StripInfDscStringInPlace (NextLine);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ if (NextLine[0] == '\0') {
+ continue;
+ }
+
+ Tool = SplitStringByWhitespace (NextLine);
+ if ((Tool != NULL) &&
+ (Tool->Count == 3)
+ ) {
+ Status = StringToGuid (Tool->Strings[0], &Guid);
+ if (!EFI_ERROR (Status)) {
+ NewGuidTool = malloc (sizeof (GUID_SEC_TOOL_ENTRY));
+ if (NewGuidTool != NULL) {
+ memcpy (&(NewGuidTool->Guid), &Guid, sizeof (Guid));
+ NewGuidTool->Name = CloneString(Tool->Strings[1]);
+ NewGuidTool->Path = CloneString(Tool->Strings[2]);
+ NewGuidTool->Next = NULL;
+ }
+ if (FirstGuidTool == NULL) {
+ FirstGuidTool = NewGuidTool;
+ } else {
+ LastGuidTool->Next = NewGuidTool;
+ }
+ LastGuidTool = NewGuidTool;
+ }
+ FreeStringList (Tool);
+ }
+ }
+
+ return FirstGuidTool;
+}
+
+
+CHAR8*
+LookupGuidedSectionToolPath (
+ IN EFI_HANDLE ParsedGuidedSectionToolsHandle,
+ IN EFI_GUID *SectionGuid
+ )
+/*++
+
+Routine Description:
+
+ This function looks up the appropriate tool to use for extracting
+ a GUID defined FV section.
+
+Arguments:
+
+ ParsedGuidedSectionToolsHandle A parsed GUID section tools handle.
+ SectionGuid The GUID for the section.
+
+Returns:
+
+ NULL - if no tool is found or there is another error
+ Non-NULL - The tool to use to access the section contents. (The caller
+ must free the memory associated with this string.)
+
+--*/
+{
+ GUID_SEC_TOOL_ENTRY *GuidTool;
+
+ GuidTool = (GUID_SEC_TOOL_ENTRY*)ParsedGuidedSectionToolsHandle;
+ if (GuidTool == NULL) {
+ return NULL;
+ }
+
+ for ( ; GuidTool != NULL; GuidTool = GuidTool->Next) {
+ if (CompareGuid (&(GuidTool->Guid), SectionGuid) == 0) {
+ return CloneString (GuidTool->Path);
+ }
+ }
+
+ return NULL;
+}
+
+
diff --git a/BaseTools/Source/C/Common/ParseGuidedSectionTools.h b/BaseTools/Source/C/Common/ParseGuidedSectionTools.h
new file mode 100644
index 0000000000..d30afff1cc
--- /dev/null
+++ b/BaseTools/Source/C/Common/ParseGuidedSectionTools.h
@@ -0,0 +1,133 @@
+/** @file
+
+Copyright (c) 2007 - 2008, 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:
+
+ ParseGuidedSectionTools.h
+
+Abstract:
+
+ Header file for helper functions for parsing GuidedSectionTools.txt
+
+**/
+
+#ifndef _EFI_PARSE_GUIDED_SECTION_TOOLS_H
+#define _EFI_PARSE_GUIDED_SECTION_TOOLS_H
+
+#include <Common/UefiBaseTypes.h>
+
+//
+// Functions declarations
+//
+
+EFI_HANDLE
+ParseGuidedSectionToolsFile (
+ IN CHAR8 *InputFile
+ )
+;
+/**
+
+Routine Description:
+
+ This function parses the tools_def.txt file. It returns a
+ EFI_HANDLE object which can be used for the other library
+ functions and should be passed to FreeParsedToolsDefHandle
+ to free resources when the tools_def.txt information is no
+ longer needed.
+
+Arguments:
+
+ InputFile Path name of file to read
+
+Returns:
+
+ NULL if error parsing
+ A non-NULL EFI_HANDLE otherwise
+
+**/
+
+
+EFI_HANDLE
+ParseGuidedSectionToolsMemoryFile (
+ IN EFI_HANDLE InputFile
+ )
+;
+/**
+
+Routine Description:
+
+ This function parses the tools_def.txt file. It returns a
+ EFI_HANDLE object which can be used for the other library
+ functions and should be passed to FreeParsedToolsDefHandle
+ to free resources when the tools_def.txt information is no
+ longer needed.
+
+Arguments:
+
+ InputFile Memory file image.
+
+Returns:
+
+ NULL if error parsing
+ A non-NULL EFI_HANDLE otherwise
+
+**/
+
+CHAR8*
+LookupGuidedSectionToolPath (
+ IN EFI_HANDLE ParsedGuidedSectionToolsHandle,
+ IN EFI_GUID *SectionGuid
+ )
+;
+/**
+
+Routine Description:
+
+ This function looks up the appropriate tool to use for extracting
+ a GUID defined FV section.
+
+Arguments:
+
+ ParsedGuidedSectionToolsHandle A parsed GUID section tools handle.
+ SectionGuid The GUID for the section.
+
+Returns:
+
+ NULL - if no tool is found or there is another error
+ Non-NULL - The tool to use to access the section contents. (The caller
+ must free the memory associated with this string.)
+
+**/
+
+EFI_STATUS
+FreeParsedGuidedSectionToolsHandle (
+ IN EFI_HANDLE ParsedGuidedSectionToolsHandle
+ )
+;
+/**
+
+Routine Description:
+
+ Frees resources that were allocated by ParseGuidedSectionToolsFile.
+ After freeing these resources, the information that was parsed
+ is no longer accessible.
+
+Arguments:
+
+ ParsedToolDefHandle Handle returned from ParseGuidedSectionToolsFile
+
+Returns:
+
+ EFI_STATUS
+
+**/
+
+#endif
diff --git a/BaseTools/Source/C/Common/ParseInf.c b/BaseTools/Source/C/Common/ParseInf.c
new file mode 100644
index 0000000000..8305f14aef
--- /dev/null
+++ b/BaseTools/Source/C/Common/ParseInf.c
@@ -0,0 +1,665 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ ParseInf.c
+
+Abstract:
+
+ This contains some useful functions for parsing INF files.
+
+--*/
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "EfiUtilityMsgs.h"
+#include "ParseInf.h"
+
+CHAR8 *
+ReadLine (
+ IN MEMORY_FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer,
+ IN UINTN MaxLength
+ )
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+ The function reads a string from the input stream argument and stores it in
+ the input string. ReadLine reads characters from the current file position
+ to and including the first newline character, to the end of the stream, or
+ until the number of characters read is equal to MaxLength - 1, whichever
+ comes first. The newline character, if read, is replaced with a \0.
+
+Arguments:
+
+ InputFile Memory file image.
+ InputBuffer Buffer to read into, must be _MAX_PATH size.
+ MaxLength The maximum size of the input buffer.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+{
+ CHAR8 *CharPtr;
+ CHAR8 *EndOfLine;
+ UINTN CharsToCopy;
+
+ //
+ // Verify input parameters are not null
+ //
+ assert (InputBuffer);
+ assert (InputFile->FileImage);
+ assert (InputFile->Eof);
+ assert (InputFile->CurrentFilePointer);
+
+ //
+ // Check for end of file condition
+ //
+ if (InputFile->CurrentFilePointer >= InputFile->Eof) {
+ return NULL;
+ }
+ //
+ // Find the next newline char
+ //
+ EndOfLine = strchr (InputFile->CurrentFilePointer, '\n');
+
+ //
+ // Determine the number of characters to copy.
+ //
+ if (EndOfLine == 0) {
+ //
+ // If no newline found, copy to the end of the file.
+ //
+ CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
+ } else if (EndOfLine >= InputFile->Eof) {
+ //
+ // If the newline found was beyond the end of file, copy to the eof.
+ //
+ CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
+ } else {
+ //
+ // Newline found in the file.
+ //
+ CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;
+ }
+ //
+ // If the end of line is too big for the current buffer, set it to the max
+ // size of the buffer (leaving room for the \0.
+ //
+ if (CharsToCopy > MaxLength - 1) {
+ CharsToCopy = MaxLength - 1;
+ }
+ //
+ // Copy the line.
+ //
+ memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy);
+
+ //
+ // Add the null termination over the 0x0D
+ //
+ if (InputBuffer[CharsToCopy - 1] == '\r') {
+
+ InputBuffer[CharsToCopy - 1] = '\0';
+
+ } else {
+
+ InputBuffer[CharsToCopy] = '\0';
+
+ }
+
+ //
+ // Increment the current file pointer (include the 0x0A)
+ //
+ InputFile->CurrentFilePointer += CharsToCopy + 1;
+
+ //
+ // Strip any comments
+ //
+ CharPtr = strstr (InputBuffer, "//");
+ if (CharPtr != 0) {
+ CharPtr[0] = 0;
+ }
+ //
+ // Return the string
+ //
+ return InputBuffer;
+}
+
+BOOLEAN
+FindSection (
+ IN MEMORY_FILE *InputFile,
+ IN CHAR8 *Section
+ )
+/*++
+
+Routine Description:
+
+ This function parses a file from the beginning to find a section.
+ The section string may be anywhere within a line.
+
+Arguments:
+
+ InputFile Memory file image.
+ Section Section to search for
+
+Returns:
+
+ FALSE if error or EOF
+ TRUE if section found
+
+--*/
+{
+ CHAR8 InputBuffer[_MAX_PATH];
+ CHAR8 *CurrentToken;
+
+ //
+ // Verify input is not NULL
+ //
+ assert (InputFile->FileImage);
+ assert (InputFile->Eof);
+ assert (InputFile->CurrentFilePointer);
+ assert (Section);
+
+ //
+ // Rewind to beginning of file
+ //
+ InputFile->CurrentFilePointer = InputFile->FileImage;
+
+ //
+ // Read lines until the section is found
+ //
+ while (InputFile->CurrentFilePointer < InputFile->Eof) {
+ //
+ // Read a line
+ //
+ ReadLine (InputFile, InputBuffer, _MAX_PATH);
+
+ //
+ // Check if the section is found
+ //
+ CurrentToken = strstr (InputBuffer, Section);
+ if (CurrentToken != NULL) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+EFI_STATUS
+FindToken (
+ IN MEMORY_FILE *InputFile,
+ IN CHAR8 *Section,
+ IN CHAR8 *Token,
+ IN UINTN Instance,
+ OUT CHAR8 *Value
+ )
+/*++
+
+Routine Description:
+
+ Finds a token value given the section and token to search for.
+
+Arguments:
+
+ InputFile Memory file image.
+ Section The section to search for, a string within [].
+ Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.
+ Instance The instance of the token to search for. Zero is the first instance.
+ Value The string that holds the value following the =. Must be _MAX_PATH in size.
+
+Returns:
+
+ EFI_SUCCESS Value found.
+ EFI_ABORTED Format error detected in INF file.
+ EFI_INVALID_PARAMETER Input argument was null.
+ EFI_LOAD_ERROR Error reading from the file.
+ EFI_NOT_FOUND Section/Token/Value not found.
+
+--*/
+{
+ CHAR8 InputBuffer[_MAX_PATH];
+ CHAR8 *CurrentToken;
+ BOOLEAN ParseError;
+ BOOLEAN ReadError;
+ UINTN Occurrance;
+
+ //
+ // Check input parameters
+ //
+ if (InputFile->FileImage == NULL ||
+ InputFile->Eof == NULL ||
+ InputFile->CurrentFilePointer == NULL ||
+ Section == NULL ||
+ strlen (Section) == 0 ||
+ Token == NULL ||
+ strlen (Token) == 0 ||
+ Value == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize error codes
+ //
+ ParseError = FALSE;
+ ReadError = FALSE;
+
+ //
+ // Initialize our instance counter for the search token
+ //
+ Occurrance = 0;
+
+ if (FindSection (InputFile, Section)) {
+ //
+ // Found the desired section, find and read the desired token
+ //
+ do {
+ //
+ // Read a line from the file
+ //
+ if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {
+ //
+ // Error reading from input file
+ //
+ ReadError = TRUE;
+ break;
+ }
+ //
+ // Get the first non-whitespace string
+ //
+ CurrentToken = strtok (InputBuffer, " \t\n");
+ if (CurrentToken == NULL) {
+ //
+ // Whitespace line found (or comment) so continue
+ //
+ CurrentToken = InputBuffer;
+ continue;
+ }
+ //
+ // Make sure we have not reached the end of the current section
+ //
+ if (CurrentToken[0] == '[') {
+ break;
+ }
+ //
+ // Compare the current token with the desired token
+ //
+ if (strcmp (CurrentToken, Token) == 0) {
+ //
+ // Found it
+ //
+ //
+ // Check if it is the correct instance
+ //
+ if (Instance == Occurrance) {
+ //
+ // Copy the contents following the =
+ //
+ CurrentToken = strtok (NULL, "= \t\n");
+ if (CurrentToken == NULL) {
+ //
+ // Nothing found, parsing error
+ //
+ ParseError = TRUE;
+ } else {
+ //
+ // Copy the current token to the output value
+ //
+ strcpy (Value, CurrentToken);
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // Increment the occurrance found
+ //
+ Occurrance++;
+ }
+ }
+ } while (
+ !ParseError &&
+ !ReadError &&
+ InputFile->CurrentFilePointer < InputFile->Eof &&
+ CurrentToken[0] != '[' &&
+ Occurrance <= Instance
+ );
+ }
+ //
+ // Distinguish between read errors and INF file format errors.
+ //
+ if (ReadError) {
+ return EFI_LOAD_ERROR;
+ }
+
+ if (ParseError) {
+ return EFI_ABORTED;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+StringToGuid (
+ IN CHAR8 *AsciiGuidBuffer,
+ OUT EFI_GUID *GuidBuffer
+ )
+/*++
+
+Routine Description:
+
+ Converts a string to an EFI_GUID. The string must be in the
+ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
+
+Arguments:
+
+ AsciiGuidBuffer - pointer to ascii string
+ GuidBuffer - pointer to destination Guid
+
+Returns:
+
+ EFI_ABORTED Could not convert the string
+ EFI_SUCCESS The string was successfully converted
+ EFI_INVALID_PARAMETER Input parameter is invalid.
+
+--*/
+{
+ INT32 Index;
+ UINT32 Data1;
+ UINT32 Data2;
+ UINT32 Data3;
+ UINT16 Data4[8];
+
+ if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check Guid Format strictly xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+ //
+ for (Index = 0; AsciiGuidBuffer[Index] != '\0' && Index < 37; Index ++) {
+ if (Index == 8 || Index == 13 || Index == 18 || Index == 23) {
+ if (AsciiGuidBuffer[Index] != '-') {
+ break;
+ }
+ } else {
+ if (((AsciiGuidBuffer[Index] >= '0') && (AsciiGuidBuffer[Index] <= '9')) ||
+ ((AsciiGuidBuffer[Index] >= 'a') && (AsciiGuidBuffer[Index] <= 'f')) ||
+ ((AsciiGuidBuffer[Index] >= 'A') && (AsciiGuidBuffer[Index] <= 'F'))) {
+ continue;
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (Index < 36 || AsciiGuidBuffer[36] != '\0') {
+ Error (NULL, 0, 1003, "Invalid option value", "Incorrect GUID \"%s\"\n Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", AsciiGuidBuffer);
+ return EFI_ABORTED;
+ }
+
+ //
+ // Scan the guid string into the buffer
+ //
+ Index = sscanf (
+ AsciiGuidBuffer,
+ "%08x-%04x-%04x-%02hx%02hx-%02hx%02hx%02hx%02hx%02hx%02hx",
+ &Data1,
+ &Data2,
+ &Data3,
+ &Data4[0],
+ &Data4[1],
+ &Data4[2],
+ &Data4[3],
+ &Data4[4],
+ &Data4[5],
+ &Data4[6],
+ &Data4[7]
+ );
+
+ //
+ // Verify the correct number of items were scanned.
+ //
+ if (Index != 11) {
+ Error (NULL, 0, 1003, "Invalid option value", "Incorrect GUID \"%s\"\n Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", AsciiGuidBuffer);
+ return EFI_ABORTED;
+ }
+ //
+ // Copy the data into our GUID.
+ //
+ GuidBuffer->Data1 = (UINT32) Data1;
+ GuidBuffer->Data2 = (UINT16) Data2;
+ GuidBuffer->Data3 = (UINT16) Data3;
+ GuidBuffer->Data4[0] = (UINT8) Data4[0];
+ GuidBuffer->Data4[1] = (UINT8) Data4[1];
+ GuidBuffer->Data4[2] = (UINT8) Data4[2];
+ GuidBuffer->Data4[3] = (UINT8) Data4[3];
+ GuidBuffer->Data4[4] = (UINT8) Data4[4];
+ GuidBuffer->Data4[5] = (UINT8) Data4[5];
+ GuidBuffer->Data4[6] = (UINT8) Data4[6];
+ GuidBuffer->Data4[7] = (UINT8) Data4[7];
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+AsciiStringToUint64 (
+ IN CONST CHAR8 *AsciiString,
+ IN BOOLEAN IsHex,
+ OUT UINT64 *ReturnValue
+ )
+/*++
+
+Routine Description:
+
+ Converts a null terminated ascii string that represents a number into a
+ UINT64 value. A hex number may be preceeded by a 0x, but may not be
+ succeeded by an h. A number without 0x or 0X is considered to be base 10
+ unless the IsHex input is true.
+
+Arguments:
+
+ AsciiString The string to convert.
+ IsHex Force the string to be treated as a hex number.
+ ReturnValue The return value.
+
+Returns:
+
+ EFI_SUCCESS Number successfully converted.
+ EFI_ABORTED Invalid character encountered.
+
+--*/
+{
+ UINT8 Index;
+ UINT64 HexNumber;
+ CHAR8 CurrentChar;
+
+ //
+ // Initialize the result
+ //
+ HexNumber = 0;
+
+ //
+ // Check input paramter
+ //
+ if (AsciiString == NULL || ReturnValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Add each character to the result
+ //
+ if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {
+ //
+ // Verify string is a hex number
+ //
+ for (Index = 2; Index < strlen (AsciiString); Index++) {
+ if (isxdigit (AsciiString[Index]) == 0) {
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Convert the hex string.
+ //
+ for (Index = 2; AsciiString[Index] != '\0'; Index++) {
+ CurrentChar = AsciiString[Index];
+ HexNumber *= 16;
+ if (CurrentChar >= '0' && CurrentChar <= '9') {
+ HexNumber += CurrentChar - '0';
+ } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {
+ HexNumber += CurrentChar - 'a' + 10;
+ } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {
+ HexNumber += CurrentChar - 'A' + 10;
+ } else {
+ //
+ // Unrecognized character
+ //
+ return EFI_ABORTED;
+ }
+ }
+
+ *ReturnValue = HexNumber;
+ } else {
+ //
+ // Verify string is a number
+ //
+ for (Index = 0; Index < strlen (AsciiString); Index++) {
+ if (isdigit (AsciiString[Index]) == 0) {
+ return EFI_ABORTED;
+ }
+ }
+
+ *ReturnValue = atol (AsciiString);
+ }
+
+ return EFI_SUCCESS;
+}
+
+CHAR8 *
+ReadLineInStream (
+ IN FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer
+ )
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+ // BUGBUG: This is obsolete once genmake goes away...
+
+Arguments:
+
+ InputFile Stream pointer.
+ InputBuffer Buffer to read into, must be _MAX_PATH size.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+{
+ CHAR8 *CharPtr;
+
+ //
+ // Verify input parameters are not null
+ //
+ assert (InputFile);
+ assert (InputBuffer);
+
+ //
+ // Read a line
+ //
+ if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {
+ return NULL;
+ }
+ //
+ // Strip any comments
+ //
+ CharPtr = strstr (InputBuffer, "//");
+ if (CharPtr != 0) {
+ CharPtr[0] = 0;
+ }
+
+ CharPtr = strstr (InputBuffer, "#");
+ if (CharPtr != 0) {
+ CharPtr[0] = 0;
+ }
+ //
+ // Return the string
+ //
+ return InputBuffer;
+}
+
+BOOLEAN
+FindSectionInStream (
+ IN FILE *InputFile,
+ IN CHAR8 *Section
+ )
+/*++
+
+Routine Description:
+
+ This function parses a stream file from the beginning to find a section.
+ The section string may be anywhere within a line.
+ // BUGBUG: This is obsolete once genmake goes away...
+
+Arguments:
+
+ InputFile Stream pointer.
+ Section Section to search for
+
+Returns:
+
+ FALSE if error or EOF
+ TRUE if section found
+
+--*/
+{
+ CHAR8 InputBuffer[_MAX_PATH];
+ CHAR8 *CurrentToken;
+
+ //
+ // Verify input is not NULL
+ //
+ assert (InputFile);
+ assert (Section);
+
+ //
+ // Rewind to beginning of file
+ //
+ if (fseek (InputFile, 0, SEEK_SET) != 0) {
+ return FALSE;
+ }
+ //
+ // Read lines until the section is found
+ //
+ while (feof (InputFile) == 0) {
+ //
+ // Read a line
+ //
+ ReadLineInStream (InputFile, InputBuffer);
+
+ //
+ // Check if the section is found
+ //
+ CurrentToken = strstr (InputBuffer, Section);
+ if (CurrentToken != NULL) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/BaseTools/Source/C/Common/ParseInf.h b/BaseTools/Source/C/Common/ParseInf.h
new file mode 100644
index 0000000000..af532b8a18
--- /dev/null
+++ b/BaseTools/Source/C/Common/ParseInf.h
@@ -0,0 +1,230 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ ParseInf.h
+
+Abstract:
+
+ Header file for helper functions useful for parsing INF files.
+
+**/
+
+#ifndef _EFI_PARSE_INF_H
+#define _EFI_PARSE_INF_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Common/UefiBaseTypes.h>
+#include <MemoryFile.h>
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 500
+#endif
+
+
+//
+// Functions declarations
+//
+CHAR8 *
+ReadLine (
+ IN MEMORY_FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer,
+ IN UINTN MaxLength
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+ The function reads a string from the input stream argument and stores it in
+ the input string. ReadLine reads characters from the current file position
+ to and including the first newline character, to the end of the stream, or
+ until the number of characters read is equal to MaxLength - 1, whichever
+ comes first. The newline character, if read, is replaced with a \0.
+
+Arguments:
+
+ InputFile Memory file image.
+ InputBuffer Buffer to read into, must be _MAX_PATH size.
+ MaxLength The maximum size of the input buffer.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+BOOLEAN
+FindSection (
+ IN MEMORY_FILE *InputFile,
+ IN CHAR8 *Section
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function parses a file from the beginning to find a section.
+ The section string may be anywhere within a line.
+
+Arguments:
+
+ InputFile Memory file image.
+ Section Section to search for
+
+Returns:
+
+ FALSE if error or EOF
+ TRUE if section found
+
+--*/
+EFI_STATUS
+FindToken (
+ IN MEMORY_FILE *InputFile,
+ IN CHAR8 *Section,
+ IN CHAR8 *Token,
+ IN UINTN Instance,
+ OUT CHAR8 *Value
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Finds a token value given the section and token to search for.
+
+Arguments:
+
+ InputFile Memory file image.
+ Section The section to search for, a string within [].
+ Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.
+ Instance The instance of the token to search for. Zero is the first instance.
+ Value The string that holds the value following the =. Must be _MAX_PATH in size.
+
+Returns:
+
+ EFI_SUCCESS Value found.
+ EFI_ABORTED Format error detected in INF file.
+ EFI_INVALID_PARAMETER Input argument was null.
+ EFI_LOAD_ERROR Error reading from the file.
+ EFI_NOT_FOUND Section/Token/Value not found.
+
+--*/
+EFI_STATUS
+StringToGuid (
+ IN CHAR8 *AsciiGuidBuffer,
+ OUT EFI_GUID *GuidBuffer
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Converts a string to an EFI_GUID. The string must be in the
+ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
+
+Arguments:
+
+ GuidBuffer - pointer to destination Guid
+ AsciiGuidBuffer - pointer to ascii string
+
+Returns:
+
+ EFI_ABORTED Could not convert the string
+ EFI_SUCCESS The string was successfully converted
+
+--*/
+EFI_STATUS
+AsciiStringToUint64 (
+ IN CONST CHAR8 *AsciiString,
+ IN BOOLEAN IsHex,
+ OUT UINT64 *ReturnValue
+ )
+;
+
+/*++
+
+Routine Description:
+
+ Converts a null terminated ascii string that represents a number into a
+ UINT64 value. A hex number may be preceeded by a 0x, but may not be
+ succeeded by an h. A number without 0x or 0X is considered to be base 10
+ unless the IsHex input is true.
+
+Arguments:
+
+ AsciiString The string to convert.
+ IsHex Force the string to be treated as a hex number.
+ ReturnValue The return value.
+
+Returns:
+
+ EFI_SUCCESS Number successfully converted.
+ EFI_ABORTED Invalid character encountered.
+
+--*/
+CHAR8 *
+ReadLineInStream (
+ IN FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+
+Arguments:
+
+ InputFile Stream pointer.
+ InputBuffer Buffer to read into, must be _MAX_PATH size.
+
+Returns:
+
+ NULL if error or EOF
+ InputBuffer otherwise
+
+--*/
+BOOLEAN
+FindSectionInStream (
+ IN FILE *InputFile,
+ IN CHAR8 *Section
+ )
+;
+
+/*++
+
+Routine Description:
+
+ This function parses a stream file from the beginning to find a section.
+ The section string may be anywhere within a line.
+
+Arguments:
+
+ InputFile Stream pointer.
+ Section Section to search for
+
+Returns:
+
+ FALSE if error or EOF
+ TRUE if section found
+
+--*/
+#endif
diff --git a/BaseTools/Source/C/Common/PeCoffLib.h b/BaseTools/Source/C/Common/PeCoffLib.h
new file mode 100644
index 0000000000..fc2e4cafc9
--- /dev/null
+++ b/BaseTools/Source/C/Common/PeCoffLib.h
@@ -0,0 +1,137 @@
+/** @file
+ Function prototypes and defines on Memory Only PE COFF loader
+
+ Copyright (c) 2006, 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: PeCoffLib.h
+
+**/
+
+#ifndef __BASE_PE_COFF_LIB_H__
+#define __BASE_PE_COFF_LIB_H__
+
+//
+// Return status codes from the PE/COFF Loader services
+// BUGBUG: Find where used and see if can be replaced by RETURN_STATUS codes
+//
+#define IMAGE_ERROR_SUCCESS 0
+#define IMAGE_ERROR_IMAGE_READ 1
+#define IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE 2
+#define IMAGE_ERROR_INVALID_MACHINE_TYPE 3
+#define IMAGE_ERROR_INVALID_SUBSYSTEM 4
+#define IMAGE_ERROR_INVALID_IMAGE_ADDRESS 5
+#define IMAGE_ERROR_INVALID_IMAGE_SIZE 6
+#define IMAGE_ERROR_INVALID_SECTION_ALIGNMENT 7
+#define IMAGE_ERROR_SECTION_NOT_LOADED 8
+#define IMAGE_ERROR_FAILED_RELOCATION 9
+#define IMAGE_ERROR_FAILED_ICACHE_FLUSH 10
+
+
+//
+// PE/COFF Loader Read Function passed in by caller
+//
+typedef
+RETURN_STATUS
+(EFIAPI *PE_COFF_LOADER_READ_FILE) (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ );
+
+//
+// Context structure used while PE/COFF image is being loaded and relocated
+//
+typedef struct {
+ PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+ PHYSICAL_ADDRESS DestinationAddress;
+ PHYSICAL_ADDRESS EntryPoint;
+ PE_COFF_LOADER_READ_FILE ImageRead;
+ VOID *Handle;
+ VOID *FixupData;
+ UINT32 SectionAlignment;
+ UINT32 PeCoffHeaderOffset;
+ UINT32 DebugDirectoryEntryRva;
+ VOID *CodeView;
+ CHAR8 *PdbPointer;
+ UINTN SizeOfHeaders;
+ UINT32 ImageCodeMemoryType;
+ UINT32 ImageDataMemoryType;
+ UINT32 ImageError;
+ UINTN FixupDataSize;
+ UINT16 Machine;
+ UINT16 ImageType;
+ BOOLEAN RelocationsStripped;
+ BOOLEAN IsTeImage;
+} PE_COFF_LOADER_IMAGE_CONTEXT;
+
+
+/**
+ Retrieves information on a PE/COFF image
+
+ @param ImageContext The context of the image being loaded
+
+ @retval EFI_SUCCESS The information on the PE/COFF image was collected.
+ @retval EFI_INVALID_PARAMETER ImageContext is NULL.
+ @retval EFI_UNSUPPORTED The PE/COFF image is not supported.
+ @retval Otherwise The error status from reading the PE/COFF image using the
+ ImageContext->ImageRead() function
+
+**/
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderGetImageInfo (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+;
+
+/**
+ Relocates a PE/COFF image in memory
+
+ @param ImageContext Contains information on the loaded image to relocate
+
+ @retval EFI_SUCCESS if the PE/COFF image was relocated
+ @retval EFI_LOAD_ERROR if the image is not a valid PE/COFF image
+ @retval EFI_UNSUPPORTED not support
+
+**/
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderRelocateImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+;
+
+/**
+ Loads a PE/COFF image into memory
+
+ @param ImageContext Contains information on image to load into memory
+
+ @retval EFI_SUCCESS if the PE/COFF image was loaded
+ @retval EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
+ @retval EFI_LOAD_ERROR if the image is a runtime driver with no relocations
+ @retval EFI_INVALID_PARAMETER if the image address is invalid
+
+**/
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderLoadImage (
+ IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext
+ )
+;
+
+VOID *
+EFIAPI
+PeCoffLoaderGetPdbPointer (
+ IN VOID *Pe32Data
+ )
+;
+#endif
diff --git a/BaseTools/Source/C/Common/PeCoffLoaderEx.c b/BaseTools/Source/C/Common/PeCoffLoaderEx.c
new file mode 100644
index 0000000000..fedc0941cb
--- /dev/null
+++ b/BaseTools/Source/C/Common/PeCoffLoaderEx.c
@@ -0,0 +1,317 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ PeCoffLoaderEx.c
+
+Abstract:
+
+ IA32, X64 and IPF Specific relocation fixups
+
+Revision History
+
+--*/
+
+#include <Common/UefiBaseTypes.h>
+#include <IndustryStandard/PeImage.h>
+#include "PeCoffLib.h"
+
+#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \
+ Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos)
+
+#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \
+ *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \
+ ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos)
+
+#define IMM64_IMM7B_INST_WORD_X 3
+#define IMM64_IMM7B_SIZE_X 7
+#define IMM64_IMM7B_INST_WORD_POS_X 4
+#define IMM64_IMM7B_VAL_POS_X 0
+
+#define IMM64_IMM9D_INST_WORD_X 3
+#define IMM64_IMM9D_SIZE_X 9
+#define IMM64_IMM9D_INST_WORD_POS_X 18
+#define IMM64_IMM9D_VAL_POS_X 7
+
+#define IMM64_IMM5C_INST_WORD_X 3
+#define IMM64_IMM5C_SIZE_X 5
+#define IMM64_IMM5C_INST_WORD_POS_X 13
+#define IMM64_IMM5C_VAL_POS_X 16
+
+#define IMM64_IC_INST_WORD_X 3
+#define IMM64_IC_SIZE_X 1
+#define IMM64_IC_INST_WORD_POS_X 12
+#define IMM64_IC_VAL_POS_X 21
+
+#define IMM64_IMM41a_INST_WORD_X 1
+#define IMM64_IMM41a_SIZE_X 10
+#define IMM64_IMM41a_INST_WORD_POS_X 14
+#define IMM64_IMM41a_VAL_POS_X 22
+
+#define IMM64_IMM41b_INST_WORD_X 1
+#define IMM64_IMM41b_SIZE_X 8
+#define IMM64_IMM41b_INST_WORD_POS_X 24
+#define IMM64_IMM41b_VAL_POS_X 32
+
+#define IMM64_IMM41c_INST_WORD_X 2
+#define IMM64_IMM41c_SIZE_X 23
+#define IMM64_IMM41c_INST_WORD_POS_X 0
+#define IMM64_IMM41c_VAL_POS_X 40
+
+#define IMM64_SIGN_INST_WORD_X 3
+#define IMM64_SIGN_SIZE_X 1
+#define IMM64_SIGN_INST_WORD_POS_X 27
+#define IMM64_SIGN_VAL_POS_X 63
+
+RETURN_STATUS
+PeCoffLoaderRelocateIa32Image (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+/*++
+
+Routine Description:
+
+ Performs an IA-32 specific relocation fixup
+
+Arguments:
+
+ Reloc - Pointer to the relocation record
+
+ Fixup - Pointer to the address to fix up
+
+ FixupData - Pointer to a buffer to log the fixups
+
+ Adjust - The offset to adjust the fixup
+
+Returns:
+
+ EFI_UNSUPPORTED - Unsupported now
+
+--*/
+{
+ return RETURN_UNSUPPORTED;
+}
+
+RETURN_STATUS
+PeCoffLoaderRelocateIpfImage (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+/*++
+
+Routine Description:
+
+ Performs an Itanium-based specific relocation fixup
+
+Arguments:
+
+ Reloc - Pointer to the relocation record
+
+ Fixup - Pointer to the address to fix up
+
+ FixupData - Pointer to a buffer to log the fixups
+
+ Adjust - The offset to adjust the fixup
+
+Returns:
+
+ Status code
+
+--*/
+{
+ UINT64 *F64;
+ UINT64 FixupVal;
+
+ switch ((*Reloc) >> 12) {
+
+ case EFI_IMAGE_REL_BASED_DIR64:
+ F64 = (UINT64 *) Fixup;
+ *F64 = *F64 + (UINT64) Adjust;
+ if (*FixupData != NULL) {
+ *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
+ *(UINT64 *)(*FixupData) = *F64;
+ *FixupData = *FixupData + sizeof(UINT64);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_IA64_IMM64:
+
+ //
+ // Align it to bundle address before fixing up the
+ // 64-bit immediate value of the movl instruction.
+ //
+
+ Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15));
+ FixupVal = (UINT64)0;
+
+ //
+ // Extract the lower 32 bits of IMM64 from bundle
+ //
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X,
+ IMM64_IMM7B_SIZE_X,
+ IMM64_IMM7B_INST_WORD_POS_X,
+ IMM64_IMM7B_VAL_POS_X
+ );
+
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X,
+ IMM64_IMM9D_SIZE_X,
+ IMM64_IMM9D_INST_WORD_POS_X,
+ IMM64_IMM9D_VAL_POS_X
+ );
+
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X,
+ IMM64_IMM5C_SIZE_X,
+ IMM64_IMM5C_INST_WORD_POS_X,
+ IMM64_IMM5C_VAL_POS_X
+ );
+
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IC_INST_WORD_X,
+ IMM64_IC_SIZE_X,
+ IMM64_IC_INST_WORD_POS_X,
+ IMM64_IC_VAL_POS_X
+ );
+
+ EXT_IMM64(FixupVal,
+ (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X,
+ IMM64_IMM41a_SIZE_X,
+ IMM64_IMM41a_INST_WORD_POS_X,
+ IMM64_IMM41a_VAL_POS_X
+ );
+
+ //
+ // Update 64-bit address
+ //
+ FixupVal += Adjust;
+
+ //
+ // Insert IMM64 into bundle
+ //
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X),
+ IMM64_IMM7B_SIZE_X,
+ IMM64_IMM7B_INST_WORD_POS_X,
+ IMM64_IMM7B_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X),
+ IMM64_IMM9D_SIZE_X,
+ IMM64_IMM9D_INST_WORD_POS_X,
+ IMM64_IMM9D_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X),
+ IMM64_IMM5C_SIZE_X,
+ IMM64_IMM5C_INST_WORD_POS_X,
+ IMM64_IMM5C_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X),
+ IMM64_IC_SIZE_X,
+ IMM64_IC_INST_WORD_POS_X,
+ IMM64_IC_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X),
+ IMM64_IMM41a_SIZE_X,
+ IMM64_IMM41a_INST_WORD_POS_X,
+ IMM64_IMM41a_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X),
+ IMM64_IMM41b_SIZE_X,
+ IMM64_IMM41b_INST_WORD_POS_X,
+ IMM64_IMM41b_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X),
+ IMM64_IMM41c_SIZE_X,
+ IMM64_IMM41c_INST_WORD_POS_X,
+ IMM64_IMM41c_VAL_POS_X
+ );
+
+ INS_IMM64(FixupVal,
+ ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X),
+ IMM64_SIGN_SIZE_X,
+ IMM64_SIGN_INST_WORD_POS_X,
+ IMM64_SIGN_VAL_POS_X
+ );
+
+ F64 = (UINT64 *) Fixup;
+ if (*FixupData != NULL) {
+ *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
+ *(UINT64 *)(*FixupData) = *F64;
+ *FixupData = *FixupData + sizeof(UINT64);
+ }
+ break;
+
+ default:
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+PeCoffLoaderRelocateX64Image (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+/**
+ Performs an x64 specific relocation fixup
+
+ @param Reloc Pointer to the relocation record
+ @param Fixup Pointer to the address to fix up
+ @param FixupData Pointer to a buffer to log the fixups
+ @param Adjust The offset to adjust the fixup
+
+ @retval RETURN_SUCCESS Success to perform relocation
+ @retval RETURN_UNSUPPORTED Unsupported.
+**/
+{
+ UINT64 *F64;
+
+ switch ((*Reloc) >> 12) {
+
+ case EFI_IMAGE_REL_BASED_DIR64:
+ F64 = (UINT64 *) Fixup;
+ *F64 = *F64 + (UINT64) Adjust;
+ if (*FixupData != NULL) {
+ *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
+ *(UINT64 *)(*FixupData) = *F64;
+ *FixupData = *FixupData + sizeof(UINT64);
+ }
+ break;
+
+ default:
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+}
+
diff --git a/BaseTools/Source/C/Common/SimpleFileParsing.c b/BaseTools/Source/C/Common/SimpleFileParsing.c
new file mode 100644
index 0000000000..52ec129193
--- /dev/null
+++ b/BaseTools/Source/C/Common/SimpleFileParsing.c
@@ -0,0 +1,1443 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ SimpleFileParsing.c
+
+Abstract:
+
+ Generic but simple file parsing routines.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "EfiUtilityMsgs.h"
+#include "SimpleFileParsing.h"
+
+#ifndef MAX_PATH
+#define MAX_PATH 255
+#endif
+//
+// just in case we get in an endless loop.
+//
+#define MAX_NEST_DEPTH 20
+//
+// number of wchars
+//
+#define MAX_STRING_IDENTIFIER_NAME 100
+
+#define T_CHAR_SPACE ' '
+#define T_CHAR_NULL 0
+#define T_CHAR_CR '\r'
+#define T_CHAR_TAB '\t'
+#define T_CHAR_LF '\n'
+#define T_CHAR_SLASH '/'
+#define T_CHAR_BACKSLASH '\\'
+#define T_CHAR_DOUBLE_QUOTE '"'
+#define T_CHAR_LC_X 'x'
+#define T_CHAR_0 '0'
+#define T_CHAR_STAR '*'
+
+//
+// We keep a linked list of these for the source files we process
+//
+typedef struct _SOURCE_FILE {
+ FILE *Fptr;
+ CHAR8 *FileBuffer;
+ CHAR8 *FileBufferPtr;
+ UINTN FileSize;
+ CHAR8 FileName[MAX_PATH];
+ UINTN LineNum;
+ BOOLEAN EndOfFile;
+ BOOLEAN SkipToHash;
+ struct _SOURCE_FILE *Previous;
+ struct _SOURCE_FILE *Next;
+ CHAR8 ControlCharacter;
+} SOURCE_FILE;
+
+typedef struct {
+ CHAR8 *FileBufferPtr;
+} FILE_POSITION;
+
+//
+// Keep all our module globals in this structure
+//
+STATIC struct {
+ SOURCE_FILE SourceFile;
+ BOOLEAN VerboseFile;
+ BOOLEAN VerboseToken;
+} mGlobals;
+
+STATIC
+UINTN
+t_strcmp (
+ CHAR8 *Buffer,
+ CHAR8 *Str
+ );
+
+STATIC
+UINTN
+t_strncmp (
+ CHAR8 *Str1,
+ CHAR8 *Str2,
+ INTN Len
+ );
+
+STATIC
+UINTN
+t_strlen (
+ CHAR8 *Str
+ );
+
+STATIC
+VOID
+RewindFile (
+ SOURCE_FILE *SourceFile
+ );
+
+STATIC
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+STATIC
+UINTN
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+STATIC
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ );
+
+STATIC
+VOID
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+STATIC
+CHAR8 *
+t_strcpy (
+ CHAR8 *Dest,
+ CHAR8 *Src
+ );
+
+STATIC
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ );
+
+STATIC
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+STATIC
+STATUS
+GetFilePosition (
+ FILE_POSITION *Fpos
+ );
+
+STATIC
+STATUS
+SetFilePosition (
+ FILE_POSITION *Fpos
+ );
+
+STATUS
+SFPInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+ None.
+
+Returns:
+ STATUS_SUCCESS always
+
+--*/
+{
+ memset ((VOID *) &mGlobals, 0, sizeof (mGlobals));
+ return STATUS_SUCCESS;
+}
+
+UINTN
+SFPGetLineNumber (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return the line number of the file we're parsing. Used
+ for error reporting purposes.
+
+Arguments:
+ None.
+
+Returns:
+ The line number, or 0 if no file is being processed
+
+--*/
+{
+ return mGlobals.SourceFile.LineNum;
+}
+
+CHAR8 *
+SFPGetFileName (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return the name of the file we're parsing. Used
+ for error reporting purposes.
+
+Arguments:
+ None.
+
+Returns:
+ A pointer to the file name. Null if no file is being
+ processed.
+
+--*/
+{
+ if (mGlobals.SourceFile.FileName[0]) {
+ return mGlobals.SourceFile.FileName;
+ }
+
+ return NULL;
+}
+
+STATUS
+SFPOpenFile (
+ CHAR8 *FileName
+ )
+/*++
+
+Routine Description:
+ Open a file for parsing.
+
+Arguments:
+ FileName - name of the file to parse
+
+Returns:
+
+
+--*/
+{
+ STATUS Status;
+ t_strcpy (mGlobals.SourceFile.FileName, FileName);
+ Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);
+ return Status;
+}
+
+BOOLEAN
+SFPIsToken (
+ CHAR8 *Str
+ )
+/*++
+
+Routine Description:
+ Check to see if the specified token is found at
+ the current position in the input file.
+
+Arguments:
+ Str - the token to look for
+
+Returns:
+ TRUE - the token is next
+ FALSE - the token is not next
+
+Notes:
+ We do a simple string comparison on this function. It is
+ the responsibility of the caller to ensure that the token
+ is not a subset of some other token.
+
+ The file pointer is advanced past the token in the input file.
+
+--*/
+{
+ UINTN Len;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ if (mGlobals.VerboseToken) {
+ printf ("Token: '%s'\n", Str);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPIsKeyword (
+ CHAR8 *Str
+ )
+/*++
+
+Routine Description:
+ Check to see if the specified keyword is found at
+ the current position in the input file.
+
+Arguments:
+ Str - keyword to look for
+
+Returns:
+ TRUE - the keyword is next
+ FALSE - the keyword is not next
+
+Notes:
+ A keyword is defined as a "special" string that has a non-alphanumeric
+ character following it.
+
+--*/
+{
+ UINTN Len;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
+ if (isalnum (mGlobals.SourceFile.FileBufferPtr[Len])) {
+ return FALSE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ if (mGlobals.VerboseToken) {
+ printf ("Token: '%s'\n", Str);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPGetNextToken (
+ CHAR8 *Str,
+ UINTN Len
+ )
+/*++
+
+Routine Description:
+ Get the next token from the input stream.
+
+Arguments:
+ Str - pointer to a copy of the next token
+ Len - size of buffer pointed to by Str
+
+Returns:
+ TRUE - next token successfully returned
+ FALSE - otherwise
+
+Notes:
+ Preceeding white space is ignored.
+ The parser's buffer pointer is advanced past the end of the
+ token.
+
+--*/
+{
+ UINTN Index;
+ CHAR8 TempChar;
+
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+ //
+ // Have to have enough string for at least one char and a null-terminator
+ //
+ if (Len < 2) {
+ return FALSE;
+ }
+ //
+ // Look at the first character. If it's an identifier, then treat it
+ // as such
+ //
+ TempChar = mGlobals.SourceFile.FileBufferPtr[0];
+ if (((TempChar >= 'a') && (TempChar <= 'z')) || ((TempChar >= 'A') && (TempChar <= 'Z')) || (TempChar == '_')) {
+ Str[0] = TempChar;
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index = 1;
+ while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
+ TempChar = mGlobals.SourceFile.FileBufferPtr[0];
+ if (((TempChar >= 'a') && (TempChar <= 'z')) ||
+ ((TempChar >= 'A') && (TempChar <= 'Z')) ||
+ ((TempChar >= '0') && (TempChar <= '9')) ||
+ (TempChar == '_')
+ ) {
+ Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index++;
+ } else {
+ //
+ // Invalid character for symbol name, so break out
+ //
+ break;
+ }
+ }
+ //
+ // Null terminate and return success
+ //
+ Str[Index] = 0;
+ return TRUE;
+ } else if ((TempChar == ')') || (TempChar == '(') || (TempChar == '*')) {
+ Str[0] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Str[1] = 0;
+ return TRUE;
+ } else {
+ //
+ // Everything else is white-space (or EOF) separated
+ //
+ Index = 0;
+ while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
+ if (IsWhiteSpace (&mGlobals.SourceFile)) {
+ if (Index > 0) {
+ Str[Index] = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+ } else {
+ Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index++;
+ }
+ }
+ //
+ // See if we just ran out of file contents, but did find a token
+ //
+ if ((Index > 0) && EndOfFile (&mGlobals.SourceFile)) {
+ Str[Index] = 0;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPGetGuidToken (
+ CHAR8 *Str,
+ UINT32 Len
+ )
+/*++
+
+Routine Description:
+ Parse a GUID from the input stream. Stop when you discover white space.
+
+Arguments:
+ Str - pointer to a copy of the next token
+ Len - size of buffer pointed to by Str
+
+Returns:
+ TRUE - GUID string returned successfully
+ FALSE - otherwise
+
+--*/
+{
+ UINT32 Index;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ Index = 0;
+ while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
+ if (IsWhiteSpace (&mGlobals.SourceFile)) {
+ if (Index > 0) {
+ Str[Index] = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+ } else {
+ Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index++;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPSkipToToken (
+ CHAR8 *Str
+ )
+{
+ UINTN Len;
+ CHAR8 *SavePos;
+ Len = t_strlen (Str);
+ SavePos = mGlobals.SourceFile.FileBufferPtr;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ while (!EndOfFile (&mGlobals.SourceFile)) {
+ if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ return TRUE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ }
+
+ mGlobals.SourceFile.FileBufferPtr = SavePos;
+ return FALSE;
+}
+
+BOOLEAN
+SFPGetNumber (
+ UINTN *Value
+ )
+/*++
+
+Routine Description:
+ Check the token at the current file position for a numeric value.
+ May be either decimal or hex.
+
+Arguments:
+ Value - pointer where to store the value
+
+Returns:
+ FALSE - current token is not a number
+ TRUE - current token is a number
+
+--*/
+{
+ UINT32 Val;
+
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ //
+ // Check for hex value
+ //
+ if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {
+ if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) {
+ return FALSE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr += 2;
+ sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", &Val);
+ *Value = Val;
+ while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ } else {
+ *Value = atoi (mGlobals.SourceFile.FileBufferPtr);
+ while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+STATUS
+SFPCloseFile (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Close the file being parsed.
+
+Arguments:
+ None.
+
+Returns:
+ STATUS_SUCCESS - the file was closed
+ STATUS_ERROR - no file is currently open
+
+--*/
+{
+ if (mGlobals.SourceFile.FileBuffer != NULL) {
+ free (mGlobals.SourceFile.FileBuffer);
+ memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_ERROR;
+}
+
+STATIC
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ )
+/*++
+
+Routine Description:
+
+ Given a source file, open the file and parse it
+
+Arguments:
+
+ SourceFile - name of file to parse
+ ParentSourceFile - for error reporting purposes, the file that #included SourceFile.
+
+Returns:
+
+ Standard status.
+
+--*/
+{
+ STATIC UINTN NestDepth = 0;
+ CHAR8 FoundFileName[MAX_PATH];
+ STATUS Status;
+
+ Status = STATUS_SUCCESS;
+ NestDepth++;
+ //
+ // Print the file being processed. Indent so you can tell the include nesting
+ // depth.
+ //
+ if (mGlobals.VerboseFile) {
+ fprintf (stdout, "%*cProcessing file '%s'\n", (INT32)NestDepth * 2, ' ', SourceFile->FileName);
+ fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile->FileName);
+ }
+
+ //
+ // Make sure we didn't exceed our maximum nesting depth
+ //
+ if (NestDepth > MAX_NEST_DEPTH) {
+ Error (NULL, 0, 3001, "Not Supported", "%s exceeeds max nesting depth (%d)", SourceFile->FileName, NestDepth);
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+ //
+ // Try to open the file locally, and if that fails try along our include paths.
+ //
+ strcpy (FoundFileName, SourceFile->FileName);
+ if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) {
+ return STATUS_ERROR;
+ }
+ //
+ // Process the file found
+ //
+ ProcessFile (SourceFile);
+Finish:
+ //
+ // Close open files and return status
+ //
+ if (SourceFile->Fptr != NULL) {
+ fclose (SourceFile->Fptr);
+ SourceFile->Fptr = NULL;
+ }
+
+ return Status;
+}
+
+STATIC
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+
+ Given a source file that's been opened, read the contents into an internal
+ buffer and pre-process it to remove comments.
+
+Arguments:
+
+ SourceFile - structure containing info on the file to process
+
+Returns:
+
+ Standard status.
+
+--*/
+{
+ //
+ // Get the file size, and then read the entire thing into memory.
+ // Allocate extra space for a terminator character.
+ //
+ fseek (SourceFile->Fptr, 0, SEEK_END);
+ SourceFile->FileSize = ftell (SourceFile->Fptr);
+ if (mGlobals.VerboseFile) {
+ printf ("FileSize = %d (0x%X)\n", (INT32)SourceFile->FileSize, (UINT32)SourceFile->FileSize);
+ }
+
+ fseek (SourceFile->Fptr, 0, SEEK_SET);
+ SourceFile->FileBuffer = (CHAR8 *) malloc (SourceFile->FileSize + sizeof (CHAR8 ));
+ if (SourceFile->FileBuffer == NULL) {
+ Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL);
+ return STATUS_ERROR;
+ }
+
+ fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
+ SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (CHAR8 ))] = T_CHAR_NULL;
+ //
+ // Pre-process the file to replace comments with spaces
+ //
+ PreprocessFile (SourceFile);
+ SourceFile->LineNum = 1;
+ return STATUS_SUCCESS;
+}
+
+STATIC
+VOID
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+ Preprocess a file to replace all carriage returns with NULLs so
+ we can print lines (as part of error messages) from the file to the screen.
+
+Arguments:
+ SourceFile - structure that we use to keep track of an input file.
+
+Returns:
+ Nothing.
+
+--*/
+{
+ BOOLEAN InComment;
+ BOOLEAN SlashSlashComment;
+ int LineNum;
+
+ RewindFile (SourceFile);
+ InComment = FALSE;
+ SlashSlashComment = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ //
+ // If a line-feed, then no longer in a comment if we're in a // comment
+ //
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ if (InComment && SlashSlashComment) {
+ InComment = FALSE;
+ SlashSlashComment = FALSE;
+ }
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
+ //
+ // Replace all carriage returns with a NULL so we can print stuff
+ //
+ SourceFile->FileBufferPtr[0] = 0;
+ SourceFile->FileBufferPtr++;
+ //
+ // Check for */ comment end
+ //
+ } else if (InComment &&
+ !SlashSlashComment &&
+ (SourceFile->FileBufferPtr[0] == T_CHAR_STAR) &&
+ (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)
+ ) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ InComment = FALSE;
+ } else if (InComment) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ //
+ // Check for // comments
+ //
+ } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {
+ InComment = TRUE;
+ SlashSlashComment = TRUE;
+ //
+ // Check for /* comment start
+ //
+ } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_STAR)) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ SlashSlashComment = FALSE;
+ InComment = TRUE;
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ }
+ //
+ // Could check for end-of-file and still in a comment, but
+ // should not be necessary. So just restore the file pointers.
+ //
+ RewindFile (SourceFile);
+ //
+ // Dump the reformatted file if verbose mode
+ //
+ if (mGlobals.VerboseFile) {
+ LineNum = 1;
+ printf ("%04d: ", LineNum);
+ while (!EndOfFile (SourceFile)) {
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ printf ("'\n%04d: '", ++LineNum);
+ } else {
+ printf ("%c", SourceFile->FileBufferPtr[0]);
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ printf ("'\n");
+ printf ("FileSize = %d (0x%X)\n", (INT32)SourceFile->FileSize, (UINT32)SourceFile->FileSize);
+ RewindFile (SourceFile);
+ }
+}
+
+BOOLEAN
+SFPGetQuotedString (
+ CHAR8 *Str,
+ INTN Length
+ )
+/*++
+
+Routine Description:
+ Retrieve a quoted-string from the input file.
+
+Arguments:
+ Str - pointer to a copy of the quoted string parsed
+ Length - size of buffer pointed to by Str
+
+Returns:
+ TRUE - next token in input stream was a quoted string, and
+ the string value was returned in Str
+ FALSE - otherwise
+
+--*/
+{
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ while (Length > 0) {
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+ //
+ // Check for closing quote
+ //
+ if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ *Str = 0;
+ return TRUE;
+ }
+
+ *Str = mGlobals.SourceFile.FileBufferPtr[0];
+ Str++;
+ Length--;
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+ }
+ //
+ // First character was not a quote, or the input string length was
+ // insufficient to contain the quoted string, so return failure code.
+ //
+ return FALSE;
+}
+
+BOOLEAN
+SFPIsEOF (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return TRUE of FALSE to indicate whether or not we've reached the end of the
+ file we're parsing.
+
+Arguments:
+ NA
+
+Returns:
+ TRUE - EOF reached
+ FALSE - otherwise
+
+--*/
+{
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ return EndOfFile (&mGlobals.SourceFile);
+}
+
+#if 0
+STATIC
+CHAR8 *
+GetQuotedString (
+ SOURCE_FILE *SourceFile,
+ BOOLEAN Optional
+ )
+{
+ CHAR8 *String;
+ CHAR8 *Start;
+ CHAR8 *Ptr;
+ UINTN Len;
+ BOOLEAN PreviousBackslash;
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ if (Optional == FALSE) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);
+ }
+
+ return NULL;
+ }
+
+ Len = 0;
+ SourceFile->FileBufferPtr++;
+ Start = Ptr = SourceFile->FileBufferPtr;
+ PreviousBackslash = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (PreviousBackslash == FALSE)) {
+ break;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
+ PreviousBackslash = FALSE;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {
+ PreviousBackslash = TRUE;
+ } else {
+ PreviousBackslash = FALSE;
+ }
+
+ SourceFile->FileBufferPtr++;
+ Len++;
+ }
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ //
+ // Now allocate memory for the string and save it off
+ //
+ String = (CHAR8 *) malloc ((Len + 1) * sizeof (CHAR8 ));
+ if (String == NULL) {
+ Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL);
+ return NULL;
+ }
+ //
+ // Copy the string from the file buffer to the local copy.
+ // We do no reformatting of it whatsoever at this point.
+ //
+ Ptr = String;
+ while (Len > 0) {
+ *Ptr = *Start;
+ Start++;
+ Ptr++;
+ Len--;
+ }
+
+ *Ptr = 0;
+ return String;
+}
+#endif
+STATIC
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ //
+ // The file buffer pointer will typically get updated before the End-of-file flag in the
+ // source file structure, so check it first.
+ //
+ if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (CHAR8 )) {
+ SourceFile->EndOfFile = TRUE;
+ return TRUE;
+ }
+
+ if (SourceFile->EndOfFile) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#if 0
+STATIC
+VOID
+ProcessTokenInclude (
+ SOURCE_FILE *SourceFile
+ )
+{
+ CHAR8 IncludeFileName[MAX_PATH];
+ CHAR8 *To;
+ UINTN Len;
+ BOOLEAN ReportedError;
+ SOURCE_FILE IncludedSourceFile;
+
+ ReportedError = FALSE;
+ if (SkipWhiteSpace (SourceFile) == 0) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);
+ }
+ //
+ // Should be quoted file name
+ //
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ SourceFile->FileBufferPtr++;
+ //
+ // Copy the filename as ascii to our local string
+ //
+ To = IncludeFileName;
+ Len = 0;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
+ SourceFile->FileBufferPtr++;
+ break;
+ }
+ //
+ // If too long, then report the error once and process until the closing quote
+ //
+ Len++;
+ if (!ReportedError && (Len >= sizeof (IncludeFileName))) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);
+ ReportedError = TRUE;
+ }
+
+ if (!ReportedError) {
+ *To = (CHAR8 ) SourceFile->FileBufferPtr[0];
+ To++;
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ if (!ReportedError) {
+ *To = 0;
+ memset ((CHAR8 *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));
+ strcpy (IncludedSourceFile.FileName, IncludeFileName);
+ ProcessIncludeFile (&IncludedSourceFile, SourceFile);
+ }
+
+ return ;
+FailDone:
+ //
+ // Error recovery -- skip to next #
+ //
+ SourceFile->SkipToHash = TRUE;
+}
+#endif
+STATIC
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ switch (*SourceFile->FileBufferPtr) {
+ case T_CHAR_NULL:
+ case T_CHAR_CR:
+ case T_CHAR_SPACE:
+ case T_CHAR_TAB:
+ case T_CHAR_LF:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+UINTN
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ UINTN Count;
+
+ Count = 0;
+ while (!EndOfFile (SourceFile)) {
+ Count++;
+ switch (*SourceFile->FileBufferPtr) {
+ case T_CHAR_NULL:
+ case T_CHAR_CR:
+ case T_CHAR_SPACE:
+ case T_CHAR_TAB:
+ SourceFile->FileBufferPtr++;
+ break;
+
+ case T_CHAR_LF:
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ break;
+
+ default:
+ return Count - 1;
+ }
+ }
+ //
+ // Some tokens require trailing whitespace. If we're at the end of the
+ // file, then we count that as well.
+ //
+ if ((Count == 0) && (EndOfFile (SourceFile))) {
+ Count++;
+ }
+
+ return Count;
+}
+
+STATIC
+UINTN
+t_strcmp (
+ CHAR8 *Buffer,
+ CHAR8 *Str
+ )
+/*++
+
+Routine Description:
+ Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated,
+ so only compare up to the length of Str.
+
+Arguments:
+ Buffer - pointer to first (possibly not null-terminated) string
+ Str - pointer to null-terminated string to compare to Buffer
+
+Returns:
+ Number of bytes matched if exact match
+ 0 if Buffer does not start with Str
+
+--*/
+{
+ UINTN Len;
+
+ Len = 0;
+ while (*Str && (*Str == *Buffer)) {
+ Buffer++;
+ Str++;
+ Len++;
+ }
+
+ if (*Str) {
+ return 0;
+ }
+
+ return Len;
+}
+
+STATIC
+UINTN
+t_strlen (
+ CHAR8 *Str
+ )
+{
+ UINTN Len;
+ Len = 0;
+ while (*Str) {
+ Len++;
+ Str++;
+ }
+
+ return Len;
+}
+
+STATIC
+UINTN
+t_strncmp (
+ CHAR8 *Str1,
+ CHAR8 *Str2,
+ INTN Len
+ )
+{
+ while (Len > 0) {
+ if (*Str1 != *Str2) {
+ return Len;
+ }
+
+ Len--;
+ Str1++;
+ Str2++;
+ }
+
+ return 0;
+}
+
+STATIC
+CHAR8 *
+t_strcpy (
+ CHAR8 *Dest,
+ CHAR8 *Src
+ )
+{
+ CHAR8 *SaveDest;
+ SaveDest = Dest;
+ while (*Src) {
+ *Dest = *Src;
+ Dest++;
+ Src++;
+ }
+
+ *Dest = 0;
+ return SaveDest;
+}
+
+STATIC
+VOID
+RewindFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ SourceFile->LineNum = 1;
+ SourceFile->FileBufferPtr = SourceFile->FileBuffer;
+ SourceFile->EndOfFile = 0;
+}
+
+STATIC
+UINT32
+GetHexChars (
+ CHAR8 *Buffer,
+ UINT32 BufferLen
+ )
+{
+ UINT32 Len;
+ Len = 0;
+ while (!EndOfFile (&mGlobals.SourceFile) && (BufferLen > 0)) {
+ if (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ *Buffer = mGlobals.SourceFile.FileBufferPtr[0];
+ Buffer++;
+ Len++;
+ BufferLen--;
+ mGlobals.SourceFile.FileBufferPtr++;
+ } else {
+ break;
+ }
+ }
+ //
+ // Null terminate if we can
+ //
+ if ((Len > 0) && (BufferLen > 0)) {
+ *Buffer = 0;
+ }
+
+ return Len;
+}
+
+BOOLEAN
+SFPGetGuid (
+ INTN GuidStyle,
+ EFI_GUID *Value
+ )
+/*++
+
+Routine Description:
+ Parse a GUID from the input stream. Stop when you discover white space.
+
+Arguments:
+ GuidStyle - Style of the following GUID token
+ Value - pointer to EFI_GUID struct for output
+
+Returns:
+ TRUE - GUID string parsed successfully
+ FALSE - otherwise
+
+ GUID styles
+ Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
+
+--*/
+{
+ UINT32 Value32;
+ UINT32 Index;
+ FILE_POSITION FPos;
+ CHAR8 TempString[20];
+ CHAR8 TempString2[3];
+ CHAR8 *From;
+ CHAR8 *To;
+ UINT32 Len;
+ BOOLEAN Status;
+
+ Status = FALSE;
+ //
+ // Skip white space, then start parsing
+ //
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ GetFilePosition (&FPos);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (GuidStyle == PARSE_GUID_STYLE_5_FIELDS) {
+ //
+ // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD
+ //
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 8)) {
+ goto Done;
+ }
+
+ sscanf (TempString, "%x", &Value32);
+ Value->Data1 = Value32;
+ //
+ // Next two UINT16 fields
+ //
+ if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
+ goto Done;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 4)) {
+ goto Done;
+ }
+
+ sscanf (TempString, "%x", &Value32);
+ Value->Data2 = (UINT16) Value32;
+
+ if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
+ goto Done;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 4)) {
+ goto Done;
+ }
+
+ sscanf (TempString, "%x", &Value32);
+ Value->Data3 = (UINT16) Value32;
+ //
+ // Parse the "AAAA" as two bytes
+ //
+ if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
+ goto Done;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 4)) {
+ goto Done;
+ }
+
+ sscanf (TempString, "%x", &Value32);
+ Value->Data4[0] = (UINT8) (Value32 >> 8);
+ Value->Data4[1] = (UINT8) Value32;
+ if (mGlobals.SourceFile.FileBufferPtr[0] != '-') {
+ goto Done;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ //
+ // Read the last 6 bytes of the GUID
+ //
+ //
+ Len = GetHexChars (TempString, sizeof (TempString));
+ if ((Len == 0) || (Len > 12)) {
+ goto Done;
+ }
+ //
+ // Insert leading 0's to make life easier
+ //
+ if (Len != 12) {
+ From = TempString + Len - 1;
+ To = TempString + 11;
+ TempString[12] = 0;
+ while (From >= TempString) {
+ *To = *From;
+ To--;
+ From--;
+ }
+
+ while (To >= TempString) {
+ *To = '0';
+ To--;
+ }
+ }
+ //
+ // Now parse each byte
+ //
+ TempString2[2] = 0;
+ for (Index = 0; Index < 6; Index++) {
+ //
+ // Copy the two characters from the input string to something
+ // we can parse.
+ //
+ TempString2[0] = TempString[Index * 2];
+ TempString2[1] = TempString[Index * 2 + 1];
+ sscanf (TempString2, "%x", &Value32);
+ Value->Data4[Index + 2] = (UINT8) Value32;
+ }
+
+ Status = TRUE;
+ } else {
+ //
+ // Unsupported GUID style
+ //
+ return FALSE;
+ }
+
+Done:
+ if (Status == FALSE) {
+ SetFilePosition (&FPos);
+ }
+
+ return Status;
+}
+
+STATIC
+STATUS
+GetFilePosition (
+ FILE_POSITION *Fpos
+ )
+{
+ Fpos->FileBufferPtr = mGlobals.SourceFile.FileBufferPtr;
+ return STATUS_SUCCESS;
+}
+
+STATIC
+STATUS
+SetFilePosition (
+ FILE_POSITION *Fpos
+ )
+{
+ //
+ // Should check range of pointer
+ //
+ mGlobals.SourceFile.FileBufferPtr = Fpos->FileBufferPtr;
+ return STATUS_SUCCESS;
+}
diff --git a/BaseTools/Source/C/Common/SimpleFileParsing.h b/BaseTools/Source/C/Common/SimpleFileParsing.h
new file mode 100644
index 0000000000..7b33727d68
--- /dev/null
+++ b/BaseTools/Source/C/Common/SimpleFileParsing.h
@@ -0,0 +1,117 @@
+/** @file
+
+Copyright (c) 2004 - 2008, 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:
+
+ SimpleFileParsing.h
+
+Abstract:
+
+ Function prototypes and defines for the simple file parsing routines.
+
+**/
+
+#ifndef _SIMPLE_FILE_PARSING_H_
+#define _SIMPLE_FILE_PARSING_H_
+
+#include <Common/UefiBaseTypes.h>
+
+STATUS
+SFPInit (
+ VOID
+ )
+;
+
+STATUS
+SFPOpenFile (
+ CHAR8 *FileName
+ )
+;
+
+BOOLEAN
+SFPIsKeyword (
+ CHAR8 *Str
+ )
+;
+
+BOOLEAN
+SFPIsToken (
+ CHAR8 *Str
+ )
+;
+
+BOOLEAN
+SFPGetNextToken (
+ CHAR8 *Str,
+ UINTN Len
+ )
+;
+
+BOOLEAN
+SFPGetGuidToken (
+ CHAR8 *Str,
+ UINT32 Len
+ )
+;
+
+#define PARSE_GUID_STYLE_5_FIELDS 0
+
+BOOLEAN
+SFPGetGuid (
+ INTN GuidStyle,
+ EFI_GUID *Value
+ )
+;
+
+BOOLEAN
+SFPSkipToToken (
+ CHAR8 *Str
+ )
+;
+
+BOOLEAN
+SFPGetNumber (
+ UINTN *Value
+ )
+;
+
+BOOLEAN
+SFPGetQuotedString (
+ CHAR8 *Str,
+ INTN Length
+ )
+;
+
+BOOLEAN
+SFPIsEOF (
+ VOID
+ )
+;
+
+STATUS
+SFPCloseFile (
+ VOID
+ )
+;
+
+UINTN
+SFPGetLineNumber (
+ VOID
+ )
+;
+
+CHAR8 *
+SFPGetFileName (
+ VOID
+ )
+;
+
+#endif // #ifndef _SIMPLE_FILE_PARSING_H_
diff --git a/BaseTools/Source/C/Common/StringFuncs.c b/BaseTools/Source/C/Common/StringFuncs.c
new file mode 100644
index 0000000000..b0ad2d165e
--- /dev/null
+++ b/BaseTools/Source/C/Common/StringFuncs.c
@@ -0,0 +1,426 @@
+/** @file
+
+Copyright (c) 2007 - 2008, 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:
+
+ StringFuncs.c
+
+Abstract:
+
+ Function prototypes and defines for string routines.
+
+**/
+
+#include <string.h>
+#include <ctype.h>
+#include "StringFuncs.h"
+
+//
+// Functions implementations
+//
+
+CHAR8*
+CloneString (
+ IN CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Allocates a new string and copies 'String' to clone it
+
+Arguments:
+
+ String The string to clone
+
+Returns:
+
+ CHAR8* - NULL if there are not enough resources
+
+--*/
+{
+ CHAR8* NewString;
+
+ NewString = malloc (strlen (String) + 1);
+ if (NewString != NULL) {
+ strcpy (NewString, String);
+ }
+
+ return NewString;
+}
+
+
+EFI_STATUS
+StripInfDscStringInPlace (
+ IN CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Remove all comments, leading and trailing whitespace from the string.
+
+Arguments:
+
+ String The string to 'strip'
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ CHAR8 *Pos;
+
+ if (String == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Remove leading whitespace
+ //
+ for (Pos = String; isspace (*Pos); Pos++) {
+ }
+ if (Pos != String) {
+ memmove (String, Pos, strlen (Pos) + 1);
+ }
+
+ //
+ // Comment BUGBUGs!
+ //
+ // What about strings? Comment characters are okay in strings.
+ // What about multiline comments?
+ //
+
+ Pos = (CHAR8 *) strstr (String, "//");
+ if (Pos != NULL) {
+ *Pos = '\0';
+ }
+
+ Pos = (CHAR8 *) strchr (String, '#');
+ if (Pos != NULL) {
+ *Pos = '\0';
+ }
+
+ //
+ // Remove trailing whitespace
+ //
+ for (Pos = String + strlen (String);
+ ((Pos - 1) >= String) && (isspace (*(Pos - 1)));
+ Pos--
+ ) {
+ }
+ *Pos = '\0';
+
+ return EFI_SUCCESS;
+}
+
+
+STRING_LIST*
+SplitStringByWhitespace (
+ IN CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Creates and returns a 'split' STRING_LIST by splitting the string
+ on whitespace boundaries.
+
+Arguments:
+
+ String The string to 'split'
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ CHAR8 *Pos;
+ CHAR8 *EndOfSubString;
+ CHAR8 *EndOfString;
+ STRING_LIST *Output;
+ UINTN Item;
+
+ String = CloneString (String);
+ if (String == NULL) {
+ return NULL;
+ }
+ EndOfString = String + strlen (String);
+
+ Output = NewStringList ();
+
+ for (Pos = String, Item = 0; Pos < EndOfString; Item++) {
+ while (isspace (*Pos)) {
+ Pos++;
+ }
+
+ for (EndOfSubString=Pos;
+ (*EndOfSubString != '\0') && !isspace (*EndOfSubString);
+ EndOfSubString++
+ ) {
+ }
+
+ if (EndOfSubString == Pos) {
+ break;
+ }
+
+ *EndOfSubString = '\0';
+
+ AppendCopyOfStringToList (&Output, Pos);
+
+ Pos = EndOfSubString + 1;
+ }
+
+ free (String);
+ return Output;
+}
+
+
+STRING_LIST*
+NewStringList (
+ )
+/*++
+
+Routine Description:
+
+ Creates a new STRING_LIST with 0 strings.
+
+Returns:
+
+ STRING_LIST* - Null if there is not enough resources to create the object.
+
+--*/
+{
+ STRING_LIST *NewList;
+ NewList = AllocateStringListStruct (0);
+ if (NewList != NULL) {
+ NewList->Count = 0;
+ }
+ return NewList;
+}
+
+
+EFI_STATUS
+AppendCopyOfStringToList (
+ IN OUT STRING_LIST **StringList,
+ IN CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Adds String to StringList. A new copy of String is made before it is
+ added to StringList.
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ STRING_LIST *OldList;
+ STRING_LIST *NewList;
+ CHAR8 *NewString;
+
+ OldList = *StringList;
+ NewList = AllocateStringListStruct (OldList->Count + 1);
+ if (NewList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewString = CloneString (String);
+ if (NewString == NULL) {
+ free (NewList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memcpy (
+ NewList->Strings,
+ OldList->Strings,
+ sizeof (OldList->Strings[0]) * OldList->Count
+ );
+ NewList->Count = OldList->Count + 1;
+ NewList->Strings[OldList->Count] = NewString;
+
+ *StringList = NewList;
+ free (OldList);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+RemoveLastStringFromList (
+ IN STRING_LIST *StringList
+ )
+/*++
+
+Routine Description:
+
+ Removes the last string from StringList and frees the memory associated
+ with it.
+
+Arguments:
+
+ StringList The string list to remove the string from
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ if (StringList->Count == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ free (StringList->Strings[StringList->Count - 1]);
+ StringList->Count--;
+ return EFI_SUCCESS;
+}
+
+
+STRING_LIST*
+AllocateStringListStruct (
+ IN UINTN StringCount
+ )
+/*++
+
+Routine Description:
+
+ Allocates a STRING_LIST structure that can store StringCount strings.
+
+Arguments:
+
+ StringCount The number of strings that need to be stored
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ return malloc (OFFSET_OF(STRING_LIST, Strings[StringCount + 1]));
+}
+
+
+VOID
+FreeStringList (
+ IN STRING_LIST *StringList
+ )
+/*++
+
+Routine Description:
+
+ Frees all memory associated with StringList.
+
+Arguments:
+
+ StringList The string list to free
+
+Returns:
+
+ VOID
+--*/
+{
+ while (StringList->Count > 0) {
+ RemoveLastStringFromList (StringList);
+ }
+
+ free (StringList);
+}
+
+
+CHAR8*
+StringListToString (
+ IN STRING_LIST *StringList
+ )
+/*++
+
+Routine Description:
+
+ Generates a string that represents the STRING_LIST
+
+Arguments:
+
+ StringList The string list to convert to a string
+
+Returns:
+
+ CHAR8* - The string list represented with a single string. The returned
+ string must be freed by the caller.
+
+--*/
+{
+ UINTN Count;
+ UINTN Length;
+ CHAR8 *NewString;
+
+ Length = 2;
+ for (Count = 0; Count < StringList->Count; Count++) {
+ if (Count > 0) {
+ Length += 2;
+ }
+ Length += strlen (StringList->Strings[Count]) + 2;
+ }
+
+ NewString = malloc (Length + 1);
+ if (NewString == NULL) {
+ return NewString;
+ }
+ NewString[0] = '\0';
+
+ strcat (NewString, "[");
+ for (Count = 0; Count < StringList->Count; Count++) {
+ if (Count > 0) {
+ strcat (NewString, ", ");
+ }
+ strcat (NewString, "\"");
+ strcat (NewString, StringList->Strings[Count]);
+ strcat (NewString, "\"");
+ }
+ strcat (NewString, "]");
+
+ return NewString;
+}
+
+
+VOID
+PrintStringList (
+ IN STRING_LIST *StringList
+ )
+/*++
+
+Routine Description:
+
+ Prints out the string list
+
+Arguments:
+
+ StringList The string list to print
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+{
+ CHAR8* String;
+ String = StringListToString (StringList);
+ if (String != NULL) {
+ printf ("%s", String);
+ free (String);
+ }
+}
+
+
diff --git a/BaseTools/Source/C/Common/StringFuncs.h b/BaseTools/Source/C/Common/StringFuncs.h
new file mode 100644
index 0000000000..cf18460c4c
--- /dev/null
+++ b/BaseTools/Source/C/Common/StringFuncs.h
@@ -0,0 +1,257 @@
+/**
+
+Copyright (c) 2007 - 2008, 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:
+
+ StringFuncs.h
+
+Abstract:
+
+ String routines implementation.
+
+**/
+
+#ifndef _EFI_STRING_FUNCS_H
+#define _EFI_STRING_FUNCS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Common/UefiBaseTypes.h>
+
+//
+// Common data structures
+//
+typedef struct {
+ UINTN Count;
+ //
+ // Actually this array can be 0 or more items (based on Count)
+ //
+ CHAR8* Strings[1];
+} STRING_LIST;
+
+
+//
+// Functions declarations
+//
+
+CHAR8*
+CloneString (
+ IN CHAR8 *String
+ )
+;
+/**
+
+Routine Description:
+
+ Allocates a new string and copies 'String' to clone it
+
+Arguments:
+
+ String The string to clone
+
+Returns:
+
+ CHAR8* - NULL if there are not enough resources
+
+**/
+
+
+EFI_STATUS
+StripInfDscStringInPlace (
+ IN CHAR8 *String
+ )
+;
+/**
+
+Routine Description:
+
+ Remove all comments, leading and trailing whitespace from the string.
+
+Arguments:
+
+ Strin The string to 'strip'
+
+Returns:
+
+ EFI_STATUS
+
+**/
+
+
+STRING_LIST*
+SplitStringByWhitespace (
+ IN CHAR8 *String
+ )
+;
+/**
+
+Routine Description:
+
+ Creates and returns a 'split' STRING_LIST by splitting the string
+ on whitespace boundaries.
+
+Arguments:
+
+ String The string to 'split'
+
+Returns:
+
+ EFI_STATUS
+
+**/
+
+
+STRING_LIST*
+NewStringList (
+ )
+;
+/**
+
+Routine Description:
+
+ Creates a new STRING_LIST with 0 strings.
+
+Returns:
+
+ STRING_LIST* - Null if there is not enough resources to create the object.
+
+**/
+
+
+EFI_STATUS
+AppendCopyOfStringToList (
+ IN OUT STRING_LIST **StringList,
+ IN CHAR8 *String
+ )
+;
+/**
+
+Routine Description:
+
+ Adds String to StringList. A new copy of String is made before it is
+ added to StringList.
+
+Returns:
+
+ EFI_STATUS
+
+**/
+
+
+EFI_STATUS
+RemoveLastStringFromList (
+ IN STRING_LIST *StringList
+ )
+;
+/**
+
+Routine Description:
+
+ Removes the last string from StringList and frees the memory associated
+ with it.
+
+Arguments:
+
+ StringList The string list to remove the string from
+
+Returns:
+
+ EFI_STATUS
+
+**/
+
+
+STRING_LIST*
+AllocateStringListStruct (
+ IN UINTN StringCount
+ )
+;
+/**
+
+Routine Description:
+
+ Allocates a STRING_LIST structure that can store StringCount strings.
+
+Arguments:
+
+ StringCount The number of strings that need to be stored
+
+Returns:
+
+ EFI_STATUS
+
+**/
+
+
+VOID
+FreeStringList (
+ IN STRING_LIST *StringList
+ )
+;
+/**
+
+Routine Description:
+
+ Frees all memory associated with StringList.
+
+Arguments:
+
+ StringList The string list to free
+
+Returns:
+
+ EFI_STATUS
+
+**/
+
+
+CHAR8*
+StringListToString (
+ IN STRING_LIST *StringList
+ )
+;
+/**
+
+Routine Description:
+
+ Generates a string that represents the STRING_LIST
+
+Arguments:
+
+ StringList The string list to convert to a string
+
+Returns:
+
+ CHAR8* - The string list represented with a single string. The returned
+ string must be freed by the caller.
+
+**/
+
+
+VOID
+PrintStringList (
+ IN STRING_LIST *StringList
+ )
+;
+/**
+
+Routine Description:
+
+ Prints out the string list
+
+Arguments:
+
+ StringList The string list to print
+
+**/
+
+
+#endif
diff --git a/BaseTools/Source/C/Common/TianoCompress.c b/BaseTools/Source/C/Common/TianoCompress.c
new file mode 100644
index 0000000000..625f99eaca
--- /dev/null
+++ b/BaseTools/Source/C/Common/TianoCompress.c
@@ -0,0 +1,1753 @@
+/** @file
+
+Copyright (c) 2006 - 2008, 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:
+
+ TianoCompress.c
+
+Abstract:
+
+ Compression routine. The compression algorithm is a mixture of
+ LZ77 and Huffman coding. LZ77 transforms the source data into a
+ sequence of Original Characters and Pointers to repeated strings.
+ This sequence is further divided into Blocks and Huffman codings
+ are applied to each Block.
+
+**/
+
+#include "Compress.h"
+
+//
+// Macro Definitions
+//
+#undef UINT8_MAX
+typedef INT32 NODE;
+#define UINT8_MAX 0xff
+#define UINT8_BIT 8
+#define THRESHOLD 3
+#define INIT_CRC 0
+#define WNDBIT 19
+#define WNDSIZ (1U << WNDBIT)
+#define MAXMATCH 256
+#define BLKSIZ (1U << 14) // 16 * 1024U
+#define PERC_FLAG 0x80000000U
+#define CODE_BIT 16
+#define NIL 0
+#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
+#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2)
+#define CRCPOLY 0xA001
+#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT)
+
+//
+// C: the Char&Len Set; P: the Position Set; T: the exTra Set
+//
+#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
+#define CBIT 9
+#define NP (WNDBIT + 1)
+#define PBIT 5
+#define NT (CODE_BIT + 3)
+#define TBIT 5
+#if NT > NP
+#define NPT NT
+#else
+#define NPT NP
+#endif
+//
+// Function Prototypes
+//
+
+STATIC
+VOID
+PutDword(
+ IN UINT32 Data
+ );
+
+STATIC
+EFI_STATUS
+AllocateMemory (
+ VOID
+ );
+
+STATIC
+VOID
+FreeMemory (
+ VOID
+ );
+
+STATIC
+VOID
+InitSlide (
+ VOID
+ );
+
+STATIC
+NODE
+Child (
+ IN NODE NodeQ,
+ IN UINT8 CharC
+ );
+
+STATIC
+VOID
+MakeChild (
+ IN NODE NodeQ,
+ IN UINT8 CharC,
+ IN NODE NodeR
+ );
+
+STATIC
+VOID
+Split (
+ IN NODE Old
+ );
+
+STATIC
+VOID
+InsertNode (
+ VOID
+ );
+
+STATIC
+VOID
+DeleteNode (
+ VOID
+ );
+
+STATIC
+VOID
+GetNextMatch (
+ VOID
+ );
+
+STATIC
+EFI_STATUS
+Encode (
+ VOID
+ );
+
+STATIC
+VOID
+CountTFreq (
+ VOID
+ );
+
+STATIC
+VOID
+WritePTLen (
+ IN INT32 Number,
+ IN INT32 nbit,
+ IN INT32 Special
+ );
+
+STATIC
+VOID
+WriteCLen (
+ VOID
+ );
+
+STATIC
+VOID
+EncodeC (
+ IN INT32 Value
+ );
+
+STATIC
+VOID
+EncodeP (
+ IN UINT32 Value
+ );
+
+STATIC
+VOID
+SendBlock (
+ VOID
+ );
+
+STATIC
+VOID
+Output (
+ IN UINT32 c,
+ IN UINT32 p
+ );
+
+STATIC
+VOID
+HufEncodeStart (
+ VOID
+ );
+
+STATIC
+VOID
+HufEncodeEnd (
+ VOID
+ );
+
+STATIC
+VOID
+MakeCrcTable (
+ VOID
+ );
+
+STATIC
+VOID
+PutBits (
+ IN INT32 Number,
+ IN UINT32 Value
+ );
+
+STATIC
+INT32
+FreadCrc (
+ OUT UINT8 *Pointer,
+ IN INT32 Number
+ );
+
+STATIC
+VOID
+InitPutBits (
+ VOID
+ );
+
+STATIC
+VOID
+CountLen (
+ IN INT32 Index
+ );
+
+STATIC
+VOID
+MakeLen (
+ IN INT32 Root
+ );
+
+STATIC
+VOID
+DownHeap (
+ IN INT32 Index
+ );
+
+STATIC
+VOID
+MakeCode (
+ IN INT32 Number,
+ IN UINT8 Len[ ],
+ OUT UINT16 Code[]
+ );
+
+STATIC
+INT32
+MakeTree (
+ IN INT32 NParm,
+ IN UINT16 FreqParm[],
+ OUT UINT8 LenParm[ ],
+ OUT UINT16 CodeParm[]
+ );
+
+//
+// Global Variables
+//
+STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit;
+
+STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen;
+STATIC INT16 mHeap[NC + 1];
+STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN;
+STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc;
+STATIC UINT32 mCompSize, mOrigSize;
+
+STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1],
+ mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1];
+
+STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL;
+
+//
+// functions
+//
+EFI_STATUS
+TianoCompress (
+ IN UINT8 *SrcBuffer,
+ IN UINT32 SrcSize,
+ IN UINT8 *DstBuffer,
+ IN OUT UINT32 *DstSize
+ )
+/*++
+
+Routine Description:
+
+ The internal implementation of [Efi/Tiano]Compress().
+
+Arguments:
+
+ SrcBuffer - The buffer storing the source data
+ SrcSize - The size of source data
+ DstBuffer - The buffer to store the compressed data
+ DstSize - On input, the size of DstBuffer; On output,
+ the size of the actual compressed data.
+ Version - The version of de/compression algorithm.
+ Version 1 for UEFI 2.0 de/compression algorithm.
+ Version 2 for Tiano de/compression algorithm.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case,
+ DstSize contains the size needed.
+ EFI_SUCCESS - Compression is successful.
+ EFI_OUT_OF_RESOURCES - No resource to complete function.
+ EFI_INVALID_PARAMETER - Parameter supplied is wrong.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // Initializations
+ //
+ mBufSiz = 0;
+ mBuf = NULL;
+ mText = NULL;
+ mLevel = NULL;
+ mChildCount = NULL;
+ mPosition = NULL;
+ mParent = NULL;
+ mPrev = NULL;
+ mNext = NULL;
+
+ mSrc = SrcBuffer;
+ mSrcUpperLimit = mSrc + SrcSize;
+ mDst = DstBuffer;
+ mDstUpperLimit = mDst +*DstSize;
+
+ PutDword (0L);
+ PutDword (0L);
+
+ MakeCrcTable ();
+
+ mOrigSize = mCompSize = 0;
+ mCrc = INIT_CRC;
+
+ //
+ // Compress it
+ //
+ Status = Encode ();
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Null terminate the compressed data
+ //
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = 0;
+ }
+ //
+ // Fill in compressed size and original size
+ //
+ mDst = DstBuffer;
+ PutDword (mCompSize + 1);
+ PutDword (mOrigSize);
+
+ //
+ // Return
+ //
+ if (mCompSize + 1 + 8 > *DstSize) {
+ *DstSize = mCompSize + 1 + 8;
+ return EFI_BUFFER_TOO_SMALL;
+ } else {
+ *DstSize = mCompSize + 1 + 8;
+ return EFI_SUCCESS;
+ }
+
+}
+
+STATIC
+VOID
+PutDword (
+ IN UINT32 Data
+ )
+/*++
+
+Routine Description:
+
+ Put a dword to output stream
+
+Arguments:
+
+ Data - the dword to put
+
+Returns: (VOID)
+
+--*/
+{
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);
+ }
+}
+
+STATIC
+EFI_STATUS
+AllocateMemory (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Allocate memory spaces for data structures used in compression process
+
+Argements:
+ VOID
+
+Returns:
+
+ EFI_SUCCESS - Memory is allocated successfully
+ EFI_OUT_OF_RESOURCES - Allocation fails
+
+--*/
+{
+ UINT32 Index;
+
+ mText = malloc (WNDSIZ * 2 + MAXMATCH);
+ for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) {
+ mText[Index] = 0;
+ }
+
+ mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
+ mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
+ mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
+ mParent = malloc (WNDSIZ * 2 * sizeof (*mParent));
+ mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev));
+ mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext));
+
+ mBufSiz = BLKSIZ;
+ mBuf = malloc (mBufSiz);
+ while (mBuf == NULL) {
+ mBufSiz = (mBufSiz / 10U) * 9U;
+ if (mBufSiz < 4 * 1024U) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mBuf = malloc (mBufSiz);
+ }
+
+ mBuf[0] = 0;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+FreeMemory (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Called when compression is completed to free memory previously allocated.
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ if (mText != NULL) {
+ free (mText);
+ }
+
+ if (mLevel != NULL) {
+ free (mLevel);
+ }
+
+ if (mChildCount != NULL) {
+ free (mChildCount);
+ }
+
+ if (mPosition != NULL) {
+ free (mPosition);
+ }
+
+ if (mParent != NULL) {
+ free (mParent);
+ }
+
+ if (mPrev != NULL) {
+ free (mPrev);
+ }
+
+ if (mNext != NULL) {
+ free (mNext);
+ }
+
+ if (mBuf != NULL) {
+ free (mBuf);
+ }
+
+ return ;
+}
+
+STATIC
+VOID
+InitSlide (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize String Info Log data structures
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE Index;
+
+ for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) {
+ mLevel[Index] = 1;
+ mPosition[Index] = NIL; /* sentinel */
+ }
+
+ for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) {
+ mParent[Index] = NIL;
+ }
+
+ mAvail = 1;
+ for (Index = 1; Index < WNDSIZ - 1; Index++) {
+ mNext[Index] = (NODE) (Index + 1);
+ }
+
+ mNext[WNDSIZ - 1] = NIL;
+ for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) {
+ mNext[Index] = NIL;
+ }
+}
+
+STATIC
+NODE
+Child (
+ IN NODE NodeQ,
+ IN UINT8 CharC
+ )
+/*++
+
+Routine Description:
+
+ Find child node given the parent node and the edge character
+
+Arguments:
+
+ NodeQ - the parent node
+ CharC - the edge character
+
+Returns:
+
+ The child node (NIL if not found)
+
+--*/
+{
+ NODE NodeR;
+
+ NodeR = mNext[HASH (NodeQ, CharC)];
+ //
+ // sentinel
+ //
+ mParent[NIL] = NodeQ;
+ while (mParent[NodeR] != NodeQ) {
+ NodeR = mNext[NodeR];
+ }
+
+ return NodeR;
+}
+
+STATIC
+VOID
+MakeChild (
+ IN NODE Parent,
+ IN UINT8 CharC,
+ IN NODE Child
+ )
+/*++
+
+Routine Description:
+
+ Create a new child for a given parent node.
+
+Arguments:
+
+ Parent - the parent node
+ CharC - the edge character
+ Child - the child node
+
+Returns: (VOID)
+
+--*/
+{
+ NODE Node1;
+ NODE Node2;
+
+ Node1 = (NODE) HASH (Parent, CharC);
+ Node2 = mNext[Node1];
+ mNext[Node1] = Child;
+ mNext[Child] = Node2;
+ mPrev[Node2] = Child;
+ mPrev[Child] = Node1;
+ mParent[Child] = Parent;
+ mChildCount[Parent]++;
+}
+
+STATIC
+VOID
+Split (
+ NODE Old
+ )
+/*++
+
+Routine Description:
+
+ Split a node.
+
+Arguments:
+
+ Old - the node to split
+
+Returns: (VOID)
+
+--*/
+{
+ NODE New;
+ NODE TempNode;
+
+ New = mAvail;
+ mAvail = mNext[New];
+ mChildCount[New] = 0;
+ TempNode = mPrev[Old];
+ mPrev[New] = TempNode;
+ mNext[TempNode] = New;
+ TempNode = mNext[Old];
+ mNext[New] = TempNode;
+ mPrev[TempNode] = New;
+ mParent[New] = mParent[Old];
+ mLevel[New] = (UINT8) mMatchLen;
+ mPosition[New] = mPos;
+ MakeChild (New, mText[mMatchPos + mMatchLen], Old);
+ MakeChild (New, mText[mPos + mMatchLen], mPos);
+}
+
+STATIC
+VOID
+InsertNode (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Insert string info for current position into the String Info Log
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE NodeQ;
+ NODE NodeR;
+ NODE Index2;
+ NODE NodeT;
+ UINT8 CharC;
+ UINT8 *t1;
+ UINT8 *t2;
+
+ if (mMatchLen >= 4) {
+ //
+ // We have just got a long match, the target tree
+ // can be located by MatchPos + 1. Travese the tree
+ // from bottom up to get to a proper starting point.
+ // The usage of PERC_FLAG ensures proper node deletion
+ // in DeleteNode() later.
+ //
+ mMatchLen--;
+ NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ);
+ NodeQ = mParent[NodeR];
+ while (NodeQ == NIL) {
+ NodeR = mNext[NodeR];
+ NodeQ = mParent[NodeR];
+ }
+
+ while (mLevel[NodeQ] >= mMatchLen) {
+ NodeR = NodeQ;
+ NodeQ = mParent[NodeQ];
+ }
+
+ NodeT = NodeQ;
+ while (mPosition[NodeT] < 0) {
+ mPosition[NodeT] = mPos;
+ NodeT = mParent[NodeT];
+ }
+
+ if (NodeT < WNDSIZ) {
+ mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG);
+ }
+ } else {
+ //
+ // Locate the target tree
+ //
+ NodeQ = (NODE) (mText[mPos] + WNDSIZ);
+ CharC = mText[mPos + 1];
+ NodeR = Child (NodeQ, CharC);
+ if (NodeR == NIL) {
+ MakeChild (NodeQ, CharC, mPos);
+ mMatchLen = 1;
+ return ;
+ }
+
+ mMatchLen = 2;
+ }
+ //
+ // Traverse down the tree to find a match.
+ // Update Position value along the route.
+ // Node split or creation is involved.
+ //
+ for (;;) {
+ if (NodeR >= WNDSIZ) {
+ Index2 = MAXMATCH;
+ mMatchPos = NodeR;
+ } else {
+ Index2 = mLevel[NodeR];
+ mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
+ }
+
+ if (mMatchPos >= mPos) {
+ mMatchPos -= WNDSIZ;
+ }
+
+ t1 = &mText[mPos + mMatchLen];
+ t2 = &mText[mMatchPos + mMatchLen];
+ while (mMatchLen < Index2) {
+ if (*t1 != *t2) {
+ Split (NodeR);
+ return ;
+ }
+
+ mMatchLen++;
+ t1++;
+ t2++;
+ }
+
+ if (mMatchLen >= MAXMATCH) {
+ break;
+ }
+
+ mPosition[NodeR] = mPos;
+ NodeQ = NodeR;
+ NodeR = Child (NodeQ, *t1);
+ if (NodeR == NIL) {
+ MakeChild (NodeQ, *t1, mPos);
+ return ;
+ }
+
+ mMatchLen++;
+ }
+
+ NodeT = mPrev[NodeR];
+ mPrev[mPos] = NodeT;
+ mNext[NodeT] = mPos;
+ NodeT = mNext[NodeR];
+ mNext[mPos] = NodeT;
+ mPrev[NodeT] = mPos;
+ mParent[mPos] = NodeQ;
+ mParent[NodeR] = NIL;
+
+ //
+ // Special usage of 'next'
+ //
+ mNext[NodeR] = mPos;
+
+}
+
+STATIC
+VOID
+DeleteNode (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Delete outdated string info. (The Usage of PERC_FLAG
+ ensures a clean deletion)
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ NODE NodeQ;
+ NODE NodeR;
+ NODE NodeS;
+ NODE NodeT;
+ NODE NodeU;
+
+ if (mParent[mPos] == NIL) {
+ return ;
+ }
+
+ NodeR = mPrev[mPos];
+ NodeS = mNext[mPos];
+ mNext[NodeR] = NodeS;
+ mPrev[NodeS] = NodeR;
+ NodeR = mParent[mPos];
+ mParent[mPos] = NIL;
+ if (NodeR >= WNDSIZ) {
+ return ;
+ }
+
+ mChildCount[NodeR]--;
+ if (mChildCount[NodeR] > 1) {
+ return ;
+ }
+
+ NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG);
+ if (NodeT >= mPos) {
+ NodeT -= WNDSIZ;
+ }
+
+ NodeS = NodeT;
+ NodeQ = mParent[NodeR];
+ NodeU = mPosition[NodeQ];
+ while (NodeU & (UINT32) PERC_FLAG) {
+ NodeU &= (UINT32)~PERC_FLAG;
+ if (NodeU >= mPos) {
+ NodeU -= WNDSIZ;
+ }
+
+ if (NodeU > NodeS) {
+ NodeS = NodeU;
+ }
+
+ mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ);
+ NodeQ = mParent[NodeQ];
+ NodeU = mPosition[NodeQ];
+ }
+
+ if (NodeQ < WNDSIZ) {
+ if (NodeU >= mPos) {
+ NodeU -= WNDSIZ;
+ }
+
+ if (NodeU > NodeS) {
+ NodeS = NodeU;
+ }
+
+ mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG);
+ }
+
+ NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]);
+ NodeT = mPrev[NodeS];
+ NodeU = mNext[NodeS];
+ mNext[NodeT] = NodeU;
+ mPrev[NodeU] = NodeT;
+ NodeT = mPrev[NodeR];
+ mNext[NodeT] = NodeS;
+ mPrev[NodeS] = NodeT;
+ NodeT = mNext[NodeR];
+ mPrev[NodeT] = NodeS;
+ mNext[NodeS] = NodeT;
+ mParent[NodeS] = mParent[NodeR];
+ mParent[NodeR] = NIL;
+ mNext[NodeR] = mAvail;
+ mAvail = NodeR;
+}
+
+STATIC
+VOID
+GetNextMatch (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Advance the current position (read in new data if needed).
+ Delete outdated string info. Find a match string for current position.
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Number;
+
+ mRemainder--;
+ mPos++;
+ if (mPos == WNDSIZ * 2) {
+ memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH);
+ Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);
+ mRemainder += Number;
+ mPos = WNDSIZ;
+ }
+
+ DeleteNode ();
+ InsertNode ();
+}
+
+STATIC
+EFI_STATUS
+Encode (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ The main controlling routine for compression process.
+
+Arguments: (VOID)
+
+Returns:
+
+ EFI_SUCCESS - The compression is successful
+ EFI_OUT_0F_RESOURCES - Not enough memory for compression process
+
+--*/
+{
+ EFI_STATUS Status;
+ INT32 LastMatchLen;
+ NODE LastMatchPos;
+
+ Status = AllocateMemory ();
+ if (EFI_ERROR (Status)) {
+ FreeMemory ();
+ return Status;
+ }
+
+ InitSlide ();
+
+ HufEncodeStart ();
+
+ mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);
+
+ mMatchLen = 0;
+ mPos = WNDSIZ;
+ InsertNode ();
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+
+ while (mRemainder > 0) {
+ LastMatchLen = mMatchLen;
+ LastMatchPos = mMatchPos;
+ GetNextMatch ();
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+
+ if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
+ //
+ // Not enough benefits are gained by outputting a pointer,
+ // so just output the original character
+ //
+ Output (mText[mPos - 1], 0);
+
+ } else {
+
+ if (LastMatchLen == THRESHOLD) {
+ if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) {
+ Output (mText[mPos - 1], 0);
+ continue;
+ }
+ }
+ //
+ // Outputting a pointer is beneficial enough, do it.
+ //
+ Output (
+ LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
+ (mPos - LastMatchPos - 2) & (WNDSIZ - 1)
+ );
+ LastMatchLen--;
+ while (LastMatchLen > 0) {
+ GetNextMatch ();
+ LastMatchLen--;
+ }
+
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+ }
+ }
+
+ HufEncodeEnd ();
+ FreeMemory ();
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+CountTFreq (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Count the frequencies for the Extra Set
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Index;
+ INT32 Index3;
+ INT32 Number;
+ INT32 Count;
+
+ for (Index = 0; Index < NT; Index++) {
+ mTFreq[Index] = 0;
+ }
+
+ Number = NC;
+ while (Number > 0 && mCLen[Number - 1] == 0) {
+ Number--;
+ }
+
+ Index = 0;
+ while (Index < Number) {
+ Index3 = mCLen[Index++];
+ if (Index3 == 0) {
+ Count = 1;
+ while (Index < Number && mCLen[Index] == 0) {
+ Index++;
+ Count++;
+ }
+
+ if (Count <= 2) {
+ mTFreq[0] = (UINT16) (mTFreq[0] + Count);
+ } else if (Count <= 18) {
+ mTFreq[1]++;
+ } else if (Count == 19) {
+ mTFreq[0]++;
+ mTFreq[1]++;
+ } else {
+ mTFreq[2]++;
+ }
+ } else {
+ mTFreq[Index3 + 2]++;
+ }
+ }
+}
+
+STATIC
+VOID
+WritePTLen (
+ IN INT32 Number,
+ IN INT32 nbit,
+ IN INT32 Special
+ )
+/*++
+
+Routine Description:
+
+ Outputs the code length array for the Extra Set or the Position Set.
+
+Arguments:
+
+ Number - the number of symbols
+ nbit - the number of bits needed to represent 'n'
+ Special - the special symbol that needs to be take care of
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Index;
+ INT32 Index3;
+
+ while (Number > 0 && mPTLen[Number - 1] == 0) {
+ Number--;
+ }
+
+ PutBits (nbit, Number);
+ Index = 0;
+ while (Index < Number) {
+ Index3 = mPTLen[Index++];
+ if (Index3 <= 6) {
+ PutBits (3, Index3);
+ } else {
+ PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2);
+ }
+
+ if (Index == Special) {
+ while (Index < 6 && mPTLen[Index] == 0) {
+ Index++;
+ }
+
+ PutBits (2, (Index - 3) & 3);
+ }
+ }
+}
+
+STATIC
+VOID
+WriteCLen (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Outputs the code length array for Char&Length Set
+
+Arguments: (VOID)
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Index;
+ INT32 Index3;
+ INT32 Number;
+ INT32 Count;
+
+ Number = NC;
+ while (Number > 0 && mCLen[Number - 1] == 0) {
+ Number--;
+ }
+
+ PutBits (CBIT, Number);
+ Index = 0;
+ while (Index < Number) {
+ Index3 = mCLen[Index++];
+ if (Index3 == 0) {
+ Count = 1;
+ while (Index < Number && mCLen[Index] == 0) {
+ Index++;
+ Count++;
+ }
+
+ if (Count <= 2) {
+ for (Index3 = 0; Index3 < Count; Index3++) {
+ PutBits (mPTLen[0], mPTCode[0]);
+ }
+ } else if (Count <= 18) {
+ PutBits (mPTLen[1], mPTCode[1]);
+ PutBits (4, Count - 3);
+ } else if (Count == 19) {
+ PutBits (mPTLen[0], mPTCode[0]);
+ PutBits (mPTLen[1], mPTCode[1]);
+ PutBits (4, 15);
+ } else {
+ PutBits (mPTLen[2], mPTCode[2]);
+ PutBits (CBIT, Count - 20);
+ }
+ } else {
+ PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]);
+ }
+ }
+}
+
+STATIC
+VOID
+EncodeC (
+ IN INT32 Value
+ )
+{
+ PutBits (mCLen[Value], mCCode[Value]);
+}
+
+STATIC
+VOID
+EncodeP (
+ IN UINT32 Value
+ )
+{
+ UINT32 Index;
+ UINT32 NodeQ;
+
+ Index = 0;
+ NodeQ = Value;
+ while (NodeQ) {
+ NodeQ >>= 1;
+ Index++;
+ }
+
+ PutBits (mPTLen[Index], mPTCode[Index]);
+ if (Index > 1) {
+ PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1)));
+ }
+}
+
+STATIC
+VOID
+SendBlock (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Huffman code the block and output it.
+
+Arguments:
+ (VOID)
+
+Returns:
+ (VOID)
+
+--*/
+{
+ UINT32 Index;
+ UINT32 Index2;
+ UINT32 Index3;
+ UINT32 Flags;
+ UINT32 Root;
+ UINT32 Pos;
+ UINT32 Size;
+ Flags = 0;
+
+ Root = MakeTree (NC, mCFreq, mCLen, mCCode);
+ Size = mCFreq[Root];
+ PutBits (16, Size);
+ if (Root >= NC) {
+ CountTFreq ();
+ Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);
+ if (Root >= NT) {
+ WritePTLen (NT, TBIT, 3);
+ } else {
+ PutBits (TBIT, 0);
+ PutBits (TBIT, Root);
+ }
+
+ WriteCLen ();
+ } else {
+ PutBits (TBIT, 0);
+ PutBits (TBIT, 0);
+ PutBits (CBIT, 0);
+ PutBits (CBIT, Root);
+ }
+
+ Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);
+ if (Root >= NP) {
+ WritePTLen (NP, PBIT, -1);
+ } else {
+ PutBits (PBIT, 0);
+ PutBits (PBIT, Root);
+ }
+
+ Pos = 0;
+ for (Index = 0; Index < Size; Index++) {
+ if (Index % UINT8_BIT == 0) {
+ Flags = mBuf[Pos++];
+ } else {
+ Flags <<= 1;
+ }
+
+ if (Flags & (1U << (UINT8_BIT - 1))) {
+ EncodeC (mBuf[Pos++] + (1U << UINT8_BIT));
+ Index3 = mBuf[Pos++];
+ for (Index2 = 0; Index2 < 3; Index2++) {
+ Index3 <<= UINT8_BIT;
+ Index3 += mBuf[Pos++];
+ }
+
+ EncodeP (Index3);
+ } else {
+ EncodeC (mBuf[Pos++]);
+ }
+ }
+
+ for (Index = 0; Index < NC; Index++) {
+ mCFreq[Index] = 0;
+ }
+
+ for (Index = 0; Index < NP; Index++) {
+ mPFreq[Index] = 0;
+ }
+}
+
+STATIC
+VOID
+Output (
+ IN UINT32 CharC,
+ IN UINT32 Pos
+ )
+/*++
+
+Routine Description:
+
+ Outputs an Original Character or a Pointer
+
+Arguments:
+
+ CharC - The original character or the 'String Length' element of a Pointer
+ Pos - The 'Position' field of a Pointer
+
+Returns: (VOID)
+
+--*/
+{
+ STATIC UINT32 CPos;
+
+ if ((mOutputMask >>= 1) == 0) {
+ mOutputMask = 1U << (UINT8_BIT - 1);
+ //
+ // Check the buffer overflow per outputing UINT8_BIT symbols
+ // which is an Original Character or a Pointer. The biggest
+ // symbol is a Pointer which occupies 5 bytes.
+ //
+ if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) {
+ SendBlock ();
+ mOutputPos = 0;
+ }
+
+ CPos = mOutputPos++;
+ mBuf[CPos] = 0;
+ }
+
+ mBuf[mOutputPos++] = (UINT8) CharC;
+ mCFreq[CharC]++;
+ if (CharC >= (1U << UINT8_BIT)) {
+ mBuf[CPos] |= mOutputMask;
+ mBuf[mOutputPos++] = (UINT8) (Pos >> 24);
+ mBuf[mOutputPos++] = (UINT8) (Pos >> 16);
+ mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT));
+ mBuf[mOutputPos++] = (UINT8) Pos;
+ CharC = 0;
+ while (Pos) {
+ Pos >>= 1;
+ CharC++;
+ }
+
+ mPFreq[CharC]++;
+ }
+}
+
+STATIC
+VOID
+HufEncodeStart (
+ VOID
+ )
+{
+ INT32 Index;
+
+ for (Index = 0; Index < NC; Index++) {
+ mCFreq[Index] = 0;
+ }
+
+ for (Index = 0; Index < NP; Index++) {
+ mPFreq[Index] = 0;
+ }
+
+ mOutputPos = mOutputMask = 0;
+ InitPutBits ();
+ return ;
+}
+
+STATIC
+VOID
+HufEncodeEnd (
+ VOID
+ )
+{
+ SendBlock ();
+
+ //
+ // Flush remaining bits
+ //
+ PutBits (UINT8_BIT - 1, 0);
+
+ return ;
+}
+
+STATIC
+VOID
+MakeCrcTable (
+ VOID
+ )
+{
+ UINT32 Index;
+ UINT32 Index2;
+ UINT32 Temp;
+
+ for (Index = 0; Index <= UINT8_MAX; Index++) {
+ Temp = Index;
+ for (Index2 = 0; Index2 < UINT8_BIT; Index2++) {
+ if (Temp & 1) {
+ Temp = (Temp >> 1) ^ CRCPOLY;
+ } else {
+ Temp >>= 1;
+ }
+ }
+
+ mCrcTable[Index] = (UINT16) Temp;
+ }
+}
+
+STATIC
+VOID
+PutBits (
+ IN INT32 Number,
+ IN UINT32 Value
+ )
+/*++
+
+Routine Description:
+
+ Outputs rightmost n bits of x
+
+Arguments:
+
+ Number - the rightmost n bits of the data is used
+ x - the data
+
+Returns: (VOID)
+
+--*/
+{
+ UINT8 Temp;
+
+ while (Number >= mBitCount) {
+ //
+ // Number -= mBitCount should never equal to 32
+ //
+ Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount)));
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = Temp;
+ }
+
+ mCompSize++;
+ mSubBitBuf = 0;
+ mBitCount = UINT8_BIT;
+ }
+
+ mSubBitBuf |= Value << (mBitCount -= Number);
+}
+
+STATIC
+INT32
+FreadCrc (
+ OUT UINT8 *Pointer,
+ IN INT32 Number
+ )
+/*++
+
+Routine Description:
+
+ Read in source data
+
+Arguments:
+
+ Pointer - the buffer to hold the data
+ Number - number of bytes to read
+
+Returns:
+
+ number of bytes actually read
+
+--*/
+{
+ INT32 Index;
+
+ for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) {
+ *Pointer++ = *mSrc++;
+ }
+
+ Number = Index;
+
+ Pointer -= Number;
+ mOrigSize += Number;
+ Index--;
+ while (Index >= 0) {
+ UPDATE_CRC (*Pointer++);
+ Index--;
+ }
+
+ return Number;
+}
+
+STATIC
+VOID
+InitPutBits (
+ VOID
+ )
+{
+ mBitCount = UINT8_BIT;
+ mSubBitBuf = 0;
+}
+
+STATIC
+VOID
+CountLen (
+ IN INT32 Index
+ )
+/*++
+
+Routine Description:
+
+ Count the number of each code length for a Huffman tree.
+
+Arguments:
+
+ Index - the top node
+
+Returns: (VOID)
+
+--*/
+{
+ STATIC INT32 Depth = 0;
+
+ if (Index < mN) {
+ mLenCnt[(Depth < 16) ? Depth : 16]++;
+ } else {
+ Depth++;
+ CountLen (mLeft[Index]);
+ CountLen (mRight[Index]);
+ Depth--;
+ }
+}
+
+STATIC
+VOID
+MakeLen (
+ IN INT32 Root
+ )
+/*++
+
+Routine Description:
+
+ Create code length array for a Huffman tree
+
+Arguments:
+
+ Root - the root of the tree
+
+Returns:
+
+ VOID
+
+--*/
+{
+ INT32 Index;
+ INT32 Index3;
+ UINT32 Cum;
+
+ for (Index = 0; Index <= 16; Index++) {
+ mLenCnt[Index] = 0;
+ }
+
+ CountLen (Root);
+
+ //
+ // Adjust the length count array so that
+ // no code will be generated longer than its designated length
+ //
+ Cum = 0;
+ for (Index = 16; Index > 0; Index--) {
+ Cum += mLenCnt[Index] << (16 - Index);
+ }
+
+ while (Cum != (1U << 16)) {
+ mLenCnt[16]--;
+ for (Index = 15; Index > 0; Index--) {
+ if (mLenCnt[Index] != 0) {
+ mLenCnt[Index]--;
+ mLenCnt[Index + 1] += 2;
+ break;
+ }
+ }
+
+ Cum--;
+ }
+
+ for (Index = 16; Index > 0; Index--) {
+ Index3 = mLenCnt[Index];
+ Index3--;
+ while (Index3 >= 0) {
+ mLen[*mSortPtr++] = (UINT8) Index;
+ Index3--;
+ }
+ }
+}
+
+STATIC
+VOID
+DownHeap (
+ IN INT32 Index
+ )
+{
+ INT32 Index2;
+ INT32 Index3;
+
+ //
+ // priority queue: send Index-th entry down heap
+ //
+ Index3 = mHeap[Index];
+ Index2 = 2 * Index;
+ while (Index2 <= mHeapSize) {
+ if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) {
+ Index2++;
+ }
+
+ if (mFreq[Index3] <= mFreq[mHeap[Index2]]) {
+ break;
+ }
+
+ mHeap[Index] = mHeap[Index2];
+ Index = Index2;
+ Index2 = 2 * Index;
+ }
+
+ mHeap[Index] = (INT16) Index3;
+}
+
+STATIC
+VOID
+MakeCode (
+ IN INT32 Number,
+ IN UINT8 Len[ ],
+ OUT UINT16 Code[]
+ )
+/*++
+
+Routine Description:
+
+ Assign code to each symbol based on the code length array
+
+Arguments:
+
+ Number - number of symbols
+ Len - the code length array
+ Code - stores codes for each symbol
+
+Returns: (VOID)
+
+--*/
+{
+ INT32 Index;
+ UINT16 Start[18];
+
+ Start[1] = 0;
+ for (Index = 1; Index <= 16; Index++) {
+ Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1);
+ }
+
+ for (Index = 0; Index < Number; Index++) {
+ Code[Index] = Start[Len[Index]]++;
+ }
+}
+
+STATIC
+INT32
+MakeTree (
+ IN INT32 NParm,
+ IN UINT16 FreqParm[],
+ OUT UINT8 LenParm[ ],
+ OUT UINT16 CodeParm[]
+ )
+/*++
+
+Routine Description:
+
+ Generates Huffman codes given a frequency distribution of symbols
+
+Arguments:
+
+ NParm - number of symbols
+ FreqParm - frequency of each symbol
+ LenParm - code length for each symbol
+ CodeParm - code for each symbol
+
+Returns:
+
+ Root of the Huffman tree.
+
+--*/
+{
+ INT32 Index;
+ INT32 Index2;
+ INT32 Index3;
+ INT32 Avail;
+
+ //
+ // make tree, calculate len[], return root
+ //
+ mN = NParm;
+ mFreq = FreqParm;
+ mLen = LenParm;
+ Avail = mN;
+ mHeapSize = 0;
+ mHeap[1] = 0;
+ for (Index = 0; Index < mN; Index++) {
+ mLen[Index] = 0;
+ if (mFreq[Index]) {
+ mHeapSize++;
+ mHeap[mHeapSize] = (INT16) Index;
+ }
+ }
+
+ if (mHeapSize < 2) {
+ CodeParm[mHeap[1]] = 0;
+ return mHeap[1];
+ }
+
+ for (Index = mHeapSize / 2; Index >= 1; Index--) {
+ //
+ // make priority queue
+ //
+ DownHeap (Index);
+ }
+
+ mSortPtr = CodeParm;
+ do {
+ Index = mHeap[1];
+ if (Index < mN) {
+ *mSortPtr++ = (UINT16) Index;
+ }
+
+ mHeap[1] = mHeap[mHeapSize--];
+ DownHeap (1);
+ Index2 = mHeap[1];
+ if (Index2 < mN) {
+ *mSortPtr++ = (UINT16) Index2;
+ }
+
+ Index3 = Avail++;
+ mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]);
+ mHeap[1] = (INT16) Index3;
+ DownHeap (1);
+ mLeft[Index3] = (UINT16) Index;
+ mRight[Index3] = (UINT16) Index2;
+ } while (mHeapSize > 1);
+
+ mSortPtr = CodeParm;
+ MakeLen (Index3);
+ MakeCode (NParm, LenParm, CodeParm);
+
+ //
+ // return root
+ //
+ return Index3;
+}
diff --git a/BaseTools/Source/C/Common/WinNtInclude.h b/BaseTools/Source/C/Common/WinNtInclude.h
new file mode 100644
index 0000000000..96c17993a1
--- /dev/null
+++ b/BaseTools/Source/C/Common/WinNtInclude.h
@@ -0,0 +1,73 @@
+/** @file
+
+Copyright (c) 2006 - 2008, 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:
+ WinNtInclude.h
+
+Abstract:
+ Include file for the WinNt Library
+
+**/
+
+#ifndef __WIN_NT_INCLUDE_H__
+#define __WIN_NT_INCLUDE_H__
+
+#define GUID _WINNT_DUP_GUID_____
+#define _LIST_ENTRY _WINNT_DUP_LIST_ENTRY_FORWARD
+#define LIST_ENTRY _WINNT_DUP_LIST_ENTRY
+#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement
+#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement
+#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64
+#undef UNALIGNED
+#undef CONST
+#undef VOID
+
+#ifndef __GNUC__
+#include "windows.h"
+
+//
+// Win32 include files do not compile clean with /W4, so we use the warning
+// pragma to suppress the warnings for Win32 only. This way our code can stil
+// compile at /W4 (highest warning level) with /WX (warnings cause build
+// errors).
+//
+#pragma warning(disable : 4115)
+#pragma warning(disable : 4201)
+#pragma warning(disable : 4214)
+#pragma warning(disable : 4028)
+#pragma warning(disable : 4133)
+
+//
+// Set the warnings back on as the EFI code must be /W4.
+//
+#pragma warning(default : 4115)
+#pragma warning(default : 4201)
+#pragma warning(default : 4214)
+
+#endif
+
+#undef GUID
+#undef _LIST_ENTRY
+#undef LIST_ENTRY
+#undef InterlockedIncrement
+#undef InterlockedDecrement
+#undef InterlockedCompareExchange64
+#undef InterlockedCompareExchangePointer
+
+#define VOID void
+
+//
+// Prevent collisions with Windows API name macros that deal with Unicode/Not issues
+//
+#undef LoadImage
+#undef CreateEvent
+
+#endif