3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 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
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.
18 Generate Dependency Expression ("GenDepex")
20 Infix to Postfix Algorithm
22 This code has been scrubbed to be free of having any EFI core tree dependencies.
23 It should build in any environment that supports a standard C-library w/ string
24 operations and File I/O services.
26 As an example of usage, consider the following:
28 The input user file could be something like "Sample.DXS" whose contents are
33 NOT (DISK_IO_PROTOCOL AND SIMPLE_FILE_SYSTEM_PROTOCOL)
34 OR EFI_PXE_BASE_CODE_PROTOCOL
37 This file is then washed through the C-preprocessor, viz.,
39 cl /EP Sample.DXS > Sample.TMP1
41 This yields the following file "Sample.TMP1" whose contents are
44 NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72,
45 0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69,
46 0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27,
50 This file, in turn, will be fed into the utility, viz.,
52 GenDepex Sample.TMP1 Sample.TMP2
54 With a file that is 55 bytes long:
56 55 bytes for the grammar binary
58 GUID Instance - 16 bytes
60 GUID Instance - 16 bytes
64 GUID Instance - 16 bytes
68 The file "Sample.TMP2" could be fed via a Section-builder utility
69 (GenSection) that would be used for the creation of a dependency
70 section file (.DPX) which in turn would be used by a generate FFS
71 utility (GenFfsFile) to produce a DXE driver/core (.DXE) or
72 a DXE application (.APP) file.
74 Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000.
83 #define UTILITY_NAME "GenDepex"
86 // Utility version information
88 #define UTILITY_VERSION "v1.0"
98 PrintGenDepexUtilityInfo (
105 Displays the standard utility information to SDTOUT.
118 const char *Str
[] = {
119 UTILITY_NAME
" "UTILITY_VERSION
" - Intel Generate Dependency Expression Utility",
120 " Copyright (C), 1996 - 2008 Intel Corporation",
122 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
123 " Built from "UTILITY_BUILD
", project of "UTILITY_VENDOR
,
127 for (Index
= 0; Str
[Index
] != NULL
; Index
++) {
128 fprintf (stdout
, "%s\n", Str
[Index
]);
133 PrintGenDepexUsageInfo (
140 Displays the utility usage syntax to STDOUT.
153 const char *Str
[] = {
156 " "UTILITY_NAME
" [OPTION]...",
158 " -I INFILE The input pre-processed dependency text files name",
159 " -O OUTFILE The output binary dependency files name",
160 " -P BOUNDARY The padding integer value to align the output file size",
164 PrintGenDepexUtilityInfo ();
165 for (Index
= 0; Str
[Index
] != NULL
; Index
++) {
166 fprintf (stdout
, "%s\n", Str
[Index
]);
178 Pop an element from the Opcode stack.
182 Stack Current top of the OpCode stack location
186 DEPENDENCY_OPCODE OpCode at the top of the OpCode stack.
187 Stack New top of the OpCode stack location
192 DEPENDENCY_OPCODE
*OpCodePtr
;
203 IN DEPENDENCY_OPCODE OpCode
209 Push an element onto the Opcode Stack
213 Stack Current top of the OpCode stack location
214 OpCode OpCode to push onto the stack
218 Stack New top of the OpCode stack location
222 DEPENDENCY_OPCODE
*OpCodePtr
;
231 GenerateDependencyExpression (
233 IN OUT
FILE *OutFile
,
234 IN UINT8 Padding OPTIONAL
240 This takes the pre-compiled dependency text file and
241 converts it into a binary dependency file.
243 The BNF for the dependency expression is as follows
244 (from the DXE 1.0 Draft specification).
246 The inputted BNF grammar is thus:
247 <depex> ::= sor <dep> |
254 <bool> ::= <bool> and <term> |
258 <term> ::= not <factor> |
261 <factor> ::= ( <bool> ) |
269 The outputed binary grammer is thus:
270 <depex> ::= sor <dep> |
271 before <depinst> <dep> |
272 after <depinst> <dep> |
277 <bool> ::= <bool> and <term> |
278 <bool> or <term> | <term>
280 <term> ::= not <factor> |
283 <factor> ::= ( <bool> ) |
292 <depinst> ::= push GUID
296 BugBug: A correct grammer is parsed correctly. A file that violates the
297 grammer may parse when it should generate an error. There is some
298 error checking and it covers most of the case when it's an include
299 of definition issue. An ill formed expresion may not be detected.
303 InFile - Input pre-compiled text file of the dependency expression.
304 This needs to be in ASCII.
305 The file pointer can not be NULL.
307 OutFile - Binary dependency file.
308 The file pointer can not be NULL.
310 Padding - OPTIONAL integer value to pad the output file to.
315 EFI_SUCCESS The function completed successfully.
316 EFI_INVALID_PARAMETER One of the parameters in the text file was invalid.
317 EFI_OUT_OF_RESOURCES Unable to allocate memory.
318 EFI_ABORTED An misc error occurred.
324 INT8
*EvaluationStack
;
338 UINTN ArgCountParsed
;
339 DEPENDENCY_OPCODE Opcode
;
346 memset (Line
, 0, LINESIZE
);
350 EvaluationStack
= (INT8
*) malloc (EVAL_STACK_SIZE
);
352 if (EvaluationStack
!= NULL
) {
353 StackPtr
= EvaluationStack
;
355 printf ("Unable to allocate memory to EvaluationStack - Out of resources\n");
356 return EFI_OUT_OF_RESOURCES
;
359 Results
= (UINTN
) fseek (InFile
, 0, SEEK_END
);
362 printf ("FSEEK failed - Aborted\n");
366 FileSize
= ftell (InFile
);
368 if (FileSize
== -1L) {
369 printf ("FTELL failed - Aborted\n");
373 Buffer
= (INT8
*) malloc (FileSize
+ BUFFER_SIZE
);
375 if (Buffer
== NULL
) {
376 printf ("Unable to allocate memory to Buffer - Out of resources\n");
377 free (EvaluationStack
);
379 Results
= (UINTN
) fclose (InFile
);
381 printf ("FCLOSE failed\n");
384 Results
= (UINTN
) fclose (OutFile
);
386 printf ("FCLOSE failed\n");
389 return EFI_OUT_OF_RESOURCES
;
392 Results
= (UINTN
) fseek (InFile
, 0, SEEK_SET
);
395 printf ("FSEEK failed - Aborted\n");
399 fread (Buffer
, FileSize
, 1, InFile
);
402 Pend
= Ptrx
+ FileSize
- strlen (DEPENDENCY_END
);
406 while ((Index
--) && NotDone
) {
408 if (strncmp (Pend
, DEPENDENCY_END
, strlen (DEPENDENCY_END
)) == 0) {
416 printf ("Couldn't find end string %s\n", DEPENDENCY_END
);
418 Results
= (UINTN
) fclose (InFile
);
420 printf ("FCLOSE failed\n");
423 Results
= (UINTN
) fclose (OutFile
);
425 printf ("FCLOSE failed\n");
429 free (EvaluationStack
);
431 return EFI_INVALID_PARAMETER
;
437 while ((Index
--) && NotDone
) {
439 if (strncmp (Ptrx
, DEPENDENCY_START
, strlen (DEPENDENCY_START
)) == 0) {
440 Ptrx
+= strlen (DEPENDENCY_START
);
443 // BUGBUG -- should Index be decremented by sizeof(DEPENDENCY_START)?
451 printf ("Couldn't find start string %s\n", DEPENDENCY_START
);
453 Results
= (UINTN
) fclose (InFile
);
455 printf ("FCLOSE failed\n");
458 Results
= (UINTN
) fclose (OutFile
);
460 printf ("FCLOSE failed\n");
464 free (EvaluationStack
);
466 return EFI_INVALID_PARAMETER
;
469 // validate the syntax of expression
471 if (!ParseDepex (Ptrx
, Pend
- Ptrx
- 1)) {
472 printf ("The syntax of expression is wrong\n");
474 Results
= (UINTN
) fclose (InFile
);
476 printf ("FCLOSE failed\n");
479 Results
= (UINTN
) fclose (OutFile
);
481 printf ("FCLOSE failed\n");
485 free (EvaluationStack
);
487 return EFI_INVALID_PARAMETER
;
492 while ((Index
--) && NotDone
) {
496 } else if (*Ptrx
== '\n' || *Ptrx
== '\r') {
498 } else if (strncmp (Ptrx
, OPERATOR_SOR
, strlen (OPERATOR_SOR
)) == 0) {
500 // Checks for some invalid dependencies
504 printf ("A BEFORE operator was detected.\n");
505 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
506 return EFI_INVALID_PARAMETER
;
508 } else if (After_Flag
) {
510 printf ("An AFTER operator was detected.\n");
511 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
512 return EFI_INVALID_PARAMETER
;
514 } else if (SOR_Flag
) {
516 printf ("Another SOR operator was detected.\n");
517 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
518 return EFI_INVALID_PARAMETER
;
520 } else if (Dep_Flag
) {
522 printf ("The Schedule On Request - SOR operator must be the first operator following DEPENDENCY_START\n");
523 return EFI_INVALID_PARAMETER
;
527 // BUGBUG - This was not in the spec but is in the CORE code
528 // An OPERATOR_SOR has to be first - following the DEPENDENCY_START
530 fputc (EFI_DEP_SOR
, OutFile
);
532 Ptrx
+= strlen (OPERATOR_SOR
);
536 } else if (strncmp (Ptrx
, OPERATOR_BEFORE
, strlen (OPERATOR_BEFORE
)) == 0) {
538 // Checks for some invalid dependencies
542 printf ("Another BEFORE operator was detected.\n");
543 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
544 return EFI_INVALID_PARAMETER
;
546 } else if (After_Flag
) {
548 printf ("An AFTER operator was detected.\n");
549 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
550 return EFI_INVALID_PARAMETER
;
552 } else if (SOR_Flag
) {
554 printf ("A SOR operator was detected.\n");
555 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
556 return EFI_INVALID_PARAMETER
;
558 } else if (Dep_Flag
) {
560 printf ("The BEFORE operator must be the first operator following DEPENDENCY_START\n");
561 return EFI_INVALID_PARAMETER
;
564 fputc (EFI_DEP_BEFORE
, OutFile
);
566 Ptrx
+= strlen (OPERATOR_BEFORE
);
569 } else if (strncmp (Ptrx
, OPERATOR_AFTER
, strlen (OPERATOR_AFTER
)) == 0) {
571 // Checks for some invalid dependencies
575 printf ("A BEFORE operator was detected.\n");
576 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
577 return EFI_INVALID_PARAMETER
;
579 } else if (After_Flag
) {
581 printf ("Another AFTER operator was detected.\n");
582 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
583 return EFI_INVALID_PARAMETER
;
585 } else if (SOR_Flag
) {
587 printf ("A SOR operator was detected.\n");
588 printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
589 return EFI_INVALID_PARAMETER
;
591 } else if (Dep_Flag
) {
593 printf ("The AFTER operator must be the first operator following DEPENDENCY_START\n");
594 return EFI_INVALID_PARAMETER
;
597 fputc (EFI_DEP_AFTER
, OutFile
);
599 Ptrx
+= strlen (OPERATOR_AFTER
);
603 } else if (strncmp (Ptrx
, OPERATOR_AND
, strlen (OPERATOR_AND
)) == 0) {
604 while (StackPtr
!= EvaluationStack
) {
605 Opcode
= PopOpCode ((VOID
**) &StackPtr
);
606 if (Opcode
!= DXE_DEP_LEFT_PARENTHESIS
) {
607 fputc (Opcode
, OutFile
);
610 PushOpCode ((VOID
**) &StackPtr
, DXE_DEP_LEFT_PARENTHESIS
);
615 PushOpCode ((VOID
**) &StackPtr
, EFI_DEP_AND
);
616 Ptrx
+= strlen (OPERATOR_AND
);
619 } else if (strncmp (Ptrx
, OPERATOR_OR
, strlen (OPERATOR_OR
)) == 0) {
620 while (StackPtr
!= EvaluationStack
) {
621 Opcode
= PopOpCode ((VOID
**) &StackPtr
);
622 if (Opcode
!= DXE_DEP_LEFT_PARENTHESIS
) {
623 fputc (Opcode
, OutFile
);
626 PushOpCode ((VOID
**) &StackPtr
, DXE_DEP_LEFT_PARENTHESIS
);
631 PushOpCode ((VOID
**) &StackPtr
, EFI_DEP_OR
);
632 Ptrx
+= strlen (OPERATOR_OR
);
635 } else if (strncmp (Ptrx
, OPERATOR_NOT
, strlen (OPERATOR_NOT
)) == 0) {
636 while (StackPtr
!= EvaluationStack
) {
637 Opcode
= PopOpCode ((VOID
**) &StackPtr
);
638 if (Opcode
!= DXE_DEP_LEFT_PARENTHESIS
) {
639 fputc (Opcode
, OutFile
);
642 PushOpCode ((VOID
**) &StackPtr
, DXE_DEP_LEFT_PARENTHESIS
);
647 PushOpCode ((VOID
**) &StackPtr
, EFI_DEP_NOT
);
648 Ptrx
+= strlen (OPERATOR_NOT
);
651 } else if (*Ptrx
== '\t') {
653 printf ("File contains tabs. This violates the coding standard\n");
654 return EFI_INVALID_PARAMETER
;
656 } else if (*Ptrx
== '\n') {
658 // Skip the newline character in the file
662 } else if (strncmp (Ptrx
, OPERATOR_LEFT_PARENTHESIS
, strlen (OPERATOR_LEFT_PARENTHESIS
)) == 0) {
663 PushOpCode ((VOID
**) &StackPtr
, DXE_DEP_LEFT_PARENTHESIS
);
665 Ptrx
+= strlen (OPERATOR_LEFT_PARENTHESIS
);
668 } else if (strncmp (Ptrx
, OPERATOR_RIGHT_PARENTHESIS
, strlen (OPERATOR_RIGHT_PARENTHESIS
)) == 0) {
669 while (StackPtr
!= EvaluationStack
) {
670 Opcode
= PopOpCode ((VOID
**) &StackPtr
);
671 if (Opcode
!= DXE_DEP_LEFT_PARENTHESIS
) {
672 fputc (Opcode
, OutFile
);
679 Ptrx
+= strlen (OPERATOR_RIGHT_PARENTHESIS
);
682 } else if (strncmp (Ptrx
, OPERATOR_TRUE
, strlen (OPERATOR_TRUE
)) == 0) {
684 fputc (EFI_DEP_TRUE
, OutFile
);
689 // OutFileSize += sizeof (EFI_DEP_TRUE);
693 Ptrx
+= strlen (OPERATOR_TRUE
);
695 } else if (strncmp (Ptrx
, OPERATOR_FALSE
, strlen (OPERATOR_FALSE
)) == 0) {
697 fputc (EFI_DEP_FALSE
, OutFile
);
702 // OutFileSize += sizeof (EFI_DEP_FALSE);
706 Ptrx
+= strlen (OPERATOR_FALSE
);
708 } else if (*Ptrx
== '{') {
715 ArgCountParsed
= sscanf (
717 "%x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x",
731 if (ArgCountParsed
!= 11) {
732 printf ("We have found an illegal GUID\n");
733 printf ("Fix your depex\n");
737 while (*Ptrx
!= '}') {
741 // Absorb the closing }
746 // Don't provide a PUSH Opcode for the Before and After case
748 if ((!Before_Flag
) && (!After_Flag
)) {
749 fputc (EFI_DEP_PUSH
, OutFile
);
753 fwrite (&Guid
, sizeof (EFI_GUID
), 1, OutFile
);
755 OutFileSize
+= sizeof (EFI_GUID
);
758 } else if (strncmp (Ptrx
, DEPENDENCY_END
, strlen (DEPENDENCY_END
)) == 0) {
762 // Not a valid construct. Null terminate somewhere out there and
763 // print an error message.
766 printf (UTILITY_NAME
" ERROR: Unrecognized input at: \"%s\"...\n", Ptrx
);
767 return EFI_INVALID_PARAMETER
;
773 while (StackPtr
!= EvaluationStack
) {
774 fputc (PopOpCode ((VOID
**) &StackPtr
), OutFile
);
778 if (OutFileSize
== 0) {
779 printf ("Grammer contains no operators or constants\n");
780 return EFI_INVALID_PARAMETER
;
783 fputc (EFI_DEP_END
, OutFile
);
788 // Checks for invalid padding values
792 printf ("The inputted padding value was %d\n", Padding
);
793 printf ("The optional padding value can not be less than ZERO\n");
794 return EFI_INVALID_PARAMETER
;
796 } else if (Padding
> 0) {
798 while ((OutFileSize
% Padding
) != 0) {
800 fputc (' ', OutFile
);
805 Results
= (UINTN
) fclose (InFile
);
807 printf ("FCLOSE failed\n");
810 Results
= (UINTN
) fclose (OutFile
);
812 printf ("FCLOSE failed\n");
816 free (EvaluationStack
);
819 } // End GenerateDependencyExpression function
830 Parse user entries. Print some rudimentary help
834 argc The count of input arguments
835 argv The input arguments string array
839 EFI_SUCCESS The function completed successfully.
840 EFI_INVALID_PARAMETER One of the input parameters was invalid or one of the parameters in the text file was invalid.
841 EFI_OUT_OF_RESOURCES Unable to allocate memory.
842 EFI_ABORTED Unable to open/create a file or a misc error.
845 // TODO: ] - add argument and description to function comment
863 // Output the calling arguments
866 //for (Index = 0; Index < argc; Index++) {
867 // printf ("%s ", argv[Index]);
873 printf ("Not enough arguments\n");
874 PrintGenDepexUsageInfo ();
875 return EFI_INVALID_PARAMETER
;
878 for (Index
= 1; Index
< argc
- 1; Index
++) {
880 if ((strcmp (argv
[Index
], "-I") == 0) || (strcmp (argv
[Index
], "-i") == 0)) {
884 InFile
= fopen (argv
[Index
+ 1], "rb");
888 printf ("GenDepex only allows one INPUT (-I) argument\n");
889 return EFI_INVALID_PARAMETER
;
892 } else if ((strcmp (argv
[Index
], "-O") == 0) || (strcmp (argv
[Index
], "-o") == 0)) {
896 OutFile
= fopen (argv
[Index
+ 1], "wb");
900 printf ("GenDepex only allows one OUTPUT (-O) argument\n");
901 return EFI_INVALID_PARAMETER
;
904 } else if ((strcmp (argv
[Index
], "-P") == 0) || (strcmp (argv
[Index
], "-p") == 0)) {
908 Padding
= (UINT8
) atoi (argv
[Index
+ 1]);
912 printf ("GenDepex only allows one PADDING (-P) argument\n");
913 return EFI_INVALID_PARAMETER
;
918 PrintGenDepexUtilityInfo ();
920 if (InFile
== NULL
) {
921 printf ("Can not open <INFILE> for reading.\n");
922 PrintGenDepexUsageInfo ();
926 if (OutFile
== NULL
) {
927 printf ("Can not open <OUTFILE> for writting.\n");
928 PrintGenDepexUsageInfo ();
932 return GenerateDependencyExpression (InFile
, OutFile
, Padding
);