git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1676 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			920 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			920 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2004, Intel Corporation                                                         
 | |
| All rights reserved. This program and the accompanying materials                          
 | |
| are licensed and made available under the terms and conditions of the BSD License         
 | |
| which accompanies this distribution.  The full text of the license may be found at        
 | |
| http://opensource.org/licenses/bsd-license.php                                            
 | |
|                                                                                           
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | |
| 
 | |
| Module Name:
 | |
| 
 | |
|   GenDepex.c
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
|   Generate Dependency Expression ("GenDepex")
 | |
| 
 | |
|   Infix to Postfix Algorithm
 | |
| 
 | |
|   This code has been scrubbed to be free of having any EFI core tree dependencies.
 | |
|   It should build in any environment that supports a standard C-library w/ string
 | |
|   operations and File I/O services.
 | |
| 
 | |
|   As an example of usage, consider the following:
 | |
| 
 | |
|   The input user file could be something like "Sample.DXS" whose contents are
 | |
| 
 | |
|     #include "Tiano.h"
 | |
| 
 | |
|     DEPENDENCY_START
 | |
|       NOT (DISK_IO_PROTOCOL AND SIMPLE_FILE_SYSTEM_PROTOCOL) 
 | |
|         OR EFI_PXE_BASE_CODE_PROTOCOL
 | |
|     DEPENDENCY_END
 | |
| 
 | |
|   This file is then washed through the C-preprocessor, viz.,
 | |
| 
 | |
|     cl /EP Sample.DXS > Sample.TMP1
 | |
| 
 | |
|   This yields the following file "Sample.TMP1" whose contents are
 | |
| 
 | |
|     DEPENDENCY_START
 | |
|       NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72,
 | |
|         0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69,
 | |
|         0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27,
 | |
|         0x3f, 0xc1, 0x4d }
 | |
|     DEPENDENCY_END
 | |
| 
 | |
|   This file, in turn, will be fed into the utility, viz.,
 | |
| 
 | |
|     GenDepex Sample.TMP1 Sample.TMP2
 | |
| 
 | |
|   With a file that is 55 bytes long:
 | |
| 
 | |
|      55 bytes for the grammar binary
 | |
|         PUSH opcode         - 1  byte
 | |
|         GUID Instance       - 16 bytes
 | |
|         PUSH opcode         - 1  byte
 | |
|         GUID Instance       - 16 bytes
 | |
|         AND opcode          - 1  byte
 | |
|         NOT opcode          - 1  byte
 | |
|         PUSH opcode         - 1  byte
 | |
|         GUID Instance       - 16 bytes
 | |
|         OR opcode           - 1  byte
 | |
|         END opcode          - 1  byte
 | |
| 
 | |
|   The file "Sample.TMP2" could be fed via a Section-builder utility 
 | |
|   (GenSection) that would be used for the creation of a dependency
 | |
|   section file (.DPX) which in turn would be used by a generate FFS
 | |
|   utility (GenFfsFile) to produce a DXE driver/core (.DXE) or 
 | |
|   a DXE application (.APP) file.
 | |
| 
 | |
|   Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000.
 | |
| 
 | |
| --*/
 | |
| 
 | |
| #include "GenDepex.h"
 | |
| 
 | |
| #define TOOL_NAME "GenDepex"
 | |
| 
 | |
| extern
 | |
| ParseDepex (
 | |
|   IN      INT8      *Pbegin,
 | |
|   IN      UINT32    length
 | |
|   );
 | |
| 
 | |
| VOID
 | |
| PrintGenDepexUtilityInfo (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Displays the standard utility information to SDTOUT.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   None
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   printf (
 | |
|     "%s, Tiano Dependency Expression Generation Utility. Version %d.%d.\n",
 | |
|     UTILITY_NAME,
 | |
|     UTILITY_MAJOR_VERSION,
 | |
|     UTILITY_MINOR_VERSION
 | |
|     );
 | |
|   printf ("Copyright (C) 1996-2002 Intel Corporation.  All rights reserved.\n\n");
 | |
| }
 | |
| 
 | |
| VOID
 | |
