git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2159 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			935 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			935 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2004-2006, 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
 | 
						|
Version (
 | 
						|
  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-2006 Intel Corporation. All rights reserved.\n");
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
Usage (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Displays the utility usage syntax to STDOUT.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  Version();
 | 
						|
  printf (
 | 
						|
    "\nUsage: %s -I InputFile -O OutputFile [-P <Optional Boundary for padding up>] \n",
 | 
						|
    UTILITY_NAME
 | 
						|
    );
 | 
						|
  printf ("  Where:\n");
 | 
						|
  printf ("    InputFile is the input pre-processed dependency text files name.\n");
 | 
						|
  printf ("    OutputFile 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 < 1) {
 | 
						|
    Usage();
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
 | 
						|
      (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
 | 
						|
    Usage();
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
 | 
						|
    Version();
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (argc < 5) {
 | 
						|
    printf ("Not enough arguments\n");
 | 
						|
    Usage();
 | 
						|
    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;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (InFile == NULL) {
 | 
						|
    printf ("Can not open <INFILE> for reading.\n");
 | 
						|
    Usage();
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (OutFile == NULL) {
 | 
						|
    printf ("Can not open <OUTFILE> for writting.\n");
 | 
						|
    Usage();
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return GenerateDependencyExpression (InFile, OutFile, Padding);
 | 
						|
}
 |