• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*++
2 
3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14   ParseInf.c
15 
16 Abstract:
17 
18   This contains some useful functions for parsing INF files.
19 
20 --*/
21 
22 #include "ParseInf.h"
23 #include <assert.h>
24 #include <string.h>
25 #include <ctype.h>
26 
27 CHAR8 *
ReadLine(IN MEMORY_FILE * InputFile,IN OUT CHAR8 * InputBuffer,IN UINTN MaxLength)28 ReadLine (
29   IN MEMORY_FILE    *InputFile,
30   IN OUT CHAR8      *InputBuffer,
31   IN UINTN          MaxLength
32   )
33 /*++
34 
35 Routine Description:
36 
37   This function reads a line, stripping any comments.
38   The function reads a string from the input stream argument and stores it in
39   the input string. ReadLine reads characters from the current file position
40   to and including the first newline character, to the end of the stream, or
41   until the number of characters read is equal to MaxLength - 1, whichever
42   comes first.  The newline character, if read, is replaced with a \0.
43 
44 Arguments:
45 
46   InputFile     Memory file image.
47   InputBuffer   Buffer to read into, must be _MAX_PATH size.
48   MaxLength     The maximum size of the input buffer.
49 
50 Returns:
51 
52   NULL if error or EOF
53   InputBuffer otherwise
54 
55 --*/
56 {
57   CHAR8 *CharPtr;
58   CHAR8 *EndOfLine;
59   UINTN CharsToCopy;
60 
61   //
62   // Verify input parameters are not null
63   //
64   assert (InputBuffer);
65   assert (InputFile->FileImage);
66   assert (InputFile->Eof);
67   assert (InputFile->CurrentFilePointer);
68 
69   //
70   // Check for end of file condition
71   //
72   if (InputFile->CurrentFilePointer >= InputFile->Eof) {
73     return NULL;
74   }
75   //
76   // Find the next newline char
77   //
78   EndOfLine = strchr (InputFile->CurrentFilePointer, '\n');
79 
80   //
81   // Determine the number of characters to copy.
82   //
83   if (EndOfLine == 0) {
84     //
85     // If no newline found, copy to the end of the file.
86     //
87     CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
88   } else if (EndOfLine >= InputFile->Eof) {
89     //
90     // If the newline found was beyond the end of file, copy to the eof.
91     //
92     CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
93   } else {
94     //
95     // Newline found in the file.
96     //
97     CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;
98   }
99   //
100   // If the end of line is too big for the current buffer, set it to the max
101   // size of the buffer (leaving room for the \0.
102   //
103   if (CharsToCopy > MaxLength - 1) {
104     CharsToCopy = MaxLength - 1;
105   }
106   //
107   // Copy the line.
108   //
109   memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy);
110 
111   //
112   // Add the null termination over the 0x0D
113   //
114   InputBuffer[CharsToCopy - 1] = '\0';
115 
116   //
117   // Increment the current file pointer (include the 0x0A)
118   //
119   InputFile->CurrentFilePointer += CharsToCopy + 1;
120 
121   //
122   // Strip any comments
123   //
124   CharPtr = strstr (InputBuffer, "//");
125   if (CharPtr != 0) {
126     CharPtr[0] = 0;
127   }
128   //
129   // Return the string
130   //
131   return InputBuffer;
132 }
133 
134 BOOLEAN
FindSection(IN MEMORY_FILE * InputFile,IN CHAR8 * Section)135 FindSection (
136   IN MEMORY_FILE    *InputFile,
137   IN CHAR8          *Section
138   )
139 /*++
140 
141 Routine Description:
142 
143   This function parses a file from the beginning to find a section.
144   The section string may be anywhere within a line.
145 
146 Arguments:
147 
148   InputFile     Memory file image.
149   Section       Section to search for
150 
151 Returns:
152 
153   FALSE if error or EOF
154   TRUE if section found
155 
156 --*/
157 {
158   CHAR8 InputBuffer[_MAX_PATH];
159   CHAR8 *CurrentToken;
160 
161   //
162   // Verify input is not NULL
163   //
164   assert (InputFile->FileImage);
165   assert (InputFile->Eof);
166   assert (InputFile->CurrentFilePointer);
167   assert (Section);
168 
169   //
170   // Rewind to beginning of file
171   //
172   InputFile->CurrentFilePointer = InputFile->FileImage;
173 
174   //
175   // Read lines until the section is found
176   //
177   while (InputFile->CurrentFilePointer < InputFile->Eof) {
178     //
179     // Read a line
180     //
181     ReadLine (InputFile, InputBuffer, _MAX_PATH);
182 
183     //
184     // Check if the section is found
185     //
186     CurrentToken = strstr (InputBuffer, Section);
187     if (CurrentToken != NULL) {
188       return TRUE;
189     }
190   }
191 
192   return FALSE;
193 }
194 
195 EFI_STATUS
FindToken(IN MEMORY_FILE * InputFile,IN CHAR8 * Section,IN CHAR8 * Token,IN UINTN Instance,OUT CHAR8 * Value)196 FindToken (
197   IN MEMORY_FILE    *InputFile,
198   IN CHAR8          *Section,
199   IN CHAR8          *Token,
200   IN UINTN          Instance,
201   OUT CHAR8         *Value
202   )
203 /*++
204 
205 Routine Description:
206 
207   Finds a token value given the section and token to search for.
208 
209 Arguments:
210 
211   InputFile Memory file image.
212   Section   The section to search for, a string within [].
213   Token     The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.
214   Instance  The instance of the token to search for.  Zero is the first instance.
215   Value     The string that holds the value following the =.  Must be _MAX_PATH in size.
216 
217 Returns:
218 
219   EFI_SUCCESS             Value found.
220   EFI_ABORTED             Format error detected in INF file.
221   EFI_INVALID_PARAMETER   Input argument was null.
222   EFI_LOAD_ERROR          Error reading from the file.
223   EFI_NOT_FOUND           Section/Token/Value not found.
224 
225 --*/
226 {
227   CHAR8   InputBuffer[_MAX_PATH];
228   CHAR8   *CurrentToken;
229   BOOLEAN ParseError;
230   BOOLEAN ReadError;
231   UINTN   Occurrance;
232 
233   //
234   // Check input parameters
235   //
236   if (InputFile->FileImage == NULL ||
237       InputFile->Eof == NULL ||
238       InputFile->CurrentFilePointer == NULL ||
239       Section == NULL ||
240       strlen (Section) == 0 ||
241       Token == NULL ||
242       strlen (Token) == 0 ||
243       Value == NULL
244       ) {
245     return EFI_INVALID_PARAMETER;
246   }
247   //
248   // Initialize error codes
249   //
250   ParseError  = FALSE;
251   ReadError   = FALSE;
252 
253   //
254   // Initialize our instance counter for the search token
255   //
256   Occurrance = 0;
257 
258   if (FindSection (InputFile, Section)) {
259     //
260     // Found the desired section, find and read the desired token
261     //
262     do {
263       //
264       // Read a line from the file
265       //
266       if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {
267         //
268         // Error reading from input file
269         //
270         ReadError = TRUE;
271         break;
272       }
273       //
274       // Get the first non-whitespace string
275       //
276       CurrentToken = strtok (InputBuffer, " \t\n");
277       if (CurrentToken == NULL) {
278         //
279         // Whitespace line found (or comment) so continue
280         //
281         CurrentToken = InputBuffer;
282         continue;
283       }
284       //
285       // Make sure we have not reached the end of the current section
286       //
287       if (CurrentToken[0] == '[') {
288         break;
289       }
290       //
291       // Compare the current token with the desired token
292       //
293       if (strcmp (CurrentToken, Token) == 0) {
294         //
295         // Found it
296         //
297         //
298         // Check if it is the correct instance
299         //
300         if (Instance == Occurrance) {
301           //
302           // Copy the contents following the =
303           //
304           CurrentToken = strtok (NULL, "= \t\n");
305           if (CurrentToken == NULL) {
306             //
307             // Nothing found, parsing error
308             //
309             ParseError = TRUE;
310           } else {
311             //
312             // Copy the current token to the output value
313             //
314             strcpy (Value, CurrentToken);
315             return EFI_SUCCESS;
316           }
317         } else {
318           //
319           // Increment the occurrance found
320           //
321           Occurrance++;
322         }
323       }
324     } while (
325       !ParseError &&
326       !ReadError &&
327       InputFile->CurrentFilePointer < InputFile->Eof &&
328       CurrentToken[0] != '[' &&
329       Occurrance <= Instance
330     );
331   }
332   //
333   // Distinguish between read errors and INF file format errors.
334   //
335   if (ReadError) {
336     return EFI_LOAD_ERROR;
337   }
338 
339   if (ParseError) {
340     return EFI_ABORTED;
341   }
342 
343   return EFI_NOT_FOUND;
344 }
345 
346 EFI_STATUS
FindTokenInstanceInSection(IN MEMORY_FILE * InputFile,IN CHAR8 * Section,IN UINTN Instance,OUT CHAR8 * Token,OUT CHAR8 * Value)347 FindTokenInstanceInSection (
348   IN MEMORY_FILE    *InputFile,
349   IN CHAR8          *Section,
350   IN UINTN          Instance,
351   OUT CHAR8         *Token,
352   OUT CHAR8         *Value
353   )
354 /*++
355 
356 Routine Description:
357 
358   Finds the Instance-th token in a section.
359 
360 Arguments:
361 
362   InputFile Memory file image.
363   Section   The section to search for, a string within [].
364   Instance  Specify the Instance-th token to search for, starting from zero
365   Token     The token name to return. Caller should allocate the buffer.
366             Must be _MAX_PATH in size.
367   Value     The token value to return. Caller should allocate the buffer.
368             Must be _MAX_PATH in size.
369 
370 Returns:
371 
372   EFI_SUCCESS             Token and Value found.
373   EFI_ABORTED             Format error detected in INF file.
374   EFI_INVALID_PARAMETER   Input argument was null.
375   EFI_LOAD_ERROR          Error reading from the file.
376   EFI_NOT_FOUND           Section/Token/Value not found.
377 
378 --*/
379 {
380   CHAR8   InputBuffer[_MAX_PATH];
381   CHAR8   *CurrentToken;
382   CHAR8   *CurrentValue;
383   BOOLEAN ParseError;
384   BOOLEAN ReadError;
385   UINTN   InstanceIndex;
386 
387   //
388   // Check input parameters
389   //
390   if (InputFile->FileImage == NULL ||
391       InputFile->Eof == NULL ||
392       InputFile->CurrentFilePointer == NULL ||
393       Section == NULL ||
394       strlen (Section) == 0 ||
395       Value == NULL
396       ) {
397     return EFI_INVALID_PARAMETER;
398   }
399   //
400   // Initialize error codes
401   //
402   ParseError  = FALSE;
403   ReadError   = FALSE;
404 
405   //
406   // Initialize our instance counter for the search token
407   //
408   InstanceIndex = 0;
409 
410   if (FindSection (InputFile, Section)) {
411     //
412     // Found the desired section, find and read the desired token
413     //
414     do {
415       //
416       // Read a line from the file
417       //
418       if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {
419         //
420         // Error reading from input file
421         //
422         ReadError = TRUE;
423         break;
424       }
425       //
426       // Get the first non-whitespace string
427       //
428       CurrentToken = strtok (InputBuffer, " \t\n");
429       if (CurrentToken == NULL) {
430         //
431         // Whitespace line found (or comment) so continue
432         //
433         CurrentToken = InputBuffer;
434         continue;
435       }
436       //
437       // Make sure we have not reached the end of the current section
438       //
439       if (CurrentToken[0] == '[') {
440         break;
441       }
442       //
443       // Check if it is the correct instance
444       //
445       if (Instance == InstanceIndex) {
446         //
447         // Copy the contents following the =
448         //
449         CurrentValue = strtok (NULL, "= \t\n");
450         if (CurrentValue == NULL) {
451           //
452           // Nothing found, parsing error
453           //
454           ParseError = TRUE;
455         } else {
456           //
457           // Copy the current token to the output value
458           //
459           strcpy (Token, CurrentToken);
460           strcpy (Value, CurrentValue);
461           return EFI_SUCCESS;
462         }
463       } else {
464         //
465         // Increment the occurrance found
466         //
467         InstanceIndex++;
468       }
469     } while (
470       !ParseError &&
471       !ReadError &&
472       InputFile->CurrentFilePointer < InputFile->Eof &&
473       CurrentToken[0] != '[' &&
474       InstanceIndex <= Instance
475     );
476   }
477   //
478   // Distinguish between read errors and INF file format errors.
479   //
480   if (ReadError) {
481     return EFI_LOAD_ERROR;
482   }
483 
484   if (ParseError) {
485     return EFI_ABORTED;
486   }
487 
488   return EFI_NOT_FOUND;
489 }
490 
491 
492 EFI_STATUS
StringToGuid(IN CHAR8 * AsciiGuidBuffer,OUT EFI_GUID * GuidBuffer)493 StringToGuid (
494   IN CHAR8      *AsciiGuidBuffer,
495   OUT EFI_GUID  *GuidBuffer
496   )
497 /*++
498 
499 Routine Description:
500 
501   Converts a string to an EFI_GUID.  The string must be in the
502   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
503 
504 Arguments:
505 
506   AsciiGuidBuffer - pointer to ascii string
507   GuidBuffer      - pointer to destination Guid
508 
509 Returns:
510 
511   EFI_ABORTED             Could not convert the string
512   EFI_SUCCESS             The string was successfully converted
513   EFI_INVALID_PARAMETER   Input parameter is invalid.
514 
515 --*/
516 {
517   INT32 Index;
518   UINTN Data1;
519   UINTN Data2;
520   UINTN Data3;
521   UINTN Data4[8];
522 
523   if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {
524     return EFI_INVALID_PARAMETER;
525   }
526   //
527   // Scan the guid string into the buffer
528   //
529   Index = sscanf (
530             AsciiGuidBuffer,
531             "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx",
532             &Data1,
533             &Data2,
534             &Data3,
535             &Data4[0],
536             &Data4[1],
537             &Data4[2],
538             &Data4[3],
539             &Data4[4],
540             &Data4[5],
541             &Data4[6],
542             &Data4[7]
543             );
544 
545   //
546   // Verify the correct number of items were scanned.
547   //
548   if (Index != 11) {
549     printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer);
550     return EFI_ABORTED;
551   }
552   //
553   // Copy the data into our GUID.
554   //
555   GuidBuffer->Data1     = (UINT32) Data1;
556   GuidBuffer->Data2     = (UINT16) Data2;
557   GuidBuffer->Data3     = (UINT16) Data3;
558   GuidBuffer->Data4[0]  = (UINT8) Data4[0];
559   GuidBuffer->Data4[1]  = (UINT8) Data4[1];
560   GuidBuffer->Data4[2]  = (UINT8) Data4[2];
561   GuidBuffer->Data4[3]  = (UINT8) Data4[3];
562   GuidBuffer->Data4[4]  = (UINT8) Data4[4];
563   GuidBuffer->Data4[5]  = (UINT8) Data4[5];
564   GuidBuffer->Data4[6]  = (UINT8) Data4[6];
565   GuidBuffer->Data4[7]  = (UINT8) Data4[7];
566 
567   return EFI_SUCCESS;
568 }
569 
570 EFI_STATUS
AsciiStringToUint64(IN CONST CHAR8 * AsciiString,IN BOOLEAN IsHex,OUT UINT64 * ReturnValue)571 AsciiStringToUint64 (
572   IN CONST CHAR8  *AsciiString,
573   IN BOOLEAN      IsHex,
574   OUT UINT64      *ReturnValue
575   )
576 /*++
577 
578 Routine Description:
579 
580   Converts a null terminated ascii string that represents a number into a
581   UINT64 value.  A hex number may be preceeded by a 0x, but may not be
582   succeeded by an h.  A number without 0x or 0X is considered to be base 10
583   unless the IsHex input is true.
584 
585 Arguments:
586 
587   AsciiString   The string to convert.
588   IsHex         Force the string to be treated as a hex number.
589   ReturnValue   The return value.
590 
591 Returns:
592 
593   EFI_SUCCESS   Number successfully converted.
594   EFI_ABORTED   Invalid character encountered.
595 
596 --*/
597 {
598   UINT8   Index;
599   UINT64  HexNumber;
600   CHAR8   CurrentChar;
601 
602   //
603   // Initialize the result
604   //
605   HexNumber = 0;
606 
607   //
608   // Add each character to the result
609   //
610   if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {
611     //
612     // Verify string is a hex number
613     //
614     for (Index = 2; Index < strlen (AsciiString); Index++) {
615       if (isxdigit (AsciiString[Index]) == 0) {
616         return EFI_ABORTED;
617       }
618     }
619     //
620     // Convert the hex string.
621     //
622     for (Index = 2; AsciiString[Index] != '\0'; Index++) {
623       CurrentChar = AsciiString[Index];
624       HexNumber *= 16;
625       if (CurrentChar >= '0' && CurrentChar <= '9') {
626         HexNumber += CurrentChar - '0';
627       } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {
628         HexNumber += CurrentChar - 'a' + 10;
629       } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {
630         HexNumber += CurrentChar - 'A' + 10;
631       } else {
632         //
633         // Unrecognized character
634         //
635         return EFI_ABORTED;
636       }
637     }
638 
639     *ReturnValue = HexNumber;
640   } else {
641     //
642     // Verify string is a number
643     //
644     for (Index = 0; Index < strlen (AsciiString); Index++) {
645       if (isdigit (AsciiString[Index]) == 0) {
646         return EFI_ABORTED;
647       }
648     }
649 
650     *ReturnValue = atol (AsciiString);
651   }
652 
653   return EFI_SUCCESS;
654 };
655 
656 CHAR8 *
ReadLineInStream(IN FILE * InputFile,IN OUT CHAR8 * InputBuffer)657 ReadLineInStream (
658   IN FILE       *InputFile,
659   IN OUT CHAR8  *InputBuffer
660   )
661 /*++
662 
663 Routine Description:
664 
665   This function reads a line, stripping any comments.
666   // BUGBUG:  This is obsolete once genmake goes away...
667 
668 Arguments:
669 
670   InputFile     Stream pointer.
671   InputBuffer   Buffer to read into, must be _MAX_PATH size.
672 
673 Returns:
674 
675   NULL if error or EOF
676   InputBuffer otherwise
677 
678 --*/
679 {
680   CHAR8 *CharPtr;
681 
682   //
683   // Verify input parameters are not null
684   //
685   assert (InputFile);
686   assert (InputBuffer);
687 
688   //
689   // Read a line
690   //
691   if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {
692     return NULL;
693   }
694   //
695   // Strip any comments
696   //
697   CharPtr = strstr (InputBuffer, "//");
698   if (CharPtr != 0) {
699     CharPtr[0] = 0;
700   }
701 
702   CharPtr = strstr (InputBuffer, "#");
703   if (CharPtr != 0) {
704     CharPtr[0] = 0;
705   }
706   //
707   // Return the string
708   //
709   return InputBuffer;
710 }
711 
712 BOOLEAN
FindSectionInStream(IN FILE * InputFile,IN CHAR8 * Section)713 FindSectionInStream (
714   IN FILE       *InputFile,
715   IN CHAR8      *Section
716   )
717 /*++
718 
719 Routine Description:
720 
721   This function parses a stream file from the beginning to find a section.
722   The section string may be anywhere within a line.
723   // BUGBUG:  This is obsolete once genmake goes away...
724 
725 Arguments:
726 
727   InputFile     Stream pointer.
728   Section       Section to search for
729 
730 Returns:
731 
732   FALSE if error or EOF
733   TRUE if section found
734 
735 --*/
736 {
737   CHAR8 InputBuffer[_MAX_PATH];
738   CHAR8 *CurrentToken;
739 
740   //
741   // Verify input is not NULL
742   //
743   assert (InputFile);
744   assert (Section);
745 
746   //
747   // Rewind to beginning of file
748   //
749   if (fseek (InputFile, 0, SEEK_SET) != 0) {
750     return FALSE;
751   }
752   //
753   // Read lines until the section is found
754   //
755   while (feof (InputFile) == 0) {
756     //
757     // Read a line
758     //
759     ReadLineInStream (InputFile, InputBuffer);
760 
761     //
762     // Check if the section is found
763     //
764     CurrentToken = strstr (InputBuffer, Section);
765     if (CurrentToken != NULL) {
766       return TRUE;
767     }
768   }
769 
770   return FALSE;
771 }
772