diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..64aad46 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/ipxe-20180825-git133f4c.tar.gz diff --git a/.ipxe.metadata b/.ipxe.metadata new file mode 100644 index 0000000..d77eb14 --- /dev/null +++ b/.ipxe.metadata @@ -0,0 +1 @@ +0cd36a1ba686ad75b91cc56e1ae73e20aaec4188 SOURCES/ipxe-20180825-git133f4c.tar.gz diff --git a/SOURCES/0001-Add-redhat-directory.patch b/SOURCES/0001-Add-redhat-directory.patch new file mode 100644 index 0000000..81faef5 --- /dev/null +++ b/SOURCES/0001-Add-redhat-directory.patch @@ -0,0 +1,57 @@ +From b75b2bfd6d8e7e4a8d8dc6910089209082fe5747 Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Wed, 21 Oct 2015 09:40:25 +0200 +Subject: Add redhat directory + +Merged patches (20170123): +- 3dc49f9 Customize ROM banner timeout +- 4845fc2 ipxe: enable e1000e rom +--- + .gitpublish | 8 + + redhat/.gitignore | 2 + + redhat/Makefile | 71 ++++++++ + redhat/Makefile.common | 35 ++++ + redhat/USAGE | 16 ++ + redhat/ipxe.spec.template | 347 +++++++++++++++++++++++++++++++++++++ + redhat/rpmbuild/BUILD/.gitignore | 1 + + redhat/rpmbuild/RPMS/.gitignore | 1 + + redhat/rpmbuild/SOURCES/.gitignore | 1 + + redhat/rpmbuild/SPECS/.gitignore | 1 + + redhat/rpmbuild/SRPMS/.gitignore | 1 + + redhat/scripts/frh.py | 27 +++ + redhat/scripts/git-backport-diff | 327 ++++++++++++++++++++++++++++++++++ + redhat/scripts/git-compile-check | 215 +++++++++++++++++++++++ + redhat/scripts/process-patches.sh | 77 ++++++++ + redhat/scripts/tarball_checksum.sh | 3 + + src/config/local/general.h | 3 + + 17 files changed, 1136 insertions(+) + create mode 100644 .gitpublish + create mode 100644 redhat/.gitignore + create mode 100644 redhat/Makefile + create mode 100644 redhat/Makefile.common + create mode 100644 redhat/USAGE + create mode 100644 redhat/ipxe.spec.template + create mode 100644 redhat/rpmbuild/BUILD/.gitignore + create mode 100644 redhat/rpmbuild/RPMS/.gitignore + create mode 100644 redhat/rpmbuild/SOURCES/.gitignore + create mode 100644 redhat/rpmbuild/SPECS/.gitignore + create mode 100644 redhat/rpmbuild/SRPMS/.gitignore + create mode 100755 redhat/scripts/frh.py + create mode 100755 redhat/scripts/git-backport-diff + create mode 100755 redhat/scripts/git-compile-check + create mode 100755 redhat/scripts/process-patches.sh + create mode 100755 redhat/scripts/tarball_checksum.sh + create mode 100644 src/config/local/general.h + +diff --git a/src/config/local/general.h b/src/config/local/general.h +new file mode 100644 +index 0000000..5814511 +--- /dev/null ++++ b/src/config/local/general.h +@@ -0,0 +1,3 @@ ++#undef ROM_BANNER_TIMEOUT ++#define ROM_BANNER_TIMEOUT 0 ++ +-- +1.8.3.1 + diff --git a/SOURCES/0002-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch b/SOURCES/0002-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch new file mode 100644 index 0000000..f771fd8 --- /dev/null +++ b/SOURCES/0002-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch @@ -0,0 +1,8947 @@ +From 8b74bd14f38ed4defcdea3ef4a15869aa909a02e Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 21 Oct 2015 11:07:05 +0200 +Subject: import EfiRom from edk2 BaseTools (RHEL only) + +Message-id: <1410295825-13989-2-git-send-email-lersek@redhat.com> +Patchwork-id: 60927 +O-Subject: [RHEL-7.1 ipxe PATCH 1/4] import EfiRom from edk2 BaseTools (RHEL only) +Bugzilla: 1084561 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann + +This patch imports the minimum set of files from edk2's BaseTools (at +commit 07da1ac8) that are necessary to build the EfiRom utility. + +The top-level BaseTools license file is added as well. The ipxe RPM's +License field already states "GPLv2 and BSD". EfiRom (and the rest of +BaseTools) are 2-clause BSD. + +Suggested-by: Paolo Bonzini +Signed-off-by: Laszlo Ersek +Signed-off-by: Miroslav Rezanina +(cherry picked from commit 781fa846a6b51b80fb08afe8ac2b8e862006082f) +--- + EfiRom/Common/CommonLib.c | 711 +++++++++++++ + EfiRom/Common/CommonLib.h | 194 ++++ + EfiRom/Common/Compress.h | 88 ++ + EfiRom/Common/EfiCompress.c | 1590 +++++++++++++++++++++++++++++ + EfiRom/Common/EfiUtilityMsgs.c | 906 ++++++++++++++++ + EfiRom/Common/EfiUtilityMsgs.h | 170 +++ + EfiRom/Common/MemoryFile.h | 111 ++ + EfiRom/Common/ParseInf.c | 701 +++++++++++++ + EfiRom/Common/ParseInf.h | 226 ++++ + EfiRom/EfiRom.c | 1564 ++++++++++++++++++++++++++++ + EfiRom/EfiRom.h | 357 +++++++ + EfiRom/Include/Common/BaseTypes.h | 286 ++++++ + EfiRom/Include/Common/BuildVersion.h | 15 + + EfiRom/Include/Common/UefiBaseTypes.h | 175 ++++ + EfiRom/Include/IndustryStandard/EfiPci.h | 57 ++ + EfiRom/Include/IndustryStandard/PeImage.h | 769 ++++++++++++++ + EfiRom/Include/IndustryStandard/pci22.h | 542 ++++++++++ + EfiRom/Include/IndustryStandard/pci23.h | 24 + + EfiRom/Include/IndustryStandard/pci30.h | 44 + + EfiRom/Include/X64/ProcessorBind.h | 194 ++++ + EfiRom/License.txt | 25 + + 21 files changed, 8749 insertions(+) + create mode 100644 EfiRom/Common/CommonLib.c + create mode 100644 EfiRom/Common/CommonLib.h + create mode 100644 EfiRom/Common/Compress.h + create mode 100644 EfiRom/Common/EfiCompress.c + create mode 100644 EfiRom/Common/EfiUtilityMsgs.c + create mode 100644 EfiRom/Common/EfiUtilityMsgs.h + create mode 100644 EfiRom/Common/MemoryFile.h + create mode 100644 EfiRom/Common/ParseInf.c + create mode 100644 EfiRom/Common/ParseInf.h + create mode 100644 EfiRom/EfiRom.c + create mode 100644 EfiRom/EfiRom.h + create mode 100644 EfiRom/Include/Common/BaseTypes.h + create mode 100644 EfiRom/Include/Common/BuildVersion.h + create mode 100644 EfiRom/Include/Common/UefiBaseTypes.h + create mode 100644 EfiRom/Include/IndustryStandard/EfiPci.h + create mode 100644 EfiRom/Include/IndustryStandard/PeImage.h + create mode 100644 EfiRom/Include/IndustryStandard/pci22.h + create mode 100644 EfiRom/Include/IndustryStandard/pci23.h + create mode 100644 EfiRom/Include/IndustryStandard/pci30.h + create mode 100644 EfiRom/Include/X64/ProcessorBind.h + create mode 100644 EfiRom/License.txt + +diff --git a/EfiRom/Common/CommonLib.c b/EfiRom/Common/CommonLib.c +new file mode 100644 +index 0000000..977efa0 +--- /dev/null ++++ b/EfiRom/Common/CommonLib.c +@@ -0,0 +1,711 @@ ++/** @file ++Common basic Library Functions ++ ++Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++#include ++#include ++#include ++#ifdef __GNUC__ ++#include ++#else ++#include ++#endif ++#include "CommonLib.h" ++#include "EfiUtilityMsgs.h" ++ ++VOID ++PeiZeroMem ( ++ IN VOID *Buffer, ++ IN UINTN Size ++ ) ++/*++ ++ ++Routine Description: ++ ++ Set Buffer to zero for Size bytes. ++ ++Arguments: ++ ++ Buffer - Memory to set. ++ ++ Size - Number of bytes to set ++ ++Returns: ++ ++ None ++ ++--*/ ++{ ++ INT8 *Ptr; ++ ++ Ptr = Buffer; ++ while (Size--) { ++ *(Ptr++) = 0; ++ } ++} ++ ++VOID ++PeiCopyMem ( ++ IN VOID *Destination, ++ IN VOID *Source, ++ IN UINTN Length ++ ) ++/*++ ++ ++Routine Description: ++ ++ Copy Length bytes from Source to Destination. ++ ++Arguments: ++ ++ Destination - Target of copy ++ ++ Source - Place to copy from ++ ++ Length - Number of bytes to copy ++ ++Returns: ++ ++ None ++ ++--*/ ++{ ++ CHAR8 *Destination8; ++ CHAR8 *Source8; ++ ++ Destination8 = Destination; ++ Source8 = Source; ++ while (Length--) { ++ *(Destination8++) = *(Source8++); ++ } ++} ++ ++VOID ++ZeroMem ( ++ IN VOID *Buffer, ++ IN UINTN Size ++ ) ++{ ++ PeiZeroMem (Buffer, Size); ++} ++ ++VOID ++CopyMem ( ++ IN VOID *Destination, ++ IN VOID *Source, ++ IN UINTN Length ++ ) ++{ ++ PeiCopyMem (Destination, Source, Length); ++} ++ ++INTN ++CompareGuid ( ++ IN EFI_GUID *Guid1, ++ IN EFI_GUID *Guid2 ++ ) ++/*++ ++ ++Routine Description: ++ ++ Compares to GUIDs ++ ++Arguments: ++ ++ Guid1 - guid to compare ++ Guid2 - guid to compare ++ ++Returns: ++ = 0 if Guid1 == Guid2 ++ != 0 if Guid1 != Guid2 ++ ++--*/ ++{ ++ INT32 *g1; ++ INT32 *g2; ++ INT32 r; ++ ++ // ++ // Compare 32 bits at a time ++ // ++ g1 = (INT32 *) Guid1; ++ g2 = (INT32 *) Guid2; ++ ++ r = g1[0] - g2[0]; ++ r |= g1[1] - g2[1]; ++ r |= g1[2] - g2[2]; ++ r |= g1[3] - g2[3]; ++ ++ return r; ++} ++ ++ ++EFI_STATUS ++GetFileImage ( ++ IN CHAR8 *InputFileName, ++ OUT CHAR8 **InputFileImage, ++ OUT UINT32 *BytesRead ++ ) ++/*++ ++ ++Routine Description: ++ ++ This function opens a file and reads it into a memory buffer. The function ++ will allocate the memory buffer and returns the size of the buffer. ++ ++Arguments: ++ ++ InputFileName The name of the file to read. ++ InputFileImage A pointer to the memory buffer. ++ BytesRead The size of the memory buffer. ++ ++Returns: ++ ++ EFI_SUCCESS The function completed successfully. ++ EFI_INVALID_PARAMETER One of the input parameters was invalid. ++ EFI_ABORTED An error occurred. ++ EFI_OUT_OF_RESOURCES No resource to complete operations. ++ ++--*/ ++{ ++ FILE *InputFile; ++ UINT32 FileSize; ++ ++ // ++ // Verify input parameters. ++ // ++ if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ // ++ // Open the file and copy contents into a memory buffer. ++ // ++ // ++ // Open the file ++ // ++ InputFile = fopen (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) { ++ strcat (mCommonLibFullPath, RootPath); ++ if (FileName[0] != '\\' && FileName[0] != '/') { ++ // ++ // Attach directory separator ++ // ++ strcat (mCommonLibFullPath, "\\"); ++ } ++ free (RootPath); ++ } ++ } ++ ++ // ++ // Construct the full file path ++ // ++ strcat (mCommonLibFullPath, FileName); ++ ++ // ++ // 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'; ++ strcat (mCommonLibFullPath, PathPointer + 3); ++ } ++ ++ // ++ // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH. ++ // ++ while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) { ++ *PathPointer = '\0'; ++ strcat (mCommonLibFullPath, PathPointer + 2); ++ } ++ ++ // ++ // 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'; ++ strcat (mCommonLibFullPath, NextPointer); ++ } else { ++ // ++ // No directory is found. Just break. ++ // ++ break; ++ } ++ } ++ ++ PathPointer = mCommonLibFullPath; ++ } ++ ++ return PathPointer; ++#endif ++} +diff --git a/EfiRom/Common/CommonLib.h b/EfiRom/Common/CommonLib.h +new file mode 100644 +index 0000000..ab1b89b +--- /dev/null ++++ b/EfiRom/Common/CommonLib.h +@@ -0,0 +1,194 @@ ++/** @file ++Common library assistance routines. ++ ++Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _EFI_COMMON_LIB_H ++#define _EFI_COMMON_LIB_H ++ ++#include ++#include ++#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination ++ ++#define MAX_LONG_FILE_PATH 500 ++ ++#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 ++); ++/*++ ++ ++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 ++ ++#define ASSERT(x) assert(x) ++ ++#ifdef __GNUC__ ++#include ++#include ++#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/EfiRom/Common/Compress.h b/EfiRom/Common/Compress.h +new file mode 100644 +index 0000000..09d8b8d +--- /dev/null ++++ b/EfiRom/Common/Compress.h +@@ -0,0 +1,88 @@ ++/** @file ++Header file for compression routine. ++Providing both EFI and Tiano Compress algorithms. ++ ++Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _COMPRESS_H_ ++#define _COMPRESS_H_ ++ ++#include ++#include ++ ++#include "CommonLib.h" ++#include ++/*++ ++ ++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/EfiRom/Common/EfiCompress.c b/EfiRom/Common/EfiCompress.c +new file mode 100644 +index 0000000..71c6f3b +--- /dev/null ++++ b/EfiRom/Common/EfiCompress.c +@@ -0,0 +1,1590 @@ ++/** @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 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include "Compress.h" ++ ++ ++// ++// Macro Definitions ++// ++ ++#undef UINT8_MAX ++typedef INT16 NODE; ++#define UINT8_MAX 0xff ++#define UINT8_BIT 8 ++#define THRESHOLD 3 ++#define INIT_CRC 0 ++#define WNDBIT 13 ++#define WNDSIZ (1U << WNDBIT) ++#define MAXMATCH 256 ++#define PERC_FLAG 0x8000U ++#define CODE_BIT 16 ++#define NIL 0 ++#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) ++#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2) ++#define CRCPOLY 0xA001 ++#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT) ++ ++// ++// C: the Char&Len Set; P: the Position Set; T: the exTra Set ++// ++ ++#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) ++#define CBIT 9 ++#define NP (WNDBIT + 1) ++#define PBIT 4 ++#define NT (CODE_BIT + 3) ++#define TBIT 5 ++#if NT > NP ++ #define NPT NT ++#else ++ #define NPT NP ++#endif ++ ++// ++// Function Prototypes ++// ++ ++STATIC ++VOID ++PutDword( ++ IN UINT32 Data ++ ); ++ ++STATIC ++EFI_STATUS ++AllocateMemory ( ++ ); ++ ++STATIC ++VOID ++FreeMemory ( ++ ); ++ ++STATIC ++VOID ++InitSlide ( ++ ); ++ ++STATIC ++NODE ++Child ( ++ IN NODE q, ++ IN UINT8 c ++ ); ++ ++STATIC ++VOID ++MakeChild ( ++ IN NODE q, ++ IN UINT8 c, ++ IN NODE r ++ ); ++ ++STATIC ++VOID ++Split ( ++ IN NODE Old ++ ); ++ ++STATIC ++VOID ++InsertNode ( ++ ); ++ ++STATIC ++VOID ++DeleteNode ( ++ ); ++ ++STATIC ++VOID ++GetNextMatch ( ++ ); ++ ++STATIC ++EFI_STATUS ++Encode ( ++ ); ++ ++STATIC ++VOID ++CountTFreq ( ++ ); ++ ++STATIC ++VOID ++WritePTLen ( ++ IN INT32 n, ++ IN INT32 nbit, ++ IN INT32 Special ++ ); ++ ++STATIC ++VOID ++WriteCLen ( ++ ); ++ ++STATIC ++VOID ++EncodeC ( ++ IN INT32 c ++ ); ++ ++STATIC ++VOID ++EncodeP ( ++ IN UINT32 p ++ ); ++ ++STATIC ++VOID ++SendBlock ( ++ ); ++ ++STATIC ++VOID ++Output ( ++ IN UINT32 c, ++ IN UINT32 p ++ ); ++ ++STATIC ++VOID ++HufEncodeStart ( ++ ); ++ ++STATIC ++VOID ++HufEncodeEnd ( ++ ); ++ ++STATIC ++VOID ++MakeCrcTable ( ++ ); ++ ++STATIC ++VOID ++PutBits ( ++ IN INT32 n, ++ IN UINT32 x ++ ); ++ ++STATIC ++INT32 ++FreadCrc ( ++ OUT UINT8 *p, ++ IN INT32 n ++ ); ++ ++STATIC ++VOID ++InitPutBits ( ++ ); ++ ++STATIC ++VOID ++CountLen ( ++ IN INT32 i ++ ); ++ ++STATIC ++VOID ++MakeLen ( ++ IN INT32 Root ++ ); ++ ++STATIC ++VOID ++DownHeap ( ++ IN INT32 i ++ ); ++ ++STATIC ++VOID ++MakeCode ( ++ IN INT32 n, ++ IN UINT8 Len[], ++ OUT UINT16 Code[] ++ ); ++ ++STATIC ++INT32 ++MakeTree ( ++ IN INT32 NParm, ++ IN UINT16 FreqParm[], ++ OUT UINT8 LenParm[], ++ OUT UINT16 CodeParm[] ++ ); ++ ++ ++// ++// Global Variables ++// ++ ++STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit; ++ ++STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen; ++STATIC INT16 mHeap[NC + 1]; ++STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; ++STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; ++STATIC UINT32 mCompSize, mOrigSize; ++ ++STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], ++ mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1],mCCode[NC], ++ mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; ++ ++STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; ++ ++ ++// ++// functions ++// ++ ++EFI_STATUS ++EfiCompress ( ++ IN UINT8 *SrcBuffer, ++ IN UINT32 SrcSize, ++ IN UINT8 *DstBuffer, ++ IN OUT UINT32 *DstSize ++ ) ++/*++ ++ ++Routine Description: ++ ++ The main compression routine. ++ ++Arguments: ++ ++ SrcBuffer - The buffer storing the source data ++ SrcSize - The size of source data ++ DstBuffer - The buffer to store the compressed data ++ DstSize - On input, the size of DstBuffer; On output, ++ the size of the actual compressed data. ++ ++Returns: ++ ++ EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, ++ DstSize contains the size needed. ++ EFI_SUCCESS - Compression is successful. ++ ++--*/ ++{ ++ EFI_STATUS Status = EFI_SUCCESS; ++ ++ // ++ // Initializations ++ // ++ mBufSiz = 0; ++ mBuf = NULL; ++ mText = NULL; ++ mLevel = NULL; ++ mChildCount = NULL; ++ mPosition = NULL; ++ mParent = NULL; ++ mPrev = NULL; ++ mNext = NULL; ++ ++ ++ mSrc = SrcBuffer; ++ mSrcUpperLimit = mSrc + SrcSize; ++ mDst = DstBuffer; ++ mDstUpperLimit = mDst + *DstSize; ++ ++ PutDword(0L); ++ PutDword(0L); ++ ++ MakeCrcTable (); ++ ++ mOrigSize = mCompSize = 0; ++ mCrc = INIT_CRC; ++ ++ // ++ // Compress it ++ // ++ ++ Status = Encode(); ++ if (EFI_ERROR (Status)) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ // ++ // Null terminate the compressed data ++ // ++ if (mDst < mDstUpperLimit) { ++ *mDst++ = 0; ++ } ++ ++ // ++ // Fill in compressed size and original size ++ // ++ mDst = DstBuffer; ++ PutDword(mCompSize+1); ++ PutDword(mOrigSize); ++ ++ // ++ // Return ++ // ++ ++ if (mCompSize + 1 + 8 > *DstSize) { ++ *DstSize = mCompSize + 1 + 8; ++ return EFI_BUFFER_TOO_SMALL; ++ } else { ++ *DstSize = mCompSize + 1 + 8; ++ return EFI_SUCCESS; ++ } ++ ++} ++ ++STATIC ++VOID ++PutDword( ++ IN UINT32 Data ++ ) ++/*++ ++ ++Routine Description: ++ ++ Put a dword to output stream ++ ++Arguments: ++ ++ Data - the dword to put ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ if (mDst < mDstUpperLimit) { ++ *mDst++ = (UINT8)(((UINT8)(Data )) & 0xff); ++ } ++ ++ if (mDst < mDstUpperLimit) { ++ *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff); ++ } ++ ++ if (mDst < mDstUpperLimit) { ++ *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff); ++ } ++ ++ if (mDst < mDstUpperLimit) { ++ *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff); ++ } ++} ++ ++STATIC ++EFI_STATUS ++AllocateMemory () ++/*++ ++ ++Routine Description: ++ ++ Allocate memory spaces for data structures used in compression process ++ ++Argements: (VOID) ++ ++Returns: ++ ++ EFI_SUCCESS - Memory is allocated successfully ++ EFI_OUT_OF_RESOURCES - Allocation fails ++ ++--*/ ++{ ++ UINT32 i; ++ ++ mText = malloc (WNDSIZ * 2 + MAXMATCH); ++ for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) { ++ mText[i] = 0; ++ } ++ ++ mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); ++ mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); ++ mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); ++ mParent = malloc (WNDSIZ * 2 * sizeof(*mParent)); ++ mPrev = malloc (WNDSIZ * 2 * sizeof(*mPrev)); ++ mNext = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext)); ++ ++ mBufSiz = 16 * 1024U; ++ while ((mBuf = malloc(mBufSiz)) == NULL) { ++ mBufSiz = (mBufSiz / 10U) * 9U; ++ if (mBufSiz < 4 * 1024U) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ } ++ mBuf[0] = 0; ++ ++ return EFI_SUCCESS; ++} ++ ++VOID ++FreeMemory () ++/*++ ++ ++Routine Description: ++ ++ Called when compression is completed to free memory previously allocated. ++ ++Arguments: (VOID) ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ if (mText) { ++ free (mText); ++ } ++ ++ if (mLevel) { ++ free (mLevel); ++ } ++ ++ if (mChildCount) { ++ free (mChildCount); ++ } ++ ++ if (mPosition) { ++ free (mPosition); ++ } ++ ++ if (mParent) { ++ free (mParent); ++ } ++ ++ if (mPrev) { ++ free (mPrev); ++ } ++ ++ if (mNext) { ++ free (mNext); ++ } ++ ++ if (mBuf) { ++ free (mBuf); ++ } ++ ++ return; ++} ++ ++ ++STATIC ++VOID ++InitSlide () ++/*++ ++ ++Routine Description: ++ ++ Initialize String Info Log data structures ++ ++Arguments: (VOID) ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ NODE i; ++ ++ for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) { ++ mLevel[i] = 1; ++ mPosition[i] = NIL; /* sentinel */ ++ } ++ for (i = WNDSIZ; i < WNDSIZ * 2; i++) { ++ mParent[i] = NIL; ++ } ++ mAvail = 1; ++ for (i = 1; i < WNDSIZ - 1; i++) { ++ mNext[i] = (NODE)(i + 1); ++ } ++ ++ mNext[WNDSIZ - 1] = NIL; ++ for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) { ++ mNext[i] = NIL; ++ } ++} ++ ++ ++STATIC ++NODE ++Child ( ++ IN NODE q, ++ IN UINT8 c ++ ) ++/*++ ++ ++Routine Description: ++ ++ Find child node given the parent node and the edge character ++ ++Arguments: ++ ++ q - the parent node ++ c - the edge character ++ ++Returns: ++ ++ The child node (NIL if not found) ++ ++--*/ ++{ ++ NODE r; ++ ++ r = mNext[HASH(q, c)]; ++ mParent[NIL] = q; /* sentinel */ ++ while (mParent[r] != q) { ++ r = mNext[r]; ++ } ++ ++ return r; ++} ++ ++STATIC ++VOID ++MakeChild ( ++ IN NODE q, ++ IN UINT8 c, ++ IN NODE r ++ ) ++/*++ ++ ++Routine Description: ++ ++ Create a new child for a given parent node. ++ ++Arguments: ++ ++ q - the parent node ++ c - the edge character ++ r - the child node ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ NODE h, t; ++ ++ h = (NODE)HASH(q, c); ++ t = mNext[h]; ++ mNext[h] = r; ++ mNext[r] = t; ++ mPrev[t] = r; ++ mPrev[r] = h; ++ mParent[r] = q; ++ mChildCount[q]++; ++} ++ ++STATIC ++VOID ++Split ( ++ NODE Old ++ ) ++/*++ ++ ++Routine Description: ++ ++ Split a node. ++ ++Arguments: ++ ++ Old - the node to split ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ NODE New, t; ++ ++ New = mAvail; ++ mAvail = mNext[New]; ++ mChildCount[New] = 0; ++ t = mPrev[Old]; ++ mPrev[New] = t; ++ mNext[t] = New; ++ t = mNext[Old]; ++ mNext[New] = t; ++ mPrev[t] = New; ++ mParent[New] = mParent[Old]; ++ mLevel[New] = (UINT8)mMatchLen; ++ mPosition[New] = mPos; ++ MakeChild(New, mText[mMatchPos + mMatchLen], Old); ++ MakeChild(New, mText[mPos + mMatchLen], mPos); ++} ++ ++STATIC ++VOID ++InsertNode () ++/*++ ++ ++Routine Description: ++ ++ Insert string info for current position into the String Info Log ++ ++Arguments: (VOID) ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ NODE q, r, j, t; ++ UINT8 c, *t1, *t2; ++ ++ if (mMatchLen >= 4) { ++ ++ // ++ // We have just got a long match, the target tree ++ // can be located by MatchPos + 1. Travese the tree ++ // from bottom up to get to a proper starting point. ++ // The usage of PERC_FLAG ensures proper node deletion ++ // in DeleteNode() later. ++ // ++ ++ mMatchLen--; ++ r = (INT16)((mMatchPos + 1) | WNDSIZ); ++ while ((q = mParent[r]) == NIL) { ++ r = mNext[r]; ++ } ++ while (mLevel[q] >= mMatchLen) { ++ r = q; q = mParent[q]; ++ } ++ t = q; ++ while (mPosition[t] < 0) { ++ mPosition[t] = mPos; ++ t = mParent[t]; ++ } ++ if (t < WNDSIZ) { ++ mPosition[t] = (NODE)(mPos | PERC_FLAG); ++ } ++ } else { ++ ++ // ++ // Locate the target tree ++ // ++ ++ q = (INT16)(mText[mPos] + WNDSIZ); ++ c = mText[mPos + 1]; ++ if ((r = Child(q, c)) == NIL) { ++ MakeChild(q, c, mPos); ++ mMatchLen = 1; ++ return; ++ } ++ mMatchLen = 2; ++ } ++ ++ // ++ // Traverse down the tree to find a match. ++ // Update Position value along the route. ++ // Node split or creation is involved. ++ // ++ ++ for ( ; ; ) { ++ if (r >= WNDSIZ) { ++ j = MAXMATCH; ++ mMatchPos = r; ++ } else { ++ j = mLevel[r]; ++ mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG); ++ } ++ if (mMatchPos >= mPos) { ++ mMatchPos -= WNDSIZ; ++ } ++ t1 = &mText[mPos + mMatchLen]; ++ t2 = &mText[mMatchPos + mMatchLen]; ++ while (mMatchLen < j) { ++ if (*t1 != *t2) { ++ Split(r); ++ return; ++ } ++ mMatchLen++; ++ t1++; ++ t2++; ++ } ++ if (mMatchLen >= MAXMATCH) { ++ break; ++ } ++ mPosition[r] = mPos; ++ q = r; ++ if ((r = Child(q, *t1)) == NIL) { ++ MakeChild(q, *t1, mPos); ++ return; ++ } ++ mMatchLen++; ++ } ++ t = mPrev[r]; ++ mPrev[mPos] = t; ++ mNext[t] = mPos; ++ t = mNext[r]; ++ mNext[mPos] = t; ++ mPrev[t] = mPos; ++ mParent[mPos] = q; ++ mParent[r] = NIL; ++ ++ // ++ // Special usage of 'next' ++ // ++ mNext[r] = mPos; ++ ++} ++ ++STATIC ++VOID ++DeleteNode () ++/*++ ++ ++Routine Description: ++ ++ Delete outdated string info. (The Usage of PERC_FLAG ++ ensures a clean deletion) ++ ++Arguments: (VOID) ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ NODE q, r, s, t, u; ++ ++ if (mParent[mPos] == NIL) { ++ return; ++ } ++ ++ r = mPrev[mPos]; ++ s = mNext[mPos]; ++ mNext[r] = s; ++ mPrev[s] = r; ++ r = mParent[mPos]; ++ mParent[mPos] = NIL; ++ if (r >= WNDSIZ || --mChildCount[r] > 1) { ++ return; ++ } ++ t = (NODE)(mPosition[r] & ~PERC_FLAG); ++ if (t >= mPos) { ++ t -= WNDSIZ; ++ } ++ s = t; ++ q = mParent[r]; ++ while ((u = mPosition[q]) & PERC_FLAG) { ++ u &= ~PERC_FLAG; ++ if (u >= mPos) { ++ u -= WNDSIZ; ++ } ++ if (u > s) { ++ s = u; ++ } ++ mPosition[q] = (INT16)(s | WNDSIZ); ++ q = mParent[q]; ++ } ++ if (q < WNDSIZ) { ++ if (u >= mPos) { ++ u -= WNDSIZ; ++ } ++ if (u > s) { ++ s = u; ++ } ++ mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG); ++ } ++ s = Child(r, mText[t + mLevel[r]]); ++ t = mPrev[s]; ++ u = mNext[s]; ++ mNext[t] = u; ++ mPrev[u] = t; ++ t = mPrev[r]; ++ mNext[t] = s; ++ mPrev[s] = t; ++ t = mNext[r]; ++ mPrev[t] = s; ++ mNext[s] = t; ++ mParent[s] = mParent[r]; ++ mParent[r] = NIL; ++ mNext[r] = mAvail; ++ mAvail = r; ++} ++ ++STATIC ++VOID ++GetNextMatch () ++/*++ ++ ++Routine Description: ++ ++ Advance the current position (read in new data if needed). ++ Delete outdated string info. Find a match string for current position. ++ ++Arguments: (VOID) ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ INT32 n; ++ ++ mRemainder--; ++ if (++mPos == WNDSIZ * 2) { ++ memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); ++ n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); ++ mRemainder += n; ++ mPos = WNDSIZ; ++ } ++ DeleteNode(); ++ InsertNode(); ++} ++ ++STATIC ++EFI_STATUS ++Encode () ++/*++ ++ ++Routine Description: ++ ++ The main controlling routine for compression process. ++ ++Arguments: (VOID) ++ ++Returns: ++ ++ EFI_SUCCESS - The compression is successful ++ EFI_OUT_0F_RESOURCES - Not enough memory for compression process ++ ++--*/ ++{ ++ EFI_STATUS Status; ++ INT32 LastMatchLen; ++ NODE LastMatchPos; ++ ++ Status = AllocateMemory(); ++ if (EFI_ERROR(Status)) { ++ FreeMemory(); ++ return Status; ++ } ++ ++ InitSlide(); ++ ++ HufEncodeStart(); ++ ++ mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH); ++ ++ mMatchLen = 0; ++ mPos = WNDSIZ; ++ InsertNode(); ++ if (mMatchLen > mRemainder) { ++ mMatchLen = mRemainder; ++ } ++ while (mRemainder > 0) { ++ LastMatchLen = mMatchLen; ++ LastMatchPos = mMatchPos; ++ GetNextMatch(); ++ if (mMatchLen > mRemainder) { ++ mMatchLen = mRemainder; ++ } ++ ++ if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { ++ ++ // ++ // Not enough benefits are gained by outputting a pointer, ++ // so just output the original character ++ // ++ ++ Output(mText[mPos - 1], 0); ++ } else { ++ ++ // ++ // Outputting a pointer is beneficial enough, do it. ++ // ++ ++ Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), ++ (mPos - LastMatchPos - 2) & (WNDSIZ - 1)); ++ while (--LastMatchLen > 0) { ++ GetNextMatch(); ++ } ++ if (mMatchLen > mRemainder) { ++ mMatchLen = mRemainder; ++ } ++ } ++ } ++ ++ HufEncodeEnd(); ++ FreeMemory(); ++ return EFI_SUCCESS; ++} ++ ++STATIC ++VOID ++CountTFreq () ++/*++ ++ ++Routine Description: ++ ++ Count the frequencies for the Extra Set ++ ++Arguments: (VOID) ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ INT32 i, k, n, Count; ++ ++ for (i = 0; i < NT; i++) { ++ mTFreq[i] = 0; ++ } ++ n = NC; ++ while (n > 0 && mCLen[n - 1] == 0) { ++ n--; ++ } ++ i = 0; ++ while (i < n) { ++ k = mCLen[i++]; ++ if (k == 0) { ++ Count = 1; ++ while (i < n && mCLen[i] == 0) { ++ i++; ++ Count++; ++ } ++ if (Count <= 2) { ++ mTFreq[0] = (UINT16)(mTFreq[0] + Count); ++ } else if (Count <= 18) { ++ mTFreq[1]++; ++ } else if (Count == 19) { ++ mTFreq[0]++; ++ mTFreq[1]++; ++ } else { ++ mTFreq[2]++; ++ } ++ } else { ++ mTFreq[k + 2]++; ++ } ++ } ++} ++ ++STATIC ++VOID ++WritePTLen ( ++ IN INT32 n, ++ IN INT32 nbit, ++ IN INT32 Special ++ ) ++/*++ ++ ++Routine Description: ++ ++ Outputs the code length array for the Extra Set or the Position Set. ++ ++Arguments: ++ ++ n - the number of symbols ++ nbit - the number of bits needed to represent 'n' ++ Special - the special symbol that needs to be take care of ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ INT32 i, k; ++ ++ while (n > 0 && mPTLen[n - 1] == 0) { ++ n--; ++ } ++ PutBits(nbit, n); ++ i = 0; ++ while (i < n) { ++ k = mPTLen[i++]; ++ if (k <= 6) { ++ PutBits(3, k); ++ } else { ++ PutBits(k - 3, (1U << (k - 3)) - 2); ++ } ++ if (i == Special) { ++ while (i < 6 && mPTLen[i] == 0) { ++ i++; ++ } ++ PutBits(2, (i - 3) & 3); ++ } ++ } ++} ++ ++STATIC ++VOID ++WriteCLen () ++/*++ ++ ++Routine Description: ++ ++ Outputs the code length array for Char&Length Set ++ ++Arguments: (VOID) ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ INT32 i, k, n, Count; ++ ++ n = NC; ++ while (n > 0 && mCLen[n - 1] == 0) { ++ n--; ++ } ++ PutBits(CBIT, n); ++ i = 0; ++ while (i < n) { ++ k = mCLen[i++]; ++ if (k == 0) { ++ Count = 1; ++ while (i < n && mCLen[i] == 0) { ++ i++; ++ Count++; ++ } ++ if (Count <= 2) { ++ for (k = 0; k < Count; k++) { ++ PutBits(mPTLen[0], mPTCode[0]); ++ } ++ } else if (Count <= 18) { ++ PutBits(mPTLen[1], mPTCode[1]); ++ PutBits(4, Count - 3); ++ } else if (Count == 19) { ++ PutBits(mPTLen[0], mPTCode[0]); ++ PutBits(mPTLen[1], mPTCode[1]); ++ PutBits(4, 15); ++ } else { ++ PutBits(mPTLen[2], mPTCode[2]); ++ PutBits(CBIT, Count - 20); ++ } ++ } else { ++ PutBits(mPTLen[k + 2], mPTCode[k + 2]); ++ } ++ } ++} ++ ++STATIC ++VOID ++EncodeC ( ++ IN INT32 c ++ ) ++{ ++ PutBits(mCLen[c], mCCode[c]); ++} ++ ++STATIC ++VOID ++EncodeP ( ++ IN UINT32 p ++ ) ++{ ++ UINT32 c, q; ++ ++ c = 0; ++ q = p; ++ while (q) { ++ q >>= 1; ++ c++; ++ } ++ PutBits(mPTLen[c], mPTCode[c]); ++ if (c > 1) { ++ PutBits(c - 1, p & (0xFFFFU >> (17 - c))); ++ } ++} ++ ++STATIC ++VOID ++SendBlock () ++/*++ ++ ++Routine Description: ++ ++ Huffman code the block and output it. ++ ++Argument: (VOID) ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ UINT32 i, k, Flags, Root, Pos, Size; ++ Flags = 0; ++ ++ Root = MakeTree(NC, mCFreq, mCLen, mCCode); ++ Size = mCFreq[Root]; ++ PutBits(16, Size); ++ if (Root >= NC) { ++ CountTFreq(); ++ Root = MakeTree(NT, mTFreq, mPTLen, mPTCode); ++ if (Root >= NT) { ++ WritePTLen(NT, TBIT, 3); ++ } else { ++ PutBits(TBIT, 0); ++ PutBits(TBIT, Root); ++ } ++ WriteCLen(); ++ } else { ++ PutBits(TBIT, 0); ++ PutBits(TBIT, 0); ++ PutBits(CBIT, 0); ++ PutBits(CBIT, Root); ++ } ++ Root = MakeTree(NP, mPFreq, mPTLen, mPTCode); ++ if (Root >= NP) { ++ WritePTLen(NP, PBIT, -1); ++ } else { ++ PutBits(PBIT, 0); ++ PutBits(PBIT, Root); ++ } ++ Pos = 0; ++ for (i = 0; i < Size; i++) { ++ if (i % UINT8_BIT == 0) { ++ Flags = mBuf[Pos++]; ++ } else { ++ Flags <<= 1; ++ } ++ if (Flags & (1U << (UINT8_BIT - 1))) { ++ EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); ++ k = mBuf[Pos++] << UINT8_BIT; ++ k += mBuf[Pos++]; ++ EncodeP(k); ++ } else { ++ EncodeC(mBuf[Pos++]); ++ } ++ } ++ for (i = 0; i < NC; i++) { ++ mCFreq[i] = 0; ++ } ++ for (i = 0; i < NP; i++) { ++ mPFreq[i] = 0; ++ } ++} ++ ++ ++STATIC ++VOID ++Output ( ++ IN UINT32 c, ++ IN UINT32 p ++ ) ++/*++ ++ ++Routine Description: ++ ++ Outputs an Original Character or a Pointer ++ ++Arguments: ++ ++ c - The original character or the 'String Length' element of a Pointer ++ p - The 'Position' field of a Pointer ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ STATIC UINT32 CPos; ++ ++ if ((mOutputMask >>= 1) == 0) { ++ mOutputMask = 1U << (UINT8_BIT - 1); ++ if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { ++ SendBlock(); ++ mOutputPos = 0; ++ } ++ CPos = mOutputPos++; ++ mBuf[CPos] = 0; ++ } ++ mBuf[mOutputPos++] = (UINT8) c; ++ mCFreq[c]++; ++ if (c >= (1U << UINT8_BIT)) { ++ mBuf[CPos] |= mOutputMask; ++ mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT); ++ mBuf[mOutputPos++] = (UINT8) p; ++ c = 0; ++ while (p) { ++ p >>= 1; ++ c++; ++ } ++ mPFreq[c]++; ++ } ++} ++ ++STATIC ++VOID ++HufEncodeStart () ++{ ++ INT32 i; ++ ++ for (i = 0; i < NC; i++) { ++ mCFreq[i] = 0; ++ } ++ for (i = 0; i < NP; i++) { ++ mPFreq[i] = 0; ++ } ++ mOutputPos = mOutputMask = 0; ++ InitPutBits(); ++ return; ++} ++ ++STATIC ++VOID ++HufEncodeEnd () ++{ ++ SendBlock(); ++ ++ // ++ // Flush remaining bits ++ // ++ PutBits(UINT8_BIT - 1, 0); ++ ++ return; ++} ++ ++ ++STATIC ++VOID ++MakeCrcTable () ++{ ++ UINT32 i, j, r; ++ ++ for (i = 0; i <= UINT8_MAX; i++) { ++ r = i; ++ for (j = 0; j < UINT8_BIT; j++) { ++ if (r & 1) { ++ r = (r >> 1) ^ CRCPOLY; ++ } else { ++ r >>= 1; ++ } ++ } ++ mCrcTable[i] = (UINT16)r; ++ } ++} ++ ++STATIC ++VOID ++PutBits ( ++ IN INT32 n, ++ IN UINT32 x ++ ) ++/*++ ++ ++Routine Description: ++ ++ Outputs rightmost n bits of x ++ ++Argments: ++ ++ n - the rightmost n bits of the data is used ++ x - the data ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ UINT8 Temp; ++ ++ if (n < mBitCount) { ++ mSubBitBuf |= x << (mBitCount -= n); ++ } else { ++ ++ Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount))); ++ if (mDst < mDstUpperLimit) { ++ *mDst++ = Temp; ++ } ++ mCompSize++; ++ ++ if (n < UINT8_BIT) { ++ mSubBitBuf = x << (mBitCount = UINT8_BIT - n); ++ } else { ++ ++ Temp = (UINT8)(x >> (n - UINT8_BIT)); ++ if (mDst < mDstUpperLimit) { ++ *mDst++ = Temp; ++ } ++ mCompSize++; ++ ++ mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n); ++ } ++ } ++} ++ ++STATIC ++INT32 ++FreadCrc ( ++ OUT UINT8 *p, ++ IN INT32 n ++ ) ++/*++ ++ ++Routine Description: ++ ++ Read in source data ++ ++Arguments: ++ ++ p - the buffer to hold the data ++ n - number of bytes to read ++ ++Returns: ++ ++ number of bytes actually read ++ ++--*/ ++{ ++ INT32 i; ++ ++ for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) { ++ *p++ = *mSrc++; ++ } ++ n = i; ++ ++ p -= n; ++ mOrigSize += n; ++ while (--i >= 0) { ++ UPDATE_CRC(*p++); ++ } ++ return n; ++} ++ ++ ++STATIC ++VOID ++InitPutBits () ++{ ++ mBitCount = UINT8_BIT; ++ mSubBitBuf = 0; ++} ++ ++STATIC ++VOID ++CountLen ( ++ IN INT32 i ++ ) ++/*++ ++ ++Routine Description: ++ ++ Count the number of each code length for a Huffman tree. ++ ++Arguments: ++ ++ i - the top node ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ STATIC INT32 Depth = 0; ++ ++ if (i < mN) { ++ mLenCnt[(Depth < 16) ? Depth : 16]++; ++ } else { ++ Depth++; ++ CountLen(mLeft [i]); ++ CountLen(mRight[i]); ++ Depth--; ++ } ++} ++ ++STATIC ++VOID ++MakeLen ( ++ IN INT32 Root ++ ) ++/*++ ++ ++Routine Description: ++ ++ Create code length array for a Huffman tree ++ ++Arguments: ++ ++ Root - the root of the tree ++ ++--*/ ++{ ++ INT32 i, k; ++ UINT32 Cum; ++ ++ for (i = 0; i <= 16; i++) { ++ mLenCnt[i] = 0; ++ } ++ CountLen(Root); ++ ++ // ++ // Adjust the length count array so that ++ // no code will be generated longer than its designated length ++ // ++ ++ Cum = 0; ++ for (i = 16; i > 0; i--) { ++ Cum += mLenCnt[i] << (16 - i); ++ } ++ while (Cum != (1U << 16)) { ++ mLenCnt[16]--; ++ for (i = 15; i > 0; i--) { ++ if (mLenCnt[i] != 0) { ++ mLenCnt[i]--; ++ mLenCnt[i+1] += 2; ++ break; ++ } ++ } ++ Cum--; ++ } ++ for (i = 16; i > 0; i--) { ++ k = mLenCnt[i]; ++ while (--k >= 0) { ++ mLen[*mSortPtr++] = (UINT8)i; ++ } ++ } ++} ++ ++STATIC ++VOID ++DownHeap ( ++ IN INT32 i ++ ) ++{ ++ INT32 j, k; ++ ++ // ++ // priority queue: send i-th entry down heap ++ // ++ ++ k = mHeap[i]; ++ while ((j = 2 * i) <= mHeapSize) { ++ if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) { ++ j++; ++ } ++ if (mFreq[k] <= mFreq[mHeap[j]]) { ++ break; ++ } ++ mHeap[i] = mHeap[j]; ++ i = j; ++ } ++ mHeap[i] = (INT16)k; ++} ++ ++STATIC ++VOID ++MakeCode ( ++ IN INT32 n, ++ IN UINT8 Len[], ++ OUT UINT16 Code[] ++ ) ++/*++ ++ ++Routine Description: ++ ++ Assign code to each symbol based on the code length array ++ ++Arguments: ++ ++ n - number of symbols ++ Len - the code length array ++ Code - stores codes for each symbol ++ ++Returns: (VOID) ++ ++--*/ ++{ ++ INT32 i; ++ UINT16 Start[18]; ++ ++ Start[1] = 0; ++ for (i = 1; i <= 16; i++) { ++ Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1); ++ } ++ for (i = 0; i < n; i++) { ++ Code[i] = Start[Len[i]]++; ++ } ++} ++ ++STATIC ++INT32 ++MakeTree ( ++ IN INT32 NParm, ++ IN UINT16 FreqParm[], ++ OUT UINT8 LenParm[], ++ OUT UINT16 CodeParm[] ++ ) ++/*++ ++ ++Routine Description: ++ ++ Generates Huffman codes given a frequency distribution of symbols ++ ++Arguments: ++ ++ NParm - number of symbols ++ FreqParm - frequency of each symbol ++ LenParm - code length for each symbol ++ CodeParm - code for each symbol ++ ++Returns: ++ ++ Root of the Huffman tree. ++ ++--*/ ++{ ++ INT32 i, j, k, Avail; ++ ++ // ++ // make tree, calculate len[], return root ++ // ++ ++ mN = NParm; ++ mFreq = FreqParm; ++ mLen = LenParm; ++ Avail = mN; ++ mHeapSize = 0; ++ mHeap[1] = 0; ++ for (i = 0; i < mN; i++) { ++ mLen[i] = 0; ++ if (mFreq[i]) { ++ mHeap[++mHeapSize] = (INT16)i; ++ } ++ } ++ if (mHeapSize < 2) { ++ CodeParm[mHeap[1]] = 0; ++ return mHeap[1]; ++ } ++ for (i = mHeapSize / 2; i >= 1; i--) { ++ ++ // ++ // make priority queue ++ // ++ DownHeap(i); ++ } ++ mSortPtr = CodeParm; ++ do { ++ i = mHeap[1]; ++ if (i < mN) { ++ *mSortPtr++ = (UINT16)i; ++ } ++ mHeap[1] = mHeap[mHeapSize--]; ++ DownHeap(1); ++ j = mHeap[1]; ++ if (j < mN) { ++ *mSortPtr++ = (UINT16)j; ++ } ++ k = Avail++; ++ mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]); ++ mHeap[1] = (INT16)k; ++ DownHeap(1); ++ mLeft[k] = (UINT16)i; ++ mRight[k] = (UINT16)j; ++ } while (mHeapSize > 1); ++ ++ mSortPtr = CodeParm; ++ MakeLen(k); ++ MakeCode(NParm, LenParm, CodeParm); ++ ++ // ++ // return root ++ // ++ return k; ++} ++ +diff --git a/EfiRom/Common/EfiUtilityMsgs.c b/EfiRom/Common/EfiUtilityMsgs.c +new file mode 100644 +index 0000000..bf837f7 +--- /dev/null ++++ b/EfiRom/Common/EfiUtilityMsgs.c +@@ -0,0 +1,906 @@ ++/** @file ++EFI tools utility functions to display warning, error, and informational messages ++ ++Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++--*/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "EfiUtilityMsgs.h" ++ ++// ++// Declare module globals for keeping track of the the utility's ++// name and other settings. ++// ++STATIC STATUS mStatus = STATUS_SUCCESS; ++STATIC CHAR8 mUtilityName[50] = { 0 }; ++STATIC 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 ++ utilty name (as set by the utility calling SetUtilityName() ++ earlier) is used. Otherwise "Unknown utility" is used. ++ ++ LineNumber - the line number of error, typically used by parsers. If the ++ utility is not a parser, then 0 should be specified. Otherwise ++ the FileName and LineNumber info can be used to cause ++ MS Visual Studio to jump to the error. ++ ++ MessageCode - an application-specific error code that can be referenced in ++ other documentation. ++ ++ Text - the text in question, typically used by parsers. ++ ++ MsgFmt - the format string for the error message. Can contain formatting ++ controls for use with the varargs. ++ ++Returns: ++ None. ++ ++Notes: ++ We print the following (similar to the Warn() and Debug() ++ W ++ Typical error/warning message format: ++ ++ bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters ++ ++ BUGBUG -- these three utility functions are almost identical, and ++ should be modified to share code. ++ ++ Visual Studio does not find error messages with: ++ ++ " error :" ++ " error 1:" ++ " error c1:" ++ " error 1000:" ++ " error c100:" ++ ++ It does find: ++ " error c1000:" ++--*/ ++{ ++ va_list List; ++ // ++ // If limits have been set, then check that we have not exceeded them ++ // ++ if (mPrintLimitsSet) { ++ // ++ // See if we've exceeded our total count ++ // ++ if (mMaxWarningsPlusErrors != 0) { ++ if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { ++ PrintLimitExceeded (); ++ return ; ++ } ++ } ++ // ++ // See if we've exceeded our error count ++ // ++ if (mMaxErrors != 0) { ++ if (mErrorCount > mMaxErrors) { ++ PrintLimitExceeded (); ++ return ; ++ } ++ } ++ } ++ ++ mErrorCount++; ++ va_start (List, MsgFmt); ++ PrintMessage ("ERROR", FileName, LineNumber, MessageCode, Text, MsgFmt, List); ++ va_end (List); ++} ++ ++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 preceed the MessageCode value in the output string. ++ ++ FileName - name of the file where the warning was detected, or the name ++ of the application that detected the warning ++ ++ LineNumber - the line number where the warning was detected (parsers). ++ 0 should be specified if the utility is not a parser. ++ ++ MessageCode - an application-specific warning code that can be referenced in ++ other documentation. ++ ++ Text - part of the message to print ++ ++ MsgFmt - the format string for the message. Can contain formatting ++ controls for use with varargs. ++ List - the variable list. ++ ++Returns: ++ None. ++ ++Notes: ++ If FileName == NULL then this utility will use the string passed into SetUtilityName(). ++ ++ LineNumber is only used if the caller is a parser, in which case FileName refers to the ++ file being parsed. ++ ++ Text and MsgFmt are both optional, though it would be of little use calling this function with ++ them both NULL. ++ ++ Output will typically be of the form: ++ () : : : ++ ++ Parser (LineNumber != 0) ++ VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters ++ Generic utility (LineNumber == 0) ++ UtilityName : error E1234 : Text string : MsgFmt string and args ++ ++--*/ ++{ ++ CHAR8 Line[MAX_LINE_LEN]; ++ CHAR8 Line2[MAX_LINE_LEN]; ++ CHAR8 *Cptr; ++ struct tm *NewTime; ++ time_t CurrentTime; ++ ++ // ++ // init local variable ++ // ++ Line[0] = '\0'; ++ Line2[0] = '\0'; ++ ++ // ++ // If given a filename, then add it (and the line number) to the string. ++ // If there's no filename, then use the program name if provided. ++ // ++ if (FileName != NULL) { ++ Cptr = FileName; ++ } else { ++ Cptr = NULL; ++ } ++ ++ if (strcmp (Type, "DEBUG") == 0) { ++ // ++ // Debug Message requires current time. ++ // ++ time (&CurrentTime); ++ NewTime = localtime (&CurrentTime); ++ fprintf (stdout, "%04d-%02d-%02d %02d:%02d:%02d", ++ NewTime->tm_year + 1900, ++ NewTime->tm_mon + 1, ++ NewTime->tm_mday, ++ NewTime->tm_hour, ++ NewTime->tm_min, ++ NewTime->tm_sec ++ ); ++ if (Cptr != NULL) { ++ sprintf (Line, ": %s", Cptr); ++ if (LineNumber != 0) { ++ sprintf (Line2, "(%u)", (unsigned) LineNumber); ++ strcat (Line, Line2); ++ } ++ } ++ } else { ++ // ++ // Error and Warning Information. ++ // ++ if (Cptr != NULL) { ++ if (mUtilityName[0] != '\0') { ++ fprintf (stdout, "%s...\n", mUtilityName); ++ } ++ sprintf (Line, "%s", Cptr); ++ if (LineNumber != 0) { ++ sprintf (Line2, "(%u)", (unsigned) LineNumber); ++ strcat (Line, Line2); ++ } ++ } else { ++ if (mUtilityName[0] != '\0') { ++ sprintf (Line, "%s", mUtilityName); ++ } ++ } ++ ++ 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. ++ // ++ if (MessageCode != 0) { ++ sprintf (Line2, ": %s %04u", Type, (unsigned) MessageCode); ++ } else { ++ sprintf (Line2, ": %s", Type); ++ } ++ strcat (Line, Line2); ++ fprintf (stdout, "%s", Line); ++ // ++ // If offending text was provided, then print it ++ // ++ if (Text != NULL) { ++ fprintf (stdout, ": %s", Text); ++ } ++ fprintf (stdout, "\n"); ++ ++ // ++ // Print formatted message if provided ++ // ++ if (MsgFmt != NULL) { ++ vsprintf (Line2, MsgFmt, List); ++ fprintf (stdout, " %s\n", Line2); ++ } ++ ++} ++ ++STATIC ++VOID ++PrintSimpleMessage ( ++ CHAR8 *MsgFmt, ++ va_list List ++ ) ++/*++ ++Routine Description: ++ Print message into stdout. ++ ++Arguments: ++ MsgFmt - the format string for the message. Can contain formatting ++ controls for use with varargs. ++ List - the variable list. ++ ++Returns: ++ None. ++--*/ ++{ ++ CHAR8 Line[MAX_LINE_LEN]; ++ // ++ // Print formatted message if provided ++ // ++ if (MsgFmt != NULL) { ++ vsprintf (Line, MsgFmt, List); ++ fprintf (stdout, "%s\n", Line); ++ } ++} ++ ++VOID ++ParserSetPosition ( ++ CHAR8 *SourceFileName, ++ UINT32 LineNum ++ ) ++/*++ ++ ++Routine Description: ++ Set the position in a file being parsed. This can be used to ++ print error messages deeper down in a parser. ++ ++Arguments: ++ SourceFileName - name of the source file being parsed ++ LineNum - line number of the source file being parsed ++ ++Returns: ++ NA ++ ++--*/ ++{ ++ mSourceFileName = SourceFileName; ++ mSourceFileLineNum = LineNum; ++} ++ ++VOID ++SetUtilityName ( ++ CHAR8 *UtilityName ++ ) ++/*++ ++ ++Routine Description: ++ All printed error/warning/debug messages follow the same format, and ++ typically will print a filename or utility name followed by the error ++ text. However if a filename is not passed to the print routines, then ++ they'll print the utility name if you call this function early in your ++ app to set the utility name. ++ ++Arguments: ++ UtilityName - name of the utility, which will be printed with all ++ error/warning/debug messags. ++ ++Returns: ++ NA ++ ++--*/ ++{ ++ // ++ // Save the name of the utility in our local variable. Make sure its ++ // length does not exceed our buffer. ++ // ++ if (UtilityName != NULL) { ++ if (strlen (UtilityName) >= sizeof (mUtilityName)) { ++ Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size"); ++ strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1); ++ mUtilityName[sizeof (mUtilityName) - 1] = 0; ++ return ; ++ } else { ++ strcpy (mUtilityName, UtilityName); ++ } ++ } else { ++ Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name"); ++ } ++} ++ ++STATUS ++GetUtilityStatus ( ++ VOID ++ ) ++/*++ ++ ++Routine Description: ++ When you call Error() or Warning(), this module keeps track of it and ++ sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility ++ exits, it can call this function to get the status and use it as a return ++ value. ++ ++Arguments: ++ None. ++ ++Returns: ++ Worst-case status reported, as defined by which print function was called. ++ ++--*/ ++{ ++ return mStatus; ++} ++ ++VOID ++SetPrintLevel ( ++ 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/EfiRom/Common/EfiUtilityMsgs.h b/EfiRom/Common/EfiUtilityMsgs.h +new file mode 100644 +index 0000000..90aa530 +--- /dev/null ++++ b/EfiRom/Common/EfiUtilityMsgs.h +@@ -0,0 +1,170 @@ ++/** @file ++Defines and prototypes for common EFI utility error and debug messages. ++ ++Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _EFI_UTILITY_MSGS_H_ ++#define _EFI_UTILITY_MSGS_H_ ++ ++#include ++ ++// ++// 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/EfiRom/Common/MemoryFile.h b/EfiRom/Common/MemoryFile.h +new file mode 100644 +index 0000000..5ce4095 +--- /dev/null ++++ b/EfiRom/Common/MemoryFile.h +@@ -0,0 +1,111 @@ ++/** @file ++Header file for helper functions useful for accessing files. ++ ++Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _EFI_MEMORY_FILE_H ++#define _EFI_MEMORY_FILE_H ++ ++#include ++#include ++#include ++ ++// ++// 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/EfiRom/Common/ParseInf.c b/EfiRom/Common/ParseInf.c +new file mode 100644 +index 0000000..08460be +--- /dev/null ++++ b/EfiRom/Common/ParseInf.c +@@ -0,0 +1,701 @@ ++/** @file ++This contains some useful functions for parsing INF files. ++ ++Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include ++#include ++#include ++#include ++#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 Occurrance; ++ ++ // ++ // Check input parameters ++ // ++ if (InputFile->FileImage == NULL || ++ InputFile->Eof == NULL || ++ InputFile->CurrentFilePointer == NULL || ++ Section == NULL || ++ strlen (Section) == 0 || ++ Token == NULL || ++ strlen (Token) == 0 || ++ Value == NULL ++ ) { ++ return EFI_INVALID_PARAMETER; ++ } ++ // ++ // Initialize error codes ++ // ++ ParseError = FALSE; ++ ReadError = FALSE; ++ ++ // ++ // Initialize our instance counter for the search token ++ // ++ Occurrance = 0; ++ ++ if (FindSection (InputFile, Section)) { ++ // ++ // Found the desired section, find and read the desired token ++ // ++ do { ++ // ++ // Read a line from the file ++ // ++ if (ReadLine (InputFile, InputBuffer, MAX_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 == Occurrance) { ++ // ++ // 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 occurrance found ++ // ++ Occurrance++; ++ } ++ } ++ } while ( ++ !ParseError && ++ !ReadError && ++ InputFile->CurrentFilePointer < InputFile->Eof && ++ CurrentToken[0] != '[' && ++ Occurrance <= Instance ++ ); ++ } ++ // ++ // Distinguish between read errors and INF file format errors. ++ // ++ if (ReadError) { ++ return EFI_LOAD_ERROR; ++ } ++ ++ if (ParseError) { ++ return EFI_ABORTED; ++ } ++ ++ return EFI_NOT_FOUND; ++} ++ ++EFI_STATUS ++StringToGuid ( ++ IN CHAR8 *AsciiGuidBuffer, ++ OUT EFI_GUID *GuidBuffer ++ ) ++/*++ ++ ++Routine Description: ++ ++ Converts a string to an EFI_GUID. The string must be in the ++ xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format. ++ ++Arguments: ++ ++ AsciiGuidBuffer - pointer to ascii string ++ GuidBuffer - pointer to destination Guid ++ ++Returns: ++ ++ EFI_ABORTED Could not convert the string ++ EFI_SUCCESS The string was successfully converted ++ EFI_INVALID_PARAMETER Input parameter is invalid. ++ ++--*/ ++{ ++ INT32 Index; ++ unsigned Data1; ++ unsigned Data2; ++ unsigned Data3; ++ unsigned 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 preceeded by a 0x, but may not be ++ succeeded by an h. A number without 0x or 0X is considered to be base 10 ++ unless the IsHex input is true. ++ ++Arguments: ++ ++ AsciiString The string to convert. ++ IsHex Force the string to be treated as a hex number. ++ ReturnValue The return value. ++ ++Returns: ++ ++ EFI_SUCCESS Number successfully converted. ++ EFI_ABORTED Invalid character encountered. ++ ++--*/ ++{ ++ UINT8 Index; ++ UINT64 Value; ++ CHAR8 CurrentChar; ++ ++ // ++ // Initialize the result ++ // ++ Value = 0; ++ Index = 0; ++ ++ // ++ // Check input paramter ++ // ++ if (AsciiString == NULL || ReturnValue == NULL) { ++ 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/EfiRom/Common/ParseInf.h b/EfiRom/Common/ParseInf.h +new file mode 100644 +index 0000000..9c2821d +--- /dev/null ++++ b/EfiRom/Common/ParseInf.h +@@ -0,0 +1,226 @@ ++/** @file ++Header file for helper functions useful for parsing INF files. ++ ++Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _EFI_PARSE_INF_H ++#define _EFI_PARSE_INF_H ++ ++#include ++#include ++#include ++#include ++ ++#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 preceeded by a 0x, but may not be ++ succeeded by an h. A number without 0x or 0X is considered to be base 10 ++ unless the IsHex input is true. ++ ++Arguments: ++ ++ AsciiString The string to convert. ++ IsHex Force the string to be treated as a hex number. ++ ReturnValue The return value. ++ ++Returns: ++ ++ EFI_SUCCESS Number successfully converted. ++ EFI_ABORTED Invalid character encountered. ++ ++--*/ ++CHAR8 * ++ReadLineInStream ( ++ IN FILE *InputFile, ++ IN OUT CHAR8 *InputBuffer ++ ) ++; ++ ++/*++ ++ ++Routine Description: ++ ++ This function reads a line, stripping any comments. ++ ++Arguments: ++ ++ InputFile Stream pointer. ++ InputBuffer Buffer to read into, must be MAX_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/EfiRom/EfiRom.c b/EfiRom/EfiRom.c +new file mode 100644 +index 0000000..a5d1926 +--- /dev/null ++++ b/EfiRom/EfiRom.c +@@ -0,0 +1,1564 @@ ++/** @file ++Utility program to create an EFI option ROM image from binary and EFI PE32 files. ++ ++Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials are licensed and made available ++under the terms and conditions of the BSD License which accompanies this ++distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#include "EfiUtilityMsgs.h" ++#include "ParseInf.h" ++#include "EfiRom.h" ++ ++UINT64 DebugLevel = 0; ++ ++int ++main ( ++ int Argc, ++ char *Argv[] ++ ) ++/*++ ++ ++Routine Description: ++ ++ Given an EFI image filename, create a ROM-able image by creating an option ++ ROM header and PCI data structure, filling them in, and then writing the ++ option ROM header + PCI data structure + EFI image out to the output file. ++ ++Arguments: ++ ++ Argc - standard C main() argument count ++ ++ Argv - standard C main() argument list ++ ++Returns: ++ ++ 0 success ++ non-zero otherwise ++ ++--*/ ++{ ++ CHAR8 *Ext; ++ FILE *FptrOut; ++ UINT32 Status; ++ FILE_LIST *FList; ++ UINT32 TotalSize; ++ UINT32 Size; ++ CHAR8 *Ptr0; ++ ++ SetUtilityName(UTILITY_NAME); ++ ++ Status = STATUS_SUCCESS; ++ FptrOut = NULL; ++ ++ // ++ // Parse the command line arguments ++ // ++ if (ParseCommandLine (Argc, Argv, &mOptions)) { ++ return STATUS_ERROR; ++ } ++ ++ if (mOptions.Quiet) { ++ SetPrintLevel(40); ++ } else if (mOptions.Verbose) { ++ SetPrintLevel(15); ++ } else if (mOptions.Debug) { ++ SetPrintLevel(DebugLevel); ++ } ++ ++ if (mOptions.Verbose) { ++ VerboseMsg("%s tool start.\n", UTILITY_NAME); ++ } ++ ++ // ++ // If dumping an image, then do that and quit ++ // ++ if (mOptions.DumpOption == 1) { ++ if (mOptions.FileList != NULL) { ++ if ((Ptr0 = strstr ((CONST CHAR8 *) mOptions.FileList->FileName, DEFAULT_OUTPUT_EXTENSION)) != NULL) { ++ DumpImage (mOptions.FileList); ++ goto BailOut; ++ } else { ++ Error (NULL, 0, 1002, "No PciRom input file", "No *.rom input file"); ++ goto BailOut; ++ } ++ } ++ } ++ // ++ // Determine the output filename. Either what they specified on ++ // the command line, or the first input filename with a different extension. ++ // ++ if (!mOptions.OutFileName[0]) { ++ strcpy (mOptions.OutFileName, mOptions.FileList->FileName); ++ // ++ // Find the last . on the line and replace the filename extension with ++ // the default ++ // ++ for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1; ++ (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\'); ++ Ext-- ++ ) ++ ; ++ // ++ // If dot here, then insert extension here, otherwise append ++ // ++ if (*Ext != '.') { ++ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName); ++ } ++ ++ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION); ++ } ++ // ++ // Make sure we don't have the same filename for input and output files ++ // ++ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) { ++ if (stricmp (mOptions.OutFileName, FList->FileName) == 0) { ++ Status = STATUS_ERROR; ++ Error (NULL, 0, 1002, "Invalid input paramter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName); ++ goto BailOut; ++ } ++ } ++ // ++ // Now open our output file ++ // ++ if ((FptrOut = fopen (LongFilePath (mOptions.OutFileName), "wb")) == NULL) { ++ Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", mOptions.OutFileName); ++ goto BailOut; ++ } ++ // ++ // Process all our files ++ // ++ TotalSize = 0; ++ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) { ++ Size = 0; ++ if ((FList->FileFlags & FILE_FLAG_EFI) != 0) { ++ if (mOptions.Verbose) { ++ VerboseMsg("Processing EFI file %s\n", FList->FileName); ++ } ++ ++ Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size); ++ } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) { ++ if (mOptions.Verbose) { ++ VerboseMsg("Processing binary file %s\n", FList->FileName); ++ } ++ ++ Status = ProcessBinFile (FptrOut, FList, &Size); ++ } else { ++ Error (NULL, 0, 2000, "Invalid parameter", "File type not specified, it must be either an EFI or binary file: %s.", FList->FileName); ++ Status = STATUS_ERROR; ++ } ++ ++ if (mOptions.Verbose) { ++ VerboseMsg(" Output size = 0x%X\n", (unsigned) Size); ++ } ++ ++ if (Status != STATUS_SUCCESS) { ++ break; ++ } ++ ++ TotalSize += Size; ++ } ++ // ++ // Check total size ++ // ++ if (TotalSize > MAX_OPTION_ROM_SIZE) { ++ Error (NULL, 0, 2000, "Invalid paramter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE); ++ Status = STATUS_ERROR; ++ } ++ ++BailOut: ++ if (Status == STATUS_SUCCESS) { ++ if (FptrOut != NULL) { ++ fclose (FptrOut); ++ } ++ // ++ // Clean up our file list ++ // ++ while (mOptions.FileList != NULL) { ++ FList = mOptions.FileList->Next; ++ free (mOptions.FileList); ++ mOptions.FileList = FList; ++ } ++ } ++ ++ if (mOptions.Verbose) { ++ VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); ++ } ++ ++ return GetUtilityStatus (); ++} ++ ++static ++int ++ProcessBinFile ( ++ FILE *OutFptr, ++ FILE_LIST *InFile, ++ UINT32 *Size ++ ) ++/*++ ++ ++Routine Description: ++ ++ Process a binary input file. ++ ++Arguments: ++ ++ OutFptr - file pointer to output binary ROM image file we're creating ++ InFile - structure contains information on the binary file to process ++ Size - pointer to where to return the size added to the output file ++ ++Returns: ++ ++ 0 - successful ++ ++--*/ ++{ ++ FILE *InFptr; ++ UINT32 TotalSize; ++ UINT32 FileSize; ++ UINT8 *Buffer; ++ UINT32 Status; ++ PCI_EXPANSION_ROM_HEADER *RomHdr; ++ PCI_DATA_STRUCTURE *PciDs23; ++ PCI_3_0_DATA_STRUCTURE *PciDs30; ++ UINT32 Index; ++ UINT8 ByteCheckSum; ++ UINT16 CodeType; ++ ++ PciDs23 = NULL; ++ PciDs30 = NULL; ++ Status = STATUS_SUCCESS; ++ ++ // ++ // Try to open the input file ++ // ++ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) { ++ Error (NULL, 0, 0001, "Error opening file", InFile->FileName); ++ return STATUS_ERROR; ++ } ++ // ++ // Seek to the end of the input file and get the file size. Then allocate ++ // a buffer to read it in to. ++ // ++ fseek (InFptr, 0, SEEK_END); ++ FileSize = ftell (InFptr); ++ if (mOptions.Verbose) { ++ VerboseMsg(" File size = 0x%X\n", (unsigned) FileSize); ++ } ++ ++ fseek (InFptr, 0, SEEK_SET); ++ Buffer = (UINT8 *) malloc (FileSize); ++ if (Buffer == NULL) { ++ Error (NULL, 0, 4003, "Resource", "memory cannot be allocated!"); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ if (fread (Buffer, FileSize, 1, InFptr) != 1) { ++ Error (NULL, 0, 2000, "Invalid", "Failed to read all bytes from input file."); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ // ++ // Total size must be an even multiple of 512 bytes, and can't exceed ++ // the option ROM image size. ++ // ++ TotalSize = FileSize; ++ if (TotalSize & 0x1FF) { ++ TotalSize = (TotalSize + 0x200) &~0x1ff; ++ } ++ ++ if (TotalSize > MAX_OPTION_ROM_SIZE) { ++ Error (NULL, 0, 3001, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ // ++ // Return the size to the caller so they can keep track of the running total. ++ // ++ *Size = TotalSize; ++ ++ // ++ // Crude check to make sure it's a legitimate ROM image ++ // ++ RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer; ++ if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { ++ Error (NULL, 0, 2000, "Invalid parameter", "ROM image file has an invalid ROM signature."); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ // ++ // Make sure the pointer to the PCI data structure is within the size of the image. ++ // Then check it for valid signature. ++ // ++ if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) { ++ Error (NULL, 0, 2000, "Invalid parameter", "Invalid PCI data structure offset."); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ // ++ // Check the header is conform to PCI2.3 or PCI3.0 ++ // ++ if (mOptions.Pci23 == 1) { ++ PciDs23 = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset); ++ if (PciDs23->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { ++ Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature."); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ } else { ++ // ++ // Default setting is PCI3.0 header ++ // ++ PciDs30 = (PCI_3_0_DATA_STRUCTURE *)(Buffer + RomHdr->PcirOffset); ++ if (PciDs30->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { ++ Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature."); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ } ++ ++ // ++ // ReSet Option Rom size ++ // ++ if (mOptions.Pci23 == 1) { ++ PciDs23->ImageLength = (UINT16) (TotalSize / 512); ++ CodeType = PciDs23->CodeType; ++ } else { ++ PciDs30->ImageLength = (UINT16) (TotalSize / 512); ++ CodeType = PciDs30->CodeType; ++ } ++ ++ // ++ // If this is the last image, then set the LAST bit unless requested not ++ // to via the command-line -n argument. Otherwise, make sure you clear it. ++ // ++ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { ++ if (mOptions.Pci23 == 1) { ++ PciDs23->Indicator = INDICATOR_LAST; ++ } else { ++ PciDs30->Indicator = INDICATOR_LAST; ++ } ++ } else { ++ if (mOptions.Pci23 == 1) { ++ PciDs23->Indicator = 0; ++ } else { ++ PciDs30->Indicator = 0; ++ } ++ } ++ ++ if (CodeType != PCI_CODE_TYPE_EFI_IMAGE) { ++ ByteCheckSum = 0; ++ for (Index = 0; Index < FileSize - 1; Index++) { ++ ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]); ++ } ++ ++ Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1); ++ if (mOptions.Verbose) { ++ VerboseMsg(" Checksum = %02x\n\n", Buffer[FileSize - 1]); ++ } ++ } ++ ++ // ++ // Now copy the input file contents out to the output file ++ // ++ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { ++ Error (NULL, 0, 0005, "Failed to write all file bytes to output file.", NULL); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ TotalSize -= FileSize; ++ // ++ // Pad the rest of the image to make it a multiple of 512 bytes ++ // ++ while (TotalSize > 0) { ++ putc (~0, OutFptr); ++ TotalSize--; ++ } ++ ++BailOut: ++ if (InFptr != NULL) { ++ fclose (InFptr); ++ } ++ ++ if (Buffer != NULL) { ++ free (Buffer); ++ } ++ // ++ // Print the file name if errors occurred ++ // ++ if (Status != STATUS_SUCCESS) { ++ Error (NULL, 0, 0003, "Error", "Error parsing file: %s", InFile->FileName); ++ } ++ ++ return Status; ++} ++ ++static ++int ++ProcessEfiFile ( ++ FILE *OutFptr, ++ FILE_LIST *InFile, ++ UINT16 VendId, ++ UINT16 DevId, ++ UINT32 *Size ++ ) ++/*++ ++ ++Routine Description: ++ ++ Process a PE32 EFI file. ++ ++Arguments: ++ ++ OutFptr - file pointer to output binary ROM image file we're creating ++ InFile - structure contains information on the PE32 file to process ++ VendId - vendor ID as required in the option ROM header ++ DevId - device ID as required in the option ROM header ++ Size - pointer to where to return the size added to the output file ++ ++Returns: ++ ++ 0 - successful ++ ++--*/ ++{ ++ UINT32 Status; ++ FILE *InFptr; ++ EFI_PCI_EXPANSION_ROM_HEADER RomHdr; ++ PCI_DATA_STRUCTURE PciDs23; ++ PCI_3_0_DATA_STRUCTURE PciDs30; ++ UINT32 FileSize; ++ UINT32 CompressedFileSize; ++ UINT8 *Buffer; ++ UINT8 *CompressedBuffer; ++ UINT8 *TempBufferPtr; ++ UINT32 TotalSize; ++ UINT32 HeaderSize; ++ UINT16 MachineType; ++ UINT16 SubSystem; ++ UINT32 HeaderPadBytes; ++ UINT32 PadBytesBeforeImage; ++ UINT32 PadBytesAfterImage; ++ ++ // ++ // Try to open the input file ++ // ++ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) { ++ Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", InFile->FileName); ++ return STATUS_ERROR; ++ } ++ // ++ // Initialize our buffer pointers to null. ++ // ++ Buffer = NULL; ++ CompressedBuffer = NULL; ++ ++ // ++ // Double-check the file to make sure it's what we expect it to be ++ // ++ Status = CheckPE32File (InFptr, &MachineType, &SubSystem); ++ if (Status != STATUS_SUCCESS) { ++ goto BailOut; ++ } ++ // ++ // Seek to the end of the input file and get the file size ++ // ++ fseek (InFptr, 0, SEEK_END); ++ FileSize = ftell (InFptr); ++ ++ // ++ // Get the size of the headers we're going to put in front of the image. The ++ // EFI header must be aligned on a 4-byte boundary, so pad accordingly. ++ // ++ if (sizeof (RomHdr) & 0x03) { ++ HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03); ++ } else { ++ HeaderPadBytes = 0; ++ } ++ ++ // ++ // For Pci3.0 to use the different data structure. ++ // ++ if (mOptions.Pci23 == 1) { ++ HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); ++ } else { ++ HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); ++ } ++ ++ if (mOptions.Verbose) { ++ VerboseMsg(" File size = 0x%X\n", (unsigned) FileSize); ++ } ++ // ++ // Allocate memory for the entire file (in case we have to compress), then ++ // seek back to the beginning of the file and read it into our buffer. ++ // ++ Buffer = (UINT8 *) malloc (FileSize); ++ if (Buffer == NULL) { ++ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ fseek (InFptr, 0, SEEK_SET); ++ if (fread (Buffer, FileSize, 1, InFptr) != 1) { ++ Error (NULL, 0, 0004, "Error reading file", "File %s", InFile->FileName); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ // ++ // Now determine the size of the final output file. It's either the header size ++ // plus the file's size, or the header size plus the compressed file size. ++ // ++ if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) { ++ // ++ // Allocate a buffer into which we can compress the image, compress it, ++ // and use that size as the new size. ++ // ++ CompressedBuffer = (UINT8 *) malloc (FileSize); ++ if (CompressedBuffer == NULL) { ++ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ CompressedFileSize = FileSize; ++ Status = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize); ++ if (Status != STATUS_SUCCESS) { ++ Error (NULL, 0, 0007, "Error compressing file!", NULL); ++ goto BailOut; ++ } ++ // ++ // Now compute the size, then swap buffer pointers. ++ // ++ if (mOptions.Verbose) { ++ VerboseMsg(" Comp size = 0x%X\n", (unsigned) CompressedFileSize); ++ } ++ ++ TotalSize = CompressedFileSize + HeaderSize; ++ FileSize = CompressedFileSize; ++ TempBufferPtr = Buffer; ++ Buffer = CompressedBuffer; ++ CompressedBuffer = TempBufferPtr; ++ } else { ++ TotalSize = FileSize + HeaderSize; ++ } ++ // ++ // Total size must be an even multiple of 512 bytes ++ // ++ if (TotalSize & 0x1FF) { ++ TotalSize = (TotalSize + 0x200) &~0x1ff; ++ } ++ // ++ // Workaround: ++ // If compressed, put the pad bytes after the image, ++ // else put the pad bytes before the image. ++ // ++ if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) { ++ PadBytesBeforeImage = 0; ++ PadBytesAfterImage = TotalSize - (FileSize + HeaderSize); ++ } else { ++ PadBytesBeforeImage = TotalSize - (FileSize + HeaderSize); ++ PadBytesAfterImage = 0; ++ } ++ // ++ // Check size ++ // ++ if (TotalSize > MAX_OPTION_ROM_SIZE) { ++ Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ // ++ // Return the size to the caller so they can keep track of the running total. ++ // ++ *Size = TotalSize; ++ ++ // ++ // Now fill in the ROM header. These values come from chapter 18 of the ++ // EFI 1.02 specification. ++ // ++ memset (&RomHdr, 0, sizeof (RomHdr)); ++ RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE; ++ RomHdr.InitializationSize = (UINT16) (TotalSize / 512); ++ RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE; ++ RomHdr.EfiSubsystem = SubSystem; ++ RomHdr.EfiMachineType = MachineType; ++ RomHdr.EfiImageHeaderOffset = (UINT16) (HeaderSize + PadBytesBeforeImage); ++ RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes); ++ // ++ // Set image as compressed or not ++ // ++ if (InFile->FileFlags & FILE_FLAG_COMPRESS) { ++ RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED; ++ } ++ // ++ // Fill in the PCI data structure ++ // ++ if (mOptions.Pci23 == 1) { ++ memset (&PciDs23, 0, sizeof (PCI_DATA_STRUCTURE)); ++ } else { ++ memset (&PciDs30, 0, sizeof (PCI_3_0_DATA_STRUCTURE)); ++ } ++ ++ if (mOptions.Pci23 == 1) { ++ PciDs23.Signature = PCI_DATA_STRUCTURE_SIGNATURE; ++ PciDs23.VendorId = VendId; ++ PciDs23.DeviceId = DevId; ++ PciDs23.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE); ++ PciDs23.Revision = 0; ++ // ++ // Class code and code revision from the command line (optional) ++ // ++ PciDs23.ClassCode[0] = (UINT8) InFile->ClassCode; ++ PciDs23.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); ++ PciDs23.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); ++ PciDs23.ImageLength = RomHdr.InitializationSize; ++ PciDs23.CodeRevision = InFile->CodeRevision; ++ PciDs23.CodeType = PCI_CODE_TYPE_EFI_IMAGE; ++ } else { ++ PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE; ++ PciDs30.VendorId = VendId; ++ PciDs30.DeviceId = DevId; ++ PciDs30.DeviceListOffset = 0; // to be fixed ++ PciDs30.Length = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE); ++ PciDs30.Revision = 0x3; ++ // ++ // Class code and code revision from the command line (optional) ++ // ++ PciDs30.ClassCode[0] = (UINT8) InFile->ClassCode; ++ PciDs30.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); ++ PciDs30.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); ++ PciDs30.ImageLength = RomHdr.InitializationSize; ++ PciDs30.CodeRevision = InFile->CodeRevision; ++ PciDs30.CodeType = PCI_CODE_TYPE_EFI_IMAGE; ++ PciDs30.MaxRuntimeImageLength = 0; // to be fixed ++ PciDs30.ConfigUtilityCodeHeaderOffset = 0; // to be fixed ++ PciDs30.DMTFCLPEntryPointOffset = 0; // to be fixed ++ } ++ // ++ // If this is the last image, then set the LAST bit unless requested not ++ // to via the command-line -n argument. ++ // ++ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { ++ if (mOptions.Pci23 == 1) { ++ PciDs23.Indicator = INDICATOR_LAST; ++ } else { ++ PciDs30.Indicator = INDICATOR_LAST;} ++ } else { ++ if (mOptions.Pci23 == 1) { ++ PciDs23.Indicator = 0; ++ } else { ++ PciDs30.Indicator = 0; ++ } ++ } ++ // ++ // Write the ROM header to the output file ++ // ++ if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) { ++ Error (NULL, 0, 0002, "Failed to write ROM header to output file!", NULL); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ // ++ // Write pad bytes to align the PciDs ++ // ++ while (HeaderPadBytes > 0) { ++ if (putc (0, OutFptr) == EOF) { ++ Error (NULL, 0, 0002, "Failed to write ROM header pad bytes to output file!", NULL); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ HeaderPadBytes--; ++ } ++ // ++ // Write the PCI data structure header to the output file ++ // ++ if (mOptions.Pci23 == 1) { ++ if (fwrite (&PciDs23, sizeof (PciDs23), 1, OutFptr) != 1) { ++ Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ } else { ++ if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) { ++ Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ } ++ ++ // ++ // Pad head to make it a multiple of 512 bytes ++ // ++ while (PadBytesBeforeImage > 0) { ++ if (putc (~0, OutFptr) == EOF) { ++ Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ PadBytesBeforeImage--; ++ } ++ // ++ // Now dump the input file's contents to the output file ++ // ++ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { ++ Error (NULL, 0, 0002, "Failed to write all file bytes to output file!", NULL); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ // ++ // Pad the rest of the image to make it a multiple of 512 bytes ++ // ++ while (PadBytesAfterImage > 0) { ++ if (putc (~0, OutFptr) == EOF) { ++ Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL); ++ Status = STATUS_ERROR; ++ goto BailOut; ++ } ++ ++ PadBytesAfterImage--; ++ } ++ ++BailOut: ++ if (InFptr != NULL) { ++ fclose (InFptr); ++ } ++ // ++ // Free up our buffers ++ // ++ if (Buffer != NULL) { ++ free (Buffer); ++ } ++ ++ if (CompressedBuffer != NULL) { ++ free (CompressedBuffer); ++ } ++ // ++ // Print the file name if errors occurred ++ // ++ if (Status != STATUS_SUCCESS) { ++ Error (NULL, 0, 0003, "Error parsing", "Error parsing file: %s", InFile->FileName); ++ } ++ ++ return Status; ++} ++ ++static ++int ++CheckPE32File ( ++ FILE *Fptr, ++ UINT16 *MachineType, ++ UINT16 *SubSystem ++ ) ++/*++ ++ ++Routine Description: ++ ++ Given a file pointer to a supposed PE32 image file, verify that it is indeed a ++ PE32 image file, and then return the machine type in the supplied pointer. ++ ++Arguments: ++ ++ Fptr File pointer to the already-opened PE32 file ++ MachineType Location to stuff the machine type of the PE32 file. This is needed ++ because the image may be Itanium-based, IA32, or EBC. ++ ++Returns: ++ ++ 0 success ++ non-zero otherwise ++ ++--*/ ++{ ++ EFI_IMAGE_DOS_HEADER DosHeader; ++ EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr; ++ ++ // ++ // Position to the start of the file ++ // ++ fseek (Fptr, 0, SEEK_SET); ++ ++ // ++ // Read the DOS header ++ // ++ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) { ++ Error (NULL, 0, 0004, "Failed to read the DOS stub from the input file!", NULL); ++ return STATUS_ERROR; ++ } ++ // ++ // Check the magic number (0x5A4D) ++ // ++ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) { ++ Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (magic number)!"); ++ return STATUS_ERROR; ++ } ++ // ++ // Position into the file and check the PE signature ++ // ++ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET); ++ ++ // ++ // Read PE headers ++ // ++ if (fread (&PeHdr, sizeof (PeHdr), 1, Fptr) != 1) { ++ Error (NULL, 0, 0004, "Failed to read PE/COFF headers from input file!", NULL); ++ return STATUS_ERROR; ++ } ++ ++ ++ // ++ // Check the PE signature in the header "PE\0\0" ++ // ++ if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { ++ Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (signature)!"); ++ return STATUS_ERROR; ++ } ++ ++ memcpy ((char *) MachineType, &PeHdr.Pe32.FileHeader.Machine, 2); ++ ++ if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { ++ *SubSystem = PeHdr.Pe32.OptionalHeader.Subsystem; ++ } else if (PeHdr.Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { ++ *SubSystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem; ++ } else { ++ Error (NULL, 0, 2000, "Invalid parameter", "Unable to find subsystem type!"); ++ return STATUS_ERROR; ++ } ++ ++ if (mOptions.Verbose) { ++ VerboseMsg(" Got subsystem = 0x%X from image\n", *SubSystem); ++ } ++ ++ // ++ // File was successfully identified as a PE32 ++ // ++ return STATUS_SUCCESS; ++} ++ ++static ++int ++ParseCommandLine ( ++ int Argc, ++ char *Argv[], ++ OPTIONS *Options ++ ) ++/*++ ++ ++Routine Description: ++ ++ Given the Argc/Argv program arguments, and a pointer to an options structure, ++ parse the command-line options and check their validity. ++ ++ ++Arguments: ++ ++ Argc - standard C main() argument count ++ Argv[] - standard C main() argument list ++ Options - pointer to a structure to store the options in ++ ++Returns: ++ ++ STATUS_SUCCESS success ++ non-zero otherwise ++ ++--*/ ++{ ++ FILE_LIST *FileList; ++ FILE_LIST *PrevFileList; ++ UINT32 FileFlags; ++ UINT32 ClassCode; ++ UINT32 CodeRevision; ++ EFI_STATUS Status; ++ BOOLEAN EfiRomFlag; ++ UINT64 TempValue; ++ ++ FileFlags = 0; ++ EfiRomFlag = FALSE; ++ ++ // ++ // Clear out the options ++ // ++ memset ((char *) Options, 0, sizeof (OPTIONS)); ++ ++ // ++ // To avoid compile warnings ++ // ++ FileList = PrevFileList = NULL; ++ ++ ClassCode = 0; ++ CodeRevision = 0; ++ // ++ // Skip over the program name ++ // ++ Argc--; ++ Argv++; ++ ++ // ++ // If no arguments, assume they want usage info ++ // ++ if (Argc == 0) { ++ Usage (); ++ return STATUS_ERROR; ++ } ++ ++ if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) { ++ Usage(); ++ return STATUS_ERROR; ++ } ++ ++ if ((stricmp(Argv[0], "--version") == 0)) { ++ Version(); ++ return STATUS_ERROR; ++ } ++ ++ // ++ // Process until no more arguments ++ // ++ while (Argc > 0) { ++ if (Argv[0][0] == '-') { ++ // ++ // Vendor ID specified with -f ++ // ++ if (stricmp (Argv[0], "-f") == 0) { ++ // ++ // Make sure there's another parameter ++ // ++ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); ++ if (EFI_ERROR (Status)) { ++ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); ++ return 1; ++ } ++ if (TempValue >= 0x10000) { ++ Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]); ++ return 1; ++ } ++ Options->VendId = (UINT16) TempValue; ++ Options->VendIdValid = 1; ++ ++ Argv++; ++ Argc--; ++ } else if (stricmp (Argv[0], "-i") == 0) { ++ // ++ // Device ID specified with -i ++ // Make sure there's another parameter ++ // ++ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); ++ if (EFI_ERROR (Status)) { ++ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); ++ return 1; ++ } ++ if (TempValue >= 0x10000) { ++ Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]); ++ return 1; ++ } ++ Options->DevId = (UINT16) TempValue; ++ Options->DevIdValid = 1; ++ ++ Argv++; ++ Argc--; ++ } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) { ++ // ++ // Output filename specified with -o ++ // Make sure there's another parameter ++ // ++ if (Argv[1] == NULL || Argv[1][0] == '-') { ++ Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]); ++ return STATUS_ERROR; ++ } ++ strcpy (Options->OutFileName, Argv[1]); ++ ++ Argv++; ++ Argc--; ++ } else if ((stricmp (Argv[0], "-h") == 0) || (stricmp (Argv[0], "--help") == 0)) { ++ // ++ // Help option ++ // ++ Usage (); ++ return STATUS_ERROR; ++ } else if (stricmp (Argv[0], "-b") == 0) { ++ // ++ // Specify binary files with -b ++ // ++ FileFlags = FILE_FLAG_BINARY; ++ } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) { ++ // ++ // Specify EFI files with -e. Specify EFI-compressed with -c. ++ // ++ FileFlags = FILE_FLAG_EFI; ++ if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) { ++ FileFlags |= FILE_FLAG_COMPRESS; ++ } ++ // ++ // Specify not to set the LAST bit in the last file with -n ++ // ++ } else if (stricmp (Argv[0], "-n") == 0) { ++ Options->NoLast = 1; ++ } else if (((stricmp (Argv[0], "-v") == 0)) || ((stricmp (Argv[0], "--verbose") == 0))) { ++ // ++ // -v for verbose ++ // ++ Options->Verbose = 1; ++ } else if (stricmp (Argv[0], "--debug") == 0) { ++ Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel); ++ if (EFI_ERROR (Status)) { ++ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); ++ return 1; ++ } ++ if (DebugLevel > 9) { ++ Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]); ++ return 1; ++ } ++ if (DebugLevel>=5 && DebugLevel<=9) { ++ Options->Debug = TRUE; ++ } else { ++ Options->Debug = FALSE; ++ } ++ Argv++; ++ Argc--; ++ } else if ((stricmp (Argv[0], "--quiet") == 0) || (stricmp (Argv[0], "-q") == 0)) { ++ Options->Quiet = TRUE; ++ } else if ((stricmp (Argv[0], "--dump") == 0) || (stricmp (Argv[0], "-d") == 0)) { ++ // ++ // -dump for dumping a ROM image. In this case, say that the device id ++ // and vendor id are valid so we don't have to specify bogus ones on the ++ // command line. ++ // ++ Options->DumpOption = 1; ++ ++ Options->VendIdValid = 1; ++ Options->DevIdValid = 1; ++ FileFlags = FILE_FLAG_BINARY; ++ } else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) { ++ // ++ // Class code value for the next file in the list. ++ // Make sure there's another parameter ++ // ++ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); ++ if (EFI_ERROR (Status)) { ++ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); ++ return 1; ++ } ++ ClassCode = (UINT32) TempValue; ++ if (ClassCode & 0xFF000000) { ++ Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]); ++ return STATUS_ERROR; ++ } ++ if (FileList != NULL && FileList->ClassCode == 0) { ++ FileList->ClassCode = ClassCode; ++ } ++ Argv++; ++ Argc--; ++ } else if ((stricmp (Argv[0], "-r") == 0) || (stricmp (Argv[0], "--Revision") == 0)) { ++ // ++ // Code revision in the PCI data structure. The value is for the next ++ // file in the list. ++ // Make sure there's another parameter ++ // ++ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); ++ if (EFI_ERROR (Status)) { ++ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); ++ return 1; ++ } ++ CodeRevision = (UINT32) TempValue; ++ if (CodeRevision & 0xFFFF0000) { ++ Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]); ++ return STATUS_ERROR; ++ } ++ if (FileList != NULL && FileList->CodeRevision == 0) { ++ FileList->CodeRevision = (UINT16) CodeRevision; ++ } ++ Argv++; ++ Argc--; ++ } else if ((stricmp (Argv[0], "-p") == 0) || (stricmp (Argv[0], "--pci23") == 0)) { ++ // ++ // Default layout meets PCI 3.0 specifications, specifying this flag will for a PCI 2.3 layout. ++ // ++ mOptions.Pci23 = 1; ++ } else { ++ Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]); ++ return STATUS_ERROR; ++ } ++ } else { ++ // ++ // Not a slash-option argument. Must be a file name. Make sure they've specified ++ // -e or -b already. ++ // ++ if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) { ++ Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]); ++ return STATUS_ERROR; ++ } ++ // ++ // Check Efi Option RomImage ++ // ++ if ((FileFlags & FILE_FLAG_EFI) == FILE_FLAG_EFI) { ++ EfiRomFlag = TRUE; ++ } ++ // ++ // Create a new file structure ++ // ++ FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST)); ++ if (FileList == NULL) { ++ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL); ++ return STATUS_ERROR; ++ } ++ ++ // ++ // set flag and class code for this image. ++ // ++ memset ((char *) FileList, 0, sizeof (FILE_LIST)); ++ FileList->FileName = Argv[0]; ++ FileList->FileFlags = FileFlags; ++ FileList->ClassCode = ClassCode; ++ FileList->CodeRevision = (UINT16) CodeRevision; ++ ClassCode = 0; ++ CodeRevision = 0; ++ ++ if (Options->FileList == NULL) { ++ Options->FileList = FileList; ++ } else { ++ if (PrevFileList == NULL) { ++ PrevFileList = FileList; ++ } else { ++ PrevFileList->Next = FileList; ++ } ++ } ++ ++ PrevFileList = FileList; ++ } ++ // ++ // Next argument ++ // ++ Argv++; ++ Argc--; ++ } ++ ++ // ++ // Must have specified some files ++ // ++ if (Options->FileList == NULL) { ++ Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!"); ++ return STATUS_ERROR; ++ } ++ ++ // ++ // For EFI OptionRom image, Make sure a device ID and vendor ID are both specified. ++ // ++ if (EfiRomFlag) { ++ if (!Options->VendIdValid) { ++ Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL); ++ return STATUS_ERROR; ++ } ++ ++ if (!Options->DevIdValid) { ++ Error (NULL, 0, 2000, "Missing Device ID in command line", NULL); ++ return STATUS_ERROR; ++ } ++ } ++ ++ return 0; ++} ++ ++static ++void ++Version ( ++ VOID ++ ) ++/*++ ++ ++Routine Description: ++ ++ Print version information for this utility. ++ ++Arguments: ++ ++ None. ++ ++Returns: ++ ++ Nothing. ++--*/ ++{ ++ fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); ++} ++ ++static ++void ++Usage ( ++ VOID ++ ) ++/*++ ++ ++Routine Description: ++ ++ Print usage information for this utility. ++ ++Arguments: ++ ++ None. ++ ++Returns: ++ ++ Nothing. ++ ++--*/ ++{ ++ // ++ // Summary usage ++ // ++ fprintf (stdout, "Usage: %s -f VendorId -i DeviceId [options] [file name] \n\n", UTILITY_NAME); ++ ++ // ++ // Copyright declaration ++ // ++ fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n"); ++ ++ // ++ // Details Option ++ // ++ fprintf (stdout, "Options:\n"); ++ fprintf (stdout, " -o FileName, --output FileName\n\ ++ File will be created to store the output content.\n"); ++ fprintf (stdout, " -e EfiFileName\n\ ++ EFI PE32 image files.\n"); ++ fprintf (stdout, " -ec EfiFileName\n\ ++ EFI PE32 image files and will be compressed.\n"); ++ fprintf (stdout, " -b BinFileName\n\ ++ Legacy binary files.\n"); ++ fprintf (stdout, " -l ClassCode\n\ ++ Hex ClassCode in the PCI data structure header.\n"); ++ fprintf (stdout, " -r Rev Hex Revision in the PCI data structure header.\n"); ++ fprintf (stdout, " -n Not to automatically set the LAST bit in the last file.\n"); ++ fprintf (stdout, " -f VendorId\n\ ++ Hex PCI Vendor ID for the device OpROM, must be specified\n"); ++ fprintf (stdout, " -i DeviceId\n\ ++ Hex PCI Device ID for the device OpROM, must be specified\n"); ++ fprintf (stdout, " -p, --pci23\n\ ++ Default layout meets PCI 3.0 specifications\n\ ++ specifying this flag will for a PCI 2.3 layout.\n"); ++ fprintf (stdout, " -d, --dump\n\ ++ Dump the headers of an existing option ROM image.\n"); ++ fprintf (stdout, " -v, --verbose\n\ ++ Turn on verbose output with informational messages.\n"); ++ fprintf (stdout, " --version Show program's version number and exit.\n"); ++ fprintf (stdout, " -h, --help\n\ ++ Show this help message and exit.\n"); ++ fprintf (stdout, " -q, --quiet\n\ ++ Disable all messages except FATAL ERRORS.\n"); ++ fprintf (stdout, " --debug [#,0-9]\n\ ++ Enable debug messages at level #.\n"); ++} ++ ++static ++void ++DumpImage ( ++ FILE_LIST *InFile ++ ) ++/*++ ++ ++Routine Description: ++ ++ Dump the headers of an existing option ROM image ++ ++Arguments: ++ ++ InFile - the file name of an existing option ROM image ++ ++Returns: ++ ++ none ++ ++--*/ ++{ ++ PCI_EXPANSION_ROM_HEADER PciRomHdr; ++ FILE *InFptr; ++ UINT32 ImageStart; ++ UINT32 ImageCount; ++ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr; ++ PCI_DATA_STRUCTURE PciDs23; ++ PCI_3_0_DATA_STRUCTURE PciDs30; ++ ++ // ++ // Open the input file ++ // ++ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) { ++ Error (NULL, 0, 0001, "Error opening file", InFile->FileName); ++ return ; ++ } ++ // ++ // Go through the image and dump the header stuff for each ++ // ++ ImageCount = 0; ++ for (;;) { ++ // ++ // Save our postition in the file, since offsets in the headers ++ // are relative to the particular image. ++ // ++ ImageStart = ftell (InFptr); ++ ImageCount++; ++ ++ // ++ // Read the option ROM header. Have to assume a raw binary image for now. ++ // ++ if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) { ++ Error (NULL, 0, 3001, "Not supported", "Failed to read PCI ROM header from file!"); ++ goto BailOut; ++ } ++ ++ // ++ // Dump the contents of the header ++ // ++ fprintf (stdout, "Image %u -- Offset 0x%X\n", (unsigned) ImageCount, (unsigned) ImageStart); ++ fprintf (stdout, " ROM header contents\n"); ++ fprintf (stdout, " Signature 0x%04X\n", PciRomHdr.Signature); ++ fprintf (stdout, " PCIR offset 0x%04X\n", PciRomHdr.PcirOffset); ++ // ++ // Find PCI data structure ++ // ++ if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) { ++ Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI data structure!"); ++ goto BailOut; ++ } ++ // ++ // Read and dump the PCI data structure ++ // ++ memset (&PciDs23, 0, sizeof (PciDs23)); ++ memset (&PciDs30, 0, sizeof (PciDs30)); ++ if (mOptions.Pci23 == 1) { ++ if (fread (&PciDs23, sizeof (PciDs23), 1, InFptr) != 1) { ++ Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName); ++ goto BailOut; ++ } ++ } else { ++ if (fread (&PciDs30, sizeof (PciDs30), 1, InFptr) != 1) { ++ Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName); ++ goto BailOut; ++ } ++ } ++ if (mOptions.Verbose) { ++ VerboseMsg("Read PCI data structure from file %s", InFile->FileName); ++ } ++ ++ //fprintf (stdout, " PCI Data Structure\n"); ++ if (mOptions.Pci23 == 1) { ++ fprintf ( ++ stdout, ++ " Signature %c%c%c%c\n", ++ (char) PciDs23.Signature, ++ (char) (PciDs23.Signature >> 8), ++ (char) (PciDs23.Signature >> 16), ++ (char) (PciDs23.Signature >> 24) ++ ); ++ fprintf (stdout, " Vendor ID 0x%04X\n", PciDs23.VendorId); ++ fprintf (stdout, " Device ID 0x%04X\n", PciDs23.DeviceId); ++ fprintf (stdout, " Length 0x%04X\n", PciDs23.Length); ++ fprintf (stdout, " Revision 0x%04X\n", PciDs23.Revision); ++ fprintf ( ++ stdout, ++ " Class Code 0x%06X\n", ++ (unsigned) (PciDs23.ClassCode[0] | (PciDs23.ClassCode[1] << 8) | (PciDs23.ClassCode[2] << 16)) ++ ); ++ fprintf (stdout, " Image size 0x%X\n", (unsigned) PciDs23.ImageLength * 512); ++ fprintf (stdout, " Code revision: 0x%04X\n", PciDs23.CodeRevision); ++ fprintf (stdout, " Indicator 0x%02X", PciDs23.Indicator); ++ } else { ++ fprintf ( ++ stdout, ++ " Signature %c%c%c%c\n", ++ (char) PciDs30.Signature, ++ (char) (PciDs30.Signature >> 8), ++ (char) (PciDs30.Signature >> 16), ++ (char) (PciDs30.Signature >> 24) ++ ); ++ fprintf (stdout, " Vendor ID 0x%04X\n", PciDs30.VendorId); ++ fprintf (stdout, " Device ID 0x%04X\n", PciDs30.DeviceId); ++ fprintf (stdout, " Length 0x%04X\n", PciDs30.Length); ++ fprintf (stdout, " Revision 0x%04X\n", PciDs30.Revision); ++ fprintf (stdout, " DeviceListOffset 0x%02X\n", PciDs30.DeviceListOffset); ++ fprintf ( ++ stdout, ++ " Class Code 0x%06X\n", ++ (unsigned) (PciDs30.ClassCode[0] | (PciDs30.ClassCode[1] << 8) | (PciDs30.ClassCode[2] << 16)) ++ ); ++ fprintf (stdout, " Image size 0x%X\n", (unsigned) PciDs30.ImageLength * 512); ++ fprintf (stdout, " Code revision: 0x%04X\n", PciDs30.CodeRevision); ++ fprintf (stdout, " MaxRuntimeImageLength 0x%02X\n", PciDs30.MaxRuntimeImageLength); ++ fprintf (stdout, " ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset); ++ fprintf (stdout, " DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset); ++ fprintf (stdout, " Indicator 0x%02X", PciDs30.Indicator); ++ } ++ // ++ // Print the indicator, used to flag the last image ++ // ++ if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) { ++ fprintf (stdout, " (last image)\n"); ++ } else { ++ fprintf (stdout, "\n"); ++ } ++ // ++ // Print the code type. If EFI code, then we can provide more info. ++ // ++ if (mOptions.Pci23 == 1) { ++ fprintf (stdout, " Code type 0x%02X", PciDs23.CodeType); ++ } else { ++ fprintf (stdout, " Code type 0x%02X", PciDs30.CodeType); ++ } ++ if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.CodeType == PCI_CODE_TYPE_EFI_IMAGE) { ++ fprintf (stdout, " (EFI image)\n"); ++ // ++ // Re-read the header as an EFI ROM header, then dump more info ++ // ++ fprintf (stdout, " EFI ROM header contents\n"); ++ if (fseek (InFptr, ImageStart, SEEK_SET)) { ++ Error (NULL, 0, 5001, "Failed to re-seek to ROM header structure!", NULL); ++ goto BailOut; ++ } ++ ++ if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) { ++ Error (NULL, 0, 5001, "Failed to read EFI PCI ROM header from file!", NULL); ++ goto BailOut; ++ } ++ // ++ // Now dump more info ++ // ++ fprintf (stdout, " EFI Signature 0x%04X\n", (unsigned) EfiRomHdr.EfiSignature); ++ fprintf ( ++ stdout, ++ " Compression Type 0x%04X ", ++ EfiRomHdr.CompressionType ++ ); ++ if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { ++ fprintf (stdout, "(compressed)\n"); ++ } else { ++ fprintf (stdout, "(not compressed)\n"); ++ } ++ ++ fprintf ( ++ stdout, ++ " Machine type 0x%04X (%s)\n", ++ EfiRomHdr.EfiMachineType, ++ GetMachineTypeStr (EfiRomHdr.EfiMachineType) ++ ); ++ fprintf ( ++ stdout, ++ " Subsystem 0x%04X (%s)\n", ++ EfiRomHdr.EfiSubsystem, ++ GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem) ++ ); ++ fprintf ( ++ stdout, ++ " EFI image offset 0x%04X (@0x%X)\n", ++ EfiRomHdr.EfiImageHeaderOffset, ++ EfiRomHdr.EfiImageHeaderOffset + (unsigned) ImageStart ++ ); ++ ++ } else { ++ // ++ // Not an EFI image ++ // ++ fprintf (stdout, "\n"); ++ } ++ // ++ // If code type is EFI image, then dump it as well? ++ // ++ // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) { ++ // } ++ // ++ // If last image, then we're done ++ // ++ if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) { ++ goto BailOut; ++ } ++ // ++ // Seek to the start of the next image ++ // ++ if (mOptions.Pci23 == 1) { ++ if (fseek (InFptr, ImageStart + (PciDs23.ImageLength * 512), SEEK_SET)) { ++ Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!"); ++ goto BailOut; ++ } ++ } else { ++ if (fseek (InFptr, ImageStart + (PciDs30.ImageLength * 512), SEEK_SET)) { ++ Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!"); ++ goto BailOut; ++ } ++ } ++ } ++ ++BailOut: ++ fclose (InFptr); ++} ++ ++char * ++GetMachineTypeStr ( ++ UINT16 MachineType ++ ) ++/*++ ++ ++Routine Description: ++ ++ GC_TODO: Add function description ++ ++Arguments: ++ ++ MachineType - GC_TODO: add argument description ++ ++Returns: ++ ++ GC_TODO: add return values ++ ++--*/ ++{ ++ int Index; ++ ++ for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) { ++ if (mMachineTypes[Index].Value == MachineType) { ++ return mMachineTypes[Index].Name; ++ } ++ } ++ ++ return "unknown"; ++} ++ ++static ++char * ++GetSubsystemTypeStr ( ++ UINT16 SubsystemType ++ ) ++/*++ ++ ++Routine Description: ++ ++ GC_TODO: Add function description ++ ++Arguments: ++ ++ SubsystemType - GC_TODO: add argument description ++ ++Returns: ++ ++ GC_TODO: add return values ++ ++--*/ ++{ ++ int Index; ++ ++ for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) { ++ if (mSubsystemTypes[Index].Value == SubsystemType) { ++ return mSubsystemTypes[Index].Name; ++ } ++ } ++ ++ return "unknown"; ++} +diff --git a/EfiRom/EfiRom.h b/EfiRom/EfiRom.h +new file mode 100644 +index 0000000..ce22f31 +--- /dev/null ++++ b/EfiRom/EfiRom.h +@@ -0,0 +1,357 @@ ++/** @file ++This file contains the relevant declarations required to generate Option Rom File ++ ++Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials are licensed and made available ++under the terms and conditions of the BSD License which accompanies this ++distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef __EFI_ROM_H__ ++#define __EFI_ROM_H__ ++ ++#include ++#include ++#include ++ ++#include ++#include // for PE32 structure definitions ++ ++#include // for option ROM header structures ++#include ++ ++#include "Compress.h" ++#include "CommonLib.h" ++ ++// ++// Version of this utility ++// ++#define UTILITY_NAME "EfiRom" ++#define UTILITY_MAJOR_VERSION 0 ++#define UTILITY_MINOR_VERSION 1 ++ ++// ++// Define the max length of a filename ++// ++#define MAX_PATH 200 ++ ++// ++// Define the default file extension name ++// ++#define DEFAULT_OUTPUT_EXTENSION ".rom" ++ ++// ++// Max size for an option ROM image ++// ++#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB ++ ++// ++// Values for the indicator field in the PCI data structure ++// ++#define INDICATOR_LAST 0x80 // last file in series of files ++ ++// ++// Masks for the FILE_LIST.FileFlags field ++// ++#define FILE_FLAG_BINARY 0x01 ++#define FILE_FLAG_EFI 0x02 ++#define FILE_FLAG_COMPRESS 0x04 ++ ++// ++// Use this linked list structure to keep track of all the filenames ++// specified on the command line. ++// ++typedef struct _FILE_LIST { ++ struct _FILE_LIST *Next; ++ CHAR8 *FileName; ++ UINT32 FileFlags; ++ UINT32 ClassCode; ++ UINT16 CodeRevision; ++} FILE_LIST; ++ ++// ++// Use this to track our command-line options ++// ++typedef struct { ++ CHAR8 OutFileName[MAX_PATH]; ++ INT8 NoLast; ++ UINT16 ClassCode; ++ UINT16 PciRevision; ++ UINT16 VendId; ++ UINT16 DevId; ++ UINT8 VendIdValid; ++ UINT8 DevIdValid; ++ INT8 Verbose; ++ INT8 Quiet; ++ INT8 Debug; ++ INT8 Pci23; ++ INT8 Pci30; ++ INT8 DumpOption; ++// INT8 Help; ++// INT8 Version; ++ FILE_LIST *FileList; ++} OPTIONS; ++ ++// ++// Make a global structure to keep track of command-line options ++// ++static OPTIONS mOptions; ++ ++// ++// Use these to convert from machine type value to a named type ++// ++typedef struct { ++ UINT16 Value; ++ CHAR8 *Name; ++} STRING_LOOKUP; ++ ++// ++// Machine Types ++// ++static STRING_LOOKUP mMachineTypes[] = { ++ { EFI_IMAGE_MACHINE_IA32, "IA32" }, ++ { EFI_IMAGE_MACHINE_IA64, "IA64" }, ++ { EFI_IMAGE_MACHINE_EBC, "EBC" }, ++ { 0, NULL } ++}; ++ ++// ++// Subsystem Types ++// ++static STRING_LOOKUP mSubsystemTypes[] = { ++ { EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION, "EFI application" }, ++ { EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, "EFI boot service driver" }, ++ { EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, "EFI runtime driver" }, ++ { 0, NULL } ++}; ++ ++// ++// Function prototypes ++// ++static ++void ++Version ( ++ VOID ++ ) ++/*++ ++ ++Routine Description: ++ ++ Displays the utility version to STDOUT ++ ++Arguments: ++ ++ None ++ ++Returns: ++ ++ None ++ ++--*/ ++; ++ ++static ++void ++Usage ( ++ VOID ++ ) ++/*++ ++ ++Routine Description: ++ ++ Displays the utility usage syntax to STDOUT ++ ++Arguments: ++ ++ None ++ ++Returns: ++ ++ None ++ ++--*/ ++; ++ ++static ++int ++ParseCommandLine ( ++ int Argc, ++ char *Argv[], ++ OPTIONS *Options ++ ) ++/*++ ++ ++Routine Description: ++ ++ Given the Argc/Argv program arguments, and a pointer to an options structure, ++ parse the command-line options and check their validity. ++ ++Arguments: ++ ++ Argc - standard C main() argument count ++ Argv[] - standard C main() argument list ++ Options - pointer to a structure to store the options in ++ ++Returns: ++ ++ STATUS_SUCCESS success ++ non-zero otherwise ++ ++--*/ ++; ++ ++static ++int ++CheckPE32File ( ++ FILE *Fptr, ++ UINT16 *MachineType, ++ UINT16 *SubSystem ++ ) ++/*++ ++ ++Routine Description: ++ ++ Given the Argc/Argv program arguments, and a pointer to an options structure, ++ parse the command-line options and check their validity. ++ ++Arguments: ++ ++ Argc - standard C main() argument count ++ Argv[] - standard C main() argument list ++ Options - pointer to a structure to store the options in ++ ++Returns: ++ ++ STATUS_SUCCESS success ++ non-zero otherwise ++ ++--*/ ++; ++ ++static ++int ++ProcessEfiFile ( ++ FILE *OutFptr, ++ FILE_LIST *InFile, ++ UINT16 VendId, ++ UINT16 DevId, ++ UINT32 *Size ++ ) ++/*++ ++ ++Routine Description: ++ ++ Process a PE32 EFI file. ++ ++Arguments: ++ ++ OutFptr - file pointer to output binary ROM image file we're creating ++ InFile - structure contains information on the PE32 file to process ++ VendId - vendor ID as required in the option ROM header ++ DevId - device ID as required in the option ROM header ++ Size - pointer to where to return the size added to the output file ++ ++Returns: ++ ++ 0 - successful ++ ++--*/ ++; ++ ++static ++int ++ProcessBinFile ( ++ FILE *OutFptr, ++ FILE_LIST *InFile, ++ UINT32 *Size ++ ) ++/*++ ++ ++Routine Description: ++ ++ Process a binary input file. ++ ++Arguments: ++ ++ OutFptr - file pointer to output binary ROM image file we're creating ++ InFile - structure contains information on the binary file to process ++ Size - pointer to where to return the size added to the output file ++ ++Returns: ++ ++ 0 - successful ++ ++--*/ ++; ++ ++static ++void ++DumpImage ( ++ FILE_LIST *InFile ++ ) ++/*++ ++ ++Routine Description: ++ ++ Dump the headers of an existing option ROM image ++ ++Arguments: ++ ++ InFile - the file name of an existing option ROM image ++ ++Returns: ++ ++ none ++ ++--*/ ++; ++ ++char * ++GetMachineTypeStr ( ++ UINT16 MachineType ++ ) ++/*++ ++ ++Routine Description: ++ ++ GC_TODO: Add function description ++ ++Arguments: ++ ++ MachineType - GC_TODO: add argument description ++ ++Returns: ++ ++ GC_TODO: add return values ++ ++--*/ ++; ++ ++static ++char * ++GetSubsystemTypeStr ( ++ UINT16 SubsystemType ++ ) ++/*++ ++ ++Routine Description: ++ ++ GC_TODO: Add function description ++ ++Arguments: ++ ++ SubsystemType - GC_TODO: add argument description ++ ++Returns: ++ ++ GC_TODO: add return values ++ ++--*/ ++; ++ ++#endif +diff --git a/EfiRom/Include/Common/BaseTypes.h b/EfiRom/Include/Common/BaseTypes.h +new file mode 100644 +index 0000000..4dbba73 +--- /dev/null ++++ b/EfiRom/Include/Common/BaseTypes.h +@@ -0,0 +1,286 @@ ++/** @file ++ Processor or Compiler specific defines for all supported processors. ++ ++ This file is stand alone self consistent set of definitions. ++ ++ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
++ This program and the accompanying materials ++ are licensed and made available under the terms and conditions of the BSD License ++ which accompanies this distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef __BASE_TYPES_H__ ++#define __BASE_TYPES_H__ ++ ++// ++// Include processor specific binding ++// ++#include ++#include ++ ++// ++// Modifiers to abstract standard types to aid in debug of problems ++// ++#define CONST const ++#define STATIC static ++#define VOID void ++ ++// ++// Modifiers for Data Types used to self document code. ++// This concept is borrowed for UEFI specification. ++// ++#ifndef IN ++// ++// Some other environments use this construct, so #ifndef to prevent ++// multiple definition. ++// ++#define IN ++#define OUT ++#define OPTIONAL ++#endif ++ ++// ++// Constants. They may exist in other build structures, so #ifndef them. ++// ++#ifndef TRUE ++// ++// BugBug: UEFI specification claims 1 and 0. We are concerned about the ++// complier portability so we did it this way. ++// ++#define TRUE ((BOOLEAN)(1==1)) ++#endif ++ ++#ifndef FALSE ++#define FALSE ((BOOLEAN)(0==1)) ++#endif ++ ++#ifndef NULL ++#define NULL ((VOID *) 0) ++#endif ++ ++// ++// Support for variable length argument lists using the ANSI standard. ++// ++// Since we are using the ANSI standard we used the standard naming and ++// did not follow the coding convention ++// ++// VA_LIST - typedef for argument list. ++// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use. ++// VA_END (VA_LIST Marker) - Clear Marker ++// VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argument from ++// the ... list. You must know the size and pass it in this macro. ++// ++// example: ++// ++// UINTN ++// ExampleVarArg ( ++// IN UINTN NumberOfArgs, ++// ... ++// ) ++// { ++// VA_LIST Marker; ++// UINTN Index; ++// UINTN Result; ++// ++// // ++// // Initialize the Marker ++// // ++// VA_START (Marker, NumberOfArgs); ++// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) { ++// // ++// // The ... list is a series of UINTN values, so average them up. ++// // ++// Result += VA_ARG (Marker, UINTN); ++// } ++// ++// VA_END (Marker); ++// return Result ++// } ++// ++ ++#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1)) ++ ++// ++// Also support coding convention rules for var arg macros ++// ++#ifndef VA_START ++ ++// typedef CHAR8 *VA_LIST; ++// #define VA_START(ap, v) (ap = (VA_LIST) & (v) + _INT_SIZE_OF (v)) ++// #define VA_ARG(ap, t) (*(t *) ((ap += _INT_SIZE_OF (t)) - _INT_SIZE_OF (t))) ++// #define VA_END(ap) (ap = (VA_LIST) 0) ++// Use the native arguments for tools. ++#define VA_START va_start ++#define VA_ARG va_arg ++#define VA_END va_end ++#define VA_LIST va_list ++ ++#endif ++ ++// ++// Macro that returns the byte offset of a field in a data structure. ++// ++#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) ++ ++/// ++/// _CR - returns a pointer to the structure ++/// from one of it's elements. ++/// ++#define _CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field))) ++ ++/// ++/// ALIGN_POINTER - aligns a pointer to the lowest boundary ++/// ++#define ALIGN_POINTER(p, s) ((VOID *) ((UINTN)(p) + (((s) - ((UINTN) (p))) & ((s) - 1)))) ++ ++/// ++/// ALIGN_VARIABLE - aligns a variable up to the next natural boundary for int size of a processor ++/// ++#define ALIGN_VARIABLE(Value, Adjustment) \ ++ Adjustment = 0U; \ ++ if ((UINTN) (Value) % sizeof (UINTN)) { \ ++ (Adjustment) = (UINTN)(sizeof (UINTN) - ((UINTN) (Value) % sizeof (UINTN))); \ ++ } \ ++ (Value) = (UINTN)((UINTN) (Value) + (UINTN) (Adjustment)) ++ ++// ++// Return the maximum of two operands. ++// This macro returns the maximum of two operand specified by a and b. ++// Both a and b must be the same numerical types, signed or unsigned. ++// ++#define MAX(a, b) \ ++ (((a) > (b)) ? (a) : (b)) ++ ++ ++// ++// Return the minimum of two operands. ++// This macro returns the minimal of two operand specified by a and b. ++// Both a and b must be the same numerical types, signed or unsigned. ++// ++#define MIN(a, b) \ ++ (((a) < (b)) ? (a) : (b)) ++ ++ ++// ++// EFI Error Codes common to all execution phases ++// ++ ++typedef INTN RETURN_STATUS; ++ ++/// ++/// Set the upper bit to indicate EFI Error. ++/// ++#define ENCODE_ERROR(a) (MAX_BIT | (a)) ++ ++#define ENCODE_WARNING(a) (a) ++#define RETURN_ERROR(a) ((a) < 0) ++ ++#define RETURN_SUCCESS 0 ++#define RETURN_LOAD_ERROR ENCODE_ERROR (1) ++#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) ++#define RETURN_UNSUPPORTED ENCODE_ERROR (3) ++#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4) ++#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5) ++#define RETURN_NOT_READY ENCODE_ERROR (6) ++#define RETURN_DEVICE_ERROR ENCODE_ERROR (7) ++#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8) ++#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) ++#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10) ++#define RETURN_VOLUME_FULL ENCODE_ERROR (11) ++#define RETURN_NO_MEDIA ENCODE_ERROR (12) ++#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13) ++#define RETURN_NOT_FOUND ENCODE_ERROR (14) ++#define RETURN_ACCESS_DENIED ENCODE_ERROR (15) ++#define RETURN_NO_RESPONSE ENCODE_ERROR (16) ++#define RETURN_NO_MAPPING ENCODE_ERROR (17) ++#define RETURN_TIMEOUT ENCODE_ERROR (18) ++#define RETURN_NOT_STARTED ENCODE_ERROR (19) ++#define RETURN_ALREADY_STARTED ENCODE_ERROR (20) ++#define RETURN_ABORTED ENCODE_ERROR (21) ++#define RETURN_ICMP_ERROR ENCODE_ERROR (22) ++#define RETURN_TFTP_ERROR ENCODE_ERROR (23) ++#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24) ++#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25) ++#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26) ++#define RETURN_CRC_ERROR ENCODE_ERROR (27) ++#define RETURN_END_OF_MEDIA ENCODE_ERROR (28) ++#define RETURN_END_OF_FILE ENCODE_ERROR (31) ++ ++#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1) ++#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2) ++#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3) ++#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) ++ ++typedef UINT64 PHYSICAL_ADDRESS; ++ ++#define BIT0 0x00000001 ++#define BIT1 0x00000002 ++#define BIT2 0x00000004 ++#define BIT3 0x00000008 ++#define BIT4 0x00000010 ++#define BIT5 0x00000020 ++#define BIT6 0x00000040 ++#define BIT7 0x00000080 ++#define BIT8 0x00000100 ++#define BIT9 0x00000200 ++#define BIT10 0x00000400 ++#define BIT11 0x00000800 ++#define BIT12 0x00001000 ++#define BIT13 0x00002000 ++#define BIT14 0x00004000 ++#define BIT15 0x00008000 ++#define BIT16 0x00010000 ++#define BIT17 0x00020000 ++#define BIT18 0x00040000 ++#define BIT19 0x00080000 ++#define BIT20 0x00100000 ++#define BIT21 0x00200000 ++#define BIT22 0x00400000 ++#define BIT23 0x00800000 ++#define BIT24 0x01000000 ++#define BIT25 0x02000000 ++#define BIT26 0x04000000 ++#define BIT27 0x08000000 ++#define BIT28 0x10000000 ++#define BIT29 0x20000000 ++#define BIT30 0x40000000 ++#define BIT31 0x80000000 ++#define BIT32 0x0000000100000000ULL ++#define BIT33 0x0000000200000000ULL ++#define BIT34 0x0000000400000000ULL ++#define BIT35 0x0000000800000000ULL ++#define BIT36 0x0000001000000000ULL ++#define BIT37 0x0000002000000000ULL ++#define BIT38 0x0000004000000000ULL ++#define BIT39 0x0000008000000000ULL ++#define BIT40 0x0000010000000000ULL ++#define BIT41 0x0000020000000000ULL ++#define BIT42 0x0000040000000000ULL ++#define BIT43 0x0000080000000000ULL ++#define BIT44 0x0000100000000000ULL ++#define BIT45 0x0000200000000000ULL ++#define BIT46 0x0000400000000000ULL ++#define BIT47 0x0000800000000000ULL ++#define BIT48 0x0001000000000000ULL ++#define BIT49 0x0002000000000000ULL ++#define BIT50 0x0004000000000000ULL ++#define BIT51 0x0008000000000000ULL ++#define BIT52 0x0010000000000000ULL ++#define BIT53 0x0020000000000000ULL ++#define BIT54 0x0040000000000000ULL ++#define BIT55 0x0080000000000000ULL ++#define BIT56 0x0100000000000000ULL ++#define BIT57 0x0200000000000000ULL ++#define BIT58 0x0400000000000000ULL ++#define BIT59 0x0800000000000000ULL ++#define BIT60 0x1000000000000000ULL ++#define BIT61 0x2000000000000000ULL ++#define BIT62 0x4000000000000000ULL ++#define BIT63 0x8000000000000000ULL ++ ++#endif +diff --git a/EfiRom/Include/Common/BuildVersion.h b/EfiRom/Include/Common/BuildVersion.h +new file mode 100644 +index 0000000..2892926 +--- /dev/null ++++ b/EfiRom/Include/Common/BuildVersion.h +@@ -0,0 +1,15 @@ ++/** @file ++This file is for build version number auto generation ++ ++Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.
++This program and the accompanying materials ++are licensed and made available under the terms and conditions of the BSD License ++which accompanies this distribution. The full text of the license may be found at ++http://opensource.org/licenses/bsd-license.php ++ ++THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#define __BUILD_VERSION "" +diff --git a/EfiRom/Include/Common/UefiBaseTypes.h b/EfiRom/Include/Common/UefiBaseTypes.h +new file mode 100644 +index 0000000..d52fa3e +--- /dev/null ++++ b/EfiRom/Include/Common/UefiBaseTypes.h +@@ -0,0 +1,175 @@ ++/** @file ++ Defines data types and constants introduced in UEFI. ++ ++ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef __UEFI_BASETYPE_H__ ++#define __UEFI_BASETYPE_H__ ++ ++#include ++ ++// ++// Basical data type definitions introduced in UEFI. ++// ++typedef struct { ++ UINT32 Data1; ++ UINT16 Data2; ++ UINT16 Data3; ++ UINT8 Data4[8]; ++} EFI_GUID; ++ ++typedef RETURN_STATUS EFI_STATUS; ++typedef VOID *EFI_HANDLE; ++ ++typedef VOID *EFI_EVENT; ++ ++typedef UINTN EFI_TPL; ++ ++ ++typedef UINT64 EFI_LBA; ++ ++ ++typedef UINT16 STRING_REF; ++ ++typedef UINT64 EFI_PHYSICAL_ADDRESS; ++typedef UINT64 EFI_VIRTUAL_ADDRESS; ++ ++// ++// EFI Time Abstraction: ++// Year: 2000 - 20XX ++// Month: 1 - 12 ++// Day: 1 - 31 ++// Hour: 0 - 23 ++// Minute: 0 - 59 ++// Second: 0 - 59 ++// Nanosecond: 0 - 999,999,999 ++// TimeZone: -1440 to 1440 or 2047 ++// ++typedef struct { ++ UINT16 Year; ++ UINT8 Month; ++ UINT8 Day; ++ UINT8 Hour; ++ UINT8 Minute; ++ UINT8 Second; ++ UINT8 Pad1; ++ UINT32 Nanosecond; ++ INT16 TimeZone; ++ UINT8 Daylight; ++ UINT8 Pad2; ++} EFI_TIME; ++ ++ ++// ++// Networking Definitions ++// ++typedef struct { ++ UINT8 Addr[4]; ++} EFI_IPv4_ADDRESS; ++ ++typedef struct { ++ UINT8 Addr[16]; ++} EFI_IPv6_ADDRESS; ++ ++typedef struct { ++ UINT8 Addr[32]; ++} EFI_MAC_ADDRESS; ++ ++typedef union { ++ UINT32 Addr[4]; ++ EFI_IPv4_ADDRESS v4; ++ EFI_IPv6_ADDRESS v6; ++} EFI_IP_ADDRESS; ++ ++ ++// ++// Enumeration of EFI_STATUS. ++// ++#define EFI_SUCCESS RETURN_SUCCESS ++#define EFI_LOAD_ERROR RETURN_LOAD_ERROR ++#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER ++#define EFI_UNSUPPORTED RETURN_UNSUPPORTED ++#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE ++#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL ++#define EFI_NOT_READY RETURN_NOT_READY ++#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR ++#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED ++#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES ++#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED ++#define EFI_VOLUME_FULL RETURN_VOLUME_FULL ++#define EFI_NO_MEDIA RETURN_NO_MEDIA ++#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED ++#define EFI_NOT_FOUND RETURN_NOT_FOUND ++#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED ++#define EFI_NO_RESPONSE RETURN_NO_RESPONSE ++#define EFI_NO_MAPPING RETURN_NO_MAPPING ++#define EFI_TIMEOUT RETURN_TIMEOUT ++#define EFI_NOT_STARTED RETURN_NOT_STARTED ++#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED ++#define EFI_ABORTED RETURN_ABORTED ++#define EFI_ICMP_ERROR RETURN_ICMP_ERROR ++#define EFI_TFTP_ERROR RETURN_TFTP_ERROR ++#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR ++#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION ++#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION ++#define EFI_CRC_ERROR RETURN_CRC_ERROR ++#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA ++#define EFI_END_OF_FILE RETURN_END_OF_FILE ++ ++#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH ++#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE ++#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE ++#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL ++ ++ ++#define NULL_HANDLE ((VOID *) 0) ++ ++// ++// Define macro to encode the status code. ++// ++#define EFIERR(_a) ENCODE_ERROR(_a) ++ ++#define EFI_ERROR(A) RETURN_ERROR(A) ++ ++// ++// Define macros to build data structure signatures from characters. ++// ++#define SIGNATURE_16(A, B) ((A) | (B << 8)) ++#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16)) ++#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ ++ (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32)) ++ ++ ++// ++// Returns the byte offset to a field within a structure ++// ++#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(&(((TYPE *) 0)->Field))) ++ ++// ++// The EFI memory allocation functions work in units of EFI_PAGEs that are ++// 4K. This should in no way be confused with the page size of the processor. ++// An EFI_PAGE is just the quanta of memory in EFI. ++// ++#define EFI_PAGE_SIZE 0x1000 ++#define EFI_PAGE_MASK 0xFFF ++#define EFI_PAGE_SHIFT 12 ++ ++#define EFI_SIZE_TO_PAGES(a) (((a) >> EFI_PAGE_SHIFT) + (((a) & EFI_PAGE_MASK) ? 1 : 0)) ++ ++#define EFI_PAGES_TO_SIZE(a) ( (a) << EFI_PAGE_SHIFT) ++ ++ ++#define EFI_MAX_BIT MAX_BIT ++#define EFI_MAX_ADDRESS MAX_ADDRESS ++ ++#endif +diff --git a/EfiRom/Include/IndustryStandard/EfiPci.h b/EfiRom/Include/IndustryStandard/EfiPci.h +new file mode 100644 +index 0000000..58c7700 +--- /dev/null ++++ b/EfiRom/Include/IndustryStandard/EfiPci.h +@@ -0,0 +1,57 @@ ++/** @file ++ Support for EFI PCI specification. ++ ++ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _EFI_PCI_H_ ++#define _EFI_PCI_H_ ++ ++//#include "pci22.h" ++//#include "pci23.h" ++//#include "pci30.h" ++ ++#pragma pack(push, 1) ++ ++typedef struct { ++ UINT8 Register; ++ UINT8 Function; ++ UINT8 Device; ++ UINT8 Bus; ++ UINT8 Reserved[4]; ++} DEFIO_PCI_ADDR; ++ ++#define EFI_ROOT_BRIDGE_LIST 'eprb' ++#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 ++ ++typedef struct { ++ UINT16 Signature; // 0xaa55 ++ UINT16 InitializationSize; ++ UINT32 EfiSignature; // 0x0EF1 ++ UINT16 EfiSubsystem; ++ UINT16 EfiMachineType; ++ UINT16 CompressionType; ++ UINT8 Reserved[8]; ++ UINT16 EfiImageHeaderOffset; ++ UINT16 PcirOffset; ++} EFI_PCI_EXPANSION_ROM_HEADER; ++ ++typedef union { ++ UINT8 *Raw; ++ PCI_EXPANSION_ROM_HEADER *Generic; ++ EFI_PCI_EXPANSION_ROM_HEADER *Efi; ++ EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt; ++} EFI_PCI_ROM_HEADER; ++ ++#pragma pack(pop) ++ ++#endif +diff --git a/EfiRom/Include/IndustryStandard/PeImage.h b/EfiRom/Include/IndustryStandard/PeImage.h +new file mode 100644 +index 0000000..342040a +--- /dev/null ++++ b/EfiRom/Include/IndustryStandard/PeImage.h +@@ -0,0 +1,769 @@ ++/** @file ++ EFI image format for PE32+. Please note some data structures are different ++ for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64 ++ ++ @bug Fix text - doc as defined in MSFT EFI specification. ++ ++ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
++ Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef __PE_IMAGE_H__ ++#define __PE_IMAGE_H__ ++ ++// ++// PE32+ Subsystem type for EFI images ++// ++#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10 ++#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 ++#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 ++#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ++ ++// ++// BugBug: Need to get a real answer for this problem. This is not in the ++// PE specification. ++// ++// A SAL runtime driver does not get fixed up when a transition to ++// virtual mode is made. In all other cases it should be treated ++// like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image ++// ++#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 ++ ++// ++// PE32+ Machine type for EFI images ++// ++#define IMAGE_FILE_MACHINE_I386 0x014c ++#define IMAGE_FILE_MACHINE_IA64 0x0200 ++#define IMAGE_FILE_MACHINE_EBC 0x0EBC ++#define IMAGE_FILE_MACHINE_X64 0x8664 ++#define IMAGE_FILE_MACHINE_ARM 0x01c0 // Thumb only ++#define IMAGE_FILE_MACHINE_ARMT 0x01c2 // 32bit Mixed ARM and Thumb/Thumb 2 Little Endian ++#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // 64bit ARM Architecture, Little Endian ++ ++// ++// Support old names for backward compatible ++// ++#define EFI_IMAGE_MACHINE_IA32 IMAGE_FILE_MACHINE_I386 ++#define EFI_IMAGE_MACHINE_IA64 IMAGE_FILE_MACHINE_IA64 ++#define EFI_IMAGE_MACHINE_IPF IMAGE_FILE_MACHINE_IA64 ++#define EFI_IMAGE_MACHINE_EBC IMAGE_FILE_MACHINE_EBC ++#define EFI_IMAGE_MACHINE_X64 IMAGE_FILE_MACHINE_X64 ++#define EFI_IMAGE_MACHINE_ARMT IMAGE_FILE_MACHINE_ARMT ++#define EFI_IMAGE_MACHINE_AARCH64 IMAGE_FILE_MACHINE_ARM64 ++ ++#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ ++#define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE ++#define EFI_IMAGE_OS2_SIGNATURE_LE 0x454C // LE ++#define EFI_IMAGE_NT_SIGNATURE 0x00004550 // PE00 ++#define EFI_IMAGE_EDOS_SIGNATURE 0x44454550 // PEED ++ ++/// ++/// PE images can start with an optional DOS header, so if an image is run ++/// under DOS it can print an error message. ++/// ++typedef struct { ++ UINT16 e_magic; // Magic number ++ UINT16 e_cblp; // Bytes on last page of file ++ UINT16 e_cp; // Pages in file ++ UINT16 e_crlc; // Relocations ++ UINT16 e_cparhdr; // Size of header in paragraphs ++ UINT16 e_minalloc; // Minimum extra paragraphs needed ++ UINT16 e_maxalloc; // Maximum extra paragraphs needed ++ UINT16 e_ss; // Initial (relative) SS value ++ UINT16 e_sp; // Initial SP value ++ UINT16 e_csum; // Checksum ++ UINT16 e_ip; // Initial IP value ++ UINT16 e_cs; // Initial (relative) CS value ++ UINT16 e_lfarlc; // File address of relocation table ++ UINT16 e_ovno; // Overlay number ++ UINT16 e_res[4]; // Reserved words ++ UINT16 e_oemid; // OEM identifier (for e_oeminfo) ++ UINT16 e_oeminfo; // OEM information; e_oemid specific ++ UINT16 e_res2[10]; // Reserved words ++ UINT32 e_lfanew; // File address of new exe header ++} EFI_IMAGE_DOS_HEADER; ++ ++/// ++/// File header format. ++/// ++typedef struct { ++ UINT16 Machine; ++ UINT16 NumberOfSections; ++ UINT32 TimeDateStamp; ++ UINT32 PointerToSymbolTable; ++ UINT32 NumberOfSymbols; ++ UINT16 SizeOfOptionalHeader; ++ UINT16 Characteristics; ++} EFI_IMAGE_FILE_HEADER; ++ ++#define EFI_IMAGE_SIZEOF_FILE_HEADER 20 ++ ++#define EFI_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. ++#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). ++#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. ++#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. ++#define EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // Supports addresses > 2-GB ++#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. ++#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. ++#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file ++#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File. ++#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL. ++#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. ++#define EFI_IMAGE_FILE_MACHINE_UNKNOWN 0 ++#define EFI_IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. ++#define EFI_IMAGE_FILE_MACHINE_R3000 0x162 // MIPS* little-endian, 0540 big-endian ++#define EFI_IMAGE_FILE_MACHINE_R4000 0x166 // MIPS* little-endian ++#define EFI_IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP* ++#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM* PowerPC Little-Endian ++#define EFI_IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine ++// ++// * Other names and brands may be claimed as the property of others. ++// ++ ++/// ++/// Directory format. ++/// ++typedef struct { ++ UINT32 VirtualAddress; ++ UINT32 Size; ++} EFI_IMAGE_DATA_DIRECTORY; ++ ++#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16 ++ ++typedef struct { ++ UINT16 Magic; ++ UINT8 MajorLinkerVersion; ++ UINT8 MinorLinkerVersion; ++ UINT32 SizeOfCode; ++ UINT32 SizeOfInitializedData; ++ UINT32 SizeOfUninitializedData; ++ UINT32 AddressOfEntryPoint; ++ UINT32 BaseOfCode; ++ UINT32 BaseOfData; ++ UINT32 BaseOfBss; ++ UINT32 GprMask; ++ UINT32 CprMask[4]; ++ UINT32 GpValue; ++} EFI_IMAGE_ROM_OPTIONAL_HEADER; ++ ++#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 ++#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER) ++ ++typedef struct { ++ EFI_IMAGE_FILE_HEADER FileHeader; ++ EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; ++} EFI_IMAGE_ROM_HEADERS; ++ ++/// ++/// @attention ++/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64 ++/// are for use ONLY by tools. All proper EFI code MUST use ++/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!! ++/// ++#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b ++ ++typedef struct { ++ // ++ // Standard fields. ++ // ++ UINT16 Magic; ++ UINT8 MajorLinkerVersion; ++ UINT8 MinorLinkerVersion; ++ UINT32 SizeOfCode; ++ UINT32 SizeOfInitializedData; ++ UINT32 SizeOfUninitializedData; ++ UINT32 AddressOfEntryPoint; ++ UINT32 BaseOfCode; ++ UINT32 BaseOfData; ++ // ++ // NT additional fields. ++ // ++ UINT32 ImageBase; ++ UINT32 SectionAlignment; ++ UINT32 FileAlignment; ++ UINT16 MajorOperatingSystemVersion; ++ UINT16 MinorOperatingSystemVersion; ++ UINT16 MajorImageVersion; ++ UINT16 MinorImageVersion; ++ UINT16 MajorSubsystemVersion; ++ UINT16 MinorSubsystemVersion; ++ UINT32 Win32VersionValue; ++ UINT32 SizeOfImage; ++ UINT32 SizeOfHeaders; ++ UINT32 CheckSum; ++ UINT16 Subsystem; ++ UINT16 DllCharacteristics; ++ UINT32 SizeOfStackReserve; ++ UINT32 SizeOfStackCommit; ++ UINT32 SizeOfHeapReserve; ++ UINT32 SizeOfHeapCommit; ++ UINT32 LoaderFlags; ++ UINT32 NumberOfRvaAndSizes; ++ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; ++} EFI_IMAGE_OPTIONAL_HEADER32; ++ ++/// ++/// @attention ++/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64 ++/// are for use ONLY by tools. All proper EFI code MUST use ++/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!! ++/// ++#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b ++ ++typedef struct { ++ // ++ // Standard fields. ++ // ++ UINT16 Magic; ++ UINT8 MajorLinkerVersion; ++ UINT8 MinorLinkerVersion; ++ UINT32 SizeOfCode; ++ UINT32 SizeOfInitializedData; ++ UINT32 SizeOfUninitializedData; ++ UINT32 AddressOfEntryPoint; ++ UINT32 BaseOfCode; ++ // ++ // NT additional fields. ++ // ++ UINT64 ImageBase; ++ UINT32 SectionAlignment; ++ UINT32 FileAlignment; ++ UINT16 MajorOperatingSystemVersion; ++ UINT16 MinorOperatingSystemVersion; ++ UINT16 MajorImageVersion; ++ UINT16 MinorImageVersion; ++ UINT16 MajorSubsystemVersion; ++ UINT16 MinorSubsystemVersion; ++ UINT32 Win32VersionValue; ++ UINT32 SizeOfImage; ++ UINT32 SizeOfHeaders; ++ UINT32 CheckSum; ++ UINT16 Subsystem; ++ UINT16 DllCharacteristics; ++ UINT64 SizeOfStackReserve; ++ UINT64 SizeOfStackCommit; ++ UINT64 SizeOfHeapReserve; ++ UINT64 SizeOfHeapCommit; ++ UINT32 LoaderFlags; ++ UINT32 NumberOfRvaAndSizes; ++ EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; ++} EFI_IMAGE_OPTIONAL_HEADER64; ++ ++/// ++/// @attention ++/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY ++/// by tools. All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!! ++/// ++typedef struct { ++ UINT32 Signature; ++ EFI_IMAGE_FILE_HEADER FileHeader; ++ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader; ++} EFI_IMAGE_NT_HEADERS32; ++ ++#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32) ++ ++typedef struct { ++ UINT32 Signature; ++ EFI_IMAGE_FILE_HEADER FileHeader; ++ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader; ++} EFI_IMAGE_NT_HEADERS64; ++ ++#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64) ++ ++// ++// Subsystem Values ++// ++#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0 ++#define EFI_IMAGE_SUBSYSTEM_NATIVE 1 ++#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2 ++#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3. ++#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5 ++#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7 ++ ++// ++// Directory Entries ++// ++#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0 ++#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1 ++#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2 ++#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 ++#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4 ++#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5 ++#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6 ++#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 ++#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 ++#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9 ++#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 ++ ++// ++// Section header format. ++// ++#define EFI_IMAGE_SIZEOF_SHORT_NAME 8 ++ ++typedef struct { ++ UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME]; ++ union { ++ UINT32 PhysicalAddress; ++ UINT32 VirtualSize; ++ } Misc; ++ UINT32 VirtualAddress; ++ UINT32 SizeOfRawData; ++ UINT32 PointerToRawData; ++ UINT32 PointerToRelocations; ++ UINT32 PointerToLinenumbers; ++ UINT16 NumberOfRelocations; ++ UINT16 NumberOfLinenumbers; ++ UINT32 Characteristics; ++} EFI_IMAGE_SECTION_HEADER; ++ ++#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 ++ ++#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. ++#define EFI_IMAGE_SCN_CNT_CODE 0x00000020 ++#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 ++#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 ++ ++#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. ++#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. ++#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. ++#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000 ++ ++#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000 ++#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000 ++#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000 ++#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000 ++#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000 ++#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000 ++#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000 ++ ++#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000 ++#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000 ++#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000 ++#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000 ++#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000 ++#define EFI_IMAGE_SCN_MEM_READ 0x40000000 ++#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000 ++ ++/// ++/// Symbol format. ++/// ++#define EFI_IMAGE_SIZEOF_SYMBOL 18 ++ ++// ++// Section values. ++// ++// Symbols have a section number of the section in which they are ++// defined. Otherwise, section numbers have the following meanings: ++// ++#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 // Symbol is undefined or is common. ++#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 // Symbol is an absolute value. ++#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 // Symbol is a special debug item. ++// ++// Type (fundamental) values. ++// ++#define EFI_IMAGE_SYM_TYPE_NULL 0 // no type. ++#define EFI_IMAGE_SYM_TYPE_VOID 1 // ++#define EFI_IMAGE_SYM_TYPE_CHAR 2 // type character. ++#define EFI_IMAGE_SYM_TYPE_SHORT 3 // type short integer. ++#define EFI_IMAGE_SYM_TYPE_INT 4 ++#define EFI_IMAGE_SYM_TYPE_LONG 5 ++#define EFI_IMAGE_SYM_TYPE_FLOAT 6 ++#define EFI_IMAGE_SYM_TYPE_DOUBLE 7 ++#define EFI_IMAGE_SYM_TYPE_STRUCT 8 ++#define EFI_IMAGE_SYM_TYPE_UNION 9 ++#define EFI_IMAGE_SYM_TYPE_ENUM 10 // enumeration. ++#define EFI_IMAGE_SYM_TYPE_MOE 11 // member of enumeration. ++#define EFI_IMAGE_SYM_TYPE_BYTE 12 ++#define EFI_IMAGE_SYM_TYPE_WORD 13 ++#define EFI_IMAGE_SYM_TYPE_UINT 14 ++#define EFI_IMAGE_SYM_TYPE_DWORD 15 ++ ++// ++// Type (derived) values. ++// ++#define EFI_IMAGE_SYM_DTYPE_NULL 0 // no derived type. ++#define EFI_IMAGE_SYM_DTYPE_POINTER 1 ++#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2 ++#define EFI_IMAGE_SYM_DTYPE_ARRAY 3 ++ ++// ++// Storage classes. ++// ++#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION (UINT8) -1 ++#define EFI_IMAGE_SYM_CLASS_NULL 0 ++#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1 ++#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2 ++#define EFI_IMAGE_SYM_CLASS_STATIC 3 ++#define EFI_IMAGE_SYM_CLASS_REGISTER 4 ++#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5 ++#define EFI_IMAGE_SYM_CLASS_LABEL 6 ++#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 ++#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 ++#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9 ++#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10 ++#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 ++#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12 ++#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13 ++#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 ++#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15 ++#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 ++#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17 ++#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18 ++#define EFI_IMAGE_SYM_CLASS_BLOCK 100 ++#define EFI_IMAGE_SYM_CLASS_FUNCTION 101 ++#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102 ++#define EFI_IMAGE_SYM_CLASS_FILE 103 ++#define EFI_IMAGE_SYM_CLASS_SECTION 104 ++#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 ++ ++// ++// type packing constants ++// ++#define EFI_IMAGE_N_BTMASK 017 ++#define EFI_IMAGE_N_TMASK 060 ++#define EFI_IMAGE_N_TMASK1 0300 ++#define EFI_IMAGE_N_TMASK2 0360 ++#define EFI_IMAGE_N_BTSHFT 4 ++#define EFI_IMAGE_N_TSHIFT 2 ++ ++// ++// Communal selection types. ++// ++#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1 ++#define EFI_IMAGE_COMDAT_SELECT_ANY 2 ++#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3 ++#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4 ++#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 ++ ++#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 ++#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 ++#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 ++ ++/// ++/// Relocation format. ++/// ++typedef struct { ++ UINT32 VirtualAddress; ++ UINT32 SymbolTableIndex; ++ UINT16 Type; ++} EFI_IMAGE_RELOCATION; ++ ++#define EFI_IMAGE_SIZEOF_RELOCATION 10 ++ ++// ++// I386 relocation types. ++// ++#define EFI_IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary ++#define EFI_IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address ++#define EFI_IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address ++#define EFI_IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address ++#define EFI_IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included ++#define EFI_IMAGE_REL_I386_SEG12 09 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address ++#define EFI_IMAGE_REL_I386_SECTION 010 ++#define EFI_IMAGE_REL_I386_SECREL 011 ++#define EFI_IMAGE_REL_I386_REL32 020 // PC-relative 32-bit reference to the symbols virtual address ++ ++// ++// x64 processor relocation types. ++// ++#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 ++#define IMAGE_REL_AMD64_ADDR64 0x0001 ++#define IMAGE_REL_AMD64_ADDR32 0x0002 ++#define IMAGE_REL_AMD64_ADDR32NB 0x0003 ++#define IMAGE_REL_AMD64_REL32 0x0004 ++#define IMAGE_REL_AMD64_REL32_1 0x0005 ++#define IMAGE_REL_AMD64_REL32_2 0x0006 ++#define IMAGE_REL_AMD64_REL32_3 0x0007 ++#define IMAGE_REL_AMD64_REL32_4 0x0008 ++#define IMAGE_REL_AMD64_REL32_5 0x0009 ++#define IMAGE_REL_AMD64_SECTION 0x000A ++#define IMAGE_REL_AMD64_SECREL 0x000B ++#define IMAGE_REL_AMD64_SECREL7 0x000C ++#define IMAGE_REL_AMD64_TOKEN 0x000D ++#define IMAGE_REL_AMD64_SREL32 0x000E ++#define IMAGE_REL_AMD64_PAIR 0x000F ++#define IMAGE_REL_AMD64_SSPAN32 0x0010 ++ ++/// ++/// Based relocation format. ++/// ++typedef struct { ++ UINT32 VirtualAddress; ++ UINT32 SizeOfBlock; ++} EFI_IMAGE_BASE_RELOCATION; ++ ++#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8 ++ ++// ++// Based relocation types. ++// ++#define EFI_IMAGE_REL_BASED_ABSOLUTE 0 ++#define EFI_IMAGE_REL_BASED_HIGH 1 ++#define EFI_IMAGE_REL_BASED_LOW 2 ++#define EFI_IMAGE_REL_BASED_HIGHLOW 3 ++#define EFI_IMAGE_REL_BASED_HIGHADJ 4 ++#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5 ++#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5 ++#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7 ++#define EFI_IMAGE_REL_BASED_IA64_IMM64 9 ++#define EFI_IMAGE_REL_BASED_DIR64 10 ++ ++ ++/// ++/// Line number format. ++/// ++typedef struct { ++ union { ++ UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. ++ UINT32 VirtualAddress; // Virtual address of line number. ++ } Type; ++ UINT16 Linenumber; // Line number. ++} EFI_IMAGE_LINENUMBER; ++ ++#define EFI_IMAGE_SIZEOF_LINENUMBER 6 ++ ++// ++// Archive format. ++// ++#define EFI_IMAGE_ARCHIVE_START_SIZE 8 ++#define EFI_IMAGE_ARCHIVE_START "!\n" ++#define EFI_IMAGE_ARCHIVE_END "`\n" ++#define EFI_IMAGE_ARCHIVE_PAD "\n" ++#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ " ++#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " ++ ++typedef struct { ++ UINT8 Name[16]; // File member name - `/' terminated. ++ UINT8 Date[12]; // File member date - decimal. ++ UINT8 UserID[6]; // File member user id - decimal. ++ UINT8 GroupID[6]; // File member group id - decimal. ++ UINT8 Mode[8]; // File member mode - octal. ++ UINT8 Size[10]; // File member size - decimal. ++ UINT8 EndHeader[2]; // String to end header. ++} EFI_IMAGE_ARCHIVE_MEMBER_HEADER; ++ ++#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 ++ ++// ++// DLL support. ++// ++ ++/// ++/// DLL Export Format ++/// ++typedef struct { ++ UINT32 Characteristics; ++ UINT32 TimeDateStamp; ++ UINT16 MajorVersion; ++ UINT16 MinorVersion; ++ UINT32 Name; ++ UINT32 Base; ++ UINT32 NumberOfFunctions; ++ UINT32 NumberOfNames; ++ UINT32 AddressOfFunctions; ++ UINT32 AddressOfNames; ++ UINT32 AddressOfNameOrdinals; ++} EFI_IMAGE_EXPORT_DIRECTORY; ++ ++/// ++/// DLL support. ++/// Import Format ++/// ++typedef struct { ++ UINT16 Hint; ++ UINT8 Name[1]; ++} EFI_IMAGE_IMPORT_BY_NAME; ++ ++typedef struct { ++ union { ++ UINT32 Function; ++ UINT32 Ordinal; ++ EFI_IMAGE_IMPORT_BY_NAME *AddressOfData; ++ } u1; ++} EFI_IMAGE_THUNK_DATA; ++ ++#define EFI_IMAGE_ORDINAL_FLAG 0x80000000 ++#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0) ++#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) ++ ++typedef struct { ++ UINT32 Characteristics; ++ UINT32 TimeDateStamp; ++ UINT32 ForwarderChain; ++ UINT32 Name; ++ EFI_IMAGE_THUNK_DATA *FirstThunk; ++} EFI_IMAGE_IMPORT_DESCRIPTOR; ++ ++/// ++/// Debug Format ++/// ++#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 ++ ++typedef struct { ++ UINT32 Characteristics; ++ UINT32 TimeDateStamp; ++ UINT16 MajorVersion; ++ UINT16 MinorVersion; ++ UINT32 Type; ++ UINT32 SizeOfData; ++ UINT32 RVA; ++ UINT32 FileOffset; ++} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY; ++ ++#define CODEVIEW_SIGNATURE_NB10 0x3031424E // "NB10" ++typedef struct { ++ UINT32 Signature; // "NB10" ++ UINT32 Unknown; ++ UINT32 Unknown2; ++ UINT32 Unknown3; ++ // ++ // Filename of .PDB goes here ++ // ++} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY; ++ ++#define CODEVIEW_SIGNATURE_RSDS 0x53445352 // "RSDS" ++typedef struct { ++ UINT32 Signature; // "RSDS" ++ UINT32 Unknown; ++ UINT32 Unknown2; ++ UINT32 Unknown3; ++ UINT32 Unknown4; ++ UINT32 Unknown5; ++ // ++ // Filename of .PDB goes here ++ // ++} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY; ++ ++/// ++/// Debug Data Structure defined by Apple Mach-O to Coff utility ++/// ++#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C') ++typedef struct { ++ UINT32 Signature; ///< "MTOC" ++ EFI_GUID MachOUuid; ++ // ++ // Filename of .DLL (Mach-O with debug info) goes here ++ // ++} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY; ++ ++// ++// .pdata entries for X64 ++// ++typedef struct { ++ UINT32 FunctionStartAddress; ++ UINT32 FunctionEndAddress; ++ UINT32 UnwindInfoAddress; ++} RUNTIME_FUNCTION; ++ ++typedef struct { ++ UINT8 Version:3; ++ UINT8 Flags:5; ++ UINT8 SizeOfProlog; ++ UINT8 CountOfUnwindCodes; ++ UINT8 FrameRegister:4; ++ UINT8 FrameRegisterOffset:4; ++} UNWIND_INFO; ++ ++/// ++/// Resource format. ++/// ++typedef struct { ++ UINT32 Characteristics; ++ UINT32 TimeDateStamp; ++ UINT16 MajorVersion; ++ UINT16 MinorVersion; ++ UINT16 NumberOfNamedEntries; ++ UINT16 NumberOfIdEntries; ++ // ++ // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here. ++ // ++} EFI_IMAGE_RESOURCE_DIRECTORY; ++ ++/// ++/// Resource directory entry format. ++/// ++typedef struct { ++ union { ++ struct { ++ UINT32 NameOffset:31; ++ UINT32 NameIsString:1; ++ } s; ++ UINT32 Id; ++ } u1; ++ union { ++ UINT32 OffsetToData; ++ struct { ++ UINT32 OffsetToDirectory:31; ++ UINT32 DataIsDirectory:1; ++ } s; ++ } u2; ++} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY; ++ ++/// ++/// Resource directory entry for string. ++/// ++typedef struct { ++ UINT16 Length; ++ CHAR16 String[1]; ++} EFI_IMAGE_RESOURCE_DIRECTORY_STRING; ++ ++/// ++/// Resource directory entry for data array. ++/// ++typedef struct { ++ UINT32 OffsetToData; ++ UINT32 Size; ++ UINT32 CodePage; ++ UINT32 Reserved; ++} EFI_IMAGE_RESOURCE_DATA_ENTRY; ++ ++/// ++/// Header format for TE images ++/// ++typedef struct { ++ UINT16 Signature; // signature for TE format = "VZ" ++ UINT16 Machine; // from the original file header ++ UINT8 NumberOfSections; // from the original file header ++ UINT8 Subsystem; // from original optional header ++ UINT16 StrippedSize; // how many bytes we removed from the header ++ UINT32 AddressOfEntryPoint; // offset to entry point -- from original optional header ++ UINT32 BaseOfCode; // from original image -- required for ITP debug ++ UINT64 ImageBase; // from original file header ++ EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; // only base relocation and debug directory ++} EFI_TE_IMAGE_HEADER; ++ ++#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // "VZ" ++ ++// ++// Data directory indexes in our TE image header ++// ++#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0 ++#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1 ++ ++ ++// ++// Union of PE32, PE32+, and TE headers ++// ++typedef union { ++ EFI_IMAGE_NT_HEADERS32 Pe32; ++ EFI_IMAGE_NT_HEADERS64 Pe32Plus; ++ EFI_TE_IMAGE_HEADER Te; ++} EFI_IMAGE_OPTIONAL_HEADER_UNION; ++ ++typedef union { ++ EFI_IMAGE_NT_HEADERS32 *Pe32; ++ EFI_IMAGE_NT_HEADERS64 *Pe32Plus; ++ EFI_TE_IMAGE_HEADER *Te; ++ EFI_IMAGE_OPTIONAL_HEADER_UNION *Union; ++} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION; ++ ++#endif +diff --git a/EfiRom/Include/IndustryStandard/pci22.h b/EfiRom/Include/IndustryStandard/pci22.h +new file mode 100644 +index 0000000..dce7cc0 +--- /dev/null ++++ b/EfiRom/Include/IndustryStandard/pci22.h +@@ -0,0 +1,542 @@ ++/** @file ++ Support for PCI 2.2 standard. ++ ++ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _PCI22_H ++#define _PCI22_H ++ ++#define PCI_MAX_SEGMENT 0 ++ ++#define PCI_MAX_BUS 255 ++ ++#define PCI_MAX_DEVICE 31 ++#define PCI_MAX_FUNC 7 ++ ++// ++// Command ++// ++#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20 ++ ++#pragma pack(push, 1) ++typedef struct { ++ UINT16 VendorId; ++ UINT16 DeviceId; ++ UINT16 Command; ++ UINT16 Status; ++ UINT8 RevisionID; ++ UINT8 ClassCode[3]; ++ UINT8 CacheLineSize; ++ UINT8 LatencyTimer; ++ UINT8 HeaderType; ++ UINT8 BIST; ++} PCI_DEVICE_INDEPENDENT_REGION; ++ ++typedef struct { ++ UINT32 Bar[6]; ++ UINT32 CISPtr; ++ UINT16 SubsystemVendorID; ++ UINT16 SubsystemID; ++ UINT32 ExpansionRomBar; ++ UINT8 CapabilityPtr; ++ UINT8 Reserved1[3]; ++ UINT32 Reserved2; ++ UINT8 InterruptLine; ++ UINT8 InterruptPin; ++ UINT8 MinGnt; ++ UINT8 MaxLat; ++} PCI_DEVICE_HEADER_TYPE_REGION; ++ ++typedef struct { ++ PCI_DEVICE_INDEPENDENT_REGION Hdr; ++ PCI_DEVICE_HEADER_TYPE_REGION Device; ++} PCI_TYPE00; ++ ++typedef struct { ++ UINT32 Bar[2]; ++ UINT8 PrimaryBus; ++ UINT8 SecondaryBus; ++ UINT8 SubordinateBus; ++ UINT8 SecondaryLatencyTimer; ++ UINT8 IoBase; ++ UINT8 IoLimit; ++ UINT16 SecondaryStatus; ++ UINT16 MemoryBase; ++ UINT16 MemoryLimit; ++ UINT16 PrefetchableMemoryBase; ++ UINT16 PrefetchableMemoryLimit; ++ UINT32 PrefetchableBaseUpper32; ++ UINT32 PrefetchableLimitUpper32; ++ UINT16 IoBaseUpper16; ++ UINT16 IoLimitUpper16; ++ UINT8 CapabilityPtr; ++ UINT8 Reserved[3]; ++ UINT32 ExpansionRomBAR; ++ UINT8 InterruptLine; ++ UINT8 InterruptPin; ++ UINT16 BridgeControl; ++} PCI_BRIDGE_CONTROL_REGISTER; ++ ++typedef struct { ++ PCI_DEVICE_INDEPENDENT_REGION Hdr; ++ PCI_BRIDGE_CONTROL_REGISTER Bridge; ++} PCI_TYPE01; ++ ++typedef union { ++ PCI_TYPE00 Device; ++ PCI_TYPE01 Bridge; ++} PCI_TYPE_GENERIC; ++ ++typedef struct { ++ UINT32 CardBusSocketReg; // Cardus Socket/ExCA Base ++ // Address Register ++ // ++ UINT16 Reserved; ++ UINT16 SecondaryStatus; // Secondary Status ++ UINT8 PciBusNumber; // PCI Bus Number ++ UINT8 CardBusBusNumber; // CardBus Bus Number ++ UINT8 SubordinateBusNumber; // Subordinate Bus Number ++ UINT8 CardBusLatencyTimer; // CardBus Latency Timer ++ UINT32 MemoryBase0; // Memory Base Register 0 ++ UINT32 MemoryLimit0; // Memory Limit Register 0 ++ UINT32 MemoryBase1; ++ UINT32 MemoryLimit1; ++ UINT32 IoBase0; ++ UINT32 IoLimit0; // I/O Base Register 0 ++ UINT32 IoBase1; // I/O Limit Register 0 ++ UINT32 IoLimit1; ++ UINT8 InterruptLine; // Interrupt Line ++ UINT8 InterruptPin; // Interrupt Pin ++ UINT16 BridgeControl; // Bridge Control ++} PCI_CARDBUS_CONTROL_REGISTER; ++ ++// ++// Definitions of PCI class bytes and manipulation macros. ++// ++#define PCI_CLASS_OLD 0x00 ++#define PCI_CLASS_OLD_OTHER 0x00 ++#define PCI_CLASS_OLD_VGA 0x01 ++ ++#define PCI_CLASS_MASS_STORAGE 0x01 ++#define PCI_CLASS_MASS_STORAGE_SCSI 0x00 ++#define PCI_CLASS_MASS_STORAGE_IDE 0x01 // obsolete ++#define PCI_CLASS_IDE 0x01 ++#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02 ++#define PCI_CLASS_MASS_STORAGE_IPI 0x03 ++#define PCI_CLASS_MASS_STORAGE_RAID 0x04 ++#define PCI_CLASS_MASS_STORAGE_OTHER 0x80 ++ ++#define PCI_CLASS_NETWORK 0x02 ++#define PCI_CLASS_NETWORK_ETHERNET 0x00 ++#define PCI_CLASS_ETHERNET 0x00 // obsolete ++#define PCI_CLASS_NETWORK_TOKENRING 0x01 ++#define PCI_CLASS_NETWORK_FDDI 0x02 ++#define PCI_CLASS_NETWORK_ATM 0x03 ++#define PCI_CLASS_NETWORK_ISDN 0x04 ++#define PCI_CLASS_NETWORK_OTHER 0x80 ++ ++#define PCI_CLASS_DISPLAY 0x03 ++#define PCI_CLASS_DISPLAY_CTRL 0x03 // obsolete ++#define PCI_CLASS_DISPLAY_VGA 0x00 ++#define PCI_CLASS_VGA 0x00 // obsolete ++#define PCI_CLASS_DISPLAY_XGA 0x01 ++#define PCI_CLASS_DISPLAY_3D 0x02 ++#define PCI_CLASS_DISPLAY_OTHER 0x80 ++#define PCI_CLASS_DISPLAY_GFX 0x80 ++#define PCI_CLASS_GFX 0x80 // obsolete ++#define PCI_CLASS_BRIDGE 0x06 ++#define PCI_CLASS_BRIDGE_HOST 0x00 ++#define PCI_CLASS_BRIDGE_ISA 0x01 ++#define PCI_CLASS_ISA 0x01 // obsolete ++#define PCI_CLASS_BRIDGE_EISA 0x02 ++#define PCI_CLASS_BRIDGE_MCA 0x03 ++#define PCI_CLASS_BRIDGE_P2P 0x04 ++#define PCI_CLASS_BRIDGE_PCMCIA 0x05 ++#define PCI_CLASS_BRIDGE_NUBUS 0x06 ++#define PCI_CLASS_BRIDGE_CARDBUS 0x07 ++#define PCI_CLASS_BRIDGE_RACEWAY 0x08 ++#define PCI_CLASS_BRIDGE_ISA_PDECODE 0x80 ++#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80 // obsolete ++ ++#define PCI_CLASS_SCC 0x07 // Simple communications controllers ++#define PCI_SUBCLASS_SERIAL 0x00 ++#define PCI_IF_GENERIC_XT 0x00 ++#define PCI_IF_16450 0x01 ++#define PCI_IF_16550 0x02 ++#define PCI_IF_16650 0x03 ++#define PCI_IF_16750 0x04 ++#define PCI_IF_16850 0x05 ++#define PCI_IF_16950 0x06 ++#define PCI_SUBCLASS_PARALLEL 0x01 ++#define PCI_IF_PARALLEL_PORT 0x00 ++#define PCI_IF_BI_DIR_PARALLEL_PORT 0x01 ++#define PCI_IF_ECP_PARALLEL_PORT 0x02 ++#define PCI_IF_1284_CONTROLLER 0x03 ++#define PCI_IF_1284_DEVICE 0xFE ++#define PCI_SUBCLASS_MULTIPORT_SERIAL 0x02 ++#define PCI_SUBCLASS_MODEM 0x03 ++#define PCI_IF_GENERIC_MODEM 0x00 ++#define PCI_IF_16450_MODEM 0x01 ++#define PCI_IF_16550_MODEM 0x02 ++#define PCI_IF_16650_MODEM 0x03 ++#define PCI_IF_16750_MODEM 0x04 ++#define PCI_SUBCLASS_OTHER 0x80 ++ ++#define PCI_CLASS_SYSTEM_PERIPHERAL 0x08 ++#define PCI_SUBCLASS_PIC 0x00 ++#define PCI_IF_8259_PIC 0x00 ++#define PCI_IF_ISA_PIC 0x01 ++#define PCI_IF_EISA_PIC 0x02 ++#define PCI_IF_APIC_CONTROLLER 0x10 // I/O APIC interrupt controller , 32 bye none-prefectable memory. ++#define PCI_IF_APIC_CONTROLLER2 0x20 ++#define PCI_SUBCLASS_TIMER 0x02 ++#define PCI_IF_8254_TIMER 0x00 ++#define PCI_IF_ISA_TIMER 0x01 ++#define PCI_EISA_TIMER 0x02 ++#define PCI_SUBCLASS_RTC 0x03 ++#define PCI_IF_GENERIC_RTC 0x00 ++#define PCI_IF_ISA_RTC 0x00 ++#define PCI_SUBCLASS_PNP_CONTROLLER 0x04 // HotPlug Controller ++ ++#define PCI_CLASS_INPUT_DEVICE 0x09 ++#define PCI_SUBCLASS_KEYBOARD 0x00 ++#define PCI_SUBCLASS_PEN 0x01 ++#define PCI_SUBCLASS_MOUSE_CONTROLLER 0x02 ++#define PCI_SUBCLASS_SCAN_CONTROLLER 0x03 ++#define PCI_SUBCLASS_GAMEPORT 0x04 ++ ++#define PCI_CLASS_DOCKING_STATION 0x0A ++ ++#define PCI_CLASS_PROCESSOR 0x0B ++#define PCI_SUBCLASS_PROC_386 0x00 ++#define PCI_SUBCLASS_PROC_486 0x01 ++#define PCI_SUBCLASS_PROC_PENTIUM 0x02 ++#define PCI_SUBCLASS_PROC_ALPHA 0x10 ++#define PCI_SUBCLASS_PROC_POWERPC 0x20 ++#define PCI_SUBCLASS_PROC_MIPS 0x30 ++#define PCI_SUBCLASS_PROC_CO_PORC 0x40 // Co-Processor ++ ++#define PCI_CLASS_SERIAL 0x0C ++#define PCI_CLASS_SERIAL_FIREWIRE 0x00 ++#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01 ++#define PCI_CLASS_SERIAL_SSA 0x02 ++#define PCI_CLASS_SERIAL_USB 0x03 ++#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04 ++#define PCI_CLASS_SERIAL_SMB 0x05 ++ ++#define PCI_CLASS_WIRELESS 0x0D ++#define PCI_SUBCLASS_IRDA 0x00 ++#define PCI_SUBCLASS_IR 0x01 ++#define PCI_SUBCLASS_RF 0x02 ++ ++#define PCI_CLASS_INTELLIGENT_IO 0x0E ++ ++#define PCI_CLASS_SATELLITE 0x0F ++#define PCI_SUBCLASS_TV 0x01 ++#define PCI_SUBCLASS_AUDIO 0x02 ++#define PCI_SUBCLASS_VOICE 0x03 ++#define PCI_SUBCLASS_DATA 0x04 ++ ++#define PCI_SECURITY_CONTROLLER 0x10 // Encryption and decryption controller ++#define PCI_SUBCLASS_NET_COMPUT 0x00 ++#define PCI_SUBCLASS_ENTERTAINMENT 0x10 ++ ++#define PCI_CLASS_DPIO 0x11 ++ ++#define IS_CLASS1(_p, c) ((_p)->Hdr.ClassCode[2] == (c)) ++#define IS_CLASS2(_p, c, s) (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s))) ++#define IS_CLASS3(_p, c, s, p) (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p))) ++ ++#define IS_PCI_DISPLAY(_p) IS_CLASS1 (_p, PCI_CLASS_DISPLAY) ++#define IS_PCI_VGA(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 0) ++#define IS_PCI_8514(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 1) ++#define IS_PCI_GFX(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_GFX, 0) ++#define IS_PCI_OLD(_p) IS_CLASS1 (_p, PCI_CLASS_OLD) ++#define IS_PCI_OLD_VGA(_p) IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) ++#define IS_PCI_IDE(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE) ++#define IS_PCI_SCSI(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI, 0) ++#define IS_PCI_RAID(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID, 0) ++#define IS_PCI_LPC(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA, 0) ++#define IS_PCI_P2P(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 0) ++#define IS_PCI_P2P_SUB(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 1) ++#define IS_PCI_USB(_p) IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB) ++ ++#define HEADER_TYPE_DEVICE 0x00 ++#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01 ++#define HEADER_TYPE_CARDBUS_BRIDGE 0x02 ++ ++#define HEADER_TYPE_MULTI_FUNCTION 0x80 ++#define HEADER_LAYOUT_CODE 0x7f ++ ++#define IS_PCI_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE)) ++#define IS_CARDBUS_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) ++#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) ++ ++#define PCI_DEVICE_ROMBAR 0x30 ++#define PCI_BRIDGE_ROMBAR 0x38 ++ ++#define PCI_MAX_BAR 0x0006 ++#define PCI_MAX_CONFIG_OFFSET 0x0100 ++ ++#define PCI_VENDOR_ID_OFFSET 0x00 ++#define PCI_DEVICE_ID_OFFSET 0x02 ++#define PCI_COMMAND_OFFSET 0x04 ++#define PCI_PRIMARY_STATUS_OFFSET 0x06 ++#define PCI_REVISION_ID_OFFSET 0x08 ++#define PCI_CLASSCODE_OFFSET 0x09 ++#define PCI_CACHELINE_SIZE_OFFSET 0x0C ++#define PCI_LATENCY_TIMER_OFFSET 0x0D ++#define PCI_HEADER_TYPE_OFFSET 0x0E ++#define PCI_BIST_OFFSET 0x0F ++#define PCI_BASE_ADDRESSREG_OFFSET 0x10 ++#define PCI_CARDBUS_CIS_OFFSET 0x28 ++#define PCI_SVID_OFFSET 0x2C // SubSystem Vendor id ++#define PCI_SUBSYSTEM_VENDOR_ID_OFFSET 0x2C ++#define PCI_SID_OFFSET 0x2E // SubSystem ID ++#define PCI_SUBSYSTEM_ID_OFFSET 0x2E ++#define PCI_EXPANSION_ROM_BASE 0x30 ++#define PCI_CAPBILITY_POINTER_OFFSET 0x34 ++#define PCI_INT_LINE_OFFSET 0x3C // Interrupt Line Register ++#define PCI_INT_PIN_OFFSET 0x3D // Interrupt Pin Register ++#define PCI_MAXGNT_OFFSET 0x3E // Max Grant Register ++#define PCI_MAXLAT_OFFSET 0x3F // Max Latency Register ++ ++#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET 0x3E ++#define PCI_BRIDGE_STATUS_REGISTER_OFFSET 0x1E ++ ++#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET 0x18 ++#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET 0x19 ++#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET 0x1a ++ ++typedef union { ++ struct { ++ UINT32 Reg : 8; ++ UINT32 Func : 3; ++ UINT32 Dev : 5; ++ UINT32 Bus : 8; ++ UINT32 Reserved : 7; ++ UINT32 Enable : 1; ++ } Bits; ++ UINT32 Uint32; ++} PCI_CONFIG_ACCESS_CF8; ++ ++#pragma pack() ++ ++#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 ++#define PCI_DATA_STRUCTURE_SIGNATURE SIGNATURE_32 ('P', 'C', 'I', 'R') ++#define PCI_CODE_TYPE_PCAT_IMAGE 0x00 ++#define PCI_CODE_TYPE_EFI_IMAGE 0x03 ++#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED 0x0001 ++ ++#define EFI_PCI_COMMAND_IO_SPACE 0x0001 ++#define EFI_PCI_COMMAND_MEMORY_SPACE 0x0002 ++#define EFI_PCI_COMMAND_BUS_MASTER 0x0004 ++#define EFI_PCI_COMMAND_SPECIAL_CYCLE 0x0008 ++#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE 0x0010 ++#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP 0x0020 ++#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND 0x0040 ++#define EFI_PCI_COMMAND_STEPPING_CONTROL 0x0080 ++#define EFI_PCI_COMMAND_SERR 0x0100 ++#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK 0x0200 ++ ++#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE 0x0001 ++#define EFI_PCI_BRIDGE_CONTROL_SERR 0x0002 ++#define EFI_PCI_BRIDGE_CONTROL_ISA 0x0004 ++#define EFI_PCI_BRIDGE_CONTROL_VGA 0x0008 ++#define EFI_PCI_BRIDGE_CONTROL_VGA_16 0x0010 ++#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT 0x0020 ++#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS 0x0040 ++#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK 0x0080 ++#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER 0x0100 ++#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER 0x0200 ++#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS 0x0400 ++#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR 0x0800 ++ ++// ++// Following are the PCI-CARDBUS bridge control bit ++// ++#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE 0x0080 ++#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE 0x0100 ++#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE 0x0200 ++#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE 0x0400 ++ ++// ++// Following are the PCI status control bit ++// ++#define EFI_PCI_STATUS_CAPABILITY 0x0010 ++#define EFI_PCI_STATUS_66MZ_CAPABLE 0x0020 ++#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE 0x0080 ++#define EFI_PCI_MASTER_DATA_PARITY_ERROR 0x0100 ++ ++#define EFI_PCI_CAPABILITY_PTR 0x34 ++#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14 ++ ++#pragma pack(1) ++typedef struct { ++ UINT16 Signature; // 0xaa55 ++ UINT8 Reserved[0x16]; ++ UINT16 PcirOffset; ++} PCI_EXPANSION_ROM_HEADER; ++ ++typedef struct { ++ UINT16 Signature; // 0xaa55 ++ UINT8 Size512; ++ UINT8 InitEntryPoint[3]; ++ UINT8 Reserved[0x12]; ++ UINT16 PcirOffset; ++} EFI_LEGACY_EXPANSION_ROM_HEADER; ++ ++typedef struct { ++ UINT32 Signature; // "PCIR" ++ UINT16 VendorId; ++ UINT16 DeviceId; ++ UINT16 Reserved0; ++ UINT16 Length; ++ UINT8 Revision; ++ UINT8 ClassCode[3]; ++ UINT16 ImageLength; ++ UINT16 CodeRevision; ++ UINT8 CodeType; ++ UINT8 Indicator; ++ UINT16 Reserved1; ++} PCI_DATA_STRUCTURE; ++ ++// ++// PCI Capability List IDs and records ++// ++#define EFI_PCI_CAPABILITY_ID_PMI 0x01 ++#define EFI_PCI_CAPABILITY_ID_AGP 0x02 ++#define EFI_PCI_CAPABILITY_ID_VPD 0x03 ++#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04 ++#define EFI_PCI_CAPABILITY_ID_MSI 0x05 ++#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06 ++#define EFI_PCI_CAPABILITY_ID_PCIX 0x07 ++ ++typedef struct { ++ UINT8 CapabilityID; ++ UINT8 NextItemPtr; ++} EFI_PCI_CAPABILITY_HDR; ++ ++// ++// Capability EFI_PCI_CAPABILITY_ID_PMI ++// ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ UINT16 PMC; ++ UINT16 PMCSR; ++ UINT8 BridgeExtention; ++ UINT8 Data; ++} EFI_PCI_CAPABILITY_PMI; ++ ++// ++// Capability EFI_PCI_CAPABILITY_ID_AGP ++// ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ UINT8 Rev; ++ UINT8 Reserved; ++ UINT32 Status; ++ UINT32 Command; ++} EFI_PCI_CAPABILITY_AGP; ++ ++// ++// Capability EFI_PCI_CAPABILITY_ID_VPD ++// ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ UINT16 AddrReg; ++ UINT32 DataReg; ++} EFI_PCI_CAPABILITY_VPD; ++ ++// ++// Capability EFI_PCI_CAPABILITY_ID_SLOTID ++// ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ UINT8 ExpnsSlotReg; ++ UINT8 ChassisNo; ++} EFI_PCI_CAPABILITY_SLOTID; ++ ++// ++// Capability EFI_PCI_CAPABILITY_ID_MSI ++// ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ UINT16 MsgCtrlReg; ++ UINT32 MsgAddrReg; ++ UINT16 MsgDataReg; ++} EFI_PCI_CAPABILITY_MSI32; ++ ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ UINT16 MsgCtrlReg; ++ UINT32 MsgAddrRegLsdw; ++ UINT32 MsgAddrRegMsdw; ++ UINT16 MsgDataReg; ++} EFI_PCI_CAPABILITY_MSI64; ++ ++// ++// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG ++// ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ // ++ // not finished - fields need to go here ++ // ++} EFI_PCI_CAPABILITY_HOTPLUG; ++ ++// ++// Capability EFI_PCI_CAPABILITY_ID_PCIX ++// ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ UINT16 CommandReg; ++ UINT32 StatusReg; ++} EFI_PCI_CAPABILITY_PCIX; ++ ++typedef struct { ++ EFI_PCI_CAPABILITY_HDR Hdr; ++ UINT16 SecStatusReg; ++ UINT32 StatusReg; ++ UINT32 SplitTransCtrlRegUp; ++ UINT32 SplitTransCtrlRegDn; ++} EFI_PCI_CAPABILITY_PCIX_BRDG; ++ ++#define DEVICE_ID_NOCARE 0xFFFF ++ ++#define PCI_ACPI_UNUSED 0 ++#define PCI_BAR_NOCHANGE 0 ++#define PCI_BAR_OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL ++#define PCI_BAR_EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL ++#define PCI_BAR_SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL ++#define PCI_BAR_DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL ++ ++#define PCI_BAR_IDX0 0x00 ++#define PCI_BAR_IDX1 0x01 ++#define PCI_BAR_IDX2 0x02 ++#define PCI_BAR_IDX3 0x03 ++#define PCI_BAR_IDX4 0x04 ++#define PCI_BAR_IDX5 0x05 ++#define PCI_BAR_ALL 0xFF ++ ++#pragma pack(pop) ++ ++// ++// NOTE: The following header files are included here for ++// compatibility consideration. ++// ++#include "pci23.h" ++#include "pci30.h" ++#include "EfiPci.h" ++ ++#endif +diff --git a/EfiRom/Include/IndustryStandard/pci23.h b/EfiRom/Include/IndustryStandard/pci23.h +new file mode 100644 +index 0000000..629baa2 +--- /dev/null ++++ b/EfiRom/Include/IndustryStandard/pci23.h +@@ -0,0 +1,24 @@ ++/** @file ++ Support for PCI 2.3 standard. ++ ++ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _PCI23_H ++#define _PCI23_H ++ ++//#include "pci22.h" ++ ++#define PCI_EXP_MAX_CONFIG_OFFSET 0x1000 ++#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10 ++ ++#endif +diff --git a/EfiRom/Include/IndustryStandard/pci30.h b/EfiRom/Include/IndustryStandard/pci30.h +new file mode 100644 +index 0000000..74c0fcf +--- /dev/null ++++ b/EfiRom/Include/IndustryStandard/pci30.h +@@ -0,0 +1,44 @@ ++/** @file ++ Support for PCI 3.0 standard. ++ ++ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef _PCI30_H ++#define _PCI30_H ++ ++//#include "pci23.h" ++ ++#define PCI_CLASS_MASS_STORAGE_SATADPA 0x06 ++ ++#pragma pack(push, 1) ++ ++typedef struct { ++ UINT32 Signature; // "PCIR" ++ UINT16 VendorId; ++ UINT16 DeviceId; ++ UINT16 DeviceListOffset; ++ UINT16 Length; ++ UINT8 Revision; ++ UINT8 ClassCode[3]; ++ UINT16 ImageLength; ++ UINT16 CodeRevision; ++ UINT8 CodeType; ++ UINT8 Indicator; ++ UINT16 MaxRuntimeImageLength; ++ UINT16 ConfigUtilityCodeHeaderOffset; ++ UINT16 DMTFCLPEntryPointOffset; ++} PCI_3_0_DATA_STRUCTURE; ++ ++#pragma pack(pop) ++ ++#endif +diff --git a/EfiRom/Include/X64/ProcessorBind.h b/EfiRom/Include/X64/ProcessorBind.h +new file mode 100644 +index 0000000..d3d0ef5 +--- /dev/null ++++ b/EfiRom/Include/X64/ProcessorBind.h +@@ -0,0 +1,194 @@ ++/** @file ++ Processor or Compiler specific defines and types x64 (Intel(r) EM64T, AMD64). ++ ++ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
++ ++ This program and the accompanying materials are licensed and made available ++ under the terms and conditions of the BSD License which accompanies this ++ distribution. The full text of the license may be found at ++ http://opensource.org/licenses/bsd-license.php ++ ++ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, ++ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. ++ ++**/ ++ ++#ifndef __PROCESSOR_BIND_H__ ++#define __PROCESSOR_BIND_H__ ++ ++// ++// Define the processor type so other code can make processor based choices ++// ++#define MDE_CPU_X64 ++ ++ ++// ++// Make sure we are useing the correct packing rules per EFI specification ++// ++#ifndef __GNUC__ ++#pragma pack() ++#endif ++ ++ ++#if _MSC_EXTENSIONS ++ ++// ++// Disable warning that make it impossible to compile at /W4 ++// This only works for Microsoft* tools ++// ++ ++// ++// Disabling bitfield type checking warnings. ++// ++#pragma warning ( disable : 4214 ) ++ ++// ++// Disabling the unreferenced formal parameter warnings. ++// ++#pragma warning ( disable : 4100 ) ++ ++// ++// Disable slightly different base types warning as CHAR8 * can not be set ++// to a constant string. ++// ++#pragma warning ( disable : 4057 ) ++ ++// ++// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning ++// ++#pragma warning ( disable : 4127 ) ++ ++ ++#endif ++ ++ ++#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L) ++ // ++ // No ANSI C 2000 stdint.h integer width declarations, so define equivalents ++ // ++ ++ #if _MSC_EXTENSIONS ++ ++ ++ // ++ // use Microsoft C complier dependent integer width types ++ // ++ typedef unsigned __int64 UINT64; ++ typedef __int64 INT64; ++ typedef unsigned __int32 UINT32; ++ typedef __int32 INT32; ++ typedef unsigned short UINT16; ++ typedef unsigned short CHAR16; ++ typedef short INT16; ++ typedef unsigned char BOOLEAN; ++ typedef unsigned char UINT8; ++ typedef char CHAR8; ++ typedef char INT8; ++ #else ++ #ifdef _EFI_P64 ++ // ++ // P64 - is Intel Itanium(TM) speak for pointers being 64-bit and longs and ints ++ // are 32-bits ++ // ++ typedef unsigned long long UINT64; ++ typedef long long INT64; ++ typedef unsigned int UINT32; ++ typedef int INT32; ++ typedef unsigned short CHAR16; ++ typedef unsigned short UINT16; ++ typedef short INT16; ++ typedef unsigned char BOOLEAN; ++ typedef unsigned char UINT8; ++ typedef char CHAR8; ++ typedef char INT8; ++ #else ++ // ++ // Assume LP64 - longs and pointers are 64-bit. Ints are 32-bit. ++ // ++ typedef unsigned long UINT64; ++ typedef long INT64; ++ typedef unsigned int UINT32; ++ typedef int INT32; ++ typedef unsigned short UINT16; ++ typedef unsigned short CHAR16; ++ typedef short INT16; ++ typedef unsigned char BOOLEAN; ++ typedef unsigned char UINT8; ++ typedef char CHAR8; ++ typedef char INT8; ++ #endif ++ #endif ++ ++ #define UINT8_MAX 0xff ++ ++#else ++ // ++ // Use ANSI C 2000 stdint.h integer width declarations ++ // ++ #include ++ typedef uint8_t BOOLEAN; ++ typedef int8_t INT8; ++ typedef uint8_t UINT8; ++ typedef int16_t INT16; ++ typedef uint16_t UINT16; ++ typedef int32_t INT32; ++ typedef uint32_t UINT32; ++ typedef int64_t INT64; ++ typedef uint64_t UINT64; ++ typedef char CHAR8; ++ typedef uint16_t CHAR16; ++ ++#endif ++ ++typedef UINT64 UINTN; ++typedef INT64 INTN; ++ ++ ++// ++// Processor specific defines ++// ++#define MAX_BIT 0x8000000000000000ULL ++#define MAX_2_BITS 0xC000000000000000ULL ++ ++// ++// Maximum legal Itanium-based address ++// ++#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL ++ ++// ++// Modifier to ensure that all protocol member functions and EFI intrinsics ++// use the correct C calling convention. All protocol member functions and ++// EFI intrinsics are required to modify thier member functions with EFIAPI. ++// ++#if _MSC_EXTENSIONS ++ /// ++ /// Define the standard calling convention reguardless of optimization level. ++ /// __cdecl is Microsoft* specific C extension. ++ /// ++ #define EFIAPI __cdecl ++#elif __GNUC__ ++ /// ++ /// Define the standard calling convention reguardless of optimization level. ++ /// efidecl is an extension to GCC that supports the differnece between x64 ++ /// GCC ABI and x64 Microsoft* ABI. EFI is closer to the Microsoft* ABI and ++ /// EFIAPI makes sure the right ABI is used for public interfaces. ++ /// eficecl is a work in progress and we do not yet have the compiler ++ /// ++ #define EFIAPI ++#else ++ #define EFIAPI ++#endif ++ ++// ++// The Microsoft* C compiler can removed references to unreferenced data items ++// if the /OPT:REF linker option is used. We defined a macro as this is a ++// a non standard extension ++// ++#if _MSC_EXTENSIONS ++ #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) ++#else ++ #define GLOBAL_REMOVE_IF_UNREFERENCED ++#endif ++ ++#endif ++ +diff --git a/EfiRom/License.txt b/EfiRom/License.txt +new file mode 100644 +index 0000000..5f530a6 +--- /dev/null ++++ b/EfiRom/License.txt +@@ -0,0 +1,25 @@ ++Copyright (c) 2013, Intel Corporation. All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions ++are met: ++ ++* Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++* Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in ++ the documentation and/or other materials provided with the ++ distribution. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ++ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ++POSSIBILITY OF SUCH DAMAGE. +-- +1.8.3.1 + diff --git a/SOURCES/0003-add-custom-Makefile-for-EfiRom-RHEL-only.patch b/SOURCES/0003-add-custom-Makefile-for-EfiRom-RHEL-only.patch new file mode 100644 index 0000000..f90b3e7 --- /dev/null +++ b/SOURCES/0003-add-custom-Makefile-for-EfiRom-RHEL-only.patch @@ -0,0 +1,75 @@ +From 3e446e7832cd4f66b352d25092a5dccaa78bd122 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Wed, 21 Oct 2015 11:08:59 +0200 +Subject: add custom Makefile for EfiRom (RHEL only) + +Message-id: <1410295825-13989-3-git-send-email-lersek@redhat.com> +Patchwork-id: 60928 +O-Subject: [RHEL-7.1 ipxe PATCH 2/4] add custom Makefile for EfiRom (RHEL only) +Bugzilla: 1084561 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Gerd Hoffmann + +The build flags have been captured from the BaseTools build log. + +Signed-off-by: Laszlo Ersek +Signed-off-by: Miroslav Rezanina +(cherry picked from commit a20ead07b711057d778645392fdda048f83cd321) +--- + EfiRom/Makefile | 43 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + create mode 100644 EfiRom/Makefile + +diff --git a/EfiRom/Makefile b/EfiRom/Makefile +new file mode 100644 +index 0000000..30914d9 +--- /dev/null ++++ b/EfiRom/Makefile +@@ -0,0 +1,43 @@ ++.POSIX: ++ ++CFLAGS = -fshort-wchar -fno-strict-aliasing -I Common -I Include -I Include/X64 ++LDFLAGS = -s ++ ++EfiRom: EfiRom.o CommonLib.o EfiUtilityMsgs.o ParseInf.o EfiCompress.o ++ $(CC) -o EfiRom $(LDFLAGS) EfiRom.o CommonLib.o EfiUtilityMsgs.o \ ++ ParseInf.o EfiCompress.o ++ ++EfiRom.o: EfiRom.c Common/EfiUtilityMsgs.h Include/Common/UefiBaseTypes.h \ ++ Include/Common/BaseTypes.h Include/X64/ProcessorBind.h Common/ParseInf.h \ ++ Common/MemoryFile.h EfiRom.h Include/IndustryStandard/PeImage.h \ ++ Include/IndustryStandard/pci22.h Include/IndustryStandard/pci23.h \ ++ Include/IndustryStandard/pci30.h Include/IndustryStandard/EfiPci.h \ ++ Include/IndustryStandard/pci30.h Common/Compress.h Common/CommonLib.h \ ++ Include/Common/BuildVersion.h Common/CommonLib.h ++ $(CC) $(CFLAGS) -c EfiRom.c ++ ++CommonLib.o: Common/CommonLib.c Common/CommonLib.h \ ++ Include/Common/UefiBaseTypes.h Include/Common/BaseTypes.h \ ++ Include/X64/ProcessorBind.h Include/Common/BuildVersion.h \ ++ Common/EfiUtilityMsgs.h ++ $(CC) $(CFLAGS) -c Common/CommonLib.c ++ ++EfiUtilityMsgs.o: Common/EfiUtilityMsgs.c Common/EfiUtilityMsgs.h \ ++ Include/Common/UefiBaseTypes.h Include/Common/BaseTypes.h \ ++ Include/X64/ProcessorBind.h ++ $(CC) $(CFLAGS) -c Common/EfiUtilityMsgs.c ++ ++ParseInf.o: Common/ParseInf.c Common/EfiUtilityMsgs.h \ ++ Include/Common/UefiBaseTypes.h Include/Common/BaseTypes.h \ ++ Include/X64/ProcessorBind.h Common/ParseInf.h Common/MemoryFile.h \ ++ Common/CommonLib.h Include/Common/BuildVersion.h ++ $(CC) $(CFLAGS) -c Common/ParseInf.c ++ ++EfiCompress.o: Common/EfiCompress.c Common/Compress.h Common/CommonLib.h \ ++ Include/Common/UefiBaseTypes.h Include/Common/BaseTypes.h \ ++ Include/X64/ProcessorBind.h Include/Common/BuildVersion.h ++ $(CC) $(CFLAGS) -c Common/EfiCompress.c ++ ++clean: ++ rm -f EfiRom EfiRom.o CommonLib.o EfiUtilityMsgs.o ParseInf.o \ ++ EfiCompress.o +-- +1.8.3.1 + diff --git a/SOURCES/0005-Use-spec-compliant-timeouts.patch b/SOURCES/0005-Use-spec-compliant-timeouts.patch new file mode 100644 index 0000000..ceabce8 --- /dev/null +++ b/SOURCES/0005-Use-spec-compliant-timeouts.patch @@ -0,0 +1,98 @@ +From c3c4dcf208faeb694df7474743dd785f159d30f6 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Wed, 21 Oct 2015 11:18:40 +0200 +Subject: Use spec compliant timeouts + +Message-id: <20150428212403.31299.29391.stgit@gimli.home> +Patchwork-id: 64951 +O-Subject: [RHEL7.2 ipxe PATCH 2/2] [dhcp][RHEL-only] Use spec compliant timeouts +Bugzilla: 1196352 +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek + +Use local config to override iPXE's abbreviated DHCP timeouts using +the recommended values for spec compliance. This matches the state +of RHEL6 gPXE DHCP timeouts after bz968474 + bz1206042 + +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +(cherry picked from commit 7038f41c0131d263de5165b416500009acdbf550) +--- + src/config/local/.gitignore | 1 - + src/config/local/dhcp.h | 62 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 62 insertions(+), 1 deletion(-) + delete mode 100644 src/config/local/.gitignore + create mode 100644 src/config/local/dhcp.h + +diff --git a/src/config/local/dhcp.h b/src/config/local/dhcp.h +new file mode 100644 +index 0000000..83df5b8 +--- /dev/null ++++ b/src/config/local/dhcp.h +@@ -0,0 +1,62 @@ ++/* ++ * Downstream localization ++ * ++ * For RHEL, use spec compliant DHCP timeouts (bz1196352) ++ */ ++ ++/* ++ * PXE spec defines timeouts of 4, 8, 16, 32 seconds ++ */ ++#undef DHCP_DISC_START_TIMEOUT_SEC ++#define DHCP_DISC_START_TIMEOUT_SEC 4 ++#undef DHCP_DISC_END_TIMEOUT_SEC ++#define DHCP_DISC_END_TIMEOUT_SEC 32 ++ ++/* ++ * Elapsed time used for early break waiting for ProxyDHCP, this therefore ++ * needs to be less than the cumulative time for the first 2 timeouts. ++ */ ++#undef DHCP_DISC_PROXY_TIMEOUT_SEC ++#define DHCP_DISC_PROXY_TIMEOUT_SEC 11 ++ ++/* ++ * Approximate PXE spec requirement using minimum timeout (0.25s) for ++ * timeouts of 0.25, 0.5, 1, 2, 4 ++ */ ++#undef DHCP_REQ_START_TIMEOUT_SEC ++#define DHCP_REQ_START_TIMEOUT_SEC 0 ++#undef DHCP_REQ_END_TIMEOUT_SEC ++#define DHCP_REQ_END_TIMEOUT_SEC 4 ++ ++/* ++ * Same as normal request phase, except non-fatal, so we extend the timer ++ * to 8 and set the early timeout to an elapsed time value that causes a ++ * break after the 4 second timeout. At least that's what we'd like to do, ++ * but our timer operates at 18Hz and has a minimum resolution of 7 cycles. ++ * Therefore the above quarter-second starting timeout looks more like ++ * 0.39s, 0.78s, 1.56s, 3.11s, 6.22s. If we had an ideal timer, we could ++ * set the timeout to 7s (0.25 + 0.5 + 1 + 2 + 4 = 7.75s) and exit without ++ * failure when the timer rolls over to 8s. With our timer, we get 0.39 + ++ * 0.78 + 1.56 + 3.11 = 5.84s. The next timeout would take us to 12.06s ++ * (+6.22). That seems like a long time to wait for an optional reply, so ++ * we reduce the early timeout to 5s to exit before the timer exceeds the ++ * max and causes a failure. This still adds one extra cycle vs the ++ * upstream defaults. ++ */ ++#undef DHCP_PROXY_START_TIMEOUT_SEC ++#define DHCP_PROXY_START_TIMEOUT_SEC 0 ++#undef DHCP_PROXY_END_TIMEOUT_SEC ++#define DHCP_PROXY_END_TIMEOUT_SEC 8 ++#undef DHCP_REQ_PROXY_TIMEOUT_SEC ++#define DHCP_REQ_PROXY_TIMEOUT_SEC 5 ++ ++/* ++ * Same as above, retry each server using our approximation of standard ++ * timeouts and exit before timer induced failure. ++ */ ++#undef PXEBS_START_TIMEOUT_SEC ++#define PXEBS_START_TIMEOUT_SEC 0 ++#undef PXEBS_END_TIMEOUT_SEC ++#define PXEBS_END_TIMEOUT_SEC 8 ++#undef PXEBS_MAX_TIMEOUT_SEC ++#define PXEBS_MAX_TIMEOUT_SEC 5 +-- +1.8.3.1 + diff --git a/SOURCES/0008-Enable-IPv6-protocol-in-non-QEMU-builds.patch b/SOURCES/0008-Enable-IPv6-protocol-in-non-QEMU-builds.patch new file mode 100644 index 0000000..7f47df4 --- /dev/null +++ b/SOURCES/0008-Enable-IPv6-protocol-in-non-QEMU-builds.patch @@ -0,0 +1,54 @@ +From ebdaa4f4f00c71cc200861fac96066a1e38dd7f1 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Tue, 28 Jun 2016 14:23:19 +0200 +Subject: Enable IPv6 protocol in non-QEMU builds + +RH-Author: Ladi Prosek +Message-id: <1467123799-26467-1-git-send-email-lprosek@redhat.com> +Patchwork-id: 70822 +O-Subject: [RHEL7.3 ipxe PATCH v2] Enable IPv6 protocol in non-QEMU builds +Bugzilla: 1350167 +RH-Acked-by: Lucas Alvares Gomes +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Neil Horman +RH-Acked-by: Laszlo Ersek + +Enables IPv6 in ipxe-bootimgs and ipxe-roms while keeping the +QEMU package ipxe-roms-qemu unaffected. This change depends on +the include order specified in upstream commit c801cb29d647. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1350167 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=11281457 + +Signed-off-by: Ladi Prosek +Signed-off-by: Miroslav Rezanina +(cherry picked from commit 35f4006845436816a651b2f154a37d38d02305d9) +--- + src/config/local/general.h | 3 +++ + src/config/local/qemu/general.h | 3 +++ + 2 files changed, 6 insertions(+) + create mode 100644 src/config/local/qemu/general.h + +diff --git a/src/config/local/general.h b/src/config/local/general.h +index 5814511..47d0e1a 100644 +--- a/src/config/local/general.h ++++ b/src/config/local/general.h +@@ -1,3 +1,6 @@ + #undef ROM_BANNER_TIMEOUT + #define ROM_BANNER_TIMEOUT 0 + ++/* Enable IPv6. Note that we leave this defined only in non-QEMU builds. ++ * Find the corresponding undef in src/config/local/qemu/general.h */ ++#define NET_PROTO_IPV6 +diff --git a/src/config/local/qemu/general.h b/src/config/local/qemu/general.h +new file mode 100644 +index 0000000..ef7b5e4 +--- /dev/null ++++ b/src/config/local/qemu/general.h +@@ -0,0 +1,3 @@ ++/* IPv6 is enabled only in non-QEMU builds. Find the corresponding define ++ * in src/config/local/general.h */ ++#undef NET_PROTO_IPV6 +-- +1.8.3.1 + diff --git a/SOURCES/0009-Strip-802.1Q-VLAN-0-priority-tags.patch b/SOURCES/0009-Strip-802.1Q-VLAN-0-priority-tags.patch new file mode 100644 index 0000000..ac31349 --- /dev/null +++ b/SOURCES/0009-Strip-802.1Q-VLAN-0-priority-tags.patch @@ -0,0 +1,150 @@ +From 2f542b36b149b32325f85ce89a6823ff97a6d675 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Mon, 11 Jul 2016 14:17:36 +0200 +Subject: Strip 802.1Q VLAN 0 priority tags + +RH-Author: Ladi Prosek +Message-id: <1468246656-15560-1-git-send-email-lprosek@redhat.com> +Patchwork-id: 71112 +O-Subject: [RHEL7.3 ipxe PATCH] [netdevice] Strip 802.Q VLAN 0 priority tags +Bugzilla: 1316329 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Xiao Wang + +iPXE was unable to receive priority tagged packets specified in +the 802.1Q standard and supported by all major networking stacks. + +This commit adds a new function net_pull_tags which is called by +all consumers of incoming packets after stripping their link-layer +headers. + +Upstream patch: +http://lists.ipxe.org/pipermail/ipxe-devel/2016-July/005099.html + +There is a difference between the upstream patch and this patch in the +path prefix of "interface/pxe/pxe_undi.c" because we don't have upstream +commit f468f12b1eca. + +Signed-off-by: Ladi Prosek +Signed-off-by: Miroslav Rezanina +--- + src/arch/x86/interface/pxe/pxe_undi.c | 6 +++++ + src/include/ipxe/netdevice.h | 2 ++ + src/interface/efi/efi_snp.c | 7 ++++++ + src/net/netdevice.c | 44 +++++++++++++++++++++++++++++++++++ + 4 files changed, 59 insertions(+) + +diff --git a/src/arch/x86/interface/pxe/pxe_undi.c b/src/arch/x86/interface/pxe/pxe_undi.c +index 2eb6817..2ea1451 100644 +--- a/src/arch/x86/interface/pxe/pxe_undi.c ++++ b/src/arch/x86/interface/pxe/pxe_undi.c +@@ -976,6 +976,12 @@ static PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { + } + ll_hlen = ( len - iob_len ( iobuf ) ); + ++ /* Strip link-layer-independent headers */ ++ if ( ( rc = net_pull_tags ( iobuf, pxe_netdev, &net_proto ) ) != 0 ) { ++ /* Assume unknown net_proto */ ++ net_proto = 0; ++ } ++ + /* Determine network-layer protocol */ + switch ( net_proto ) { + case htons ( ETH_P_IP ): +diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h +index d498ab6..27dda45 100644 +--- a/src/include/ipxe/netdevice.h ++++ b/src/include/ipxe/netdevice.h +@@ -726,6 +726,8 @@ extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, + extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev, + uint16_t net_proto, const void *ll_dest, + const void *ll_source, unsigned int flags ); ++extern int net_pull_tags ( struct io_buffer *iobuf, struct net_device *netdev, ++ uint16_t *net_proto ); + extern void net_poll ( void ); + extern struct net_device_configurator * + find_netdev_configurator ( const char *name ); +diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c +index 9c1b14d..6b974d4 100644 +--- a/src/interface/efi/efi_snp.c ++++ b/src/interface/efi/efi_snp.c +@@ -813,6 +813,13 @@ efi_snp_receive ( EFI_SIMPLE_NETWORK_PROTOCOL *snp, + goto out_bad_ll_header; + } + ++ /* Strip link-layer-independent headers */ ++ if ( ( rc = net_pull_tags ( iobuf, snpdev->netdev, &iob_net_proto ) ) ) { ++ DBGC ( snpdev, "SNPDEV %p could not parse tags: %s\n", ++ snpdev, strerror ( rc ) ); ++ goto out_bad_ll_header; ++ } ++ + /* Return link-layer header parameters to caller, if required */ + if ( ll_header_len ) + *ll_header_len = ll_protocol->ll_header_len; +diff --git a/src/net/netdevice.c b/src/net/netdevice.c +index 71a37ec..fdf541b 100644 +--- a/src/net/netdevice.c ++++ b/src/net/netdevice.c +@@ -1044,6 +1044,44 @@ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev, + } + + /** ++ * Strip extra link-layer-independent tags from a received packet ++ * ++ * @v iobuf I/O buffer ++ * @v netdev Network device ++ * @v net_proto Network-layer protocol, in network-byte order ++ * @ret rc Return status code ++ * ++ * This function should be called after stripping link-layer headers but ++ * before inspecting the network-layer protocol. ++ */ ++int net_pull_tags ( struct io_buffer *iobuf, struct net_device *netdev, ++ uint16_t *net_proto ) { ++ struct vlan_header *vlanhdr; ++ uint16_t tag; ++ ++ /* Strip 802.1Q VLAN 0 priority tags if present */ ++ while ( *net_proto == htons ( ETH_P_8021Q ) ) { ++ if ( iob_len ( iobuf ) < sizeof ( *vlanhdr ) ) { ++ DBG ( "VLAN header too short at %zd bytes (min %zd bytes)\n", ++ iob_len ( iobuf ), sizeof ( *vlanhdr ) ); ++ return -EINVAL; ++ } ++ vlanhdr = ( struct vlan_header * ) iobuf->data; ++ tag = VLAN_TAG ( ntohs ( vlanhdr->tci ) ); ++ ++ if ( tag == 0 && ! vlan_find ( netdev, tag ) ) { ++ /* VLAN 0, strip and continue */ ++ *net_proto = vlanhdr->net_proto; ++ iob_pull ( iobuf, sizeof ( *vlanhdr ) ); ++ } else { ++ /* Real VLAN tag, leave it alone */ ++ break; ++ } ++ } ++ return 0; ++} ++ ++/** + * Poll the network stack + * + * This polls all interfaces for received packets, and processes +@@ -1094,6 +1132,12 @@ void net_poll ( void ) { + continue; + } + ++ /* Remove link-layer-independent headers */ ++ if ( ( rc = net_pull_tags ( iobuf, netdev, &net_proto ) ) ) { ++ free_iob ( iobuf ); ++ continue; ++ } ++ + /* Hand packet to network layer */ + if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev, + net_proto, ll_dest, +-- +1.8.3.1 + diff --git a/SOURCES/USAGE b/SOURCES/USAGE new file mode 100644 index 0000000..6b7f529 --- /dev/null +++ b/SOURCES/USAGE @@ -0,0 +1,16 @@ +To create a bootable floppy, type + cat /usr/share/gpxe/gpxe.dsk > /dev/fd0 +where /dev/fd0 is your floppy drive. This will erase any +data already on the disk. + +To create a bootable USB key, type + cat /usr/share/gpxe/gpxe.usb > /dev/sdX +where /dev/sdX is your USB key, and is *not* a real hard +disk on your system. This will erase any data already on +the USB key. + +To create a bootable CD-ROM, burn the ISO image +/usr/share/gpxe/gpxe.iso to a blank CD-ROM. + +http://www.etherboot.org/wiki/pxechaining describes how to chain boot +from PXE into gPXE using /usr/share/gpxe/undionly.kpxe. diff --git a/SOURCES/ipxe-vlan-cmds.patch b/SOURCES/ipxe-vlan-cmds.patch new file mode 100644 index 0000000..c5dfa43 --- /dev/null +++ b/SOURCES/ipxe-vlan-cmds.patch @@ -0,0 +1,12 @@ +diff -up ./src/config/general.h.vlan ./src/config/general.h +--- ./src/config/general.h.vlan 2018-10-09 13:11:42.940904753 -0400 ++++ ./src/config/general.h 2018-10-09 13:12:03.258821711 -0400 +@@ -140,7 +140,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + //#define TIME_CMD /* Time commands */ + //#define DIGEST_CMD /* Image crypto digest commands */ + //#define LOTEST_CMD /* Loopback testing commands */ +-//#define VLAN_CMD /* VLAN commands */ ++#define VLAN_CMD /* VLAN commands */ + //#define PXE_CMD /* PXE commands */ + //#define REBOOT_CMD /* Reboot command */ + //#define POWEROFF_CMD /* Power off command */ diff --git a/SPECS/ipxe.spec b/SPECS/ipxe.spec new file mode 100644 index 0000000..f9a5226 --- /dev/null +++ b/SPECS/ipxe.spec @@ -0,0 +1,393 @@ + +# Resulting binary formats we want from iPXE +%global formats rom + +# PCI IDs (vendor,product) of the ROMS we want for QEMU +# +# pcnet32: 0x1022 0x2000 +# ne2k_pci: 0x10ec 0x8029 +# e1000: 0x8086 0x100e +# rtl8139: 0x10ec 0x8139 +# virtio-net: 0x1af4 0x1000 +# e1000e: 0x8086 0x10d3 +%global qemuroms 10222000 10ec8029 8086100e 10ec8139 1af41000 808610d3 + +# We only build the ROMs if on an x86 build host. The resulting +# binary RPM will be noarch, so other archs will still be able +# to use the binary ROMs. +# +# We do cross-compilation for 32->64-bit, but not for other arches +# because EDK II does not support big-endian hosts. +%global buildarches x86_64 + +# debugging firmwares does not goes the same way as a normal program. +# moreover, all architectures providing debuginfo for a single noarch +# package is currently clashing in koji, so don't bother. +%global debug_package %{nil} + +# Upstream don't do "releases" :-( So we're going to use the date +# as the version, and a GIT hash as the release. Generate new GIT +# snapshots using the folowing commands: +# +# $ hash=`git log -1 --format='%h'` +# $ date=`date '+%Y%m%d'` +# $ git archive --output ipxe-${date}-git${hash}.tar.gz --prefix ipxe-${date}-git${hash}/ ${hash} +# +# And then change these two: + +%global date 20180825 +%global hash 133f4c + +Name: ipxe +Version: %{date} +Release: 2.git%{hash}%{?dist} +Summary: A network boot loader + +Group: System Environment/Base +License: GPLv2 and BSD +URL: http://ipxe.org/ + +Source0: %{name}-%{date}-git%{hash}.tar.gz +Source1: USAGE + +Patch0001: 0001-Add-redhat-directory.patch +Patch0002: 0002-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch +Patch0003: 0003-add-custom-Makefile-for-EfiRom-RHEL-only.patch +Patch0005: 0005-Use-spec-compliant-timeouts.patch +Patch0008: 0008-Enable-IPv6-protocol-in-non-QEMU-builds.patch +Patch0009: 0009-Strip-802.1Q-VLAN-0-priority-tags.patch +Patch0010: ipxe-vlan-cmds.patch + +%ifarch %{buildarches} +BuildRequires: perl +BuildRequires: syslinux +BuildRequires: mtools +BuildRequires: mkisofs +BuildRequires: binutils-devel +BuildRequires: xz-devel + +Obsoletes: gpxe <= 1.0.1 + +%package bootimgs +Summary: Network boot loader images in bootable USB, CD, floppy and GRUB formats +Group: Development/Tools +BuildArch: noarch +Obsoletes: gpxe-bootimgs <= 1.0.1 + +%package roms +Summary: Network boot loader roms in .rom format +Group: Development/Tools +Requires: %{name}-roms-qemu = %{version}-%{release} +BuildArch: noarch +Obsoletes: gpxe-roms <= 1.0.1 + +%package roms-qemu +Summary: Network boot loader roms supported by QEMU, .rom format +Group: Development/Tools +BuildArch: noarch +Obsoletes: gpxe-roms-qemu <= 1.0.1 + +%description bootimgs +iPXE is an open source network bootloader. It provides a direct +replacement for proprietary PXE ROMs, with many extra features such as +DNS, HTTP, iSCSI, etc. + +This package contains the iPXE boot images in USB, CD, floppy, and PXE +UNDI formats. + +%description roms +iPXE is an open source network bootloader. It provides a direct +replacement for proprietary PXE ROMs, with many extra features such as +DNS, HTTP, iSCSI, etc. + +This package contains the iPXE roms in .rom format. + + +%description roms-qemu +iPXE is an open source network bootloader. It provides a direct +replacement for proprietary PXE ROMs, with many extra features such as +DNS, HTTP, iSCSI, etc. + +This package contains the iPXE ROMs for devices emulated by QEMU, in +.rom format. +%endif + +%description +iPXE is an open source network bootloader. It provides a direct +replacement for proprietary PXE ROMs, with many extra features such as +DNS, HTTP, iSCSI, etc. + +%prep +%setup -q -n %{name}-%{hash} +cp -a %{SOURCE1} . + +patch_command="patch -p1 -s" + +%patch0001 -p1 +%patch0002 -p1 +%patch0003 -p1 +%patch0005 -p1 +%patch0008 -p1 +%patch0009 -p1 +%patch0010 -p1 + +%build +%ifarch %{buildarches} +# The src/Makefile.housekeeping relies on .git/index existing +# but since we pass GITVERSION= to make, we don't actally need +# it to be the real deal, so just touch it to let the build pass +mkdir .git +touch .git/index + +ISOLINUX_BIN=/usr/share/syslinux/isolinux.bin +cd src +# ath9k drivers are too big for an Option ROM +rm -rf drivers/net/ath/ath9k + +#make %{?_smp_mflags} bin/undionly.kpxe bin/ipxe.{dsk,iso,usb,lkrn} allroms \ +make bin/undionly.kpxe bin/ipxe.{dsk,iso,usb,lkrn} allroms \ + ISOLINUX_BIN=${ISOLINUX_BIN} NO_WERROR=1 V=1 \ + GITVERSION=%{hash} + +make bin-x86_64-efi/ipxe.efi \ + NO_WERROR=1 V=1 GITVERSION=%{hash} + +# build EfiRom +cd ../EfiRom +make %{?_smp_mflags} +cd ../src + +# build roms with efi support for qemu +for rom in %qemuroms; do + make NO_WERROR=1 V=1 GITVERSION=%{hash} CONFIG=qemu \ + bin/${rom}.rom bin-x86_64-efi/${rom}.efidrv + vid="0x${rom%%????}" + did="0x${rom#????}" + ../EfiRom/EfiRom -f "$vid" -i "$did" --pci23 \ + -b bin/${rom}.rom \ + -ec bin-x86_64-efi/${rom}.efidrv \ + -o bin/${rom}.combined.rom + ../EfiRom/EfiRom -d bin/${rom}.combined.rom + mv bin/${rom}.combined.rom bin/${rom}.rom +done + +%endif + +%install +%ifarch %{buildarches} +mkdir -p %{buildroot}/%{_datadir}/%{name}/ + +pushd src + +cp -a bin/undionly.kpxe bin/ipxe.{iso,usb,dsk,lkrn} bin-x86_64-efi/ipxe.efi \ + %{buildroot}/%{_datadir}/%{name}/ + +cd bin +for fmt in %{formats};do + for img in *.${fmt};do + if [ -e $img ]; then + cat $img /dev/zero | dd bs=256k count=1 of=$img.tmp iflag=fullblock + install -D -p -m 0644 $img.tmp %{buildroot}/%{_datadir}/%{name}/$img + rm $img.tmp + echo %{_datadir}/%{name}/$img >> ../../${fmt}.list + fi + done +done +popd + +# the roms supported by qemu will be packaged separatedly +# remove from the main rom list and add them to qemu.list +for fmt in rom ;do + for rom in %{qemuroms} ; do + sed -i -e "/\/${rom}.${fmt}/d" ${fmt}.list + echo %{_datadir}/%{name}/${rom}.${fmt} >> qemu.${fmt}.list + done +done +%endif + +%ifarch %{buildarches} +%files bootimgs +%dir %{_datadir}/%{name} +%{_datadir}/%{name}/ipxe.iso +%{_datadir}/%{name}/ipxe.usb +%{_datadir}/%{name}/ipxe.dsk +%{_datadir}/%{name}/ipxe.lkrn +%{_datadir}/%{name}/ipxe.efi +%{_datadir}/%{name}/undionly.kpxe +%doc COPYING COPYING.GPLv2 USAGE + +%files roms -f rom.list +%dir %{_datadir}/%{name} +%doc COPYING COPYING.GPLv2 + +%files roms-qemu -f qemu.rom.list +%dir %{_datadir}/%{name} +%doc COPYING COPYING.GPLv2 +%endif + +%changelog +* Mon Jan 14 2019 Neil Horman - 20180825-2.git133f4c.el7 +- Enable vcreate and vdestroy commands (1583231) + +* Mon Dec 17 2018 Miroslav Rezanina - 20180825-1.git133f4c.el7 +- Rebase to newer upstream [bz#1597210] +- Resolves: bz#1597210 + (Rebase ipxe to latest upstream) + +* Thu Aug 17 2017 Miroslav Rezanina - 20170123-2.git4e85b27.el7 +- ipxe-Support-VIRTIO_NET_F_IOMMU_PLATFORM.patch [bz#1467887] +- Resolves: bz#1467887 + (iommu platform support for ipxe) + +* Fri Mar 10 2017 Miroslav Rezanina - 20170123-1.git4e85b27.el7 +- Rebase to commit 4e85b27 [bz#1413781] +- Resolves: bz#1413781 + (Rebase ipxe for RHEL-7.4) + +* Thu Sep 01 2016 Miroslav Rezanina - 20160127-5.git6366fa7a.el7 +- ipxe-Strip-802.1Q-VLAN-0-priority-tags.patch [bz#1316329] +- Resolves: bz#1316329 + ([RFE] Properly Handle 8021.Q VID 0 Frames, as new vlan model in linux kernel does.) + +* Tue Aug 02 2016 Miroslav Rezanina - 20160127-4.git6366fa7a.el7 +- ipxe-Send-TCP-keepalives-on-idle-established-connections.patch [bz#1322056] +- ipxe-enable-e1000e-rom.patch [bz#1361534] +- Resolves: bz#1322056 + (ipxe freeze during HTTP download with last RPM) +- Resolves: bz#1361534 + (RFE: Integrate e1000e implementation in downstream QEMU) + +* Fri Jul 15 2016 Miroslav Rezanina - 20160127-3.git6366fa7a.el7 +- ipxe-Add-pci_find_next_capability.patch [bz#1242850] +- ipxe-Add-virtio-1.0-constants-and-data-structures.patch [bz#1242850] +- ipxe-Add-virtio-1.0-PCI-support.patch [bz#1242850] +- ipxe-Add-virtio-net-1.0-support.patch [bz#1242850] +- ipxe-Renumber-virtio_pci_region-flags.patch [bz#1242850] +- ipxe-Fix-virtio-pci-logging.patch [bz#1242850] +- Resolves: bz#1242850 + (Ipxe can not recognize "network device" when enable virtio-1 of virtio-net-pci) + +* Tue Jul 12 2016 Miroslav Rezanina - 20160127-2.git6366fa7a.el7 +- ipxe-Enable-IPv6-protocol-in-non-QEMU-builds.patch [bz#1350167] +- Resolves: bz#1350167 + (ipxe: enable IPV6) + +* Wed Mar 09 2016 Miroslav Rezanina - 20160127-1.git6366fa7a.el7 +- Rebase to 6366fa7a +- Resolves: bz#1297853 + +* Mon Sep 15 2014 Miroslav Rezanina - 20130517-6.gitc4bce43.el7 +- ipxe-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch [bz#1084561] +- ipxe-add-custom-Makefile-for-EfiRom-RHEL-only.patch [bz#1084561] +- ipxe-redhat-build-and-install-combined-legacy-UEFI-roms-f.patch [bz#1084561] +- Resolves: bz#1084561 + (RFE: ship UEFI drivers for ipxe in RHEL-7.y) + +* Wed Mar 05 2014 Miroslav Rezanina - 20130517-5.gitc4bce43.el7 +- ipxe-Enable-infrastructure-to-specify-an-autoboot-device-.patch [bz#1031518] +- ipxe-Allow-prefix-to-specify-a-PCI-autoboot-device-locati.patch [bz#1031518] +- ipxe-Store-boot-bus-dev.fn-address-as-autoboot-device-loc.patch [bz#1031518] +- ipxe-Ignore-PCI-autoboot-device-location-if-set-to-00-00..patch [bz#1031518] +- ipxe-Revert-Remove-2-second-startup-wait.patch [bz#857123] +- ipxe-Allow-ROM-banner-timeout-to-be-configured-independen.patch [bz#857123] +- ipxe-Customize-ROM-banner-timeout.patch [bz#857123] +- Resolves: bz#1031518 + (iPXE does not honor specified boot device) +- Resolves: bz#857123 + (Guests never get an iPXE prompt) + +* Tue Feb 11 2014 Miroslav Rezanina - 20130517-4.gitc4bce43 +- ipxe-Use-next-server-from-filename-s-settings-block.patch [bz#1062644] +- Resolves: bz#1062644 + (pxe boot fails if next-server details come from a different dhcp server) + +* Wed Jan 15 2014 Miroslav Rezanina - 20130517-3.gitc4bce43 +- pad ROMs to 256k (rhbz #1038630) +- Resolves: rhbz# 1038630 + +* Fri Dec 27 2013 Daniel Mach - 20130517-2.gitc4bce43 +- Mass rebuild 2013-12-27 + +* Fri May 17 2013 Daniel P. Berrange - 20130517-1.gitc4bce43 +- Update to latest upstream snapshot + +* Fri May 17 2013 Daniel P. Berrange - 20130103-3.git717279a +- Fix build with GCC 4.8 (rhbz #914091) + +* Thu Feb 14 2013 Fedora Release Engineering - 20130103-2.git717279a +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Thu Jan 3 2013 Daniel P. Berrange - 20130103-1.git717279a +- Updated to latest GIT snapshot + +* Thu Jul 19 2012 Fedora Release Engineering - 20120328-2.gitaac9718 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed Mar 28 2012 Daniel P. Berrange - 20120328-1.gitaac9718 +- Update to newer upstream + +* Fri Mar 23 2012 Daniel P. Berrange - 20120319-3.git0b2c788 +- Remove more defattr statements + +* Tue Mar 20 2012 Daniel P. Berrange - 20120319-2.git0b2c788 +- Remove BuildRoot & rm -rf of it in install/clean sections +- Remove defattr in file section +- Switch to use global, instead of define for macros +- Add note about Patch1 not going upstream +- Split BRs across lines for easier readability + +* Mon Feb 27 2012 Daniel P. Berrange - 20120319-1.git0b2c788 +- Initial package based on gPXE + +* Fri Jan 13 2012 Fedora Release Engineering - 1.0.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Feb 21 2011 Matt Domsch - 1.0.1-4 +- don't use -Werror, it flags a failure that is not a failure for gPXE + +* Mon Feb 21 2011 Matt Domsch - 1.0.1-3 +- Fix virtio-net ethernet frame length (patch by cra), fixes BZ678789 + +* Tue Feb 08 2011 Fedora Release Engineering - 1.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Thu Aug 5 2010 Matt Domsch - 1.0.1-1 +- New drivers: Intel e1000, e1000e, igb, EFI snpnet, JMicron jme, + Neterion X3100, vxge, pcnet32. +- Bug fixes and improvements to drivers, wireless, DHCP, iSCSI, + COMBOOT, and EFI. +* Tue Feb 2 2010 Matt Domsch - 1.0.0-1 +- bugfix release, also adds wireless card support +- bnx2 builds again +- drop our one patch + +* Tue Oct 27 2009 Matt Domsch - 0.9.9-1 +- new upstream version 0.9.9 +-- plus patches from git up to 20090818 which fix build errors and + other release-critical bugs. +-- 0.9.9: added Attansic L1E and sis190/191 ethernet drivers. Fixes + and updates to e1000 and 3c90x drivers. +-- 0.9.8: new commands: time, sleep, md5sum, sha1sum. 802.11 wireless + support with Realtek 8180/8185 and non-802.11n Atheros drivers. + New Marvell Yukon-II gigabet Ethernet driver. HTTP redirection + support. SYSLINUX floppy image type (.sdsk) with usable file + system. Rewrites, fixes, and updates to 3c90x, forcedeth, pcnet32, + e1000, and hermon drivers. + +* Mon Oct 5 2009 Matt Domsch - 0.9.7-6 +- move rtl8029 from -roms to -roms-qemu for qemu ne2k_pci NIC (BZ 526776) + +* Fri Jul 24 2009 Fedora Release Engineering - 0.9.7-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue May 19 2009 Matt Domsch - 0.9.7-4 +- add undionly.kpxe to -bootimgs + +* Tue May 12 2009 Matt Domsch - 0.9.7-3 +- handle isolinux changing paths + +* Sat May 9 2009 Matt Domsch - 0.9.7-2 +- add dist tag + +* Thu Mar 26 2009 Matt Domsch - 0.9.7-1 +- Initial release based on etherboot spec