| PrintGenDepexUsageInfo (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Displays the utility usage syntax to STDOUT.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   None
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   printf (
 | |
|     "Usage: %s -I <INFILE> -O <OUTFILE> [-P <Optional Boundary for padding up>] \n",
 | |
|     UTILITY_NAME
 | |
|     );
 | |
|   printf (" Where:\n");
 | |
|   printf ("  <INFILE> is the input pre-processed dependency text files name.\n");
 | |
|   printf ("  <OUTFILE> is the output binary dependency files name.\n");
 | |
|   printf ("  <Optional Boundary for padding up> is the padding integer value.\n");
 | |
|   printf ("    This is the boundary to align the output file size to.\n");
 | |
| }
 | |
| 
 | |
| DEPENDENCY_OPCODE
 | |
| PopOpCode (
 | |
|   IN OUT VOID **Stack
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Pop an element from the Opcode stack.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Stack               Current top of the OpCode stack location
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   DEPENDENCY_OPCODE   OpCode at the top of the OpCode stack.
 | |
|   Stack               New top of the OpCode stack location
 | |
| 
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   DEPENDENCY_OPCODE *OpCodePtr;
 | |
| 
 | |
|   OpCodePtr = *Stack;
 | |
|   OpCodePtr--;
 | |
|   *Stack = OpCodePtr;
 | |
|   return *OpCodePtr;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| PushOpCode (
 | |
|   IN OUT  VOID                **Stack,
 | |
|   IN      DEPENDENCY_OPCODE   OpCode
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Push an element onto the Opcode Stack
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Stack     Current top of the OpCode stack location
 | |
|   OpCode    OpCode to push onto the stack
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   Stack     New top of the OpCode stack location
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   DEPENDENCY_OPCODE *OpCodePtr;
 | |
| 
 | |
|   OpCodePtr   = *Stack;
 | |
|   *OpCodePtr  = OpCode;
 | |
|   OpCodePtr++;
 | |
|   *Stack = OpCodePtr;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| GenerateDependencyExpression (
 | |
|   IN     FILE           *InFile,
 | |
|   IN OUT FILE           *OutFile,
 | |
|   IN     INT8           Padding  OPTIONAL
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   This takes the pre-compiled dependency text file and 
 | |
|   converts it into a binary dependency file.
 | |
| 
 | |
|   The BNF for the dependency expression is as follows 
 | |
|   (from the DXE 1.0 Draft specification).
 | |
| 
 | |
|   The inputted BNF grammar is thus:
 | |
|     <depex> ::= sor <dep> | 
 | |
|                 before GUID <dep> | 
 | |
|                 after GUID <dep> | 
 | |
|                 <bool>
 | |
| 
 | |
|     <dep> ::=   <bool> |
 | |
| 
 | |
|     <bool> ::=  <bool> and <term> | 
 | |
|                 <bool> or <term> | 
 | |
|                 <term>
 | |
| 
 | |
|     <term> ::=  not <factor> | 
 | |
|                 <factor>
 | |
| 
 | |
|     <factor> ::= ( <bool> ) | 
 | |
|                  <term> <term> | 
 | |
|                  GUID | 
 | |
|                  <boolval>
 | |
| 
 | |
|     <boolval> ::= true | 
 | |
|                   false
 | |
| 
 | |
|   The outputed binary grammer is thus:
 | |
|     <depex> ::= sor <dep> | 
 | |
|                 before <depinst> <dep> | 
 | |
|                 after <depinst> <dep> | 
 | |
|                 <bool>
 | |
| 
 | |
|     <dep> ::=   <bool> |
 | |
| 
 | |
|     <bool> ::=  <bool> and <term> | 
 | |
|                 <bool> or <term> | <term>
 | |
| 
 | |
|     <term> ::=  not <factor> | 
 | |
|                 <factor>
 | |
| 
 | |
|     <factor> ::= ( <bool> ) | 
 | |
|                  <term> <term> | 
 | |
|                  <boolval> | 
 | |
|                  <depinst> | 
 | |
|                  <termval>
 | |
| 
 | |
|     <boolval> ::= true | 
 | |
|                   false
 | |
| 
 | |
|     <depinst> ::= push GUID
 | |
| 
 | |
|     <termval> ::= end
 | |
| 
 | |
|   BugBug: A correct grammer is parsed correctly. A file that violates the
 | |
|           grammer may parse when it should generate an error. There is some
 | |
|           error checking and it covers most of the case when it's an include
 | |
|           of definition issue. An ill formed expresion may not be detected.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   InFile -  Input pre-compiled text file of the dependency expression.
 | |
|             This needs to be in ASCII.
 | |
|             The file pointer can not be NULL.
 | |
| 
 | |
|   OutFile - Binary dependency file.
 | |
|             The file pointer can not be NULL.
 | |
| 
 | |
|   Padding - OPTIONAL integer value to pad the output file to.
 | |
| 
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS             The function completed successfully.
 | |
|   EFI_INVALID_PARAMETER   One of the parameters in the text file was invalid.
 | |
|   EFI_OUT_OF_RESOURCES    Unable to allocate memory.
 | |
|   EFI_ABORTED             An misc error occurred.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   INT8              *Ptrx;
 | |
|   INT8              *Pend;
 | |
|   INT8              *EvaluationStack;
 | |
|   INT8              *StackPtr;
 | |
|   INT8              *Buffer;
 | |
|   INT8              Line[LINESIZE];
 | |
|   UINTN             Index;
 | |
|   UINTN             OutFileSize;
 | |
|   UINTN             FileSize;
 | |
|   UINTN             Results;
 | |
|   BOOLEAN           NotDone;
 | |
|   BOOLEAN           Before_Flag;
 | |
|   BOOLEAN           After_Flag;
 | |
|   BOOLEAN           Dep_Flag;
 | |
|   BOOLEAN           SOR_Flag;
 | |
|   EFI_GUID          Guid;
 | |
|   UINTN             ArgCountParsed;
 | |
|   DEPENDENCY_OPCODE Opcode;
 | |
| 
 | |
|   Before_Flag = FALSE;
 | |
|   After_Flag  = FALSE;
 | |
|   Dep_Flag    = FALSE;
 | |
|   SOR_Flag    = FALSE;
 | |
| 
 | |
|   memset (Line, 0, LINESIZE);
 | |
| 
 | |
|   OutFileSize     = 0;
 | |
| 
 | |
|   EvaluationStack = (INT8 *) malloc (EVAL_STACK_SIZE);
 | |
| 
 | |
|   if (EvaluationStack != NULL) {
 | |
|     StackPtr = EvaluationStack;
 | |
|   } else {
 | |
|     printf ("Unable to allocate memory to EvaluationStack - Out of resources\n");
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Results = (UINTN) fseek (InFile, 0, SEEK_END);
 | |
| 
 | |
|   if (Results != 0) {
 | |
|     printf ("FSEEK failed - Aborted\n");
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   FileSize = ftell (InFile);
 | |
| 
 | |
|   if (FileSize == -1L) {
 | |
|     printf ("FTELL failed - Aborted\n");
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   Buffer = (INT8 *) malloc (FileSize + BUFFER_SIZE);
 | |
| 
 | |
|   if (Buffer == NULL) {
 | |
|     printf ("Unable to allocate memory to Buffer - Out of resources\n");
 | |
|     free (EvaluationStack);
 | |
| 
 | |
|     Results = (UINTN) fclose (InFile);
 | |
|     if (Results != 0) {
 | |
|       printf ("FCLOSE failed\n");
 | |
|     }
 | |
| 
 | |
|     Results = (UINTN) fclose (OutFile);
 | |
|     if (Results != 0) {
 | |
|       printf ("FCLOSE failed\n");
 | |
|     }
 | |
| 
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Results = (UINTN) fseek (InFile, 0, SEEK_SET);
 | |
| 
 | |
|   if (Results != 0) {
 | |
|     printf ("FSEEK failed - Aborted\n");
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   memset (Buffer, 0, FileSize + BUFFER_SIZE);
 | |
|   fread (Buffer, FileSize, 1, InFile);
 | |
| 
 | |
|   Ptrx    = Buffer;
 | |
|   Pend    = Ptrx + FileSize - strlen (DEPENDENCY_END);
 | |
|   Index   = FileSize;
 | |
| 
 | |
|   NotDone = TRUE;
 | |
|   while ((Index--) && NotDone) {
 | |
| 
 | |
|     if (strncmp (Pend, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) {
 | |
|       NotDone = FALSE;
 | |
|     } else {
 | |
|       Pend--;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (NotDone) {
 | |
|     printf ("Couldn't find end string %s\n", DEPENDENCY_END);
 | |
| 
 | |
|     Results = (UINTN) fclose (InFile);
 | |
|     if (Results != 0) {
 | |
|       printf ("FCLOSE failed\n");
 | |
|     }
 | |
| 
 | |
|     Results = (UINTN) fclose (OutFile);
 | |
|     if (Results != 0) {
 | |
|       printf ("FCLOSE failed\n");
 | |
|     }
 | |
| 
 | |
|     free (Buffer);
 | |
|     free (EvaluationStack);
 | |
| 
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Index   = FileSize;
 | |
| 
 | |
|   NotDone = TRUE;
 | |
|   while ((Index--) && NotDone) {
 | |
| 
 | |
|     if (strncmp (Ptrx, DEPENDENCY_START, strlen (DEPENDENCY_START)) == 0) {
 | |
|       Ptrx += sizeof (DEPENDENCY_START);
 | |
|       NotDone = FALSE;
 | |
|       //
 | |
|       // BUGBUG -- should Index be decremented by sizeof(DEPENDENCY_START)?
 | |
|       //
 | |
|     } else {
 | |
|       Ptrx++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (NotDone) {
 | |
|     printf ("Couldn't find start string %s\n", DEPENDENCY_START);
 | |
| 
 | |
|     Results = (UINTN) fclose (InFile);
 | |
|     if (Results != 0) {
 | |
|       printf ("FCLOSE failed\n");
 | |
|     }
 | |
| 
 | |
|     Results = (UINTN) fclose (OutFile);
 | |
|     if (Results != 0) {
 | |
|       printf ("FCLOSE failed\n");
 | |
|     }
 | |
| 
 | |
|     free (Buffer);
 | |
|     free (EvaluationStack);
 | |
| 
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   //
 | |
|   //  validate the syntax of expression
 | |
|   //
 | |
|   if (!ParseDepex (Ptrx, Pend - Ptrx - 1)) {
 | |
|     printf ("The syntax of expression is wrong\n");
 | |
| 
 | |
|     Results = (UINTN) fclose (InFile);
 | |
|     if (Results != 0) {
 | |
|       printf ("FCLOSE failed\n");
 | |
|     }
 | |
| 
 | |
|     Results = (UINTN) fclose (OutFile);
 | |
|     if (Results != 0) {
 | |
|       printf ("FCLOSE failed\n");
 | |
|     }
 | |
| 
 | |
|     free (Buffer);
 | |
|     free (EvaluationStack);
 | |
| 
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   NotDone = TRUE;
 | |
| 
 | |
|   while ((Index--) && NotDone) {
 | |
| 
 | |
|     if (*Ptrx == ' ') {
 | |
|       Ptrx++;
 | |
|     } else if (*Ptrx == '\n' || *Ptrx == '\r') {
 | |
|       Ptrx++;
 | |
|     } else if (strncmp (Ptrx, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) {
 | |
|       //
 | |
|       //  Checks for some invalid dependencies
 | |
|       //
 | |
|       if (Before_Flag) {
 | |
| 
 | |
|         printf ("A BEFORE operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (After_Flag) {
 | |
| 
 | |
|         printf ("An AFTER operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (SOR_Flag) {
 | |
| 
 | |
|         printf ("Another SOR operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (Dep_Flag) {
 | |
| 
 | |
|         printf ("The Schedule On Request - SOR operator must be the first operator following DEPENDENCY_START\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else {
 | |
|         //
 | |
|         //  BUGBUG - This was not in the spec but is in the CORE code
 | |
|         //  An OPERATOR_SOR has to be first - following the DEPENDENCY_START
 | |
|         //
 | |
|         fputc (EFI_DEP_SOR, OutFile);
 | |
|         OutFileSize++;
 | |
|         Ptrx += sizeof (OPERATOR_SOR);
 | |
|         SOR_Flag = TRUE;
 | |
| 
 | |
|       }
 | |
|     } else if (strncmp (Ptrx, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) {
 | |
|       //
 | |
|       //  Checks for some invalid dependencies
 | |
|       //
 | |
|       if (Before_Flag) {
 | |
| 
 | |
|         printf ("Another BEFORE operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (After_Flag) {
 | |
| 
 | |
|         printf ("An AFTER operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (SOR_Flag) {
 | |
| 
 | |
|         printf ("A SOR operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (Dep_Flag) {
 | |
| 
 | |
|         printf ("The BEFORE operator must be the first operator following DEPENDENCY_START\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else {
 | |
|         fputc (EFI_DEP_BEFORE, OutFile);
 | |
|         OutFileSize++;
 | |
|         Ptrx += sizeof (OPERATOR_BEFORE);
 | |
|         Before_Flag = TRUE;
 | |
|       }
 | |
|     } else if (strncmp (Ptrx, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) {
 | |
|       //
 | |
|       //  Checks for some invalid dependencies
 | |
|       //
 | |
|       if (Before_Flag) {
 | |
| 
 | |
|         printf ("A BEFORE operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (After_Flag) {
 | |
| 
 | |
|         printf ("Another AFTER operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (SOR_Flag) {
 | |
| 
 | |
|         printf ("A SOR operator was detected.\n");
 | |
|         printf ("There can only be one SOR or one AFTER or one BEFORE operator\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else if (Dep_Flag) {
 | |
| 
 | |
|         printf ("The AFTER operator must be the first operator following DEPENDENCY_START\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|       } else {
 | |
|         fputc (EFI_DEP_AFTER, OutFile);
 | |
|         OutFileSize++;
 | |
|         Ptrx += sizeof (OPERATOR_AFTER);
 | |
|         Dep_Flag    = TRUE;
 | |
|         After_Flag  = TRUE;
 | |
|       }
 | |
|     } else if (strncmp (Ptrx, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) {
 | |
|       while (StackPtr != EvaluationStack) {
 | |
|         Opcode = PopOpCode ((VOID **) &StackPtr);
 | |
|         if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {
 | |
|           fputc (Opcode, OutFile);
 | |
|           OutFileSize++;
 | |
|         } else {
 | |
|           PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       PushOpCode ((VOID **) &StackPtr, EFI_DEP_AND);
 | |
|       Ptrx += sizeof (OPERATOR_AND);
 | |
|       Dep_Flag = TRUE;
 | |
| 
 | |
|     } else if (strncmp (Ptrx, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) {
 | |
|       while (StackPtr != EvaluationStack) {
 | |
|         Opcode = PopOpCode ((VOID **) &StackPtr);
 | |
|         if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {
 | |
|           fputc (Opcode, OutFile);
 | |
|           OutFileSize++;
 | |
|         } else {
 | |
|           PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       PushOpCode ((VOID **) &StackPtr, EFI_DEP_OR);
 | |
|       Ptrx += sizeof (OPERATOR_OR);
 | |
|       Dep_Flag = TRUE;
 | |
| 
 | |
|     } else if (strncmp (Ptrx, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) {
 | |
|       while (StackPtr != EvaluationStack) {
 | |
|         Opcode = PopOpCode ((VOID **) &StackPtr);
 | |
|         if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {
 | |
|           fputc (Opcode, OutFile);
 | |
|           OutFileSize++;
 | |
|         } else {
 | |
|           PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       PushOpCode ((VOID **) &StackPtr, EFI_DEP_NOT);
 | |
|       Ptrx += sizeof (OPERATOR_NOT);
 | |
|       Dep_Flag = TRUE;
 | |
| 
 | |
|     } else if (*Ptrx == '\t') {
 | |
| 
 | |
|       printf ("File contains tabs. This violates the coding standard\n");
 | |
|       return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|     } else if (*Ptrx == '\n') {
 | |
|       //
 | |
|       // Skip the newline character in the file
 | |
|       //
 | |
|       Ptrx++;
 | |
| 
 | |
|     } else if (strncmp (Ptrx, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) {
 | |
|       PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS);
 | |
| 
 | |
|       Ptrx += strlen (OPERATOR_LEFT_PARENTHESIS);
 | |
|       Dep_Flag = TRUE;
 | |
| 
 | |
|     } else if (strncmp (Ptrx, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) {
 | |
|       while (StackPtr != EvaluationStack) {
 | |
|         Opcode = PopOpCode ((VOID **) &StackPtr);
 | |
|         if (Opcode != DXE_DEP_LEFT_PARENTHESIS) {
 | |
|           fputc (Opcode, OutFile);
 | |
|           OutFileSize++;
 | |
|         } else {
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       Ptrx += strlen (OPERATOR_RIGHT_PARENTHESIS);
 | |
|       Dep_Flag = TRUE;
 | |
| 
 | |
|     } else if (strncmp (Ptrx, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) {
 | |
| 
 | |
|       fputc (EFI_DEP_TRUE, OutFile);
 | |
| 
 | |
|       OutFileSize++;
 | |
| 
 | |
|       //
 | |
|       // OutFileSize += sizeof (EFI_DEP_TRUE);
 | |
|       //
 | |
|       Dep_Flag = TRUE;
 | |
| 
 | |
|       Ptrx += strlen (OPERATOR_TRUE);
 | |
| 
 | |
|     } else if (strncmp (Ptrx, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) {
 | |
| 
 | |
|       fputc (EFI_DEP_FALSE, OutFile);
 | |
| 
 | |
|       OutFileSize++;
 | |
| 
 | |
|       //
 | |
|       // OutFileSize += sizeof (EFI_DEP_FALSE);
 | |
|       //
 | |
|       Dep_Flag = TRUE;
 | |
| 
 | |
|       Ptrx += strlen (OPERATOR_FALSE);
 | |
| 
 | |
|     } else if (*Ptrx == '{') {
 | |
|       Ptrx++;
 | |
| 
 | |
|       if (*Ptrx == ' ') {
 | |
|         Ptrx++;
 | |
|       }
 | |
| 
 | |
|       {
 | |
|         int byte_index;
 | |
|         // This is an array of UINT32s. sscanf will trash memory
 | |
|         // if you try to read into a UINT8 with a %x formatter.
 | |
|         UINT32 Guid_Data4[8];
 | |
| 
 | |
|         ArgCountParsed = sscanf (
 | |
|                          Ptrx,
 | |
|             "%x, %x, %x, { %x, %x, %x, %x, %x, %x, %x, %x }",
 | |
|                          &Guid.Data1,
 | |
|                          &Guid.Data2,
 | |
|                          &Guid.Data3,
 | |
|                          &Guid_Data4[0],
 | |
|                          &Guid_Data4[1],
 | |
|                          &Guid_Data4[2],
 | |
|                          &Guid_Data4[3],
 | |
|                          &Guid_Data4[4],
 | |
|                          &Guid_Data4[5],
 | |
|                          &Guid_Data4[6],
 | |
|                          &Guid_Data4[7]
 | |
|                          );
 | |
|         
 | |
|         // Now we can copy the 32 bit ints into the GUID.
 | |
|         for (byte_index=0; byte_index<8; byte_index++) {
 | |
|           Guid.Data4[byte_index] = (UINT8) Guid_Data4[byte_index];
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (ArgCountParsed != 11) {
 | |
|         printf ("We have found an illegal GUID\n");
 | |
|         printf ("Fix your depex\n");
 | |
|         exit (-1);
 | |
|       }
 | |
| 
 | |
|       while (*Ptrx != '}') {
 | |
|         Ptrx++;
 | |
|       }
 | |
| 
 | |
|     Ptrx++;
 | |
|       while (*Ptrx != '}') {
 | |
|         Ptrx++;
 | |
|       }
 | |
|     //
 | |
|       // Absorb the closing }
 | |
|       //
 | |
|       Ptrx++;
 | |
| 
 | |
|       //
 | |
|       // Don't provide a PUSH Opcode for the Before and After case
 | |
|       //
 | |
|       if ((!Before_Flag) && (!After_Flag)) {
 | |
|         fputc (EFI_DEP_PUSH, OutFile);
 | |
|         OutFileSize++;
 | |
|       }
 | |
| 
 | |
|       fwrite (&Guid, sizeof (EFI_GUID), 1, OutFile);
 | |
| 
 | |
|       OutFileSize += sizeof (EFI_GUID);
 | |
|       Dep_Flag = TRUE;
 | |
| 
 | |
|     } else if (strncmp (Ptrx, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) {
 | |
|       NotDone = FALSE;
 | |
|     } else {
 | |
|       //
 | |
|       // Not a valid construct. Null terminate somewhere out there and
 | |
|       // print an error message.
 | |
|       //
 | |
|       *(Ptrx + 20) = 0;
 | |
|       printf (TOOL_NAME " ERROR: Unrecognized input at: \"%s\"...\n", Ptrx);
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   //  DRAIN();
 | |
|   //
 | |
|   while (StackPtr != EvaluationStack) {
 | |
|     fputc (PopOpCode ((VOID **) &StackPtr), OutFile);
 | |
|     OutFileSize++;
 | |
|   }
 | |
| 
 | |
|   if (OutFileSize == 0) {
 | |
|     printf ("Grammer contains no operators or constants\n");
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   fputc (EFI_DEP_END, OutFile);
 | |
| 
 | |
|   OutFileSize++;
 | |
| 
 | |
|   //
 | |
|   //  Checks for invalid padding values
 | |
|   //
 | |
|   if (Padding < 0) {
 | |
| 
 | |
|     printf ("The inputted padding value was %d\n", Padding);
 | |
|     printf ("The optional padding value can not be less than ZERO\n");
 | |
|     return EFI_INVALID_PARAMETER;
 | |
| 
 | |
|   } else if (Padding > 0) {
 | |
| 
 | |
|     while ((OutFileSize % Padding) != 0) {
 | |
| 
 | |
|       fputc (' ', OutFile);
 | |
|       OutFileSize++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Results = (UINTN) fclose (InFile);
 | |
|   if (Results != 0) {
 | |
|     printf ("FCLOSE failed\n");
 | |
|   }
 | |
| 
 | |
|   Results = (UINTN) fclose (OutFile);
 | |
|   if (Results != 0) {
 | |
|     printf ("FCLOSE failed\n");
 | |
|   }
 | |
| 
 | |
|   free (Buffer);
 | |
|   free (EvaluationStack);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| } // End GenerateDependencyExpression function
 | |
| 
 | |
| int
 | |
| main (
 | |
|   IN UINTN argc,
 | |
|   IN CHAR8 *argv[]
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Parse user entries.  Print some rudimentary help
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   argc    The count of input arguments
 | |
|   argv    The input arguments string array
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS             The function completed successfully.
 | |
|   EFI_INVALID_PARAMETER   One of the input parameters was invalid or one of the parameters in the text file was invalid.
 | |
|   EFI_OUT_OF_RESOURCES    Unable to allocate memory.
 | |
|   EFI_ABORTED             Unable to open/create a file or a misc error.
 | |
| 
 | |
| --*/
 | |
| // TODO:    ] - add argument and description to function comment
 | |
| {
 | |
|   FILE    *OutFile;
 | |
|   FILE    *InFile;
 | |
|   UINT8   Padding;
 | |
|   UINTN   Index;
 | |
|   BOOLEAN Input_Flag;
 | |
|   BOOLEAN Output_Flag;
 | |
|   BOOLEAN Pad_Flag;
 | |
| 
 | |
|   InFile      = NULL;
 | |
|   OutFile     = NULL;
 | |
|   Padding     = 0;
 | |
|   Input_Flag  = FALSE;
 | |
|   Output_Flag = FALSE;
 | |
|   Pad_Flag    = FALSE;
 | |
| 
 | |
|   if (argc < 5) {
 | |
|     printf ("Not enough arguments\n");
 | |
|     PrintGenDepexUsageInfo ();
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   for (Index = 1; Index < argc - 1; Index++) {
 | |
| 
 | |
|     if ((strcmp (argv[Index], "-I") == 0) || (strcmp (argv[Index], "-i") == 0)) {
 | |
| 
 | |
|       if (!Input_Flag) {
 | |
| 
 | |
|         InFile      = fopen (argv[Index + 1], "rb");
 | |
|         Input_Flag  = TRUE;
 | |
| 
 | |
|       } else {
 | |
|         printf ("GenDepex only allows one INPUT (-I) argument\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((strcmp (argv[Index], "-O") == 0) || (strcmp (argv[Index], "-o") == 0)) {
 | |
| 
 | |
|       if (!Output_Flag) {
 | |
| 
 | |
|         OutFile     = fopen (argv[Index + 1], "wb");
 | |
|         Output_Flag = TRUE;
 | |
| 
 | |
|       } else {
 | |
|         printf ("GenDepex only allows one OUTPUT (-O) argument\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|     } else if ((strcmp (argv[Index], "-P") == 0) || (strcmp (argv[Index], "-p") == 0)) {
 | |
| 
 | |
|       if (!Pad_Flag) {
 | |
| 
 | |
|         Padding   = (UINT8) atoi (argv[Index + 1]);
 | |
|         Pad_Flag  = TRUE;
 | |
| 
 | |
|       } else {
 | |
|         printf ("GenDepex only allows one PADDING (-P) argument\n");
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   PrintGenDepexUtilityInfo ();
 | |
| 
 | |
|   if (InFile == NULL) {
 | |
|     printf ("Can not open <INFILE> for reading.\n");
 | |
|     PrintGenDepexUsageInfo ();
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   if (OutFile == NULL) {
 | |
|     printf ("Can not open <OUTFILE> for writting.\n");
 | |
|     PrintGenDepexUsageInfo ();
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   return GenerateDependencyExpression (InFile, OutFile, Padding);
 | |
| }
 |