mirror of https://github.com/acidanthera/audk.git
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);
|
|
}
|