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