diff --git a/.gitignore b/.gitignore index 936feab..03454cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/ipxe-20130517-gitc4bce43.tar.gz +SOURCES/ipxe-6366fa7a.tar.bz2 diff --git a/.ipxe.metadata b/.ipxe.metadata index 116f3a6..0e1816a 100644 --- a/.ipxe.metadata +++ b/.ipxe.metadata @@ -1 +1 @@ -fee6ca099c3c36675ec939a219119978d62e04b4 SOURCES/ipxe-20130517-gitc4bce43.tar.gz +47792b25b354cbfbb59bdd3ee34d787e8a342b08 SOURCES/ipxe-6366fa7a.tar.bz2 diff --git a/SOURCES/0002-Customize-ROM-banner-timeout.patch b/SOURCES/0002-Customize-ROM-banner-timeout.patch new file mode 100644 index 0000000..e1dd8fb --- /dev/null +++ b/SOURCES/0002-Customize-ROM-banner-timeout.patch @@ -0,0 +1,43 @@ +From 3dc49f939c6192c94f8088e65a41ba37ed1baebc Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Wed, 21 Oct 2015 11:03:07 +0200 +Subject: Customize ROM banner timeout + +RH-Author: Alex Williamson +Message-id: <20140304154230.6292.69267.stgit@bling.home> +Patchwork-id: 58011 +O-Subject: [RHEL7 ipxe PATCH v2 3/3] [rhel7] Customize ROM banner timeout +Bugzilla: 857123 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Vlad Yasevich +RH-Acked-by: Richard Jones +RH-Acked-by: Stefan Hajnoczi + +Bugzilla: 857123 +Upstream: N/A (downstream customization) + +Users want some opportunity to interact with the iPXE shell, but +tools like libguestfs want to boot as quickly as possible. Create +a compromise by disabling the interactive banner prompt during ROM +initialization, but retaining it when we actually attempt to boot +from the device. + +Signed-off-by: Alex Williamson +Signed-off-by: Miroslav Rezanina +--- + src/config/local/general.h | 3 +++ + 1 file changed, 3 insertions(+) + 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 ++ +-- +2.5.0 + diff --git a/SOURCES/0003-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch b/SOURCES/0003-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch new file mode 100644 index 0000000..ae05098 --- /dev/null +++ b/SOURCES/0003-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch @@ -0,0 +1,8946 @@ +From 781fa846a6b51b80fb08afe8ac2b8e862006082f 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 +--- + 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. +-- +2.5.0 + diff --git a/SOURCES/0004-add-custom-Makefile-for-EfiRom-RHEL-only.patch b/SOURCES/0004-add-custom-Makefile-for-EfiRom-RHEL-only.patch new file mode 100644 index 0000000..7938418 --- /dev/null +++ b/SOURCES/0004-add-custom-Makefile-for-EfiRom-RHEL-only.patch @@ -0,0 +1,74 @@ +From a20ead07b711057d778645392fdda048f83cd321 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 +--- + 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 +-- +2.5.0 + diff --git a/SOURCES/0006-Use-spec-compliant-timeouts.patch b/SOURCES/0006-Use-spec-compliant-timeouts.patch new file mode 100644 index 0000000..355b931 --- /dev/null +++ b/SOURCES/0006-Use-spec-compliant-timeouts.patch @@ -0,0 +1,97 @@ +From 7038f41c0131d263de5165b416500009acdbf550 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 +--- + 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 +-- +2.5.0 + diff --git a/SOURCES/ipxe-Add-pci_find_next_capability.patch b/SOURCES/ipxe-Add-pci_find_next_capability.patch new file mode 100644 index 0000000..44f19e2 --- /dev/null +++ b/SOURCES/ipxe-Add-pci_find_next_capability.patch @@ -0,0 +1,133 @@ +From ae9193b7e61405ac1fe7db0a453713f211af00c3 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Wed, 13 Jul 2016 13:28:34 +0200 +Subject: [PATCH 1/6] Add pci_find_next_capability() + +RH-Author: Ladi Prosek +Message-id: <1468416519-11107-2-git-send-email-lprosek@redhat.com> +Patchwork-id: 71167 +O-Subject: [RHEL7.3 ipxe PATCH v2 1/6] [pci] Add pci_find_next_capability() +Bugzilla: 1242850 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +PCI devices may support more capabilities of the same type (for +example PCI_CAP_ID_VNDR) and there was no way to discover all of them. +This commit adds a new API pci_find_next_capability which provides +this functionality. It would typically be used like so: + + for (pos = pci_find_capability(pci, PCI_CAP_ID_VNDR); + pos > 0; + pos = pci_find_next_capability(pci, pos, PCI_CAP_ID_VNDR)) { + ... + } + +Signed-off-by: Ladi Prosek +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael Brown +(cherry picked from commit 237949491860bf1ca6f704e586bf723b7d8001e7) +Signed-off-by: Ladi Prosek +Signed-off-by: Miroslav Rezanina +--- + src/drivers/bus/pciextra.c | 54 +++++++++++++++++++++++++++++++++++----------- + src/include/ipxe/pci.h | 2 ++ + 2 files changed, 43 insertions(+), 13 deletions(-) + +diff --git a/src/drivers/bus/pciextra.c b/src/drivers/bus/pciextra.c +index 82287fb..3082d8a 100644 +--- a/src/drivers/bus/pciextra.c ++++ b/src/drivers/bus/pciextra.c +@@ -3,6 +3,24 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + #include + #include + ++static int pci_find_capability_common ( struct pci_device *pci, ++ uint8_t pos, int cap ) { ++ uint8_t id; ++ int ttl = 48; ++ ++ while ( ttl-- && pos >= 0x40 ) { ++ pos &= ~3; ++ pci_read_config_byte ( pci, pos + PCI_CAP_ID, &id ); ++ DBG ( "PCI Capability: %d\n", id ); ++ if ( id == 0xff ) ++ break; ++ if ( id == cap ) ++ return pos; ++ pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &pos ); ++ } ++ return 0; ++} ++ + /** + * Look for a PCI capability + * +@@ -17,9 +35,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + */ + int pci_find_capability ( struct pci_device *pci, int cap ) { + uint16_t status; +- uint8_t pos, id; ++ uint8_t pos; + uint8_t hdr_type; +- int ttl = 48; + + pci_read_config_word ( pci, PCI_STATUS, &status ); + if ( ! ( status & PCI_STATUS_CAP_LIST ) ) +@@ -36,17 +53,28 @@ int pci_find_capability ( struct pci_device *pci, int cap ) { + pci_read_config_byte ( pci, PCI_CB_CAPABILITY_LIST, &pos ); + break; + } +- while ( ttl-- && pos >= 0x40 ) { +- pos &= ~3; +- pci_read_config_byte ( pci, pos + PCI_CAP_ID, &id ); +- DBG ( "PCI Capability: %d\n", id ); +- if ( id == 0xff ) +- break; +- if ( id == cap ) +- return pos; +- pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &pos ); +- } +- return 0; ++ return pci_find_capability_common ( pci, pos, cap ); ++} ++ ++/** ++ * Look for another PCI capability ++ * ++ * @v pci PCI device to query ++ * @v pos Address of the current capability ++ * @v cap Capability code ++ * @ret address Address of capability, or 0 if not found ++ * ++ * Determine whether or not a device supports a given PCI capability ++ * starting the search at a given address within the device's PCI ++ * configuration space. Returns the address of the next capability ++ * structure within the device's PCI configuration space, or 0 if the ++ * device does not support another such capability. ++ */ ++int pci_find_next_capability ( struct pci_device *pci, int pos, int cap ) { ++ uint8_t new_pos; ++ ++ pci_read_config_byte ( pci, pos + PCI_CAP_NEXT, &new_pos ); ++ return pci_find_capability_common ( pci, new_pos, cap ); + } + + /** +diff --git a/src/include/ipxe/pci.h b/src/include/ipxe/pci.h +index 89d9d80..0c6bc7e 100644 +--- a/src/include/ipxe/pci.h ++++ b/src/include/ipxe/pci.h +@@ -286,6 +286,8 @@ extern int pci_find_driver ( struct pci_device *pci ); + extern int pci_probe ( struct pci_device *pci ); + extern void pci_remove ( struct pci_device *pci ); + extern int pci_find_capability ( struct pci_device *pci, int capability ); ++extern int pci_find_next_capability ( struct pci_device *pci, ++ int pos, int capability ); + extern unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ); + + /** +-- +1.8.3.1 + diff --git a/SOURCES/ipxe-Add-virtio-1.0-PCI-support.patch b/SOURCES/ipxe-Add-virtio-1.0-PCI-support.patch new file mode 100644 index 0000000..a5aea71 --- /dev/null +++ b/SOURCES/ipxe-Add-virtio-1.0-PCI-support.patch @@ -0,0 +1,704 @@ +From 7d9a148e44a99d81e4a075eb571e8f8cbf5d03e0 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Wed, 13 Jul 2016 13:28:36 +0200 +Subject: [PATCH 3/6] Add virtio 1.0 PCI support + +RH-Author: Ladi Prosek +Message-id: <1468416519-11107-4-git-send-email-lprosek@redhat.com> +Patchwork-id: 71169 +O-Subject: [RHEL7.3 ipxe PATCH v2 3/6] [virtio] Add virtio 1.0 PCI support +Bugzilla: 1242850 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +This commit adds support for driving virtio 1.0 PCI devices. In +addition to various helpers, a number of vpm_ functions are introduced +to be used instead of their legacy vp_ counterparts when accessing +virtio 1.0 (aka modern) devices. + +Signed-off-by: Ladi Prosek +Reviewed-by: Michael S. Tsirkin +Modified-by: Michael Brown +Signed-off-by: Michael Brown +(cherry picked from commit 8a055a2a707f8cb92e7b62512391e03b4e25cae2) +Signed-off-by: Ladi Prosek +Signed-off-by: Miroslav Rezanina +--- + src/drivers/bus/virtio-pci.c | 352 ++++++++++++++++++++++++++++++++++++++++- + src/drivers/bus/virtio-ring.c | 17 +- + src/drivers/net/virtio-net.c | 5 +- + src/include/ipxe/errfile.h | 1 + + src/include/ipxe/virtio-pci.h | 147 +++++++++++++++++ + src/include/ipxe/virtio-ring.h | 6 +- + 6 files changed, 516 insertions(+), 12 deletions(-) + +diff --git a/src/drivers/bus/virtio-pci.c b/src/drivers/bus/virtio-pci.c +index fbef067..494da28 100644 +--- a/src/drivers/bus/virtio-pci.c ++++ b/src/drivers/bus/virtio-pci.c +@@ -11,10 +11,14 @@ + * + */ + ++#include "errno.h" ++#include "byteswap.h" + #include "etherboot.h" + #include "ipxe/io.h" +-#include "ipxe/virtio-ring.h" ++#include "ipxe/pci.h" ++#include "ipxe/reboot.h" + #include "ipxe/virtio-pci.h" ++#include "ipxe/virtio-ring.h" + + int vp_find_vq(unsigned int ioaddr, int queue_index, + struct vring_virtqueue *vq) +@@ -30,19 +34,19 @@ int vp_find_vq(unsigned int ioaddr, int queue_index, + + num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); + if (!num) { +- printf("ERROR: queue size is 0\n"); ++ DBG("VIRTIO-PCI ERROR: queue size is 0\n"); + return -1; + } + + if (num > MAX_QUEUE_NUM) { +- printf("ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); ++ DBG("VIRTIO-PCI ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); + return -1; + } + + /* check if the queue is already active */ + + if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { +- printf("ERROR: queue already active\n"); ++ DBG("VIRTIO-PCI ERROR: queue already active\n"); + return -1; + } + +@@ -62,3 +66,343 @@ int vp_find_vq(unsigned int ioaddr, int queue_index, + + return num; + } ++ ++#define CFG_POS(vdev, field) \ ++ (vdev->cfg_cap_pos + offsetof(struct virtio_pci_cfg_cap, field)) ++ ++static void prep_pci_cfg_cap(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, ++ size_t offset, u32 length) ++{ ++ pci_write_config_byte(vdev->pci, CFG_POS(vdev, cap.bar), region->bar); ++ pci_write_config_dword(vdev->pci, CFG_POS(vdev, cap.length), length); ++ pci_write_config_dword(vdev->pci, CFG_POS(vdev, cap.offset), ++ (intptr_t)(region->base + offset)); ++} ++ ++void vpm_iowrite8(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, u8 data, size_t offset) ++{ ++ switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { ++ case VIRTIO_PCI_REGION_MEMORY: ++ writeb(data, region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PORT: ++ outb(data, region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PCI_CONFIG: ++ prep_pci_cfg_cap(vdev, region, offset, 1); ++ pci_write_config_byte(vdev->pci, CFG_POS(vdev, pci_cfg_data), data); ++ break; ++ default: ++ assert(0); ++ break; ++ } ++} ++ ++void vpm_iowrite16(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, u16 data, size_t offset) ++{ ++ data = cpu_to_le16(data); ++ switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { ++ case VIRTIO_PCI_REGION_MEMORY: ++ writew(data, region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PORT: ++ outw(data, region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PCI_CONFIG: ++ prep_pci_cfg_cap(vdev, region, offset, 2); ++ pci_write_config_word(vdev->pci, CFG_POS(vdev, pci_cfg_data), data); ++ break; ++ default: ++ assert(0); ++ break; ++ } ++} ++ ++void vpm_iowrite32(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, u32 data, size_t offset) ++{ ++ data = cpu_to_le32(data); ++ switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { ++ case VIRTIO_PCI_REGION_MEMORY: ++ writel(data, region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PORT: ++ outl(data, region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PCI_CONFIG: ++ prep_pci_cfg_cap(vdev, region, offset, 4); ++ pci_write_config_dword(vdev->pci, CFG_POS(vdev, pci_cfg_data), data); ++ break; ++ default: ++ assert(0); ++ break; ++ } ++} ++ ++u8 vpm_ioread8(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, size_t offset) ++{ ++ uint8_t data; ++ switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { ++ case VIRTIO_PCI_REGION_MEMORY: ++ data = readb(region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PORT: ++ data = inb(region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PCI_CONFIG: ++ prep_pci_cfg_cap(vdev, region, offset, 1); ++ pci_read_config_byte(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data); ++ break; ++ default: ++ assert(0); ++ data = 0; ++ break; ++ } ++ return data; ++} ++ ++u16 vpm_ioread16(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, size_t offset) ++{ ++ uint16_t data; ++ switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { ++ case VIRTIO_PCI_REGION_MEMORY: ++ data = readw(region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PORT: ++ data = inw(region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PCI_CONFIG: ++ prep_pci_cfg_cap(vdev, region, offset, 2); ++ pci_read_config_word(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data); ++ break; ++ default: ++ assert(0); ++ data = 0; ++ break; ++ } ++ return le16_to_cpu(data); ++} ++ ++u32 vpm_ioread32(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, size_t offset) ++{ ++ uint32_t data; ++ switch (region->flags & VIRTIO_PCI_REGION_TYPE_MASK) { ++ case VIRTIO_PCI_REGION_MEMORY: ++ data = readw(region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PORT: ++ data = inw(region->base + offset); ++ break; ++ case VIRTIO_PCI_REGION_PCI_CONFIG: ++ prep_pci_cfg_cap(vdev, region, offset, 4); ++ pci_read_config_dword(vdev->pci, CFG_POS(vdev, pci_cfg_data), &data); ++ break; ++ default: ++ assert(0); ++ data = 0; ++ break; ++ } ++ return le32_to_cpu(data); ++} ++ ++int virtio_pci_find_capability(struct pci_device *pci, uint8_t cfg_type) ++{ ++ int pos; ++ uint8_t type, bar; ++ ++ for (pos = pci_find_capability(pci, PCI_CAP_ID_VNDR); ++ pos > 0; ++ pos = pci_find_next_capability(pci, pos, PCI_CAP_ID_VNDR)) { ++ ++ pci_read_config_byte(pci, pos + offsetof(struct virtio_pci_cap, ++ cfg_type), &type); ++ pci_read_config_byte(pci, pos + offsetof(struct virtio_pci_cap, ++ bar), &bar); ++ ++ /* Ignore structures with reserved BAR values */ ++ if (bar > 0x5) { ++ continue; ++ } ++ ++ if (type == cfg_type) { ++ return pos; ++ } ++ } ++ return 0; ++} ++ ++int virtio_pci_map_capability(struct pci_device *pci, int cap, size_t minlen, ++ u32 align, u32 start, u32 size, ++ struct virtio_pci_region *region) ++{ ++ u8 bar; ++ u32 offset, length, base_raw; ++ unsigned long base; ++ ++ pci_read_config_byte(pci, cap + offsetof(struct virtio_pci_cap, bar), &bar); ++ pci_read_config_dword(pci, cap + offsetof(struct virtio_pci_cap, offset), ++ &offset); ++ pci_read_config_dword(pci, cap + offsetof(struct virtio_pci_cap, length), ++ &length); ++ ++ if (length <= start) { ++ DBG("VIRTIO-PCI bad capability len %u (>%u expected)\n", length, start); ++ return -EINVAL; ++ } ++ if (length - start < minlen) { ++ DBG("VIRTIO-PCI bad capability len %u (>=%zu expected)\n", length, minlen); ++ return -EINVAL; ++ } ++ length -= start; ++ if (start + offset < offset) { ++ DBG("VIRTIO-PCI map wrap-around %u+%u\n", start, offset); ++ return -EINVAL; ++ } ++ offset += start; ++ if (offset & (align - 1)) { ++ DBG("VIRTIO-PCI offset %u not aligned to %u\n", offset, align); ++ return -EINVAL; ++ } ++ if (length > size) { ++ length = size; ++ } ++ ++ if (minlen + offset < minlen || ++ minlen + offset > pci_bar_size(pci, PCI_BASE_ADDRESS(bar))) { ++ DBG("VIRTIO-PCI map virtio %zu@%u out of range on bar %i length %lu\n", ++ minlen, offset, ++ bar, (unsigned long)pci_bar_size(pci, PCI_BASE_ADDRESS(bar))); ++ return -EINVAL; ++ } ++ ++ region->base = NULL; ++ region->length = length; ++ region->bar = bar; ++ ++ base = pci_bar_start(pci, PCI_BASE_ADDRESS(bar)); ++ if (base) { ++ pci_read_config_dword(pci, PCI_BASE_ADDRESS(bar), &base_raw); ++ ++ if (base_raw & PCI_BASE_ADDRESS_SPACE_IO) { ++ /* Region accessed using port I/O */ ++ region->base = (void *)(base + offset); ++ region->flags = VIRTIO_PCI_REGION_PORT; ++ } else { ++ /* Region mapped into memory space */ ++ region->base = ioremap(base + offset, length); ++ region->flags = VIRTIO_PCI_REGION_MEMORY; ++ } ++ } ++ if (!region->base) { ++ /* Region accessed via PCI config space window */ ++ region->base = (void *)(intptr_t)offset; ++ region->flags = VIRTIO_PCI_REGION_PCI_CONFIG; ++ } ++ return 0; ++} ++ ++void virtio_pci_unmap_capability(struct virtio_pci_region *region) ++{ ++ unsigned region_type = region->flags & VIRTIO_PCI_REGION_TYPE_MASK; ++ if (region_type == VIRTIO_PCI_REGION_MEMORY) { ++ iounmap(region->base); ++ } ++} ++ ++void vpm_notify(struct virtio_pci_modern_device *vdev, ++ struct vring_virtqueue *vq) ++{ ++ vpm_iowrite16(vdev, &vq->notification, (u16)vq->queue_index, 0); ++} ++ ++int vpm_find_vqs(struct virtio_pci_modern_device *vdev, ++ unsigned nvqs, struct vring_virtqueue *vqs) ++{ ++ unsigned i; ++ struct vring_virtqueue *vq; ++ u16 size, off; ++ u32 notify_offset_multiplier; ++ int err; ++ ++ if (nvqs > vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(num_queues))) { ++ return -ENOENT; ++ } ++ ++ /* Read notify_off_multiplier from config space. */ ++ pci_read_config_dword(vdev->pci, ++ vdev->notify_cap_pos + offsetof(struct virtio_pci_notify_cap, ++ notify_off_multiplier), ++ ¬ify_offset_multiplier); ++ ++ for (i = 0; i < nvqs; i++) { ++ /* Select the queue we're interested in */ ++ vpm_iowrite16(vdev, &vdev->common, (u16)i, COMMON_OFFSET(queue_select)); ++ ++ /* Check if queue is either not available or already active. */ ++ size = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_size)); ++ /* QEMU has a bug where queues don't revert to inactive on device ++ * reset. Skip checking the queue_enable field until it is fixed. ++ */ ++ if (!size /*|| vpm_ioread16(vdev, &vdev->common.queue_enable)*/) ++ return -ENOENT; ++ ++ if (size & (size - 1)) { ++ DBG("VIRTIO-PCI %p: bad queue size %u", vdev, size); ++ return -EINVAL; ++ } ++ ++ vq = &vqs[i]; ++ vq->queue_index = i; ++ ++ /* get offset of notification word for this vq */ ++ off = vpm_ioread16(vdev, &vdev->common, COMMON_OFFSET(queue_notify_off)); ++ vq->vring.num = size; ++ ++ vring_init(&vq->vring, size, (unsigned char *)vq->queue); ++ ++ /* activate the queue */ ++ vpm_iowrite16(vdev, &vdev->common, size, COMMON_OFFSET(queue_size)); ++ ++ vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.desc), ++ COMMON_OFFSET(queue_desc_lo), ++ COMMON_OFFSET(queue_desc_hi)); ++ vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.avail), ++ COMMON_OFFSET(queue_avail_lo), ++ COMMON_OFFSET(queue_avail_hi)); ++ vpm_iowrite64(vdev, &vdev->common, virt_to_phys(vq->vring.used), ++ COMMON_OFFSET(queue_used_lo), ++ COMMON_OFFSET(queue_used_hi)); ++ ++ err = virtio_pci_map_capability(vdev->pci, ++ vdev->notify_cap_pos, 2, 2, ++ off * notify_offset_multiplier, 2, ++ &vq->notification); ++ if (err) { ++ goto err_map_notify; ++ } ++ } ++ ++ /* Select and activate all queues. Has to be done last: once we do ++ * this, there's no way to go back except reset. ++ */ ++ for (i = 0; i < nvqs; i++) { ++ vq = &vqs[i]; ++ vpm_iowrite16(vdev, &vdev->common, (u16)vq->queue_index, ++ COMMON_OFFSET(queue_select)); ++ vpm_iowrite16(vdev, &vdev->common, 1, COMMON_OFFSET(queue_enable)); ++ } ++ return 0; ++ ++err_map_notify: ++ /* Undo the virtio_pci_map_capability calls. */ ++ while (i-- > 0) { ++ virtio_pci_unmap_capability(&vqs[i].notification); ++ } ++ return err; ++} +diff --git a/src/drivers/bus/virtio-ring.c b/src/drivers/bus/virtio-ring.c +index e55b6d0..98e787e 100644 +--- a/src/drivers/bus/virtio-ring.c ++++ b/src/drivers/bus/virtio-ring.c +@@ -18,8 +18,8 @@ FILE_LICENCE ( GPL2_OR_LATER ); + + #include "etherboot.h" + #include "ipxe/io.h" +-#include "ipxe/virtio-ring.h" + #include "ipxe/virtio-pci.h" ++#include "ipxe/virtio-ring.h" + + #define BUG() do { \ + printf("BUG: failure at %s:%d/%s()!\n", \ +@@ -122,7 +122,8 @@ void vring_add_buf(struct vring_virtqueue *vq, + wmb(); + } + +-void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) ++void vring_kick(struct virtio_pci_modern_device *vdev, unsigned int ioaddr, ++ struct vring_virtqueue *vq, int num_added) + { + struct vring *vr = &vq->vring; + +@@ -130,7 +131,13 @@ void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added) + vr->avail->idx += num_added; + + mb(); +- if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY)) +- vp_notify(ioaddr, vq->queue_index); ++ if (!(vr->used->flags & VRING_USED_F_NO_NOTIFY)) { ++ if (vdev) { ++ /* virtio 1.0 */ ++ vpm_notify(vdev, vq); ++ } else { ++ /* legacy virtio */ ++ vp_notify(ioaddr, vq->queue_index); ++ } ++ } + } +- +diff --git a/src/drivers/net/virtio-net.c b/src/drivers/net/virtio-net.c +index 533ccb0..446bbd6 100644 +--- a/src/drivers/net/virtio-net.c ++++ b/src/drivers/net/virtio-net.c +@@ -24,14 +24,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + + #include + #include ++#include + #include + #include + #include + #include + #include + #include +-#include + #include ++#include + #include "virtio-net.h" + + /* +@@ -135,7 +136,7 @@ static void virtnet_enqueue_iob ( struct net_device *netdev, + virtnet, iobuf, vq_idx ); + + vring_add_buf ( vq, list, out, in, iobuf, 0 ); +- vring_kick ( virtnet->ioaddr, vq, 1 ); ++ vring_kick ( NULL, virtnet->ioaddr, vq, 1 ); + } + + /** Try to keep rx virtqueue filled with iobufs +diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h +index 65b4d9c..a828dc3 100644 +--- a/src/include/ipxe/errfile.h ++++ b/src/include/ipxe/errfile.h +@@ -185,6 +185,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + #define ERRFILE_intelxvf ( ERRFILE_DRIVER | 0x00790000 ) + #define ERRFILE_smsc95xx ( ERRFILE_DRIVER | 0x007a0000 ) + #define ERRFILE_acm ( ERRFILE_DRIVER | 0x007b0000 ) ++#define ERRFILE_virtio_pci ( ERRFILE_DRIVER | 0x007f0000 ) + + #define ERRFILE_aoe ( ERRFILE_NET | 0x00000000 ) + #define ERRFILE_arp ( ERRFILE_NET | 0x00010000 ) +diff --git a/src/include/ipxe/virtio-pci.h b/src/include/ipxe/virtio-pci.h +index 8076f20..c7452c8 100644 +--- a/src/include/ipxe/virtio-pci.h ++++ b/src/include/ipxe/virtio-pci.h +@@ -97,6 +97,44 @@ struct virtio_pci_common_cfg { + __le32 queue_used_hi; /* read-write */ + }; + ++/* Virtio 1.0 PCI region descriptor. We support memory mapped I/O, port I/O, ++ * and PCI config space access via the cfg PCI capability as a fallback. */ ++struct virtio_pci_region { ++ void *base; ++ size_t length; ++ u8 bar; ++ ++/* How to interpret the base field */ ++#define VIRTIO_PCI_REGION_TYPE_MASK 0x00000003 ++/* The base field is a memory address */ ++#define VIRTIO_PCI_REGION_MEMORY 0x00000000 ++/* The base field is a port address */ ++#define VIRTIO_PCI_REGION_PORT 0x00000001 ++/* The base field is an offset within the PCI bar */ ++#define VIRTIO_PCI_REGION_PCI_CONFIG 0x00000002 ++ unsigned flags; ++}; ++ ++/* Virtio 1.0 device state */ ++struct virtio_pci_modern_device { ++ struct pci_device *pci; ++ ++ /* VIRTIO_PCI_CAP_PCI_CFG position */ ++ int cfg_cap_pos; ++ ++ /* VIRTIO_PCI_CAP_COMMON_CFG data */ ++ struct virtio_pci_region common; ++ ++ /* VIRTIO_PCI_CAP_DEVICE_CFG data */ ++ struct virtio_pci_region device; ++ ++ /* VIRTIO_PCI_CAP_ISR_CFG data */ ++ struct virtio_pci_region isr; ++ ++ /* VIRTIO_PCI_CAP_NOTIFY_CFG data */ ++ int notify_cap_pos; ++}; ++ + static inline u32 vp_get_features(unsigned int ioaddr) + { + return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES); +@@ -156,6 +194,115 @@ static inline void vp_del_vq(unsigned int ioaddr, int queue_index) + outl(0, ioaddr + VIRTIO_PCI_QUEUE_PFN); + } + ++struct vring_virtqueue; ++ + int vp_find_vq(unsigned int ioaddr, int queue_index, + struct vring_virtqueue *vq); ++ ++/* Virtio 1.0 I/O routines abstract away the three possible HW access ++ * mechanisms - memory, port I/O, and PCI cfg space access. Also built-in ++ * are endianness conversions - to LE on write and from LE on read. */ ++ ++void vpm_iowrite8(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, u8 data, size_t offset); ++ ++void vpm_iowrite16(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, u16 data, size_t offset); ++ ++void vpm_iowrite32(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, u32 data, size_t offset); ++ ++static inline void vpm_iowrite64(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, ++ u64 data, size_t offset_lo, size_t offset_hi) ++{ ++ vpm_iowrite32(vdev, region, (u32)data, offset_lo); ++ vpm_iowrite32(vdev, region, data >> 32, offset_hi); ++} ++ ++u8 vpm_ioread8(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, size_t offset); ++ ++u16 vpm_ioread16(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, size_t offset); ++ ++u32 vpm_ioread32(struct virtio_pci_modern_device *vdev, ++ struct virtio_pci_region *region, size_t offset); ++ ++/* Virtio 1.0 device manipulation routines */ ++ ++#define COMMON_OFFSET(field) offsetof(struct virtio_pci_common_cfg, field) ++ ++static inline void vpm_reset(struct virtio_pci_modern_device *vdev) ++{ ++ vpm_iowrite8(vdev, &vdev->common, 0, COMMON_OFFSET(device_status)); ++ while (vpm_ioread8(vdev, &vdev->common, COMMON_OFFSET(device_status))) ++ mdelay(1); ++} ++ ++static inline u8 vpm_get_status(struct virtio_pci_modern_device *vdev) ++{ ++ return vpm_ioread8(vdev, &vdev->common, COMMON_OFFSET(device_status)); ++} ++ ++static inline void vpm_add_status(struct virtio_pci_modern_device *vdev, ++ u8 status) ++{ ++ u8 curr_status = vpm_ioread8(vdev, &vdev->common, COMMON_OFFSET(device_status)); ++ vpm_iowrite8(vdev, &vdev->common, ++ curr_status | status, COMMON_OFFSET(device_status)); ++} ++ ++static inline u64 vpm_get_features(struct virtio_pci_modern_device *vdev) ++{ ++ u32 features_lo, features_hi; ++ ++ vpm_iowrite32(vdev, &vdev->common, 0, COMMON_OFFSET(device_feature_select)); ++ features_lo = vpm_ioread32(vdev, &vdev->common, COMMON_OFFSET(device_feature)); ++ vpm_iowrite32(vdev, &vdev->common, 1, COMMON_OFFSET(device_feature_select)); ++ features_hi = vpm_ioread32(vdev, &vdev->common, COMMON_OFFSET(device_feature)); ++ ++ return ((u64)features_hi << 32) | features_lo; ++} ++ ++static inline void vpm_set_features(struct virtio_pci_modern_device *vdev, ++ u64 features) ++{ ++ u32 features_lo = (u32)features; ++ u32 features_hi = features >> 32; ++ ++ vpm_iowrite32(vdev, &vdev->common, 0, COMMON_OFFSET(guest_feature_select)); ++ vpm_iowrite32(vdev, &vdev->common, features_lo, COMMON_OFFSET(guest_feature)); ++ vpm_iowrite32(vdev, &vdev->common, 1, COMMON_OFFSET(guest_feature_select)); ++ vpm_iowrite32(vdev, &vdev->common, features_hi, COMMON_OFFSET(guest_feature)); ++} ++ ++static inline void vpm_get(struct virtio_pci_modern_device *vdev, ++ unsigned offset, void *buf, unsigned len) ++{ ++ u8 *ptr = buf; ++ unsigned i; ++ ++ for (i = 0; i < len; i++) ++ ptr[i] = vpm_ioread8(vdev, &vdev->device, offset + i); ++} ++ ++static inline u8 vpm_get_isr(struct virtio_pci_modern_device *vdev) ++{ ++ return vpm_ioread8(vdev, &vdev->isr, 0); ++} ++ ++void vpm_notify(struct virtio_pci_modern_device *vdev, ++ struct vring_virtqueue *vq); ++ ++int vpm_find_vqs(struct virtio_pci_modern_device *vdev, ++ unsigned nvqs, struct vring_virtqueue *vqs); ++ ++int virtio_pci_find_capability(struct pci_device *pci, uint8_t cfg_type); ++ ++int virtio_pci_map_capability(struct pci_device *pci, int cap, size_t minlen, ++ u32 align, u32 start, u32 size, ++ struct virtio_pci_region *region); ++ ++void virtio_pci_unmap_capability(struct virtio_pci_region *region); + #endif /* _VIRTIO_PCI_H_ */ +diff --git a/src/include/ipxe/virtio-ring.h b/src/include/ipxe/virtio-ring.h +index e44d13c..6ba550b 100644 +--- a/src/include/ipxe/virtio-ring.h ++++ b/src/include/ipxe/virtio-ring.h +@@ -1,6 +1,8 @@ + #ifndef _VIRTIO_RING_H_ + # define _VIRTIO_RING_H_ + ++#include ++ + /* Status byte for guest to report progress, and synchronize features. */ + /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ + #define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 +@@ -79,6 +81,7 @@ struct vring_virtqueue { + void *vdata[MAX_QUEUE_NUM]; + /* PCI */ + int queue_index; ++ struct virtio_pci_region notification; + }; + + struct vring_list { +@@ -142,6 +145,7 @@ void *vring_get_buf(struct vring_virtqueue *vq, unsigned int *len); + void vring_add_buf(struct vring_virtqueue *vq, struct vring_list list[], + unsigned int out, unsigned int in, + void *index, int num_added); +-void vring_kick(unsigned int ioaddr, struct vring_virtqueue *vq, int num_added); ++void vring_kick(struct virtio_pci_modern_device *vdev, unsigned int ioaddr, ++ struct vring_virtqueue *vq, int num_added); + + #endif /* _VIRTIO_RING_H_ */ +-- +1.8.3.1 + diff --git a/SOURCES/ipxe-Add-virtio-1.0-constants-and-data-structures.patch b/SOURCES/ipxe-Add-virtio-1.0-constants-and-data-structures.patch new file mode 100644 index 0000000..038cfb8 --- /dev/null +++ b/SOURCES/ipxe-Add-virtio-1.0-constants-and-data-structures.patch @@ -0,0 +1,159 @@ +From 974120e731457af7c621cbc8a346813bd90c6b15 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Wed, 13 Jul 2016 13:28:35 +0200 +Subject: [PATCH 2/6] Add virtio 1.0 constants and data structures + +RH-Author: Ladi Prosek +Message-id: <1468416519-11107-3-git-send-email-lprosek@redhat.com> +Patchwork-id: 71168 +O-Subject: [RHEL7.3 ipxe PATCH v2 2/6] [virtio] Add virtio 1.0 constants and data structures +Bugzilla: 1242850 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +Virtio 1.0 introduces new constants and data structures, common to all +devices as well as specific to virtio-net. This commit adds a subset +of these to be able to drive the virtio-net 1.0 network device. + +Signed-off-by: Ladi Prosek +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael Brown +(cherry picked from commit 7b499f849edc79f30b27dfe8143c04e90e3154c9) +Signed-off-by: Ladi Prosek +Signed-off-by: Miroslav Rezanina +--- + src/drivers/net/virtio-net.h | 16 +++++++++++ + src/include/ipxe/virtio-pci.h | 60 ++++++++++++++++++++++++++++++++++++++++++ + src/include/ipxe/virtio-ring.h | 8 ++++++ + 3 files changed, 84 insertions(+) + +diff --git a/src/drivers/net/virtio-net.h b/src/drivers/net/virtio-net.h +index 3abef28..c2b4a17 100644 +--- a/src/drivers/net/virtio-net.h ++++ b/src/drivers/net/virtio-net.h +@@ -14,6 +14,12 @@ + #define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ + #define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */ + #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ ++#define VIRTIO_NET_F_MRG_RXBUF 15 /* Driver can merge receive buffers. */ ++#define VIRTIO_NET_F_STATUS 16 /* Configuration status field is available. */ ++#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel is available. */ ++#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support. */ ++#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering. */ ++#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Driver can send gratuitous packets. */ + + struct virtio_net_config + { +@@ -41,4 +47,14 @@ struct virtio_net_hdr + uint16_t csum_start; + uint16_t csum_offset; + }; ++ ++/* Virtio 1.0 version of the first element of the scatter-gather list. */ ++struct virtio_net_hdr_modern ++{ ++ struct virtio_net_hdr legacy; ++ ++ /* Used only if VIRTIO_NET_F_MRG_RXBUF: */ ++ uint16_t num_buffers; ++}; ++ + #endif /* _VIRTIO_NET_H_ */ +diff --git a/src/include/ipxe/virtio-pci.h b/src/include/ipxe/virtio-pci.h +index a09c463..8076f20 100644 +--- a/src/include/ipxe/virtio-pci.h ++++ b/src/include/ipxe/virtio-pci.h +@@ -37,6 +37,66 @@ + /* Virtio ABI version, this must match exactly */ + #define VIRTIO_PCI_ABI_VERSION 0 + ++/* PCI capability types: */ ++#define VIRTIO_PCI_CAP_COMMON_CFG 1 /* Common configuration */ ++#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 /* Notifications */ ++#define VIRTIO_PCI_CAP_ISR_CFG 3 /* ISR access */ ++#define VIRTIO_PCI_CAP_DEVICE_CFG 4 /* Device specific configuration */ ++#define VIRTIO_PCI_CAP_PCI_CFG 5 /* PCI configuration access */ ++ ++#define __u8 uint8_t ++#define __le16 uint16_t ++#define __le32 uint32_t ++#define __le64 uint64_t ++ ++/* This is the PCI capability header: */ ++struct virtio_pci_cap { ++ __u8 cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ ++ __u8 cap_next; /* Generic PCI field: next ptr. */ ++ __u8 cap_len; /* Generic PCI field: capability length */ ++ __u8 cfg_type; /* Identifies the structure. */ ++ __u8 bar; /* Where to find it. */ ++ __u8 padding[3]; /* Pad to full dword. */ ++ __le32 offset; /* Offset within bar. */ ++ __le32 length; /* Length of the structure, in bytes. */ ++}; ++ ++struct virtio_pci_notify_cap { ++ struct virtio_pci_cap cap; ++ __le32 notify_off_multiplier; /* Multiplier for queue_notify_off. */ ++}; ++ ++struct virtio_pci_cfg_cap { ++ struct virtio_pci_cap cap; ++ __u8 pci_cfg_data[4]; /* Data for BAR access. */ ++}; ++ ++/* Fields in VIRTIO_PCI_CAP_COMMON_CFG: */ ++struct virtio_pci_common_cfg { ++ /* About the whole device. */ ++ __le32 device_feature_select; /* read-write */ ++ __le32 device_feature; /* read-only */ ++ __le32 guest_feature_select; /* read-write */ ++ __le32 guest_feature; /* read-write */ ++ __le16 msix_config; /* read-write */ ++ __le16 num_queues; /* read-only */ ++ __u8 device_status; /* read-write */ ++ __u8 config_generation; /* read-only */ ++ ++ /* About a specific virtqueue. */ ++ __le16 queue_select; /* read-write */ ++ __le16 queue_size; /* read-write, power of 2. */ ++ __le16 queue_msix_vector; /* read-write */ ++ __le16 queue_enable; /* read-write */ ++ __le16 queue_notify_off; /* read-only */ ++ __le32 queue_desc_lo; /* read-write */ ++ __le32 queue_desc_hi; /* read-write */ ++ __le32 queue_avail_lo; /* read-write */ ++ __le32 queue_avail_hi; /* read-write */ ++ __le32 queue_used_lo; /* read-write */ ++ __le32 queue_used_hi; /* read-write */ ++}; ++ + static inline u32 vp_get_features(unsigned int ioaddr) + { + return inl(ioaddr + VIRTIO_PCI_HOST_FEATURES); +diff --git a/src/include/ipxe/virtio-ring.h b/src/include/ipxe/virtio-ring.h +index c687aca..e44d13c 100644 +--- a/src/include/ipxe/virtio-ring.h ++++ b/src/include/ipxe/virtio-ring.h +@@ -8,9 +8,17 @@ + #define VIRTIO_CONFIG_S_DRIVER 2 + /* Driver has used its parts of the config, and is happy */ + #define VIRTIO_CONFIG_S_DRIVER_OK 4 ++/* Driver has finished configuring features */ ++#define VIRTIO_CONFIG_S_FEATURES_OK 8 + /* We've given up on this device. */ + #define VIRTIO_CONFIG_S_FAILED 0x80 + ++/* Virtio feature flags used to negotiate device and driver features. */ ++/* Can the device handle any descriptor layout? */ ++#define VIRTIO_F_ANY_LAYOUT 27 ++/* v1.0 compliant. */ ++#define VIRTIO_F_VERSION_1 32 ++ + #define MAX_QUEUE_NUM (256) + + #define VRING_DESC_F_NEXT 1 +-- +1.8.3.1 + diff --git a/SOURCES/ipxe-Add-virtio-net-1.0-support.patch b/SOURCES/ipxe-Add-virtio-net-1.0-support.patch new file mode 100644 index 0000000..706b258 --- /dev/null +++ b/SOURCES/ipxe-Add-virtio-net-1.0-support.patch @@ -0,0 +1,405 @@ +From 0374108c3d2fd3e032bfa3cc7ec2a9452fa193ef Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Wed, 13 Jul 2016 13:28:37 +0200 +Subject: [PATCH 4/6] Add virtio-net 1.0 support + +RH-Author: Ladi Prosek +Message-id: <1468416519-11107-5-git-send-email-lprosek@redhat.com> +Patchwork-id: 71170 +O-Subject: [RHEL7.3 ipxe PATCH v2 4/6] [virtio] Add virtio-net 1.0 support +Bugzilla: 1242850 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +This commit makes virtio-net support devices with VEN 0x1af4 and DEV +0x1041, which is how non-transitional (modern-only) virtio-net devices +are exposed on the PCI bus. + +Transitional devices supporting both the old 0.9.5 and new 1.0 version +of the virtio spec are driven using the new protocol. Legacy devices +are driven using the old protocol, same as before this commit. + +Signed-off-by: Ladi Prosek +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael Brown +(cherry picked from commit 988243c93fb87190e1867ef913136ecf139e7cb8) +Signed-off-by: Ladi Prosek +Signed-off-by: Miroslav Rezanina +--- + src/drivers/net/virtio-net.c | 262 +++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 251 insertions(+), 11 deletions(-) + +diff --git a/src/drivers/net/virtio-net.c b/src/drivers/net/virtio-net.c +index 446bbd6..fe0fd4b 100644 +--- a/src/drivers/net/virtio-net.c ++++ b/src/drivers/net/virtio-net.c +@@ -89,6 +89,12 @@ struct virtnet_nic { + /** Base pio register address */ + unsigned long ioaddr; + ++ /** 0 for legacy, 1 for virtio 1.0 */ ++ int virtio_version; ++ ++ /** Virtio 1.0 device data */ ++ struct virtio_pci_modern_device vdev; ++ + /** RX/TX virtqueues */ + struct vring_virtqueue *virtqueue; + +@@ -99,7 +105,7 @@ struct virtnet_nic { + unsigned int rx_num_iobufs; + + /** Virtio net packet header, we only need one */ +- struct virtio_net_hdr empty_header; ++ struct virtio_net_hdr_modern empty_header; + }; + + /** Add an iobuf to a virtqueue +@@ -116,6 +122,9 @@ static void virtnet_enqueue_iob ( struct net_device *netdev, + struct vring_virtqueue *vq = &virtnet->virtqueue[vq_idx]; + unsigned int out = ( vq_idx == TX_INDEX ) ? 2 : 0; + unsigned int in = ( vq_idx == TX_INDEX ) ? 0 : 2; ++ size_t header_len = virtnet->virtio_version ++ ? sizeof ( virtnet->empty_header ) ++ : sizeof ( virtnet->empty_header.legacy ); + struct vring_list list[] = { + { + /* Share a single zeroed virtio net header between all +@@ -124,7 +133,7 @@ static void virtnet_enqueue_iob ( struct net_device *netdev, + * header fields get used. + */ + .addr = ( char* ) &virtnet->empty_header, +- .length = sizeof ( virtnet->empty_header ), ++ .length = header_len, + }, + { + .addr = ( char* ) iobuf->data, +@@ -136,7 +145,8 @@ static void virtnet_enqueue_iob ( struct net_device *netdev, + virtnet, iobuf, vq_idx ); + + vring_add_buf ( vq, list, out, in, iobuf, 0 ); +- vring_kick ( NULL, virtnet->ioaddr, vq, 1 ); ++ vring_kick ( virtnet->virtio_version ? &virtnet->vdev : NULL, ++ virtnet->ioaddr, vq, 1 ); + } + + /** Try to keep rx virtqueue filled with iobufs +@@ -165,12 +175,12 @@ static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) { + } + } + +-/** Open network device ++/** Open network device, legacy virtio 0.9.5 + * + * @v netdev Network device + * @ret rc Return status code + */ +-static int virtnet_open ( struct net_device *netdev ) { ++static int virtnet_open_legacy ( struct net_device *netdev ) { + struct virtnet_nic *virtnet = netdev->priv; + unsigned long ioaddr = virtnet->ioaddr; + u32 features; +@@ -211,6 +221,81 @@ static int virtnet_open ( struct net_device *netdev ) { + return 0; + } + ++/** Open network device, modern virtio 1.0 ++ * ++ * @v netdev Network device ++ * @ret rc Return status code ++ */ ++static int virtnet_open_modern ( struct net_device *netdev ) { ++ struct virtnet_nic *virtnet = netdev->priv; ++ u64 features; ++ u8 status; ++ ++ /* Negotiate features */ ++ features = vpm_get_features ( &virtnet->vdev ); ++ if ( ! ( features & VIRTIO_F_VERSION_1 ) ) { ++ vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED ); ++ return -EINVAL; ++ } ++ vpm_set_features ( &virtnet->vdev, features & ( ++ ( 1ULL << VIRTIO_NET_F_MAC ) | ++ ( 1ULL << VIRTIO_F_VERSION_1 ) | ++ ( 1ULL << VIRTIO_F_ANY_LAYOUT ) ) ); ++ vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FEATURES_OK ); ++ ++ status = vpm_get_status ( &virtnet->vdev ); ++ if ( ! ( status & VIRTIO_CONFIG_S_FEATURES_OK ) ) { ++ DBGC ( virtnet, "VIRTIO-NET %p device didn't accept features\n", ++ virtnet ); ++ vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED ); ++ return -EINVAL; ++ } ++ ++ /* Allocate virtqueues */ ++ virtnet->virtqueue = zalloc ( QUEUE_NB * ++ sizeof ( *virtnet->virtqueue ) ); ++ if ( ! virtnet->virtqueue ) { ++ vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED ); ++ return -ENOMEM; ++ } ++ ++ /* Initialize rx/tx virtqueues */ ++ if ( vpm_find_vqs ( &virtnet->vdev, QUEUE_NB, virtnet->virtqueue ) ) { ++ DBGC ( virtnet, "VIRTIO-NET %p cannot register queues\n", ++ virtnet ); ++ free ( virtnet->virtqueue ); ++ virtnet->virtqueue = NULL; ++ vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FAILED ); ++ return -ENOENT; ++ } ++ ++ /* Disable interrupts before starting */ ++ netdev_irq ( netdev, 0 ); ++ ++ vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER_OK ); ++ ++ /* Initialize rx packets */ ++ INIT_LIST_HEAD ( &virtnet->rx_iobufs ); ++ virtnet->rx_num_iobufs = 0; ++ virtnet_refill_rx_virtqueue ( netdev ); ++ return 0; ++} ++ ++/** Open network device ++ * ++ * @v netdev Network device ++ * @ret rc Return status code ++ */ ++static int virtnet_open ( struct net_device *netdev ) { ++ struct virtnet_nic *virtnet = netdev->priv; ++ ++ if ( virtnet->virtio_version ) { ++ return virtnet_open_modern ( netdev ); ++ } else { ++ return virtnet_open_legacy ( netdev ); ++ } ++} ++ + /** Close network device + * + * @v netdev Network device +@@ -219,10 +304,19 @@ static void virtnet_close ( struct net_device *netdev ) { + struct virtnet_nic *virtnet = netdev->priv; + struct io_buffer *iobuf; + struct io_buffer *next_iobuf; ++ int i; + +- vp_reset ( virtnet->ioaddr ); ++ if ( virtnet->virtio_version ) { ++ vpm_reset ( &virtnet->vdev ); ++ } else { ++ vp_reset ( virtnet->ioaddr ); ++ } + + /* Virtqueues can be freed now that NIC is reset */ ++ for ( i = 0 ; i < QUEUE_NB ; i++ ) { ++ virtio_pci_unmap_capability ( &virtnet->virtqueue[i].notification ); ++ } ++ + free ( virtnet->virtqueue ); + virtnet->virtqueue = NULL; + +@@ -303,10 +397,14 @@ static void virtnet_poll ( struct net_device *netdev ) { + + /* Acknowledge interrupt. This is necessary for UNDI operation and + * interrupts that are raised despite VRING_AVAIL_F_NO_INTERRUPT being +- * set (that flag is just a hint and the hypervisor not not have to ++ * set (that flag is just a hint and the hypervisor does not have to + * honor it). + */ +- vp_get_isr ( virtnet->ioaddr ); ++ if ( virtnet->virtio_version ) { ++ vpm_get_isr ( &virtnet->vdev ); ++ } else { ++ vp_get_isr ( virtnet->ioaddr ); ++ } + + virtnet_process_tx_packets ( netdev ); + virtnet_process_rx_packets ( netdev ); +@@ -339,13 +437,12 @@ static struct net_device_operations virtnet_operations = { + }; + + /** +- * Probe PCI device ++ * Probe PCI device, legacy virtio 0.9.5 + * + * @v pci PCI device +- * @v id PCI ID + * @ret rc Return status code + */ +-static int virtnet_probe ( struct pci_device *pci ) { ++static int virtnet_probe_legacy ( struct pci_device *pci ) { + unsigned long ioaddr = pci->ioaddr; + struct net_device *netdev; + struct virtnet_nic *virtnet; +@@ -396,12 +493,154 @@ static int virtnet_probe ( struct pci_device *pci ) { + } + + /** ++ * Probe PCI device, modern virtio 1.0 ++ * ++ * @v pci PCI device ++ * @v found_dev Set to non-zero if modern device was found (probe may still fail) ++ * @ret rc Return status code ++ */ ++static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) { ++ struct net_device *netdev; ++ struct virtnet_nic *virtnet; ++ u64 features; ++ int rc, common, isr, notify, config, device; ++ ++ common = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_COMMON_CFG ); ++ if ( ! common ) { ++ DBG ( "Common virtio capability not found!\n" ); ++ return -ENODEV; ++ } ++ *found_dev = 1; ++ ++ isr = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_ISR_CFG ); ++ notify = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_NOTIFY_CFG ); ++ config = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_PCI_CFG ); ++ if ( ! isr || ! notify || ! config ) { ++ DBG ( "Missing virtio capabilities %i/%i/%i/%i\n", ++ common, isr, notify, config ); ++ return -EINVAL; ++ } ++ device = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_DEVICE_CFG ); ++ ++ /* Allocate and hook up net device */ ++ netdev = alloc_etherdev ( sizeof ( *virtnet ) ); ++ if ( ! netdev ) ++ return -ENOMEM; ++ netdev_init ( netdev, &virtnet_operations ); ++ virtnet = netdev->priv; ++ ++ pci_set_drvdata ( pci, netdev ); ++ netdev->dev = &pci->dev; ++ ++ DBGC ( virtnet, "VIRTIO-NET modern %p busaddr=%s irq=%d\n", ++ virtnet, pci->dev.name, pci->irq ); ++ ++ virtnet->vdev.pci = pci; ++ rc = virtio_pci_map_capability ( pci, common, ++ sizeof ( struct virtio_pci_common_cfg ), 4, ++ 0, sizeof ( struct virtio_pci_common_cfg ), ++ &virtnet->vdev.common ); ++ if ( rc ) ++ goto err_map_common; ++ ++ rc = virtio_pci_map_capability ( pci, isr, sizeof ( u8 ), 1, ++ 0, 1, ++ &virtnet->vdev.isr ); ++ if ( rc ) ++ goto err_map_isr; ++ ++ virtnet->vdev.notify_cap_pos = notify; ++ virtnet->vdev.cfg_cap_pos = config; ++ ++ /* Map the device capability */ ++ if ( device ) { ++ rc = virtio_pci_map_capability ( pci, device, ++ 0, 4, 0, sizeof ( struct virtio_net_config ), ++ &virtnet->vdev.device ); ++ if ( rc ) ++ goto err_map_device; ++ } ++ ++ /* Enable the PCI device */ ++ adjust_pci_device ( pci ); ++ ++ /* Reset the device and set initial status bits */ ++ vpm_reset ( &virtnet->vdev ); ++ vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE ); ++ vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER ); ++ ++ /* Load MAC address */ ++ if ( device ) { ++ features = vpm_get_features ( &virtnet->vdev ); ++ if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) { ++ vpm_get ( &virtnet->vdev, ++ offsetof ( struct virtio_net_config, mac ), ++ netdev->hw_addr, ETH_ALEN ); ++ DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet, ++ eth_ntoa ( netdev->hw_addr ) ); ++ } ++ } ++ ++ /* We need a valid MAC address */ ++ if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) { ++ rc = -EADDRNOTAVAIL; ++ goto err_mac_address; ++ } ++ ++ /* Register network device */ ++ if ( ( rc = register_netdev ( netdev ) ) != 0 ) ++ goto err_register_netdev; ++ ++ /* Mark link as up, control virtqueue is not used */ ++ netdev_link_up ( netdev ); ++ ++ virtnet->virtio_version = 1; ++ return 0; ++ ++ unregister_netdev ( netdev ); ++err_register_netdev: ++err_mac_address: ++ vpm_reset ( &virtnet->vdev ); ++ netdev_nullify ( netdev ); ++ netdev_put ( netdev ); ++ ++ virtio_pci_unmap_capability ( &virtnet->vdev.device ); ++err_map_device: ++ virtio_pci_unmap_capability ( &virtnet->vdev.isr ); ++err_map_isr: ++ virtio_pci_unmap_capability ( &virtnet->vdev.common ); ++err_map_common: ++ return rc; ++} ++ ++/** ++ * Probe PCI device ++ * ++ * @v pci PCI device ++ * @ret rc Return status code ++ */ ++static int virtnet_probe ( struct pci_device *pci ) { ++ int found_modern = 0; ++ int rc = virtnet_probe_modern ( pci, &found_modern ); ++ if ( ! found_modern && pci->device < 0x1040 ) { ++ /* fall back to the legacy probe */ ++ rc = virtnet_probe_legacy ( pci ); ++ } ++ return rc; ++} ++ ++/** + * Remove device + * + * @v pci PCI device + */ + static void virtnet_remove ( struct pci_device *pci ) { + struct net_device *netdev = pci_get_drvdata ( pci ); ++ struct virtnet_nic *virtnet = netdev->priv; ++ ++ virtio_pci_unmap_capability ( &virtnet->vdev.device ); ++ virtio_pci_unmap_capability ( &virtnet->vdev.isr ); ++ virtio_pci_unmap_capability ( &virtnet->vdev.common ); + + unregister_netdev ( netdev ); + netdev_nullify ( netdev ); +@@ -410,6 +649,7 @@ static void virtnet_remove ( struct pci_device *pci ) { + + static struct pci_device_id virtnet_nics[] = { + PCI_ROM(0x1af4, 0x1000, "virtio-net", "Virtio Network Interface", 0), ++PCI_ROM(0x1af4, 0x1041, "virtio-net", "Virtio Network Interface 1.0", 0), + }; + + struct pci_driver virtnet_driver __pci_driver = { +-- +1.8.3.1 + diff --git a/SOURCES/ipxe-Allow-ROM-banner-timeout-to-be-configured-independen.patch b/SOURCES/ipxe-Allow-ROM-banner-timeout-to-be-configured-independen.patch deleted file mode 100644 index ac155ac..0000000 --- a/SOURCES/ipxe-Allow-ROM-banner-timeout-to-be-configured-independen.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 941332209d767a090b8003047fbb798bf8f193d4 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 4 Mar 2014 15:42:24 +0100 -Subject: [PATCH 6/7] Allow ROM banner timeout to be configured independently - -RH-Author: Alex Williamson -Message-id: <20140304154224.6292.81292.stgit@bling.home> -Patchwork-id: 58010 -O-Subject: [RHEL7 ipxe PATCH v2 2/3] [romprefix] Allow ROM banner timeout to be configured independently -Bugzilla: 857123 -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: Vlad Yasevich -RH-Acked-by: Richard Jones -RH-Acked-by: Stefan Hajnoczi - -Bugzilla: 857123 -Upstream: 27d1b40ee961d0910576a094a71dea1211254776 - -iPXE currently prints a "Press Ctrl-B" banner twice: once when the ROM -is first called for initialisation and again if we attempt to boot -from the ROM. This slows boot, especially when the NIC is not the -primary boot device. Tools such as libguestfs make use of QEMU VMs -for performing maintenance on disk images and may make use of NICs in -the VM for network support. If iPXE introduces a static init-time -delay, that directly translates to increased runtime for the tools. - -Fix by allowing the ROM banner timeout to be configured independently -of the main banner timeout. - -Signed-off-by: Alex Williamson -Modified-by: Michael Brown -Signed-off-by: Michael Brown ---- - src/arch/i386/prefix/romprefix.S | 10 +++------- - src/config/general.h | 19 +++++++++++++++---- - 2 files changed, 18 insertions(+), 11 deletions(-) - -Signed-off-by: Miroslav Rezanina ---- - src/arch/i386/prefix/romprefix.S | 10 +++------- - src/config/general.h | 17 ++++++++++++++--- - 2 files changed, 17 insertions(+), 10 deletions(-) - -diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S -index c75b9b9..d606006 100644 ---- a/src/arch/i386/prefix/romprefix.S -+++ b/src/arch/i386/prefix/romprefix.S -@@ -25,12 +25,8 @@ FILE_LICENCE ( GPL2_OR_LATER ) - ( PMM_HANDLE_BASE | 0x00002000 ) - #define PCI_FUNC_MASK 0x07 - --/* ROM banner timeout. Based on the configurable BANNER_TIMEOUT in -- * config.h, but converted to a number of (18Hz) timer ticks, and -- * doubled to allow for BIOSes that switch video modes immediately -- * beforehand, so rendering the message almost invisible to the user. -- */ --#define ROM_BANNER_TIMEOUT ( 2 * ( 18 * BANNER_TIMEOUT ) / 10 ) -+/* ROM banner timeout, converted to a number of (18Hz) timer ticks. */ -+#define ROM_BANNER_TIMEOUT_TICKS ( ( 18 * ROM_BANNER_TIMEOUT ) / 10 ) - - /* Allow payload to be excluded from ROM size - */ -@@ -801,7 +797,7 @@ wait_for_key: - int $0x16 - jmp 1b - 2: /* Wait for a key press */ -- movw $ROM_BANNER_TIMEOUT, %cx -+ movw $ROM_BANNER_TIMEOUT_TICKS, %cx - 3: decw %cx - js 99f /* Exit with ZF clear */ - /* Wait for timer tick to be updated */ -diff --git a/src/config/general.h b/src/config/general.h -index 9f0bb52..c5c8ea7 100644 ---- a/src/config/general.h -+++ b/src/config/general.h -@@ -28,11 +28,22 @@ FILE_LICENCE ( GPL2_OR_LATER ); - #define PRODUCT_SHORT_NAME "iPXE" - - /* -- * Timer configuration -- * -+ * Banner timeout configuration -+ * -+ * This controls the timeout for the "Press Ctrl-B for the iPXE -+ * command line" banner displayed when iPXE starts up. The value is -+ * specified in tenths of a second for which the banner should appear. -+ * A value of 0 disables the banner. -+ * -+ * ROM_BANNER_TIMEOUT controls the "Press Ctrl-B to configure iPXE" -+ * banner displayed only by ROM builds of iPXE during POST. This -+ * defaults to being twice the length of BANNER_TIMEOUT, to allow for -+ * BIOSes that switch video modes immediately before calling the -+ * initialisation vector, thus rendering the banner almost invisible -+ * to the user. - */ --#define BANNER_TIMEOUT 20 /* Tenths of a second for which the shell -- banner should appear */ -+#define BANNER_TIMEOUT 20 -+#define ROM_BANNER_TIMEOUT ( 2 * BANNER_TIMEOUT ) - - /* - * Network protocols --- -1.7.1 - diff --git a/SOURCES/ipxe-Allow-prefix-to-specify-a-PCI-autoboot-device-locati.patch b/SOURCES/ipxe-Allow-prefix-to-specify-a-PCI-autoboot-device-locati.patch deleted file mode 100644 index c393773..0000000 --- a/SOURCES/ipxe-Allow-prefix-to-specify-a-PCI-autoboot-device-locati.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 8eaadd87cfe66d11e587c5470fc82472315cc20d Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Mon, 3 Mar 2014 18:47:03 +0100 -Subject: [PATCH 2/7] Allow prefix to specify a PCI autoboot device location - -RH-Author: Alex Williamson -Message-id: <20140303184703.19235.50926.stgit@bling.home> -Patchwork-id: 57977 -O-Subject: [RHEL7 ipxe PATCH 2/4] [prefix] Allow prefix to specify a PCI autoboot device location -Bugzilla: 1031518 -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: Paolo Bonzini -RH-Acked-by: Vlad Yasevich -RH-Acked-by: Stefan Hajnoczi - -Bugzilla: 1031518 -Upstream: 90fc273b2b099df4a2c2ca06e1eaa7508e9734be - -Signed-off-by: Alex Williamson -Modified-by: Michael Brown -Signed-off-by: Michael Brown ---- - src/arch/i386/core/pci_autoboot.c | 44 +++++++++++++++++++++++++++++++++++++ - 1 file changed, 44 insertions(+) - create mode 100644 src/arch/i386/core/pci_autoboot.c - -Signed-off-by: Miroslav Rezanina ---- - src/arch/i386/core/pci_autoboot.c | 44 +++++++++++++++++++++++++++++++++++++ - 1 files changed, 44 insertions(+), 0 deletions(-) - create mode 100644 src/arch/i386/core/pci_autoboot.c - -diff --git a/src/arch/i386/core/pci_autoboot.c b/src/arch/i386/core/pci_autoboot.c -new file mode 100644 -index 0000000..bbb4027 ---- /dev/null -+++ b/src/arch/i386/core/pci_autoboot.c -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (C) 2014 Red Hat Inc. -+ * Alex Williamson -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License as -+ * published by the Free Software Foundation; either version 2 of the -+ * License, or any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -+ * 02110-1301, USA. -+ */ -+ -+FILE_LICENCE ( GPL2_OR_LATER ); -+ -+#include -+#include -+#include -+#include -+#include -+ -+uint16_t __bss16 ( autoboot_busdevfn ); -+#define autoboot_busdevfn __use_data16 ( autoboot_busdevfn ) -+ -+/** -+ * Initialise PCI autoboot device -+ */ -+static void pci_autoboot_init ( void ) { -+ -+ autoboot_device.bus_type = BUS_TYPE_PCI; -+ autoboot_device.location = autoboot_busdevfn; -+} -+ -+/** PCI autoboot device initialisation function */ -+struct init_fn pci_autoboot_init_fn __init_fn ( INIT_NORMAL ) = { -+ .initialise = pci_autoboot_init, -+}; --- -1.7.1 - diff --git a/SOURCES/ipxe-Customize-ROM-banner-timeout.patch b/SOURCES/ipxe-Customize-ROM-banner-timeout.patch deleted file mode 100644 index 596df7b..0000000 --- a/SOURCES/ipxe-Customize-ROM-banner-timeout.patch +++ /dev/null @@ -1,47 +0,0 @@ -From e53b49d7d8d1b17b1326e37e6e3674e0ceae0cf9 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 4 Mar 2014 15:42:30 +0100 -Subject: [PATCH 7/7] Customize ROM banner timeout - -RH-Author: Alex Williamson -Message-id: <20140304154230.6292.69267.stgit@bling.home> -Patchwork-id: 58011 -O-Subject: [RHEL7 ipxe PATCH v2 3/3] [rhel7] Customize ROM banner timeout -Bugzilla: 857123 -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: Vlad Yasevich -RH-Acked-by: Richard Jones -RH-Acked-by: Stefan Hajnoczi - -Bugzilla: 857123 -Upstream: N/A (downstream customization) - -Users want some opportunity to interact with the iPXE shell, but -tools like libguestfs want to boot as quickly as possible. Create -a compromise by disabling the interactive banner prompt during ROM -initialization, but retaining it when we actually attempt to boot -from the device. - -Signed-off-by: Alex Williamson ---- - src/config/local/general.h | 2 ++ - 1 file changed, 2 insertions(+) - create mode 100644 src/config/local/general.h - -Signed-off-by: Miroslav Rezanina ---- - src/config/local/general.h | 2 ++ - 1 files changed, 2 insertions(+), 0 deletions(-) - 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..349d435 ---- /dev/null -+++ b/src/config/local/general.h -@@ -0,0 +1,2 @@ -+#undef ROM_BANNER_TIMEOUT -+#define ROM_BANNER_TIMEOUT 0 --- -1.7.1 - diff --git a/SOURCES/ipxe-Enable-IPv6-protocol-in-non-QEMU-builds.patch b/SOURCES/ipxe-Enable-IPv6-protocol-in-non-QEMU-builds.patch new file mode 100644 index 0000000..b5939cf --- /dev/null +++ b/SOURCES/ipxe-Enable-IPv6-protocol-in-non-QEMU-builds.patch @@ -0,0 +1,53 @@ +From 35f4006845436816a651b2f154a37d38d02305d9 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Tue, 28 Jun 2016 14:23:19 +0200 +Subject: [PATCH] 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 +--- + 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/ipxe-Enable-infrastructure-to-specify-an-autoboot-device-.patch b/SOURCES/ipxe-Enable-infrastructure-to-specify-an-autoboot-device-.patch deleted file mode 100644 index 8c67d46..0000000 --- a/SOURCES/ipxe-Enable-infrastructure-to-specify-an-autoboot-device-.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 13a929c026fe7346be3c9342f10169eab6958015 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Mon, 3 Mar 2014 18:46:57 +0100 -Subject: [PATCH 1/7] Enable infrastructure to specify an autoboot device location - -RH-Author: Alex Williamson -Message-id: <20140303184657.19235.97871.stgit@bling.home> -Patchwork-id: 57976 -O-Subject: [RHEL7 ipxe PATCH 1/4] [autoboot] Enable infrastructure to specify an autoboot device location -Bugzilla: 1031518 -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: Paolo Bonzini -RH-Acked-by: Vlad Yasevich -RH-Acked-by: Stefan Hajnoczi - -Bugzilla: 1031518 -Upstream: 123bae9d939235a62e67d0cbfc66f3277bd81844 - -iPXE will currently attempt to boot from every network device for -which it has a driver. Where a system has more than one network -device supported by iPXE, this renders BIOS IPL lists ineffective. - -Allow an autoboot device location to be specified. If such a location -is specified, then only devices matching that location will be used as -part of the automatic boot sequence. If no such location is -specified, then all devices will be used. - -Note that this does not affect the "autoboot" command, which will -continue to use all devices. - -Signed-off-by: Alex Williamson -Modified-by: Michael Brown -Signed-off-by: Michael Brown ---- - src/include/usr/autoboot.h | 4 +++- - src/usr/autoboot.c | 43 ++++++++++++++++++++++++++----------------- - 2 files changed, 29 insertions(+), 18 deletions(-) - -Signed-off-by: Miroslav Rezanina ---- - src/include/usr/autoboot.h | 4 +++- - src/usr/autoboot.c | 43 ++++++++++++++++++++++++++----------------- - 2 files changed, 29 insertions(+), 18 deletions(-) - -diff --git a/src/include/usr/autoboot.h b/src/include/usr/autoboot.h -index cfa4c41..f562b2b 100644 ---- a/src/include/usr/autoboot.h -+++ b/src/include/usr/autoboot.h -@@ -10,6 +10,7 @@ - FILE_LICENCE ( GPL2_OR_LATER ); - - #include -+#include - struct net_device; - struct uri; - struct settings; -@@ -25,12 +26,13 @@ enum uriboot_flags { - URIBOOT_NO_SAN_BOOT | \ - URIBOOT_NO_SAN_UNHOOK ) - -+extern struct device_description autoboot_device; -+ - extern int uriboot ( struct uri *filename, struct uri *root_path, int drive, - unsigned int flags ); - extern struct uri * - fetch_next_server_and_filename ( struct settings *settings ); - extern int netboot ( struct net_device *netdev ); --extern int autoboot ( void ); - extern void ipxe ( struct net_device *netdev ); - - extern int pxe_menu_boot ( struct net_device *netdev ); -diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c -index 70f883a..07157cf 100644 ---- a/src/usr/autoboot.c -+++ b/src/usr/autoboot.c -@@ -49,6 +49,9 @@ FILE_LICENCE ( GPL2_OR_LATER ); - * - */ - -+/** Device location of preferred autoboot device */ -+struct device_description autoboot_device; -+ - /* Disambiguate the various error causes */ - #define ENOENT_BOOT __einfo_error ( EINFO_ENOENT_BOOT ) - #define EINFO_ENOENT_BOOT \ -@@ -74,15 +77,6 @@ __weak int pxe_menu_boot ( struct net_device *netdev __unused ) { - } - - /** -- * Identify the boot network device -- * -- * @ret netdev Boot network device -- */ --static struct net_device * find_boot_netdev ( void ) { -- return NULL; --} -- --/** - * Parse next-server and filename into a URI - * - * @v next_server Next-server address -@@ -432,21 +426,36 @@ int netboot ( struct net_device *netdev ) { - } - - /** -+ * Test if network device matches the autoboot device location -+ * -+ * @v netdev Network device -+ * @ret is_autoboot Network device matches the autoboot device location -+ */ -+static int is_autoboot_device ( struct net_device *netdev ) { -+ -+ return ( ( netdev->dev->desc.bus_type == autoboot_device.bus_type ) && -+ ( netdev->dev->desc.location == autoboot_device.location ) ); -+} -+ -+/** - * Boot the system - */ --int autoboot ( void ) { -- struct net_device *boot_netdev; -+static int autoboot ( void ) { - struct net_device *netdev; - int rc = -ENODEV; - -- /* If we have an identifable boot device, try that first */ -- if ( ( boot_netdev = find_boot_netdev() ) ) -- rc = netboot ( boot_netdev ); -- -- /* If that fails, try booting from any of the other devices */ -+ /* Try booting from each network device. If we have a -+ * specified autoboot device location, then use only devices -+ * matching that location. -+ */ - for_each_netdev ( netdev ) { -- if ( netdev == boot_netdev ) -+ -+ /* Skip any non-matching devices, if applicable */ -+ if ( autoboot_device.bus_type && -+ ( ! is_autoboot_device ( netdev ) ) ) - continue; -+ -+ /* Attempt booting from this device */ - rc = netboot ( netdev ); - } - --- -1.7.1 - diff --git a/SOURCES/ipxe-Extract-timing-parameters-out-to-config-dhcp.h.patch b/SOURCES/ipxe-Extract-timing-parameters-out-to-config-dhcp.h.patch deleted file mode 100644 index f07aad5..0000000 --- a/SOURCES/ipxe-Extract-timing-parameters-out-to-config-dhcp.h.patch +++ /dev/null @@ -1,262 +0,0 @@ -From 82f54ed91ab0dbf9b2fdab7b3ea80b7b9f02ae13 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 28 Apr 2015 21:23:57 +0200 -Subject: [PATCH 1/2] Extract timing parameters out to config/dhcp.h - -Message-id: <20150428212357.31299.65270.stgit@gimli.home> -Patchwork-id: 64950 -O-Subject: [RHEL7.2 ipxe PATCH 1/2] [dhcp] Extract timing parameters out to config/dhcp.h -Bugzilla: 1196352 -RH-Acked-by: Miroslav Rezanina -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: Laszlo Ersek - -iPXE uses DHCP timeouts loosely based on values recommended by the -specification, but often abbreviated to reduce timeouts for reliable -and/or simple network topologies. Extract the DHCP timing parameters -to config/dhcp.h and document them. The resulting default iPXE -behavior is exactly the same, but downstreams are now afforded the -opportunity to implement spec-compliant behavior via config file -overrides. - -Signed-off-by: Alex Williamson -Modified-by: Michael Brown -Signed-off-by: Michael Brown -Signed-off-by: Miroslav Rezanina ---- - src/config/dhcp.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ - src/include/ipxe/dhcp.h | 10 ------ - src/net/udp/dhcp.c | 32 ++++++++++-------- - 3 files changed, 106 insertions(+), 23 deletions(-) - create mode 100644 src/config/dhcp.h - -diff --git a/src/config/dhcp.h b/src/config/dhcp.h -new file mode 100644 -index 0000000..21e863b ---- /dev/null -+++ b/src/config/dhcp.h -@@ -0,0 +1,87 @@ -+#ifndef CONFIG_DHCP_H -+#define CONFIG_DHCP_H -+ -+/** @file -+ * -+ * DHCP configuration -+ * -+ */ -+ -+FILE_LICENCE ( GPL2_OR_LATER ); -+ -+#include -+ -+/* -+ * DHCP and PXE Boot Server timeout parameters -+ * -+ * Initial and final timeout for DHCP discovery -+ * -+ * The PXE spec indicates discover request are sent 4 times, with -+ * timeouts of 4, 8, 16, 32 seconds. iPXE by default uses 1, 2, 4, 8. -+ */ -+#define DHCP_DISC_START_TIMEOUT_SEC 1 -+#define DHCP_DISC_END_TIMEOUT_SEC 10 -+//#define DHCP_DISC_START_TIMEOUT_SEC 4 /* as per PXE spec */ -+//#define DHCP_DISC_END_TIMEOUT_SEC 32 /* as per PXE spec */ -+ -+/* -+ * ProxyDHCP offers are given precedence by continue to wait for them -+ * after a valid DHCPOFFER is received. We'll wait through this -+ * timeout for it. The PXE spec indicates waiting through the 4 & 8 -+ * second timeouts, iPXE by default stops after 2. -+ */ -+#define DHCP_DISC_PROXY_TIMEOUT_SEC 2 -+//#define DHCP_DISC_PROXY_TIMEOUT_SEC 11 /* as per PXE spec */ -+ -+/* -+ * Per the PXE spec, requests are also tried 4 times, but at timeout -+ * intervals of 1, 2, 3, 4 seconds. To adapt this to an exponential -+ * backoff timer, we can either do 1, 2, 4, 8, ie. 4 retires with a -+ * longer interval or start at 0 (0.25s) for 0.25, 0.5, 1, 2, 4, -+ * ie. one extra try and shorter initial timeouts. iPXE by default -+ * does a combination of both, starting at 0 and going through the 8 -+ * second timeout. -+ */ -+#define DHCP_REQ_START_TIMEOUT_SEC 0 -+#define DHCP_REQ_END_TIMEOUT_SEC 10 -+//#define DHCP_REQ_END_TIMEOUT_SEC 4 /* as per PXE spec */ -+ -+/* -+ * A ProxyDHCP offer without PXE options also goes through a request -+ * phase using these same parameters, but note the early break below. -+ */ -+#define DHCP_PROXY_START_TIMEOUT_SEC 0 -+#define DHCP_PROXY_END_TIMEOUT_SEC 10 -+//#define DHCP_PROXY_END_TIMEOUT_SEC 8 /* as per PXE spec */ -+ -+/* -+ * A ProxyDHCP request timeout should not induce a failure condition, -+ * so we always want to break before the above set of timers expire. -+ * The iPXE default value of 2 breaks at the first timeout after 2 -+ * seconds, which will be after the 2 second timeout. -+ */ -+#define DHCP_REQ_PROXY_TIMEOUT_SEC 2 -+//#define DHCP_REQ_PROXY_TIMEOUT_SEC 7 /* as per PXE spec */ -+ -+/* -+ * Per the PXE spec, a PXE boot server request is also be retried 4 -+ * times at timeouts of 1, 2, 3, 4. iPXE uses the same timeouts as -+ * discovery, 1, 2, 4, 8, but will move on to the next server if -+ * available after an elapsed time greater than 3 seconds, therefore -+ * effectively only sending 3 tries at timeouts of 1, 2, 4. -+ */ -+#define PXEBS_START_TIMEOUT_SEC 1 -+#define PXEBS_END_TIMEOUT_SEC 10 -+//#define PXEBS_START_TIMEOUT_SEC 0 /* as per PXE spec */ -+//#define PXEBS_END_TIMEOUT_SEC 8 /* as per PXE spec */ -+ -+/* -+ * Increment to the next PXE Boot server, if available, after this -+ * this much time has elapsed. -+ */ -+#define PXEBS_MAX_TIMEOUT_SEC 3 -+//#define PXEBS_MAX_TIMEOUT_SEC 7 /* as per PXE spec */ -+ -+#include -+ -+#endif /* CONFIG_DHCP_H */ -diff --git a/src/include/ipxe/dhcp.h b/src/include/ipxe/dhcp.h -index b97dfe3..13c8ca4 100644 ---- a/src/include/ipxe/dhcp.h -+++ b/src/include/ipxe/dhcp.h -@@ -631,16 +631,6 @@ struct dhcphdr { - */ - #define DHCP_MIN_LEN 552 - --/** Timeouts for sending DHCP packets */ --#define DHCP_MIN_TIMEOUT ( 1 * TICKS_PER_SEC ) --#define DHCP_MAX_TIMEOUT ( 10 * TICKS_PER_SEC ) -- --/** Maximum time that we will wait for ProxyDHCP responses */ --#define PROXYDHCP_MAX_TIMEOUT ( 2 * TICKS_PER_SEC ) -- --/** Maximum time that we will wait for Boot Server responses */ --#define PXEBS_MAX_TIMEOUT ( 3 * TICKS_PER_SEC ) -- - /** Settings block name used for DHCP responses */ - #define DHCP_SETTINGS_NAME "dhcp" - -diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c -index 762ae73..6c4f29e 100644 ---- a/src/net/udp/dhcp.c -+++ b/src/net/udp/dhcp.c -@@ -44,6 +44,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); - #include - #include - #include -+#include - - /** @file - * -@@ -185,8 +186,9 @@ struct dhcp_session_state { - void ( * expired ) ( struct dhcp_session *dhcp ); - /** Transmitted message type */ - uint8_t tx_msgtype; -- /** Apply minimum timeout */ -- uint8_t apply_min_timeout; -+ /** Timeout parameters */ -+ uint8_t min_timeout_sec; -+ uint8_t max_timeout_sec; - }; - - static struct dhcp_session_state dhcp_state_discover; -@@ -286,9 +288,8 @@ static void dhcp_set_state ( struct dhcp_session *dhcp, - dhcp->state = state; - dhcp->start = currticks(); - stop_timer ( &dhcp->timer ); -- dhcp->timer.min_timeout = -- ( state->apply_min_timeout ? DHCP_MIN_TIMEOUT : 0 ); -- dhcp->timer.max_timeout = DHCP_MAX_TIMEOUT; -+ dhcp->timer.min_timeout = state->min_timeout_sec * TICKS_PER_SEC; -+ dhcp->timer.max_timeout = state->max_timeout_sec * TICKS_PER_SEC; - start_timer_nodelay ( &dhcp->timer ); - } - -@@ -429,7 +430,7 @@ static void dhcp_discovery_rx ( struct dhcp_session *dhcp, - /* If we can't yet transition to DHCPREQUEST, do nothing */ - elapsed = ( currticks() - dhcp->start ); - if ( ! ( dhcp->no_pxedhcp || dhcp->proxy_offer || -- ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) ) -+ ( elapsed > DHCP_DISC_PROXY_TIMEOUT_SEC * TICKS_PER_SEC ) ) ) - return; - - /* Transition to DHCPREQUEST */ -@@ -445,7 +446,8 @@ static void dhcp_discovery_expired ( struct dhcp_session *dhcp ) { - unsigned long elapsed = ( currticks() - dhcp->start ); - - /* Give up waiting for ProxyDHCP before we reach the failure point */ -- if ( dhcp->offer.s_addr && ( elapsed > PROXYDHCP_MAX_TIMEOUT ) ) { -+ if ( dhcp->offer.s_addr && -+ ( elapsed > DHCP_DISC_PROXY_TIMEOUT_SEC * TICKS_PER_SEC ) ) { - dhcp_set_state ( dhcp, &dhcp_state_request ); - return; - } -@@ -461,7 +463,8 @@ static struct dhcp_session_state dhcp_state_discover = { - .rx = dhcp_discovery_rx, - .expired = dhcp_discovery_expired, - .tx_msgtype = DHCPDISCOVER, -- .apply_min_timeout = 1, -+ .min_timeout_sec = DHCP_DISC_START_TIMEOUT_SEC, -+ .max_timeout_sec = DHCP_DISC_END_TIMEOUT_SEC, - }; - - /** -@@ -598,7 +601,8 @@ static struct dhcp_session_state dhcp_state_request = { - .rx = dhcp_request_rx, - .expired = dhcp_request_expired, - .tx_msgtype = DHCPREQUEST, -- .apply_min_timeout = 0, -+ .min_timeout_sec = DHCP_REQ_START_TIMEOUT_SEC, -+ .max_timeout_sec = DHCP_REQ_END_TIMEOUT_SEC, - }; - - /** -@@ -683,7 +687,7 @@ static void dhcp_proxy_expired ( struct dhcp_session *dhcp ) { - unsigned long elapsed = ( currticks() - dhcp->start ); - - /* Give up waiting for ProxyDHCP before we reach the failure point */ -- if ( elapsed > PROXYDHCP_MAX_TIMEOUT ) { -+ if ( elapsed > DHCP_REQ_PROXY_TIMEOUT_SEC * TICKS_PER_SEC ) { - dhcp_finished ( dhcp, 0 ); - return; - } -@@ -699,7 +703,8 @@ static struct dhcp_session_state dhcp_state_proxy = { - .rx = dhcp_proxy_rx, - .expired = dhcp_proxy_expired, - .tx_msgtype = DHCPREQUEST, -- .apply_min_timeout = 0, -+ .min_timeout_sec = DHCP_PROXY_START_TIMEOUT_SEC, -+ .max_timeout_sec = DHCP_PROXY_END_TIMEOUT_SEC, - }; - - /** -@@ -824,7 +829,7 @@ static void dhcp_pxebs_expired ( struct dhcp_session *dhcp ) { - /* Give up waiting before we reach the failure point, and fail - * over to the next server in the attempt list - */ -- if ( elapsed > PXEBS_MAX_TIMEOUT ) { -+ if ( elapsed > PXEBS_MAX_TIMEOUT_SEC * TICKS_PER_SEC ) { - dhcp->pxe_attempt++; - if ( dhcp->pxe_attempt->s_addr ) { - dhcp_set_state ( dhcp, &dhcp_state_pxebs ); -@@ -846,7 +851,8 @@ static struct dhcp_session_state dhcp_state_pxebs = { - .rx = dhcp_pxebs_rx, - .expired = dhcp_pxebs_expired, - .tx_msgtype = DHCPREQUEST, -- .apply_min_timeout = 1, -+ .min_timeout_sec = PXEBS_START_TIMEOUT_SEC, -+ .max_timeout_sec = PXEBS_END_TIMEOUT_SEC, - }; - - /**************************************************************************** --- -1.8.3.1 - diff --git a/SOURCES/ipxe-Fix-virtio-pci-logging.patch b/SOURCES/ipxe-Fix-virtio-pci-logging.patch new file mode 100644 index 0000000..99b585d --- /dev/null +++ b/SOURCES/ipxe-Fix-virtio-pci-logging.patch @@ -0,0 +1,82 @@ +From 8346d9bc5cfacb19001df7f272d0c86cfd570ca5 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Wed, 13 Jul 2016 13:28:39 +0200 +Subject: [PATCH 6/6] Fix virtio-pci logging + +RH-Author: Ladi Prosek +Message-id: <1468416519-11107-7-git-send-email-lprosek@redhat.com> +Patchwork-id: 71172 +O-Subject: [RHEL7.3 ipxe PATCH v2 6/6] [virtio] Fix virtio-pci logging +Bugzilla: 1242850 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +iPXE debug logging doesn't support %u. This commit replaces it with +%d in virtio-pci debug format strings. + +Signed-off-by: Ladi Prosek +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael Brown +(cherry picked from commit 040aa980d630e45cb6d9e5fbaf5719b814accd5f) +Signed-off-by: Ladi Prosek +Signed-off-by: Miroslav Rezanina +--- + src/drivers/bus/virtio-pci.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/drivers/bus/virtio-pci.c b/src/drivers/bus/virtio-pci.c +index 494da28..a5dabc4 100644 +--- a/src/drivers/bus/virtio-pci.c ++++ b/src/drivers/bus/virtio-pci.c +@@ -252,21 +252,21 @@ int virtio_pci_map_capability(struct pci_device *pci, int cap, size_t minlen, + &length); + + if (length <= start) { +- DBG("VIRTIO-PCI bad capability len %u (>%u expected)\n", length, start); ++ DBG("VIRTIO-PCI bad capability len %d (>%d expected)\n", length, start); + return -EINVAL; + } + if (length - start < minlen) { +- DBG("VIRTIO-PCI bad capability len %u (>=%zu expected)\n", length, minlen); ++ DBG("VIRTIO-PCI bad capability len %d (>=%zd expected)\n", length, minlen); + return -EINVAL; + } + length -= start; + if (start + offset < offset) { +- DBG("VIRTIO-PCI map wrap-around %u+%u\n", start, offset); ++ DBG("VIRTIO-PCI map wrap-around %d+%d\n", start, offset); + return -EINVAL; + } + offset += start; + if (offset & (align - 1)) { +- DBG("VIRTIO-PCI offset %u not aligned to %u\n", offset, align); ++ DBG("VIRTIO-PCI offset %d not aligned to %d\n", offset, align); + return -EINVAL; + } + if (length > size) { +@@ -275,9 +275,9 @@ int virtio_pci_map_capability(struct pci_device *pci, int cap, size_t minlen, + + if (minlen + offset < minlen || + minlen + offset > pci_bar_size(pci, PCI_BASE_ADDRESS(bar))) { +- DBG("VIRTIO-PCI map virtio %zu@%u out of range on bar %i length %lu\n", ++ DBG("VIRTIO-PCI map virtio %zd@%d out of range on bar %i length %ld\n", + minlen, offset, +- bar, (unsigned long)pci_bar_size(pci, PCI_BASE_ADDRESS(bar))); ++ bar, pci_bar_size(pci, PCI_BASE_ADDRESS(bar))); + return -EINVAL; + } + +@@ -353,7 +353,7 @@ int vpm_find_vqs(struct virtio_pci_modern_device *vdev, + return -ENOENT; + + if (size & (size - 1)) { +- DBG("VIRTIO-PCI %p: bad queue size %u", vdev, size); ++ DBG("VIRTIO-PCI %p: bad queue size %d", vdev, size); + return -EINVAL; + } + +-- +1.8.3.1 + diff --git a/SOURCES/ipxe-Ignore-PCI-autoboot-device-location-if-set-to-00-00..patch b/SOURCES/ipxe-Ignore-PCI-autoboot-device-location-if-set-to-00-00..patch deleted file mode 100644 index e955b7e..0000000 --- a/SOURCES/ipxe-Ignore-PCI-autoboot-device-location-if-set-to-00-00..patch +++ /dev/null @@ -1,60 +0,0 @@ -From 41604531cac69c5591316df32a45bc102effc2c3 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Mon, 3 Mar 2014 18:47:15 +0100 -Subject: [PATCH 4/7] Ignore PCI autoboot device location if set to 00:00.0 - -RH-Author: Alex Williamson -Message-id: <20140303184715.19235.4758.stgit@bling.home> -Patchwork-id: 57979 -O-Subject: [RHEL7 ipxe PATCH 4/4] [prefix] Ignore PCI autoboot device location if set to 00:00.0 -Bugzilla: 1031518 -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: Paolo Bonzini -RH-Acked-by: Vlad Yasevich -RH-Acked-by: Stefan Hajnoczi - -From: Michael Brown - -Bugzilla: 1031518 -Upstream: ff1e7fc72b138fe66de1452a311b7e871f33e201 - -qemu can load an option ROM which is not associated with a particular -PCI device using the "-option-rom" syntax. Under these circumstances, -we should ignore the PCI bus:dev.fn address that we expect to find in -%ax on entry to the initialisation vector. - -Fix by using the PCI bus:dev.fn address only if it is non-zero. Since -00:00.0 will always be the host bridge, it can never be the address of -a network card. - -Reported-by: Alex Williamson -Signed-off-by: Michael Brown ---- - src/arch/i386/core/pci_autoboot.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -Signed-off-by: Miroslav Rezanina ---- - src/arch/i386/core/pci_autoboot.c | 6 ++++-- - 1 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/src/arch/i386/core/pci_autoboot.c b/src/arch/i386/core/pci_autoboot.c -index bbb4027..5e6197e 100644 ---- a/src/arch/i386/core/pci_autoboot.c -+++ b/src/arch/i386/core/pci_autoboot.c -@@ -34,8 +34,10 @@ uint16_t __bss16 ( autoboot_busdevfn ); - */ - static void pci_autoboot_init ( void ) { - -- autoboot_device.bus_type = BUS_TYPE_PCI; -- autoboot_device.location = autoboot_busdevfn; -+ if ( autoboot_busdevfn ) { -+ autoboot_device.bus_type = BUS_TYPE_PCI; -+ autoboot_device.location = autoboot_busdevfn; -+ } - } - - /** PCI autoboot device initialisation function */ --- -1.7.1 - diff --git a/SOURCES/ipxe-Renumber-virtio_pci_region-flags.patch b/SOURCES/ipxe-Renumber-virtio_pci_region-flags.patch new file mode 100644 index 0000000..80fc74b --- /dev/null +++ b/SOURCES/ipxe-Renumber-virtio_pci_region-flags.patch @@ -0,0 +1,54 @@ +From d398d8c57ad556207fd04e13e4ada688c0f23e7a Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Wed, 13 Jul 2016 13:28:38 +0200 +Subject: [PATCH 5/6] Renumber virtio_pci_region flags + +RH-Author: Ladi Prosek +Message-id: <1468416519-11107-6-git-send-email-lprosek@redhat.com> +Patchwork-id: 71171 +O-Subject: [RHEL7.3 ipxe PATCH v2 5/6] [virtio] Renumber virtio_pci_region flags +Bugzilla: 1242850 +RH-Acked-by: Marcel Apfelbaum +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Laszlo Ersek + +Some of the regions may end up being unmapped, either because they are +optional or because the attempt to map them has failed. Region types +starting at 0 didn't make it easy to test for this condition. + +This commit bumps all valid region types up by 1 with 0 having the +implicit 'unmapped' meaning. + +Signed-off-by: Ladi Prosek +Reviewed-by: Marcel Apfelbaum +Signed-off-by: Michael Brown +(cherry picked from commit fbbc895442847b4d3baa05fe1be66b510c949381) +Signed-off-by: Ladi Prosek +Signed-off-by: Miroslav Rezanina +--- + src/include/ipxe/virtio-pci.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/include/ipxe/virtio-pci.h b/src/include/ipxe/virtio-pci.h +index c7452c8..f3c9b17 100644 +--- a/src/include/ipxe/virtio-pci.h ++++ b/src/include/ipxe/virtio-pci.h +@@ -107,11 +107,11 @@ struct virtio_pci_region { + /* How to interpret the base field */ + #define VIRTIO_PCI_REGION_TYPE_MASK 0x00000003 + /* The base field is a memory address */ +-#define VIRTIO_PCI_REGION_MEMORY 0x00000000 ++#define VIRTIO_PCI_REGION_MEMORY 0x00000001 + /* The base field is a port address */ +-#define VIRTIO_PCI_REGION_PORT 0x00000001 ++#define VIRTIO_PCI_REGION_PORT 0x00000002 + /* The base field is an offset within the PCI bar */ +-#define VIRTIO_PCI_REGION_PCI_CONFIG 0x00000002 ++#define VIRTIO_PCI_REGION_PCI_CONFIG 0x00000003 + unsigned flags; + }; + +-- +1.8.3.1 + diff --git a/SOURCES/ipxe-Revert-Remove-2-second-startup-wait.patch b/SOURCES/ipxe-Revert-Remove-2-second-startup-wait.patch deleted file mode 100644 index 9e036dc..0000000 --- a/SOURCES/ipxe-Revert-Remove-2-second-startup-wait.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 8113d9275f87a5b962cc6e83060577ed36e4c7ca Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 4 Mar 2014 15:42:18 +0100 -Subject: [PATCH 5/7] Revert: Remove 2 second startup wait. - -RH-Author: Alex Williamson -Message-id: <20140304154218.6292.69336.stgit@bling.home> -Patchwork-id: 58009 -O-Subject: [RHEL7 ipxe PATCH v2 1/3] [rhel7] Revert: Remove 2 second startup wait. -Bugzilla: 857123 -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: Vlad Yasevich -RH-Acked-by: Richard Jones -RH-Acked-by: Stefan Hajnoczi - -Bugzilla: 857123 -Upstream: N/A (downstream customization) - -This reverts RHEL7 bd2e0975ef2213375bf97bcf2b39552e8a1a591a - -Downstream customized the banner timeout to remove it entirely, -allowing users no opportunity for interaction with the iPXE shell. -Remove this in preparation for removing only the banner displayed -during ROM init and keeping the banner displayed prior to autoboot. - -Signed-off-by: Alex Williamson ---- - src/config/general.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Signed-off-by: Miroslav Rezanina ---- - src/config/general.h | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/src/config/general.h b/src/config/general.h -index c497ed3..9f0bb52 100644 ---- a/src/config/general.h -+++ b/src/config/general.h -@@ -31,7 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); - * Timer configuration - * - */ --#define BANNER_TIMEOUT 0 /* Tenths of a second for which the shell -+#define BANNER_TIMEOUT 20 /* Tenths of a second for which the shell - banner should appear */ - - /* --- -1.7.1 - diff --git a/SOURCES/ipxe-Send-TCP-keepalives-on-idle-established-connections.patch b/SOURCES/ipxe-Send-TCP-keepalives-on-idle-established-connections.patch new file mode 100644 index 0000000..090bbfb --- /dev/null +++ b/SOURCES/ipxe-Send-TCP-keepalives-on-idle-established-connections.patch @@ -0,0 +1,162 @@ +From 506552bef7f9813d1cf6722ce25d2d46aa79b92f Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Wed, 13 Jul 2016 11:42:16 +0200 +Subject: [PATCH 1/2] Send TCP keepalives on idle established connections + +RH-Author: Ladi Prosek +Message-id: <1468410136-5607-1-git-send-email-lprosek@redhat.com> +Patchwork-id: 71165 +O-Subject: [RHEL7.3 ipxe PATCH] [tcp] Send TCP keepalives on idle established connections +Bugzilla: 1322056 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Laszlo Ersek + +From: Michael Brown + +In some circumstances, intermediate devices may lose state in a way +that temporarily prevents the successful delivery of packets from a +TCP peer. For example, a firewall may drop a NAT forwarding table +entry. + +Since iPXE spends most of its time downloading files (and hence purely +receiving data, sending only TCP ACKs), this can easily happen in a +situation in which there is no reason for iPXE's TCP stack to generate +any retransmissions. The temporary loss of connectivity can therefore +effectively become permanent. + +Work around this problem by sending TCP keepalives after a period of +inactivity on an established connection. + +TCP keepalives usually send a single garbage byte in sequence number +space that has already been ACKed by the peer. Since we do not need +to elicit a response from the peer, we instead send pure ACKs (with no +garbage data) in order to keep the transmit code path simple. + +Originally-implemented-by: Ladi Prosek +Debugged-by: Ladi Prosek +Signed-off-by: Michael Brown +(cherry picked from commit 188789eb3cb83496bd48847da59c74e3f06d413e) +Signed-off-by: Ladi Prosek + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1322056 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=11343040 +Signed-off-by: Miroslav Rezanina +--- + src/include/ipxe/tcp.h | 8 ++++++++ + src/net/tcp.c | 38 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 46 insertions(+) + +diff --git a/src/include/ipxe/tcp.h b/src/include/ipxe/tcp.h +index 063ebaa..faf4154 100644 +--- a/src/include/ipxe/tcp.h ++++ b/src/include/ipxe/tcp.h +@@ -381,6 +381,14 @@ struct tcp_options { + #define TCP_MSL ( 2 * 60 * TICKS_PER_SEC ) + + /** ++ * TCP keepalive period ++ * ++ * We send keepalive ACKs after this period of inactivity has elapsed ++ * on an established connection. ++ */ ++#define TCP_KEEPALIVE_DELAY ( 15 * TICKS_PER_SEC ) ++ ++/** + * TCP maximum header length + * + */ +diff --git a/src/net/tcp.c b/src/net/tcp.c +index c69c83b..77a7d8e 100644 +--- a/src/net/tcp.c ++++ b/src/net/tcp.c +@@ -113,6 +113,8 @@ struct tcp_connection { + struct process process; + /** Retransmission timer */ + struct retry_timer timer; ++ /** Keepalive timer */ ++ struct retry_timer keepalive; + /** Shutdown (TIME_WAIT) timer */ + struct retry_timer wait; + +@@ -177,6 +179,7 @@ static struct profiler tcp_xfer_profiler __profiler = { .name = "tcp.xfer" }; + static struct process_descriptor tcp_process_desc; + static struct interface_descriptor tcp_xfer_desc; + static void tcp_expired ( struct retry_timer *timer, int over ); ++static void tcp_keepalive_expired ( struct retry_timer *timer, int over ); + static void tcp_wait_expired ( struct retry_timer *timer, int over ); + static struct tcp_connection * tcp_demux ( unsigned int local_port ); + static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack, +@@ -284,6 +287,7 @@ static int tcp_open ( struct interface *xfer, struct sockaddr *peer, + intf_init ( &tcp->xfer, &tcp_xfer_desc, &tcp->refcnt ); + process_init_stopped ( &tcp->process, &tcp_process_desc, &tcp->refcnt ); + timer_init ( &tcp->timer, tcp_expired, &tcp->refcnt ); ++ timer_init ( &tcp->keepalive, tcp_keepalive_expired, &tcp->refcnt ); + timer_init ( &tcp->wait, tcp_wait_expired, &tcp->refcnt ); + tcp->prev_tcp_state = TCP_CLOSED; + tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN ); +@@ -380,6 +384,7 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) { + /* Remove from list and drop reference */ + process_del ( &tcp->process ); + stop_timer ( &tcp->timer ); ++ stop_timer ( &tcp->keepalive ); + stop_timer ( &tcp->wait ); + list_del ( &tcp->list ); + ref_put ( &tcp->refcnt ); +@@ -394,6 +399,9 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) { + if ( ! ( tcp->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) ) + tcp_rx_ack ( tcp, ( tcp->snd_seq + 1 ), 0 ); + ++ /* Stop keepalive timer */ ++ stop_timer ( &tcp->keepalive ); ++ + /* If we have no data remaining to send, start sending FIN */ + if ( list_empty ( &tcp->tx_queue ) && + ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) ) { +@@ -802,6 +810,32 @@ static void tcp_expired ( struct retry_timer *timer, int over ) { + } + + /** ++ * Keepalive timer expired ++ * ++ * @v timer Keepalive timer ++ * @v over Failure indicator ++ */ ++static void tcp_keepalive_expired ( struct retry_timer *timer, ++ int over __unused ) { ++ struct tcp_connection *tcp = ++ container_of ( timer, struct tcp_connection, keepalive ); ++ ++ DBGC ( tcp, "TCP %p sending keepalive\n", tcp ); ++ ++ /* Reset keepalive timer */ ++ start_timer_fixed ( &tcp->keepalive, TCP_KEEPALIVE_DELAY ); ++ ++ /* Send keepalive. We do this only to preserve or restore ++ * state in intermediate devices (e.g. firewall NAT tables); ++ * we don't actually care about eliciting a response to verify ++ * that the peer is still alive. We therefore send just a ++ * pure ACK, to keep our transmit path simple. ++ */ ++ tcp->flags |= TCP_ACK_PENDING; ++ tcp_xmit ( tcp ); ++} ++ ++/** + * Shutdown timer expired + * + * @v timer Shutdown timer +@@ -1063,6 +1097,10 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack, + /* Update window size */ + tcp->snd_win = win; + ++ /* Hold off (or start) the keepalive timer, if applicable */ ++ if ( ! ( tcp->tcp_state & TCP_STATE_SENT ( TCP_FIN ) ) ) ++ start_timer_fixed ( &tcp->keepalive, TCP_KEEPALIVE_DELAY ); ++ + /* Ignore ACKs that don't actually acknowledge any new data. + * (In particular, do not stop the retransmission timer; this + * avoids creating a sorceror's apprentice syndrome when a +-- +1.8.3.1 + diff --git a/SOURCES/ipxe-Store-boot-bus-dev.fn-address-as-autoboot-device-loc.patch b/SOURCES/ipxe-Store-boot-bus-dev.fn-address-as-autoboot-device-loc.patch deleted file mode 100644 index 22297d7..0000000 --- a/SOURCES/ipxe-Store-boot-bus-dev.fn-address-as-autoboot-device-loc.patch +++ /dev/null @@ -1,67 +0,0 @@ -From b745ae34559366ccc158f5782cfb81eeb054d62f Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Mon, 3 Mar 2014 18:47:09 +0100 -Subject: [PATCH 3/7] Store boot bus:dev.fn address as autoboot device location - -RH-Author: Alex Williamson -Message-id: <20140303184709.19235.66132.stgit@bling.home> -Patchwork-id: 57978 -O-Subject: [RHEL7 ipxe PATCH 3/4] [romprefix] Store boot bus:dev.fn address as autoboot device location -Bugzilla: 1031518 -RH-Acked-by: Gerd Hoffmann -RH-Acked-by: Paolo Bonzini -RH-Acked-by: Vlad Yasevich -RH-Acked-by: Stefan Hajnoczi - -Bugzilla: 1031518 -Upstream: c429bf0aa2428e6d12143285b29cbaf6a82f8d84 - -Per the BIOS Boot Specification, the initialization phase of the ROM -is called with the PFA (PCI Function Address) in the %ax register. -The intention is that the ROM code will store that device address -somewhere and use it for booting from that device when the Boot Entry -Vector (BEV) is called. iPXE does store the PFA, but doesn't use it -to select the boot network device. This renders BIOS IPL lists fairly -ineffective. - -Fix by using the BBS-specified bus:dev.fn address as the autoboot -device location. - -Signed-off-by: Alex Williamson -Modified-by: Michael Brown -Signed-off-by: Michael Brown ---- - src/arch/i386/prefix/romprefix.S | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -Signed-off-by: Miroslav Rezanina ---- - src/arch/i386/prefix/romprefix.S | 12 +++++++++++- - 1 files changed, 11 insertions(+), 1 deletions(-) - -diff --git a/src/arch/i386/prefix/romprefix.S b/src/arch/i386/prefix/romprefix.S -index 091673d..c75b9b9 100644 ---- a/src/arch/i386/prefix/romprefix.S -+++ b/src/arch/i386/prefix/romprefix.S -@@ -742,7 +742,17 @@ exec: /* Set %ds = %cs */ - pushw $1f - lret - .section ".text16", "awx", @progbits --1: /* Call main() */ -+1: -+ /* Retrieve PCI bus:dev.fn */ -+ movw init_pci_busdevfn, %cx -+ -+ /* Set up %ds for access to .data16 */ -+ movw %bx, %ds -+ -+ /* Store PCI bus:dev.fn */ -+ movw %cx, autoboot_busdevfn -+ -+ /* Call main() */ - pushl $main - pushw %cs - call prot_call --- -1.7.1 - diff --git a/SOURCES/ipxe-Strip-802.1Q-VLAN-0-priority-tags.patch b/SOURCES/ipxe-Strip-802.1Q-VLAN-0-priority-tags.patch new file mode 100644 index 0000000..dbea118 --- /dev/null +++ b/SOURCES/ipxe-Strip-802.1Q-VLAN-0-priority-tags.patch @@ -0,0 +1,150 @@ +From cd670f3a4f12b35e71802b2c2d57430a5fa624e3 Mon Sep 17 00:00:00 2001 +From: Ladi Prosek +Date: Mon, 11 Jul 2016 14:17:36 +0200 +Subject: [PATCH] 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/i386/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/i386/interface/pxe/pxe_undi.c b/src/arch/i386/interface/pxe/pxe_undi.c +index 2eb6817..2ea1451 100644 +--- a/src/arch/i386/interface/pxe/pxe_undi.c ++++ b/src/arch/i386/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 a1d207f..cea87f7 100644 +--- a/src/include/ipxe/netdevice.h ++++ b/src/include/ipxe/netdevice.h +@@ -719,6 +719,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 4508967..bf5e48e 100644 +--- a/src/interface/efi/efi_snp.c ++++ b/src/interface/efi/efi_snp.c +@@ -744,6 +744,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 7c40a2a..2d808b6 100644 +--- a/src/net/netdevice.c ++++ b/src/net/netdevice.c +@@ -1018,6 +1018,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 +@@ -1068,6 +1106,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/ipxe-Use-next-server-from-filename-s-settings-block.patch b/SOURCES/ipxe-Use-next-server-from-filename-s-settings-block.patch deleted file mode 100644 index efbe7eb..0000000 --- a/SOURCES/ipxe-Use-next-server-from-filename-s-settings-block.patch +++ /dev/null @@ -1,101 +0,0 @@ -From b83eff7520225d393dec4d656bc9cab915495a5c Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Fri, 7 Feb 2014 17:21:17 +0100 -Subject: [PATCH] Use next-server from filename's settings block - -RH-Author: Alex Williamson -Message-id: <20140207172042.26907.16755.stgit@bling.home> -Patchwork-id: 57133 -O-Subject: [RHEL7 ipxe PATCH] [autoboot] Use next-server from filename's settings block -Bugzilla: 1062644 -RH-Acked-by: Laszlo Ersek -RH-Acked-by: Stefan Hajnoczi -RH-Acked-by: Miroslav Rezanina - -From: Michael Brown - -Bugzilla: 1062644 -Brew: https://brewweb.devel.redhat.com/taskinfo?taskID=7015017 -Upstream: 936134ed460618e18cc05d677a442d43d5e739a1 - -Locate the settings block containing the filename, and search only -that settings block for the next-server address. This avoids problems -caused by misconfigured DHCP servers which provide a next-server -address (often defaulting to the DHCP server's own IP address) even -when not providing a filename. - -Originally-implemented-by: Alex Williamson -Signed-off-by: Michael Brown ---- - src/usr/autoboot.c | 39 +++++++++++++++++++++++++-------------- - 1 file changed, 25 insertions(+), 14 deletions(-) - -Signed-off-by: Miroslav Rezanina ---- - src/usr/autoboot.c | 39 +++++++++++++++++++++++++-------------- - 1 files changed, 25 insertions(+), 14 deletions(-) - -diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c -index b2d288e..70f883a 100644 ---- a/src/usr/autoboot.c -+++ b/src/usr/autoboot.c -@@ -251,31 +251,42 @@ static void close_all_netdevs ( void ) { - * @ret uri URI, or NULL on failure - */ - struct uri * fetch_next_server_and_filename ( struct settings *settings ) { -- struct in_addr next_server; -- char buf[256]; -+ struct in_addr next_server = { 0 }; -+ char *raw_filename = NULL; -+ struct uri *uri = NULL; - char *filename; -- struct uri *uri; - -- /* Fetch next-server setting */ -- fetch_ipv4_setting ( settings, &next_server_setting, &next_server ); -- if ( next_server.s_addr ) -- printf ( "Next server: %s\n", inet_ntoa ( next_server ) ); -+ /* Determine settings block containing the filename, if any */ -+ settings = fetch_setting_origin ( settings, &filename_setting ); - -- /* Fetch filename setting */ -- fetch_string_setting ( settings, &filename_setting, -- buf, sizeof ( buf ) ); -- if ( buf[0] ) -- printf ( "Filename: %s\n", buf ); -+ /* If we have a filename, fetch it along with next-server */ -+ if ( settings ) { -+ fetch_ipv4_setting ( settings, &next_server_setting, -+ &next_server ); -+ if ( fetch_string_setting_copy ( settings, &filename_setting, -+ &raw_filename ) < 0 ) -+ goto err_fetch; -+ } - - /* Expand filename setting */ -- filename = expand_settings ( buf ); -+ filename = expand_settings ( raw_filename ? raw_filename : "" ); - if ( ! filename ) -- return NULL; -+ goto err_expand; - - /* Parse next server and filename */ -+ if ( next_server.s_addr ) -+ printf ( "Next server: %s\n", inet_ntoa ( next_server ) ); -+ if ( filename[0] ) -+ printf ( "Filename: %s\n", filename ); - uri = parse_next_server_and_filename ( next_server, filename ); -+ if ( ! uri ) -+ goto err_parse; - -+ err_parse: - free ( filename ); -+ err_expand: -+ free ( raw_filename ); -+ err_fetch: - return uri; - } - --- -1.7.1 - diff --git a/SOURCES/ipxe-Use-spec-compliant-timeouts.patch b/SOURCES/ipxe-Use-spec-compliant-timeouts.patch deleted file mode 100644 index 285012b..0000000 --- a/SOURCES/ipxe-Use-spec-compliant-timeouts.patch +++ /dev/null @@ -1,104 +0,0 @@ -From b86874e0fa472f0d2e70babb5c37443cc37762b7 Mon Sep 17 00:00:00 2001 -From: Alex Williamson -Date: Tue, 28 Apr 2015 21:24:03 +0200 -Subject: [PATCH 2/2] 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 ---- - 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/.gitignore b/src/config/local/.gitignore -deleted file mode 100644 -index 72e8ffc..0000000 ---- a/src/config/local/.gitignore -+++ /dev/null -@@ -1 +0,0 @@ --* -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/ipxe-add-custom-Makefile-for-EfiRom-RHEL-only.patch b/SOURCES/ipxe-add-custom-Makefile-for-EfiRom-RHEL-only.patch deleted file mode 100644 index f5251a6..0000000 --- a/SOURCES/ipxe-add-custom-Makefile-for-EfiRom-RHEL-only.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 02dbc54913d8274ecb24239ed016e5b8eedf41cd Mon Sep 17 00:00:00 2001 -From: Laszlo Ersek -Date: Tue, 9 Sep 2014 20:50:23 +0200 -Subject: [PATCH 2/4] 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 ---- - EfiRom/Makefile | 43 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 43 insertions(+) - create mode 100644 EfiRom/Makefile - -Signed-off-by: Miroslav Rezanina ---- - EfiRom/Makefile | 43 +++++++++++++++++++++++++++++++++++++++++++ - 1 files changed, 43 insertions(+), 0 deletions(-) - 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.7.1 - diff --git a/SOURCES/ipxe-asm.patch b/SOURCES/ipxe-asm.patch deleted file mode 100644 index ee1ba05..0000000 --- a/SOURCES/ipxe-asm.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff -rup ipxe-20130517-gitc4bce43/src/arch/i386/interface/pxe/pxe_call.c ipxe-20130517-gitc4bce43.new/src/arch/i386/interface/pxe/pxe_call.c ---- ipxe-20130517-gitc4bce43/src/arch/i386/interface/pxe/pxe_call.c 2013-05-16 15:41:20.000000000 +0100 -+++ ipxe-20130517-gitc4bce43.new/src/arch/i386/interface/pxe/pxe_call.c 2013-05-17 10:55:13.282095767 +0100 -@@ -271,12 +271,14 @@ int pxe_start_nbp ( void ) { - DBG ( "Restarting NBP (%x)\n", jmp ); - - /* Far call to PXE NBP */ -- __asm__ __volatile__ ( REAL_CODE ( "movw %%cx, %%es\n\t" -+ __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" -+ "movw %%cx, %%es\n\t" - "pushw %%es\n\t" - "pushw %%di\n\t" - "sti\n\t" - "lcall $0, $0x7c00\n\t" -- "addw $4, %%sp\n\t" ) -+ "addw $4, %%sp\n\t" -+ "popl %%ebp\n\t" ) - : "=a" ( status ), "=b" ( discard_b ), - "=c" ( discard_c ), "=d" ( discard_d ), - "=D" ( discard_D ) -@@ -284,7 +286,7 @@ int pxe_start_nbp ( void ) { - "c" ( rm_cs ), - "d" ( virt_to_phys ( &pxenv ) ), - "D" ( __from_text16 ( &ppxe ) ) -- : "esi", "ebp", "memory" ); -+ : "esi", "memory" ); - if ( status ) - return -EPXENBP ( status ); - diff --git a/SOURCES/ipxe-banner-timeout.patch b/SOURCES/ipxe-banner-timeout.patch deleted file mode 100644 index b63c948..0000000 --- a/SOURCES/ipxe-banner-timeout.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -rup gpxe-1.0.1.orig/src/config/general.h gpxe-1.0.1.new/src/config/general.h ---- gpxe-1.0.1.orig/src/config/general.h 2010-06-29 20:31:33.000000000 +0100 -+++ gpxe-1.0.1.new/src/config/general.h 2012-03-19 11:53:36.035138977 +0000 -@@ -31,7 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); - * Timer configuration - * - */ --#define BANNER_TIMEOUT 20 /* Tenths of a second for which the shell -+#define BANNER_TIMEOUT 0 /* Tenths of a second for which the shell - banner should appear */ - - /* diff --git a/SOURCES/ipxe-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch b/SOURCES/ipxe-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch deleted file mode 100644 index 33c4013..0000000 --- a/SOURCES/ipxe-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch +++ /dev/null @@ -1,8991 +0,0 @@ -From 0884fdba4e127fa1870e6b7cdde13d78d288529f Mon Sep 17 00:00:00 2001 -From: Laszlo Ersek -Date: Tue, 9 Sep 2014 20:50:22 +0200 -Subject: [PATCH 1/4] 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 ---- - EfiRom/Common/CommonLib.h | 194 ++++ - EfiRom/Common/Compress.h | 88 ++ - EfiRom/Common/EfiUtilityMsgs.h | 170 +++ - EfiRom/Common/MemoryFile.h | 111 ++ - EfiRom/Common/ParseInf.h | 226 ++++ - 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/Common/CommonLib.c | 711 +++++++++++++ - EfiRom/Common/EfiCompress.c | 1590 +++++++++++++++++++++++++++++ - EfiRom/Common/EfiUtilityMsgs.c | 906 ++++++++++++++++ - EfiRom/Common/ParseInf.c | 701 +++++++++++++ - EfiRom/EfiRom.c | 1564 ++++++++++++++++++++++++++++ - EfiRom/License.txt | 25 + - 21 files changed, 8749 insertions(+) - create mode 100644 EfiRom/Common/CommonLib.h - create mode 100644 EfiRom/Common/Compress.h - create mode 100644 EfiRom/Common/EfiUtilityMsgs.h - create mode 100644 EfiRom/Common/MemoryFile.h - create mode 100644 EfiRom/Common/ParseInf.h - 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/Common/CommonLib.c - create mode 100644 EfiRom/Common/EfiCompress.c - create mode 100644 EfiRom/Common/EfiUtilityMsgs.c - create mode 100644 EfiRom/Common/ParseInf.c - create mode 100644 EfiRom/EfiRom.c - create mode 100644 EfiRom/License.txt - -Signed-off-by: Miroslav Rezanina ---- - 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(+), 0 deletions(-) - 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.7.1 - diff --git a/SPECS/ipxe.spec b/SPECS/ipxe.spec index 33f399a..b965d94 100644 --- a/SPECS/ipxe.spec +++ b/SPECS/ipxe.spec @@ -9,7 +9,8 @@ # e1000: 0x8086 0x100e # rtl8139: 0x10ec 0x8139 # virtio-net: 0x1af4 0x1000 -%global qemuroms 10222000 10ec8029 8086100e 10ec8139 1af41000 +# 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 @@ -34,51 +35,43 @@ # # And then change these two: -%global date 20130517 -%global hash c4bce43 +%global date 20160127 +%global hash 6366fa7a Name: ipxe Version: %{date} -Release: 8.git%{hash}%{?dist}.1 +Release: 5.git%{hash}%{?dist} Summary: A network boot loader Group: System Environment/Base License: GPLv2 and BSD URL: http://ipxe.org/ -Source0: %{name}-%{version}-git%{hash}.tar.gz +Source0: %{name}-%{hash}.tar.bz2 Source1: USAGE -# Remove 2 second startup wait. This patch is not intended to -# go upstream. Modifying the general config header file is the -# intended means for downstream customization. -Patch1: %{name}-banner-timeout.patch -# GCC >= 4.8 doesn't like the use of 'ebp' in asm -# https://bugzilla.redhat.com/show_bug.cgi?id=914091 -Patch2: %{name}-asm.patch -# For bz#1062644 - pxe boot fails if next-server details come from a different dhcp server -Patch3: ipxe-Use-next-server-from-filename-s-settings-block.patch -# For bz#1031518 - iPXE does not honor specified boot device -Patch4: ipxe-Enable-infrastructure-to-specify-an-autoboot-device-.patch -# For bz#1031518 - iPXE does not honor specified boot device -Patch5: ipxe-Allow-prefix-to-specify-a-PCI-autoboot-device-locati.patch -# For bz#1031518 - iPXE does not honor specified boot device -Patch6: ipxe-Store-boot-bus-dev.fn-address-as-autoboot-device-loc.patch -# For bz#1031518 - iPXE does not honor specified boot device -Patch7: ipxe-Ignore-PCI-autoboot-device-location-if-set-to-00-00..patch -# For bz#857123 - Guests never get an iPXE prompt -Patch8: ipxe-Revert-Remove-2-second-startup-wait.patch -# For bz#857123 - Guests never get an iPXE prompt -Patch9: ipxe-Allow-ROM-banner-timeout-to-be-configured-independen.patch -# For bz#857123 - Guests never get an iPXE prompt -Patch10: ipxe-Customize-ROM-banner-timeout.patch -# For bz#1084561 - RFE: ship UEFI drivers for ipxe in RHEL-7.y -Patch11: ipxe-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch -# For bz#1084561 - RFE: ship UEFI drivers for ipxe in RHEL-7.y -Patch12: ipxe-add-custom-Makefile-for-EfiRom-RHEL-only.patch -# For bz#1196352 - [RFE] option to increase gpxe retry timeout -Patch13: ipxe-Extract-timing-parameters-out-to-config-dhcp.h.patch -# For bz#1196352 - [RFE] option to increase gpxe retry timeout -Patch14: ipxe-Use-spec-compliant-timeouts.patch + +Patch2: 0002-Customize-ROM-banner-timeout.patch +Patch3: 0003-import-EfiRom-from-edk2-BaseTools-RHEL-only.patch +Patch4: 0004-add-custom-Makefile-for-EfiRom-RHEL-only.patch +Patch6: 0006-Use-spec-compliant-timeouts.patch +# For bz#1350167 - ipxe: enable IPV6 +Patch7: ipxe-Enable-IPv6-protocol-in-non-QEMU-builds.patch +# For bz#1242850 - Ipxe can not recognize "network device" when enable virtio-1 of virtio-net-pci +Patch8: ipxe-Add-pci_find_next_capability.patch +# For bz#1242850 - Ipxe can not recognize "network device" when enable virtio-1 of virtio-net-pci +Patch9: ipxe-Add-virtio-1.0-constants-and-data-structures.patch +# For bz#1242850 - Ipxe can not recognize "network device" when enable virtio-1 of virtio-net-pci +Patch10: ipxe-Add-virtio-1.0-PCI-support.patch +# For bz#1242850 - Ipxe can not recognize "network device" when enable virtio-1 of virtio-net-pci +Patch11: ipxe-Add-virtio-net-1.0-support.patch +# For bz#1242850 - Ipxe can not recognize "network device" when enable virtio-1 of virtio-net-pci +Patch12: ipxe-Renumber-virtio_pci_region-flags.patch +# For bz#1242850 - Ipxe can not recognize "network device" when enable virtio-1 of virtio-net-pci +Patch13: ipxe-Fix-virtio-pci-logging.patch +# For bz#1322056 - ipxe freeze during HTTP download with last RPM +Patch14: ipxe-Send-TCP-keepalives-on-idle-established-connections.patch +# For bz#1316329 - [RFE] Properly Handle 8021.Q VID 0 Frames, as new vlan model in linux kernel does. +Patch15: ipxe-Strip-802.1Q-VLAN-0-priority-tags.patch %ifarch %{buildarches} BuildRequires: perl @@ -86,6 +79,7 @@ BuildRequires: syslinux BuildRequires: mtools BuildRequires: mkisofs BuildRequires: binutils-devel +BuildRequires: xz-devel Obsoletes: gpxe <= 1.0.1 @@ -139,12 +133,14 @@ replacement for proprietary PXE ROMs, with many extra features such as DNS, HTTP, iSCSI, etc. %prep -%setup -q -n %{name}-%{version}-git%{hash} -%patch1 -p1 +%setup -q -n %{name}-%{hash} +cp -a %{SOURCE1} . + +patch_command="patch -p1 -s" + %patch2 -p1 %patch3 -p1 %patch4 -p1 -%patch5 -p1 %patch6 -p1 %patch7 -p1 %patch8 -p1 @@ -154,7 +150,7 @@ DNS, HTTP, iSCSI, etc. %patch12 -p1 %patch13 -p1 %patch14 -p1 -cp -a %{SOURCE1} . +%patch15 -p1 %build %ifarch %{buildarches} @@ -174,6 +170,9 @@ 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} @@ -181,8 +180,8 @@ cd ../src # build roms with efi support for qemu for rom in %qemuroms; do - make NO_WERROR=1 V=1 GITVERSION=%{hash} bin/${rom}.rom - make NO_WERROR=1 V=1 GITVERSION=%{hash} bin-x86_64-efi/${rom}.efidrv + 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 \ @@ -198,10 +197,13 @@ done %install %ifarch %{buildarches} mkdir -p %{buildroot}/%{_datadir}/%{name}/ -pushd src/bin/ -cp -a undionly.kpxe ipxe.{iso,usb,dsk,lkrn} %{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 @@ -231,32 +233,55 @@ done %{_datadir}/%{name}/ipxe.usb %{_datadir}/%{name}/ipxe.dsk %{_datadir}/%{name}/ipxe.lkrn +%{_datadir}/%{name}/ipxe.efi %{_datadir}/%{name}/undionly.kpxe -%doc COPYING COPYRIGHTS USAGE +%doc COPYING COPYING.GPLv2 USAGE %files roms -f rom.list %dir %{_datadir}/%{name} -%doc COPYING COPYRIGHTS +%doc COPYING COPYING.GPLv2 %files roms-qemu -f qemu.rom.list %dir %{_datadir}/%{name} -%doc COPYING COPYRIGHTS +%doc COPYING COPYING.GPLv2 %endif %changelog -* Tue Jan 26 2016 Miroslav Rezanina - 20130517-8.gitc4bce43.el7_2.1 -- Rebuild for preventing conflicts [bz#1301855] - -* Wed May 06 2015 Miroslav Rezanina - 20130517-7.gitc4bce43.el7 -- ipxe-Extract-timing-parameters-out-to-config-dhcp.h.patch [bz#1196352] -- ipxe-Use-spec-compliant-timeouts.patch [bz#1196352] -- Resolves: bz#1196352 - ([RFE] option to increase gpxe retry timeout) +* 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-delete-useless-editor-backup-of-spec.template.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) @@ -279,7 +304,7 @@ done - Resolves: bz#1062644 (pxe boot fails if next-server details come from a different dhcp server) -* Thu Jan 15 2014 Miroslav Rezanina - 20130517-3.gitc4bce43 +* Wed Jan 15 2014 Miroslav Rezanina - 20130517-3.gitc4bce43 - pad ROMs to 256k (rhbz #1038630) - Resolves: rhbz# 1038630