summaryrefslogtreecommitdiff
path: root/Platform/BroxtonPlatformPkg/Common/SampleCode/MdeModulePkg/Core/Pei/Dependency/Dependency.c
diff options
context:
space:
mode:
Diffstat (limited to 'Platform/BroxtonPlatformPkg/Common/SampleCode/MdeModulePkg/Core/Pei/Dependency/Dependency.c')
-rw-r--r--Platform/BroxtonPlatformPkg/Common/SampleCode/MdeModulePkg/Core/Pei/Dependency/Dependency.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/Platform/BroxtonPlatformPkg/Common/SampleCode/MdeModulePkg/Core/Pei/Dependency/Dependency.c b/Platform/BroxtonPlatformPkg/Common/SampleCode/MdeModulePkg/Core/Pei/Dependency/Dependency.c
new file mode 100644
index 0000000000..e71566b5a7
--- /dev/null
+++ b/Platform/BroxtonPlatformPkg/Common/SampleCode/MdeModulePkg/Core/Pei/Dependency/Dependency.c
@@ -0,0 +1,253 @@
+/** @file
+ PEI Dispatcher Dependency Evaluator
+
+ This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine
+ if a driver can be scheduled for execution. The criteria for
+ schedulability is that the dependency expression is satisfied.
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+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.
+
+**/
+
+#include "PeiMain.h"
+#include "Dependency.h"
+
+/**
+
+ This routine determines if a PPI has been installed.
+ The truth value of a GUID is determined by if the PPI has
+ been published and can be queried from the PPI database.
+
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param Stack Reference to EVAL_STACK_ENTRY that contains PPI GUID to check
+
+ @retval TRUE if the PPI is already installed.
+ @retval FALSE if the PPI has yet to be installed.
+
+**/
+BOOLEAN
+IsPpiInstalled (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EVAL_STACK_ENTRY *Stack
+ )
+{
+ VOID *PeiInstance;
+ EFI_STATUS Status;
+ EFI_GUID PpiGuid;
+
+ //
+ // If there is no GUID to evaluate, just return current result on stack.
+ //
+ if (Stack->Operator == NULL) {
+ return Stack->Result;
+ }
+
+ //
+ // Copy the Guid into a locale variable so that there are no
+ // possibilities of alignment faults for cross-compilation
+ // environments such as Intel?Itanium(TM).
+ //
+ CopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID));
+
+ //
+ // Check if the PPI is installed.
+ //
+ Status = PeiServicesLocatePpi(
+ &PpiGuid, // GUID
+ 0, // INSTANCE
+ NULL, // EFI_PEI_PPI_DESCRIPTOR
+ &PeiInstance // PPI
+ );
+
+ if (EFI_ERROR(Status)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+
+ This is the POSTFIX version of the dependency evaluator. When a
+ PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on
+ the evaluation stack. When that entry is poped from the evaluation
+ stack, the PPI is checked if it is installed. This method allows
+ some time savings as not all PPIs must be checked for certain
+ operation types (AND, OR).
+
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
+ @param DependencyExpression Pointer to a dependency expression. The Grammar adheres to
+ the BNF described above and is stored in postfix notation.
+
+ @retval TRUE if it is a well-formed Grammar
+ @retval FALSE if the dependency expression overflows the evaluation stack
+ if the dependency expression underflows the evaluation stack
+ if the dependency expression is not a well-formed Grammar.
+
+**/
+BOOLEAN
+PeimDispatchReadiness (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN VOID *DependencyExpression
+ )
+{
+ DEPENDENCY_EXPRESSION_OPERAND *Iterator;
+ EVAL_STACK_ENTRY *StackPtr;
+ EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE];
+
+ Iterator = DependencyExpression;
+
+ StackPtr = EvalStack;
+
+ while (TRUE) {
+
+ switch (*(Iterator++)) {
+
+ //
+ // For performance reason we put the frequently used items in front of
+ // the rarely used items
+ //
+
+ case (EFI_DEP_PUSH):
+ //
+ // Check to make sure the dependency grammar doesn't overflow the
+ // EvalStack on the push
+ //
+ if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {
+ DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
+ return FALSE;
+ }
+
+ //
+ // Push the pointer to the PUSH opcode operator (pointer to PPI GUID)
+ // We will evaluate if the PPI is insalled on the POP operation.
+ //
+ StackPtr->Operator = (VOID *) Iterator;
+ Iterator = Iterator + sizeof (EFI_GUID);
+ DEBUG ((DEBUG_DISPATCH, " PUSH GUID(%g) = %a\n", StackPtr->Operator, IsPpiInstalled (PeiServices, StackPtr) ? "TRUE" : "FALSE"));
+ StackPtr++;
+ break;
+
+ case (EFI_DEP_AND):
+ case (EFI_DEP_OR):
+ if (*(Iterator - 1) == EFI_DEP_AND) {
+ DEBUG ((DEBUG_DISPATCH, " AND\n"));
+ } else {
+ DEBUG ((DEBUG_DISPATCH, " OR\n"));
+ }
+ //
+ // Check to make sure the dependency grammar doesn't underflow the
+ // EvalStack on the two POPs for the AND operation. Don't need to
+ // check for the overflow on PUSHing the result since we already
+ // did two POPs.
+ //
+ if (StackPtr < &EvalStack[2]) {
+ DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
+ return FALSE;
+ }
+
+ //
+ // Evaluate the first POPed operator only. If the operand is
+ // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the
+ // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE,
+ // we don't need to check the second operator, and the result will be
+ // evaluation of the POPed operator. Otherwise, don't POP the second
+ // operator since it will now evaluate to the final result on the
+ // next operand that causes a POP.
+ //
+ StackPtr--;
+ //
+ // Iterator has increased by 1 after we retrieve the operand, so here we
+ // should get the value pointed by (Iterator - 1), in order to obtain the
+ // same operand.
+ //
+ if (*(Iterator - 1) == EFI_DEP_AND) {
+ if (!(IsPpiInstalled (PeiServices, StackPtr))) {
+ (StackPtr-1)->Result = FALSE;
+ (StackPtr-1)->Operator = NULL;
+ }
+ } else {
+ if (IsPpiInstalled (PeiServices, StackPtr)) {
+ (StackPtr-1)->Result = TRUE;
+ (StackPtr-1)->Operator = NULL;
+ }
+ }
+ break;
+
+ case (EFI_DEP_END):
+ DEBUG ((DEBUG_DISPATCH, " END\n"));
+ StackPtr--;
+ //
+ // Check to make sure EvalStack is balanced. If not, then there is
+ // an error in the dependency grammar, so return EFI_INVALID_PARAMETER.
+ //
+ if (StackPtr != &EvalStack[0]) {
+ DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
+ return FALSE;
+ }
+ DEBUG ((DEBUG_DISPATCH, " RESULT = %a\n", IsPpiInstalled (PeiServices, StackPtr) ? "TRUE" : "FALSE"));
+ return IsPpiInstalled (PeiServices, StackPtr);
+
+ case (EFI_DEP_NOT):
+ DEBUG ((DEBUG_DISPATCH, " NOT\n"));
+ //
+ // Check to make sure the dependency grammar doesn't underflow the
+ // EvalStack on the POP for the NOT operation. Don't need to
+ // check for the overflow on PUSHing the result since we already
+ // did a POP.
+ //
+ if (StackPtr < &EvalStack[1]) {
+ DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
+ return FALSE;
+ }
+ (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1));
+ (StackPtr-1)->Operator = NULL;
+ break;
+
+ case (EFI_DEP_TRUE):
+ case (EFI_DEP_FALSE):
+ if (*(Iterator - 1) == EFI_DEP_TRUE) {
+ DEBUG ((DEBUG_DISPATCH, " TRUE\n"));
+ } else {
+ DEBUG ((DEBUG_DISPATCH, " FALSE\n"));
+ }
+ //
+ // Check to make sure the dependency grammar doesn't overflow the
+ // EvalStack on the push
+ //
+ if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {
+ DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));
+ return FALSE;
+ }
+ //
+ // Iterator has increased by 1 after we retrieve the operand, so here we
+ // should get the value pointed by (Iterator - 1), in order to obtain the
+ // same operand.
+ //
+ if (*(Iterator - 1) == EFI_DEP_TRUE) {
+ StackPtr->Result = TRUE;
+ } else {
+ StackPtr->Result = FALSE;
+ }
+ StackPtr->Operator = NULL;
+ StackPtr++;
+ break;
+
+ default:
+ DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Invalid opcode)\n"));
+ //
+ // The grammar should never arrive here
+ //
+ return FALSE;
+ }
+ }
+}