123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695 |
- /** @file
- This contains some useful functions for parsing INF files.
- Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <assert.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include "EfiUtilityMsgs.h"
- #include "ParseInf.h"
- #include "CommonLib.h"
- CHAR8 *
- ReadLine (
- IN MEMORY_FILE *InputFile,
- IN OUT CHAR8 *InputBuffer,
- IN UINTN MaxLength
- )
- /*++
- Routine Description:
- This function reads a line, stripping any comments.
- The function reads a string from the input stream argument and stores it in
- the input string. ReadLine reads characters from the current file position
- to and including the first newline character, to the end of the stream, or
- until the number of characters read is equal to MaxLength - 1, whichever
- comes first. The newline character, if read, is replaced with a \0.
- Arguments:
- InputFile Memory file image.
- InputBuffer Buffer to read into, must be MaxLength size.
- MaxLength The maximum size of the input buffer.
- Returns:
- NULL if error or EOF
- InputBuffer otherwise
- --*/
- {
- CHAR8 *CharPtr;
- CHAR8 *EndOfLine;
- UINTN CharsToCopy;
- //
- // Verify input parameters are not null
- //
- assert (InputBuffer);
- assert (InputFile->FileImage);
- assert (InputFile->Eof);
- assert (InputFile->CurrentFilePointer);
- //
- // Check for end of file condition
- //
- if (InputFile->CurrentFilePointer >= InputFile->Eof) {
- return NULL;
- }
- //
- // Find the next newline char
- //
- EndOfLine = strchr (InputFile->CurrentFilePointer, '\n');
- //
- // Determine the number of characters to copy.
- //
- if (EndOfLine == 0) {
- //
- // If no newline found, copy to the end of the file.
- //
- CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
- } else if (EndOfLine >= InputFile->Eof) {
- //
- // If the newline found was beyond the end of file, copy to the eof.
- //
- CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
- } else {
- //
- // Newline found in the file.
- //
- CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;
- }
- //
- // If the end of line is too big for the current buffer, set it to the max
- // size of the buffer (leaving room for the \0.
- //
- if (CharsToCopy > MaxLength - 1) {
- CharsToCopy = MaxLength - 1;
- }
- //
- // Copy the line.
- //
- memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy);
- //
- // Add the null termination over the 0x0D
- //
- if (InputBuffer[CharsToCopy - 1] == '\r') {
- InputBuffer[CharsToCopy - 1] = '\0';
- } else {
- InputBuffer[CharsToCopy] = '\0';
- }
- //
- // Increment the current file pointer (include the 0x0A)
- //
- InputFile->CurrentFilePointer += CharsToCopy + 1;
- //
- // Strip any comments
- //
- CharPtr = strstr (InputBuffer, "//");
- if (CharPtr != 0) {
- CharPtr[0] = 0;
- }
- //
- // Return the string
- //
- return InputBuffer;
- }
- BOOLEAN
- FindSection (
- IN MEMORY_FILE *InputFile,
- IN CHAR8 *Section
- )
- /*++
- Routine Description:
- This function parses a file from the beginning to find a section.
- The section string may be anywhere within a line.
- Arguments:
- InputFile Memory file image.
- Section Section to search for
- Returns:
- FALSE if error or EOF
- TRUE if section found
- --*/
- {
- CHAR8 InputBuffer[MAX_LONG_FILE_PATH];
- CHAR8 *CurrentToken;
- //
- // Verify input is not NULL
- //
- assert (InputFile->FileImage);
- assert (InputFile->Eof);
- assert (InputFile->CurrentFilePointer);
- assert (Section);
- //
- // Rewind to beginning of file
- //
- InputFile->CurrentFilePointer = InputFile->FileImage;
- //
- // Read lines until the section is found
- //
- while (InputFile->CurrentFilePointer < InputFile->Eof) {
- //
- // Read a line
- //
- ReadLine (InputFile, InputBuffer, MAX_LONG_FILE_PATH);
- //
- // Check if the section is found
- //
- CurrentToken = strstr (InputBuffer, Section);
- if (CurrentToken != NULL) {
- return TRUE;
- }
- }
- return FALSE;
- }
- EFI_STATUS
- FindToken (
- IN MEMORY_FILE *InputFile,
- IN CHAR8 *Section,
- IN CHAR8 *Token,
- IN UINTN Instance,
- OUT CHAR8 *Value
- )
- /*++
- Routine Description:
- Finds a token value given the section and token to search for.
- Arguments:
- InputFile Memory file image.
- Section The section to search for, a string within [].
- Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.
- Instance The instance of the token to search for. Zero is the first instance.
- Value The string that holds the value following the =. Must be MAX_LONG_FILE_PATH in size.
- Returns:
- EFI_SUCCESS Value found.
- EFI_ABORTED Format error detected in INF file.
- EFI_INVALID_PARAMETER Input argument was null.
- EFI_LOAD_ERROR Error reading from the file.
- EFI_NOT_FOUND Section/Token/Value not found.
- --*/
- {
- CHAR8 InputBuffer[MAX_LONG_FILE_PATH];
- CHAR8 *CurrentToken;
- CHAR8 *Delimiter;
- BOOLEAN ParseError;
- BOOLEAN ReadError;
- UINTN Occurrence;
- //
- // Check input parameters
- //
- if (InputFile->FileImage == NULL ||
- InputFile->Eof == NULL ||
- InputFile->CurrentFilePointer == NULL ||
- Section == NULL ||
- strlen (Section) == 0 ||
- Token == NULL ||
- strlen (Token) == 0 ||
- Value == NULL
- ) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Initialize error codes
- //
- ParseError = FALSE;
- ReadError = FALSE;
- //
- // Initialize our instance counter for the search token
- //
- Occurrence = 0;
- if (FindSection (InputFile, Section)) {
- //
- // Found the desired section, find and read the desired token
- //
- do {
- //
- // Read a line from the file
- //
- if (ReadLine (InputFile, InputBuffer, MAX_LONG_FILE_PATH) == NULL) {
- //
- // Error reading from input file
- //
- ReadError = TRUE;
- break;
- }
- //
- // Get the first non-whitespace string
- //
- Delimiter = strchr (InputBuffer, '=');
- if (Delimiter != NULL) {
- *Delimiter = 0;
- }
- CurrentToken = strtok (InputBuffer, " \t\n");
- if (CurrentToken == NULL || Delimiter == NULL) {
- //
- // Whitespace line found (or comment) so continue
- //
- CurrentToken = InputBuffer;
- continue;
- }
- //
- // Make sure we have not reached the end of the current section
- //
- if (CurrentToken[0] == '[') {
- break;
- }
- //
- // Compare the current token with the desired token
- //
- if (strcmp (CurrentToken, Token) == 0) {
- //
- // Found it
- //
- //
- // Check if it is the correct instance
- //
- if (Instance == Occurrence) {
- //
- // Copy the contents following the =
- //
- CurrentToken = Delimiter + 1;
- if (*CurrentToken == 0) {
- //
- // Nothing found, parsing error
- //
- ParseError = TRUE;
- } else {
- //
- // Strip leading white space
- //
- while (*CurrentToken == ' ' || *CurrentToken == '\t') {
- CurrentToken++;
- }
- //
- // Copy the current token to the output value
- //
- strcpy (Value, CurrentToken);
- //
- // Strip trailing white space
- //
- while (strlen(Value) > 0 && (*(Value + strlen(Value) - 1) == ' ' || *(Value + strlen(Value) - 1) == '\t')) {
- *(Value + strlen(Value) - 1) = 0;
- }
- return EFI_SUCCESS;
- }
- } else {
- //
- // Increment the occurrence found
- //
- Occurrence++;
- }
- }
- } while (
- !ParseError &&
- !ReadError &&
- InputFile->CurrentFilePointer < InputFile->Eof &&
- CurrentToken[0] != '[' &&
- Occurrence <= Instance
- );
- }
- //
- // Distinguish between read errors and INF file format errors.
- //
- if (ReadError) {
- return EFI_LOAD_ERROR;
- }
- if (ParseError) {
- return EFI_ABORTED;
- }
- return EFI_NOT_FOUND;
- }
- EFI_STATUS
- StringToGuid (
- IN CHAR8 *AsciiGuidBuffer,
- OUT EFI_GUID *GuidBuffer
- )
- /*++
- Routine Description:
- Converts a string to an EFI_GUID. The string must be in the
- xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
- Arguments:
- AsciiGuidBuffer - pointer to ascii string
- GuidBuffer - pointer to destination Guid
- Returns:
- EFI_ABORTED Could not convert the string
- EFI_SUCCESS The string was successfully converted
- EFI_INVALID_PARAMETER Input parameter is invalid.
- --*/
- {
- INT32 Index;
- int Data1;
- int Data2;
- int Data3;
- int Data4[8];
- if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Check Guid Format strictly xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- //
- for (Index = 0; AsciiGuidBuffer[Index] != '\0' && Index < 37; Index ++) {
- if (Index == 8 || Index == 13 || Index == 18 || Index == 23) {
- if (AsciiGuidBuffer[Index] != '-') {
- break;
- }
- } else {
- if (((AsciiGuidBuffer[Index] >= '0') && (AsciiGuidBuffer[Index] <= '9')) ||
- ((AsciiGuidBuffer[Index] >= 'a') && (AsciiGuidBuffer[Index] <= 'f')) ||
- ((AsciiGuidBuffer[Index] >= 'A') && (AsciiGuidBuffer[Index] <= 'F'))) {
- continue;
- } else {
- break;
- }
- }
- }
- if (Index < 36 || AsciiGuidBuffer[36] != '\0') {
- Error (NULL, 0, 1003, "Invalid option value", "Incorrect GUID \"%s\"\n Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", AsciiGuidBuffer);
- return EFI_ABORTED;
- }
- //
- // Scan the guid string into the buffer
- //
- Index = sscanf (
- AsciiGuidBuffer,
- "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
- &Data1,
- &Data2,
- &Data3,
- &Data4[0],
- &Data4[1],
- &Data4[2],
- &Data4[3],
- &Data4[4],
- &Data4[5],
- &Data4[6],
- &Data4[7]
- );
- //
- // Verify the correct number of items were scanned.
- //
- if (Index != 11) {
- Error (NULL, 0, 1003, "Invalid option value", "Incorrect GUID \"%s\"\n Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", AsciiGuidBuffer);
- return EFI_ABORTED;
- }
- //
- // Copy the data into our GUID.
- //
- GuidBuffer->Data1 = (UINT32) Data1;
- GuidBuffer->Data2 = (UINT16) Data2;
- GuidBuffer->Data3 = (UINT16) Data3;
- GuidBuffer->Data4[0] = (UINT8) Data4[0];
- GuidBuffer->Data4[1] = (UINT8) Data4[1];
- GuidBuffer->Data4[2] = (UINT8) Data4[2];
- GuidBuffer->Data4[3] = (UINT8) Data4[3];
- GuidBuffer->Data4[4] = (UINT8) Data4[4];
- GuidBuffer->Data4[5] = (UINT8) Data4[5];
- GuidBuffer->Data4[6] = (UINT8) Data4[6];
- GuidBuffer->Data4[7] = (UINT8) Data4[7];
- return EFI_SUCCESS;
- }
- EFI_STATUS
- AsciiStringToUint64 (
- IN CONST CHAR8 *AsciiString,
- IN BOOLEAN IsHex,
- OUT UINT64 *ReturnValue
- )
- /*++
- Routine Description:
- Converts a null terminated ascii string that represents a number into a
- UINT64 value. A hex number may be preceded by a 0x, but may not be
- succeeded by an h. A number without 0x or 0X is considered to be base 10
- unless the IsHex input is true.
- Arguments:
- AsciiString The string to convert.
- IsHex Force the string to be treated as a hex number.
- ReturnValue The return value.
- Returns:
- EFI_SUCCESS Number successfully converted.
- EFI_ABORTED Invalid character encountered.
- --*/
- {
- UINT8 Index;
- UINT64 Value;
- CHAR8 CurrentChar;
- //
- // Initialize the result
- //
- Value = 0;
- Index = 0;
- //
- // Check input parameter
- //
- if (AsciiString == NULL || ReturnValue == NULL || strlen(AsciiString) > 0xFF) {
- return EFI_INVALID_PARAMETER;
- }
- while (AsciiString[Index] == ' ') {
- Index ++;
- }
- //
- // Add each character to the result
- //
- //
- // Skip first two chars only if the string starts with '0x' or '0X'
- //
- if (AsciiString[Index] == '0' && (AsciiString[Index + 1] == 'x' || AsciiString[Index + 1] == 'X')) {
- IsHex = TRUE;
- Index += 2;
- }
- if (IsHex) {
- //
- // Convert the hex string.
- //
- for (; AsciiString[Index] != '\0'; Index++) {
- CurrentChar = AsciiString[Index];
- if (CurrentChar == ' ') {
- break;
- }
- //
- // Verify Hex string
- //
- if (isxdigit ((int)CurrentChar) == 0) {
- return EFI_ABORTED;
- }
- //
- // Add hex value
- //
- Value *= 16;
- if (CurrentChar >= '0' && CurrentChar <= '9') {
- Value += CurrentChar - '0';
- } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {
- Value += CurrentChar - 'a' + 10;
- } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {
- Value += CurrentChar - 'A' + 10;
- }
- }
- *ReturnValue = Value;
- } else {
- //
- // Convert dec string is a number
- //
- for (; Index < strlen (AsciiString); Index++) {
- CurrentChar = AsciiString[Index];
- if (CurrentChar == ' ') {
- break;
- }
- //
- // Verify Dec string
- //
- if (isdigit ((int)CurrentChar) == 0) {
- return EFI_ABORTED;
- }
- //
- // Add dec value
- //
- Value = Value * 10;
- Value += CurrentChar - '0';
- }
- *ReturnValue = Value;
- }
- return EFI_SUCCESS;
- }
- CHAR8 *
- ReadLineInStream (
- IN FILE *InputFile,
- IN OUT CHAR8 *InputBuffer
- )
- /*++
- Routine Description:
- This function reads a line, stripping any comments.
- // BUGBUG: This is obsolete once genmake goes away...
- Arguments:
- InputFile Stream pointer.
- InputBuffer Buffer to read into, must be MAX_LONG_FILE_PATH size.
- Returns:
- NULL if error or EOF
- InputBuffer otherwise
- --*/
- {
- CHAR8 *CharPtr;
- //
- // Verify input parameters are not null
- //
- assert (InputFile);
- assert (InputBuffer);
- //
- // Read a line
- //
- if (fgets (InputBuffer, MAX_LONG_FILE_PATH, InputFile) == NULL) {
- return NULL;
- }
- //
- // Strip any comments
- //
- CharPtr = strstr (InputBuffer, "//");
- if (CharPtr != 0) {
- CharPtr[0] = 0;
- }
- CharPtr = strstr (InputBuffer, "#");
- if (CharPtr != 0) {
- CharPtr[0] = 0;
- }
- //
- // Return the string
- //
- return InputBuffer;
- }
- BOOLEAN
- FindSectionInStream (
- IN FILE *InputFile,
- IN CHAR8 *Section
- )
- /*++
- Routine Description:
- This function parses a stream file from the beginning to find a section.
- The section string may be anywhere within a line.
- // BUGBUG: This is obsolete once genmake goes away...
- Arguments:
- InputFile Stream pointer.
- Section Section to search for
- Returns:
- FALSE if error or EOF
- TRUE if section found
- --*/
- {
- CHAR8 InputBuffer[MAX_LONG_FILE_PATH];
- CHAR8 *CurrentToken;
- //
- // Verify input is not NULL
- //
- assert (InputFile);
- assert (Section);
- //
- // Rewind to beginning of file
- //
- if (fseek (InputFile, 0, SEEK_SET) != 0) {
- return FALSE;
- }
- //
- // Read lines until the section is found
- //
- while (feof (InputFile) == 0) {
- //
- // Read a line
- //
- ReadLineInStream (InputFile, InputBuffer);
- //
- // Check if the section is found
- //
- CurrentToken = strstr (InputBuffer, Section);
- if (CurrentToken != NULL) {
- return TRUE;
- }
- }
- return FALSE;
- }
|