• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 
3 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14   Expression.c
15 
16 Abstract:
17 
18   Expression evaluation.
19 
20 
21 **/
22 #include <PiDxe.h>
23 #include <Library/BaseLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/DebugLib.h>
26 #include <Library/MemoryAllocationLib.h>
27 #include <Library/PrintLib.h>
28 #include <Library/UefiBootServicesTableLib.h>
29 #include <Protocol/UnicodeCollation.h>
30 
31 #include "UefiIfrParser.h"
32 
33 //
34 // Global stack used to evaluate boolean expresions
35 //
36 EFI_HII_VALUE *mOpCodeScopeStack = NULL;
37 EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;
38 EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;
39 
40 EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
41 EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
42 EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
43 
44 #define EXPRESSION_STACK_SIZE_INCREMENT    0x100
45 
46 
47 /**
48   Grow size of the stack
49 
50   @param  Stack                  On input: old stack; On output: new stack
51   @param  StackPtr               On input: old stack pointer; On output: new stack
52                                  pointer
53   @param  StackEnd               On input: old stack end; On output: new stack end
54 
55   @retval EFI_SUCCESS            Grow stack success.
56   @retval EFI_OUT_OF_RESOURCES   No enough memory for stack space.
57 
58 **/
59 EFI_STATUS
GrowStack(IN OUT EFI_HII_VALUE ** Stack,IN OUT EFI_HII_VALUE ** StackPtr,IN OUT EFI_HII_VALUE ** StackEnd)60 GrowStack (
61   IN OUT EFI_HII_VALUE  **Stack,
62   IN OUT EFI_HII_VALUE  **StackPtr,
63   IN OUT EFI_HII_VALUE  **StackEnd
64   )
65 {
66   UINTN           Size;
67   EFI_HII_VALUE  *NewStack;
68 
69   Size = EXPRESSION_STACK_SIZE_INCREMENT;
70   if (*StackPtr != NULL) {
71     Size = Size + (*StackEnd - *Stack);
72   }
73 
74   NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));
75   if (NewStack == NULL) {
76     return EFI_OUT_OF_RESOURCES;
77   }
78 
79   if (*StackPtr != NULL) {
80     //
81     // Copy from Old Stack to the New Stack
82     //
83     CopyMem (
84       NewStack,
85       *Stack,
86       (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)
87       );
88 
89     //
90     // Free The Old Stack
91     //
92     gBS->FreePool (*Stack);
93   }
94 
95   //
96   // Make the Stack pointer point to the old data in the new stack
97   //
98   *StackPtr = NewStack + (*StackPtr - *Stack);
99   *Stack    = NewStack;
100   *StackEnd = NewStack + Size;
101 
102   return EFI_SUCCESS;
103 }
104 
105 
106 /**
107   Push an element onto the Boolean Stack
108 
109   @param  Stack                  On input: old stack; On output: new stack
110   @param  StackPtr               On input: old stack pointer; On output: new stack
111                                  pointer
112   @param  StackEnd               On input: old stack end; On output: new stack end
113   @param  Data                   Data to push.
114 
115   @retval EFI_SUCCESS            Push stack success.
116 
117 **/
118 EFI_STATUS
PushStack(IN OUT EFI_HII_VALUE ** Stack,IN OUT EFI_HII_VALUE ** StackPtr,IN OUT EFI_HII_VALUE ** StackEnd,IN EFI_HII_VALUE * Data)119 PushStack (
120   IN OUT EFI_HII_VALUE       **Stack,
121   IN OUT EFI_HII_VALUE       **StackPtr,
122   IN OUT EFI_HII_VALUE       **StackEnd,
123   IN EFI_HII_VALUE           *Data
124   )
125 {
126   EFI_STATUS  Status;
127 
128   //
129   // Check for a stack overflow condition
130   //
131   if (*StackPtr >= *StackEnd) {
132     //
133     // Grow the stack
134     //
135     Status = GrowStack (Stack, StackPtr, StackEnd);
136     if (EFI_ERROR (Status)) {
137       return Status;
138     }
139   }
140 
141   //
142   // Push the item onto the stack
143   //
144   CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));
145   *StackPtr = *StackPtr + 1;
146 
147   return EFI_SUCCESS;
148 }
149 
150 
151 /**
152   Pop an element from the stack.
153 
154   @param  Stack                  On input: old stack; On output: new stack
155   @param  StackPtr               On input: old stack pointer; On output: new stack
156                                  pointer
157   @param  StackEnd               On input: old stack end; On output: new stack end
158   @param  Data                   Data to pop.
159 
160   @retval EFI_SUCCESS            The value was popped onto the stack.
161   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
162 
163 **/
164 EFI_STATUS
PopStack(IN OUT EFI_HII_VALUE ** Stack,IN OUT EFI_HII_VALUE ** StackPtr,IN OUT EFI_HII_VALUE ** StackEnd,OUT EFI_HII_VALUE * Data)165 PopStack (
166   IN OUT EFI_HII_VALUE       **Stack,
167   IN OUT EFI_HII_VALUE       **StackPtr,
168   IN OUT EFI_HII_VALUE       **StackEnd,
169   OUT EFI_HII_VALUE          *Data
170   )
171 {
172   //
173   // Check for a stack underflow condition
174   //
175   if (*StackPtr == *Stack) {
176     return EFI_ACCESS_DENIED;
177   }
178 
179   //
180   // Pop the item off the stack
181   //
182   *StackPtr = *StackPtr - 1;
183   CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));
184   return EFI_SUCCESS;
185 }
186 
187 /**
188   Reset stack pointer to begin of the stack.
189 
190 **/
191 VOID
ResetScopeStack(VOID)192 ResetScopeStack (
193   VOID
194   )
195 {
196   mOpCodeScopeStackPointer = mOpCodeScopeStack;
197 }
198 
199 
200 /**
201   Push an Operand onto the Stack
202 
203   @param  Operand                Operand to push.
204 
205   @retval EFI_SUCCESS            The value was pushed onto the stack.
206   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
207                                  stack.
208 
209 **/
210 EFI_STATUS
PushScope(IN UINT8 Operand)211 PushScope (
212   IN UINT8   Operand
213   )
214 {
215   EFI_HII_VALUE  Data;
216 
217   Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;
218   Data.Value.u8 = Operand;
219 
220   return PushStack (
221            &mOpCodeScopeStack,
222            &mOpCodeScopeStackPointer,
223            &mOpCodeScopeStackEnd,
224            &Data
225            );
226 }
227 
228 
229 /**
230   Pop an Operand from the Stack
231 
232   @param  Operand                Operand to pop.
233 
234   @retval EFI_SUCCESS            The value was pushed onto the stack.
235   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
236                                  stack.
237 
238 **/
239 EFI_STATUS
PopScope(OUT UINT8 * Operand)240 PopScope (
241   OUT UINT8     *Operand
242   )
243 {
244   EFI_STATUS     Status;
245   EFI_HII_VALUE  Data;
246 
247   Status = PopStack (
248              &mOpCodeScopeStack,
249              &mOpCodeScopeStackPointer,
250              &mOpCodeScopeStackEnd,
251              &Data
252              );
253 
254   *Operand = Data.Value.u8;
255 
256   return Status;
257 }
258 
259 
260 /**
261   Reset stack pointer to begin of the stack.
262 
263 **/
264 VOID
ResetExpressionStack(VOID)265 ResetExpressionStack (
266   VOID
267   )
268 {
269   mExpressionEvaluationStackPointer = mExpressionEvaluationStack;
270 }
271 
272 
273 /**
274   Push an Expression value onto the Stack
275 
276   @param  Value                  Expression value to push.
277 
278   @retval EFI_SUCCESS            The value was pushed onto the stack.
279   @retval EFI_OUT_OF_RESOURCES   There is not enough system memory to grow the
280                                  stack.
281 
282 **/
283 EFI_STATUS
PushExpression(IN EFI_HII_VALUE * Value)284 PushExpression (
285   IN EFI_HII_VALUE  *Value
286   )
287 {
288   return PushStack (
289            &mExpressionEvaluationStack,
290            &mExpressionEvaluationStackPointer,
291            &mExpressionEvaluationStackEnd,
292            Value
293            );
294 }
295 
296 
297 /**
298   Pop an Expression value from the stack.
299 
300   @param  Value                  Expression value to pop.
301 
302   @retval EFI_SUCCESS            The value was popped onto the stack.
303   @retval EFI_ACCESS_DENIED      The pop operation underflowed the stack
304 
305 **/
306 EFI_STATUS
PopExpression(OUT EFI_HII_VALUE * Value)307 PopExpression (
308   OUT EFI_HII_VALUE  *Value
309   )
310 {
311   return PopStack (
312            &mExpressionEvaluationStack,
313            &mExpressionEvaluationStackPointer,
314            &mExpressionEvaluationStackEnd,
315            Value
316            );
317 }
318 
319 /**
320   Zero extend integer/boolean/date/time to UINT64 for comparing.
321 
322   @param  Value                  HII Value to be converted.
323 
324   @return None.
325 
326 **/
327 VOID
ExtendValueToU64(IN EFI_HII_VALUE * Value)328 ExtendValueToU64 (
329   IN  EFI_HII_VALUE   *Value
330   )
331 {
332   UINT64  Temp;
333 
334   Temp = 0;
335   switch (Value->Type) {
336   case EFI_IFR_TYPE_NUM_SIZE_8:
337     Temp = Value->Value.u8;
338     break;
339 
340   case EFI_IFR_TYPE_NUM_SIZE_16:
341     Temp = Value->Value.u16;
342     break;
343 
344   case EFI_IFR_TYPE_NUM_SIZE_32:
345     Temp = Value->Value.u32;
346     break;
347 
348   case EFI_IFR_TYPE_BOOLEAN:
349     Temp = Value->Value.b;
350     break;
351 
352   case EFI_IFR_TYPE_TIME:
353     Temp = Value->Value.u32 & 0xffffff;
354     break;
355 
356   case EFI_IFR_TYPE_DATE:
357     Temp = Value->Value.u32;
358     break;
359 
360   default:
361     return;
362   }
363 
364   Value->Value.u64 = Temp;
365 }
366