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