]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidChk.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / GuidChk / GuidChk.c
1 /*++
2
3 Copyright (c) 2004 - 2007, 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 GuidChk.c
15
16 Abstract:
17
18 Parse files in a directory and subdirectories to find all guid definitions.
19 Then check them against each other to make sure there are no duplicates.
20
21 --*/
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27
28 #include "CommonUtils.h"
29 #include "FileSearch.h"
30 #include "UtilsMsgs.h"
31
32 #define MAX_LINE_LEN 1024 // we concatenate lines sometimes
33 // Define a structure that correlates filename extensions to an enumerated
34 // type.
35 //
36 #ifdef MAX_PATH
37 #undef MAX_PATH
38 #define MAX_PATH 1024
39 #endif
40
41 typedef struct {
42 INT8 *Extension;
43 INT8 ExtensionCode;
44 } FILE_TYPE_TABLE_ENTRY;
45
46 #define FILE_EXTENSION_UNKNOWN 0
47 #define FILE_EXTENSION_C 1
48 #define FILE_EXTENSION_H 2
49 #define FILE_EXTENSION_IA32_ASM 3
50 #define FILE_EXTENSION_IA32_INC 4
51 #define FILE_EXTENSION_IA64_ASM 5
52 #define FILE_EXTENSION_IA64_INC 6
53 #define FILE_EXTENSION_PKG 7
54 #define FILE_EXTENSION_INF 8
55
56 FILE_TYPE_TABLE_ENTRY FileTypeTable[] = {
57 ".c",
58 FILE_EXTENSION_C,
59 ".h",
60 FILE_EXTENSION_H,
61 ".inc",
62 FILE_EXTENSION_IA32_INC,
63 ".asm",
64 FILE_EXTENSION_IA32_ASM,
65 ".s",
66 FILE_EXTENSION_IA64_ASM,
67 ".pkg",
68 FILE_EXTENSION_PKG,
69 ".inf",
70 FILE_EXTENSION_INF,
71 ".i",
72 FILE_EXTENSION_IA64_INC,
73 NULL,
74 0
75 };
76
77 typedef struct EFI_GUID {
78 UINT32 Data1;
79 UINT16 Data2;
80 UINT16 Data3;
81 UINT8 Data4[8];
82 } EFI_GUID;
83
84 typedef struct {
85 INT8 Data[8];
86 INT8 DataLen;
87 } EFI_SIGNATURE;
88
89 typedef struct _GUID_RECORD {
90 struct _GUID_RECORD *Next;
91 BOOLEAN Reported;
92 INT8 *FileName;
93 INT8 *SymName;
94 EFI_GUID Guid;
95 } GUID_RECORD;
96
97 typedef struct _SIGNATURE_RECORD {
98 struct _SIGNATURE_RECORD *Next;
99 BOOLEAN Reported;
100 INT8 *FileName;
101 EFI_SIGNATURE Signature;
102 } SIGNATURE_RECORD;
103
104 //
105 // Utility options
106 //
107 typedef struct {
108 INT8 DatabaseOutputFileName[MAX_PATH]; // with -b option
109 STRING_LIST *ExcludeDirs; // list of directory names not to process
110 STRING_LIST *ExcludeSubDirs; // list of directory names to not process subdirectories (build)
111 STRING_LIST *ExcludeFiles; // list of files to exclude (make.inf)
112 STRING_LIST *ExcludeExtensions; // list of filename extensions to exclude (.inf, .pkg)
113 BOOLEAN Verbose;
114 BOOLEAN PrintFound;
115 BOOLEAN CheckGuids;
116 BOOLEAN CheckSignatures;
117 BOOLEAN GuidXReference;
118 } OPTIONS;
119
120 static
121 STATUS
122 ProcessArgs (
123 int Argc,
124 char *Argv[]
125 );
126
127 static
128 VOID
129 Usage (
130 VOID
131 );
132
133 static
134 STATUS
135 ProcessDirectory (
136 INT8 *Path,
137 INT8 *DirectoryName
138 );
139
140 static
141 STATUS
142 ProcessFile (
143 INT8 *DirectoryName,
144 INT8 *FileName
145 );
146
147 static
148 UINT32
149 GetFileExtension (
150 INT8 *FileName
151 );
152
153 static
154 UINT32
155 SkipWhiteSpace (
156 INT8 *Str
157 );
158
159 static
160 UINT32
161 ValidSymbolName (
162 INT8 *Name
163 );
164
165 static
166 STATUS
167 ProcessCFileGuids (
168 INT8 *FileName
169 );
170
171 static
172 STATUS
173 AddSignature (
174 INT8 *FileName,
175 INT8 *StrDef,
176 UINT32 SigSize
177 );
178
179 static
180 STATUS
181 ProcessCFileSigs (
182 INT8 *FileName
183 );
184
185 static
186 STATUS
187 ProcessINFFileGuids (
188 INT8 *FileName
189 );
190
191 static
192 STATUS
193 ProcessPkgFileGuids (
194 INT8 *FileName
195 );
196
197 static
198 STATUS
199 ProcessIA32FileGuids (
200 INT8 *FileName
201 );
202
203 static
204 STATUS
205 ProcessIA64FileGuids (
206 INT8 *FileName
207 );
208
209 static
210 BOOLEAN
211 IsIA64GuidLine (
212 INT8 *Line,
213 UINT32 *GuidHigh,
214 UINT32 *GuidLow,
215 BOOLEAN *Low,
216 INT8 *SymName
217 );
218
219 static
220 STATUS
221 AddGuid11 (
222 INT8 *FileName,
223 UINT32 *Data,
224 INT8 *SymName
225 );
226
227 static
228 STATUS
229 AddPkgGuid (
230 INT8 *FileName,
231 UINT32 *Data,
232 UINT64 *Data64
233 );
234
235 static
236 STATUS
237 AddGuid16 (
238 INT8 *FileName,
239 UINT32 *Data
240 );
241
242 static
243 STATUS
244 AddGuid64x2 (
245 INT8 *FileName,
246 UINT32 DataHH, // Upper 32-bits of upper 64 bits of guid
247 UINT32 DataHL, // Lower 32-bits of upper 64 bits
248 UINT32 DataLH,
249 UINT32 DataLL,
250 INT8 *SymName
251 );
252
253 static
254 VOID
255 FreeGuids (
256 VOID
257 );
258
259 static
260 VOID
261 FreeSigs (
262 VOID
263 );
264
265 static
266 STATUS
267 CheckDuplicates (
268 VOID
269 );
270
271 //
272 // static
273 // VOID
274 // ReportGuid (
275 // INT8 *FileName,
276 // GUID_RECORD *FileRecord
277 // );
278 //
279 static
280 VOID
281 FreeOptions (
282 VOID
283 );
284
285 static
286 BOOLEAN
287 CheckGuidData (
288 UINT32 *GuidData,
289 UINT32 DataCount
290 );
291
292 static
293 VOID
294 ConcatenateLines (
295 FILE *Fptr,
296 INT8 *Line,
297 UINT32 Len
298 );
299
300 /**************************** GLOBALS ****************************************/
301 static GUID_RECORD *gGuidList = NULL;
302 static SIGNATURE_RECORD *gSignatureList = NULL;
303 static OPTIONS gOptions;
304
305 /*****************************************************************************/
306 int
307 main (
308 int Argc,
309 char *Argv[]
310 )
311 {
312 INT8 *Cwd;
313 STATUS Status;
314
315 SetUtilityName ("GuidChk");
316 //
317 // Get the current working directory and then process the command line
318 // arguments.
319 //
320 Cwd = _getcwd (NULL, 0);
321 Status = ProcessArgs (Argc, Argv);
322 if (Status != STATUS_SUCCESS) {
323 return Status;
324 }
325
326 if (gOptions.CheckGuids || gOptions.CheckSignatures) {
327 Status = ProcessDirectory (Cwd, NULL);
328 if (Status == STATUS_SUCCESS) {
329 //
330 // Check for duplicates
331 //
332 Status = CheckDuplicates ();
333 }
334 }
335
336 if (gOptions.DatabaseOutputFileName[0] != 0) {
337 CreateGuidList (gOptions.DatabaseOutputFileName);
338 }
339 //
340 // Free up the memory
341 //
342 free (Cwd);
343 FreeGuids ();
344 FreeSigs ();
345 FreeOptions ();
346 return GetUtilityStatus ();
347 }
348
349 static
350 STATUS
351 ProcessArgs (
352 int Argc,
353 char *Argv[]
354 )
355 {
356 STRING_LIST *StrList;
357
358 memset ((char *) &gOptions, 0, sizeof (gOptions));
359 //
360 // skip over program name
361 //
362 Argc--;
363 Argv++;
364
365 if (Argc == 0) {
366 Usage ();
367 return STATUS_ERROR;
368 }
369
370 while (Argc > 0) {
371 //
372 // Look for options
373 //
374 if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {
375 switch (Argv[0][1]) {
376 //
377 // Help option
378 //
379 case 'h':
380 case 'H':
381 case '?':
382 Usage ();
383 return STATUS_ERROR;
384 break;
385
386 //
387 // Check guids option
388 //
389 case 'g':
390 case 'G':
391 gOptions.CheckGuids = TRUE;
392 break;
393
394 //
395 // Check signatures option
396 //
397 case 's':
398 case 'S':
399 gOptions.CheckSignatures = TRUE;
400 break;
401
402 //
403 // Print guids found option
404 //
405 case 'p':
406 case 'P':
407 gOptions.PrintFound = TRUE;
408 break;
409
410 //
411 // Exclude files option
412 //
413 case 'f':
414 case 'F':
415 //
416 // Check for another arg
417 //
418 if (Argc < 2) {
419 Error (NULL, 0, 0, Argv[0], "missing argument with option");
420 Usage ();
421 return STATUS_ERROR;
422 }
423
424 StrList = malloc (sizeof (STRING_LIST));
425 if (StrList == NULL) {
426 Error (NULL, 0, 0, "memory allocation failure", NULL);
427 return STATUS_ERROR;
428 }
429
430 memset ((char *) StrList, 0, sizeof (STRING_LIST));
431 StrList->Str = Argv[1];
432 StrList->Next = gOptions.ExcludeFiles;
433 gOptions.ExcludeFiles = StrList;
434 Argc--;
435 Argv++;
436 break;
437
438 //
439 // Exclude directories option
440 //
441 case 'd':
442 case 'D':
443 //
444 // Check for another arg
445 //
446 if (Argc < 2) {
447 Error (NULL, 0, 0, Argv[0], "missing argument with option");
448 Usage ();
449 return STATUS_ERROR;
450 }
451
452 StrList = malloc (sizeof (STRING_LIST));
453 if (StrList == NULL) {
454 Error (NULL, 0, 0, "memory allocation failure", NULL);
455 return STATUS_ERROR;
456 }
457
458 memset ((char *) StrList, 0, sizeof (STRING_LIST));
459 StrList->Str = Argv[1];
460 StrList->Next = gOptions.ExcludeDirs;
461 gOptions.ExcludeDirs = StrList;
462 Argc--;
463 Argv++;
464 break;
465
466 //
467 // -u exclude all subdirectories of a given directory option
468 //
469 case 'u':
470 case 'U':
471 //
472 // Check for another arg
473 //
474 if (Argc < 2) {
475 Error (NULL, 0, 0, Argv[0], "missing argument with option");
476 Usage ();
477 return STATUS_ERROR;
478 }
479
480 StrList = malloc (sizeof (STRING_LIST));
481 if (StrList == NULL) {
482 Error (NULL, 0, 0, "memory allocation failure", NULL);
483 return STATUS_ERROR;
484 }
485
486 memset ((char *) StrList, 0, sizeof (STRING_LIST));
487 StrList->Str = Argv[1];
488 StrList->Next = gOptions.ExcludeSubDirs;
489 gOptions.ExcludeSubDirs = StrList;
490 Argc--;
491 Argv++;
492 break;
493
494 //
495 // -e exclude by filename extension option
496 //
497 case 'e':
498 case 'E':
499 //
500 // Check for another arg
501 //
502 if (Argc < 2) {
503 Error (NULL, 0, 0, Argv[0], "missing argument with option");
504 Usage ();
505 return STATUS_ERROR;
506 }
507
508 StrList = malloc (sizeof (STRING_LIST));
509 if (StrList == NULL) {
510 Error (NULL, 0, 0, "memory allocation failure", NULL);
511 return STATUS_ERROR;
512 }
513
514 memset ((char *) StrList, 0, sizeof (STRING_LIST));
515 //
516 // Let them put a * in front of the filename extension
517 //
518 StrList->Str = Argv[1];
519 if (StrList->Str[0] == '*') {
520 StrList->Str++;
521 }
522
523 StrList->Next = gOptions.ExcludeExtensions;
524 gOptions.ExcludeExtensions = StrList;
525 Argc--;
526 Argv++;
527 break;
528
529 //
530 // Print guid with matching symbol name for guid definitions found
531 //
532 case 'x':
533 case 'X':
534 gOptions.GuidXReference = TRUE;
535 break;
536
537 //
538 // -b Print the internal database list to a file
539 //
540 case 'b':
541 case 'B':
542 //
543 // Check for one more arg
544 //
545 if (Argc < 2) {
546 Error (NULL, 0, 0, Argv[0], "must specify file name with option");
547 Usage ();
548 return STATUS_ERROR;
549 }
550
551 strcpy (gOptions.DatabaseOutputFileName, Argv[1]);
552 Argc--;
553 Argv++;
554 break;
555
556 default:
557 Error (NULL, 0, 0, Argv[0], "invalid option");
558 Usage ();
559 return STATUS_ERROR;
560 }
561 } else {
562 break;
563 }
564 //
565 // Next arg
566 //
567 Argc--;
568 Argv++;
569 }
570
571 if (Argc > 0) {
572 Error (NULL, 0, 0, Argv[0], "invalid argument");
573 Usage ();
574 return STATUS_ERROR;
575 }
576 //
577 // Have to check signatures, GUIDs, or dump the GUID database.
578 //
579 if ((!gOptions.CheckGuids) && (!gOptions.CheckSignatures) && (gOptions.DatabaseOutputFileName[0] == 0)) {
580 Error (NULL, 0, 0, "nothing to do", "must specify -g, -s, and/or -b");
581 Usage ();
582 return STATUS_ERROR;
583 }
584
585 return STATUS_SUCCESS;
586 }
587 //
588 // Print usage instructions
589 //
590 static
591 VOID
592 Usage (
593 VOID
594 )
595 {
596 int Index;
597 char *Str[] = {
598 "GuidChk - scan files for duplicate GUID or signature definitions",
599 "",
600 "Usage: GuidChk {options}\n",
601 " Options: ",
602 " -d dirname exclude searching of a directory",
603 " -f filename exclude searching of a file",
604 " -e extension exclude searching of files by extension",
605 " -p print all GUIDS found",
606 " -g check for duplicate guids",
607 " -s check for duplicate signatures",
608 " -x print guid+defined symbol name",
609 " -b outfile write internal GUID+basename list to outfile",
610 " -u dirname exclude searching all subdirectories of a directory",
611 " -h -? print this help text",
612 " ",
613 " Example: GuidChk -g -u build -d fv -f make.inf -e .pkg",
614 "",
615 NULL
616 };
617 for (Index = 0; Str[Index] != NULL; Index++) {
618 fprintf (stdout, "%s\n", Str[Index]);
619 }
620 }
621 //
622 // Process an entire directory by name
623 //
624 static
625 STATUS
626 ProcessDirectory (
627 INT8 *Path,
628 INT8 *DirectoryName
629 )
630 {
631 FILE_SEARCH_DATA FSData;
632 char *FileMask;
633 BOOLEAN Done;
634 UINT32 Len;
635 BOOLEAN NoSubdirs;
636 STRING_LIST *SLPtr;
637
638 //
639 // Root directory may be null
640 //
641 if (DirectoryName != NULL) {
642 //
643 // printf ("Processing directory: %s\n", DirectoryName);
644 //
645 }
646 //
647 // Initialize our file searching
648 //
649 FileSearchInit (&FSData);
650
651 //
652 // Exclude some directories, files, and extensions
653 //
654 FileSearchExcludeDirs (&FSData, gOptions.ExcludeDirs);
655 FileSearchExcludeExtensions (&FSData, gOptions.ExcludeExtensions);
656 FileSearchExcludeFiles (&FSData, gOptions.ExcludeFiles);
657 //
658 // See if this directory is in the list of directories that they
659 // don't want to process subdirectories of
660 //
661 NoSubdirs = FALSE;
662 if (DirectoryName != NULL) {
663 for (SLPtr = gOptions.ExcludeSubDirs; SLPtr != NULL; SLPtr = SLPtr->Next) {
664 if (_stricmp (SLPtr->Str, DirectoryName) == 0) {
665 //
666 // printf ("not processing subdirectories of %s\n", DirectoryName);
667 //
668 NoSubdirs = TRUE;
669 break;
670 }
671 }
672 }
673 //
674 // Create a filemask of files to search for. We'll append "\*.*" on the
675 // end, so allocate some extra bytes.
676 //
677 Len = strlen (Path) + 10;
678 if (DirectoryName != NULL) {
679 Len += strlen (DirectoryName);
680 }
681
682 FileMask = malloc (Len);
683 if (FileMask == NULL) {
684 Error (NULL, 0, 0, "memory allocation failure", NULL);
685 return STATUS_ERROR;
686 }
687 //
688 // Now put it all together
689 //
690 strcpy (FileMask, Path);
691 if ((DirectoryName != NULL) && (strlen (DirectoryName) > 0)) {
692 strcat (FileMask, "\\");
693 strcat (FileMask, DirectoryName);
694 }
695
696 strcat (FileMask, "\\*.*");
697
698 //
699 // Start file searching for files and directories
700 //
701 if (FileSearchStart (&FSData, FileMask, FILE_SEARCH_FILE | FILE_SEARCH_DIR) == STATUS_SUCCESS) {
702 Done = FALSE;
703 } else {
704 Done = TRUE;
705 }
706
707 //
708 // Now hack the "\*.*" off the end of the filemask so we can use it to pass
709 // the full directory path on recursive calls to process directories.
710 //
711 FileMask[strlen (FileMask) - 4] = 0;
712
713 //
714 // Loop until no more files
715 //
716 while (!Done) {
717 //
718 // printf ("Found %s...", FSData.FileName);
719 //
720 if (FSData.FileFlags & FILE_SEARCH_DIR) {
721 //
722 // printf ("directory\n");
723 //
724 if (!NoSubdirs) {
725 ProcessDirectory (FileMask, FSData.FileName);
726 }
727 } else if (FSData.FileFlags & FILE_SEARCH_FILE) {
728 //
729 // printf ("file\n");
730 //
731 ProcessFile (FileMask, FSData.FileName);
732 } else {
733 //
734 // printf ("unknown\n");
735 //
736 }
737
738 if (FileSearchFindNext (&FSData) != STATUS_SUCCESS) {
739 Done = TRUE;
740 }
741 }
742 //
743 // Free up allocated memory
744 //
745 free (FileMask);
746
747 //
748 // Free up our file searching
749 //
750 FileSearchDestroy (&FSData);
751
752 return STATUS_SUCCESS;
753 }
754 //
755 // Process a single file.
756 //
757 static
758 STATUS
759 ProcessFile (
760 INT8 *DirectoryName,
761 INT8 *FileName
762 )
763 {
764 STATUS Status;
765 UINT32 FileExtension;
766 INT8 FullFileName[MAX_PATH];
767
768 Status = STATUS_SUCCESS;
769
770 sprintf (FullFileName, "%s\\%s", DirectoryName, FileName);
771 //
772 // printf ("Found file: %s\n", FullFileName);
773 //
774 FileExtension = GetFileExtension (FileName);
775
776 //
777 // Process these for GUID checks
778 //
779 if (gOptions.CheckGuids) {
780 switch (FileExtension) {
781 case FILE_EXTENSION_C:
782 case FILE_EXTENSION_H:
783 Status = ProcessCFileGuids (FullFileName);
784 break;
785
786 case FILE_EXTENSION_PKG:
787 Status = ProcessPkgFileGuids (FullFileName);
788 break;
789
790 case FILE_EXTENSION_IA32_INC:
791 case FILE_EXTENSION_IA32_ASM:
792 Status = ProcessIA32FileGuids (FullFileName);
793 break;
794
795 case FILE_EXTENSION_INF:
796 Status = ProcessINFFileGuids (FullFileName);
797 break;
798
799 case FILE_EXTENSION_IA64_INC:
800 case FILE_EXTENSION_IA64_ASM:
801 Status = ProcessIA64FileGuids (FullFileName);
802 break;
803
804 default:
805 //
806 // No errors anyway
807 //
808 Status = STATUS_SUCCESS;
809 break;
810 }
811 }
812
813 if (gOptions.CheckSignatures) {
814 switch (FileExtension) {
815 case FILE_EXTENSION_C:
816 case FILE_EXTENSION_H:
817 Status = ProcessCFileSigs (FullFileName);
818 break;
819
820 default:
821 //
822 // No errors anyway
823 //
824 Status = STATUS_SUCCESS;
825 break;
826 }
827 }
828
829 return Status;
830 }
831 //
832 // Return a code indicating the file name extension.
833 //
834 static
835 UINT32
836 GetFileExtension (
837 INT8 *FileName
838 )
839 {
840 INT8 *Extension;
841 int Index;
842
843 //
844 // Look back for a filename extension
845 //
846 for (Extension = FileName + strlen (FileName) - 1; Extension >= FileName; Extension--) {
847 if (*Extension == '.') {
848 for (Index = 0; FileTypeTable[Index].Extension != NULL; Index++) {
849 if (_stricmp (FileTypeTable[Index].Extension, Extension) == 0) {
850 return FileTypeTable[Index].ExtensionCode;
851 }
852 }
853 }
854 }
855
856 return FILE_TYPE_UNKNOWN;
857 }
858 //
859 // Process a .pkg file.
860 //
861 // Look for FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7
862 //
863 static
864 STATUS
865 ProcessPkgFileGuids (
866 INT8 *FileName
867 )
868 {
869 FILE *Fptr;
870 INT8 Line[MAX_LINE_LEN * 2];
871 INT8 *Cptr;
872 INT8 *Cptr2;
873 UINT32 GuidScan[11];
874 UINT64 Guid64;
875
876 if ((Fptr = fopen (FileName, "r")) == NULL) {
877 Error (NULL, 0, 0, FileName, "could not open input file for reading");
878 return STATUS_ERROR;
879 }
880 //
881 // Read lines from the file until done
882 //
883 while (fgets (Line, sizeof (Line), Fptr) != NULL) {
884 Cptr = Line;
885 Cptr += SkipWhiteSpace (Line);
886 if (strncmp (Cptr, "FFS_FILEGUID", 12) == 0) {
887 Cptr += 12;
888 Cptr += SkipWhiteSpace (Cptr);
889 if (*Cptr == '=') {
890 Cptr++;
891 Cptr += SkipWhiteSpace (Cptr + 1);
892 //
893 // Blank out dashes on the line.
894 //
895 for (Cptr2 = Cptr; *Cptr2; Cptr2++) {
896 if (*Cptr2 == '-') {
897 *Cptr2 = ' ';
898 }
899 }
900
901 if (sscanf (
902 Cptr,
903 "%X %X %X %X %I64X",
904 &GuidScan[0],
905 &GuidScan[1],
906 &GuidScan[2],
907 &GuidScan[3],
908 &Guid64
909 ) == 5) {
910 AddPkgGuid (FileName, GuidScan, &Guid64);
911 } else {
912 DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");
913 }
914 }
915 }
916 }
917
918 fclose (Fptr);
919 return STATUS_SUCCESS;
920 }
921 //
922 // Process an IA32 assembly file.
923 //
924 // Look for:
925 // FIND_FD_GUID_VAL equ 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h
926 // PEI_GUID_FileNameGuid_Gmch815 equ 081818181h, 08181h, 08181h, 081h, 081h, 081h, 081h, 081h, 081h, 081h, 081h
927 //
928 static
929 STATUS
930 ProcessIA32FileGuids (
931 INT8 *FileName
932 )
933 {
934 FILE *Fptr;
935 INT8 Line[MAX_LINE_LEN];
936 INT8 *Cptr;
937 INT8 CSave;
938 INT8 *CSavePtr;
939 UINT32 Len;
940 UINT32 GuidData[16];
941 UINT32 Index;
942
943 if ((Fptr = fopen (FileName, "r")) == NULL) {
944 Error (NULL, 0, 0, FileName, "could not open input file for reading");
945 return STATUS_ERROR;
946 }
947 //
948 // Read lines from the file until done
949 //
950 while (fgets (Line, sizeof (Line), Fptr) != NULL) {
951 Cptr = Line;
952 Cptr += SkipWhiteSpace (Line);
953 //
954 // Look for xxxGUIDyyy equ 01h, 02h, 03h, ...
955 //
956 Len = ValidSymbolName (Cptr);
957 if (Len) {
958 //
959 // Terminate the line after the symbol name, then look for "guid" in
960 // the name.
961 //
962 CSavePtr = Cptr + Len;
963 CSave = *CSavePtr;
964 *CSavePtr = 0;
965 while (*Cptr) {
966 if (_strnicmp (Cptr, "guid", 4) == 0) {
967 break;
968 }
969
970 Cptr++;
971 }
972 //
973 // If we found the string "guid", continue
974 //
975 if (*Cptr) {
976 //
977 // Restore the character on the line where we null-terminated the symbol
978 //
979 *CSavePtr = CSave;
980 Cptr = CSavePtr;
981 Len = SkipWhiteSpace (Cptr);
982 //
983 // Had to be some white space
984 //
985 if (Len) {
986 Cptr += Len;
987 //
988 // now look for "equ"
989 //
990 if (_strnicmp (Cptr, "equ", 3) == 0) {
991 Cptr += 3;
992 Cptr += SkipWhiteSpace (Cptr);
993 //
994 // Now scan all the data
995 //
996 for (Index = 0; Index < 16; Index++) {
997 if (sscanf (Cptr, "%X", &GuidData[Index]) != 1) {
998 break;
999 }
1000 //
1001 // Skip to next
1002 //
1003 while (isxdigit (*Cptr)) {
1004 Cptr++;
1005 }
1006
1007 if ((*Cptr != 'h') && (*Cptr != 'H')) {
1008 break;
1009 } else {
1010 Cptr++;
1011 while (*Cptr && (isspace (*Cptr) || (*Cptr == ','))) {
1012 Cptr++;
1013 }
1014 }
1015 }
1016 //
1017 // Now see which form we had
1018 //
1019 if (Index == 16) {
1020 AddGuid16 (FileName, GuidData);
1021 } else if (Index == 11) {
1022 AddGuid11 (FileName, GuidData, NULL);
1023 }
1024 }
1025 }
1026 }
1027 }
1028 }
1029
1030 fclose (Fptr);
1031 return STATUS_SUCCESS;
1032 }
1033 //
1034 // Found and parsed an IA32 assembly code guid. Save the 16 bytes off in the list
1035 // of guids.
1036 //
1037 static
1038 STATUS
1039 AddGuid16 (
1040 INT8 *FileName,
1041 UINT32 *Data
1042 )
1043 {
1044 GUID_RECORD *NewRec;
1045 int Index;
1046
1047 //
1048 // Sanity check the data
1049 //
1050 if (!CheckGuidData (Data, 16)) {
1051 return STATUS_ERROR;
1052 }
1053 //
1054 // Allocate memory for a new guid structure
1055 //
1056 NewRec = malloc (sizeof (GUID_RECORD));
1057 if (NewRec == NULL) {
1058 Error (NULL, 0, 0, "memory allocation failure", NULL);
1059 return STATUS_ERROR;
1060 }
1061
1062 memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
1063 NewRec->FileName = malloc (strlen (FileName) + 1);
1064 if (NewRec->FileName == NULL) {
1065 free (NewRec);
1066 Error (NULL, 0, 0, "memory allocation failure", NULL);
1067 return STATUS_ERROR;
1068 }
1069
1070 strcpy (NewRec->FileName, FileName);
1071 NewRec->Guid.Data1 = (UINT32) (Data[0] | (Data[1] << 8) | (Data[2] << 16) | (Data[3] << 24));
1072 NewRec->Guid.Data2 = (UINT16) (Data[4] | (Data[5] << 8));
1073 NewRec->Guid.Data3 = (UINT16) (Data[6] | (Data[7] << 8));
1074 for (Index = 0; Index < 8; Index++) {
1075 NewRec->Guid.Data4[Index] = (UINT8) Data[Index + 8];
1076 }
1077 //
1078 // Add it to the list
1079 //
1080 NewRec->Next = gGuidList;
1081 gGuidList = NewRec;
1082
1083 //
1084 // Report it
1085 // ReportGuid (FileName, NewRec);
1086 //
1087 return STATUS_SUCCESS;
1088 }
1089 //
1090 // Add a GUID defined as GuidLow: 0x1122334455667788
1091 // GuidHi: 0x99AABBCCDDEEFF00
1092 //
1093 // These are equivalent:
1094 // { 0x11223344, 0x5566, 0x7788, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 }
1095 // and:
1096 // Low: 00FFEEDDCCBBAA99
1097 // Hi: 7788556611223344
1098 //
1099 static
1100 STATUS
1101 AddGuid64x2 (
1102 INT8 *FileName,
1103 UINT32 DataHH, // Upper 32-bits of upper 64 bits of guid
1104 UINT32 DataHL, // Lower 32-bits of upper 64 bits
1105 UINT32 DataLH,
1106 UINT32 DataLL,
1107 INT8 *SymName
1108 )
1109 {
1110 GUID_RECORD *NewRec;
1111 int Index;
1112
1113 //
1114 // Allocate memory for a new guid structure
1115 //
1116 NewRec = malloc (sizeof (GUID_RECORD));
1117 if (NewRec == NULL) {
1118 Error (NULL, 0, 0, "memory allocation failure", NULL);
1119 return STATUS_ERROR;
1120 }
1121
1122 memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
1123 NewRec->FileName = malloc (strlen (FileName) + 1);
1124 if (NewRec->FileName == NULL) {
1125 free (NewRec);
1126 Error (NULL, 0, 0, "memory allocation failure", NULL);
1127 return STATUS_ERROR;
1128 }
1129
1130 strcpy (NewRec->FileName, FileName);
1131 NewRec->Guid.Data1 = DataHL;
1132 NewRec->Guid.Data2 = (UINT16) DataHH;
1133 NewRec->Guid.Data3 = (UINT16) (DataHH >> 16);
1134 for (Index = 0; Index < 4; Index++) {
1135 NewRec->Guid.Data4[Index] = (UINT8) DataLL;
1136 DataLL >>= 8;
1137 }
1138
1139 for (Index = 0; Index < 4; Index++) {
1140 NewRec->Guid.Data4[Index + 4] = (UINT8) DataLH;
1141 DataLH >>= 8;
1142 }
1143
1144 if (SymName != NULL) {
1145 NewRec->SymName = malloc (strlen (SymName) + 1);
1146 if (NewRec->SymName == NULL) {
1147 free (NewRec);
1148 Error (NULL, 0, 0, "memory allocation failure", NULL);
1149 return STATUS_ERROR;
1150 }
1151 strcpy (NewRec->SymName, SymName);
1152 }
1153
1154 //
1155 // Add it to the list
1156 //
1157 NewRec->Next = gGuidList;
1158 gGuidList = NewRec;
1159
1160 //
1161 // Report it
1162 // ReportGuid (FileName, NewRec);
1163 //
1164 return STATUS_SUCCESS;
1165 }
1166 //
1167 // Process INF files. Look for:
1168 // FILE_GUID = 240612B6-A063-11d4-9A3A-0090273FC14D
1169 //
1170 static
1171 STATUS
1172 ProcessINFFileGuids (
1173 INT8 *FileName
1174 )
1175 {
1176 FILE *Fptr;
1177 INT8 Line[MAX_LINE_LEN * 2];
1178 INT8 *Cptr;
1179 INT8 *Cptr2;
1180 UINT32 GuidScan[11];
1181 UINT64 Guid64;
1182
1183 if ((Fptr = fopen (FileName, "r")) == NULL) {
1184 Error (NULL, 0, 0, FileName, "could not open input file for reading");
1185 return STATUS_ERROR;
1186 }
1187 //
1188 // Read lines from the file until done
1189 //
1190 while (fgets (Line, sizeof (Line), Fptr) != NULL) {
1191 Cptr = Line;
1192 Cptr += SkipWhiteSpace (Line);
1193 if (strncmp (Cptr, "FILE_GUID", 9) == 0) {
1194 Cptr += 9;
1195 Cptr += SkipWhiteSpace (Cptr);
1196 if (*Cptr == '=') {
1197 Cptr++;
1198 Cptr += SkipWhiteSpace (Cptr + 1);
1199 //
1200 // Blank out dashes on the line.
1201 //
1202 for (Cptr2 = Cptr; *Cptr2; Cptr2++) {
1203 if (*Cptr2 == '-') {
1204 *Cptr2 = ' ';
1205 }
1206 }
1207
1208 if (sscanf (
1209 Cptr,
1210 "%X %X %X %X %I64X",
1211 &GuidScan[0],
1212 &GuidScan[1],
1213 &GuidScan[2],
1214 &GuidScan[3],
1215 &Guid64
1216 ) == 5) {
1217 AddPkgGuid (FileName, GuidScan, &Guid64);
1218 } else {
1219 DebugMsg (NULL, 0, 0, FileName, "GUID scan failed");
1220 }
1221 }
1222 }
1223 }
1224
1225 fclose (Fptr);
1226 return STATUS_SUCCESS;
1227 }
1228 //
1229 // Parse ('g','m','a','p','a','b','c','d')
1230 //
1231 static
1232 STATUS
1233 AddSignature (
1234 INT8 *FileName,
1235 INT8 *StrDef,
1236 UINT32 SigSize
1237 )
1238 {
1239 SIGNATURE_RECORD *NewRec;
1240 INT8 *Cptr;
1241 UINT32 Index;
1242 BOOLEAN Fail;
1243
1244 //
1245 // Allocate memory for the new record
1246 //
1247 Fail = FALSE;
1248 NewRec = malloc (sizeof (SIGNATURE_RECORD));
1249
1250 if (NewRec == NULL) {
1251 Error (NULL, 0, 0, "memory allocation failure", NULL);
1252 return STATUS_ERROR;
1253 }
1254 memset ((char *) NewRec, 0, sizeof (SIGNATURE_RECORD));
1255
1256 //
1257 // Allocate memory to save the file name
1258 //
1259 NewRec->FileName = malloc (strlen (FileName) + 1);
1260 if (NewRec->FileName == NULL) {
1261 Error (NULL, 0, 0, "memory allocation failure", NULL);
1262 free (NewRec);
1263 return STATUS_ERROR;
1264 }
1265 //
1266 // Fill in the fields
1267 //
1268 strcpy (NewRec->FileName, FileName);
1269 NewRec->Signature.DataLen = (UINT8) SigSize;
1270 //
1271 // Skip to open parenthesis
1272 //
1273 Cptr = StrDef;
1274 Cptr += SkipWhiteSpace (Cptr);
1275 if (*Cptr != '(') {
1276 Fail = TRUE;
1277 goto Done;
1278 }
1279
1280 Cptr++;
1281 //
1282 // Skip to first ' and start processing
1283 //
1284 while (*Cptr && (*Cptr != '\'')) {
1285 Cptr++;
1286 }
1287
1288 for (Index = 0; Index < SigSize; Index++) {
1289 if (*Cptr == '\'') {
1290 Cptr++;
1291 NewRec->Signature.Data[Index] = (INT8) *Cptr;
1292 //
1293 // Skip to closing quote
1294 //
1295 Cptr++;
1296 if (*Cptr != '\'') {
1297 Fail = TRUE;
1298 break;
1299 }
1300 //
1301 // Skip over closing quote, go to next one
1302 //
1303 Cptr++;
1304 while (*Cptr && (*Cptr != '\'')) {
1305 Cptr++;
1306 }
1307 } else {
1308 Fail = TRUE;
1309 DebugMsg (NULL, 0, 0, FileName, "failed to parse signature");
1310 break;
1311 }
1312 }
1313
1314 Done:
1315 if (Fail) {
1316 free (NewRec->FileName);
1317 free (NewRec);
1318 return STATUS_ERROR;
1319 }
1320
1321 NewRec->Next = gSignatureList;
1322 gSignatureList = NewRec;
1323 return STATUS_SUCCESS;
1324 }
1325 //
1326 // Look for:
1327 // #define POOL_HEAD_SIGNATURE EFI_SIGNATURE_16('p','h')
1328 // #define GCD_MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('g','m','a','p')
1329 // #define GCD_MEMORY_MAP_SIGNATURE EFI_SIGNATURE_64('g','m','a','p','a','b','c','d')
1330 //
1331 static
1332 STATUS
1333 ProcessCFileSigs (
1334 INT8 *FileName
1335 )
1336 {
1337 FILE *Fptr;
1338 INT8 Line[MAX_LINE_LEN * 2];
1339 INT8 *Cptr;
1340 UINT32 Len;
1341
1342 if ((Fptr = fopen (FileName, "r")) == NULL) {
1343 Error (NULL, 0, 0, FileName, "could not open input file for reading");
1344 return STATUS_ERROR;
1345 }
1346 //
1347 // Read lines from the file until done
1348 //
1349 while (fgets (Line, sizeof (Line), Fptr) != NULL) {
1350 Cptr = Line;
1351 Cptr += SkipWhiteSpace (Line);
1352 //
1353 // look for #define EFI_SIGNATURE_xx value
1354 //
1355 if (*Cptr == '#') {
1356 Cptr++;
1357 Cptr += SkipWhiteSpace (Cptr);
1358 //
1359 // Look for "define"
1360 //
1361 if (!strncmp (Cptr, "define", 6)) {
1362 Cptr += 6;
1363 //
1364 // Better be whitespace
1365 //
1366 Len = SkipWhiteSpace (Cptr);
1367 if (Len) {
1368 Cptr += Len;
1369 //
1370 // See if it's a valid symbol name
1371 //
1372 Len = ValidSymbolName (Cptr);
1373 if (Len) {
1374 //
1375 // It is a valid symbol name. See if there's line continuation,
1376 // and if so, read more lines.
1377 // Skip over the symbol name and look for the string "EFI_SIGNATURE_xx"
1378 //
1379 ConcatenateLines (Fptr, Line, sizeof(Line));
1380
1381 Cptr += Len;
1382 Cptr += SkipWhiteSpace (Cptr);
1383 if (strncmp (Cptr, "EFI_SIGNATURE_16", 16) == 0) {
1384 AddSignature (FileName, Cptr + 16, 2);
1385 } else if (strncmp (Cptr, "EFI_SIGNATURE_32", 16) == 0) {
1386 AddSignature (FileName, Cptr + 16, 4);
1387 } else if (strncmp (Cptr, "EFI_SIGNATURE_64", 16) == 0) {
1388 AddSignature (FileName, Cptr + 16, 8);
1389 }
1390 }
1391 }
1392 }
1393 }
1394 }
1395
1396 fclose (Fptr);
1397 return STATUS_SUCCESS;
1398 }
1399 //
1400 // look for #define xxxGUIDyyy { 0x...}
1401 // xxx EFI_GUID GuidName = { 0x... };
1402 //
1403 static
1404 STATUS
1405 ProcessCFileGuids (
1406 INT8 *FileName
1407 )
1408 {
1409 FILE *Fptr;
1410 INT8 Line[MAX_LINE_LEN * 2];
1411 INT8 *Cptr;
1412 INT8 *CSavePtr;
1413 INT8 *TempCptr;
1414 INT8 *SymName;
1415 UINT32 Len;
1416 UINT32 LineLen;
1417 UINT32 GuidScan[11];
1418
1419 if ((Fptr = fopen (FileName, "r")) == NULL) {
1420 Error (NULL, 0, 0, FileName, "could not open input file for reading");
1421 return STATUS_ERROR;
1422 }
1423 //
1424 // Read lines from the file until done
1425 //
1426 while (fgets (Line, sizeof (Line), Fptr) != NULL) {
1427 Cptr = Line;
1428 Cptr += SkipWhiteSpace (Line);
1429 //
1430 // look for #define xxxGUIDxxx value
1431 //
1432 if (*Cptr == '#') {
1433 Cptr++;
1434 Cptr += SkipWhiteSpace (Cptr);
1435 //
1436 // Look for "define"
1437 //
1438 if (!strncmp (Cptr, "define", 6)) {
1439 DefineLine:
1440 Cptr += 6;
1441 //
1442 // Better be whitespace
1443 //
1444 Len = SkipWhiteSpace (Cptr);
1445 if (Len) {
1446 Cptr += Len;
1447 //
1448 // See if it's a valid symbol name
1449 //
1450 Len = ValidSymbolName (Cptr);
1451 if (Len) {
1452 //
1453 // It is a valid symbol name. See if there's line continuation,
1454 // and if so, read more lines.
1455 // Then truncate after the symbol name, look for the string "GUID",
1456 // and continue.
1457 //
1458 SymName = Cptr;
1459 ConcatenateLines (Fptr, Line, sizeof(Line));
1460
1461 //
1462 // Now look for { 0x....... }
1463 //
1464 CSavePtr = Cptr + Len;
1465 Cptr += Len;
1466 Cptr += SkipWhiteSpace (Cptr);
1467 if (*Cptr == '{') {
1468 Cptr++;
1469 //
1470 // Blank out 'L', 'l', '{', '}', ',' on the line.
1471 //
1472 for (TempCptr = Cptr; *TempCptr; TempCptr++) {
1473 if ((*TempCptr == 'L') || (*TempCptr == 'l') || (*TempCptr == '{') ||
1474 (*TempCptr == '}') || (*TempCptr == ',')) {
1475 *TempCptr = ' ';
1476 }
1477 }
1478
1479 if (sscanf (
1480 Cptr,
1481 "%X %X %X %X %X %X %X %X %X %X %X",
1482 &GuidScan[0],
1483 &GuidScan[1],
1484 &GuidScan[2],
1485 &GuidScan[3],
1486 &GuidScan[4],
1487 &GuidScan[5],
1488 &GuidScan[6],
1489 &GuidScan[7],
1490 &GuidScan[8],
1491 &GuidScan[9],
1492 &GuidScan[10]
1493 ) == 11) {
1494 *CSavePtr = '\0';
1495 AddGuid11 (FileName, GuidScan, SymName);
1496 }
1497 }
1498 }
1499 }
1500 }
1501 //
1502 // Else look for "static EFI_GUID xxxGUIDxxx = { 0x.... };
1503 //
1504 } else if ((CSavePtr = strstr (Line, "EFI_GUID")) != NULL) {
1505 //
1506 // Read more lines until met ';'
1507 //
1508 ConcatenateLines (Fptr, Line, sizeof(Line));
1509 while (strstr (Line, ";") == NULL) {
1510 LineLen = strlen (Line);
1511 Len = sizeof(Line) - LineLen;
1512 if (Len <= 1) {
1513 break;
1514 }
1515 if (Line[LineLen - 1] == '\n') {
1516 Cptr = Line + LineLen - 1;
1517 *Cptr = '\0';
1518 if (fgets (Cptr, Len, Fptr) == NULL){
1519 break;
1520 }
1521 ConcatenateLines (Fptr, Line, sizeof(Line));
1522 } else {
1523 Cptr = Line + LineLen;
1524 *Cptr = '\0';
1525 if (fgets (Cptr, Len, Fptr) == NULL) {
1526 break;
1527 }
1528 ConcatenateLines (Fptr, Line, sizeof(Line));
1529 }
1530
1531 //
1532 // EFI_GUID may appear in comments wihout end of ';' which may cause
1533 // ignoring of new #define, so handle it here.
1534 //
1535 Cptr += SkipWhiteSpace (Cptr);
1536 if (*Cptr == '#') {
1537 Cptr++;
1538 Cptr += SkipWhiteSpace (Cptr);
1539 if (!strncmp (Cptr, "define", 6)) {
1540 goto DefineLine;
1541 }
1542 }
1543 }
1544
1545 Cptr = CSavePtr + 8;
1546 Cptr += SkipWhiteSpace (Cptr);
1547 //
1548 // Should be variable name next
1549 //
1550 Len = ValidSymbolName (Cptr);
1551 SymName = Cptr;
1552 Cptr += Len;
1553 CSavePtr = Cptr;
1554 Cptr += SkipWhiteSpace (Cptr);
1555 if (*Cptr == '=') {
1556 *CSavePtr = '\0';
1557 Cptr++;
1558 Cptr += SkipWhiteSpace (Cptr);
1559 //
1560 // Should be open-brace next to define guid
1561 //
1562 if (*Cptr == '{') {
1563 Cptr++;
1564 //
1565 // Blank out 'L', 'l', '{', '}', ',' on the line.
1566 //
1567 for (TempCptr = Cptr; *TempCptr; TempCptr++) {
1568 if ((*TempCptr == 'L') || (*TempCptr == 'l') || (*TempCptr == '{') ||
1569 (*TempCptr == '}') || (*TempCptr == ',')) {
1570 *TempCptr = ' ';
1571 }
1572 }
1573
1574 if (sscanf (
1575 Cptr,
1576 "%X %X %X %X %X %X %X %X %X %X %X",
1577 &GuidScan[0],
1578 &GuidScan[1],
1579 &GuidScan[2],
1580 &GuidScan[3],
1581 &GuidScan[4],
1582 &GuidScan[5],
1583 &GuidScan[6],
1584 &GuidScan[7],
1585 &GuidScan[8],
1586 &GuidScan[9],
1587 &GuidScan[10]
1588 ) == 11) {
1589 AddGuid11 (FileName, GuidScan, SymName);
1590 }
1591 }
1592 }
1593 }
1594 }
1595
1596 fclose (Fptr);
1597 return STATUS_SUCCESS;
1598 }
1599 //
1600 // Process Intel Itanium(TM) GUID definitions. Look for:
1601 // #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA
1602 // #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0
1603 // in either order.
1604 // This function assumes no blank lines between definitions.
1605 //
1606 static
1607 STATUS
1608 ProcessIA64FileGuids (
1609 INT8 *FileName
1610 )
1611 {
1612 FILE *Fptr;
1613 INT8 Line[MAX_LINE_LEN];
1614 UINT32 Guid1H;
1615 UINT32 Guid1L;
1616 UINT32 Guid2H;
1617 UINT32 Guid2L;
1618 INT8 SymName1[MAX_LINE_LEN];
1619 INT8 SymName2[MAX_LINE_LEN];
1620 BOOLEAN Done;
1621 BOOLEAN LowFirst;
1622 BOOLEAN FoundLow;
1623
1624 if ((Fptr = fopen (FileName, "r")) == NULL) {
1625 Error (NULL, 0, 0, FileName, "could not open input file for reading");
1626 return STATUS_ERROR;
1627 }
1628
1629 Done = FALSE;
1630 if (fgets (Line, sizeof (Line), Fptr) == NULL) {
1631 Done = 1;
1632 }
1633 //
1634 // Read lines from the file until done. Since the guid definition takes
1635 // two lines, we read lines in different places to recover gracefully
1636 // from mismatches. For example, if you thought you found the first half,
1637 // but the next line had a symbol mismatch, then you have to process the
1638 // line again in case it's the start of a new definition.
1639 //
1640 while (!Done) {
1641 //
1642 // Check current line for GUID definition. Assume low define first.
1643 //
1644 if (IsIA64GuidLine (Line, &Guid1H, &Guid1L, &FoundLow, SymName1)) {
1645 //
1646 // Might have to swap guids later. Save off if we found the LOW first
1647 //
1648 if (FoundLow) {
1649 LowFirst = TRUE;
1650 } else {
1651 LowFirst = FALSE;
1652 }
1653 //
1654 // Read the next line and try for the rest of the guid definition
1655 //
1656 if (fgets (Line, sizeof (Line), Fptr) == NULL) {
1657 Done = 1;
1658 } else {
1659 if (IsIA64GuidLine (Line, &Guid2H, &Guid2L, &FoundLow, SymName2)) {
1660 //
1661 // Found another. If the symbol names match, then save it off.
1662 //
1663 if (strcmp (SymName1, SymName2) == 0) {
1664 //
1665 // Yea, found one. Save it off.
1666 //
1667 if (LowFirst) {
1668 AddGuid64x2 (FileName, Guid2H, Guid2L, Guid1H, Guid1L, SymName1);
1669 } else {
1670 AddGuid64x2 (FileName, Guid1H, Guid1L, Guid2H, Guid2L, SymName1);
1671 }
1672 //
1673 // Read the next line for processing
1674 //
1675 if (fgets (Line, sizeof (Line), Fptr) == NULL) {
1676 Done = 1;
1677 }
1678 } else {
1679 //
1680 // Don't get another line so that we reprocess this line in case it
1681 // contains the start of a new definition.
1682 // fprintf (stdout, "Symbol name mismatch: %s: %s != %s\n",
1683 // FileName, SymName1, SymName2);
1684 //
1685 }
1686 } else {
1687 //
1688 // Second line was not a guid definition. Get the next line from the
1689 // file.
1690 //
1691 if (fgets (Line, sizeof (Line), Fptr) == NULL) {
1692 Done = 1;
1693 }
1694 }
1695 }
1696 } else {
1697 //
1698 // Not a guid define line. Next.
1699 //
1700 if (fgets (Line, sizeof (Line), Fptr) == NULL) {
1701 Done = 1;
1702 }
1703 }
1704 }
1705
1706 fclose (Fptr);
1707 return STATUS_SUCCESS;
1708 }
1709 //
1710 // Given a line from an Itanium-based assembly file, check the line for a guid
1711 // defininition. One of either:
1712 // #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA
1713 // #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0
1714 // Return the defined value as two 32-bit values, and whether it's a high
1715 // or low guid.
1716 //
1717 static
1718 BOOLEAN
1719 IsIA64GuidLine (
1720 INT8 *Line,
1721 UINT32 *GuidHigh,
1722 UINT32 *GuidLow,
1723 BOOLEAN *FoundLow,
1724 INT8 *SymName
1725 )
1726 {
1727 INT8 *Cptr;
1728 INT8 CSave;
1729 INT8 *CSavePtr;
1730 INT8 *SymStart;
1731 UINT32 Len;
1732
1733 Cptr = Line;
1734 Cptr += SkipWhiteSpace (Cptr);
1735 //
1736 // look for #define xxxGUID[L|H] 0xHexValue
1737 //
1738 if (*Cptr == '#') {
1739 Cptr++;
1740 Cptr += SkipWhiteSpace (Cptr);
1741 //
1742 // Look for "define"
1743 //
1744 if (!strncmp (Cptr, "define", 6)) {
1745 Cptr += 6;
1746 //
1747 // Better be whitespace
1748 //
1749 Len = SkipWhiteSpace (Cptr);
1750 if (Len) {
1751 Cptr += Len;
1752 //
1753 // See if it's a valid symbol name
1754 //
1755 Len = ValidSymbolName (Cptr);
1756 if (Len) {
1757 //
1758 // Save the start so we can copy it to their string if later checks are ok
1759 //
1760 SymStart = Cptr;
1761 //
1762 // It is a valid symbol name, look for the string GuidL or GuidH
1763 //
1764 CSavePtr = Cptr + Len;
1765 CSave = *CSavePtr;
1766 *CSavePtr = 0;
1767 while (*Cptr) {
1768 if (strncmp (Cptr, "GuidL", 5) == 0) {
1769 *FoundLow = 1;
1770 break;
1771 } else if (strncmp (Cptr, "GuidH", 5) == 0) {
1772 *FoundLow = 0;
1773 break;
1774 }
1775
1776 Cptr++;
1777 }
1778 //
1779 // If we didn't run out of string, then we found the GUID string.
1780 // Restore the null character we inserted above and continue.
1781 // Now look for 0x.......
1782 //
1783 if (*Cptr) {
1784 //
1785 // Return symbol name less the "L" or "H"
1786 //
1787 strcpy (SymName, SymStart);
1788 SymName[strlen (SymName) - 1] = 0;
1789 Cptr = CSavePtr;
1790 *CSavePtr = CSave;
1791 Cptr += SkipWhiteSpace (Cptr);
1792 if ((*Cptr == '0') && (*(Cptr + 1) == 'x')) {
1793 //
1794 // skip over "0x"
1795 //
1796 Cptr += 2;
1797 //
1798 // 0x0123456789ABCDEF -- null terminate after 8 characters,
1799 // scan, replace the character and scan at that point.
1800 //
1801 CSave = *(Cptr + 8);
1802 *(Cptr + 8) = 0;
1803 if (sscanf (Cptr, "%X", GuidHigh) == 1) {
1804 *(Cptr + 8) = CSave;
1805 if (sscanf (Cptr + 8, "%X", GuidLow) == 1) {
1806 return TRUE;
1807 }
1808 }
1809 }
1810 }
1811 }
1812 }
1813 }
1814 }
1815
1816 return FALSE;
1817 }
1818 //
1819 // Look at the characters in the string and determine if it's a valid
1820 // symbol name. Basically [a-zA-Z_][a-zA-Z_0-9]*
1821 //
1822 static
1823 UINT32
1824 ValidSymbolName (
1825 INT8 *Name
1826 )
1827 {
1828 int Len;
1829
1830 Len = 0;
1831
1832 //
1833 // Test first character
1834 //
1835 if (((*Name >= 'a') && (*Name <= 'z')) || ((*Name >= 'A') && (*Name <= 'Z')) || (*Name == '_')) {
1836 Name++;
1837 Len = 1;
1838 while (*Name) {
1839 if (((*Name >= 'a') && (*Name <= 'z')) ||
1840 ((*Name >= 'A') && (*Name <= 'Z')) ||
1841 ((*Name >= '0') && (*Name <= '9')) ||
1842 (*Name == '_')
1843 ) {
1844 Name++;
1845 Len++;
1846 } else {
1847 break;
1848 }
1849 }
1850 }
1851
1852 return Len;
1853 }
1854
1855 static
1856 UINT32
1857 SkipWhiteSpace (
1858 INT8 *Str
1859 )
1860 {
1861 UINT32 Len;
1862 Len = 0;
1863 while (isspace (*Str) && *Str) {
1864 Len++;
1865 Str++;
1866 }
1867
1868 return Len;
1869 }
1870 //
1871 // found FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7
1872 //
1873 static
1874 STATUS
1875 AddPkgGuid (
1876 INT8 *FileName,
1877 UINT32 *Data,
1878 UINT64 *Data64
1879 )
1880 {
1881 GUID_RECORD *NewRec;
1882 int Index;
1883
1884 //
1885 // Sanity check the data
1886 //
1887 if ((Data[1] | Data[2] | Data[3]) & 0xFFFF0000) {
1888 Error (NULL, 0, 0, "out of range value for GUID data word(s) [1] - [3]", NULL);
1889 return STATUS_ERROR;
1890 }
1891 //
1892 // More checks for Data64?
1893 // Allocate memory for a new one guid structure
1894 //
1895 NewRec = malloc (sizeof (GUID_RECORD));
1896 if (NewRec == NULL) {
1897 Error (NULL, 0, 0, "memory allocation failure", NULL);
1898 return STATUS_ERROR;
1899 }
1900
1901 memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
1902 NewRec->FileName = malloc (strlen (FileName) + 1);
1903 if (NewRec->FileName == NULL) {
1904 free (NewRec);
1905 Error (NULL, 0, 0, "memory allocation failure", NULL);
1906 return STATUS_ERROR;
1907 }
1908
1909 strcpy (NewRec->FileName, FileName);
1910 NewRec->Guid.Data1 = Data[0];
1911 NewRec->Guid.Data2 = (UINT16) Data[1];
1912 NewRec->Guid.Data3 = (UINT16) Data[2];
1913 NewRec->Guid.Data4[0] = (UINT8) (Data[3] >> 8);
1914 NewRec->Guid.Data4[1] = (UINT8) Data[3];
1915 for (Index = 2; Index < 8; Index++) {
1916 NewRec->Guid.Data4[Index] = ((UINT8*)Data64)[7-Index];
1917 }
1918 //
1919 // Add it to the list
1920 //
1921 NewRec->Next = gGuidList;
1922 gGuidList = NewRec;
1923
1924 //
1925 // Report it
1926 // ReportGuid (FileName, NewRec);
1927 //
1928 return STATUS_SUCCESS;
1929 }
1930 //
1931 // Add a guid consisting of 11 fields to our list of guids
1932 //
1933 static
1934 STATUS
1935 AddGuid11 (
1936 INT8 *FileName,
1937 UINT32 *Data,
1938 INT8 *SymName
1939 )
1940 {
1941 GUID_RECORD *NewRec;
1942 int Index;
1943
1944 //
1945 // Sanity check the data
1946 //
1947 if (!CheckGuidData (Data, 11)) {
1948 return STATUS_ERROR;
1949 }
1950 //
1951 // Allocate memory for a new one guid structure
1952 //
1953 NewRec = malloc (sizeof (GUID_RECORD));
1954 if (NewRec == NULL) {
1955 Error (NULL, 0, 0, "memory allocation failure", NULL);
1956 return STATUS_ERROR;
1957 }
1958
1959 memset ((char *) NewRec, 0, sizeof (GUID_RECORD));
1960 NewRec->FileName = malloc (strlen (FileName) + 1);
1961 if (NewRec->FileName == NULL) {
1962 free (NewRec);
1963 Error (NULL, 0, 0, "memory allocation failure", NULL);
1964 return STATUS_ERROR;
1965 }
1966
1967 strcpy (NewRec->FileName, FileName);
1968 if (SymName != NULL) {
1969 NewRec->SymName = malloc (strlen (SymName) + 1);
1970 if (NewRec->SymName == NULL) {
1971 free (NewRec);
1972 Error (NULL, 0, 0, "memory allocation failure", NULL);
1973 return STATUS_ERROR;
1974 }
1975 strcpy (NewRec->SymName, SymName);
1976 }
1977
1978 NewRec->Guid.Data1 = Data[0];
1979 NewRec->Guid.Data2 = (UINT16) Data[1];
1980 NewRec->Guid.Data3 = (UINT16) Data[2];
1981 for (Index = 0; Index < 8; Index++) {
1982 NewRec->Guid.Data4[Index] = (UINT8) Data[3 + Index];
1983 }
1984 //
1985 // Add it to the list
1986 //
1987 NewRec->Next = gGuidList;
1988 gGuidList = NewRec;
1989
1990 //
1991 // Report it
1992 // ReportGuid (FileName, NewRec);
1993 //
1994 return STATUS_SUCCESS;
1995 }
1996 //
1997 // For debug purposes, print each guid found
1998 //
1999 // static
2000 // VOID
2001 // ReportGuid (
2002 // INT8 *FileName,
2003 // GUID_RECORD *NewGuid
2004 // )
2005 // {
2006 // //fprintf (stdout, "%s: 0x%08X\n", FileName, NewGuid->Guid.Data1);
2007 // }
2008 //
2009 // Free up memory we allocated to keep track of guids defined.
2010 //
2011 static
2012 VOID
2013 FreeGuids (
2014 VOID
2015 )
2016 {
2017 GUID_RECORD *NextRec;
2018 while (gGuidList != NULL) {
2019 NextRec = gGuidList->Next;
2020 if (gGuidList->FileName != NULL) {
2021 free (gGuidList->FileName);
2022 }
2023
2024 if (gGuidList->SymName != NULL) {
2025 free (gGuidList->SymName);
2026 }
2027
2028 free (gGuidList);
2029 gGuidList = NextRec;
2030 }
2031 }
2032
2033 static
2034 VOID
2035 FreeSigs (
2036 VOID
2037 )
2038 {
2039 SIGNATURE_RECORD *NextRec;
2040 while (gSignatureList != NULL) {
2041 NextRec = gSignatureList->Next;
2042 if (gSignatureList->FileName != NULL) {
2043 free (gSignatureList->FileName);
2044 }
2045
2046 free (gSignatureList);
2047 gSignatureList = NextRec;
2048 }
2049 }
2050 //
2051 // Scan through all guids defined and compare each for duplicates.
2052 //
2053 static
2054 STATUS
2055 CheckDuplicates (
2056 VOID
2057 )
2058 {
2059 GUID_RECORD *CurrentFile;
2060
2061 GUID_RECORD *TempFile;
2062 SIGNATURE_RECORD *CurrentSig;
2063 SIGNATURE_RECORD *TempSig;
2064 STATUS Status;
2065 int Index;
2066 int DupCount;
2067 int Len;
2068 BOOLEAN Same;
2069 UINT32 GuidSum;
2070 INT8 *SymName;
2071
2072 Status = STATUS_SUCCESS;
2073
2074 //
2075 // If we're checking guids.....
2076 //
2077 if (gOptions.CheckGuids) {
2078 //
2079 // If -p option, print all guids found
2080 //
2081 if (gOptions.PrintFound) {
2082 CurrentFile = gGuidList;
2083 while (CurrentFile != NULL) {
2084 fprintf (
2085 stdout,
2086 "GUID: 0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X %s\n",
2087 (UINT32) CurrentFile->Guid.Data1,
2088 (UINT32) CurrentFile->Guid.Data2,
2089 (UINT32) CurrentFile->Guid.Data3,
2090 (UINT32) CurrentFile->Guid.Data4[0],
2091 (UINT32) CurrentFile->Guid.Data4[1],
2092 (UINT32) CurrentFile->Guid.Data4[2],
2093 (UINT32) CurrentFile->Guid.Data4[3],
2094 (UINT32) CurrentFile->Guid.Data4[4],
2095 (UINT32) CurrentFile->Guid.Data4[5],
2096 (UINT32) CurrentFile->Guid.Data4[6],
2097 (UINT32) CurrentFile->Guid.Data4[7],
2098 CurrentFile->FileName
2099 );
2100 CurrentFile = CurrentFile->Next;
2101 }
2102 }
2103
2104 if (gOptions.GuidXReference) {
2105 CurrentFile = gGuidList;
2106 while (CurrentFile != NULL) {
2107 //
2108 // If no symbol name, print FileName
2109 //
2110 SymName = CurrentFile->SymName;
2111 if (SymName == NULL) {
2112 //
2113 // Assume file name will not be NULL and strlen > 0
2114 //
2115 SymName = CurrentFile->FileName + strlen (CurrentFile->FileName) - 1;
2116 while ((*SymName != '\\') && (SymName > CurrentFile->FileName)) SymName --;
2117 if (*SymName == '\\') SymName ++;
2118 }
2119
2120 fprintf (
2121 stdout,
2122 "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s\n",
2123 (UINT32) CurrentFile->Guid.Data1,
2124 (UINT32) CurrentFile->Guid.Data2,
2125 (UINT32) CurrentFile->Guid.Data3,
2126 (UINT32) CurrentFile->Guid.Data4[0],
2127 (UINT32) CurrentFile->Guid.Data4[1],
2128 (UINT32) CurrentFile->Guid.Data4[2],
2129 (UINT32) CurrentFile->Guid.Data4[3],
2130 (UINT32) CurrentFile->Guid.Data4[4],
2131 (UINT32) CurrentFile->Guid.Data4[5],
2132 (UINT32) CurrentFile->Guid.Data4[6],
2133 (UINT32) CurrentFile->Guid.Data4[7],
2134 SymName
2135 );
2136 CurrentFile = CurrentFile->Next;
2137 }
2138 }
2139 //
2140 // Now go through all guids and report duplicates.
2141 //
2142 CurrentFile = gGuidList;
2143 while (CurrentFile != NULL) {
2144 DupCount = 0;
2145 TempFile = CurrentFile->Next;
2146 while (TempFile) {
2147 //
2148 // Compare the guids
2149 //
2150 if ((CurrentFile->Guid.Data1 == TempFile->Guid.Data1) &&
2151 (CurrentFile->Guid.Data2 == TempFile->Guid.Data2) &&
2152 (CurrentFile->Guid.Data3 == TempFile->Guid.Data3)
2153 ) {
2154 //
2155 // OR in all the guid bytes so we can ignore NULL-guid definitions.
2156 //
2157 GuidSum = CurrentFile->Guid.Data1 | CurrentFile->Guid.Data2 | CurrentFile->Guid.Data3;
2158 Same = TRUE;
2159 for (Index = 0; Index < 8; Index++) {
2160 GuidSum |= CurrentFile->Guid.Data4[Index];
2161 if (CurrentFile->Guid.Data4[Index] != TempFile->Guid.Data4[Index]) {
2162 Same = FALSE;
2163 break;
2164 }
2165 }
2166 //
2167 // If they're the same, and the guid was non-zero, print a message.
2168 //
2169 if (Same && GuidSum) {
2170 if (DupCount == 0) {
2171 Error (NULL, 0, 0, "duplicate GUIDS found", NULL);
2172 fprintf (stdout, " FILE1: %s\n", CurrentFile->FileName);
2173 }
2174
2175 DupCount++;
2176 fprintf (stdout, " FILE%d: %s\n", DupCount + 1, TempFile->FileName);
2177 //
2178 // Flag it as reported so we don't report it again if there's three or more
2179 //
2180 TempFile->Reported = TRUE;
2181 }
2182 }
2183 //
2184 // Next one
2185 //
2186 TempFile = TempFile->Next;
2187 }
2188 //
2189 // Print the guid if we found duplicates
2190 //
2191 if (DupCount) {
2192 fprintf (
2193 stdout,
2194 " GUID: 0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
2195 (UINT32) CurrentFile->Guid.Data1,
2196 (UINT32) CurrentFile->Guid.Data2,
2197 (UINT32) CurrentFile->Guid.Data3,
2198 (UINT32) CurrentFile->Guid.Data4[0],
2199 (UINT32) CurrentFile->Guid.Data4[1],
2200 (UINT32) CurrentFile->Guid.Data4[2],
2201 (UINT32) CurrentFile->Guid.Data4[3],
2202 (UINT32) CurrentFile->Guid.Data4[4],
2203 (UINT32) CurrentFile->Guid.Data4[5],
2204 (UINT32) CurrentFile->Guid.Data4[6],
2205 (UINT32) CurrentFile->Guid.Data4[7]
2206 );
2207 //
2208 // return STATUS_ERROR;
2209 //
2210 }
2211 //
2212 // Find the next one that hasn't been reported
2213 //
2214 do {
2215 CurrentFile = CurrentFile->Next;
2216 } while ((CurrentFile != NULL) && (CurrentFile->Reported));
2217 }
2218 }
2219
2220 if (gOptions.CheckSignatures) {
2221 //
2222 // Print ones found if specified
2223 //
2224 if (gOptions.PrintFound) {
2225 CurrentSig = gSignatureList;
2226 while (CurrentSig != NULL) {
2227 Len = CurrentSig->Signature.DataLen;
2228 for (Index = 0; Index < Len; Index++) {
2229 fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);
2230 }
2231
2232 fprintf (stdout, " %s\n", CurrentSig->FileName);
2233 CurrentSig = CurrentSig->Next;
2234 }
2235 }
2236
2237 CurrentSig = gSignatureList;
2238 while (CurrentSig != NULL) {
2239 DupCount = 0;
2240 TempSig = CurrentSig->Next;
2241 Len = CurrentSig->Signature.DataLen;
2242 while (TempSig) {
2243 //
2244 // Check for same length, then do string compare
2245 //
2246 if (Len == TempSig->Signature.DataLen) {
2247 if (strncmp (CurrentSig->Signature.Data, TempSig->Signature.Data, Len) == 0) {
2248 //
2249 // Print header message if first failure for this sig
2250 //
2251 if (DupCount == 0) {
2252 Error (NULL, 0, 0, "duplicate signatures found", NULL);
2253 fprintf (stdout, " FILE1: %s\n", CurrentSig->FileName);
2254 }
2255
2256 DupCount++;
2257 fprintf (stdout, " FILE%d: %s\n", DupCount + 1, TempSig->FileName);
2258 TempSig->Reported = TRUE;
2259 }
2260 }
2261
2262 TempSig = TempSig->Next;
2263 }
2264
2265 if (DupCount) {
2266 fprintf (stdout, " SIG: ");
2267 for (Index = 0; Index < Len; Index++) {
2268 fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]);
2269 }
2270
2271 fprintf (stdout, "\n");
2272 }
2273 //
2274 // On to the next one that hasn't been reported
2275 //
2276 do {
2277 CurrentSig = CurrentSig->Next;
2278 } while ((CurrentSig != NULL) && (CurrentSig->Reported));
2279 }
2280 }
2281
2282 return Status;
2283 }
2284
2285 static
2286 VOID
2287 FreeOptions (
2288 VOID
2289 )
2290 /*++
2291
2292 Routine Description:
2293 Free up any memory we allocated when processing command-line options.
2294
2295 Arguments:
2296 None.
2297
2298 Returns:
2299 NA
2300
2301 Notes:
2302 We don't free up the ->Str fields because we did not allocate them.
2303 Instead, we just set the pointer to point to the actual parameter
2304 from the command line.
2305
2306 --*/
2307 {
2308 STRING_LIST *Ptr;
2309 while (gOptions.ExcludeDirs != NULL) {
2310 Ptr = gOptions.ExcludeDirs->Next;
2311 //
2312 // free (gOptions.ExcludeDirs->Str);
2313 //
2314 free (gOptions.ExcludeDirs);
2315 gOptions.ExcludeDirs = Ptr;
2316 }
2317
2318 while (gOptions.ExcludeSubDirs != NULL) {
2319 Ptr = gOptions.ExcludeSubDirs->Next;
2320 //
2321 // free (gOptions.ExcludeSubDirs->Str);
2322 //
2323 free (gOptions.ExcludeSubDirs);
2324 gOptions.ExcludeSubDirs = Ptr;
2325 }
2326
2327 while (gOptions.ExcludeExtensions != NULL) {
2328 Ptr = gOptions.ExcludeExtensions->Next;
2329 //
2330 // free (gOptions.ExcludeExtensions->Str);
2331 //
2332 free (gOptions.ExcludeExtensions);
2333 gOptions.ExcludeExtensions = Ptr;
2334 }
2335
2336 while (gOptions.ExcludeFiles != NULL) {
2337 Ptr = gOptions.ExcludeFiles->Next;
2338 //
2339 // free (gOptions.ExcludeFiles->Str);
2340 //
2341 free (gOptions.ExcludeFiles);
2342 gOptions.ExcludeFiles = Ptr;
2343 }
2344 }
2345 //
2346 // Given an array of 32-bit data, validate the data for the given number of
2347 // guid data. For example, it might have been scanned as 16 bytes of data, or
2348 // 11 fields of data.
2349 //
2350 static
2351 BOOLEAN
2352 CheckGuidData (
2353 UINT32 *Data,
2354 UINT32 DataCount
2355 )
2356 {
2357 UINT32 Index;
2358
2359 if (DataCount == 16) {
2360 for (Index = 0; Index < 16; Index++) {
2361 if (Data[Index] &~0xFF) {
2362 return FALSE;
2363 }
2364 }
2365
2366 return TRUE;
2367 } else if (DataCount == 11) {
2368 //
2369 // Data[0] never out of range (32-bit)
2370 //
2371 if ((Data[1] | Data[2]) &~0xFFFF) {
2372 //
2373 // Error ("Out of range value for GUID data word(s) [1] and/or [2]");
2374 //
2375 return FALSE;
2376 }
2377
2378 for (Index = 0; Index < 8; Index++) {
2379 if (Data[Index + 3] &~0xFF) {
2380 //
2381 // Error ("Out of range value for GUID data byte(s) [4] - [11]");
2382 //
2383 return FALSE;
2384 }
2385 }
2386
2387 return TRUE;
2388 }
2389
2390 return FALSE;
2391 }
2392
2393 static
2394 VOID
2395 ConcatenateLines (
2396 FILE *Fptr,
2397 INT8 *Line,
2398 UINT32 Len
2399 )
2400 {
2401 UINT32 LineLen;
2402 BOOLEAN NeedCheck;
2403
2404 NeedCheck = TRUE;
2405 while (NeedCheck) {
2406 LineLen = strlen (Line);
2407 if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) {
2408 Line[LineLen - 2] = '\0';
2409 fgets (Line + LineLen - 2, Len - LineLen, Fptr);
2410 } else if (Line[LineLen - 1] == '\\') {
2411 Line[LineLen - 1] = '\0';
2412 fgets (Line + LineLen - 1, Len - LineLen, Fptr);
2413 } else {
2414 NeedCheck = FALSE;
2415 }
2416 }
2417 }