+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2004, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- ParseInf.c\r
-\r
-Abstract:\r
-\r
- This contains some useful functions for parsing INF files.\r
-\r
---*/\r
-\r
-#include <assert.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <stdlib.h>\r
-#include "ParseInf.h"\r
-\r
-#ifndef _MAX_PATH\r
-#define _MAX_PATH 500\r
-#endif\r
-\r
-CHAR8 *\r
-ReadLine (\r
- IN MEMORY_FILE *InputFile,\r
- IN OUT CHAR8 *InputBuffer,\r
- IN UINTN MaxLength\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This function reads a line, stripping any comments.\r
- The function reads a string from the input stream argument and stores it in \r
- the input string. ReadLine reads characters from the current file position \r
- to and including the first newline character, to the end of the stream, or \r
- until the number of characters read is equal to MaxLength - 1, whichever \r
- comes first. The newline character, if read, is replaced with a \0. \r
-\r
-Arguments:\r
-\r
- InputFile Memory file image.\r
- InputBuffer Buffer to read into, must be _MAX_PATH size.\r
- MaxLength The maximum size of the input buffer.\r
-\r
-Returns:\r
-\r
- NULL if error or EOF\r
- InputBuffer otherwise\r
-\r
---*/\r
-{\r
- CHAR8 *CharPtr;\r
- CHAR8 *EndOfLine;\r
- UINTN CharsToCopy;\r
-\r
- //\r
- // Verify input parameters are not null\r
- //\r
- assert (InputBuffer);\r
- assert (InputFile->FileImage);\r
- assert (InputFile->Eof);\r
- assert (InputFile->CurrentFilePointer);\r
-\r
- //\r
- // Check for end of file condition\r
- //\r
- if (InputFile->CurrentFilePointer >= InputFile->Eof) {\r
- return NULL;\r
- }\r
- //\r
- // Find the next newline char\r
- //\r
- EndOfLine = strchr (InputFile->CurrentFilePointer, '\n');\r
-\r
- //\r
- // Determine the number of characters to copy.\r
- //\r
- if (EndOfLine == 0) {\r
- //\r
- // If no newline found, copy to the end of the file.\r
- //\r
- CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;\r
- } else if (EndOfLine >= InputFile->Eof) {\r
- //\r
- // If the newline found was beyond the end of file, copy to the eof.\r
- //\r
- CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;\r
- } else {\r
- //\r
- // Newline found in the file.\r
- //\r
- CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;\r
- }\r
- //\r
- // If the end of line is too big for the current buffer, set it to the max\r
- // size of the buffer (leaving room for the \0.\r
- //\r
- if (CharsToCopy > MaxLength - 1) {\r
- CharsToCopy = MaxLength - 1;\r
- }\r
- //\r
- // Copy the line.\r
- //\r
- memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy);\r
-\r
- //\r
- // Add the null termination over the 0x0D\r
- //\r
- InputBuffer[CharsToCopy - 1] = '\0';\r
-\r
- //\r
- // Increment the current file pointer (include the 0x0A)\r
- //\r
- InputFile->CurrentFilePointer += CharsToCopy + 1;\r
-\r
- //\r
- // Strip any comments\r
- //\r
- CharPtr = strstr (InputBuffer, "//");\r
- if (CharPtr != 0) {\r
- CharPtr[0] = 0;\r
- }\r
- //\r
- // Return the string\r
- //\r
- return InputBuffer;\r
-}\r
-\r
-BOOLEAN\r
-FindSection (\r
- IN MEMORY_FILE *InputFile,\r
- IN CHAR8 *Section\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This function parses a file from the beginning to find a section.\r
- The section string may be anywhere within a line.\r
-\r
-Arguments:\r
-\r
- InputFile Memory file image.\r
- Section Section to search for\r
-\r
-Returns:\r
-\r
- FALSE if error or EOF\r
- TRUE if section found\r
-\r
---*/\r
-{\r
- CHAR8 InputBuffer[_MAX_PATH];\r
- CHAR8 *CurrentToken;\r
-\r
- //\r
- // Verify input is not NULL\r
- //\r
- assert (InputFile->FileImage);\r
- assert (InputFile->Eof);\r
- assert (InputFile->CurrentFilePointer);\r
- assert (Section);\r
-\r
- //\r
- // Rewind to beginning of file\r
- //\r
- InputFile->CurrentFilePointer = InputFile->FileImage;\r
-\r
- //\r
- // Read lines until the section is found\r
- //\r
- while (InputFile->CurrentFilePointer < InputFile->Eof) {\r
- //\r
- // Read a line\r
- //\r
- ReadLine (InputFile, InputBuffer, _MAX_PATH);\r
-\r
- //\r
- // Check if the section is found\r
- //\r
- CurrentToken = strstr (InputBuffer, Section);\r
- if (CurrentToken != NULL) {\r
- return TRUE;\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-EFI_STATUS\r
-FindToken (\r
- IN MEMORY_FILE *InputFile,\r
- IN CHAR8 *Section,\r
- IN CHAR8 *Token,\r
- IN UINTN Instance,\r
- OUT CHAR8 *Value\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Finds a token value given the section and token to search for.\r
-\r
-Arguments:\r
-\r
- InputFile Memory file image.\r
- Section The section to search for, a string within [].\r
- Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.\r
- Instance The instance of the token to search for. Zero is the first instance.\r
- Value The string that holds the value following the =. Must be _MAX_PATH in size.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Value found.\r
- EFI_ABORTED Format error detected in INF file.\r
- EFI_INVALID_PARAMETER Input argument was null.\r
- EFI_LOAD_ERROR Error reading from the file.\r
- EFI_NOT_FOUND Section/Token/Value not found.\r
-\r
---*/\r
-{\r
- CHAR8 InputBuffer[_MAX_PATH];\r
- CHAR8 *CurrentToken;\r
- BOOLEAN ParseError;\r
- BOOLEAN ReadError;\r
- UINTN Occurrance;\r
-\r
- //\r
- // Check input parameters\r
- //\r
- if (InputFile->FileImage == NULL ||\r
- InputFile->Eof == NULL ||\r
- InputFile->CurrentFilePointer == NULL ||\r
- Section == NULL ||\r
- strlen (Section) == 0 ||\r
- Token == NULL ||\r
- strlen (Token) == 0 ||\r
- Value == NULL\r
- ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Initialize error codes\r
- //\r
- ParseError = FALSE;\r
- ReadError = FALSE;\r
-\r
- //\r
- // Initialize our instance counter for the search token\r
- //\r
- Occurrance = 0;\r
-\r
- if (FindSection (InputFile, Section)) {\r
- //\r
- // Found the desired section, find and read the desired token\r
- //\r
- do {\r
- //\r
- // Read a line from the file\r
- //\r
- if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {\r
- //\r
- // Error reading from input file\r
- //\r
- ReadError = TRUE;\r
- break;\r
- }\r
- //\r
- // Get the first non-whitespace string\r
- //\r
- CurrentToken = strtok (InputBuffer, " \t\n");\r
- if (CurrentToken == NULL) {\r
- //\r
- // Whitespace line found (or comment) so continue\r
- //\r
- CurrentToken = InputBuffer;\r
- continue;\r
- }\r
- //\r
- // Make sure we have not reached the end of the current section\r
- //\r
- if (CurrentToken[0] == '[') {\r
- break;\r
- }\r
- //\r
- // Compare the current token with the desired token\r
- //\r
- if (strcmp (CurrentToken, Token) == 0) {\r
- //\r
- // Found it\r
- //\r
- //\r
- // Check if it is the correct instance\r
- //\r
- if (Instance == Occurrance) {\r
- //\r
- // Copy the contents following the =\r
- //\r
- CurrentToken = strtok (NULL, "= \t\n");\r
- if (CurrentToken == NULL) {\r
- //\r
- // Nothing found, parsing error\r
- //\r
- ParseError = TRUE;\r
- } else {\r
- //\r
- // Copy the current token to the output value\r
- //\r
- strcpy (Value, CurrentToken);\r
- return EFI_SUCCESS;\r
- }\r
- } else {\r
- //\r
- // Increment the occurrance found\r
- //\r
- Occurrance++;\r
- }\r
- }\r
- } while (\r
- !ParseError &&\r
- !ReadError &&\r
- InputFile->CurrentFilePointer < InputFile->Eof &&\r
- CurrentToken[0] != '[' &&\r
- Occurrance <= Instance\r
- );\r
- }\r
- //\r
- // Distinguish between read errors and INF file format errors.\r
- //\r
- if (ReadError) {\r
- return EFI_LOAD_ERROR;\r
- }\r
-\r
- if (ParseError) {\r
- return EFI_ABORTED;\r
- }\r
-\r
- return EFI_NOT_FOUND;\r
-}\r
-\r
-EFI_STATUS\r
-StringToGuid (\r
- IN CHAR8 *AsciiGuidBuffer,\r
- OUT EFI_GUID *GuidBuffer\r
- )\r
-/*++\r
-\r
-Routine Description: \r
-\r
- Converts a string to an EFI_GUID. The string must be in the \r
- xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.\r
-\r
-Arguments: \r
-\r
- AsciiGuidBuffer - pointer to ascii string\r
- GuidBuffer - pointer to destination Guid\r
-\r
-Returns: \r
-\r
- EFI_ABORTED Could not convert the string\r
- EFI_SUCCESS The string was successfully converted\r
- EFI_INVALID_PARAMETER Input parameter is invalid.\r
-\r
---*/\r
-{\r
- INT32 Index;\r
- UINTN Data1;\r
- UINTN Data2;\r
- UINTN Data3;\r
- UINTN Data4[8];\r
-\r
- if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Scan the guid string into the buffer\r
- //\r
- Index = sscanf (\r
- AsciiGuidBuffer,\r
- "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx",\r
- &Data1,\r
- &Data2,\r
- &Data3,\r
- &Data4[0],\r
- &Data4[1],\r
- &Data4[2],\r
- &Data4[3],\r
- &Data4[4],\r
- &Data4[5],\r
- &Data4[6],\r
- &Data4[7]\r
- );\r
-\r
- //\r
- // Verify the correct number of items were scanned.\r
- //\r
- if (Index != 11) {\r
- printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer);\r
- return EFI_ABORTED;\r
- }\r
- //\r
- // Copy the data into our GUID.\r
- //\r
- GuidBuffer->Data1 = (UINT32) Data1;\r
- GuidBuffer->Data2 = (UINT16) Data2;\r
- GuidBuffer->Data3 = (UINT16) Data3;\r
- GuidBuffer->Data4[0] = (UINT8) Data4[0];\r
- GuidBuffer->Data4[1] = (UINT8) Data4[1];\r
- GuidBuffer->Data4[2] = (UINT8) Data4[2];\r
- GuidBuffer->Data4[3] = (UINT8) Data4[3];\r
- GuidBuffer->Data4[4] = (UINT8) Data4[4];\r
- GuidBuffer->Data4[5] = (UINT8) Data4[5];\r
- GuidBuffer->Data4[6] = (UINT8) Data4[6];\r
- GuidBuffer->Data4[7] = (UINT8) Data4[7];\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-EFI_STATUS\r
-AsciiStringToUint64 (\r
- IN CONST CHAR8 *AsciiString,\r
- IN BOOLEAN IsHex,\r
- OUT UINT64 *ReturnValue\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Converts a null terminated ascii string that represents a number into a \r
- UINT64 value. A hex number may be preceeded by a 0x, but may not be \r
- succeeded by an h. A number without 0x or 0X is considered to be base 10 \r
- unless the IsHex input is true.\r
-\r
-Arguments:\r
-\r
- AsciiString The string to convert.\r
- IsHex Force the string to be treated as a hex number.\r
- ReturnValue The return value.\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS Number successfully converted.\r
- EFI_ABORTED Invalid character encountered.\r
-\r
---*/\r
-{\r
- UINT8 Index;\r
- UINT64 HexNumber;\r
- CHAR8 CurrentChar;\r
-\r
- //\r
- // Initialize the result\r
- //\r
- HexNumber = 0;\r
-\r
- //\r
- // Add each character to the result\r
- //\r
- if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {\r
- //\r
- // Verify string is a hex number\r
- //\r
- for (Index = 2; Index < strlen (AsciiString); Index++) {\r
- if (isxdigit (AsciiString[Index]) == 0) {\r
- return EFI_ABORTED;\r
- }\r
- }\r
- //\r
- // Convert the hex string.\r
- //\r
- for (Index = 2; AsciiString[Index] != '\0'; Index++) {\r
- CurrentChar = AsciiString[Index];\r
- HexNumber *= 16;\r
- if (CurrentChar >= '0' && CurrentChar <= '9') {\r
- HexNumber += CurrentChar - '0';\r
- } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {\r
- HexNumber += CurrentChar - 'a' + 10;\r
- } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {\r
- HexNumber += CurrentChar - 'A' + 10;\r
- } else {\r
- //\r
- // Unrecognized character\r
- //\r
- return EFI_ABORTED;\r
- }\r
- }\r
-\r
- *ReturnValue = HexNumber;\r
- } else {\r
- //\r
- // Verify string is a number\r
- //\r
- for (Index = 0; Index < strlen (AsciiString); Index++) {\r
- if (isdigit (AsciiString[Index]) == 0) {\r
- return EFI_ABORTED;\r
- }\r
- }\r
-\r
- *ReturnValue = atol (AsciiString);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-};\r
-\r
-CHAR8 *\r
-ReadLineInStream (\r
- IN FILE *InputFile,\r
- IN OUT CHAR8 *InputBuffer\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This function reads a line, stripping any comments.\r
- // BUGBUG: This is obsolete once genmake goes away...\r
-\r
-Arguments:\r
-\r
- InputFile Stream pointer.\r
- InputBuffer Buffer to read into, must be _MAX_PATH size.\r
-\r
-Returns:\r
-\r
- NULL if error or EOF\r
- InputBuffer otherwise\r
-\r
---*/\r
-{\r
- CHAR8 *CharPtr;\r
-\r
- //\r
- // Verify input parameters are not null\r
- //\r
- assert (InputFile);\r
- assert (InputBuffer);\r
-\r
- //\r
- // Read a line\r
- //\r
- if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {\r
- return NULL;\r
- }\r
- //\r
- // Strip any comments\r
- //\r
- CharPtr = strstr (InputBuffer, "//");\r
- if (CharPtr != 0) {\r
- CharPtr[0] = 0;\r
- }\r
-\r
- CharPtr = strstr (InputBuffer, "#");\r
- if (CharPtr != 0) {\r
- CharPtr[0] = 0;\r
- }\r
- //\r
- // Return the string\r
- //\r
- return InputBuffer;\r
-}\r
-\r
-BOOLEAN\r
-FindSectionInStream (\r
- IN FILE *InputFile,\r
- IN CHAR8 *Section\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This function parses a stream file from the beginning to find a section.\r
- The section string may be anywhere within a line.\r
- // BUGBUG: This is obsolete once genmake goes away...\r
-\r
-Arguments:\r
-\r
- InputFile Stream pointer.\r
- Section Section to search for\r
-\r
-Returns:\r
-\r
- FALSE if error or EOF\r
- TRUE if section found\r
-\r
---*/\r
-{\r
- CHAR8 InputBuffer[_MAX_PATH];\r
- CHAR8 *CurrentToken;\r
-\r
- //\r
- // Verify input is not NULL\r
- //\r
- assert (InputFile);\r
- assert (Section);\r
-\r
- //\r
- // Rewind to beginning of file\r
- //\r
- if (fseek (InputFile, 0, SEEK_SET) != 0) {\r
- return FALSE;\r
- }\r
- //\r
- // Read lines until the section is found\r
- //\r
- while (feof (InputFile) == 0) {\r
- //\r
- // Read a line\r
- //\r
- ReadLineInStream (InputFile, InputBuffer);\r
-\r
- //\r
- // Check if the section is found\r
- //\r
- CurrentToken = strstr (InputBuffer, Section);\r
- if (CurrentToken != NULL) {\r
- return TRUE;\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r