]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Dependency/Dependency.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Dependency / Dependency.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 PEI Dispatcher Dependency Evaluator\r
3\r
4 This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine\r
5 if a driver can be scheduled for execution. The criteria for\r
6 schedulability is that the dependency expression is satisfied.\r
192f6d4c 7\r
d1102dba
LG
8Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9This program and the accompanying materials\r
10are licensed and made available under the terms and conditions of the BSD License\r
11which accompanies this distribution. The full text of the license may be found at\r
12http://opensource.org/licenses/bsd-license.php\r
13\r
14THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
192f6d4c 16\r
615c6dd0 17**/\r
192f6d4c 18\r
0d516397 19#include "PeiMain.h"\r
95770ed8 20#include "Dependency.h"\r
192f6d4c 21\r
b1f6a7c6 22/**\r
192f6d4c 23\r
24 This routine determines if a PPI has been installed.\r
25 The truth value of a GUID is determined by if the PPI has\r
26 been published and can be queried from the PPI database.\r
27\r
192f6d4c 28\r
ed299e3c 29 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
b1f6a7c6 30 @param Stack Reference to EVAL_STACK_ENTRY that contains PPI GUID to check\r
192f6d4c 31\r
b1f6a7c6 32 @retval TRUE if the PPI is already installed.\r
33 @retval FALSE if the PPI has yet to be installed.\r
192f6d4c 34\r
b1f6a7c6 35**/\r
36BOOLEAN\r
37IsPpiInstalled (\r
38 IN EFI_PEI_SERVICES **PeiServices,\r
39 IN EVAL_STACK_ENTRY *Stack\r
40 )\r
192f6d4c 41{\r
42 VOID *PeiInstance;\r
43 EFI_STATUS Status;\r
44 EFI_GUID PpiGuid;\r
d1102dba 45\r
192f6d4c 46 //\r
47 // If there is no GUID to evaluate, just return current result on stack.\r
48 //\r
49 if (Stack->Operator == NULL) {\r
50 return Stack->Result;\r
51 }\r
d1102dba 52\r
192f6d4c 53 //\r
54 // Copy the Guid into a locale variable so that there are no\r
d1102dba 55 // possibilities of alignment faults for cross-compilation\r
192f6d4c 56 // environments such as Intel?Itanium(TM).\r
57 //\r
58 CopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID));\r
59\r
60 //\r
61 // Check if the PPI is installed.\r
62 //\r
63 Status = PeiServicesLocatePpi(\r
64 &PpiGuid, // GUID\r
65 0, // INSTANCE\r
66 NULL, // EFI_PEI_PPI_DESCRIPTOR\r
67 &PeiInstance // PPI\r
68 );\r
69\r
70 if (EFI_ERROR(Status)) {\r
71 return FALSE;\r
72 }\r
d1102dba 73\r
192f6d4c 74 return TRUE;\r
75}\r
76\r
b1f6a7c6 77/**\r
192f6d4c 78\r
79 This is the POSTFIX version of the dependency evaluator. When a\r
80 PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on\r
81 the evaluation stack. When that entry is poped from the evaluation\r
82 stack, the PPI is checked if it is installed. This method allows\r
83 some time savings as not all PPIs must be checked for certain\r
84 operation types (AND, OR).\r
85\r
192f6d4c 86\r
ed299e3c 87 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
b1f6a7c6 88 @param DependencyExpression Pointer to a dependency expression. The Grammar adheres to\r
89 the BNF described above and is stored in postfix notation.\r
192f6d4c 90\r
b1f6a7c6 91 @retval TRUE if it is a well-formed Grammar\r
92 @retval FALSE if the dependency expression overflows the evaluation stack\r
93 if the dependency expression underflows the evaluation stack\r
94 if the dependency expression is not a well-formed Grammar.\r
192f6d4c 95\r
b1f6a7c6 96**/\r
97BOOLEAN\r
98PeimDispatchReadiness (\r
99 IN EFI_PEI_SERVICES **PeiServices,\r
100 IN VOID *DependencyExpression\r
101 )\r
192f6d4c 102{\r
103 DEPENDENCY_EXPRESSION_OPERAND *Iterator;\r
104 EVAL_STACK_ENTRY *StackPtr;\r
105 EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE];\r
106\r
107 Iterator = DependencyExpression;\r
192f6d4c 108\r
523f48e7 109 StackPtr = EvalStack;\r
192f6d4c 110\r
111 while (TRUE) {\r
112\r
113 switch (*(Iterator++)) {\r
d1102dba 114\r
192f6d4c 115 //\r
d1102dba 116 // For performance reason we put the frequently used items in front of\r
192f6d4c 117 // the rarely used items\r
118 //\r
d1102dba 119\r
192f6d4c 120 case (EFI_DEP_PUSH):\r
121 //\r
122 // Check to make sure the dependency grammar doesn't overflow the\r
123 // EvalStack on the push\r
124 //\r
125 if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {\r
6a55eea3 126 DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));\r
b0d803fe 127 return FALSE;\r
192f6d4c 128 }\r
129\r
130 //\r
131 // Push the pointer to the PUSH opcode operator (pointer to PPI GUID)\r
132 // We will evaluate if the PPI is insalled on the POP operation.\r
133 //\r
134 StackPtr->Operator = (VOID *) Iterator;\r
135 Iterator = Iterator + sizeof (EFI_GUID);\r
6a55eea3 136 DEBUG ((DEBUG_DISPATCH, " PUSH GUID(%g) = %a\n", StackPtr->Operator, IsPpiInstalled (PeiServices, StackPtr) ? "TRUE" : "FALSE"));\r
192f6d4c 137 StackPtr++;\r
138 break;\r
139\r
d1102dba
LG
140 case (EFI_DEP_AND):\r
141 case (EFI_DEP_OR):\r
6a55eea3 142 if (*(Iterator - 1) == EFI_DEP_AND) {\r
143 DEBUG ((DEBUG_DISPATCH, " AND\n"));\r
144 } else {\r
145 DEBUG ((DEBUG_DISPATCH, " OR\n"));\r
146 }\r
192f6d4c 147 //\r
148 // Check to make sure the dependency grammar doesn't underflow the\r
149 // EvalStack on the two POPs for the AND operation. Don't need to\r
150 // check for the overflow on PUSHing the result since we already\r
151 // did two POPs.\r
152 //\r
153 if (StackPtr < &EvalStack[2]) {\r
6a55eea3 154 DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));\r
b0d803fe 155 return FALSE;\r
192f6d4c 156 }\r
157\r
158 //\r
159 // Evaluate the first POPed operator only. If the operand is\r
160 // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the\r
161 // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE,\r
162 // we don't need to check the second operator, and the result will be\r
163 // evaluation of the POPed operator. Otherwise, don't POP the second\r
164 // operator since it will now evaluate to the final result on the\r
165 // next operand that causes a POP.\r
d1102dba 166 //\r
192f6d4c 167 StackPtr--;\r
168 //\r
d1102dba
LG
169 // Iterator has increased by 1 after we retrieve the operand, so here we\r
170 // should get the value pointed by (Iterator - 1), in order to obtain the\r
192f6d4c 171 // same operand.\r
172 //\r
173 if (*(Iterator - 1) == EFI_DEP_AND) {\r
174 if (!(IsPpiInstalled (PeiServices, StackPtr))) {\r
175 (StackPtr-1)->Result = FALSE;\r
176 (StackPtr-1)->Operator = NULL;\r
177 }\r
178 } else {\r
179 if (IsPpiInstalled (PeiServices, StackPtr)) {\r
180 (StackPtr-1)->Result = TRUE;\r
181 (StackPtr-1)->Operator = NULL;\r
182 }\r
183 }\r
184 break;\r
d1102dba 185\r
192f6d4c 186 case (EFI_DEP_END):\r
6a55eea3 187 DEBUG ((DEBUG_DISPATCH, " END\n"));\r
192f6d4c 188 StackPtr--;\r
189 //\r
190 // Check to make sure EvalStack is balanced. If not, then there is\r
191 // an error in the dependency grammar, so return EFI_INVALID_PARAMETER.\r
192 //\r
193 if (StackPtr != &EvalStack[0]) {\r
6a55eea3 194 DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));\r
b0d803fe 195 return FALSE;\r
192f6d4c 196 }\r
6a55eea3 197 DEBUG ((DEBUG_DISPATCH, " RESULT = %a\n", IsPpiInstalled (PeiServices, StackPtr) ? "TRUE" : "FALSE"));\r
b0d803fe 198 return IsPpiInstalled (PeiServices, StackPtr);\r
192f6d4c 199\r
d1102dba 200 case (EFI_DEP_NOT):\r
6a55eea3 201 DEBUG ((DEBUG_DISPATCH, " NOT\n"));\r
192f6d4c 202 //\r
203 // Check to make sure the dependency grammar doesn't underflow the\r
204 // EvalStack on the POP for the NOT operation. Don't need to\r
205 // check for the overflow on PUSHing the result since we already\r
206 // did a POP.\r
207 //\r
208 if (StackPtr < &EvalStack[1]) {\r
6a55eea3 209 DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));\r
b0d803fe 210 return FALSE;\r
192f6d4c 211 }\r
212 (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1));\r
213 (StackPtr-1)->Operator = NULL;\r
214 break;\r
215\r
216 case (EFI_DEP_TRUE):\r
217 case (EFI_DEP_FALSE):\r
6a55eea3 218 if (*(Iterator - 1) == EFI_DEP_TRUE) {\r
219 DEBUG ((DEBUG_DISPATCH, " TRUE\n"));\r
220 } else {\r
221 DEBUG ((DEBUG_DISPATCH, " FALSE\n"));\r
222 }\r
192f6d4c 223 //\r
224 // Check to make sure the dependency grammar doesn't overflow the\r
225 // EvalStack on the push\r
226 //\r
227 if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) {\r
6a55eea3 228 DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Underflow Error)\n"));\r
b0d803fe 229 return FALSE;\r
192f6d4c 230 }\r
231 //\r
d1102dba
LG
232 // Iterator has increased by 1 after we retrieve the operand, so here we\r
233 // should get the value pointed by (Iterator - 1), in order to obtain the\r
192f6d4c 234 // same operand.\r
235 //\r
236 if (*(Iterator - 1) == EFI_DEP_TRUE) {\r
237 StackPtr->Result = TRUE;\r
238 } else {\r
239 StackPtr->Result = FALSE;\r
240 }\r
241 StackPtr->Operator = NULL;\r
242 StackPtr++;\r
243 break;\r
244\r
245 default:\r
6a55eea3 246 DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Invalid opcode)\n"));\r
192f6d4c 247 //\r
248 // The grammar should never arrive here\r
249 //\r
b0d803fe 250 return FALSE;\r
192f6d4c 251 }\r
252 }\r
253}\r