summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common')
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BasePeCoff.c1469
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.c74
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.h61
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.c2191
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h469
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Compress.h82
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.c313
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.h41
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.c1014
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.h159
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiCompress.c1591
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.c902
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.h164
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c1775
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h163
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.c927
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.h189
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/GNUmakefile33
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile36
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile.kmk63
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.c251
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.h105
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.c548
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.h209
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.c295
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.h133
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.c205
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.h120
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.c695
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.h220
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.c779
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h185
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLib.h213
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c334
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.c1429
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.h104
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.c413
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.h244
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/TianoCompress.c1746
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/WinNtInclude.h78
40 files changed, 20022 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BasePeCoff.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BasePeCoff.c
new file mode 100644
index 00000000..154f737f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BasePeCoff.c
@@ -0,0 +1,1469 @@
+/** @file
+
+ Functions to get info and load PE/COFF image.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+PeCoffLoaderRelocateArmImage (
+ IN UINT16 **Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ );
+
+RETURN_STATUS
+PeCoffLoaderRelocateRiscVImage (
+ 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_X64 && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_ARMT && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_EBC && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_AARCH64 && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_RISCV64) {
+ 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) {
+ //
+ // unsupported 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) && (TeHdr->DataDirectory[0].VirtualAddress == 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 multiple 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;
+ UINT64 *F64;
+ 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;
+ }
+
+ //
+ // Use DestinationAddress field of ImageContext as the relocation address even if it is 0.
+ //
+ BaseAddress = ImageContext->DestinationAddress;
+
+ 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];
+ if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
+ RelocBaseEnd = PeCoffLoaderImageAddress (
+ ImageContext,
+ RelocDir->VirtualAddress + RelocDir->Size - 1
+ );
+ if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_LOAD_ERROR;
+ }
+ } else {
+ //
+ // Set base and end to bypass processing below.
+ //
+ RelocBase = RelocBaseEnd = 0;
+ }
+ } 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];
+ if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
+ RelocBaseEnd = PeCoffLoaderImageAddress (
+ ImageContext,
+ RelocDir->VirtualAddress + RelocDir->Size - 1
+ );
+ if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_LOAD_ERROR;
+ }
+ } else {
+ //
+ // Set base and end to bypass processing below.
+ //
+ RelocBase = RelocBaseEnd = 0;
+ }
+ } 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);
+ if (FixupBase == NULL) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_LOAD_ERROR;
+ }
+ } 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_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_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:
+ Status = PeCoffLoaderRelocateIa32Image (Reloc, Fixup, &FixupData, Adjust);
+ break;
+ case EFI_IMAGE_MACHINE_ARMT:
+ Status = PeCoffLoaderRelocateArmImage (&Reloc, Fixup, &FixupData, Adjust);
+ break;
+ case EFI_IMAGE_MACHINE_RISCV64:
+ Status = PeCoffLoaderRelocateRiscVImage (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;
+ OptionHeader.Header = 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 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;
+ }
+
+
+ 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;
+ }
+
+ //
+ // 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 = (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;
+
+ case CODEVIEW_SIGNATURE_MTOC:
+ ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY);
+
+ 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:
+ //
+ // Assume PE32+ image with X64 Machine field
+ //
+ Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+ break;
+ default:
+ //
+ // For unknown 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.
+ //
+ CodeViewEntryPointer = NULL;
+ 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));
+ case CODEVIEW_SIGNATURE_MTOC:
+ return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderGetEntryPoint (
+ IN VOID *Pe32Data,
+ OUT VOID **EntryPoint,
+ OUT VOID **BaseOfImage
+ )
+{
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
+
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ //
+ // 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;
+ }
+
+ //
+ // Calculate the entry point relative to the start of the image.
+ // AddressOfEntryPoint is common for PE32 & PE32+
+ //
+ if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ *BaseOfImage = (VOID *)(UINTN)(Hdr.Te->ImageBase + Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
+ *EntryPoint = (VOID *)((UINTN)*BaseOfImage + (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
+ return RETURN_SUCCESS;
+ } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
+ *EntryPoint = (VOID *)(UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint;
+ if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ *BaseOfImage = (VOID *)(UINTN)Hdr.Pe32->OptionalHeader.ImageBase;
+ } else {
+ *BaseOfImage = (VOID *)(UINTN)Hdr.Pe32Plus->OptionalHeader.ImageBase;
+ }
+ *EntryPoint = (VOID *)(UINTN)((UINTN)*EntryPoint + (UINTN)*BaseOfImage);
+ return RETURN_SUCCESS;
+ }
+
+ return RETURN_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.c
new file mode 100644
index 00000000..507b70aa
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.c
@@ -0,0 +1,74 @@
+/** @file
+Binder function implementations for ANSI C libraries.
+
+Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.h
new file mode 100644
index 00000000..accd22d1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.h
@@ -0,0 +1,61 @@
+/** @file
+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.
+
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.c
new file mode 100644
index 00000000..ecda9d70
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.c
@@ -0,0 +1,2191 @@
+/** @file
+Common basic Library Functions
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#ifdef __GNUC__
+#include <unistd.h>
+#else
+#include <direct.h>
+#endif
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \
+ do { \
+ ASSERT (Expression); \
+ if (!(Expression)) { \
+ return Status; \
+ } \
+ } while (FALSE)
+
+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 (LongFilePath (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 (LongFilePath (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",
+ (unsigned) 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",
+ (unsigned) 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",
+ (unsigned) 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
+
+#define WINDOWS_EXTENSION_PATH "\\\\?\\"
+#define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC"
+
+//
+// Global data to store full file path. It is not required to be free.
+//
+CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH];
+
+CHAR8 *
+LongFilePath (
+ IN CHAR8 *FileName
+ )
+/*++
+
+Routine Description:
+ Convert FileName to the long file path, which can support larger than 260 length.
+
+Arguments:
+ FileName - FileName.
+
+Returns:
+ LongFilePath A pointer to the converted long file path.
+
+--*/
+{
+#ifdef __GNUC__
+ //
+ // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here.
+ // unix has no limitation on file path. Just return FileName.
+ //
+ return FileName;
+#else
+ CHAR8 *RootPath;
+ CHAR8 *PathPointer;
+ CHAR8 *NextPointer;
+
+ PathPointer = (CHAR8 *) FileName;
+
+ if (FileName != NULL) {
+ //
+ // Add the extension string first to support long file path.
+ //
+ mCommonLibFullPath[0] = 0;
+ strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH);
+
+ if (strlen (FileName) > 1 && FileName[0] == '\\' && FileName[1] == '\\') {
+ //
+ // network path like \\server\share to \\?\UNC\server\share
+ //
+ strcpy (mCommonLibFullPath, WINDOWS_UNC_EXTENSION_PATH);
+ FileName ++;
+ } else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) {
+ //
+ // Relative file path. Convert it to absolute path.
+ //
+ RootPath = getcwd (NULL, 0);
+ if (RootPath != NULL) {
+ if (strlen (mCommonLibFullPath) + strlen (RootPath) > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");
+ free (RootPath);
+ return NULL;
+ }
+ strncat (mCommonLibFullPath, RootPath, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ if (FileName[0] != '\\' && FileName[0] != '/') {
+ if (strlen (mCommonLibFullPath) + 1 > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!");
+ free (RootPath);
+ return NULL;
+ }
+ //
+ // Attach directory separator
+ //
+ strncat (mCommonLibFullPath, "\\", MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ }
+ free (RootPath);
+ }
+ }
+
+ //
+ // Construct the full file path
+ //
+ if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName);
+ return NULL;
+ }
+ strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+
+ //
+ // Convert directory separator '/' to '\\'
+ //
+ PathPointer = (CHAR8 *) mCommonLibFullPath;
+ do {
+ if (*PathPointer == '/') {
+ *PathPointer = '\\';
+ }
+ } while (*PathPointer ++ != '\0');
+
+ //
+ // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
+ //
+ if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) {
+ *(PathPointer + 2) = '\0';
+ strncat (mCommonLibFullPath, PathPointer + 3, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ }
+
+ //
+ // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH.
+ //
+ while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) {
+ *PathPointer = '\0';
+ strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ }
+
+ //
+ // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH.
+ //
+ while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) {
+ *PathPointer = '\0';
+ strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ }
+
+ //
+ // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH.
+ //
+ while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) {
+ NextPointer = PathPointer + 3;
+ do {
+ PathPointer --;
+ } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\');
+
+ if (*PathPointer == '\\') {
+ //
+ // Skip one directory
+ //
+ *PathPointer = '\0';
+ strncat (mCommonLibFullPath, NextPointer, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1);
+ } else {
+ //
+ // No directory is found. Just break.
+ //
+ break;
+ }
+ }
+
+ PathPointer = mCommonLibFullPath;
+ }
+
+ return PathPointer;
+#endif
+}
+
+CHAR16
+InternalCharToUpper (
+ CHAR16 Char
+ )
+{
+ if (Char >= L'a' && Char <= L'z') {
+ return (CHAR16) (Char - (L'a' - L'A'));
+ }
+
+ return Char;
+}
+
+UINTN
+StrnLenS (
+ CONST CHAR16 *String,
+ UINTN MaxSize
+ )
+{
+ UINTN Length;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero.
+ //
+ if ((String == NULL) || (MaxSize == 0)) {
+ return 0;
+ }
+
+ Length = 0;
+ while (String[Length] != 0) {
+ if (Length >= MaxSize - 1) {
+ return MaxSize;
+ }
+ Length++;
+ }
+ return Length;
+}
+
+
+VOID *
+InternalAllocatePool (
+ UINTN AllocationSize
+ )
+{
+ VOID * Memory;
+
+ Memory = malloc(AllocationSize);
+ ASSERT(Memory != NULL);
+ return Memory;
+}
+
+
+VOID *
+InternalReallocatePool (
+ UINTN OldSize,
+ UINTN NewSize,
+ VOID *OldBuffer OPTIONAL
+ )
+{
+ VOID *NewBuffer;
+
+ NewBuffer = AllocateZeroPool (NewSize);
+ if (NewBuffer != NULL && OldBuffer != NULL) {
+ memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize));
+ free(OldBuffer);
+ }
+ return NewBuffer;
+}
+
+VOID *
+ReallocatePool (
+ UINTN OldSize,
+ UINTN NewSize,
+ VOID *OldBuffer OPTIONAL
+ )
+{
+ return InternalReallocatePool (OldSize, NewSize, OldBuffer);
+}
+
+/**
+ Returns the length of a Null-terminated Unicode string.
+
+ This function returns the number of Unicode characters in the Null-terminated
+ Unicode string specified by String.
+
+ If String is NULL, then ASSERT().
+ If String is not aligned on a 16-bit boundary, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the
+ Null-terminator, then ASSERT().
+
+ @param String A pointer to a Null-terminated Unicode string.
+
+ @return The length of String.
+
+**/
+UINTN
+StrLen (
+ CONST CHAR16 *String
+ )
+{
+ UINTN Length;
+
+ ASSERT (String != NULL);
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ for (Length = 0; *String != L'\0'; String++, Length++) {
+ //
+ // If PcdMaximumUnicodeStringLength is not zero,
+ // length should not more than PcdMaximumUnicodeStringLength
+ //
+ }
+ return Length;
+}
+
+BOOLEAN
+InternalSafeStringIsOverlap (
+ IN VOID *Base1,
+ IN UINTN Size1,
+ IN VOID *Base2,
+ IN UINTN Size2
+ )
+{
+ if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) ||
+ (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOLEAN
+InternalSafeStringNoStrOverlap (
+ IN CHAR16 *Str1,
+ IN UINTN Size1,
+ IN CHAR16 *Str2,
+ IN UINTN Size2
+ )
+{
+ return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16));
+}
+
+/**
+ Convert a Null-terminated Unicode decimal string to a value of type UINT64.
+
+ This function outputs a value of type UINT64 by interpreting the contents of
+ the Unicode string specified by String as a decimal number. The format of the
+ input Unicode string String is:
+
+ [spaces] [decimal digits].
+
+ The valid decimal digit character is in the range [0-9]. The function will
+ ignore the pad space, which includes spaces or tab characters, before
+ [decimal digits]. The running zero in the beginning of [decimal digits] will
+ be ignored. Then, the function stops at the first character that is a not a
+ valid decimal character or a Null-terminator, whichever one comes first.
+
+ If String is NULL, then ASSERT().
+ If Data is NULL, then ASSERT().
+ If String is not aligned in a 16-bit boundary, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the
+ Null-terminator, then ASSERT().
+
+ If String has no valid decimal digits in the above format, then 0 is stored
+ at the location pointed to by Data.
+ If the number represented by String exceeds the range defined by UINT64, then
+ MAX_UINT64 is stored at the location pointed to by Data.
+
+ If EndPointer is not NULL, a pointer to the character that stopped the scan
+ is stored at the location pointed to by EndPointer. If String has no valid
+ decimal digits right after the optional pad spaces, the value of String is
+ stored at the location pointed to by EndPointer.
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param EndPointer Pointer to character that stops scan.
+ @param Data Pointer to the converted value.
+
+ @retval RETURN_SUCCESS Value is translated from String.
+ @retval RETURN_INVALID_PARAMETER If String is NULL.
+ If Data is NULL.
+ If PcdMaximumUnicodeStringLength is not
+ zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode
+ characters, not including the
+ Null-terminator.
+ @retval RETURN_UNSUPPORTED If the number represented by String exceeds
+ the range defined by UINT64.
+
+**/
+RETURN_STATUS
+StrDecimalToUint64S (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer, OPTIONAL
+ UINT64 *Data
+ )
+{
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. Neither String nor Data shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. The length of String shall not be greater than RSIZE_MAX.
+ //
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+
+ //
+ // Ignore the pad spaces (space or tab)
+ //
+ while ((*String == L' ') || (*String == L'\t')) {
+ String++;
+ }
+
+ //
+ // Ignore leading Zeros after the spaces
+ //
+ while (*String == L'0') {
+ String++;
+ }
+
+ *Data = 0;
+
+ while (InternalIsDecimalDigitCharacter (*String)) {
+ //
+ // If the number represented by String overflows according to the range
+ // defined by UINT64, then MAX_UINT64 is stored in *Data and
+ // RETURN_UNSUPPORTED is returned.
+ //
+ if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) {
+ *Data = MAX_UINT64;
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+ return RETURN_UNSUPPORTED;
+ }
+
+ *Data = (*Data) * 10 + (*String - L'0');
+ String++;
+ }
+
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+ return RETURN_SUCCESS;
+}
+
+/**
+ Convert a Null-terminated Unicode hexadecimal string to a value of type
+ UINT64.
+
+ This function outputs a value of type UINT64 by interpreting the contents of
+ the Unicode string specified by String as a hexadecimal number. The format of
+ the input Unicode string String is:
+
+ [spaces][zeros][x][hexadecimal digits].
+
+ The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
+ The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
+ If "x" appears in the input string, it must be prefixed with at least one 0.
+ The function will ignore the pad space, which includes spaces or tab
+ characters, before [zeros], [x] or [hexadecimal digit]. The running zero
+ before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts
+ after [x] or the first valid hexadecimal digit. Then, the function stops at
+ the first character that is a not a valid hexadecimal character or NULL,
+ whichever one comes first.
+
+ If String is NULL, then ASSERT().
+ If Data is NULL, then ASSERT().
+ If String is not aligned in a 16-bit boundary, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the
+ Null-terminator, then ASSERT().
+
+ If String has no valid hexadecimal digits in the above format, then 0 is
+ stored at the location pointed to by Data.
+ If the number represented by String exceeds the range defined by UINT64, then
+ MAX_UINT64 is stored at the location pointed to by Data.
+
+ If EndPointer is not NULL, a pointer to the character that stopped the scan
+ is stored at the location pointed to by EndPointer. If String has no valid
+ hexadecimal digits right after the optional pad spaces, the value of String
+ is stored at the location pointed to by EndPointer.
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param EndPointer Pointer to character that stops scan.
+ @param Data Pointer to the converted value.
+
+ @retval RETURN_SUCCESS Value is translated from String.
+ @retval RETURN_INVALID_PARAMETER If String is NULL.
+ If Data is NULL.
+ If PcdMaximumUnicodeStringLength is not
+ zero, and String contains more than
+ PcdMaximumUnicodeStringLength Unicode
+ characters, not including the
+ Null-terminator.
+ @retval RETURN_UNSUPPORTED If the number represented by String exceeds
+ the range defined by UINT64.
+
+**/
+RETURN_STATUS
+StrHexToUint64S (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer, OPTIONAL
+ UINT64 *Data
+ )
+{
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. Neither String nor Data shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. The length of String shall not be greater than RSIZE_MAX.
+ //
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+
+ //
+ // Ignore the pad spaces (space or tab)
+ //
+ while ((*String == L' ') || (*String == L'\t')) {
+ String++;
+ }
+
+ //
+ // Ignore leading Zeros after the spaces
+ //
+ while (*String == L'0') {
+ String++;
+ }
+
+ if (InternalCharToUpper (*String) == L'X') {
+ if (*(String - 1) != L'0') {
+ *Data = 0;
+ return RETURN_SUCCESS;
+ }
+ //
+ // Skip the 'X'
+ //
+ String++;
+ }
+
+ *Data = 0;
+
+ while (InternalIsHexaDecimalDigitCharacter (*String)) {
+ //
+ // If the number represented by String overflows according to the range
+ // defined by UINT64, then MAX_UINT64 is stored in *Data and
+ // RETURN_UNSUPPORTED is returned.
+ //
+ if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) {
+ *Data = MAX_UINT64;
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+ return RETURN_UNSUPPORTED;
+ }
+
+ *Data = ((*Data) << 4) + InternalHexCharToUintn (*String);
+ String++;
+ }
+
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) String;
+ }
+ return RETURN_SUCCESS;
+}
+
+UINT64
+StrDecimalToUint64 (
+ CONST CHAR16 *String
+ )
+{
+ UINT64 Result;
+
+ StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result);
+ return Result;
+}
+
+
+UINT64
+StrHexToUint64 (
+ CONST CHAR16 *String
+ )
+{
+ UINT64 Result;
+
+ StrHexToUint64S (String, (CHAR16 **) NULL, &Result);
+ return Result;
+}
+
+UINTN
+StrSize (
+ CONST CHAR16 *String
+ )
+{
+ return (StrLen (String) + 1) * sizeof (*String);
+}
+
+
+UINT64
+ReadUnaligned64 (
+ CONST UINT64 *Buffer
+ )
+{
+ ASSERT (Buffer != NULL);
+
+ return *Buffer;
+}
+
+UINT64
+WriteUnaligned64 (
+ UINT64 *Buffer,
+ UINT64 Value
+ )
+{
+ ASSERT (Buffer != NULL);
+
+ return *Buffer = Value;
+}
+
+
+EFI_GUID *
+CopyGuid (
+ EFI_GUID *DestinationGuid,
+ CONST EFI_GUID *SourceGuid
+ )
+{
+ WriteUnaligned64 (
+ (UINT64*)DestinationGuid,
+ ReadUnaligned64 ((CONST UINT64*)SourceGuid)
+ );
+ WriteUnaligned64 (
+ (UINT64*)DestinationGuid + 1,
+ ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1)
+ );
+ return DestinationGuid;
+}
+
+UINT16
+SwapBytes16 (
+ UINT16 Value
+ )
+{
+ return (UINT16) ((Value<< 8) | (Value>> 8));
+}
+
+
+UINT32
+SwapBytes32 (
+ UINT32 Value
+ )
+{
+ UINT32 LowerBytes;
+ UINT32 HigherBytes;
+
+ LowerBytes = (UINT32) SwapBytes16 ((UINT16) Value);
+ HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16));
+ return (LowerBytes << 16 | HigherBytes);
+}
+
+BOOLEAN
+InternalIsDecimalDigitCharacter (
+ CHAR16 Char
+ )
+{
+ return (BOOLEAN) (Char >= L'0' && Char <= L'9');
+}
+
+VOID *
+InternalAllocateCopyPool (
+ UINTN AllocationSize,
+ CONST VOID *Buffer
+ )
+{
+ VOID *Memory;
+
+ ASSERT (Buffer != NULL);
+
+ Memory = malloc (AllocationSize);
+ if (Memory != NULL) {
+ Memory = memcpy (Memory, Buffer, AllocationSize);
+ }
+ return Memory;
+}
+
+BOOLEAN
+InternalIsHexaDecimalDigitCharacter (
+ CHAR16 Char
+ )
+{
+
+ return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) ||
+ (Char >= L'A' && Char <= L'F') ||
+ (Char >= L'a' && Char <= L'f'));
+}
+
+UINTN
+InternalHexCharToUintn (
+ CHAR16 Char
+ )
+{
+ if (InternalIsDecimalDigitCharacter (Char)) {
+ return Char - L'0';
+ }
+
+ return (10 + InternalCharToUpper (Char) - L'A');
+}
+
+
+/**
+ Convert a Null-terminated Unicode hexadecimal string to a byte array.
+
+ This function outputs a byte array by interpreting the contents of
+ the Unicode string specified by String in hexadecimal format. The format of
+ the input Unicode string String is:
+
+ [XX]*
+
+ X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F].
+ The function decodes every two hexadecimal digit characters as one byte. The
+ decoding stops after Length of characters and outputs Buffer containing
+ (Length / 2) bytes.
+
+ If String is not aligned in a 16-bit boundary, then ASSERT().
+
+ If String is NULL, then ASSERT().
+
+ If Buffer is NULL, then ASSERT().
+
+ If Length is not multiple of 2, then ASSERT().
+
+ If PcdMaximumUnicodeStringLength is not zero and Length is greater than
+ PcdMaximumUnicodeStringLength, then ASSERT().
+
+ If MaxBufferSize is less than (Length / 2), then ASSERT().
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param Length The number of Unicode characters to decode.
+ @param Buffer Pointer to the converted bytes array.
+ @param MaxBufferSize The maximum size of Buffer.
+
+ @retval RETURN_SUCCESS Buffer is translated from String.
+ @retval RETURN_INVALID_PARAMETER If String is NULL.
+ If Data is NULL.
+ If Length is not multiple of 2.
+ If PcdMaximumUnicodeStringLength is not zero,
+ and Length is greater than
+ PcdMaximumUnicodeStringLength.
+ @retval RETURN_UNSUPPORTED If Length of characters from String contain
+ a character that is not valid hexadecimal
+ digit characters, or a Null-terminator.
+ @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2).
+**/
+RETURN_STATUS
+StrHexToBytes (
+ CONST CHAR16 *String,
+ UINTN Length,
+ UINT8 *Buffer,
+ UINTN MaxBufferSize
+ )
+{
+ UINTN Index;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. None of String or Buffer shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. Length shall not be greater than RSIZE_MAX.
+ //
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ //
+ // 3. Length shall not be odd.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER);
+
+ //
+ // 4. MaxBufferSize shall equal to or greater than Length / 2.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL);
+
+ //
+ // 5. String shall not contains invalid hexadecimal digits.
+ //
+ for (Index = 0; Index < Length; Index++) {
+ if (!InternalIsHexaDecimalDigitCharacter (String[Index])) {
+ break;
+ }
+ }
+ if (Index != Length) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Convert the hex string to bytes.
+ //
+ for(Index = 0; Index < Length; Index++) {
+
+ //
+ // For even characters, write the upper nibble for each buffer byte,
+ // and for even characters, the lower nibble.
+ //
+ if ((Index & BIT0) == 0) {
+ Buffer[Index / 2] = (UINT8) InternalHexCharToUintn (String[Index]) << 4;
+ } else {
+ Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]);
+ }
+ }
+ return RETURN_SUCCESS;
+}
+
+/**
+ Convert a Null-terminated Unicode GUID string to a value of type
+ EFI_GUID.
+
+ This function outputs a GUID value by interpreting the contents of
+ the Unicode string specified by String. The format of the input
+ Unicode string String consists of 36 characters, as follows:
+
+ aabbccdd-eeff-gghh-iijj-kkllmmnnoopp
+
+ The pairs aa - pp are two characters in the range [0-9], [a-f] and
+ [A-F], with each pair representing a single byte hexadecimal value.
+
+ The mapping between String and the EFI_GUID structure is as follows:
+ aa Data1[24:31]
+ bb Data1[16:23]
+ cc Data1[8:15]
+ dd Data1[0:7]
+ ee Data2[8:15]
+ ff Data2[0:7]
+ gg Data3[8:15]
+ hh Data3[0:7]
+ ii Data4[0:7]
+ jj Data4[8:15]
+ kk Data4[16:23]
+ ll Data4[24:31]
+ mm Data4[32:39]
+ nn Data4[40:47]
+ oo Data4[48:55]
+ pp Data4[56:63]
+
+ If String is NULL, then ASSERT().
+ If Guid is NULL, then ASSERT().
+ If String is not aligned in a 16-bit boundary, then ASSERT().
+
+ @param String Pointer to a Null-terminated Unicode string.
+ @param Guid Pointer to the converted GUID.
+
+ @retval RETURN_SUCCESS Guid is translated from String.
+ @retval RETURN_INVALID_PARAMETER If String is NULL.
+ If Data is NULL.
+ @retval RETURN_UNSUPPORTED If String is not as the above format.
+
+**/
+RETURN_STATUS
+StrToGuid (
+ CONST CHAR16 *String,
+ EFI_GUID *Guid
+ )
+{
+ RETURN_STATUS Status;
+ EFI_GUID LocalGuid;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. None of String or Guid shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // Get aabbccdd in big-endian.
+ //
+ Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1));
+ if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') {
+ return RETURN_UNSUPPORTED;
+ }
+ //
+ // Convert big-endian to little-endian.
+ //
+ LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1);
+ String += 2 * sizeof (LocalGuid.Data1) + 1;
+
+ //
+ // Get eeff in big-endian.
+ //
+ Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2));
+ if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') {
+ return RETURN_UNSUPPORTED;
+ }
+ //
+ // Convert big-endian to little-endian.
+ //
+ LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2);
+ String += 2 * sizeof (LocalGuid.Data2) + 1;
+
+ //
+ // Get gghh in big-endian.
+ //
+ Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3));
+ if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') {
+ return RETURN_UNSUPPORTED;
+ }
+ //
+ // Convert big-endian to little-endian.
+ //
+ LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3);
+ String += 2 * sizeof (LocalGuid.Data3) + 1;
+
+ //
+ // Get iijj.
+ //
+ Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2);
+ if (RETURN_ERROR (Status) || String[2 * 2] != L'-') {
+ return RETURN_UNSUPPORTED;
+ }
+ String += 2 * 2 + 1;
+
+ //
+ // Get kkllmmnnoopp.
+ //
+ Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6);
+ if (RETURN_ERROR (Status)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ CopyGuid (Guid, &LocalGuid);
+ return RETURN_SUCCESS;
+}
+
+/**
+ Compares up to a specified length the contents of two Null-terminated Unicode strings,
+ and returns the difference between the first mismatched Unicode characters.
+
+ This function compares the Null-terminated Unicode string FirstString to the
+ Null-terminated Unicode string SecondString. At most, Length Unicode
+ characters will be compared. If Length is 0, then 0 is returned. If
+ FirstString is identical to SecondString, then 0 is returned. Otherwise, the
+ value returned is the first mismatched Unicode character in SecondString
+ subtracted from the first mismatched Unicode character in FirstString.
+
+ If Length > 0 and FirstString is NULL, then ASSERT().
+ If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT().
+ If Length > 0 and SecondString is NULL, then ASSERT().
+ If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
+ PcdMaximumUnicodeStringLength, then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
+ then ASSERT().
+ If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than
+ PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
+ then ASSERT().
+
+ @param FirstString A pointer to a Null-terminated Unicode string.
+ @param SecondString A pointer to a Null-terminated Unicode string.
+ @param Length The maximum number of Unicode characters to compare.
+
+ @retval 0 FirstString is identical to SecondString.
+ @return others FirstString is not identical to SecondString.
+
+**/
+INTN
+StrnCmp (
+ CONST CHAR16 *FirstString,
+ CONST CHAR16 *SecondString,
+ UINTN Length
+ )
+{
+ if (Length == 0) {
+ return 0;
+ }
+
+ //
+ // ASSERT both strings are less long than PcdMaximumUnicodeStringLength.
+ // Length tests are performed inside StrLen().
+ //
+ ASSERT (StrSize (FirstString) != 0);
+ ASSERT (StrSize (SecondString) != 0);
+
+ while ((*FirstString != L'\0') &&
+ (*SecondString != L'\0') &&
+ (*FirstString == *SecondString) &&
+ (Length > 1)) {
+ FirstString++;
+ SecondString++;
+ Length--;
+ }
+
+ return *FirstString - *SecondString;
+}
+
+VOID *
+AllocateCopyPool (
+ UINTN AllocationSize,
+ CONST VOID *Buffer
+ )
+{
+ return InternalAllocateCopyPool (AllocationSize, Buffer);
+}
+
+INTN
+StrCmp (
+ CONST CHAR16 *FirstString,
+ CONST CHAR16 *SecondString
+ )
+{
+ //
+ // ASSERT both strings are less long than PcdMaximumUnicodeStringLength
+ //
+ ASSERT (StrSize (FirstString) != 0);
+ ASSERT (StrSize (SecondString) != 0);
+
+ while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
+ FirstString++;
+ SecondString++;
+ }
+ return *FirstString - *SecondString;
+}
+
+UINT64
+SwapBytes64 (
+ UINT64 Value
+ )
+{
+ return InternalMathSwapBytes64 (Value);
+}
+
+UINT64
+InternalMathSwapBytes64 (
+ UINT64 Operand
+ )
+{
+ UINT64 LowerBytes;
+ UINT64 HigherBytes;
+
+ LowerBytes = (UINT64) SwapBytes32 ((UINT32) Operand);
+ HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32));
+
+ return (LowerBytes << 32 | HigherBytes);
+}
+
+RETURN_STATUS
+StrToIpv4Address (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer,
+ EFI_IPv4_ADDRESS *Address,
+ UINT8 *PrefixLength
+ )
+{
+ RETURN_STATUS Status;
+ UINTN AddressIndex;
+ UINT64 Uint64;
+ EFI_IPv4_ADDRESS LocalAddress;
+ UINT8 LocalPrefixLength;
+ CHAR16 *Pointer;
+
+ LocalPrefixLength = MAX_UINT8;
+ LocalAddress.Addr[0] = 0;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. None of String or Guid shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
+
+ for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
+ if (!InternalIsDecimalDigitCharacter (*Pointer)) {
+ //
+ // D or P contains invalid characters.
+ //
+ break;
+ }
+
+ //
+ // Get D or P.
+ //
+ Status = StrDecimalToUint64S ((CONST CHAR16 *) Pointer, &Pointer, &Uint64);
+ if (RETURN_ERROR (Status)) {
+ return RETURN_UNSUPPORTED;
+ }
+ if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+ //
+ // It's P.
+ //
+ if (Uint64 > 32) {
+ return RETURN_UNSUPPORTED;
+ }
+ LocalPrefixLength = (UINT8) Uint64;
+ } else {
+ //
+ // It's D.
+ //
+ if (Uint64 > MAX_UINT8) {
+ return RETURN_UNSUPPORTED;
+ }
+ LocalAddress.Addr[AddressIndex] = (UINT8) Uint64;
+ AddressIndex++;
+ }
+
+ //
+ // Check the '.' or '/', depending on the AddressIndex.
+ //
+ if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+ if (*Pointer == L'/') {
+ //
+ // '/P' is in the String.
+ // Skip "/" and get P in next loop.
+ //
+ Pointer++;
+ } else {
+ //
+ // '/P' is not in the String.
+ //
+ break;
+ }
+ } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
+ if (*Pointer == L'.') {
+ //
+ // D should be followed by '.'
+ //
+ Pointer++;
+ } else {
+ return RETURN_UNSUPPORTED;
+ }
+ }
+ }
+
+ if (AddressIndex < ARRAY_SIZE (Address->Addr)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ memcpy (Address, &LocalAddress, sizeof (*Address));
+ if (PrefixLength != NULL) {
+ *PrefixLength = LocalPrefixLength;
+ }
+ if (EndPointer != NULL) {
+ *EndPointer = Pointer;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+StrToIpv6Address (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer,
+ EFI_IPv6_ADDRESS *Address,
+ UINT8 *PrefixLength
+ )
+{
+ RETURN_STATUS Status;
+ UINTN AddressIndex;
+ UINT64 Uint64;
+ EFI_IPv6_ADDRESS LocalAddress;
+ UINT8 LocalPrefixLength;
+ CONST CHAR16 *Pointer;
+ CHAR16 *End;
+ UINTN CompressStart;
+ BOOLEAN ExpectPrefix;
+
+ LocalPrefixLength = MAX_UINT8;
+ CompressStart = ARRAY_SIZE (Address->Addr);
+ ExpectPrefix = FALSE;
+
+ ASSERT (((UINTN) String & BIT0) == 0);
+
+ //
+ // 1. None of String or Guid shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER);
+
+ for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) {
+ if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
+ if (*Pointer != L':') {
+ //
+ // ":" or "/" should be followed by digit characters.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+
+ //
+ // Meet second ":" after previous ":" or "/"
+ // or meet first ":" in the beginning of String.
+ //
+ if (ExpectPrefix) {
+ //
+ // ":" shall not be after "/"
+ //
+ return RETURN_UNSUPPORTED;
+ }
+
+ if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) {
+ //
+ // "::" can only appear once.
+ // "::" can only appear when address is not full length.
+ //
+ return RETURN_UNSUPPORTED;
+ } else {
+ //
+ // Remember the start of zero compressing.
+ //
+ CompressStart = AddressIndex;
+ Pointer++;
+
+ if (CompressStart == 0) {
+ if (*Pointer != L':') {
+ //
+ // Single ":" shall not be in the beginning of String.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ Pointer++;
+ }
+ }
+ }
+
+ if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) {
+ if (*Pointer == L'/') {
+ //
+ // Might be optional "/P" after "::".
+ //
+ if (CompressStart != AddressIndex) {
+ return RETURN_UNSUPPORTED;
+ }
+ } else {
+ break;
+ }
+ } else {
+ if (!ExpectPrefix) {
+ //
+ // Get X.
+ //
+ Status = StrHexToUint64S (Pointer, &End, &Uint64);
+ if (RETURN_ERROR (Status) || End - Pointer > 4) {
+ //
+ // Number of hexadecimal digit characters is no more than 4.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ Pointer = End;
+ //
+ // Uint64 won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4.
+ //
+ ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr));
+ LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uint64 >> 8);
+ LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uint64;
+ AddressIndex += 2;
+ } else {
+ //
+ // Get P, then exit the loop.
+ //
+ Status = StrDecimalToUint64S (Pointer, &End, &Uint64);
+ if (RETURN_ERROR (Status) || End == Pointer || Uint64 > 128) {
+ //
+ // Prefix length should not exceed 128.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ LocalPrefixLength = (UINT8) Uint64;
+ Pointer = End;
+ break;
+ }
+ }
+
+ //
+ // Skip ':' or "/"
+ //
+ if (*Pointer == L'/') {
+ ExpectPrefix = TRUE;
+ } else if (*Pointer == L':') {
+ if (AddressIndex == ARRAY_SIZE (Address->Addr)) {
+ //
+ // Meet additional ":" after all 8 16-bit address
+ //
+ break;
+ }
+ } else {
+ //
+ // Meet other character that is not "/" or ":" after all 8 16-bit address
+ //
+ break;
+ }
+ Pointer++;
+ }
+
+ if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) ||
+ (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr))
+ ) {
+ //
+ // Full length of address shall not have compressing zeros.
+ // Non-full length of address shall have compressing zeros.
+ //
+ return RETURN_UNSUPPORTED;
+ }
+ memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart);
+ if (AddressIndex > CompressStart) {
+ memset (&Address->Addr[CompressStart], 0, ARRAY_SIZE (Address->Addr) - AddressIndex);
+ memcpy (
+ &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex],
+ &LocalAddress.Addr[CompressStart],
+ AddressIndex - CompressStart
+ );
+ }
+
+ if (PrefixLength != NULL) {
+ *PrefixLength = LocalPrefixLength;
+ }
+ if (EndPointer != NULL) {
+ *EndPointer = (CHAR16 *) Pointer;
+ }
+
+ return RETURN_SUCCESS;
+}
+
+
+RETURN_STATUS
+UnicodeStrToAsciiStrS (
+ CONST CHAR16 *Source,
+ CHAR8 *Destination,
+ UINTN DestMax
+ )
+{
+ UINTN SourceLen;
+
+ ASSERT (((UINTN) Source & BIT0) == 0);
+
+ //
+ // 1. Neither Destination nor Source shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX.
+ //
+ if (ASCII_RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ //
+ // 3. DestMax shall not equal zero.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
+
+ //
+ // 4. DestMax shall be greater than StrnLenS (Source, DestMax).
+ //
+ SourceLen = StrnLenS (Source, DestMax);
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
+
+ //
+ // 5. Copying shall not take place between objects that overlap.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED);
+
+ //
+ // convert string
+ //
+ while (*Source != '\0') {
+ //
+ // If any Unicode characters in Source contain
+ // non-zero value in the upper 8 bits, then ASSERT().
+ //
+ ASSERT (*Source < 0x100);
+ *(Destination++) = (CHAR8) *(Source++);
+ }
+ *Destination = '\0';
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+StrCpyS (
+ CHAR16 *Destination,
+ UINTN DestMax,
+ CONST CHAR16 *Source
+ )
+{
+ UINTN SourceLen;
+
+ ASSERT (((UINTN) Destination & BIT0) == 0);
+ ASSERT (((UINTN) Source & BIT0) == 0);
+
+ //
+ // 1. Neither Destination nor Source shall be a null pointer.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER);
+ SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER);
+
+ //
+ // 2. DestMax shall not be greater than RSIZE_MAX.
+ //
+ if (RSIZE_MAX != 0) {
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER);
+ }
+
+ //
+ // 3. DestMax shall not equal zero.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER);
+
+ //
+ // 4. DestMax shall be greater than StrnLenS(Source, DestMax).
+ //
+ SourceLen = StrnLenS (Source, DestMax);
+ SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL);
+
+ //
+ // 5. Copying shall not take place between objects that overlap.
+ //
+ SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED);
+
+ //
+ // The StrCpyS function copies the string pointed to by Source (including the terminating
+ // null character) into the array pointed to by Destination.
+ //
+ while (*Source != 0) {
+ *(Destination++) = *(Source++);
+ }
+ *Destination = 0;
+
+ return RETURN_SUCCESS;
+}
+
+VOID *
+AllocateZeroPool (
+ UINTN AllocationSize
+ )
+{
+ VOID * Memory;
+ Memory = malloc(AllocationSize);
+ ASSERT (Memory != NULL);
+ if (Memory == NULL) {
+ fprintf(stderr, "Not memory for malloc\n");
+ }
+ memset(Memory, 0, AllocationSize);
+ return Memory;
+}
+
+VOID *
+AllocatePool (
+ UINTN AllocationSize
+ )
+{
+ return InternalAllocatePool (AllocationSize);
+}
+
+UINT16
+WriteUnaligned16 (
+ UINT16 *Buffer,
+ UINT16 Value
+ )
+{
+ ASSERT (Buffer != NULL);
+
+ return *Buffer = Value;
+}
+
+UINT16
+ReadUnaligned16 (
+ CONST UINT16 *Buffer
+ )
+{
+ ASSERT (Buffer != NULL);
+
+ return *Buffer;
+}
+/**
+ Return whether the integer string is a hex string.
+
+ @param Str The integer string
+
+ @retval TRUE Hex string
+ @retval FALSE Decimal string
+
+**/
+BOOLEAN
+IsHexStr (
+ CHAR16 *Str
+ )
+{
+ //
+ // skip preceding white space
+ //
+ while ((*Str != 0) && *Str == L' ') {
+ Str ++;
+ }
+ //
+ // skip preceding zeros
+ //
+ while ((*Str != 0) && *Str == L'0') {
+ Str ++;
+ }
+
+ return (BOOLEAN) (*Str == L'x' || *Str == L'X');
+}
+
+/**
+
+ Convert integer string to uint.
+
+ @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
+
+ @return A UINTN value represented by Str
+
+**/
+UINTN
+Strtoi (
+ CHAR16 *Str
+ )
+{
+ if (IsHexStr (Str)) {
+ return (UINTN)StrHexToUint64 (Str);
+ } else {
+ return (UINTN)StrDecimalToUint64 (Str);
+ }
+}
+
+/**
+
+ Convert integer string to 64 bit data.
+
+ @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal.
+ @param Data A pointer to the UINT64 value represented by Str
+
+**/
+VOID
+Strtoi64 (
+ CHAR16 *Str,
+ UINT64 *Data
+ )
+{
+ if (IsHexStr (Str)) {
+ *Data = StrHexToUint64 (Str);
+ } else {
+ *Data = StrDecimalToUint64 (Str);
+ }
+}
+
+/**
+ Converts a Unicode string to ASCII string.
+
+ @param Str The equivalent Unicode string
+ @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points
+ to the next ASCII string next to it
+
+**/
+VOID
+StrToAscii (
+ CHAR16 *Str,
+ CHAR8 **AsciiStr
+ )
+{
+ CHAR8 *Dest;
+
+ Dest = *AsciiStr;
+ while (!IS_NULL (*Str)) {
+ *(Dest++) = (CHAR8) *(Str++);
+ }
+ *Dest = 0;
+
+ //
+ // Return the string next to it
+ //
+ *AsciiStr = Dest + 1;
+}
+
+/**
+ Gets current sub-string from a string list, before return
+ the list header is moved to next sub-string. The sub-string is separated
+ by the specified character. For example, the separator is ',', the string
+ list is "2,0,3", it returns "2", the remain list move to "0,3"
+
+ @param List A string list separated by the specified separator
+ @param Separator The separator character
+
+ @return A pointer to the current sub-string
+
+**/
+CHAR16 *
+SplitStr (
+ CHAR16 **List,
+ CHAR16 Separator
+ )
+{
+ CHAR16 *Str;
+ CHAR16 *ReturnStr;
+
+ Str = *List;
+ ReturnStr = Str;
+
+ if (IS_NULL (*Str)) {
+ return ReturnStr;
+ }
+
+ //
+ // Find first occurrence of the separator
+ //
+ while (!IS_NULL (*Str)) {
+ if (*Str == Separator) {
+ break;
+ }
+ Str++;
+ }
+
+ if (*Str == Separator) {
+ //
+ // Find a sub-string, terminate it
+ //
+ *Str = L'\0';
+ Str++;
+ }
+
+ //
+ // Move to next sub-string
+ //
+ *List = Str;
+ return ReturnStr;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h
new file mode 100644
index 00000000..2fa4b576
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h
@@ -0,0 +1,469 @@
+/** @file
+Common library assistance routines.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_COMMON_LIB_H
+#define _EFI_COMMON_LIB_H
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/BuildVersion.h>
+#include <assert.h>
+#ifndef _WIN32
+#include <limits.h>
+#endif
+
+#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination
+
+#ifdef PATH_MAX
+#define MAX_LONG_FILE_PATH PATH_MAX
+#else
+#define MAX_LONG_FILE_PATH 500
+#endif
+
+#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL)
+#define MAX_UINT32 ((UINT32)0xFFFFFFFF)
+#define MAX_UINT16 ((UINT16)0xFFFF)
+#define MAX_UINT8 ((UINT8)0xFF)
+#define ARRAY_SIZE(Array) (sizeof (Array) / sizeof ((Array)[0]))
+#define ASCII_RSIZE_MAX 1000000
+#undef RSIZE_MAX
+#define RSIZE_MAX 1000000
+
+#define IS_COMMA(a) ((a) == L',')
+#define IS_HYPHEN(a) ((a) == L'-')
+#define IS_DOT(a) ((a) == L'.')
+#define IS_LEFT_PARENTH(a) ((a) == L'(')
+#define IS_RIGHT_PARENTH(a) ((a) == L')')
+#define IS_SLASH(a) ((a) == L'/')
+#define IS_NULL(a) ((a) == L'\0')
+
+#define ASSERT(x) assert(x)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// 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
+ )
+;
+
+CHAR8 *
+LongFilePath (
+ IN CHAR8 *FileName
+);
+
+UINTN
+StrLen (
+ CONST CHAR16 *String
+ );
+
+VOID *
+AllocateCopyPool (
+ UINTN AllocationSize,
+ CONST VOID *Buffer
+ );
+
+INTN
+StrnCmp (
+ CONST CHAR16 *FirstString,
+ CONST CHAR16 *SecondString,
+ UINTN Length
+ );
+
+RETURN_STATUS
+StrToGuid (
+ CONST CHAR16 *String,
+ EFI_GUID *Guid
+ );
+
+RETURN_STATUS
+StrHexToBytes (
+ CONST CHAR16 *String,
+ UINTN Length,
+ UINT8 *Buffer,
+ UINTN MaxBufferSize
+ );
+
+UINTN
+InternalHexCharToUintn (
+ CHAR16 Char
+ );
+
+VOID *
+InternalAllocateCopyPool (
+ UINTN AllocationSize,
+ CONST VOID *Buffer
+ );
+
+BOOLEAN
+InternalIsDecimalDigitCharacter (
+ CHAR16 Char
+ );
+
+UINT32
+SwapBytes32 (
+ UINT32 Value
+ );
+
+UINT16
+SwapBytes16 (
+ UINT16 Value
+ );
+
+EFI_GUID *
+CopyGuid (
+ EFI_GUID *DestinationGuid,
+ CONST EFI_GUID *SourceGuid
+ );
+
+UINT64
+WriteUnaligned64 (
+ UINT64 *Buffer,
+ UINT64 Value
+ );
+
+UINT64
+ReadUnaligned64 (
+ CONST UINT64 *Buffer
+ );
+
+UINTN
+StrSize (
+ CONST CHAR16 *String
+ );
+
+UINT64
+StrHexToUint64 (
+ CONST CHAR16 *String
+ );
+
+UINT64
+StrDecimalToUint64 (
+ CONST CHAR16 *String
+ );
+
+RETURN_STATUS
+StrHexToUint64S (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer,
+ UINT64 *Data
+ );
+
+RETURN_STATUS
+StrDecimalToUint64S (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer, OPTIONAL
+ UINT64 *Data
+ );
+
+VOID *
+ReallocatePool (
+ UINTN OldSize,
+ UINTN NewSize,
+ VOID *OldBuffer OPTIONAL
+ );
+
+VOID *
+InternalReallocatePool (
+ UINTN OldSize,
+ UINTN NewSize,
+ VOID *OldBuffer OPTIONAL
+ );
+
+VOID *
+InternalAllocateZeroPool (
+ UINTN AllocationSize
+ ) ;
+
+VOID *
+InternalAllocatePool (
+ UINTN AllocationSize
+ );
+
+UINTN
+StrnLenS (
+ CONST CHAR16 *String,
+ UINTN MaxSize
+ );
+
+CHAR16
+InternalCharToUpper (
+ CHAR16 Char
+ );
+
+INTN
+StrCmp (
+ CONST CHAR16 *FirstString,
+ CONST CHAR16 *SecondString
+ );
+
+UINT64
+SwapBytes64 (
+ UINT64 Value
+ );
+
+UINT64
+InternalMathSwapBytes64 (
+ UINT64 Operand
+ );
+
+RETURN_STATUS
+StrToIpv4Address (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer,
+ EFI_IPv4_ADDRESS *Address,
+ UINT8 *PrefixLength
+ );
+
+RETURN_STATUS
+StrToIpv6Address (
+ CONST CHAR16 *String,
+ CHAR16 **EndPointer,
+ EFI_IPv6_ADDRESS *Address,
+ UINT8 *PrefixLength
+ );
+
+RETURN_STATUS
+StrCpyS (
+ CHAR16 *Destination,
+ UINTN DestMax,
+ CONST CHAR16 *Source
+ );
+
+RETURN_STATUS
+UnicodeStrToAsciiStrS (
+ CONST CHAR16 *Source,
+ CHAR8 *Destination,
+ UINTN DestMax
+ );
+VOID *
+AllocatePool (
+ UINTN AllocationSize
+ );
+
+UINT16
+WriteUnaligned16 (
+ UINT16 *Buffer,
+ UINT16 Value
+ );
+
+UINT16
+ReadUnaligned16 (
+ CONST UINT16 *Buffer
+ );
+
+VOID *
+AllocateZeroPool (
+ UINTN AllocationSize
+ );
+
+BOOLEAN
+InternalIsHexaDecimalDigitCharacter (
+ CHAR16 Char
+ );
+
+BOOLEAN
+InternalSafeStringIsOverlap (
+ IN VOID *Base1,
+ IN UINTN Size1,
+ IN VOID *Base2,
+ IN UINTN Size2
+ );
+
+BOOLEAN
+InternalSafeStringNoStrOverlap (
+ IN CHAR16 *Str1,
+ IN UINTN Size1,
+ IN CHAR16 *Str2,
+ IN UINTN Size2
+ );
+
+BOOLEAN
+IsHexStr (
+ CHAR16 *Str
+ );
+
+UINTN
+Strtoi (
+ CHAR16 *Str
+ );
+
+VOID
+Strtoi64 (
+ CHAR16 *Str,
+ UINT64 *Data
+ );
+
+VOID
+StrToAscii (
+ CHAR16 *Str,
+ CHAR8 **AsciiStr
+ );
+
+CHAR16 *
+SplitStr (
+ CHAR16 **List,
+ CHAR16 Separator
+ );
+
+/*++
+
+Routine Description:
+ Convert FileName to the long file path, which can support larger than 260 length.
+
+Arguments:
+ FileName - FileName.
+
+Returns:
+ LongFilePath A pointer to the converted long file path.
+
+--*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Compress.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Compress.h
new file mode 100644
index 00000000..bacc8183
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Compress.h
@@ -0,0 +1,82 @@
+/** @file
+Header file for compression routine.
+Providing both EFI and Tiano Compress algorithms.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.c
new file mode 100644
index 00000000..df823283
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.c
@@ -0,0 +1,313 @@
+/** @file
+CalculateCrc32 routine.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 containing 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.h
new file mode 100644
index 00000000..a8c855c4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.h
@@ -0,0 +1,41 @@
+/** @file
+Header file for CalculateCrc32 routine
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 containing 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.c
new file mode 100644
index 00000000..e494437a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.c
@@ -0,0 +1,1014 @@
+/** @file
+Decompressor. Algorithm Ported from OPSD code (Decomp.asm) for Efi and Tiano
+compress algorithm.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+--*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.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) (((UINT64)Sd->mBitBuf) << NumOfBits);
+
+ while (NumOfBits > Sd->mBitCount) {
+
+ Sd->mBitBuf |= (UINT32) (((UINT64)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;
+ UINT16 MaxTableLength;
+
+ for (Index = 1; Index <= 16; Index++) {
+ Count[Index] = 0;
+ }
+
+ for (Index = 0; Index < NumOfChar; Index++) {
+ if (BitLen[Index] > 16) {
+ return (UINT16) BAD_TABLE;
+ }
+ 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));
+ MaxTableLength = (UINT16) (1U << TableBits);
+
+ for (Char = 0; Char < NumOfChar; Char++) {
+
+ Len = BitLen[Char];
+ if (Len == 0 || Len >= 17) {
+ continue;
+ }
+
+ NextCode = (UINT16) (Start[Len] + Weight[Len]);
+
+ if (Len <= TableBits) {
+
+ if (Start[Len] >= NextCode || NextCode > MaxTableLength){
+ return (UINT16) BAD_TABLE;
+ }
+
+ 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;
+
+ assert (nn <= NPT);
+
+ 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 && Index < NPT) {
+
+ 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 && Index < NPT) {
+ Sd->mPTLen[Index++] = 0;
+ CharC--;
+ }
+ }
+ }
+
+ while (Index < nn && Index < NPT) {
+ 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) {
+ if (Sd->mOutBuf >= Sd->mOrigSize) {
+ return ;
+ }
+ if (DataIdx >= Sd->mOrigSize) {
+ Sd->mBadTableFlag = (UINT16) BAD_TABLE;
+ return ;
+ }
+ Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++];
+
+ BytesRemain--;
+ }
+ //
+ // Once mOutBuf is fully filled, directly return
+ //
+ if (Sd->mOutBuf >= Sd->mOrigSize) {
+ return ;
+ }
+ }
+ }
+
+ 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 successfully retrieved.
+ EFI_INVALID_PARAMETER - The source data is corrupted
+
+--*/
+{
+ UINT8 *Src;
+ UINT32 CompSize;
+
+ *ScratchSize = sizeof (SCRATCH_DATA);
+
+ Src = Source;
+ if (SrcSize < 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24);
+ *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24);
+
+ if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ 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 successful
+ 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 || (CompSize + 8) < 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 successfully 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 successfully 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 successful
+ 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 successful
+ 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;
+
+ Scratch = NULL;
+ 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);
+ if (Scratch == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Destination = (VOID *)malloc(*DstSize);
+ if (*Destination == NULL) {
+ free (Scratch);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = EfiDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize);
+ }
+ break;
+ case 2:
+ Status = TianoGetInfo(Source, SrcSize, DstSize, &ScratchSize);
+ if (Status == EFI_SUCCESS) {
+ Scratch = (VOID *)malloc(ScratchSize);
+ if (Scratch == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *Destination = (VOID *)malloc(*DstSize);
+ if (*Destination == NULL) {
+ free (Scratch);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = TianoDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize);
+ }
+ break;
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ if (Scratch != NULL) {
+ free (Scratch);
+ }
+
+ return Status;
+}
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.h
new file mode 100644
index 00000000..2df9a14b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.h
@@ -0,0 +1,159 @@
+/** @file
+Header file for compression routine
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 successfully 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 successful
+ 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 successfully 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 successful
+ 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiCompress.c
new file mode 100644
index 00000000..4cbd49b5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiCompress.c
@@ -0,0 +1,1591 @@
+/** @file
+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.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+
+Arguments: (VOID)
+
+Returns:
+
+ EFI_SUCCESS - Memory is allocated successfully
+ EFI_OUT_OF_RESOURCES - Allocation fails
+
+--*/
+{
+ UINT32 i;
+
+ mText = malloc (WNDSIZ * 2 + MAXMATCH);
+ if (mText == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ 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));
+ if (mLevel == NULL || mChildCount == NULL || mPosition == NULL ||
+ mParent == NULL || mPrev == NULL || mNext == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ 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. Traverse 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
+
+Arguments:
+
+ 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.c
new file mode 100644
index 00000000..69b9f899
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.c
@@ -0,0 +1,902 @@
+/** @file
+EFI tools utility functions to display warning, error, and informational messages
+
+Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+--*/
+
+#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 utility's
+// name and other settings.
+//
+STATIC STATUS mStatus = STATUS_SUCCESS;
+STATIC CHAR8 mUtilityName[50] = { 0 };
+STATIC UINT64 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
+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
+ utility 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);
+}
+
+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);
+}
+
+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,
+ UINT64 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);
+}
+
+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 precede 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);
+ if (NewTime != NULL) {
+ 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) {
+ strcpy (Line, ": ");
+ strncat (Line, Cptr, MAX_LINE_LEN - strlen (Line) - 1);
+ if (LineNumber != 0) {
+ sprintf (Line2, "(%u)", (unsigned) LineNumber);
+ strncat (Line, Line2, MAX_LINE_LEN - strlen (Line) - 1);
+ }
+ }
+ } else {
+ //
+ // Error and Warning Information.
+ //
+ if (Cptr != NULL) {
+ if (mUtilityName[0] != '\0') {
+ fprintf (stdout, "%s...\n", mUtilityName);
+ }
+ strncpy (Line, Cptr, MAX_LINE_LEN - 1);
+ Line[MAX_LINE_LEN - 1] = 0;
+ if (LineNumber != 0) {
+ sprintf (Line2, "(%u)", (unsigned) LineNumber);
+ strncat (Line, Line2, MAX_LINE_LEN - strlen (Line) - 1);
+ }
+ } else {
+ if (mUtilityName[0] != '\0') {
+ strncpy (Line, mUtilityName, MAX_LINE_LEN - 1);
+ Line[MAX_LINE_LEN - 1] = 0;
+ }
+ }
+
+ if (strcmp (Type, "ERROR") == 0) {
+ //
+ // Set status accordingly for ERROR information.
+ //
+ if (mStatus < STATUS_ERROR) {
+ mStatus = STATUS_ERROR;
+ }
+ }
+ }
+
+ //
+ // Have to print an error code or Visual Studio won't find the
+ // message for you. It has to be decimal digits too.
+ //
+ strncat (Line, ": ", MAX_LINE_LEN - strlen (Line) - 1);
+ strncat (Line, Type, MAX_LINE_LEN - strlen (Line) - 1);
+ if (MessageCode != 0) {
+ sprintf (Line2, " %04u", (unsigned) MessageCode);
+ strncat (Line, Line2, MAX_LINE_LEN - strlen (Line) - 1);
+ }
+ 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 messages.
+
+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;
+ } 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 (
+ UINT64 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";
+ int 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.h
new file mode 100644
index 00000000..406cc70e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.h
@@ -0,0 +1,164 @@
+/** @file
+Defines and prototypes for common EFI utility error and debug messages.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+PrintMessage (
+ CHAR8 *Type,
+ CHAR8 *FileName,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ CHAR8 *Text,
+ CHAR8 *MsgFmt,
+ va_list List
+ );
+
+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,
+ UINT64 MsgLevel,
+ CHAR8 *OffendingText,
+ CHAR8 *MsgFmt,
+ ...
+ )
+;
+
+VOID
+VerboseMsg (
+ CHAR8 *MsgFmt,
+ ...
+ );
+
+VOID
+NormalMsg (
+ CHAR8 *MsgFmt,
+ ...
+ );
+
+VOID
+KeyMsg (
+ CHAR8 *MsgFmt,
+ ...
+ );
+
+VOID
+SetPrintLevel (
+ UINT64 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c
new file mode 100644
index 00000000..fcf62e70
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c
@@ -0,0 +1,1775 @@
+/** @file
+EFI Firmware Volume routines which work on a Fv image in buffers.
+
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+UINT32
+FvBufGetSecHdrLen(
+ IN EFI_COMMON_SECTION_HEADER *SectionHeader
+ )
+{
+ if (SectionHeader == NULL) {
+ return 0;
+ }
+ if (FvBufExpand3ByteSize(SectionHeader->Size) == 0xffffff) {
+ return sizeof(EFI_COMMON_SECTION_HEADER2);
+ }
+ return sizeof(EFI_COMMON_SECTION_HEADER);
+}
+
+STATIC
+UINT32
+FvBufGetSecFileLen (
+ IN EFI_COMMON_SECTION_HEADER *SectionHeader
+ )
+{
+ UINT32 Length;
+ if (SectionHeader == NULL) {
+ return 0;
+ }
+ Length = FvBufExpand3ByteSize(SectionHeader->Size);
+ if (Length == 0xffffff) {
+ Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
+ }
+ return Length;
+}
+
+//
+// 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 = FvBufGetFfsFileSize (FileToRm);
+
+ 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)) {
+ CommonLibBinderFree (TempFv);
+ 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 = FvBufGetFfsFileSize (File);
+
+ //
+ // 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,
+ FvBufGetFfsHeaderSize (File)
+ );
+
+ if (File->Attributes & FFS_ATTRIB_CHECKSUM) {
+ File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 (
+ (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)),
+ FileSize - FvBufGetFfsHeaderSize (File)
+ );
+ } 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);
+ if (*DestinationFv == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ 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_2 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 = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
+
+ 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 = FvBufGetFfsFileSize (fhdr);
+ 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 = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
+
+ 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 = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
+ } 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
+FvBufGetFfsFileSize (
+ IN EFI_FFS_FILE_HEADER *Ffs
+ )
+/*++
+
+Routine Description:
+
+ Get the FFS file size.
+
+Arguments:
+
+ Ffs - Pointer to FFS header
+
+Returns:
+
+ UINT32
+
+--*/
+{
+ if (Ffs == NULL) {
+ return 0;
+ }
+ if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {
+ return (UINT32) ((EFI_FFS_FILE_HEADER2 *)Ffs)->ExtendedSize;
+ }
+ return FvBufExpand3ByteSize(Ffs->Size);
+}
+
+UINT32
+FvBufGetFfsHeaderSize (
+ IN EFI_FFS_FILE_HEADER *Ffs
+ )
+/*++
+
+Routine Description:
+
+ Get the FFS header size.
+
+Arguments:
+
+ Ffs - Pointer to FFS header
+
+Returns:
+
+ UINT32
+
+--*/
+{
+ if (Ffs == NULL) {
+ return 0;
+ }
+ if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {
+ return sizeof(EFI_FFS_FILE_HEADER2);
+ }
+ return sizeof(EFI_FFS_FILE_HEADER);
+}
+
+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 its 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_2 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 = FvBufGetFfsFileSize (fhdr);
+
+ 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*)((UINT8 *)File + FvBufGetFfsHeaderSize (File));
+ *RawDataSize = FvBufGetFfsFileSize (File) - FvBufGetFfsHeaderSize (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*)((UINT8 *)Section + FvBufGetSecHdrLen(Section));
+ *RawDataSize =
+ FvBufGetSecFileLen (Section) - FvBufGetSecHdrLen(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;
+ UINT32 FfsHdrLen;
+ UINT32 SecHdrLen;
+
+ //
+ // The section size is the DataSize + the size of the section header
+ //
+ NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize;
+ SecHdrLen = sizeof (EFI_RAW_SECTION);
+ if (NewSectionSize >= MAX_SECTION_SIZE) {
+ NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION2) + (UINT32)RawDataSize;
+ SecHdrLen = sizeof (EFI_RAW_SECTION2);
+ }
+
+ //
+ // The file size is the size of the file header + the section size
+ //
+ NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize;
+ FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER);
+ if (NewFileSize >= MAX_FFS_SIZE) {
+ NewFileSize = sizeof (EFI_FFS_FILE_HEADER2) + NewSectionSize;
+ FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER2);
+ }
+
+ //
+ // 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*)((UINT8*)NewFile + FfsHdrLen);
+ if (NewSectionSize >= MAX_SECTION_SIZE) {
+ FvBufCompact3ByteSize (NewSection->Size, 0xffffff);
+ ((EFI_RAW_SECTION2 *)NewSection)->ExtendedSize = NewSectionSize;
+ } else {
+ FvBufCompact3ByteSize (NewSection->Size, NewSectionSize);
+ }
+ NewSection->Type = EFI_SECTION_RAW;
+
+ //
+ // Copy the actual file data into the buffer
+ //
+ CommonLibBinderCopyMem ((UINT8 *)NewSection + SecHdrLen, RawData, RawDataSize);
+
+ //
+ // Initialize the FFS file header
+ //
+ CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID));
+ NewFile->Attributes = 0;
+ if (NewFileSize >= MAX_FFS_SIZE) {
+ FvBufCompact3ByteSize (NewFile->Size, 0x0);
+ ((EFI_FFS_FILE_HEADER2 *)NewFile)->ExtendedSize = NewFileSize;
+ NewFile->Attributes |= FFS_ATTRIB_LARGE_FILE;
+ } else {
+ FvBufCompact3ByteSize (NewFile->Size, NewFileSize);
+ }
+ NewFile->Type = EFI_FV_FILETYPE_FREEFORM;
+ NewFile->IntegrityCheck.Checksum.Header =
+ FvBufCalculateChecksum8 ((UINT8*)NewFile, FfsHdrLen);
+ 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 its 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 = FvBufGetSecFileLen (sectionHdr);
+
+ 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 + FvBufGetFfsHeaderSize(FfsFile));
+ TotalSectionsSize =
+ FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -
+ FvBufGetFfsHeaderSize(FfsFile);
+ 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 + FvBufGetFfsHeaderSize(FfsFile));
+ TotalSectionsSize =
+ FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -
+ FvBufGetFfsHeaderSize(FfsFile);
+ 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 + FvBufGetFfsFileSize (FileIt));
+ }
+
+ //
+ // 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h
new file mode 100644
index 00000000..6ba9e80e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h
@@ -0,0 +1,163 @@
+/** @file
+EFI Firmware Volume routines which work on a Fv image in buffers.
+
+Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+ );
+
+UINT32
+FvBufGetFfsFileSize (
+ IN EFI_FFS_FILE_HEADER *Ffs
+ );
+
+UINT32
+FvBufGetFfsHeaderSize (
+ IN EFI_FFS_FILE_HEADER *Ffs
+ );
+
+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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.c
new file mode 100644
index 00000000..d9f45930
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.c
@@ -0,0 +1,927 @@
+/** @file
+These functions assist in parsing and manipulating a Firmware Volume.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// 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;
+ *FvLength = mFvLength;
+ 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 + GetFfsFileLength(CurrentFile) > (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 + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength)
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Get next file, compensate for 8 byte alignment if necessary.
+ //
+ *NextFile = (EFI_FFS_FILE_HEADER *) ((((UINTN) CurrentFile - (UINTN) mFvHeader + GetFfsFileLength(CurrentFile) + 0x07) & (~(UINTN) 7)) + (UINT8 *) mFvHeader);
+
+ //
+ // Verify file is in this FV.
+ //
+ if (((UINTN) *NextFile + GetFfsHeaderLength(*NextFile) >= (UINTN) mFvHeader + mFvLength) ||
+ ((UINTN) *NextFile + GetFfsFileLength (*NextFile) > (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 Instance 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;
+ UINT16 GuidSecAttr;
+ UINT16 GuidDataOffset;
+
+ GuidSecAttr = 0;
+ GuidDataOffset = 0;
+ 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 (CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED) {
+ if (GetLength(CurrentSection.CommonHeader->Size) == 0xffffff) {
+ GuidSecAttr = CurrentSection.GuidDefinedSection2->Attributes;
+ GuidDataOffset = CurrentSection.GuidDefinedSection2->DataOffset;
+ } else {
+ GuidSecAttr = CurrentSection.GuidDefinedSection->Attributes;
+ GuidDataOffset = CurrentSection.GuidDefinedSection->DataOffset;
+ }
+ }
+ if (SectionType != EFI_SECTION_GUID_DEFINED &&
+ CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED &&
+ !(GuidSecAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {
+ InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *)
+ ((UINTN) CurrentSection.CommonHeader + GuidDataOffset);
+ SectionSize = GetSectionFileLength(CurrentSection.CommonHeader);
+ 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) + GetSectionFileLength(CurrentSection.CommonHeader) + 0x03) & (~(UINTN) 3));
+ }
+
+ 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 Instance 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 + GetFfsHeaderLength(File));
+
+ //
+ // Depth-first manner to find section file.
+ //
+ Status = SearchSectionByType (
+ CurrentSection,
+ (UINT8 *) ((UINTN) File + GetFfsFileLength (File)),
+ 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_HEADER2 BlankHeader;
+ UINT8 Checksum;
+ UINT32 FileLength;
+ UINT8 SavedChecksum;
+ UINT8 SavedState;
+ UINT8 FileGuidString[80];
+ UINT32 FfsHeaderSize;
+
+ //
+ // 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;
+ }
+
+ FfsHeaderSize = GetFfsHeaderLength(FfsHeader);
+ //
+ // Check if we have free space
+ //
+ if (ErasePolarity) {
+ memset (&BlankHeader, -1, FfsHeaderSize);
+ } else {
+ memset (&BlankHeader, 0, FfsHeaderSize);
+ }
+
+ if (memcmp (&BlankHeader, FfsHeader, FfsHeaderSize) == 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, FfsHeaderSize);
+ 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 = GetFfsFileLength (FfsHeader);
+ Checksum = CalculateSum8 ((UINT8 *) ((UINT8 *)FfsHeader + FfsHeaderSize), FileLength - FfsHeaderSize);
+ Checksum = Checksum + FfsHeader->IntegrityCheck.Checksum.File;
+ 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 0xAA 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
+GetFfsHeaderLength(
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+{
+ if (FfsHeader == NULL) {
+ return 0;
+ }
+ if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {
+ return sizeof(EFI_FFS_FILE_HEADER2);
+ }
+ return sizeof(EFI_FFS_FILE_HEADER);
+}
+
+UINT32
+GetSectionHeaderLength(
+ IN EFI_COMMON_SECTION_HEADER *SectionHeader
+ )
+{
+ if (SectionHeader == NULL) {
+ return 0;
+ }
+ if (GetLength(SectionHeader->Size) == 0xffffff) {
+ return sizeof(EFI_COMMON_SECTION_HEADER2);
+ }
+ return sizeof(EFI_COMMON_SECTION_HEADER);
+}
+
+UINT32
+GetFfsFileLength (
+ EFI_FFS_FILE_HEADER *FfsHeader
+ )
+/*++
+
+Routine Description:
+
+ Get FFS file length including FFS header.
+
+Arguments:
+
+ FfsHeader Pointer to EFI_FFS_FILE_HEADER.
+
+Returns:
+
+ UINT32 Length of FFS file header.
+
+--*/
+{
+ if (FfsHeader == NULL) {
+ return 0;
+ }
+ if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {
+ return (UINT32) ((EFI_FFS_FILE_HEADER2 *)FfsHeader)->ExtendedSize;
+ } else {
+ return GetLength(FfsHeader->Size);
+ }
+}
+
+UINT32
+GetSectionFileLength (
+ EFI_COMMON_SECTION_HEADER *SectionHeader
+ )
+{
+ UINT32 Length;
+ if (SectionHeader == NULL) {
+ return 0;
+ }
+ Length = GetLength(SectionHeader->Size);
+ if (Length == 0xffffff) {
+ Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
+ }
+ return Length;
+}
+
+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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.h
new file mode 100644
index 00000000..0128779e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.h
@@ -0,0 +1,189 @@
+/** @file
+These functions assist in parsing and manipulating a Firmware Volume.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+ )
+;
+
+UINT32
+GetFfsFileLength (
+ EFI_FFS_FILE_HEADER *FfsHeader
+ )
+;
+
+UINT32
+GetSectionFileLength (
+ EFI_COMMON_SECTION_HEADER *SectionHeader
+ )
+;
+
+UINT32
+GetFfsHeaderLength(
+ IN EFI_FFS_FILE_HEADER *FfsHeader
+ )
+;
+
+UINT32
+GetSectionHeaderLength(
+ IN EFI_COMMON_SECTION_HEADER *SectionHeader
+ )
+;
+
+/*++
+
+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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/GNUmakefile
new file mode 100644
index 00000000..a2ff48f3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/GNUmakefile
@@ -0,0 +1,33 @@
+## @file
+# GNU/Linux makefile for 'Common' module build.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile
new file mode 100644
index 00000000..971025f6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile
@@ -0,0 +1,36 @@
+## @file
+# Windows makefile for 'Common' module build.
+#
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+!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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile.kmk
new file mode 100644
index 00000000..aab8f640
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile.kmk
@@ -0,0 +1,63 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-makefile for the EFI build tool common library.
+#
+
+#
+# Copyright (C) 2013-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# The contents of this file may alternatively be used under the terms
+# of the Common Development and Distribution License Version 1.0
+# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+# in the VirtualBox distribution, in which case the provisions of the
+# CDDL are applicable instead of those of the GPL.
+#
+# You may elect to license modified versions of this file under the
+# terms and conditions of either the GPL or the CDDL or both.
+#
+# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+#
+
+SUB_DEPTH = ../../../../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+LIBRARIES += EfiBldCommonLib
+EfiBldCommonLib_TEMPLATE = VBoxEfiBldLib
+EfiBldCommonLib_SOURCES = \
+ BasePeCoff.c \
+ BinderFuncs.c \
+ CommonLib.c \
+ Crc32.c \
+ Decompress.c \
+ EfiCompress.c \
+ EfiUtilityMsgs.c \
+ FirmwareVolumeBuffer.c \
+ FvLib.c \
+ MemoryFile.c \
+ MyAlloc.c \
+ OsPath.c \
+ ParseGuidedSectionTools.c \
+ ParseInf.c \
+ PeCoffLoaderEx.c \
+ SimpleFileParsing.c \
+ StringFuncs.c \
+ TianoCompress.c
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.c
new file mode 100644
index 00000000..68277e98
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.c
@@ -0,0 +1,251 @@
+/** @file
+This contains some useful functions for accessing files.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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) {
+ free (InputFileImage);
+ 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 + 1);
+ 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;
+ if (InputFile->CurrentFilePointer > InputFile->Eof) {
+ InputFile->CurrentFilePointer = InputFile->Eof;
+ }
+ 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.h
new file mode 100644
index 00000000..56a11d89
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.h
@@ -0,0 +1,105 @@
+/** @file
+Header file for helper functions useful for accessing files.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_MEMORY_FILE_H
+#define _EFI_MEMORY_FILE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Common/UefiBaseTypes.h>
+
+//
+// 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.c
new file mode 100644
index 00000000..dacb07ec
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.c
@@ -0,0 +1,548 @@
+/** @file
+File for memory allocation tracking functions.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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) {
+ printf (
+ "\nMyCheck(Final=%u, File=NULL, Line=%u)"
+ "Invalid parameter(s).\n",
+ Final,
+ (unsigned)Line
+ );
+
+ exit (1);
+ }
+
+ if (Line == 0) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)"
+ "Invalid parameter(s).\n",
+ Final,
+ File,
+ (unsigned)Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen ((CHAR8 *)File) == 0) {
+ printf (
+ "\nMyCheck(Final=%u, File=%s, Line=%u)"
+ "Invalid parameter.\n",
+ Final,
+ File,
+ (unsigned)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,
+ (unsigned)Line,
+ Tmp->File,
+ (unsigned) Tmp->Line,
+ (unsigned) Tmp->Size,
+ (unsigned) *(UINT32 *) (Tmp->Buffer),
+ (unsigned) *(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,
+ (unsigned)Line
+ );
+
+ for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
+ printf (
+ "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
+ Tmp->File,
+ (unsigned) Tmp->Line,
+ (unsigned) Tmp->Size,
+ (unsigned) *(UINT32 *) (Tmp->Buffer),
+ (unsigned) *(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 (File == NULL) {
+ printf (
+ "\nMyAlloc(Size=%u, File=NULL, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ (unsigned)Size,
+ (unsigned)Line
+ );
+
+ exit (1);
+ }
+
+ if (Size == 0 || Line == 0) {
+ printf (
+ "\nMyAlloc(Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ (unsigned)Size,
+ File,
+ (unsigned)Line
+ );
+
+ exit (1);
+ }
+
+ Len = strlen ((CHAR8 *)File);
+ if (Len == 0) {
+ printf (
+ "\nMyAlloc(Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ (unsigned)Size,
+ File,
+ (unsigned)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",
+ (unsigned)Size,
+ File,
+ (unsigned)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 (File == NULL) {
+ printf (
+ "\nMyRealloc(Ptr=%p, Size=%u, File=NULL, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Ptr,
+ (unsigned)Size,
+ (unsigned)Line
+ );
+
+ exit (1);
+ }
+
+ if (Size == 0 || Line == 0) {
+ printf (
+ "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Ptr,
+ (unsigned)Size,
+ File,
+ (unsigned)Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen ((CHAR8 *)File) == 0) {
+ printf (
+ "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ Ptr,
+ (unsigned)Size,
+ File,
+ (unsigned)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,
+ (unsigned)Size,
+ File,
+ (unsigned)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) {
+ printf (
+ "\nMyFree(Ptr=%p, File=NULL, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Ptr,
+ (unsigned)Line
+ );
+
+ exit (1);
+ }
+
+ if (Line == 0) {
+ printf (
+ "\nMyFree(Ptr=%p, File=%s, Line=%u)"
+ "\nInvalid parameter(s).\n",
+ Ptr,
+ File,
+ (unsigned)Line
+ );
+
+ exit (1);
+ }
+
+ if (strlen ((CHAR8 *)File) == 0) {
+ printf (
+ "\nMyFree(Ptr=%p, File=%s, Line=%u)"
+ "\nInvalid parameter.\n",
+ Ptr,
+ File,
+ (unsigned)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,
+ (unsigned)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,
+ (unsigned)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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.h
new file mode 100644
index 00000000..005f477b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.h
@@ -0,0 +1,209 @@
+/** @file
+Header file for memory allocation tracking functions.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.c
new file mode 100644
index 00000000..04e1557d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.c
@@ -0,0 +1,295 @@
+/** @file
+Functions useful to operate file directories by parsing file path.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "CommonLib.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 concatenate 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 (LongFilePath (InputFileName), "rb");
+ if (InputFile == NULL) {
+ return FALSE;
+ } else {
+ fclose (InputFile);
+ return TRUE;
+ }
+}
+
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.h
new file mode 100644
index 00000000..1b0640bd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.h
@@ -0,0 +1,133 @@
+/** @file
+Header file for helper functions useful to operate file directories by parsing
+file path.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 concatenate 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.c
new file mode 100644
index 00000000..f8b8f061
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.c
@@ -0,0 +1,205 @@
+/** @file
+Helper functions for parsing GuidedSectionTools.txt
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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;
+
+//
+// Function 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;
+ LastGuidTool = NULL;
+
+ while (TRUE) {
+ NextLine = ReadMemoryFileLine (InputFile);
+ if (NextLine == NULL) {
+ break;
+ }
+
+ Status = StripInfDscStringInPlace (NextLine);
+ if (EFI_ERROR (Status)) {
+ free (NextLine);
+ break;
+ }
+
+ if (NextLine[0] == '\0') {
+ free (NextLine);
+ 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;
+ }
+ }
+ }
+
+ if (Tool != NULL) {
+ FreeStringList (Tool);
+ }
+ free (NextLine);
+ }
+
+ 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.h
new file mode 100644
index 00000000..6b7bf1a7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.h
@@ -0,0 +1,120 @@
+/** @file
+Header file for helper functions for parsing GuidedSectionTools.txt
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.c
new file mode 100644
index 00000000..cc0b04ad
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.c
@@ -0,0 +1,695 @@
+/** @file
+This contains some useful functions for parsing INF files.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "EfiUtilityMsgs.h"
+#include "ParseInf.h"
+#include "CommonLib.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 MaxLength 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_LONG_FILE_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_LONG_FILE_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_LONG_FILE_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_LONG_FILE_PATH];
+ CHAR8 *CurrentToken;
+ CHAR8 *Delimiter;
+ BOOLEAN ParseError;
+ BOOLEAN ReadError;
+ UINTN Occurrence;
+
+ //
+ // 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
+ //
+ Occurrence = 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_LONG_FILE_PATH) == NULL) {
+ //
+ // Error reading from input file
+ //
+ ReadError = TRUE;
+ break;
+ }
+ //
+ // Get the first non-whitespace string
+ //
+ Delimiter = strchr (InputBuffer, '=');
+ if (Delimiter != NULL) {
+ *Delimiter = 0;
+ }
+
+ CurrentToken = strtok (InputBuffer, " \t\n");
+ if (CurrentToken == NULL || Delimiter == 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 == Occurrence) {
+ //
+ // Copy the contents following the =
+ //
+ CurrentToken = Delimiter + 1;
+ if (*CurrentToken == 0) {
+ //
+ // Nothing found, parsing error
+ //
+ ParseError = TRUE;
+ } else {
+ //
+ // Strip leading white space
+ //
+ while (*CurrentToken == ' ' || *CurrentToken == '\t') {
+ CurrentToken++;
+ }
+ //
+ // Copy the current token to the output value
+ //
+ strcpy (Value, CurrentToken);
+ //
+ // Strip trailing white space
+ //
+ while (strlen(Value) > 0 && (*(Value + strlen(Value) - 1) == ' ' || *(Value + strlen(Value) - 1) == '\t')) {
+ *(Value + strlen(Value) - 1) = 0;
+ }
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // Increment the occurrence found
+ //
+ Occurrence++;
+ }
+ }
+ } while (
+ !ParseError &&
+ !ReadError &&
+ InputFile->CurrentFilePointer < InputFile->Eof &&
+ CurrentToken[0] != '[' &&
+ Occurrence <= 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;
+ int Data1;
+ int Data2;
+ int Data3;
+ int 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-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ &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 preceded 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 Value;
+ CHAR8 CurrentChar;
+
+ //
+ // Initialize the result
+ //
+ Value = 0;
+ Index = 0;
+
+ //
+ // Check input parameter
+ //
+ if (AsciiString == NULL || ReturnValue == NULL || strlen(AsciiString) > 0xFF) {
+ return EFI_INVALID_PARAMETER;
+ }
+ while (AsciiString[Index] == ' ') {
+ Index ++;
+ }
+
+ //
+ // Add each character to the result
+ //
+
+ //
+ // Skip first two chars only if the string starts with '0x' or '0X'
+ //
+ if (AsciiString[Index] == '0' && (AsciiString[Index + 1] == 'x' || AsciiString[Index + 1] == 'X')) {
+ IsHex = TRUE;
+ Index += 2;
+ }
+ if (IsHex) {
+ //
+ // Convert the hex string.
+ //
+ for (; AsciiString[Index] != '\0'; Index++) {
+ CurrentChar = AsciiString[Index];
+ if (CurrentChar == ' ') {
+ break;
+ }
+ //
+ // Verify Hex string
+ //
+ if (isxdigit ((int)CurrentChar) == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Add hex value
+ //
+ Value *= 16;
+ if (CurrentChar >= '0' && CurrentChar <= '9') {
+ Value += CurrentChar - '0';
+ } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {
+ Value += CurrentChar - 'a' + 10;
+ } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {
+ Value += CurrentChar - 'A' + 10;
+ }
+ }
+
+ *ReturnValue = Value;
+ } else {
+ //
+ // Convert dec string is a number
+ //
+ for (; Index < strlen (AsciiString); Index++) {
+ CurrentChar = AsciiString[Index];
+ if (CurrentChar == ' ') {
+ break;
+ }
+ //
+ // Verify Dec string
+ //
+ if (isdigit ((int)CurrentChar) == 0) {
+ return EFI_ABORTED;
+ }
+ //
+ // Add dec value
+ //
+ Value = Value * 10;
+ Value += CurrentChar - '0';
+ }
+
+ *ReturnValue = Value;
+ }
+
+ 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_LONG_FILE_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_LONG_FILE_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_LONG_FILE_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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.h
new file mode 100644
index 00000000..69c92cc1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.h
@@ -0,0 +1,220 @@
+/** @file
+Header file for helper functions useful for parsing INF files.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EFI_PARSE_INF_H
+#define _EFI_PARSE_INF_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <Common/UefiBaseTypes.h>
+#include <MemoryFile.h>
+
+#ifdef __cplusplus
+extern "C" {
+#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 MaxLength 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_LONG_FILE_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 preceded 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_LONG_FILE_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
+
+--*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.c
new file mode 100644
index 00000000..de3b7446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.c
@@ -0,0 +1,779 @@
+/** @file
+This file contains the PcdValue structure definition.
+
+Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "CommonLib.h"
+#include "PcdValueCommon.h"
+
+typedef enum {
+ PcdDataTypeBoolean,
+ PcdDataTypeUint8,
+ PcdDataTypeUint16,
+ PcdDataTypeUint32,
+ PcdDataTypeUint64,
+ PcdDataTypePointer
+} PCD_DATA_TYPE;
+
+typedef struct {
+ CHAR8 *SkuName;
+ CHAR8 *DefaultValueName;
+ CHAR8 *TokenSpaceGuidName;
+ CHAR8 *TokenName;
+ CHAR8 *DataType;
+ CHAR8 *Value;
+ PCD_DATA_TYPE PcdDataType;
+} PCD_ENTRY;
+
+PCD_ENTRY *PcdList;
+UINT32 PcdListLength;
+
+VOID
+STATIC
+RecordToken (
+ UINT8 *FileBuffer,
+ UINT32 PcdIndex,
+ UINT32 TokenIndex,
+ UINT32 TokenStart,
+ UINT32 TokenEnd
+ )
+/*++
+
+Routine Description:
+
+ Record new token information
+
+Arguments:
+
+ FileBuffer File Buffer to be record
+ PcdIndex Index of PCD in database
+ TokenIndex Index of Token
+ TokenStart Start of Token
+ TokenEnd End of Token
+
+Returns:
+
+ None
+--*/
+{
+ CHAR8 *Token;
+
+ Token = malloc (TokenEnd - TokenStart + 1);
+ if (Token == NULL) {
+ return;
+ }
+ memcpy (Token, &FileBuffer[TokenStart], TokenEnd - TokenStart);
+ Token[TokenEnd - TokenStart] = 0;
+ switch (TokenIndex) {
+ case 0:
+ PcdList[PcdIndex].SkuName = Token;
+ break;
+ case 1:
+ PcdList[PcdIndex].DefaultValueName = Token;
+ break;
+ case 2:
+ PcdList[PcdIndex].TokenSpaceGuidName = Token;
+ break;
+ case 3:
+ PcdList[PcdIndex].TokenName = Token;
+ break;
+ case 4:
+ PcdList[PcdIndex].DataType = Token;
+ if (strcmp (Token, "BOOLEAN") == 0) {
+ PcdList[PcdIndex].PcdDataType = PcdDataTypeBoolean;
+ } else if (strcmp (Token, "UINT8") == 0) {
+ PcdList[PcdIndex].PcdDataType = PcdDataTypeUint8;
+ } else if (strcmp (Token, "UINT16") == 0) {
+ PcdList[PcdIndex].PcdDataType = PcdDataTypeUint16;
+ } else if (strcmp (Token, "UINT32") == 0) {
+ PcdList[PcdIndex].PcdDataType = PcdDataTypeUint32;
+ } else if (strcmp (Token, "UINT64") == 0) {
+ PcdList[PcdIndex].PcdDataType = PcdDataTypeUint64;
+ } else {
+ PcdList[PcdIndex].PcdDataType = PcdDataTypePointer;
+ }
+ break;
+ case 5:
+ PcdList[PcdIndex].Value = Token;
+ break;
+ default:
+ free (Token);
+ break;
+ }
+}
+
+int
+STATIC
+LookupPcdIndex (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName
+ )
+/*++
+
+Routine Description:
+
+ Get PCD index in Pcd database
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+
+Returns:
+
+ Index of PCD in Pcd database
+--*/
+{
+ UINT32 Index;
+
+ if (SkuName == NULL) {
+ SkuName = "DEFAULT";
+ }
+ if (DefaultValueName == NULL) {
+ DefaultValueName = "DEFAULT";
+ }
+ for (Index = 0; Index < PcdListLength; Index++) {
+ if (strcmp(PcdList[Index].TokenSpaceGuidName, TokenSpaceGuidName) != 0) {
+ continue;
+ }
+ if (strcmp(PcdList[Index].TokenName, TokenName) != 0) {
+ continue;
+ }
+ if (strcmp(PcdList[Index].SkuName, SkuName) != 0) {
+ continue;
+ }
+ if (strcmp(PcdList[Index].DefaultValueName, DefaultValueName) != 0) {
+ continue;
+ }
+ return Index;
+ }
+ return -1;
+}
+
+UINT64
+__PcdGet (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName
+ )
+/*++
+
+Routine Description:
+
+ Get PCD value
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+
+Returns:
+
+ PCD value
+--*/
+{
+ int Index;
+ CHAR8 *End;
+
+ Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ if (Index < 0) {
+ fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ exit (EXIT_FAILURE);
+ }
+ switch (PcdList[Index].PcdDataType) {
+ case PcdDataTypeBoolean:
+ case PcdDataTypeUint8:
+ case PcdDataTypeUint16:
+ case PcdDataTypeUint32:
+ return (UINT64)strtoul(PcdList[Index].Value, &End, 16);
+ break;
+ case PcdDataTypeUint64:
+ return (UINT64)strtoul(PcdList[Index].Value, &End, 16);
+ break;
+ case PcdDataTypePointer:
+ fprintf (stderr, "PCD %s.%s.%s.%s is structure. Use PcdGetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ exit (EXIT_FAILURE);
+ break;
+ }
+ return 0;
+}
+
+VOID
+__PcdSet (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName,
+ UINT64 Value
+ )
+/*++
+
+Routine Description:
+
+ Set PCD value
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+ Value PCD value to be set
+
+Returns:
+
+ None
+--*/
+{
+ int Index;
+
+ Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ if (Index < 0) {
+ fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ exit (EXIT_FAILURE);
+ }
+ free(PcdList[Index].Value);
+ PcdList[Index].Value = malloc(20);
+ switch (PcdList[Index].PcdDataType) {
+ case PcdDataTypeBoolean:
+ if (Value == 0) {
+ strcpy (PcdList[Index].Value, "0x00");
+ } else {
+ strcpy (PcdList[Index].Value, "0x01");
+ }
+ break;
+ case PcdDataTypeUint8:
+ sprintf(PcdList[Index].Value, "0x%02x", (UINT8)(Value & 0xff));
+ break;
+ case PcdDataTypeUint16:
+ sprintf(PcdList[Index].Value, "0x%04x", (UINT16)(Value & 0xffff));
+ break;
+ case PcdDataTypeUint32:
+ sprintf(PcdList[Index].Value, "0x%08x", (UINT32)(Value & 0xffffffff));
+ break;
+ case PcdDataTypeUint64:
+ sprintf(PcdList[Index].Value, "0x%016llx", (unsigned long long)Value);
+ break;
+ case PcdDataTypePointer:
+ fprintf (stderr, "PCD %s.%s.%s.%s is structure. Use PcdSetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ exit (EXIT_FAILURE);
+ break;
+ }
+}
+
+VOID *
+__PcdGetPtr (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Get PCD value buffer
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+ Size Size of PCD value buffer
+
+Returns:
+
+ PCD value buffer
+--*/
+{
+ int Index;
+ CHAR8 *Value;
+ UINT8 *Buffer;
+ CHAR8 *End;
+
+ Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ if (Index < 0) {
+ fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ exit (EXIT_FAILURE);
+ }
+ switch (PcdList[Index].PcdDataType) {
+ case PcdDataTypeBoolean:
+ case PcdDataTypeUint8:
+ case PcdDataTypeUint16:
+ case PcdDataTypeUint32:
+ case PcdDataTypeUint64:
+ fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ exit (EXIT_FAILURE);
+ break;
+ case PcdDataTypePointer:
+ Value = &PcdList[Index].Value[1];
+ for (*Size = 0, strtoul(Value, &End, 16); Value != End; strtoul(Value, &End, 16), *Size = *Size + 1) {
+ Value = End + 1;
+ }
+ Buffer = malloc(*Size + 1);
+ if (Buffer == NULL) {
+ *Size = 0;
+ return NULL;
+ }
+ Value = &PcdList[Index].Value[1];
+ for (*Size = 0, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16); Value != End; *Size = *Size + 1, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16)) {
+ Value = End + 1;
+ }
+ return Buffer;
+ }
+ *Size = 0;
+ return 0;
+}
+
+VOID
+__PcdSetPtr (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName,
+ UINT32 Size,
+ UINT8 *Value
+ )
+/*++
+
+Routine Description:
+
+ Set PCD value buffer
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+ Size Size of PCD value
+ Value Pointer to the updated PCD value buffer
+
+Returns:
+
+ None
+--*/
+{
+ int Index;
+ UINT32 ValueIndex;
+
+ Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ if (Index < 0) {
+ fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ exit (EXIT_FAILURE);
+ }
+ switch (PcdList[Index].PcdDataType) {
+ case PcdDataTypeBoolean:
+ case PcdDataTypeUint8:
+ case PcdDataTypeUint16:
+ case PcdDataTypeUint32:
+ case PcdDataTypeUint64:
+ fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
+ exit (EXIT_FAILURE);
+ break;
+ case PcdDataTypePointer:
+ free(PcdList[Index].Value);
+ PcdList[Index].Value = malloc(Size * 5 + 3);
+ PcdList[Index].Value[0] = '{';
+ for (ValueIndex = 0; ValueIndex < Size; ValueIndex++) {
+ sprintf(&PcdList[Index].Value[1 + ValueIndex * 5], "0x%02x,", Value[ValueIndex]);
+ }
+ PcdList[Index].Value[1 + Size * 5 - 1] = '}';
+ PcdList[Index].Value[1 + Size * 5 ] = 0;
+ break;
+ }
+}
+
+VOID
+STATIC
+ReadInputFile (
+ CHAR8 *InputFileName,
+ UINT8 **FileBuffer,
+ UINT32 *FileSize
+ )
+/*++
+
+Routine Description:
+
+ Read the file buffer from the input file.
+
+Arguments:
+
+ InputFileName Point to the input file name.
+ FileBuffer Point to the input file buffer.
+ FileSize Size of the file buffer.
+
+Returns:
+
+ None
+--*/
+{
+ FILE *InputFile;
+ UINT32 BytesRead;
+
+ //
+ // Open Input file and read file data.
+ //
+ InputFile = fopen (InputFileName, "rb");
+ if (InputFile == NULL) {
+ fprintf (stderr, "Error opening file %s\n", InputFileName);
+ exit (EXIT_FAILURE);
+ }
+
+ //
+ // Go to the end so that we can determine the file size
+ //
+ if (fseek (InputFile, 0, SEEK_END)) {
+ fprintf (stderr, "Error reading input file %s\n", InputFileName);
+ fclose (InputFile);
+ exit (EXIT_FAILURE);
+ }
+
+ //
+ // Get the file size
+ //
+ *FileSize = ftell (InputFile);
+ if (*FileSize == -1) {
+ fprintf (stderr, "Error parsing the input file %s\n", InputFileName);
+ fclose (InputFile);
+ exit (EXIT_FAILURE);
+ }
+
+ //
+ // Allocate a buffer
+ //
+ *FileBuffer = malloc (*FileSize);
+ if (*FileBuffer == NULL) {
+ fprintf (stderr, "Can not allocate buffer for input input file %s\n", InputFileName);
+ fclose (InputFile);
+ exit (EXIT_FAILURE);
+ }
+
+ //
+ // Reset to the beginning of the file
+ //
+ if (fseek (InputFile, 0, SEEK_SET)) {
+ fprintf (stderr, "Error reading the input file %s\n", InputFileName);
+ fclose (InputFile);
+ free (*FileBuffer);
+ exit (EXIT_FAILURE);
+ }
+
+ //
+ // Read all of the file contents.
+ //
+ BytesRead = (UINT32)fread (*FileBuffer, sizeof (UINT8), *FileSize, InputFile);
+ if (BytesRead != *FileSize * sizeof (UINT8)) {
+ fprintf (stderr, "Error reading the input file %s\n", InputFileName);
+ fclose (InputFile);
+ free (*FileBuffer);
+ exit (EXIT_FAILURE);
+ }
+
+ //
+ // Close the file
+ //
+ fclose (InputFile);
+}
+
+VOID
+STATIC
+ParseFile (
+ UINT8 *FileBuffer,
+ UINT32 FileSize
+ )
+/*++
+
+Routine Description:
+
+ Read the initial PCD value from the input file buffer.
+
+Arguments:
+
+ FileBuffer Point to the input file buffer.
+ FileSize Size of the file buffer.
+
+Returns:
+
+ None
+--*/
+{
+ UINT32 Index;
+ UINT32 NumLines;
+ UINT32 TokenIndex;
+ UINT32 TokenStart;
+
+ for (Index = 0, NumLines = 0; Index < FileSize; Index++) {
+ if (FileBuffer[Index] == '\n') {
+ NumLines++;
+ }
+ }
+ PcdList = malloc((NumLines + 1) * sizeof(PcdList[0]));
+
+ for (Index = 0, TokenIndex = 0, PcdListLength = 0, TokenStart = 0; Index < FileSize; Index++) {
+ if (FileBuffer[Index] == ' ') {
+ continue;
+ }
+ if (FileBuffer[Index] == '|' || FileBuffer[Index] == '.' || FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
+ RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
+ if (FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
+ if (TokenIndex != 0) {
+ PcdListLength++;
+ TokenIndex = 0;
+ }
+ } else {
+ TokenIndex++;
+ }
+ TokenStart = Index + 1;
+ continue;
+ }
+ }
+ if (Index > TokenStart) {
+ RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
+ if (TokenIndex != 0) {
+ PcdListLength++;
+ }
+ }
+}
+
+VOID
+STATIC
+WriteOutputFile (
+ CHAR8 *OutputFileName
+ )
+/*++
+
+Routine Description:
+
+ Write the updated PCD value into the output file name.
+
+Arguments:
+
+ OutputFileName Point to the output file name.
+
+Returns:
+
+ None
+--*/
+{
+ FILE *OutputFile;
+ UINT32 Index;
+
+ //
+ // Open output file
+ //
+ OutputFile = fopen (OutputFileName, "wb");
+ if (OutputFile == NULL) {
+ fprintf (stderr, "Error opening file %s\n", OutputFileName);
+ exit (EXIT_FAILURE);
+ }
+
+ for (Index = 0; Index < PcdListLength; Index++) {
+ fprintf (
+ OutputFile,
+ "%s.%s.%s.%s|%s|%s\n",
+ PcdList[Index].SkuName,
+ PcdList[Index].DefaultValueName,
+ PcdList[Index].TokenSpaceGuidName,
+ PcdList[Index].TokenName,
+ PcdList[Index].DataType,
+ PcdList[Index].Value
+ );
+ }
+
+ //
+ // Done, write output file.
+ //
+ if (OutputFile != NULL) {
+ fclose (OutputFile);
+ }
+}
+
+VOID
+STATIC
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ fprintf (stdout, "Usage: -i <input_file> -o <output_file>\n\n");
+ fprintf (stdout, "optional arguments:\n");
+ fprintf (stdout, " -h, --help Show this help message and exit\n");
+ fprintf (stdout, " -i INPUT_FILENAME, --input INPUT_FILENAME\n\
+ PCD Database Input file name\n");
+ fprintf (stdout, " -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\
+ PCD Database Output file name\n");
+}
+
+VOID
+STATIC
+ParseArguments (
+ int argc,
+ char *argv[],
+ CHAR8 **InputFileName,
+ CHAR8 **OutputFileName
+ )
+/*++
+
+Routine Description:
+
+ Parse the input parameters to get the input/output file name.
+
+Arguments:
+
+ argc Number of command line parameters.
+ argv Array of pointers to parameter strings.
+ InputFileName Point to the input file name.
+ OutputFileName Point to the output file name.
+
+Returns:
+
+ None
+--*/
+{
+ if (argc == 1) {
+ fprintf (stderr, "Missing options\n");
+ exit (EXIT_FAILURE);
+ }
+
+ //
+ // Parse command line
+ //
+ argc--;
+ argv++;
+
+ if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
+ Usage ();
+ exit (EXIT_SUCCESS);
+ }
+
+ while (argc > 0) {
+ if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--input") == 0)) {
+ if (argv[1] == NULL || argv[1][0] == '-') {
+ fprintf (stderr, "Invalid option value. Input File name is missing for -i option\n");
+ exit (EXIT_FAILURE);
+ }
+ *InputFileName = argv[1];
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
+ if (argv[1] == NULL || argv[1][0] == '-') {
+ fprintf (stderr, "Invalid option value. Output File name is missing for -i option\n");
+ exit (EXIT_FAILURE);
+ }
+ *OutputFileName = argv[1];
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+
+ if (argv[0][0] == '-') {
+ fprintf (stderr, "Unknown option %s\n", argv[0]);
+ exit (EXIT_FAILURE);
+ }
+ argc --;
+ argv ++;
+ }
+
+ //
+ // Check Input parameters
+ //
+ if (*InputFileName == NULL) {
+ fprintf (stderr, "Missing option. Input files is not specified\n");
+ exit (EXIT_FAILURE);
+ }
+
+ if (*OutputFileName == NULL) {
+ fprintf (stderr, "Missing option. Output file is not specified\n");
+ exit (EXIT_FAILURE);
+ }
+}
+
+int
+PcdValueMain (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main function updates PCD values.
+
+Arguments:
+
+ argc Number of command line parameters.
+ argv Array of pointers to parameter strings.
+
+Returns:
+ EXIT_SUCCESS
+--*/
+{
+ CHAR8 *InputFileName;
+ CHAR8 *OutputFileName;
+ UINT8 *FileBuffer;
+ UINT32 FileSize;
+
+ InputFileName = NULL;
+ OutputFileName = NULL;
+
+ //
+ // Parse the input arguments
+ //
+ ParseArguments (argc, argv, &InputFileName, &OutputFileName);
+
+ //
+ // Open Input file and read file data.
+ //
+ ReadInputFile (InputFileName, &FileBuffer, &FileSize);
+
+ //
+ // Read the initial Pcd value
+ //
+ ParseFile (FileBuffer, FileSize);
+
+ //
+ // Customize PCD values in the PCD Database
+ //
+ PcdEntryPoint ();
+
+ //
+ // Save the updated PCD value
+ //
+ WriteOutputFile (OutputFileName);
+
+ exit (EXIT_SUCCESS);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h
new file mode 100644
index 00000000..f53d8a4b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h
@@ -0,0 +1,185 @@
+/** @file
+Header file for PcdValue structure definition.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _PCD_VALUE_COMMON_H
+#define _PCD_VALUE_COMMON_H
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/UefiInternalFormRepresentation.h>
+
+#define __FIELD_SIZE(TYPE, Field) (sizeof((TYPE *)0)->Field)
+#define __ARRAY_ELEMENT_SIZE(TYPE, Field) (sizeof((TYPE *)0)->Field[0])
+#define __OFFSET_OF(TYPE, Field) ((UINT32)(size_t) &(((TYPE *)0)->Field))
+#define __FLEXIBLE_SIZE(Size, TYPE, Field, MaxIndex) if (__FIELD_SIZE(TYPE, Field) == 0) Size = MAX((__OFFSET_OF(TYPE, Field) + __ARRAY_ELEMENT_SIZE(TYPE, Field) * (MaxIndex)), Size)
+#define __ARRAY_SIZE(Array) (sizeof(Array)/sizeof(Array[0]))
+
+#if defined(_MSC_EXTENSIONS)
+#define __STATIC_ASSERT static_assert
+#else
+#define __STATIC_ASSERT _Static_assert
+#endif
+
+VOID
+PcdEntryPoint (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Main function updates PCD values. It is auto generated by Build
+
+Arguments:
+
+ None
+
+Returns:
+ None
+--*/
+;
+
+int
+PcdValueMain (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main function updates PCD values.
+
+Arguments:
+
+ argc Number of command line parameters.
+ argv Array of pointers to parameter strings.
+
+Returns:
+ EXIT_SUCCESS
+--*/
+;
+
+VOID
+__PcdSet (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName,
+ UINT64 Value
+ )
+/*++
+
+Routine Description:
+
+ Get PCD value
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+
+Returns:
+
+ PCD value
+--*/
+;
+
+VOID
+__PcdSet (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName,
+ UINT64 Value
+ )
+/*++
+
+Routine Description:
+
+ Set PCD value
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+ Value PCD value to be set
+
+Returns:
+
+ None
+--*/
+;
+
+VOID *
+__PcdGetPtr (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Get PCD value buffer
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+ Size Size of PCD value buffer
+
+Returns:
+
+ PCD value buffer
+--*/
+;
+
+VOID
+__PcdSetPtr (
+ CHAR8 *SkuName OPTIONAL,
+ CHAR8 *DefaultValueName OPTIONAL,
+ CHAR8 *TokenSpaceGuidName,
+ CHAR8 *TokenName,
+ UINT32 Size,
+ UINT8 *Value
+ )
+/*++
+
+Routine Description:
+
+ Set PCD value buffer
+
+Arguments:
+
+ SkuName SkuName String
+ DefaultValueName DefaultValueName String
+ TokenSpaceGuidName TokenSpaceGuidName String
+ TokenName TokenName String
+ Size Size of PCD value
+ Value Pointer to the updated PCD value buffer
+
+Returns:
+
+ None
+--*/
+;
+
+#define PcdGet(A, B, C, D) __PcdGet(#A, #B, #C, #D)
+#define PcdSet(A, B, C, D, Value) __PcdSet(#A, #B, #C, #D, Value)
+#define PcdGetPtr(A, B, C, D, Size) __PcdGetPtr(#A, #B, #C, #D, Size)
+#define PcdSetPtr(A, B, C, D, Size, Value) __PcdSetPtr(#A, #B, #C, #D, Size, Value)
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLib.h
new file mode 100644
index 00000000..b625f6ac
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLib.h
@@ -0,0 +1,213 @@
+/** @file
+ Function prototypes and defines on Memory Only PE COFF loader
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Portion Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+
+//
+// Macro definitions for RISC-V architecture.
+//
+#define RV_X(x, s, n) (((x) >> (s)) & ((1<<(n))-1))
+#define RISCV_IMM_BITS 12
+#define RISCV_IMM_REACH (1LL<<RISCV_IMM_BITS)
+#define RISCV_CONST_HIGH_PART(VALUE) \
+ (((VALUE) + (RISCV_IMM_REACH/2)) & ~(RISCV_IMM_REACH-1))
+
+//
+// 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
+ )
+;
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderGetEntryPoint (
+ IN VOID *Pe32Data,
+ OUT VOID **EntryPoint,
+ OUT VOID **BaseOfImage
+ )
+;
+
+//
+// These functions are used by the ARM PE/COFF relocation code and by
+// the ELF to PE/COFF converter so that is why they are public
+//
+
+/**
+ Pass in a pointer to an ARM MOVT or MOVW immediate instruction and
+ return the immediate data encoded in the instruction
+
+ @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
+
+ @return Immediate address encoded in the instruction
+
+**/
+UINT16
+EFIAPI
+ThumbMovtImmediateAddress (
+ IN UINT16 *Instruction
+ );
+
+/**
+ Update an ARM MOVT or MOVW immediate instruction immediate data.
+
+ @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
+ @param Address New address to patch into the instruction
+
+**/
+VOID
+EFIAPI
+ThumbMovtImmediatePatch (
+ IN OUT UINT16 *Instruction,
+ IN UINT16 Address
+ );
+
+
+/**
+ Pass in a pointer to an ARM MOVW/MOVT instruction pair and
+ return the immediate data encoded in the two` instruction
+
+ @param Instructions Pointer to ARM MOVW/MOVT instruction pair
+
+ @return Immediate address encoded in the instructions
+
+**/
+UINT32
+EFIAPI
+ThumbMovwMovtImmediateAddress (
+ IN UINT16 *Instructions
+ );
+
+/**
+ Update an ARM MOVW/MOVT immediate instruction instruction pair.
+
+ @param Instructions Pointer to ARM MOVW/MOVT instruction pair
+ @param Address New address to patch into the instructions
+**/
+VOID
+EFIAPI
+ThumbMovwMovtImmediatePatch (
+ IN OUT UINT16 *Instructions,
+ IN UINT32 Address
+ );
+
+
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c
new file mode 100644
index 00000000..b7492998
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c
@@ -0,0 +1,334 @@
+/** @file
+IA32 and X64 Specific relocation fixups
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+--*/
+
+#include <Common/UefiBaseTypes.h>
+#include <IndustryStandard/PeImage.h>
+#include "PeCoffLib.h"
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.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
+
+UINT32 *RiscVHi20Fixup = NULL;
+
+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;
+}
+
+/*++
+
+Routine Description:
+
+ Performs an RISC-V 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
+
+--*/
+RETURN_STATUS
+PeCoffLoaderRelocateRiscVImage (
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+{
+ UINT32 Value;
+ UINT32 Value2;
+
+ switch ((*Reloc) >> 12) {
+ case EFI_IMAGE_REL_BASED_RISCV_HI20:
+ RiscVHi20Fixup = (UINT32 *) Fixup;
+ break;
+
+ case EFI_IMAGE_REL_BASED_RISCV_LOW12I:
+ if (RiscVHi20Fixup != NULL) {
+ Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12);
+ Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 20, 12));
+ if (Value2 & (RISCV_IMM_REACH/2)) {
+ Value2 |= ~(RISCV_IMM_REACH-1);
+ }
+ Value += Value2;
+ Value += (UINT32)Adjust;
+ Value2 = RISCV_CONST_HIGH_PART (Value);
+ *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \
+ (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12));
+ *(UINT32 *)Fixup = (RV_X (Value, 0, 12) << 20) | \
+ (RV_X (*(UINT32 *)Fixup, 0, 20));
+ }
+ RiscVHi20Fixup = NULL;
+ break;
+
+ case EFI_IMAGE_REL_BASED_RISCV_LOW12S:
+ if (RiscVHi20Fixup != NULL) {
+ Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12);
+ Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 7, 5) | (RV_X(*(UINT32 *)Fixup, 25, 7) << 5));
+ if (Value2 & (RISCV_IMM_REACH/2)) {
+ Value2 |= ~(RISCV_IMM_REACH-1);
+ }
+ Value += Value2;
+ Value += (UINT32)Adjust;
+ Value2 = RISCV_CONST_HIGH_PART (Value);
+ *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \
+ (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12));
+ Value2 = *(UINT32 *)Fixup & 0x01fff07f;
+ Value &= RISCV_IMM_REACH - 1;
+ *(UINT32 *)Fixup = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25)));
+ }
+ RiscVHi20Fixup = NULL;
+ break;
+
+ default:
+ return EFI_UNSUPPORTED;
+
+ }
+ return RETURN_SUCCESS;
+}
+
+/**
+ Pass in a pointer to an ARM MOVT or MOVW immediate instruction and
+ return the immediate data encoded in the instruction
+
+ @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
+
+ @return Immediate address encoded in the instruction
+
+**/
+UINT16
+ThumbMovtImmediateAddress (
+ IN UINT16 *Instruction
+ )
+{
+ UINT32 Movt;
+ UINT16 Address;
+
+ // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction
+ // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000
+ Movt = (*Instruction << 16) | (*(Instruction + 1));
+
+ // imm16 = imm4:i:imm3:imm8
+ // imm4 -> Bit19:Bit16
+ // i -> Bit26
+ // imm3 -> Bit14:Bit12
+ // imm8 -> Bit7:Bit0
+ Address = (UINT16)(Movt & 0x000000ff); // imm8
+ Address |= (UINT16)((Movt >> 4) & 0x0000f700); // imm4 imm3
+ Address |= (((Movt & BIT26) != 0) ? BIT11 : 0); // i
+ return Address;
+}
+
+
+/**
+ Update an ARM MOVT or MOVW immediate instruction immediate data.
+
+ @param Instruction Pointer to ARM MOVT or MOVW immediate instruction
+ @param Address New address to patch into the instruction
+**/
+VOID
+ThumbMovtImmediatePatch (
+ IN OUT UINT16 *Instruction,
+ IN UINT16 Address
+ )
+{
+ UINT16 Patch;
+
+ // First 16-bit chunk of instruction
+ Patch = ((Address >> 12) & 0x000f); // imm4
+ Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i
+ *Instruction = (*Instruction & ~0x040f) | Patch;
+
+ // Second 16-bit chunk of instruction
+ Patch = Address & 0x000000ff; // imm8
+ Patch |= ((Address << 4) & 0x00007000); // imm3
+ Instruction++;
+ *Instruction = (*Instruction & ~0x70ff) | Patch;
+}
+
+/**
+ Pass in a pointer to an ARM MOVW/MOVT instruction pair and
+ return the immediate data encoded in the two` instruction
+
+ @param Instructions Pointer to ARM MOVW/MOVT instruction pair
+
+ @return Immediate address encoded in the instructions
+
+**/
+UINT32
+EFIAPI
+ThumbMovwMovtImmediateAddress (
+ IN UINT16 *Instructions
+ )
+{
+ UINT16 *Word;
+ UINT16 *Top;
+
+ Word = Instructions; // MOVW
+ Top = Word + 2; // MOVT
+
+ return (ThumbMovtImmediateAddress (Top) << 16) + ThumbMovtImmediateAddress (Word);
+}
+
+
+/**
+ Update an ARM MOVW/MOVT immediate instruction instruction pair.
+
+ @param Instructions Pointer to ARM MOVW/MOVT instruction pair
+ @param Address New address to patch into the instructions
+**/
+VOID
+EFIAPI
+ThumbMovwMovtImmediatePatch (
+ IN OUT UINT16 *Instructions,
+ IN UINT32 Address
+ )
+{
+ UINT16 *Word;
+ UINT16 *Top;
+
+ Word = (UINT16 *)Instructions; // MOVW
+ Top = Word + 2; // MOVT
+
+ ThumbMovtImmediatePatch (Word, (UINT16)(Address & 0xffff));
+ ThumbMovtImmediatePatch (Top, (UINT16)(Address >> 16));
+}
+
+
+/**
+ Performs an ARM-based specific relocation fixup and is a no-op on other
+ instruction sets.
+
+ @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.
+
+ @return Status code.
+
+**/
+RETURN_STATUS
+PeCoffLoaderRelocateArmImage (
+ IN UINT16 **Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN UINT64 Adjust
+ )
+{
+ UINT16 *Fixup16;
+ UINT32 FixupVal;
+
+ Fixup16 = (UINT16 *) Fixup;
+
+ switch ((**Reloc) >> 12) {
+
+ case EFI_IMAGE_REL_BASED_ARM_MOV32T:
+ FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;
+ ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);
+
+
+ if (*FixupData != NULL) {
+ *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
+ CopyMem (*FixupData, Fixup16, sizeof (UINT64));
+ *FixupData = *FixupData + sizeof(UINT64);
+ }
+ break;
+
+ case EFI_IMAGE_REL_BASED_ARM_MOV32A:
+ // break omitted - ARM instruction encoding not implemented
+ default:
+ return RETURN_UNSUPPORTED;
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.c
new file mode 100644
index 00000000..337899ed
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.c
@@ -0,0 +1,1429 @@
+/** @file
+Generic but simple file parsing routines.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "CommonLib.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 ((int)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:
+ Preceding 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
+
+--*/
+{
+ int Val;
+
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (isdigit ((int)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 ((int)mGlobals.SourceFile.FileBufferPtr[2])) {
+ return FALSE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr += 2;
+ sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", &Val);
+ *Value = (UINT32) Val;
+ while (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ } else {
+ *Value = atoi (mGlobals.SourceFile.FileBufferPtr);
+ while (isdigit ((int)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", (int)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 exceeds max nesting depth (%u)", SourceFile->FileName, (unsigned) 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 (LongFilePath (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 = %u (0x%X)\n", (unsigned) SourceFile->FileSize, (unsigned) 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 = %u (0x%X)\n", (unsigned)SourceFile->FileSize, (unsigned)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) && (Len < BufferLen)) {
+ if (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) {
+ Buffer[Len] = mGlobals.SourceFile.FileBufferPtr[0];
+ Len++;
+ mGlobals.SourceFile.FileBufferPtr++;
+ } else {
+ break;
+ }
+ }
+ //
+ // Null terminate if we can
+ //
+ if ((Len > 0) && (Len < BufferLen)) {
+ Buffer[Len] = 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
+
+--*/
+{
+ INT32 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.h
new file mode 100644
index 00000000..e699f050
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.h
@@ -0,0 +1,104 @@
+/** @file
+Function prototypes and defines for the simple file parsing routines.
+
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.c
new file mode 100644
index 00000000..2d092869
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.c
@@ -0,0 +1,413 @@
+/** @file
+Function prototypes and defines for string routines.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 ((int)*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 ((int)*(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 ((int)*Pos)) {
+ Pos++;
+ }
+
+ for (EndOfSubString=Pos;
+ (*EndOfSubString != '\0') && !isspace ((int)*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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.h
new file mode 100644
index 00000000..937abcd9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.h
@@ -0,0 +1,244 @@
+/** @file
+String routines implementation
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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:
+
+ String 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/TianoCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/TianoCompress.c
new file mode 100644
index 00000000..b5aea760
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/TianoCompress.c
@@ -0,0 +1,1746 @@
+/** @file
+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.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+
+Arguments:
+ VOID
+
+Returns:
+
+ EFI_SUCCESS - Memory is allocated successfully
+ EFI_OUT_OF_RESOURCES - Allocation fails
+
+--*/
+{
+ UINT32 Index;
+
+ mText = malloc (WNDSIZ * 2 + MAXMATCH);
+ if (mText == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ 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));
+ if (mLevel == NULL || mChildCount == NULL || mPosition == NULL ||
+ mParent == NULL || mPrev == NULL || mNext == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ 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. Traverse 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/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/WinNtInclude.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/WinNtInclude.h
new file mode 100644
index 00000000..b3c58497
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/WinNtInclude.h
@@ -0,0 +1,78 @@
+/** @file
+Include file for the WinNt Library
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+
+#ifndef VBOX
+#if (_MSC_VER < 1800)
+#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement
+#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement
+#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64
+#endif
+#endif
+
+#undef UNALIGNED
+#undef CONST
+#undef VOID
+
+#ifndef __GNUC__
+# ifdef VBOX
+# define RUNTIME_FUNCTION _WINNT_DUP_RUNTIME_FUNCTION
+# endif
+#ifdef VBOX
+#include <iprt/win/windows.h>
+#else
+#include "windows.h"
+#endif
+
+//
+// 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 still
+// 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)
+
+# ifdef VBOX
+# undef RUNTIME_FUNCTION
+# endif
+#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