]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / Common / ParseInf.c
CommitLineData
3eb9473e 1/*++\r
2\r
3Copyright (c) 2004, Intel Corporation \r
4All rights reserved. This 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
347StringToGuid (\r
348 IN CHAR8 *AsciiGuidBuffer,\r
349 OUT EFI_GUID *GuidBuffer\r
350 )\r
351/*++\r
352\r
353Routine Description: \r
354\r
355 Converts a string to an EFI_GUID. The string must be in the \r
356 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.\r
357\r
358Arguments: \r
359\r
360 AsciiGuidBuffer - pointer to ascii string\r
361 GuidBuffer - pointer to destination Guid\r
362\r
363Returns: \r
364\r
365 EFI_ABORTED Could not convert the string\r
366 EFI_SUCCESS The string was successfully converted\r
367 EFI_INVALID_PARAMETER Input parameter is invalid.\r
368\r
369--*/\r
370{\r
371 INT32 Index;\r
372 UINTN Data1;\r
373 UINTN Data2;\r
374 UINTN Data3;\r
375 UINTN Data4[8];\r
376\r
377 if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {\r
378 return EFI_INVALID_PARAMETER;\r
379 }\r
380 //\r
381 // Scan the guid string into the buffer\r
382 //\r
383 Index = sscanf (\r
384 AsciiGuidBuffer,\r
385 "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx",\r
386 &Data1,\r
387 &Data2,\r
388 &Data3,\r
389 &Data4[0],\r
390 &Data4[1],\r
391 &Data4[2],\r
392 &Data4[3],\r
393 &Data4[4],\r
394 &Data4[5],\r
395 &Data4[6],\r
396 &Data4[7]\r
397 );\r
398\r
399 //\r
400 // Verify the correct number of items were scanned.\r
401 //\r
402 if (Index != 11) {\r
403 printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer);\r
404 return EFI_ABORTED;\r
405 }\r
406 //\r
407 // Copy the data into our GUID.\r
408 //\r
409 GuidBuffer->Data1 = (UINT32) Data1;\r
410 GuidBuffer->Data2 = (UINT16) Data2;\r
411 GuidBuffer->Data3 = (UINT16) Data3;\r
412 GuidBuffer->Data4[0] = (UINT8) Data4[0];\r
413 GuidBuffer->Data4[1] = (UINT8) Data4[1];\r
414 GuidBuffer->Data4[2] = (UINT8) Data4[2];\r
415 GuidBuffer->Data4[3] = (UINT8) Data4[3];\r
416 GuidBuffer->Data4[4] = (UINT8) Data4[4];\r
417 GuidBuffer->Data4[5] = (UINT8) Data4[5];\r
418 GuidBuffer->Data4[6] = (UINT8) Data4[6];\r
419 GuidBuffer->Data4[7] = (UINT8) Data4[7];\r
420\r
421 return EFI_SUCCESS;\r
422}\r
423\r
424EFI_STATUS\r
425AsciiStringToUint64 (\r
426 IN CONST CHAR8 *AsciiString,\r
427 IN BOOLEAN IsHex,\r
428 OUT UINT64 *ReturnValue\r
429 )\r
430/*++\r
431\r
432Routine Description:\r
433\r
434 Converts a null terminated ascii string that represents a number into a \r
435 UINT64 value. A hex number may be preceeded by a 0x, but may not be \r
436 succeeded by an h. A number without 0x or 0X is considered to be base 10 \r
437 unless the IsHex input is true.\r
438\r
439Arguments:\r
440\r
441 AsciiString The string to convert.\r
442 IsHex Force the string to be treated as a hex number.\r
443 ReturnValue The return value.\r
444\r
445Returns:\r
446\r
447 EFI_SUCCESS Number successfully converted.\r
448 EFI_ABORTED Invalid character encountered.\r
449\r
450--*/\r
451{\r
452 UINT8 Index;\r
453 UINT64 HexNumber;\r
454 CHAR8 CurrentChar;\r
455\r
456 //\r
457 // Initialize the result\r
458 //\r
459 HexNumber = 0;\r
460\r
461 //\r
462 // Add each character to the result\r
463 //\r
464 if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {\r
465 //\r
466 // Verify string is a hex number\r
467 //\r
468 for (Index = 2; Index < strlen (AsciiString); Index++) {\r
469 if (isxdigit (AsciiString[Index]) == 0) {\r
470 return EFI_ABORTED;\r
471 }\r
472 }\r
473 //\r
474 // Convert the hex string.\r
475 //\r
476 for (Index = 2; AsciiString[Index] != '\0'; Index++) {\r
477 CurrentChar = AsciiString[Index];\r
478 HexNumber *= 16;\r
479 if (CurrentChar >= '0' && CurrentChar <= '9') {\r
480 HexNumber += CurrentChar - '0';\r
481 } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {\r
482 HexNumber += CurrentChar - 'a' + 10;\r
483 } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {\r
484 HexNumber += CurrentChar - 'A' + 10;\r
485 } else {\r
486 //\r
487 // Unrecognized character\r
488 //\r
489 return EFI_ABORTED;\r
490 }\r
491 }\r
492\r
493 *ReturnValue = HexNumber;\r
494 } else {\r
495 //\r
496 // Verify string is a number\r
497 //\r
498 for (Index = 0; Index < strlen (AsciiString); Index++) {\r
499 if (isdigit (AsciiString[Index]) == 0) {\r
500 return EFI_ABORTED;\r
501 }\r
502 }\r
503\r
504 *ReturnValue = atol (AsciiString);\r
505 }\r
506\r
507 return EFI_SUCCESS;\r
508};\r
509\r
510CHAR8 *\r
511ReadLineInStream (\r
512 IN FILE *InputFile,\r
513 IN OUT CHAR8 *InputBuffer\r
514 )\r
515/*++\r
516\r
517Routine Description:\r
518\r
519 This function reads a line, stripping any comments.\r
520 // BUGBUG: This is obsolete once genmake goes away...\r
521\r
522Arguments:\r
523\r
524 InputFile Stream pointer.\r
525 InputBuffer Buffer to read into, must be _MAX_PATH size.\r
526\r
527Returns:\r
528\r
529 NULL if error or EOF\r
530 InputBuffer otherwise\r
531\r
532--*/\r
533{\r
534 CHAR8 *CharPtr;\r
535\r
536 //\r
537 // Verify input parameters are not null\r
538 //\r
539 assert (InputFile);\r
540 assert (InputBuffer);\r
541\r
542 //\r
543 // Read a line\r
544 //\r
545 if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {\r
546 return NULL;\r
547 }\r
548 //\r
549 // Strip any comments\r
550 //\r
551 CharPtr = strstr (InputBuffer, "//");\r
552 if (CharPtr != 0) {\r
553 CharPtr[0] = 0;\r
554 }\r
555\r
556 CharPtr = strstr (InputBuffer, "#");\r
557 if (CharPtr != 0) {\r
558 CharPtr[0] = 0;\r
559 }\r
560 //\r
561 // Return the string\r
562 //\r
563 return InputBuffer;\r
564}\r
565\r
566BOOLEAN\r
567FindSectionInStream (\r
568 IN FILE *InputFile,\r
569 IN CHAR8 *Section\r
570 )\r
571/*++\r
572\r
573Routine Description:\r
574\r
575 This function parses a stream file from the beginning to find a section.\r
576 The section string may be anywhere within a line.\r
577 // BUGBUG: This is obsolete once genmake goes away...\r
578\r
579Arguments:\r
580\r
581 InputFile Stream pointer.\r
582 Section Section to search for\r
583\r
584Returns:\r
585\r
586 FALSE if error or EOF\r
587 TRUE if section found\r
588\r
589--*/\r
590{\r
591 CHAR8 InputBuffer[_MAX_PATH];\r
592 CHAR8 *CurrentToken;\r
593\r
594 //\r
595 // Verify input is not NULL\r
596 //\r
597 assert (InputFile);\r
598 assert (Section);\r
599\r
600 //\r
601 // Rewind to beginning of file\r
602 //\r
603 if (fseek (InputFile, 0, SEEK_SET) != 0) {\r
604 return FALSE;\r
605 }\r
606 //\r
607 // Read lines until the section is found\r
608 //\r
609 while (feof (InputFile) == 0) {\r
610 //\r
611 // Read a line\r
612 //\r
613 ReadLineInStream (InputFile, InputBuffer);\r
614\r
615 //\r
616 // Check if the section is found\r
617 //\r
618 CurrentToken = strstr (InputBuffer, Section);\r
619 if (CurrentToken != NULL) {\r
620 return TRUE;\r
621 }\r
622 }\r
623\r
624 return FALSE;\r
625}\r