+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
-\r
- dependency.c\r
-\r
-Abstract:\r
-\r
- PEI Dispatcher Dependency Evaluator\r
-\r
- This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine\r
- if a driver can be scheduled for execution. The criteria for\r
- schedulability is that the dependency expression is satisfied.\r
- \r
---*/\r
-\r
-#include <PeiMain.h>\r
-#include "dependency.h"\r
-\r
-STATIC\r
-BOOLEAN\r
-IsPpiInstalled (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN EVAL_STACK_ENTRY *Stack\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This routine determines if a PPI has been installed.\r
- The truth value of a GUID is determined by if the PPI has\r
- been published and can be queried from the PPI database.\r
-\r
-Arguments:\r
- PeiServices - The PEI core services table.\r
- Stack - Reference to EVAL_STACK_ENTRY that contains PPI GUID to check\r
-\r
-Returns:\r
-\r
- True if the PPI is already installed.\r
- False if the PPI has yet to be installed.\r
-\r
---*/\r
-{\r
- VOID *PeiInstance;\r
- EFI_STATUS Status;\r
- EFI_GUID PpiGuid;\r
- \r
- //\r
- // If there is no GUID to evaluate, just return current result on stack.\r
- //\r
- if (Stack->Operator == NULL) {\r
- return Stack->Result;\r
- }\r
- \r
- //\r
- // Copy the Guid into a locale variable so that there are no\r
- // possibilities of alignment faults for cross-compilation \r
- // environments such as Intel?Itanium(TM).\r
- //\r
- CopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID));\r
-\r
- //\r
- // Check if the PPI is installed.\r
- //\r
- Status = PeiServicesLocatePpi(\r
- &PpiGuid, // GUID\r
- 0, // INSTANCE\r
- NULL, // EFI_PEI_PPI_DESCRIPTOR\r
- &PeiInstance // PPI\r
- );\r
-\r
- if (EFI_ERROR(Status)) {\r
- return FALSE;\r
- }\r
- \r
- return TRUE;\r
-}\r
-\r
-\r
-EFI_STATUS\r
-PeimDispatchReadiness (\r
- IN EFI_PEI_SERVICES **PeiServices,\r
- IN VOID *DependencyExpression,\r
- OUT BOOLEAN *Runnable\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- This is the POSTFIX version of the dependency evaluator. When a\r
- PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on\r
- the evaluation stack. When that entry is poped from the evaluation\r
- stack, the PPI is checked if it is installed. This method allows\r
- some time savings as not all PPIs must be checked for certain\r
- operation types (AND, OR).\r
-\r
-Arguments:\r
-\r
- PeiServices - Calling context.\r
-\r
- DependencyExpression - Pointer to a dependency expression. The Grammar adheres to \r
- the BNF described above and is stored in postfix notation.\r
- Runnable - is True if the driver can be scheduled and False if the driver \r
- cannot be scheduled. This is the value that the schedulers \r
- should use for deciding the state of the driver.\r
-\r
-Returns:\r
-\r
- Status = EFI_SUCCESS if it is a well-formed Grammar\r
- EFI_INVALID_PARAMETER if the dependency expression overflows\r
- the evaluation stack\r
- EFI_INVALID_PARAMETER if the dependency expression underflows\r
- the evaluation stack\r
- EFI_INVALID_PARAMETER if the dependency expression is not a\r
- well-formed Grammar.\r
---*/\r
-{\r
- DEPENDENCY_EXPRESSION_OPERAND *Iterator;\r
- EVAL_STACK_ENTRY *StackPtr;\r
- EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE];\r
-\r
- Iterator = DependencyExpression;\r
- *Runnable = FALSE;\r
-\r
- StackPtr = &EvalStack[0];\r
-\r
- while (TRUE) {\r
-\r
- switch (*(Iterator++)) {\r
- \r
- //\r
- // For performance reason we put the frequently used items in front of \r
- // the rarely used items\r
- //\r
- \r
- case (EFI_DEP_PUSH):\r
- //\r
- // Check to make sure the dependency grammar doesn't overflow the\r
- // EvalStack on the push\r
- //\r
- if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Push the pointer to the PUSH opcode operator (pointer to PPI GUID)\r
- // We will evaluate if the PPI is insalled on the POP operation.\r
- //\r
- StackPtr->Operator = (VOID *) Iterator;\r
- Iterator = Iterator + sizeof (EFI_GUID);\r
- StackPtr++;\r
- break;\r
-\r
- case (EFI_DEP_AND): \r
- case (EFI_DEP_OR): \r
- //\r
- // Check to make sure the dependency grammar doesn't underflow the\r
- // EvalStack on the two POPs for the AND operation. Don't need to\r
- // check for the overflow on PUSHing the result since we already\r
- // did two POPs.\r
- //\r
- if (StackPtr < &EvalStack[2]) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Evaluate the first POPed operator only. If the operand is\r
- // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the\r
- // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE,\r
- // we don't need to check the second operator, and the result will be\r
- // evaluation of the POPed operator. Otherwise, don't POP the second\r
- // operator since it will now evaluate to the final result on the\r
- // next operand that causes a POP.\r
- // \r
- StackPtr--;\r
- //\r
- // Iterator has increased by 1 after we retrieve the operand, so here we \r
- // should get the value pointed by (Iterator - 1), in order to obtain the \r
- // same operand.\r
- //\r
- if (*(Iterator - 1) == EFI_DEP_AND) {\r
- if (!(IsPpiInstalled (PeiServices, StackPtr))) {\r
- (StackPtr-1)->Result = FALSE;\r
- (StackPtr-1)->Operator = NULL;\r
- }\r
- } else {\r
- if (IsPpiInstalled (PeiServices, StackPtr)) {\r
- (StackPtr-1)->Result = TRUE;\r
- (StackPtr-1)->Operator = NULL;\r
- }\r
- }\r
- break;\r
- \r
- case (EFI_DEP_END):\r
- StackPtr--;\r
- //\r
- // Check to make sure EvalStack is balanced. If not, then there is\r
- // an error in the dependency grammar, so return EFI_INVALID_PARAMETER.\r
- //\r
- if (StackPtr != &EvalStack[0]) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- *Runnable = IsPpiInstalled (PeiServices, StackPtr);\r
- return EFI_SUCCESS;\r
- break;\r
-\r
- case (EFI_DEP_NOT): \r
- //\r
- // Check to make sure the dependency grammar doesn't underflow the\r
- // EvalStack on the POP for the NOT operation. Don't need to\r
- // check for the overflow on PUSHing the result since we already\r
- // did a POP.\r
- //\r
- if (StackPtr < &EvalStack[1]) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1));\r
- (StackPtr-1)->Operator = NULL;\r
- break;\r
-\r
- case (EFI_DEP_TRUE):\r
- case (EFI_DEP_FALSE):\r
- //\r
- // Check to make sure the dependency grammar doesn't overflow the\r
- // EvalStack on the push\r
- //\r
- if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Iterator has increased by 1 after we retrieve the operand, so here we \r
- // should get the value pointed by (Iterator - 1), in order to obtain the \r
- // same operand.\r
- //\r
- if (*(Iterator - 1) == EFI_DEP_TRUE) {\r
- StackPtr->Result = TRUE;\r
- } else {\r
- StackPtr->Result = FALSE;\r
- }\r
- StackPtr->Operator = NULL;\r
- StackPtr++;\r
- break;\r
-\r
- default:\r
- //\r
- // The grammar should never arrive here\r
- //\r
- return EFI_INVALID_PARAMETER;\r
- break;\r
- }\r
- }\r
-}\r