]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/TianoTools/Common/ParseInf.c
989add7e9c0b0802cdcbf0990a8c9fcfdf9e0ef4
[mirror_edk2.git] / Tools / Source / TianoTools / Common / ParseInf.c
1 /*++
2
3 Copyright (c) 2004, Intel Corporation
4 All rights reserved. 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 #include <stdlib.h>
27
28 #ifndef _MAX_PATH
29 #define _MAX_PATH 500
30 #endif
31
32 CHAR8 *
33 ReadLine (
34 IN MEMORY_FILE *InputFile,
35 IN OUT CHAR8 *InputBuffer,
36 IN UINTN MaxLength
37 )
38 /*++
39
40 Routine Description:
41
42 This function reads a line, stripping any comments.
43 The function reads a string from the input stream argument and stores it in
44 the input string. ReadLine reads characters from the current file position
45 to and including the first newline character, to the end of the stream, or
46 until the number of characters read is equal to MaxLength - 1, whichever
47 comes first. The newline character, if read, is replaced with a \0.
48
49 Arguments:
50
51 InputFile Memory file image.
52 InputBuffer Buffer to read into, must be _MAX_PATH size.
53 MaxLength The maximum size of the input buffer.
54
55 Returns:
56
57 NULL if error or EOF
58 InputBuffer otherwise
59
60 --*/
61 {
62 CHAR8 *CharPtr;
63 CHAR8 *EndOfLine;
64 UINTN CharsToCopy;
65
66 //
67 // Verify input parameters are not null
68 //
69 assert (InputBuffer);
70 assert (InputFile->FileImage);
71 assert (InputFile->Eof);
72 assert (InputFile->CurrentFilePointer);
73
74 //
75 // Check for end of file condition
76 //
77 if (InputFile->CurrentFilePointer >= InputFile->Eof) {
78 return NULL;
79 }
80 //
81 // Find the next newline char
82 //
83 EndOfLine = strchr (InputFile->CurrentFilePointer, '\n');
84
85 //
86 // Determine the number of characters to copy.
87 //
88 if (EndOfLine == 0) {
89 //
90 // If no newline found, copy to the end of the file.
91 //
92 CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
93 } else if (EndOfLine >= InputFile->Eof) {
94 //
95 // If the newline found was beyond the end of file, copy to the eof.
96 //
97 CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer;
98 } else {
99 //
100 // Newline found in the file.
101 //
102 CharsToCopy = EndOfLine - InputFile->CurrentFilePointer;
103 }
104 //
105 // If the end of line is too big for the current buffer, set it to the max
106 // size of the buffer (leaving room for the \0.
107 //
108 if (CharsToCopy > MaxLength - 1) {
109 CharsToCopy = MaxLength - 1;
110 }
111 //
112 // Copy the line.
113 //
114 memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy);
115
116 //
117 // Add the null termination over the 0x0D
118 //
119 InputBuffer[CharsToCopy - 1] = '\0';
120
121 //
122 // Increment the current file pointer (include the 0x0A)
123 //
124 InputFile->CurrentFilePointer += CharsToCopy + 1;
125
126 //
127 // Strip any comments
128 //
129 CharPtr = strstr (InputBuffer, "//");
130 if (CharPtr != 0) {
131 CharPtr[0] = 0;
132 }
133 //
134 // Return the string
135 //
136 return InputBuffer;
137 }
138
139 BOOLEAN
140 FindSection (
141 IN MEMORY_FILE *InputFile,
142 IN CHAR8 *Section
143 )
144 /*++
145
146 Routine Description:
147
148 This function parses a file from the beginning to find a section.
149 The section string may be anywhere within a line.
150
151 Arguments:
152
153 InputFile Memory file image.
154 Section Section to search for
155
156 Returns:
157
158 FALSE if error or EOF
159 TRUE if section found
160
161 --*/
162 {
163 CHAR8 InputBuffer[_MAX_PATH];
164 CHAR8 *CurrentToken;
165
166 //
167 // Verify input is not NULL
168 //
169 assert (InputFile->FileImage);
170 assert (InputFile->Eof);
171 assert (InputFile->CurrentFilePointer);
172 assert (Section);
173
174 //
175 // Rewind to beginning of file
176 //
177 InputFile->CurrentFilePointer = InputFile->FileImage;
178
179 //
180 // Read lines until the section is found
181 //
182 while (InputFile->CurrentFilePointer < InputFile->Eof) {
183 //
184 // Read a line
185 //
186 ReadLine (InputFile, InputBuffer, _MAX_PATH);
187
188 //
189 // Check if the section is found
190 //
191 CurrentToken = strstr (InputBuffer, Section);
192 if (CurrentToken != NULL) {
193 return TRUE;
194 }
195 }
196
197 return FALSE;
198 }
199
200 EFI_STATUS
201 FindToken (
202 IN MEMORY_FILE *InputFile,
203 IN CHAR8 *Section,
204 IN CHAR8 *Token,
205 IN UINTN Instance,
206 OUT CHAR8 *Value
207 )
208 /*++
209
210 Routine Description:
211
212 Finds a token value given the section and token to search for.
213
214 Arguments:
215
216 InputFile Memory file image.
217 Section The section to search for, a string within [].
218 Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file.
219 Instance The instance of the token to search for. Zero is the first instance.
220 Value The string that holds the value following the =. Must be _MAX_PATH in size.
221
222 Returns:
223
224 EFI_SUCCESS Value found.
225 EFI_ABORTED Format error detected in INF file.
226 EFI_INVALID_PARAMETER Input argument was null.
227 EFI_LOAD_ERROR Error reading from the file.
228 EFI_NOT_FOUND Section/Token/Value not found.
229
230 --*/
231 {
232 CHAR8 InputBuffer[_MAX_PATH];
233 CHAR8 *CurrentToken;
234 BOOLEAN ParseError;
235 BOOLEAN ReadError;
236 UINTN Occurrance;
237
238 //
239 // Check input parameters
240 //
241 if (InputFile->FileImage == NULL ||
242 InputFile->Eof == NULL ||
243 InputFile->CurrentFilePointer == NULL ||
244 Section == NULL ||
245 strlen (Section) == 0 ||
246 Token == NULL ||
247 strlen (Token) == 0 ||
248 Value == NULL
249 ) {
250 return EFI_INVALID_PARAMETER;
251 }
252 //
253 // Initialize error codes
254 //
255 ParseError = FALSE;
256 ReadError = FALSE;
257
258 //
259 // Initialize our instance counter for the search token
260 //
261 Occurrance = 0;
262
263 if (FindSection (InputFile, Section)) {
264 //
265 // Found the desired section, find and read the desired token
266 //
267 do {
268 //
269 // Read a line from the file
270 //
271 if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) {
272 //
273 // Error reading from input file
274 //
275 ReadError = TRUE;
276 break;
277 }
278 //
279 // Get the first non-whitespace string
280 //
281 CurrentToken = strtok (InputBuffer, " \t\n");
282 if (CurrentToken == NULL) {
283 //
284 // Whitespace line found (or comment) so continue
285 //
286 CurrentToken = InputBuffer;
287 continue;
288 }
289 //
290 // Make sure we have not reached the end of the current section
291 //
292 if (CurrentToken[0] == '[') {
293 break;
294 }
295 //
296 // Compare the current token with the desired token
297 //
298 if (strcmp (CurrentToken, Token) == 0) {
299 //
300 // Found it
301 //
302 //
303 // Check if it is the correct instance
304 //
305 if (Instance == Occurrance) {
306 //
307 // Copy the contents following the =
308 //
309 CurrentToken = strtok (NULL, "= \t\n");
310 if (CurrentToken == NULL) {
311 //
312 // Nothing found, parsing error
313 //
314 ParseError = TRUE;
315 } else {
316 //
317 // Copy the current token to the output value
318 //
319 strcpy (Value, CurrentToken);
320 return EFI_SUCCESS;
321 }
322 } else {
323 //
324 // Increment the occurrance found
325 //
326 Occurrance++;
327 }
328 }
329 } while (
330 !ParseError &&
331 !ReadError &&
332 InputFile->CurrentFilePointer < InputFile->Eof &&
333 CurrentToken[0] != '[' &&
334 Occurrance <= Instance
335 );
336 }
337 //
338 // Distinguish between read errors and INF file format errors.
339 //
340 if (ReadError) {
341 return EFI_LOAD_ERROR;
342 }
343
344 if (ParseError) {
345 return EFI_ABORTED;
346 }
347
348 return EFI_NOT_FOUND;
349 }
350
351 EFI_STATUS
352 StringToGuid (
353 IN CHAR8 *AsciiGuidBuffer,
354 OUT EFI_GUID *GuidBuffer
355 )
356 /*++
357
358 Routine Description:
359
360 Converts a string to an EFI_GUID. The string must be in the
361 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format.
362
363 Arguments:
364
365 AsciiGuidBuffer - pointer to ascii string
366 GuidBuffer - pointer to destination Guid
367
368 Returns:
369
370 EFI_ABORTED Could not convert the string
371 EFI_SUCCESS The string was successfully converted
372 EFI_INVALID_PARAMETER Input parameter is invalid.
373
374 --*/
375 {
376 INT32 Index;
377 UINTN Data1;
378 UINTN Data2;
379 UINTN Data3;
380 UINTN Data4[8];
381
382 if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) {
383 return EFI_INVALID_PARAMETER;
384 }
385 //
386 // Scan the guid string into the buffer
387 //
388 Index = sscanf (
389 AsciiGuidBuffer,
390 "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx",
391 &Data1,
392 &Data2,
393 &Data3,
394 &Data4[0],
395 &Data4[1],
396 &Data4[2],
397 &Data4[3],
398 &Data4[4],
399 &Data4[5],
400 &Data4[6],
401 &Data4[7]
402 );
403
404 //
405 // Verify the correct number of items were scanned.
406 //
407 if (Index != 11) {
408 printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer);
409 return EFI_ABORTED;
410 }
411 //
412 // Copy the data into our GUID.
413 //
414 GuidBuffer->Data1 = (UINT32) Data1;
415 GuidBuffer->Data2 = (UINT16) Data2;
416 GuidBuffer->Data3 = (UINT16) Data3;
417 GuidBuffer->Data4[0] = (UINT8) Data4[0];
418 GuidBuffer->Data4[1] = (UINT8) Data4[1];
419 GuidBuffer->Data4[2] = (UINT8) Data4[2];
420 GuidBuffer->Data4[3] = (UINT8) Data4[3];
421 GuidBuffer->Data4[4] = (UINT8) Data4[4];
422 GuidBuffer->Data4[5] = (UINT8) Data4[5];
423 GuidBuffer->Data4[6] = (UINT8) Data4[6];
424 GuidBuffer->Data4[7] = (UINT8) Data4[7];
425
426 return EFI_SUCCESS;
427 }
428
429 EFI_STATUS
430 AsciiStringToUint64 (
431 IN CONST CHAR8 *AsciiString,
432 IN BOOLEAN IsHex,
433 OUT UINT64 *ReturnValue
434 )
435 /*++
436
437 Routine Description:
438
439 Converts a null terminated ascii string that represents a number into a
440 UINT64 value. A hex number may be preceeded by a 0x, but may not be
441 succeeded by an h. A number without 0x or 0X is considered to be base 10
442 unless the IsHex input is true.
443
444 Arguments:
445
446 AsciiString The string to convert.
447 IsHex Force the string to be treated as a hex number.
448 ReturnValue The return value.
449
450 Returns:
451
452 EFI_SUCCESS Number successfully converted.
453 EFI_ABORTED Invalid character encountered.
454
455 --*/
456 {
457 UINT8 Index;
458 UINT64 HexNumber;
459 CHAR8 CurrentChar;
460
461 //
462 // Initialize the result
463 //
464 HexNumber = 0;
465
466 //
467 // Add each character to the result
468 //
469 if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) {
470 //
471 // Verify string is a hex number
472 //
473 for (Index = 2; Index < strlen (AsciiString); Index++) {
474 if (isxdigit (AsciiString[Index]) == 0) {
475 return EFI_ABORTED;
476 }
477 }
478 //
479 // Convert the hex string.
480 //
481 for (Index = 2; AsciiString[Index] != '\0'; Index++) {
482 CurrentChar = AsciiString[Index];
483 HexNumber *= 16;
484 if (CurrentChar >= '0' && CurrentChar <= '9') {
485 HexNumber += CurrentChar - '0';
486 } else if (CurrentChar >= 'a' && CurrentChar <= 'f') {
487 HexNumber += CurrentChar - 'a' + 10;
488 } else if (CurrentChar >= 'A' && CurrentChar <= 'F') {
489 HexNumber += CurrentChar - 'A' + 10;
490 } else {
491 //
492 // Unrecognized character
493 //
494 return EFI_ABORTED;
495 }
496 }
497
498 *ReturnValue = HexNumber;
499 } else {
500 //
501 // Verify string is a number
502 //
503 for (Index = 0; Index < strlen (AsciiString); Index++) {
504 if (isdigit (AsciiString[Index]) == 0) {
505 return EFI_ABORTED;
506 }
507 }
508
509 *ReturnValue = atol (AsciiString);
510 }
511
512 return EFI_SUCCESS;
513 };
514
515 CHAR8 *
516 ReadLineInStream (
517 IN FILE *InputFile,
518 IN OUT CHAR8 *InputBuffer
519 )
520 /*++
521
522 Routine Description:
523
524 This function reads a line, stripping any comments.
525 // BUGBUG: This is obsolete once genmake goes away...
526
527 Arguments:
528
529 InputFile Stream pointer.
530 InputBuffer Buffer to read into, must be _MAX_PATH size.
531
532 Returns:
533
534 NULL if error or EOF
535 InputBuffer otherwise
536
537 --*/
538 {
539 CHAR8 *CharPtr;
540
541 //
542 // Verify input parameters are not null
543 //
544 assert (InputFile);
545 assert (InputBuffer);
546
547 //
548 // Read a line
549 //
550 if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) {
551 return NULL;
552 }
553 //
554 // Strip any comments
555 //
556 CharPtr = strstr (InputBuffer, "//");
557 if (CharPtr != 0) {
558 CharPtr[0] = 0;
559 }
560
561 CharPtr = strstr (InputBuffer, "#");
562 if (CharPtr != 0) {
563 CharPtr[0] = 0;
564 }
565 //
566 // Return the string
567 //
568 return InputBuffer;
569 }
570
571 BOOLEAN
572 FindSectionInStream (
573 IN FILE *InputFile,
574 IN CHAR8 *Section
575 )
576 /*++
577
578 Routine Description:
579
580 This function parses a stream file from the beginning to find a section.
581 The section string may be anywhere within a line.
582 // BUGBUG: This is obsolete once genmake goes away...
583
584 Arguments:
585
586 InputFile Stream pointer.
587 Section Section to search for
588
589 Returns:
590
591 FALSE if error or EOF
592 TRUE if section found
593
594 --*/
595 {
596 CHAR8 InputBuffer[_MAX_PATH];
597 CHAR8 *CurrentToken;
598
599 //
600 // Verify input is not NULL
601 //
602 assert (InputFile);
603 assert (Section);
604
605 //
606 // Rewind to beginning of file
607 //
608 if (fseek (InputFile, 0, SEEK_SET) != 0) {
609 return FALSE;
610 }
611 //
612 // Read lines until the section is found
613 //
614 while (feof (InputFile) == 0) {
615 //
616 // Read a line
617 //
618 ReadLineInStream (InputFile, InputBuffer);
619
620 //
621 // Check if the section is found
622 //
623 CurrentToken = strstr (InputBuffer, Section);
624 if (CurrentToken != NULL) {
625 return TRUE;
626 }
627 }
628
629 return FALSE;
630 }