]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Enable nest for suppressif/grayoutif/diableif for form/question/option.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
e8ef4283 4Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
7936fb6a 15#include "Setup.h"\r
16\r
17//\r
18// Global stack used to evaluate boolean expresions\r
19//\r
20EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
21EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
22EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
23\r
24EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
25EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
26EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
2573712e
LG
27UINTN mExpressionEvaluationStackOffset = 0;\r
28\r
29EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
30EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
31EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
32\r
33EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
34EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
35EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
7936fb6a 36\r
31585af4
ED
37FORM_EXPRESSION **mFormExpressionStack = NULL;\r
38FORM_EXPRESSION **mFormExpressionEnd = NULL;\r
39FORM_EXPRESSION **mFormExpressionPointer = NULL;\r
40\r
41FORM_EXPRESSION **mStatementExpressionStack = NULL;\r
42FORM_EXPRESSION **mStatementExpressionEnd = NULL;\r
43FORM_EXPRESSION **mStatementExpressionPointer = NULL;\r
44\r
45FORM_EXPRESSION **mOptionExpressionStack = NULL;\r
46FORM_EXPRESSION **mOptionExpressionEnd = NULL;\r
47FORM_EXPRESSION **mOptionExpressionPointer = NULL;\r
48\r
49\r
7936fb6a 50//\r
51// Unicode collation protocol interface\r
52//\r
53EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
cbf73e50 54EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
7936fb6a 55\r
56/**\r
57 Grow size of the stack.\r
58\r
59 This is an internal function.\r
60\r
61 @param Stack On input: old stack; On output: new stack\r
62 @param StackPtr On input: old stack pointer; On output: new stack\r
63 pointer\r
64 @param StackEnd On input: old stack end; On output: new stack end\r
65\r
66 @retval EFI_SUCCESS Grow stack success.\r
67 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
68\r
69**/\r
70EFI_STATUS\r
71GrowStack (\r
72 IN OUT EFI_HII_VALUE **Stack,\r
73 IN OUT EFI_HII_VALUE **StackPtr,\r
74 IN OUT EFI_HII_VALUE **StackEnd\r
75 )\r
76{\r
77 UINTN Size;\r
78 EFI_HII_VALUE *NewStack;\r
79\r
80 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
81 if (*StackPtr != NULL) {\r
82 Size = Size + (*StackEnd - *Stack);\r
83 }\r
84\r
85 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
86 if (NewStack == NULL) {\r
87 return EFI_OUT_OF_RESOURCES;\r
88 }\r
89\r
90 if (*StackPtr != NULL) {\r
91 //\r
92 // Copy from Old Stack to the New Stack\r
93 //\r
94 CopyMem (\r
95 NewStack,\r
96 *Stack,\r
97 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
98 );\r
99\r
100 //\r
101 // Free The Old Stack\r
102 //\r
f4113e1f 103 FreePool (*Stack);\r
7936fb6a 104 }\r
105\r
106 //\r
107 // Make the Stack pointer point to the old data in the new stack\r
108 //\r
109 *StackPtr = NewStack + (*StackPtr - *Stack);\r
110 *Stack = NewStack;\r
111 *StackEnd = NewStack + Size;\r
112\r
113 return EFI_SUCCESS;\r
114}\r
115\r
116\r
117/**\r
118 Push an element onto the Boolean Stack.\r
119\r
120 @param Stack On input: old stack; On output: new stack\r
121 @param StackPtr On input: old stack pointer; On output: new stack\r
122 pointer\r
123 @param StackEnd On input: old stack end; On output: new stack end\r
124 @param Data Data to push.\r
125\r
126 @retval EFI_SUCCESS Push stack success.\r
127\r
128**/\r
129EFI_STATUS\r
130PushStack (\r
131 IN OUT EFI_HII_VALUE **Stack,\r
132 IN OUT EFI_HII_VALUE **StackPtr,\r
133 IN OUT EFI_HII_VALUE **StackEnd,\r
134 IN EFI_HII_VALUE *Data\r
135 )\r
136{\r
137 EFI_STATUS Status;\r
138\r
139 //\r
140 // Check for a stack overflow condition\r
141 //\r
142 if (*StackPtr >= *StackEnd) {\r
143 //\r
144 // Grow the stack\r
145 //\r
146 Status = GrowStack (Stack, StackPtr, StackEnd);\r
147 if (EFI_ERROR (Status)) {\r
148 return Status;\r
149 }\r
150 }\r
151\r
152 //\r
153 // Push the item onto the stack\r
154 //\r
155 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
901ba0e7
ED
156 if (Data->Type == EFI_IFR_TYPE_BUFFER) {\r
157 (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer);\r
158 ASSERT ((*StackPtr)->Buffer != NULL);\r
159 }\r
160 \r
7936fb6a 161 *StackPtr = *StackPtr + 1;\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166\r
167/**\r
168 Pop an element from the stack.\r
169\r
2573712e
LG
170 @param Stack On input: old stack\r
171 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
7936fb6a 172 @param Data Data to pop.\r
173\r
174 @retval EFI_SUCCESS The value was popped onto the stack.\r
175 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
176\r
177**/\r
178EFI_STATUS\r
179PopStack (\r
2573712e 180 IN EFI_HII_VALUE *Stack,\r
7936fb6a 181 IN OUT EFI_HII_VALUE **StackPtr,\r
7936fb6a 182 OUT EFI_HII_VALUE *Data\r
183 )\r
184{\r
185 //\r
186 // Check for a stack underflow condition\r
187 //\r
2573712e 188 if (*StackPtr == Stack) {\r
7936fb6a 189 return EFI_ACCESS_DENIED;\r
190 }\r
191\r
192 //\r
193 // Pop the item off the stack\r
194 //\r
195 *StackPtr = *StackPtr - 1;\r
196 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
197 return EFI_SUCCESS;\r
198}\r
199\r
200\r
2573712e
LG
201/**\r
202 Reset stack pointer to begin of the stack.\r
203\r
204**/\r
205VOID\r
206ResetCurrentExpressionStack (\r
207 VOID\r
208 )\r
209{\r
31585af4
ED
210 mCurrentExpressionPointer = mCurrentExpressionStack;\r
211 mFormExpressionPointer = mFormExpressionStack;\r
212 mStatementExpressionPointer = mStatementExpressionStack;\r
213 mOptionExpressionPointer = mOptionExpressionStack; \r
2573712e
LG
214}\r
215\r
216\r
217/**\r
218 Push current expression onto the Stack\r
219\r
220 @param Pointer Pointer to current expression.\r
221\r
222 @retval EFI_SUCCESS The value was pushed onto the stack.\r
223 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
224\r
225**/\r
226EFI_STATUS\r
227PushCurrentExpression (\r
228 IN VOID *Pointer\r
229 )\r
230{\r
231 EFI_HII_VALUE Data;\r
232\r
233 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
234 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
235\r
236 return PushStack (\r
237 &mCurrentExpressionStack,\r
238 &mCurrentExpressionPointer,\r
239 &mCurrentExpressionEnd,\r
240 &Data\r
241 );\r
242}\r
243\r
244\r
245/**\r
246 Pop current expression from the Stack\r
247\r
248 @param Pointer Pointer to current expression to be pop.\r
249\r
250 @retval EFI_SUCCESS The value was pushed onto the stack.\r
251 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
252\r
253**/\r
254EFI_STATUS\r
255PopCurrentExpression (\r
256 OUT VOID **Pointer\r
257 )\r
258{\r
259 EFI_STATUS Status;\r
260 EFI_HII_VALUE Data;\r
261\r
262 Status = PopStack (\r
263 mCurrentExpressionStack,\r
264 &mCurrentExpressionPointer,\r
265 &Data\r
266 );\r
267\r
268 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
269\r
270 return Status;\r
271}\r
272\r
273/**\r
274 Reset stack pointer to begin of the stack.\r
275\r
276**/\r
277VOID\r
278ResetMapExpressionListStack (\r
279 VOID\r
280 )\r
281{\r
282 mMapExpressionListPointer = mMapExpressionListStack;\r
283}\r
284\r
285\r
31585af4
ED
286/**\r
287 Grow size of the stack.\r
288\r
289 This is an internal function.\r
290\r
291 @param Stack On input: old stack; On output: new stack\r
292 @param StackPtr On input: old stack pointer; On output: new stack\r
293 pointer\r
294 @param StackEnd On input: old stack end; On output: new stack end\r
295 @param MemberSize The stack member size.\r
296 \r
297 @retval EFI_SUCCESS Grow stack success.\r
298 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
299\r
300**/\r
301EFI_STATUS\r
302GrowConditionalStack (\r
303 IN OUT FORM_EXPRESSION ***Stack,\r
304 IN OUT FORM_EXPRESSION ***StackPtr,\r
305 IN OUT FORM_EXPRESSION ***StackEnd,\r
306 IN UINTN MemberSize\r
307 )\r
308{\r
309 UINTN Size;\r
310 FORM_EXPRESSION **NewStack;\r
311\r
312 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
313 if (*StackPtr != NULL) {\r
314 Size = Size + (*StackEnd - *Stack);\r
315 }\r
316\r
317 NewStack = AllocatePool (Size * MemberSize);\r
318 if (NewStack == NULL) {\r
319 return EFI_OUT_OF_RESOURCES;\r
320 }\r
321\r
322 if (*StackPtr != NULL) {\r
323 //\r
324 // Copy from Old Stack to the New Stack\r
325 //\r
326 CopyMem (\r
327 NewStack,\r
328 *Stack,\r
329 (*StackEnd - *Stack) * MemberSize\r
330 );\r
331\r
332 //\r
333 // Free The Old Stack\r
334 //\r
335 FreePool (*Stack);\r
336 }\r
337\r
338 //\r
339 // Make the Stack pointer point to the old data in the new stack\r
340 //\r
341 *StackPtr = NewStack + (*StackPtr - *Stack);\r
342 *Stack = NewStack;\r
343 *StackEnd = NewStack + Size;\r
344\r
345 return EFI_SUCCESS;\r
346}\r
347\r
348/**\r
349 Push an element onto the Stack.\r
350\r
351 @param Stack On input: old stack; On output: new stack\r
352 @param StackPtr On input: old stack pointer; On output: new stack\r
353 pointer\r
354 @param StackEnd On input: old stack end; On output: new stack end\r
355 @param Data Data to push.\r
356\r
357 @retval EFI_SUCCESS Push stack success.\r
358\r
359**/\r
360EFI_STATUS\r
361PushConditionalStack (\r
362 IN OUT FORM_EXPRESSION ***Stack,\r
363 IN OUT FORM_EXPRESSION ***StackPtr,\r
364 IN OUT FORM_EXPRESSION ***StackEnd,\r
365 IN FORM_EXPRESSION **Data\r
366 )\r
367{\r
368 EFI_STATUS Status;\r
369\r
370 //\r
371 // Check for a stack overflow condition\r
372 //\r
373 if (*StackPtr >= *StackEnd) {\r
374 //\r
375 // Grow the stack\r
376 //\r
377 Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));\r
378 if (EFI_ERROR (Status)) {\r
379 return Status;\r
380 }\r
381 }\r
382\r
383 //\r
384 // Push the item onto the stack\r
385 //\r
386 CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *)); \r
387 *StackPtr = *StackPtr + 1;\r
388\r
389 return EFI_SUCCESS;\r
390\r
391}\r
392\r
393/**\r
394 Pop an element from the stack.\r
395\r
396 @param Stack On input: old stack\r
397 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
398 @param Data Data to pop.\r
399\r
400 @retval EFI_SUCCESS The value was popped onto the stack.\r
401 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
402\r
403**/\r
404EFI_STATUS\r
405PopConditionalStack (\r
406 IN FORM_EXPRESSION **Stack,\r
407 IN OUT FORM_EXPRESSION ***StackPtr,\r
408 OUT FORM_EXPRESSION **Data\r
409 )\r
410{\r
411 //\r
412 // Check for a stack underflow condition\r
413 //\r
414 if (*StackPtr == Stack) {\r
415 return EFI_ACCESS_DENIED;\r
416 }\r
417\r
418 //\r
419 // Pop the item off the stack\r
420 //\r
421 *StackPtr = *StackPtr - 1;\r
422 CopyMem (Data, *StackPtr, sizeof (FORM_EXPRESSION *));\r
423 return EFI_SUCCESS;\r
424\r
425}\r
426\r
427/**\r
428 Get the expression list count.\r
429 \r
430 @param Level Which type this expression belong to. Form, \r
431 statement or option?\r
432\r
433 @retval >=0 The expression count\r
434 @retval -1 Input parameter error.\r
435\r
436**/\r
437INTN \r
438GetConditionalExpressionCount (\r
439 IN EXPRESS_LEVEL Level\r
440 )\r
441{\r
442 switch (Level) {\r
443 case ExpressForm:\r
444 return mFormExpressionPointer - mFormExpressionStack;\r
445 case ExpressStatement:\r
446 return mStatementExpressionPointer - mStatementExpressionStack;\r
447 case ExpressOption:\r
448 return mOptionExpressionPointer - mOptionExpressionStack;\r
449 default:\r
450 ASSERT (FALSE);\r
451 return -1;\r
452 } \r
453}\r
454\r
455/**\r
456 Get the expression Buffer pointer.\r
457 \r
458 @param Level Which type this expression belong to. Form, \r
459 statement or option?\r
460\r
461 @retval The start pointer of the expression buffer or NULL.\r
462\r
463**/\r
464FORM_EXPRESSION **\r
465GetConditionalExpressionList (\r
466 IN EXPRESS_LEVEL Level\r
467 )\r
468{\r
469 switch (Level) {\r
470 case ExpressForm:\r
471 return mFormExpressionStack;\r
472 case ExpressStatement:\r
473 return mStatementExpressionStack;\r
474 case ExpressOption:\r
475 return mOptionExpressionStack;\r
476 default:\r
477 ASSERT (FALSE);\r
478 return NULL;\r
479 } \r
480}\r
481\r
482\r
483/**\r
484 Push the expression options onto the Stack.\r
485\r
486 @param Pointer Pointer to the current expression.\r
487 @param Level Which type this expression belong to. Form, \r
488 statement or option?\r
489\r
490 @retval EFI_SUCCESS The value was pushed onto the stack.\r
491 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
492\r
493**/\r
494EFI_STATUS\r
495PushConditionalExpression (\r
496 IN FORM_EXPRESSION *Pointer,\r
497 IN EXPRESS_LEVEL Level\r
498 )\r
499{\r
500 switch (Level) {\r
501 case ExpressForm:\r
502 return PushConditionalStack (\r
503 &mFormExpressionStack,\r
504 &mFormExpressionPointer,\r
505 &mFormExpressionEnd,\r
506 &Pointer\r
507 );\r
508 case ExpressStatement:\r
509 return PushConditionalStack (\r
510 &mStatementExpressionStack,\r
511 &mStatementExpressionPointer,\r
512 &mStatementExpressionEnd,\r
513 &Pointer\r
514 );\r
515 case ExpressOption:\r
516 return PushConditionalStack (\r
517 &mOptionExpressionStack,\r
518 &mOptionExpressionPointer,\r
519 &mOptionExpressionEnd,\r
520 &Pointer\r
521 );\r
522 default:\r
523 ASSERT (FALSE);\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
526}\r
527\r
528/**\r
529 Pop the expression options from the Stack\r
530\r
531 @param Level Which type this expression belong to. Form, \r
532 statement or option?\r
533\r
534 @retval EFI_SUCCESS The value was pushed onto the stack.\r
535 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
536\r
537**/\r
538EFI_STATUS\r
539PopConditionalExpression (\r
540 IN EXPRESS_LEVEL Level\r
541 )\r
542{\r
543 FORM_EXPRESSION *Pointer;\r
544\r
545 switch (Level) {\r
546 case ExpressForm:\r
547 return PopConditionalStack (\r
548 mFormExpressionStack,\r
549 &mFormExpressionPointer,\r
550 &Pointer\r
551 );\r
552\r
553 case ExpressStatement:\r
554 return PopConditionalStack (\r
555 mStatementExpressionStack,\r
556 &mStatementExpressionPointer,\r
557 &Pointer\r
558 );\r
559\r
560 case ExpressOption:\r
561 return PopConditionalStack (\r
562 mOptionExpressionStack,\r
563 &mOptionExpressionPointer,\r
564 &Pointer\r
565 );\r
566\r
567 default:\r
568 ASSERT (FALSE);\r
569 return EFI_INVALID_PARAMETER;\r
570 }\r
571}\r
572\r
573\r
2573712e
LG
574/**\r
575 Push the list of map expression onto the Stack\r
576\r
577 @param Pointer Pointer to the list of map expression to be pushed.\r
578\r
579 @retval EFI_SUCCESS The value was pushed onto the stack.\r
580 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
581\r
582**/\r
583EFI_STATUS\r
584PushMapExpressionList (\r
585 IN VOID *Pointer\r
586 )\r
587{\r
588 EFI_HII_VALUE Data;\r
589\r
590 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
591 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
592\r
593 return PushStack (\r
594 &mMapExpressionListStack,\r
595 &mMapExpressionListPointer,\r
596 &mMapExpressionListEnd,\r
597 &Data\r
598 );\r
599}\r
600\r
601\r
602/**\r
603 Pop the list of map expression from the Stack\r
604\r
605 @param Pointer Pointer to the list of map expression to be pop.\r
606\r
607 @retval EFI_SUCCESS The value was pushed onto the stack.\r
608 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
609\r
610**/\r
611EFI_STATUS\r
612PopMapExpressionList (\r
613 OUT VOID **Pointer\r
614 )\r
615{\r
616 EFI_STATUS Status;\r
617 EFI_HII_VALUE Data;\r
618\r
619 Status = PopStack (\r
620 mMapExpressionListStack,\r
621 &mMapExpressionListPointer,\r
622 &Data\r
623 );\r
624\r
625 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
626\r
627 return Status;\r
628}\r
629\r
7936fb6a 630/**\r
631 Reset stack pointer to begin of the stack.\r
632\r
633**/\r
634VOID\r
635ResetScopeStack (\r
636 VOID\r
637 )\r
638{\r
639 mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
640}\r
641\r
642\r
643/**\r
644 Push an Operand onto the Stack\r
645\r
646 @param Operand Operand to push.\r
647\r
648 @retval EFI_SUCCESS The value was pushed onto the stack.\r
649 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
650 stack.\r
651\r
652**/\r
653EFI_STATUS\r
654PushScope (\r
655 IN UINT8 Operand\r
656 )\r
657{\r
658 EFI_HII_VALUE Data;\r
659\r
660 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
661 Data.Value.u8 = Operand;\r
662\r
663 return PushStack (\r
664 &mOpCodeScopeStack,\r
665 &mOpCodeScopeStackPointer,\r
666 &mOpCodeScopeStackEnd,\r
667 &Data\r
668 );\r
669}\r
670\r
671\r
672/**\r
673 Pop an Operand from the Stack\r
674\r
675 @param Operand Operand to pop.\r
676\r
677 @retval EFI_SUCCESS The value was pushed onto the stack.\r
678 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
679 stack.\r
680\r
681**/\r
682EFI_STATUS\r
683PopScope (\r
684 OUT UINT8 *Operand\r
685 )\r
686{\r
687 EFI_STATUS Status;\r
688 EFI_HII_VALUE Data;\r
689\r
690 Status = PopStack (\r
2573712e 691 mOpCodeScopeStack,\r
7936fb6a 692 &mOpCodeScopeStackPointer,\r
7936fb6a 693 &Data\r
694 );\r
695\r
696 *Operand = Data.Value.u8;\r
697\r
698 return Status;\r
699}\r
700\r
701\r
7936fb6a 702/**\r
703 Push an Expression value onto the Stack\r
704\r
705 @param Value Expression value to push.\r
706\r
707 @retval EFI_SUCCESS The value was pushed onto the stack.\r
708 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
709 stack.\r
710\r
711**/\r
712EFI_STATUS\r
713PushExpression (\r
714 IN EFI_HII_VALUE *Value\r
715 )\r
716{\r
717 return PushStack (\r
718 &mExpressionEvaluationStack,\r
719 &mExpressionEvaluationStackPointer,\r
720 &mExpressionEvaluationStackEnd,\r
721 Value\r
722 );\r
723}\r
724\r
725\r
726/**\r
727 Pop an Expression value from the stack.\r
728\r
729 @param Value Expression value to pop.\r
730\r
731 @retval EFI_SUCCESS The value was popped onto the stack.\r
732 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
733\r
734**/\r
735EFI_STATUS\r
736PopExpression (\r
737 OUT EFI_HII_VALUE *Value\r
738 )\r
739{\r
740 return PopStack (\r
2573712e 741 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
7936fb6a 742 &mExpressionEvaluationStackPointer,\r
7936fb6a 743 Value\r
744 );\r
745}\r
746\r
2573712e
LG
747/**\r
748 Get current stack offset from stack start.\r
749\r
750 @return Stack offset to stack start.\r
751**/\r
752UINTN\r
753SaveExpressionEvaluationStackOffset (\r
754 )\r
755{\r
756 UINTN TempStackOffset;\r
757 TempStackOffset = mExpressionEvaluationStackOffset;\r
758 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
759 return TempStackOffset;\r
760}\r
761\r
762/**\r
763 Restore stack offset based on input stack offset\r
764\r
765 @param StackOffset Offset to stack start.\r
766\r
767**/\r
768VOID\r
769RestoreExpressionEvaluationStackOffset (\r
770 UINTN StackOffset\r
771 )\r
772{\r
773 mExpressionEvaluationStackOffset = StackOffset;\r
774}\r
7936fb6a 775\r
776/**\r
777 Get Form given its FormId.\r
778\r
779 @param FormSet The formset which contains this form.\r
780 @param FormId Id of this form.\r
781\r
782 @retval Pointer The form.\r
783 @retval NULL Specified Form is not found in the formset.\r
784\r
785**/\r
786FORM_BROWSER_FORM *\r
787IdToForm (\r
788 IN FORM_BROWSER_FORMSET *FormSet,\r
789 IN UINT16 FormId\r
790)\r
791{\r
792 LIST_ENTRY *Link;\r
793 FORM_BROWSER_FORM *Form;\r
794\r
795 Link = GetFirstNode (&FormSet->FormListHead);\r
796 while (!IsNull (&FormSet->FormListHead, Link)) {\r
797 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
798\r
799 if (Form->FormId == FormId) {\r
800 return Form;\r
801 }\r
802\r
803 Link = GetNextNode (&FormSet->FormListHead, Link);\r
804 }\r
805\r
806 return NULL;\r
807}\r
808\r
809\r
810/**\r
811 Search a Question in Form scope using its QuestionId.\r
812\r
813 @param Form The form which contains this Question.\r
814 @param QuestionId Id of this Question.\r
815\r
816 @retval Pointer The Question.\r
817 @retval NULL Specified Question not found in the form.\r
818\r
819**/\r
820FORM_BROWSER_STATEMENT *\r
821IdToQuestion2 (\r
822 IN FORM_BROWSER_FORM *Form,\r
823 IN UINT16 QuestionId\r
824 )\r
825{\r
826 LIST_ENTRY *Link;\r
827 FORM_BROWSER_STATEMENT *Question;\r
828\r
db40504e 829 if (QuestionId == 0 || Form == NULL) {\r
7936fb6a 830 //\r
831 // The value of zero is reserved\r
832 //\r
833 return NULL;\r
834 }\r
835\r
836 Link = GetFirstNode (&Form->StatementListHead);\r
837 while (!IsNull (&Form->StatementListHead, Link)) {\r
838 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
839\r
840 if (Question->QuestionId == QuestionId) {\r
841 return Question;\r
842 }\r
843\r
844 Link = GetNextNode (&Form->StatementListHead, Link);\r
845 }\r
846\r
847 return NULL;\r
848}\r
849\r
850\r
851/**\r
852 Search a Question in Formset scope using its QuestionId.\r
853\r
854 @param FormSet The formset which contains this form.\r
855 @param Form The form which contains this Question.\r
856 @param QuestionId Id of this Question.\r
857\r
858 @retval Pointer The Question.\r
859 @retval NULL Specified Question not found in the form.\r
860\r
861**/\r
862FORM_BROWSER_STATEMENT *\r
863IdToQuestion (\r
864 IN FORM_BROWSER_FORMSET *FormSet,\r
865 IN FORM_BROWSER_FORM *Form,\r
866 IN UINT16 QuestionId\r
867 )\r
868{\r
869 LIST_ENTRY *Link;\r
870 FORM_BROWSER_STATEMENT *Question;\r
871\r
872 //\r
873 // Search in the form scope first\r
874 //\r
875 Question = IdToQuestion2 (Form, QuestionId);\r
876 if (Question != NULL) {\r
877 return Question;\r
878 }\r
879\r
880 //\r
881 // Search in the formset scope\r
882 //\r
883 Link = GetFirstNode (&FormSet->FormListHead);\r
884 while (!IsNull (&FormSet->FormListHead, Link)) {\r
885 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
886\r
887 Question = IdToQuestion2 (Form, QuestionId);\r
888 if (Question != NULL) {\r
8d00a0f1 889 //\r
890 // EFI variable storage may be updated by Callback() asynchronous,\r
891 // to keep synchronous, always reload the Question Value.\r
892 //\r
893 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
894 GetQuestionValue (FormSet, Form, Question, FALSE);\r
895 }\r
896\r
7936fb6a 897 return Question;\r
898 }\r
899\r
900 Link = GetNextNode (&FormSet->FormListHead, Link);\r
901 }\r
902\r
903 return NULL;\r
904}\r
905\r
906\r
907/**\r
908 Get Expression given its RuleId.\r
909\r
910 @param Form The form which contains this Expression.\r
911 @param RuleId Id of this Expression.\r
912\r
913 @retval Pointer The Expression.\r
914 @retval NULL Specified Expression not found in the form.\r
915\r
916**/\r
917FORM_EXPRESSION *\r
918RuleIdToExpression (\r
919 IN FORM_BROWSER_FORM *Form,\r
920 IN UINT8 RuleId\r
921 )\r
922{\r
923 LIST_ENTRY *Link;\r
924 FORM_EXPRESSION *Expression;\r
925\r
926 Link = GetFirstNode (&Form->ExpressionListHead);\r
927 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
928 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
929\r
930 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
931 return Expression;\r
932 }\r
933\r
934 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
935 }\r
936\r
937 return NULL;\r
938}\r
939\r
940\r
941/**\r
942 Locate the Unicode Collation Protocol interface for later use.\r
943\r
944 @retval EFI_SUCCESS Protocol interface initialize success.\r
945 @retval Other Protocol interface initialize failed.\r
946\r
947**/\r
948EFI_STATUS\r
949InitializeUnicodeCollationProtocol (\r
950 VOID\r
951 )\r
952{\r
953 EFI_STATUS Status;\r
954\r
955 if (mUnicodeCollation != NULL) {\r
956 return EFI_SUCCESS;\r
957 }\r
958\r
959 //\r
960 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
961 // instances first and then select one which support English language.\r
962 // Current implementation just pick the first instance.\r
963 //\r
964 Status = gBS->LocateProtocol (\r
965 &gEfiUnicodeCollation2ProtocolGuid,\r
966 NULL,\r
967 (VOID **) &mUnicodeCollation\r
968 );\r
969 return Status;\r
970}\r
971\r
972/**\r
973 Convert the input Unicode character to upper.\r
974\r
975 @param String Th Unicode character to be converted.\r
976\r
977**/\r
978VOID\r
979IfrStrToUpper (\r
8b0fc5c1 980 IN CHAR16 *String\r
7936fb6a 981 )\r
982{\r
983 while (*String != 0) {\r
984 if ((*String >= 'a') && (*String <= 'z')) {\r
985 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
986 }\r
987 String++;\r
988 }\r
989}\r
990\r
991\r
992/**\r
993 Evaluate opcode EFI_IFR_TO_STRING.\r
994\r
995 @param FormSet Formset which contains this opcode.\r
996 @param Format String format in EFI_IFR_TO_STRING.\r
997 @param Result Evaluation result for this opcode.\r
998\r
999 @retval EFI_SUCCESS Opcode evaluation success.\r
1000 @retval Other Opcode evaluation failed.\r
1001\r
1002**/\r
1003EFI_STATUS\r
1004IfrToString (\r
1005 IN FORM_BROWSER_FORMSET *FormSet,\r
1006 IN UINT8 Format,\r
1007 OUT EFI_HII_VALUE *Result\r
1008 )\r
1009{\r
1010 EFI_STATUS Status;\r
1011 EFI_HII_VALUE Value;\r
1012 CHAR16 *String;\r
1013 CHAR16 *PrintFormat;\r
1014 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
901ba0e7 1015 UINT8 *TmpBuf;\r
7936fb6a 1016 UINTN BufferSize;\r
1017\r
1018 Status = PopExpression (&Value);\r
1019 if (EFI_ERROR (Status)) {\r
1020 return Status;\r
1021 }\r
1022\r
1023 switch (Value.Type) {\r
1024 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1025 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1026 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1027 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1028 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
1029 switch (Format) {\r
1030 case EFI_IFR_STRING_UNSIGNED_DEC:\r
1031 case EFI_IFR_STRING_SIGNED_DEC:\r
1032 PrintFormat = L"%ld";\r
1033 break;\r
1034\r
1035 case EFI_IFR_STRING_LOWERCASE_HEX:\r
1036 PrintFormat = L"%lx";\r
1037 break;\r
1038\r
1039 case EFI_IFR_STRING_UPPERCASE_HEX:\r
1040 PrintFormat = L"%lX";\r
1041 break;\r
1042\r
1043 default:\r
1044 return EFI_UNSUPPORTED;\r
1045 }\r
1046 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
1047 String = Buffer;\r
1048 break;\r
1049\r
1050 case EFI_IFR_TYPE_STRING:\r
1051 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1052 return EFI_SUCCESS;\r
1053\r
1054 case EFI_IFR_TYPE_BOOLEAN:\r
1055 String = (Value.Value.b) ? L"True" : L"False";\r
1056 break;\r
901ba0e7
ED
1057 \r
1058 case EFI_IFR_TYPE_BUFFER:\r
1059 //\r
1060 // + 3 is base on the unicode format, the length may be odd number, \r
1061 // so need 1 byte to align, also need 2 bytes for L'\0'.\r
1062 //\r
1063 TmpBuf = AllocateZeroPool (Value.BufferLen + 3);\r
db40504e 1064 ASSERT (TmpBuf != NULL);\r
901ba0e7
ED
1065 if (Format == EFI_IFR_STRING_ASCII) {\r
1066 CopyMem (TmpBuf, Value.Buffer, Value.BufferLen);\r
1067 PrintFormat = L"%a"; \r
1068 } else {\r
1069 // Format == EFI_IFR_STRING_UNICODE\r
1070 CopyMem (TmpBuf, Value.Buffer, Value.BufferLen * sizeof (CHAR16));\r
1071 PrintFormat = L"%s"; \r
1072 }\r
1073 UnicodeSPrint (Buffer, MAXIMUM_VALUE_CHARACTERS, PrintFormat, Value.Buffer); \r
1074 String = Buffer; \r
1075 FreePool (TmpBuf);\r
1076 FreePool (Value.Buffer);\r
1077 break;\r
1078 \r
7936fb6a 1079 default:\r
1080 return EFI_UNSUPPORTED;\r
1081 }\r
1082\r
1083 Result->Type = EFI_IFR_TYPE_STRING;\r
1084 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
1085 return EFI_SUCCESS;\r
1086}\r
1087\r
1088\r
1089/**\r
1090 Evaluate opcode EFI_IFR_TO_UINT.\r
1091\r
1092 @param FormSet Formset which contains this opcode.\r
1093 @param Result Evaluation result for this opcode.\r
1094\r
1095 @retval EFI_SUCCESS Opcode evaluation success.\r
1096 @retval Other Opcode evaluation failed.\r
1097\r
1098**/\r
1099EFI_STATUS\r
1100IfrToUint (\r
1101 IN FORM_BROWSER_FORMSET *FormSet,\r
1102 OUT EFI_HII_VALUE *Result\r
1103 )\r
1104{\r
1105 EFI_STATUS Status;\r
1106 EFI_HII_VALUE Value;\r
1107 CHAR16 *String;\r
1108 CHAR16 *StringPtr;\r
7936fb6a 1109\r
1110 Status = PopExpression (&Value);\r
1111 if (EFI_ERROR (Status)) {\r
1112 return Status;\r
1113 }\r
1114\r
901ba0e7 1115 if (Value.Type >= EFI_IFR_TYPE_OTHER && Value.Type != EFI_IFR_TYPE_BUFFER) {\r
7936fb6a 1116 return EFI_UNSUPPORTED;\r
1117 }\r
1118\r
1119 Status = EFI_SUCCESS;\r
1120 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
1121 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1122 if (String == NULL) {\r
1123 return EFI_NOT_FOUND;\r
1124 }\r
8b0fc5c1 1125\r
7936fb6a 1126 IfrStrToUpper (String);\r
1127 StringPtr = StrStr (String, L"0X");\r
1128 if (StringPtr != NULL) {\r
1129 //\r
1130 // Hex string\r
1131 //\r
ac7e320c 1132 Result->Value.u64 = StrHexToUint64 (String);\r
7936fb6a 1133 } else {\r
1134 //\r
ac7e320c 1135 // decimal string\r
7936fb6a 1136 //\r
ac7e320c 1137 Result->Value.u64 = StrDecimalToUint64 (String);\r
7936fb6a 1138 }\r
f4113e1f 1139 FreePool (String);\r
901ba0e7
ED
1140 } else if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1141 if (Value.BufferLen > 8) {\r
1142 FreePool (Value.Buffer);\r
1143 return EFI_UNSUPPORTED;\r
1144 }\r
1145 Result->Value.u64 = *(UINT64*) Value.Buffer;\r
1146 FreePool (Value.Buffer);\r
7936fb6a 1147 } else {\r
1148 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1149 }\r
1150\r
1151 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1152 return Status;\r
1153}\r
1154\r
1155\r
1156/**\r
1157 Evaluate opcode EFI_IFR_CATENATE.\r
1158\r
1159 @param FormSet Formset which contains this opcode.\r
1160 @param Result Evaluation result for this opcode.\r
1161\r
1162 @retval EFI_SUCCESS Opcode evaluation success.\r
1163 @retval Other Opcode evaluation failed.\r
1164\r
1165**/\r
1166EFI_STATUS\r
1167IfrCatenate (\r
1168 IN FORM_BROWSER_FORMSET *FormSet,\r
1169 OUT EFI_HII_VALUE *Result\r
1170 )\r
1171{\r
1172 EFI_STATUS Status;\r
901ba0e7 1173 EFI_HII_VALUE Value[2];\r
7936fb6a 1174 CHAR16 *String[2];\r
1175 UINTN Index;\r
1176 CHAR16 *StringPtr;\r
1177 UINTN Size;\r
1178\r
1179 //\r
1180 // String[0] - The second string\r
1181 // String[1] - The first string\r
1182 //\r
1183 String[0] = NULL;\r
1184 String[1] = NULL;\r
1185 StringPtr = NULL;\r
1186 Status = EFI_SUCCESS;\r
901ba0e7 1187 ZeroMem (Value, sizeof (Value));\r
7936fb6a 1188\r
1189 for (Index = 0; Index < 2; Index++) {\r
901ba0e7 1190 Status = PopExpression (&Value[Index]);\r
7936fb6a 1191 if (EFI_ERROR (Status)) {\r
1192 goto Done;\r
1193 }\r
1194\r
901ba0e7 1195 if (Value[Index].Type != EFI_IFR_TYPE_STRING && Value[Index].Type != EFI_IFR_TYPE_BUFFER) {\r
7936fb6a 1196 Status = EFI_UNSUPPORTED;\r
1197 goto Done;\r
1198 }\r
1199\r
901ba0e7
ED
1200 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
1201 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1202 if (String[Index] == NULL) {\r
1203 Status = EFI_NOT_FOUND;\r
1204 goto Done;\r
1205 }\r
7936fb6a 1206 }\r
1207 }\r
1208\r
901ba0e7
ED
1209 if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
1210 Size = StrSize (String[0]);\r
1211 StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
1212 ASSERT (StringPtr != NULL);\r
1213 StrCpy (StringPtr, String[1]);\r
1214 StrCat (StringPtr, String[0]);\r
7936fb6a 1215\r
901ba0e7
ED
1216 Result->Type = EFI_IFR_TYPE_STRING;\r
1217 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
1218 } else {\r
1219 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1220 Result->BufferLen = (UINT16) (Value[0].BufferLen + Value[1].BufferLen);\r
1221\r
1222 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1223 ASSERT (Result->Buffer != NULL);\r
7936fb6a 1224\r
901ba0e7
ED
1225 CopyMem (Result->Buffer, Value[0].Buffer, Value[0].BufferLen);\r
1226 CopyMem (&Result->Buffer[Value[0].BufferLen], Value[1].Buffer, Value[1].BufferLen);\r
1227 }\r
7936fb6a 1228Done:\r
901ba0e7
ED
1229 if (Value[0].Buffer != NULL) {\r
1230 FreePool (Value[0].Buffer);\r
1231 }\r
1232 if (Value[1].Buffer != NULL) {\r
1233 FreePool (Value[1].Buffer);\r
1234 }\r
676df92c 1235 if (String[0] != NULL) {\r
1236 FreePool (String[0]);\r
1237 }\r
1238 if (String[1] != NULL) {\r
1239 FreePool (String[1]);\r
8b0fc5c1 1240 }\r
676df92c 1241 if (StringPtr != NULL) {\r
1242 FreePool (StringPtr);\r
1243 }\r
7936fb6a 1244\r
1245 return Status;\r
1246}\r
1247\r
1248\r
1249/**\r
1250 Evaluate opcode EFI_IFR_MATCH.\r
1251\r
1252 @param FormSet Formset which contains this opcode.\r
1253 @param Result Evaluation result for this opcode.\r
1254\r
1255 @retval EFI_SUCCESS Opcode evaluation success.\r
1256 @retval Other Opcode evaluation failed.\r
1257\r
1258**/\r
1259EFI_STATUS\r
1260IfrMatch (\r
1261 IN FORM_BROWSER_FORMSET *FormSet,\r
1262 OUT EFI_HII_VALUE *Result\r
1263 )\r
1264{\r
1265 EFI_STATUS Status;\r
1266 EFI_HII_VALUE Value;\r
1267 CHAR16 *String[2];\r
1268 UINTN Index;\r
1269\r
1270 //\r
1271 // String[0] - The string to search\r
1272 // String[1] - pattern\r
1273 //\r
1274 String[0] = NULL;\r
1275 String[1] = NULL;\r
1276 Status = EFI_SUCCESS;\r
1277 for (Index = 0; Index < 2; Index++) {\r
1278 Status = PopExpression (&Value);\r
1279 if (EFI_ERROR (Status)) {\r
1280 goto Done;\r
1281 }\r
1282\r
1283 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1284 Status = EFI_UNSUPPORTED;\r
1285 goto Done;\r
1286 }\r
1287\r
1288 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
bc166db3 1289 if (String [Index] == NULL) {\r
7936fb6a 1290 Status = EFI_NOT_FOUND;\r
1291 goto Done;\r
1292 }\r
1293 }\r
1294\r
1295 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1296 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
1297\r
1298Done:\r
676df92c 1299 if (String[0] != NULL) {\r
1300 FreePool (String[0]);\r
1301 }\r
1302 if (String[1] != NULL) {\r
1303 FreePool (String[1]);\r
8b0fc5c1 1304 }\r
7936fb6a 1305\r
1306 return Status;\r
1307}\r
1308\r
1309\r
1310/**\r
1311 Evaluate opcode EFI_IFR_FIND.\r
1312\r
1313 @param FormSet Formset which contains this opcode.\r
1314 @param Format Case sensitive or insensitive.\r
1315 @param Result Evaluation result for this opcode.\r
1316\r
1317 @retval EFI_SUCCESS Opcode evaluation success.\r
1318 @retval Other Opcode evaluation failed.\r
1319\r
1320**/\r
1321EFI_STATUS\r
1322IfrFind (\r
1323 IN FORM_BROWSER_FORMSET *FormSet,\r
1324 IN UINT8 Format,\r
1325 OUT EFI_HII_VALUE *Result\r
1326 )\r
1327{\r
1328 EFI_STATUS Status;\r
1329 EFI_HII_VALUE Value;\r
1330 CHAR16 *String[2];\r
1331 UINTN Base;\r
1332 CHAR16 *StringPtr;\r
1333 UINTN Index;\r
1334\r
1335 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
1336 return EFI_UNSUPPORTED;\r
1337 }\r
1338\r
1339 Status = PopExpression (&Value);\r
1340 if (EFI_ERROR (Status)) {\r
1341 return Status;\r
1342 }\r
1343 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1344 return EFI_UNSUPPORTED;\r
1345 }\r
1346 Base = (UINTN) Value.Value.u64;\r
1347\r
1348 //\r
1349 // String[0] - sub-string\r
1350 // String[1] - The string to search\r
1351 //\r
1352 String[0] = NULL;\r
1353 String[1] = NULL;\r
1354 for (Index = 0; Index < 2; Index++) {\r
1355 Status = PopExpression (&Value);\r
1356 if (EFI_ERROR (Status)) {\r
1357 goto Done;\r
1358 }\r
1359\r
1360 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1361 Status = EFI_UNSUPPORTED;\r
1362 goto Done;\r
1363 }\r
1364\r
1365 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 1366 if (String[Index] == NULL) {\r
7936fb6a 1367 Status = EFI_NOT_FOUND;\r
1368 goto Done;\r
1369 }\r
1370\r
1371 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
1372 //\r
1373 // Case insensitive, convert both string to upper case\r
1374 //\r
1375 IfrStrToUpper (String[Index]);\r
1376 }\r
1377 }\r
1378\r
1379 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1380 if (Base >= StrLen (String[1])) {\r
1381 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
1382 } else {\r
1383 StringPtr = StrStr (String[1] + Base, String[0]);\r
1384 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
1385 }\r
1386\r
1387Done:\r
676df92c 1388 if (String[0] != NULL) {\r
1389 FreePool (String[0]);\r
1390 }\r
1391 if (String[1] != NULL) {\r
1392 FreePool (String[1]);\r
8b0fc5c1 1393 }\r
7936fb6a 1394\r
1395 return Status;\r
1396}\r
1397\r
1398\r
1399/**\r
1400 Evaluate opcode EFI_IFR_MID.\r
1401\r
1402 @param FormSet Formset which contains this opcode.\r
1403 @param Result Evaluation result for this opcode.\r
1404\r
1405 @retval EFI_SUCCESS Opcode evaluation success.\r
1406 @retval Other Opcode evaluation failed.\r
1407\r
1408**/\r
1409EFI_STATUS\r
1410IfrMid (\r
1411 IN FORM_BROWSER_FORMSET *FormSet,\r
1412 OUT EFI_HII_VALUE *Result\r
1413 )\r
1414{\r
1415 EFI_STATUS Status;\r
1416 EFI_HII_VALUE Value;\r
1417 CHAR16 *String;\r
1418 UINTN Base;\r
1419 UINTN Length;\r
1420 CHAR16 *SubString;\r
901ba0e7
ED
1421 UINT8 *Buffer;\r
1422 UINT16 BufferLen;\r
7936fb6a 1423\r
1424 Status = PopExpression (&Value);\r
1425 if (EFI_ERROR (Status)) {\r
1426 return Status;\r
1427 }\r
1428 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1429 return EFI_UNSUPPORTED;\r
1430 }\r
1431 Length = (UINTN) Value.Value.u64;\r
1432\r
1433 Status = PopExpression (&Value);\r
1434 if (EFI_ERROR (Status)) {\r
1435 return Status;\r
1436 }\r
1437 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1438 return EFI_UNSUPPORTED;\r
1439 }\r
1440 Base = (UINTN) Value.Value.u64;\r
1441\r
1442 Status = PopExpression (&Value);\r
1443 if (EFI_ERROR (Status)) {\r
1444 return Status;\r
1445 }\r
901ba0e7 1446 if (Value.Type != EFI_IFR_TYPE_STRING && Value.Type != EFI_IFR_TYPE_BUFFER) {\r
7936fb6a 1447 return EFI_UNSUPPORTED;\r
1448 }\r
901ba0e7
ED
1449 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
1450 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1451 if (String == NULL) {\r
1452 return EFI_NOT_FOUND;\r
1453 }\r
7936fb6a 1454\r
901ba0e7
ED
1455 if (Length == 0 || Base >= StrLen (String)) {\r
1456 SubString = gEmptyString;\r
1457 } else {\r
1458 SubString = String + Base;\r
1459 if ((Base + Length) < StrLen (String)) {\r
1460 SubString[Length] = L'\0';\r
1461 }\r
7936fb6a 1462 }\r
7936fb6a 1463\r
901ba0e7
ED
1464 Result->Type = EFI_IFR_TYPE_STRING;\r
1465 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
7936fb6a 1466\r
901ba0e7
ED
1467 FreePool (String);\r
1468 } else {\r
1469 Buffer = Value.Buffer;\r
1470 BufferLen = Value.BufferLen;\r
1471 \r
1472 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1473 if (Length == 0 || Base >= BufferLen) {\r
1474 Result->BufferLen = 0;\r
1475 Result->Buffer = NULL;\r
1476 } else {\r
1477 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length); \r
1478 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1479 ASSERT (Result->Buffer != NULL);\r
1480 CopyMem (Result->Buffer, &Value.Buffer[Base], Result->BufferLen);\r
1481 }\r
7936fb6a 1482\r
901ba0e7
ED
1483 FreePool (Value.Buffer);\r
1484 }\r
1485 \r
7936fb6a 1486 return Status;\r
1487}\r
1488\r
1489\r
1490/**\r
1491 Evaluate opcode EFI_IFR_TOKEN.\r
1492\r
1493 @param FormSet Formset which contains this opcode.\r
1494 @param Result Evaluation result for this opcode.\r
1495\r
1496 @retval EFI_SUCCESS Opcode evaluation success.\r
1497 @retval Other Opcode evaluation failed.\r
1498\r
1499**/\r
1500EFI_STATUS\r
1501IfrToken (\r
1502 IN FORM_BROWSER_FORMSET *FormSet,\r
1503 OUT EFI_HII_VALUE *Result\r
1504 )\r
1505{\r
1506 EFI_STATUS Status;\r
1507 EFI_HII_VALUE Value;\r
1508 CHAR16 *String[2];\r
1509 UINTN Count;\r
1510 CHAR16 *Delimiter;\r
1511 CHAR16 *SubString;\r
1512 CHAR16 *StringPtr;\r
1513 UINTN Index;\r
1514\r
1515 Status = PopExpression (&Value);\r
1516 if (EFI_ERROR (Status)) {\r
1517 return Status;\r
1518 }\r
1519 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1520 return EFI_UNSUPPORTED;\r
1521 }\r
1522 Count = (UINTN) Value.Value.u64;\r
1523\r
1524 //\r
1525 // String[0] - Delimiter\r
1526 // String[1] - The string to search\r
1527 //\r
1528 String[0] = NULL;\r
1529 String[1] = NULL;\r
1530 for (Index = 0; Index < 2; Index++) {\r
1531 Status = PopExpression (&Value);\r
1532 if (EFI_ERROR (Status)) {\r
1533 goto Done;\r
1534 }\r
1535\r
1536 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1537 Status = EFI_UNSUPPORTED;\r
1538 goto Done;\r
1539 }\r
1540\r
1541 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 1542 if (String[Index] == NULL) {\r
7936fb6a 1543 Status = EFI_NOT_FOUND;\r
1544 goto Done;\r
1545 }\r
1546 }\r
1547\r
1548 Delimiter = String[0];\r
1549 SubString = String[1];\r
1550 while (Count > 0) {\r
1551 SubString = StrStr (SubString, Delimiter);\r
1552 if (SubString != NULL) {\r
1553 //\r
1554 // Skip over the delimiter\r
1555 //\r
1556 SubString = SubString + StrLen (Delimiter);\r
1557 } else {\r
1558 break;\r
1559 }\r
1560 Count--;\r
1561 }\r
1562\r
1563 if (SubString == NULL) {\r
1564 //\r
1565 // nth delimited sub-string not found, push an empty string\r
1566 //\r
1567 SubString = gEmptyString;\r
1568 } else {\r
1569 //\r
1570 // Put a NULL terminator for nth delimited sub-string\r
1571 //\r
1572 StringPtr = StrStr (SubString, Delimiter);\r
1573 if (StringPtr != NULL) {\r
1574 *StringPtr = L'\0';\r
1575 }\r
1576 }\r
1577\r
1578 Result->Type = EFI_IFR_TYPE_STRING;\r
1579 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1580\r
1581Done:\r
676df92c 1582 if (String[0] != NULL) {\r
1583 FreePool (String[0]);\r
1584 }\r
1585 if (String[1] != NULL) {\r
1586 FreePool (String[1]);\r
8b0fc5c1 1587 }\r
7936fb6a 1588\r
1589 return Status;\r
1590}\r
1591\r
1592\r
1593/**\r
1594 Evaluate opcode EFI_IFR_SPAN.\r
1595\r
1596 @param FormSet Formset which contains this opcode.\r
1597 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1598 @param Result Evaluation result for this opcode.\r
1599\r
1600 @retval EFI_SUCCESS Opcode evaluation success.\r
1601 @retval Other Opcode evaluation failed.\r
1602\r
1603**/\r
1604EFI_STATUS\r
1605IfrSpan (\r
1606 IN FORM_BROWSER_FORMSET *FormSet,\r
1607 IN UINT8 Flags,\r
1608 OUT EFI_HII_VALUE *Result\r
1609 )\r
1610{\r
1611 EFI_STATUS Status;\r
1612 EFI_HII_VALUE Value;\r
1613 CHAR16 *String[2];\r
1614 CHAR16 *Charset;\r
1615 UINTN Base;\r
1616 UINTN Index;\r
1617 CHAR16 *StringPtr;\r
1618 BOOLEAN Found;\r
1619\r
1620 Status = PopExpression (&Value);\r
1621 if (EFI_ERROR (Status)) {\r
1622 return Status;\r
1623 }\r
1624 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1625 return EFI_UNSUPPORTED;\r
1626 }\r
1627 Base = (UINTN) Value.Value.u64;\r
1628\r
1629 //\r
1630 // String[0] - Charset\r
1631 // String[1] - The string to search\r
1632 //\r
1633 String[0] = NULL;\r
1634 String[1] = NULL;\r
1635 for (Index = 0; Index < 2; Index++) {\r
1636 Status = PopExpression (&Value);\r
1637 if (EFI_ERROR (Status)) {\r
1638 goto Done;\r
1639 }\r
1640\r
1641 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1642 Status = EFI_UNSUPPORTED;\r
1643 goto Done;\r
1644 }\r
1645\r
1646 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
bc166db3 1647 if (String [Index] == NULL) {\r
7936fb6a 1648 Status = EFI_NOT_FOUND;\r
1649 goto Done;\r
1650 }\r
1651 }\r
1652\r
1653 if (Base >= StrLen (String[1])) {\r
1654 Status = EFI_UNSUPPORTED;\r
1655 goto Done;\r
1656 }\r
1657\r
1658 Found = FALSE;\r
1659 StringPtr = String[1] + Base;\r
1660 Charset = String[0];\r
1661 while (*StringPtr != 0 && !Found) {\r
1662 Index = 0;\r
1663 while (Charset[Index] != 0) {\r
1664 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
1665 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1666 Found = TRUE;\r
1667 break;\r
1668 }\r
1669 } else {\r
1670 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1671 Found = TRUE;\r
1672 break;\r
1673 }\r
1674 }\r
1675 //\r
1676 // Skip characters pair representing low-end of a range and high-end of a range\r
1677 //\r
1678 Index += 2;\r
1679 }\r
1680\r
1681 if (!Found) {\r
1682 StringPtr++;\r
1683 }\r
1684 }\r
1685\r
1686 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1687 Result->Value.u64 = StringPtr - String[1];\r
1688\r
1689Done:\r
676df92c 1690 if (String[0] != NULL) {\r
1691 FreePool (String[0]);\r
1692 }\r
1693 if (String[1] != NULL) {\r
1694 FreePool (String[1]);\r
8b0fc5c1 1695 }\r
7936fb6a 1696\r
1697 return Status;\r
1698}\r
1699\r
1700\r
1701/**\r
1702 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1703\r
1704 @param Value HII Value to be converted.\r
1705\r
1706**/\r
1707VOID\r
1708ExtendValueToU64 (\r
1709 IN EFI_HII_VALUE *Value\r
1710 )\r
1711{\r
1712 UINT64 Temp;\r
1713\r
1714 Temp = 0;\r
1715 switch (Value->Type) {\r
1716 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1717 Temp = Value->Value.u8;\r
1718 break;\r
1719\r
1720 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1721 Temp = Value->Value.u16;\r
1722 break;\r
1723\r
1724 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1725 Temp = Value->Value.u32;\r
1726 break;\r
1727\r
1728 case EFI_IFR_TYPE_BOOLEAN:\r
1729 Temp = Value->Value.b;\r
1730 break;\r
1731\r
1732 case EFI_IFR_TYPE_TIME:\r
1733 Temp = Value->Value.u32 & 0xffffff;\r
1734 break;\r
1735\r
1736 case EFI_IFR_TYPE_DATE:\r
1737 Temp = Value->Value.u32;\r
1738 break;\r
1739\r
1740 default:\r
1741 return;\r
1742 }\r
1743\r
1744 Value->Value.u64 = Temp;\r
1745}\r
1746\r
1747\r
1748/**\r
1749 Compare two Hii value.\r
1750\r
1751 @param Value1 Expression value to compare on left-hand.\r
1752 @param Value2 Expression value to compare on right-hand.\r
1753 @param HiiHandle Only required for string compare.\r
1754\r
2573712e
LG
1755 @retval EFI_INVALID_PARAMETER Could not perform compare on two values.\r
1756 @retval 0 Two operators equal.\r
7936fb6a 1757 @return Positive value if Value1 is greater than Value2.\r
1758 @retval Negative value if Value1 is less than Value2.\r
1759\r
1760**/\r
1761INTN\r
1762CompareHiiValue (\r
1763 IN EFI_HII_VALUE *Value1,\r
1764 IN EFI_HII_VALUE *Value2,\r
1765 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
1766 )\r
1767{\r
1768 INTN Result;\r
1769 INT64 Temp64;\r
1770 CHAR16 *Str1;\r
1771 CHAR16 *Str2;\r
901ba0e7 1772 UINTN Len;\r
7936fb6a 1773\r
1774 if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
901ba0e7
ED
1775 if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {\r
1776 return EFI_INVALID_PARAMETER;\r
1777 }\r
7936fb6a 1778 }\r
1779\r
1780 if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
1781 if (Value1->Type != Value2->Type) {\r
1782 //\r
1783 // Both Operator should be type of String\r
1784 //\r
1785 return EFI_INVALID_PARAMETER;\r
1786 }\r
1787\r
1788 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
1789 //\r
1790 // StringId 0 is reserved\r
1791 //\r
1792 return EFI_INVALID_PARAMETER;\r
1793 }\r
1794\r
1795 if (Value1->Value.string == Value2->Value.string) {\r
1796 return 0;\r
1797 }\r
1798\r
1799 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
1800 if (Str1 == NULL) {\r
1801 //\r
1802 // String not found\r
1803 //\r
1804 return EFI_INVALID_PARAMETER;\r
1805 }\r
1806\r
1807 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
1808 if (Str2 == NULL) {\r
f4113e1f 1809 FreePool (Str1);\r
7936fb6a 1810 return EFI_INVALID_PARAMETER;\r
1811 }\r
1812\r
1813 Result = StrCmp (Str1, Str2);\r
1814\r
f4113e1f 1815 FreePool (Str1);\r
1816 FreePool (Str2);\r
7936fb6a 1817\r
1818 return Result;\r
1819 }\r
1820\r
901ba0e7
ED
1821 if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) {\r
1822 if (Value1->Type != Value2->Type) {\r
1823 //\r
1824 // Both Operator should be type of Buffer.\r
1825 //\r
1826 return EFI_INVALID_PARAMETER;\r
1827 }\r
1828 Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;\r
1829 Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);\r
1830 if ((Result == 0) && (Value1->BufferLen != Value2->BufferLen))\r
1831 {\r
1832 //\r
1833 // In this case, means base on samll number buffer, the data is same\r
1834 // So which value has more data, which value is bigger.\r
1835 //\r
1836 Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1;\r
1837 }\r
1838 return Result;\r
1839 } \r
1840\r
7936fb6a 1841 //\r
1842 // Take remain types(integer, boolean, date/time) as integer\r
1843 //\r
1844 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
1845 if (Temp64 > 0) {\r
1846 Result = 1;\r
1847 } else if (Temp64 < 0) {\r
1848 Result = -1;\r
1849 } else {\r
1850 Result = 0;\r
1851 }\r
1852\r
1853 return Result;\r
1854}\r
1855\r
cbf73e50 1856/**\r
1857 Check if current user has the privilege specified by the permissions GUID.\r
1858\r
1859 @param[in] Guid A GUID specifying setup access permissions.\r
1860\r
1861 @retval TRUE Current user has the privilege.\r
1862 @retval FALSE Current user does not have the privilege.\r
1863**/\r
1864BOOLEAN\r
1865CheckUserPrivilege (\r
1866 IN EFI_GUID *Guid\r
1867 )\r
1868{\r
1869 EFI_STATUS Status;\r
1870 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
1871 EFI_USER_INFO_HANDLE UserInfoHandle;\r
1872 EFI_USER_INFO *UserInfo;\r
1873 EFI_GUID *UserPermissionsGuid;\r
1874 UINTN UserInfoSize;\r
1875 UINTN AccessControlDataSize;\r
1876 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
1877 UINTN RemainSize;\r
1878\r
1879 if (mUserManager == NULL) {\r
1880 Status = gBS->LocateProtocol (\r
1881 &gEfiUserManagerProtocolGuid,\r
1882 NULL,\r
1883 (VOID **) &mUserManager\r
1884 );\r
1885 if (EFI_ERROR (Status)) {\r
1886 ///\r
1887 /// If the system does not support user management, then it is assumed that\r
1888 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
1889 /// op-code is always TRUE.\r
1890 ///\r
1891 return TRUE;\r
1892 }\r
1893 }\r
1894\r
1895 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
1896 ASSERT_EFI_ERROR (Status);\r
1897\r
1898 ///\r
1899 /// Enumerate all user information of the current user profile\r
1900 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
1901 ///\r
1902 \r
1903 for (UserInfoHandle = NULL;;) {\r
1904 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
1905 if (EFI_ERROR (Status)) {\r
1906 break;\r
1907 }\r
1908\r
1909 UserInfoSize = 0;\r
1910 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
1911 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1912 continue;\r
1913 }\r
1914\r
1915 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
1916 if (UserInfo == NULL) {\r
1917 break;\r
1918 }\r
1919\r
1920 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
1921 if (EFI_ERROR (Status) ||\r
1922 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
1923 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
1924 FreePool (UserInfo);\r
1925 continue;\r
1926 }\r
1927\r
1928 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
1929 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
1930 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
3dd405be 1931 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
cbf73e50 1932 break;\r
1933 }\r
1934 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
1935 ///\r
1936 /// Check if current user has the privilege specified by the permissions GUID.\r
1937 ///\r
1938\r
1939 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
1940 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
1941 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
1942 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
1943 FreePool (UserInfo);\r
1944 return TRUE;\r
1945 }\r
1946 UserPermissionsGuid++;\r
1947 AccessControlDataSize -= sizeof (EFI_GUID);\r
1948 }\r
1949 }\r
1950 RemainSize -= AccessControl->Size;\r
1951 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
1952 }\r
1953\r
1954 FreePool (UserInfo);\r
1955 }\r
1956 return FALSE;\r
1957}\r
7936fb6a 1958\r
db40504e
ED
1959/**\r
1960 Get question value from the predefined formset.\r
1961\r
1962 @param DevicePath The driver's device path which produece the formset data.\r
1963 @param InputHiiHandle The hii handle associate with the formset data.\r
1964 @param FormSetGuid The formset guid which include the question.\r
1965 @param QuestionId The question id which need to get value from.\r
1966 @param Value The return data about question's value.\r
1967 \r
1968 @retval TRUE Get the question value success.\r
1969 @retval FALSE Get the question value failed.\r
1970**/\r
1971BOOLEAN \r
1972GetQuestionValueFromForm (\r
1973 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
1974 IN EFI_HII_HANDLE InputHiiHandle,\r
1975 IN EFI_GUID *FormSetGuid,\r
1976 IN EFI_QUESTION_ID QuestionId,\r
1977 OUT EFI_HII_VALUE *Value\r
1978 )\r
1979{\r
1980 EFI_STATUS Status;\r
1981 EFI_HANDLE DriverHandle;\r
1982 EFI_HANDLE Handle;\r
1983 EFI_HII_HANDLE *HiiHandles;\r
1984 EFI_HII_HANDLE HiiHandle;\r
1985 UINTN Index;\r
1986 FORM_BROWSER_STATEMENT *Question;\r
1987 FORM_BROWSER_FORMSET *FormSet;\r
1988 FORM_BROWSER_FORM *Form;\r
1989 BOOLEAN GetTheVal;\r
1990 LIST_ENTRY *Link;\r
1991\r
1992 // \r
1993 // The input parameter DevicePath or InputHiiHandle must have one valid input. \r
1994 //\r
1995 ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) || \r
1996 (DevicePath == NULL && InputHiiHandle != NULL) );\r
1997\r
1998 GetTheVal = TRUE;\r
1999 DriverHandle = NULL;\r
2000 HiiHandle = NULL;\r
2001 Question = NULL;\r
2002 Form = NULL;\r
2003\r
2004 //\r
2005 // Get HiiHandle.\r
2006 //\r
2007 if (DevicePath != NULL) {\r
2008 //\r
2009 // 1. Get Driver handle.\r
2010 //\r
2011 Status = gBS->LocateDevicePath (\r
2012 &gEfiDevicePathProtocolGuid,\r
2013 &DevicePath,\r
2014 &DriverHandle\r
2015 );\r
2016 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2017 return FALSE;\r
2018 }\r
2019\r
2020 //\r
2021 // 2. Get Hii handle\r
2022 //\r
2023 HiiHandles = HiiGetHiiHandles (NULL);\r
2024 if (HiiHandles == NULL) {\r
2025 return FALSE;\r
2026 }\r
2027\r
2028 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
2029 Status = mHiiDatabase->GetPackageListHandle (\r
2030 mHiiDatabase,\r
2031 HiiHandles[Index],\r
2032 &Handle\r
2033 );\r
2034 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
2035 HiiHandle = HiiHandles[Index];\r
2036 break;\r
2037 }\r
2038 }\r
2039 FreePool (HiiHandles);\r
2040 } else {\r
2041 HiiHandle = InputHiiHandle;\r
2042 } \r
2043 ASSERT (HiiHandle != NULL);\r
2044\r
2045 //\r
2046 // Get the formset data include this question.\r
2047 //\r
2048 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
2049 ASSERT (FormSet != NULL);\r
2050 Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet, FALSE);\r
2051 if (EFI_ERROR (Status)) {\r
2052 GetTheVal = FALSE;\r
2053 goto Done;\r
2054 }\r
2055\r
2056 //\r
2057 // Base on the Question Id to get the question info.\r
2058 // \r
2059 Question = IdToQuestion(FormSet, NULL, QuestionId);\r
2060 if (Question == NULL) {\r
2061 GetTheVal = FALSE;\r
2062 goto Done;\r
2063 }\r
2064\r
2065 //\r
2066 // Search form in the formset scope\r
2067 //\r
2068 Link = GetFirstNode (&FormSet->FormListHead);\r
2069 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2070 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2071\r
2072 Question = IdToQuestion2 (Form, QuestionId);\r
2073 if (Question != NULL) {\r
2074 break;\r
2075 }\r
2076\r
2077 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2078 Form = NULL;\r
2079 }\r
2080 ASSERT (Form != NULL);\r
2081 \r
2082 //\r
2083 // Get the question value.\r
2084 //\r
2085 Status = GetQuestionValue(FormSet, Form, Question, FALSE);\r
2086 if (EFI_ERROR (Status)) {\r
2087 GetTheVal = FALSE;\r
2088 goto Done;\r
2089 }\r
2090\r
2091 CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
2092 \r
2093Done:\r
2094 //\r
2095 // Clean the formset structure and restore the global parameter.\r
2096 //\r
2097 if (FormSet != NULL) {\r
2098 DestroyFormSet (FormSet);\r
2099 }\r
2100 \r
2101 return GetTheVal;\r
2102}\r
2103\r
7936fb6a 2104/**\r
bc166db3 2105 Evaluate the result of a HII expression.\r
2106\r
2107 If Expression is NULL, then ASSERT.\r
7936fb6a 2108\r
2109 @param FormSet FormSet associated with this expression.\r
2110 @param Form Form associated with this expression.\r
2111 @param Expression Expression to be evaluated.\r
2112\r
2113 @retval EFI_SUCCESS The expression evaluated successfuly\r
2114 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
2115 could not be found.\r
2116 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
2117 stack.\r
2118 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
2119 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
2120\r
2121**/\r
2122EFI_STATUS\r
2123EvaluateExpression (\r
2124 IN FORM_BROWSER_FORMSET *FormSet,\r
2125 IN FORM_BROWSER_FORM *Form,\r
2126 IN OUT FORM_EXPRESSION *Expression\r
2127 )\r
2128{\r
2129 EFI_STATUS Status;\r
2130 LIST_ENTRY *Link;\r
2131 EXPRESSION_OPCODE *OpCode;\r
2132 FORM_BROWSER_STATEMENT *Question;\r
2133 FORM_BROWSER_STATEMENT *Question2;\r
2134 UINT16 Index;\r
2135 EFI_HII_VALUE Data1;\r
2136 EFI_HII_VALUE Data2;\r
2137 EFI_HII_VALUE Data3;\r
2138 FORM_EXPRESSION *RuleExpression;\r
2139 EFI_HII_VALUE *Value;\r
2140 INTN Result;\r
2141 CHAR16 *StrPtr;\r
2573712e 2142 CHAR16 *NameValue;\r
7936fb6a 2143 UINT32 TempValue;\r
2573712e
LG
2144 LIST_ENTRY *SubExpressionLink;\r
2145 FORM_EXPRESSION *SubExpression;\r
2146 UINTN StackOffset;\r
2147 UINTN TempLength;\r
2148 CHAR16 TempStr[5];\r
2149 UINT8 DigitUint8;\r
2150 UINT8 *TempBuffer;\r
2151 EFI_TIME EfiTime;\r
db40504e 2152 EFI_HII_VALUE QuestionVal;\r
7936fb6a 2153\r
2154 //\r
2573712e 2155 // Save current stack offset.\r
7936fb6a 2156 //\r
2573712e 2157 StackOffset = SaveExpressionEvaluationStackOffset ();\r
7936fb6a 2158\r
bc166db3 2159 ASSERT (Expression != NULL);\r
7936fb6a 2160 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
2161\r
2162 Link = GetFirstNode (&Expression->OpCodeListHead);\r
2163 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
2164 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
2165\r
2166 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
2167\r
2168 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
2169 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
2170 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
2171\r
2172 Value = &Data3;\r
2173 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2174 Status = EFI_SUCCESS;\r
2175\r
2176 switch (OpCode->Operand) {\r
2177 //\r
2178 // Built-in functions\r
2179 //\r
2180 case EFI_IFR_EQ_ID_VAL_OP:\r
2181 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2182 if (Question == NULL) {\r
2573712e
LG
2183 Status = EFI_NOT_FOUND;\r
2184 goto Done;\r
7936fb6a 2185 }\r
2186\r
2187 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
2188 if (Result == EFI_INVALID_PARAMETER) {\r
2573712e
LG
2189 Status = EFI_INVALID_PARAMETER;\r
2190 goto Done;\r
7936fb6a 2191 }\r
2192 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2193 break;\r
2194\r
2195 case EFI_IFR_EQ_ID_ID_OP:\r
2196 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2197 if (Question == NULL) {\r
2573712e
LG
2198 Status = EFI_NOT_FOUND;\r
2199 goto Done;\r
7936fb6a 2200 }\r
2201\r
2202 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
2203 if (Question2 == NULL) {\r
2573712e
LG
2204 Status = EFI_NOT_FOUND;\r
2205 goto Done;\r
7936fb6a 2206 }\r
2207\r
2208 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
2209 if (Result == EFI_INVALID_PARAMETER) {\r
2573712e
LG
2210 Status = EFI_INVALID_PARAMETER;\r
2211 goto Done;\r
7936fb6a 2212 }\r
2213 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2214 break;\r
2215\r
e8ef4283 2216 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
7936fb6a 2217 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2218 if (Question == NULL) {\r
2573712e
LG
2219 Status = EFI_NOT_FOUND;\r
2220 goto Done;\r
7936fb6a 2221 }\r
2222\r
2223 Value->Value.b = FALSE;\r
2224 for (Index =0; Index < OpCode->ListLength; Index++) {\r
2225 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
2226 Value->Value.b = TRUE;\r
2227 break;\r
2228 }\r
2229 }\r
2230 break;\r
2231\r
2232 case EFI_IFR_DUP_OP:\r
2233 Status = PopExpression (Value);\r
2234 if (EFI_ERROR (Status)) {\r
2573712e 2235 goto Done;\r
7936fb6a 2236 }\r
2237\r
2238 Status = PushExpression (Value);\r
2239 break;\r
2240\r
2241 case EFI_IFR_QUESTION_REF1_OP:\r
2242 case EFI_IFR_THIS_OP:\r
2243 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2244 if (Question == NULL) {\r
2573712e
LG
2245 Status = EFI_NOT_FOUND;\r
2246 goto Done;\r
7936fb6a 2247 }\r
2248\r
2249 Value = &Question->HiiValue;\r
2250 break;\r
2251\r
cbf73e50 2252 case EFI_IFR_SECURITY_OP:\r
2253 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
2254 break;\r
2255\r
2573712e
LG
2256 case EFI_IFR_GET_OP:\r
2257 //\r
2258 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2259 //\r
2260 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2261 Value->Value.u8 = 0;\r
2262 if (OpCode->VarStorage != NULL) {\r
2263 switch (OpCode->VarStorage->Type) {\r
2264 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2265 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2266 //\r
2267 // Get value from Edit Buffer\r
2268 //\r
2269 Value->Type = OpCode->ValueType;\r
2270 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2271 break;\r
2272 case EFI_HII_VARSTORE_NAME_VALUE:\r
2273 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2274 //\r
2275 // Get value from string except for STRING value.\r
2276 //\r
2277 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr);\r
2278 if (!EFI_ERROR (Status)) {\r
771ececd 2279 ASSERT (StrPtr != NULL);\r
2573712e
LG
2280 TempLength = StrLen (StrPtr);\r
2281 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
2282 Value->Type = OpCode->ValueType;\r
2283 TempBuffer = (UINT8 *) &Value->Value;\r
2284 ZeroMem (TempStr, sizeof (TempStr));\r
2285 for (Index = 0; Index < TempLength; Index ++) {\r
2286 TempStr[0] = StrPtr[TempLength - Index - 1];\r
2287 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
2288 if ((Index & 1) == 0) {\r
2289 TempBuffer [Index/2] = DigitUint8;\r
2290 } else {\r
771ececd 2291 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
2292 }\r
2293 }\r
2294 } \r
2295 }\r
2296 }\r
2297 break;\r
2298 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2299 //\r
2300 // Get value from variable.\r
2301 //\r
2302 TempLength = OpCode->ValueWidth;\r
2303 Value->Type = OpCode->ValueType;\r
2304 Status = gRT->GetVariable (\r
2305 OpCode->ValueName,\r
2306 &OpCode->VarStorage->Guid,\r
2307 NULL,\r
2308 &TempLength,\r
2309 &Value->Value\r
2310 );\r
2311 if (EFI_ERROR (Status)) {\r
2312 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2313 Value->Value.u8 = 0;\r
2314 }\r
cce6230f 2315 break;\r
2573712e
LG
2316 default:\r
2317 //\r
2318 // Not recognize storage.\r
2319 //\r
2320 Status = EFI_UNSUPPORTED;\r
2321 goto Done;\r
2322 }\r
2323 } else {\r
2324 //\r
2325 // For Time/Date Data\r
2326 //\r
2327 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2328 //\r
2329 // Only support Data/Time data when storage doesn't exist.\r
2330 //\r
2331 Status = EFI_UNSUPPORTED;\r
2332 goto Done;\r
2333 }\r
2334 Status = gRT->GetTime (&EfiTime, NULL);\r
2335 if (!EFI_ERROR (Status)) {\r
2336 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2337 switch (OpCode->VarStoreInfo.VarOffset) {\r
2338 case 0x00:\r
2339 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
2340 Value->Value.u16 = EfiTime.Year;\r
2341 break;\r
2342 case 0x02:\r
2343 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2344 Value->Value.u8 = EfiTime.Month;\r
2345 break;\r
2346 case 0x03:\r
2347 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2348 Value->Value.u8 = EfiTime.Day;\r
2349 break;\r
2350 default:\r
2351 //\r
2352 // Invalid Date field.\r
2353 //\r
2354 Status = EFI_INVALID_PARAMETER;\r
2355 goto Done;\r
2356 }\r
2357 } else {\r
2358 switch (OpCode->VarStoreInfo.VarOffset) {\r
2359 case 0x00:\r
2360 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2361 Value->Value.u8 = EfiTime.Hour;\r
2362 break;\r
2363 case 0x01:\r
2364 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2365 Value->Value.u8 = EfiTime.Minute;\r
2366 break;\r
2367 case 0x02:\r
2368 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2369 Value->Value.u8 = EfiTime.Second;\r
2370 break;\r
2371 default:\r
2372 //\r
2373 // Invalid Time field.\r
2374 //\r
2375 Status = EFI_INVALID_PARAMETER;\r
2376 goto Done;\r
2377 }\r
2378 }\r
2379 }\r
2380 }\r
2381\r
2382 break;\r
2383\r
7936fb6a 2384 case EFI_IFR_QUESTION_REF3_OP:\r
db40504e
ED
2385 //\r
2386 // EFI_IFR_QUESTION_REF3\r
2387 // Pop an expression from the expression stack\r
2388 //\r
2389 Status = PopExpression (Value);\r
2390 if (EFI_ERROR (Status)) {\r
2391 goto Done;\r
2392 }\r
2393 \r
2394 //\r
2395 // Validate the expression value\r
2396 //\r
2397 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2398 Status = EFI_NOT_FOUND;\r
2399 goto Done;\r
2400 }\r
2401\r
2402 if (OpCode->DevicePath != 0) {\r
2403 StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
2404 if (StrPtr == NULL) {\r
2405 Status = EFI_NOT_FOUND;\r
2573712e 2406 goto Done;\r
7936fb6a 2407 }\r
2408\r
db40504e 2409 if (!GetQuestionValueFromForm((EFI_DEVICE_PATH_PROTOCOL*)StrPtr, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
2573712e
LG
2410 Status = EFI_NOT_FOUND;\r
2411 goto Done;\r
7936fb6a 2412 }\r
db40504e
ED
2413 Value = &QuestionVal;\r
2414 } else if (CompareGuid (&OpCode->Guid, &gZeroGuid) != 0) {\r
2415 if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
2416 Status = EFI_NOT_FOUND;\r
2417 goto Done;\r
2418 }\r
2419 Value = &QuestionVal; \r
2420 } else {\r
7936fb6a 2421 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2422 if (Question == NULL) {\r
2573712e
LG
2423 Status = EFI_NOT_FOUND;\r
2424 goto Done;\r
7936fb6a 2425 }\r
2426\r
2427 //\r
2428 // push the questions' value on to the expression stack\r
2429 //\r
2430 Value = &Question->HiiValue;\r
7936fb6a 2431 }\r
2432 break;\r
2433\r
2434 case EFI_IFR_RULE_REF_OP:\r
2435 //\r
2436 // Find expression for this rule\r
2437 //\r
2438 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
2439 if (RuleExpression == NULL) {\r
2573712e
LG
2440 Status = EFI_NOT_FOUND;\r
2441 goto Done;\r
7936fb6a 2442 }\r
2443\r
2444 //\r
2445 // Evaluate this rule expression\r
2446 //\r
2447 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
2448 if (EFI_ERROR (Status)) {\r
2573712e 2449 goto Done;\r
7936fb6a 2450 }\r
2451\r
2452 Value = &RuleExpression->Result;\r
2453 break;\r
2454\r
2455 case EFI_IFR_STRING_REF1_OP:\r
2456 Value->Type = EFI_IFR_TYPE_STRING;\r
2457 Value->Value.string = OpCode->Value.Value.string;\r
2458 break;\r
2459\r
2460 //\r
2461 // Constant\r
2462 //\r
2463 case EFI_IFR_TRUE_OP:\r
2464 case EFI_IFR_FALSE_OP:\r
2465 case EFI_IFR_ONE_OP:\r
2466 case EFI_IFR_ONES_OP:\r
2467 case EFI_IFR_UINT8_OP:\r
2468 case EFI_IFR_UINT16_OP:\r
2469 case EFI_IFR_UINT32_OP:\r
2470 case EFI_IFR_UINT64_OP:\r
2471 case EFI_IFR_UNDEFINED_OP:\r
2472 case EFI_IFR_VERSION_OP:\r
2473 case EFI_IFR_ZERO_OP:\r
2474 Value = &OpCode->Value;\r
2475 break;\r
2476\r
2477 //\r
2478 // unary-op\r
2479 //\r
2480 case EFI_IFR_LENGTH_OP:\r
2481 Status = PopExpression (Value);\r
2482 if (EFI_ERROR (Status)) {\r
2573712e 2483 goto Done;\r
7936fb6a 2484 }\r
901ba0e7 2485 if (Value->Type != EFI_IFR_TYPE_STRING && Value->Type != EFI_IFR_TYPE_BUFFER) {\r
2573712e
LG
2486 Status = EFI_INVALID_PARAMETER;\r
2487 goto Done;\r
7936fb6a 2488 }\r
2489\r
901ba0e7
ED
2490 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2491 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2492 if (StrPtr == NULL) {\r
2493 Status = EFI_INVALID_PARAMETER;\r
2494 goto Done;\r
2495 }\r
7936fb6a 2496\r
901ba0e7
ED
2497 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2498 Value->Value.u64 = StrLen (StrPtr);\r
2499 FreePool (StrPtr);\r
2500 } else {\r
2501 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2502 Value->Value.u64 = Value->BufferLen;\r
2503 FreePool (Value->Buffer);\r
2504 }\r
7936fb6a 2505 break;\r
2506\r
2507 case EFI_IFR_NOT_OP:\r
2508 Status = PopExpression (Value);\r
2509 if (EFI_ERROR (Status)) {\r
2573712e 2510 goto Done;\r
7936fb6a 2511 }\r
2512 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2513 Status = EFI_INVALID_PARAMETER;\r
2514 goto Done;\r
7936fb6a 2515 }\r
2516 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2517 break;\r
2518\r
2519 case EFI_IFR_QUESTION_REF2_OP:\r
2520 //\r
2521 // Pop an expression from the expression stack\r
2522 //\r
2523 Status = PopExpression (Value);\r
2524 if (EFI_ERROR (Status)) {\r
2573712e 2525 goto Done;\r
7936fb6a 2526 }\r
2527\r
2528 //\r
2529 // Validate the expression value\r
2530 //\r
2531 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2573712e
LG
2532 Status = EFI_NOT_FOUND;\r
2533 goto Done;\r
7936fb6a 2534 }\r
2535\r
2536 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2537 if (Question == NULL) {\r
2573712e
LG
2538 Status = EFI_NOT_FOUND;\r
2539 goto Done;\r
7936fb6a 2540 }\r
2541\r
2542 Value = &Question->HiiValue;\r
2543 break;\r
2544\r
2545 case EFI_IFR_STRING_REF2_OP:\r
2546 //\r
2547 // Pop an expression from the expression stack\r
2548 //\r
2549 Status = PopExpression (Value);\r
2550 if (EFI_ERROR (Status)) {\r
2573712e 2551 goto Done;\r
7936fb6a 2552 }\r
2553\r
2554 //\r
2555 // Validate the expression value\r
2556 //\r
2557 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2573712e
LG
2558 Status = EFI_NOT_FOUND;\r
2559 goto Done;\r
7936fb6a 2560 }\r
2561\r
2562 Value->Type = EFI_IFR_TYPE_STRING;\r
2563 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2564 if (StrPtr == NULL) {\r
2565 //\r
2566 // If String not exit, push an empty string\r
2567 //\r
2568 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2569 } else {\r
2570 Index = (UINT16) Value->Value.u64;\r
2571 Value->Value.string = Index;\r
f4113e1f 2572 FreePool (StrPtr);\r
7936fb6a 2573 }\r
2574 break;\r
2575\r
2576 case EFI_IFR_TO_BOOLEAN_OP:\r
2577 //\r
2578 // Pop an expression from the expression stack\r
2579 //\r
2580 Status = PopExpression (Value);\r
2581 if (EFI_ERROR (Status)) {\r
2573712e 2582 goto Done;\r
7936fb6a 2583 }\r
2584\r
2585 //\r
2586 // Convert an expression to a Boolean\r
2587 //\r
2588 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
2589 //\r
2590 // When converting from an unsigned integer, zero will be converted to\r
2591 // FALSE and any other value will be converted to TRUE.\r
2592 //\r
4140a663 2593 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);\r
7936fb6a 2594\r
2595 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2596 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2597 //\r
2598 // When converting from a string, if case-insensitive compare\r
2599 // with "true" is True, then push True. If a case-insensitive compare\r
39099cbd 2600 // with "false" is True, then push False. Otherwise, push Undefined. \r
7936fb6a 2601 //\r
2602 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2603 if (StrPtr == NULL) {\r
2573712e
LG
2604 Status = EFI_INVALID_PARAMETER;\r
2605 goto Done;\r
7936fb6a 2606 }\r
39099cbd
ED
2607 \r
2608 IfrStrToUpper (StrPtr);\r
2609 if (StrCmp (StrPtr, L"TRUE") == 0){\r
7936fb6a 2610 Value->Value.b = TRUE;\r
39099cbd 2611 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
7936fb6a 2612 Value->Value.b = FALSE;\r
39099cbd
ED
2613 } else {\r
2614 Status = EFI_INVALID_PARAMETER;\r
2615 FreePool (StrPtr);\r
2616 goto Done;\r
7936fb6a 2617 }\r
f4113e1f 2618 FreePool (StrPtr);\r
7936fb6a 2619 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
901ba0e7
ED
2620 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
2621 //\r
2622 // When converting from a buffer, if the buffer is all zeroes, \r
2623 // then push False. Otherwise push True. \r
2624 //\r
2625 for (Index =0; Index < Value->BufferLen; Index ++) {\r
2626 if (Value->Buffer[Index] != 0) { \r
2627 break;\r
2628 }\r
2629 }\r
2630\r
2631 if (Index >= Value->BufferLen) {\r
2632 Value->Value.b = FALSE;\r
2633 } else {\r
2634 Value->Value.b = TRUE;\r
2635 }\r
2636 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2637 FreePool (Value->Buffer);\r
7936fb6a 2638 }\r
2639 break;\r
2640\r
2641 case EFI_IFR_TO_STRING_OP:\r
2642 Status = IfrToString (FormSet, OpCode->Format, Value);\r
2643 break;\r
2644\r
2645 case EFI_IFR_TO_UINT_OP:\r
2646 Status = IfrToUint (FormSet, Value);\r
2647 break;\r
2648\r
2649 case EFI_IFR_TO_LOWER_OP:\r
2650 case EFI_IFR_TO_UPPER_OP:\r
2651 Status = InitializeUnicodeCollationProtocol ();\r
2652 if (EFI_ERROR (Status)) {\r
2573712e 2653 goto Done;\r
7936fb6a 2654 }\r
2655\r
2656 Status = PopExpression (Value);\r
2657 if (EFI_ERROR (Status)) {\r
2573712e 2658 goto Done;\r
7936fb6a 2659 }\r
2660\r
2661 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
2573712e
LG
2662 Status = EFI_UNSUPPORTED;\r
2663 goto Done;\r
7936fb6a 2664 }\r
2665\r
2666 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2667 if (StrPtr == NULL) {\r
2573712e
LG
2668 Status = EFI_NOT_FOUND;\r
2669 goto Done;\r
7936fb6a 2670 }\r
2671\r
2672 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
2673 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
2674 } else {\r
2675 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
2676 }\r
2677 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 2678 FreePool (StrPtr);\r
7936fb6a 2679 break;\r
2680\r
2681 case EFI_IFR_BITWISE_NOT_OP:\r
2682 //\r
2683 // Pop an expression from the expression stack\r
2684 //\r
2685 Status = PopExpression (Value);\r
2686 if (EFI_ERROR (Status)) {\r
2573712e 2687 goto Done;\r
7936fb6a 2688 }\r
2689 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2690 Status = EFI_INVALID_PARAMETER;\r
2691 goto Done;\r
7936fb6a 2692 }\r
2693\r
2694 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2695 Value->Value.u64 = ~Value->Value.u64;\r
2696 break;\r
2697\r
2573712e
LG
2698 case EFI_IFR_SET_OP:\r
2699 //\r
2700 // Pop an expression from the expression stack\r
2701 //\r
2702 Status = PopExpression (Value);\r
2703 if (EFI_ERROR (Status)) {\r
2704 goto Done;\r
2705 }\r
2706 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
2707 Data1.Value.b = FALSE;\r
2708 //\r
2709 // Set value to var storage buffer\r
2710 //\r
2711 if (OpCode->VarStorage != NULL) {\r
2712 switch (OpCode->VarStorage->Type) {\r
2713 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2714 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2715 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
2716 Data1.Value.b = TRUE;\r
2717 break;\r
2718 case EFI_HII_VARSTORE_NAME_VALUE:\r
2719 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2720 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
2721 ASSERT (Value != NULL);\r
2722 //\r
2723 // Convert Buffer to Hex String\r
2724 //\r
2725 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
2726 StrPtr = NameValue;\r
2727 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
2728 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
2729 }\r
b18e7050 2730 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, TRUE);\r
2573712e
LG
2731 FreePool (NameValue);\r
2732 if (!EFI_ERROR (Status)) {\r
2733 Data1.Value.b = TRUE;\r
2734 }\r
2735 }\r
2736 break;\r
2737 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2738 Status = gRT->SetVariable (\r
2739 OpCode->ValueName,\r
2740 &OpCode->VarStorage->Guid,\r
2741 OpCode->VarStorage->Attributes,\r
2742 OpCode->ValueWidth,\r
2743 &Value->Value\r
2744 );\r
2745 if (!EFI_ERROR (Status)) {\r
2746 Data1.Value.b = TRUE;\r
2747 }\r
2748 break;\r
2749 default:\r
2750 //\r
2751 // Not recognize storage.\r
2752 //\r
2753 Status = EFI_UNSUPPORTED;\r
2754 goto Done;\r
2755 break;\r
2756 }\r
2757 } else {\r
2758 //\r
2759 // For Time/Date Data\r
2760 //\r
2761 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2762 //\r
2763 // Only support Data/Time data when storage doesn't exist.\r
2764 //\r
2765 Status = EFI_UNSUPPORTED;\r
2766 goto Done;\r
2767 }\r
2768 Status = gRT->GetTime (&EfiTime, NULL);\r
2769 if (!EFI_ERROR (Status)) {\r
2770 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2771 switch (OpCode->VarStoreInfo.VarOffset) {\r
2772 case 0x00:\r
2773 EfiTime.Year = Value->Value.u16;\r
2774 break;\r
2775 case 0x02:\r
2776 EfiTime.Month = Value->Value.u8;\r
2777 break;\r
2778 case 0x03:\r
2779 EfiTime.Day = Value->Value.u8;\r
2780 break;\r
2781 default:\r
2782 //\r
2783 // Invalid Date field.\r
2784 //\r
2785 Status = EFI_INVALID_PARAMETER;\r
2786 goto Done;\r
2787 }\r
2788 } else {\r
2789 switch (OpCode->VarStoreInfo.VarOffset) {\r
2790 case 0x00:\r
2791 EfiTime.Hour = Value->Value.u8;\r
2792 break;\r
2793 case 0x01:\r
2794 EfiTime.Minute = Value->Value.u8;\r
2795 break;\r
2796 case 0x02:\r
2797 EfiTime.Second = Value->Value.u8;\r
2798 break;\r
2799 default:\r
2800 //\r
2801 // Invalid Time field.\r
2802 //\r
2803 Status = EFI_INVALID_PARAMETER;\r
2804 goto Done;\r
2805 }\r
2806 }\r
2807 Status = gRT->SetTime (&EfiTime);\r
2808 if (!EFI_ERROR (Status)) {\r
2809 Data1.Value.b = TRUE;\r
2810 }\r
2811 }\r
2812 }\r
2813 Value = &Data1;\r
2814 break;\r
2815\r
7936fb6a 2816 //\r
2817 // binary-op\r
2818 //\r
2819 case EFI_IFR_ADD_OP:\r
2820 case EFI_IFR_SUBTRACT_OP:\r
2821 case EFI_IFR_MULTIPLY_OP:\r
2822 case EFI_IFR_DIVIDE_OP:\r
2823 case EFI_IFR_MODULO_OP:\r
2824 case EFI_IFR_BITWISE_AND_OP:\r
2825 case EFI_IFR_BITWISE_OR_OP:\r
2826 case EFI_IFR_SHIFT_LEFT_OP:\r
2827 case EFI_IFR_SHIFT_RIGHT_OP:\r
2828 //\r
2829 // Pop an expression from the expression stack\r
2830 //\r
2831 Status = PopExpression (&Data2);\r
2832 if (EFI_ERROR (Status)) {\r
2573712e 2833 goto Done;\r
7936fb6a 2834 }\r
2835 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2836 Status = EFI_INVALID_PARAMETER;\r
2837 goto Done;\r
7936fb6a 2838 }\r
2839\r
2840 //\r
2841 // Pop another expression from the expression stack\r
2842 //\r
2843 Status = PopExpression (&Data1);\r
2844 if (EFI_ERROR (Status)) {\r
2573712e 2845 goto Done;\r
7936fb6a 2846 }\r
2847 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2848 Status = EFI_INVALID_PARAMETER;\r
2849 goto Done;\r
7936fb6a 2850 }\r
2851\r
2852 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2853\r
2854 switch (OpCode->Operand) {\r
2855 case EFI_IFR_ADD_OP:\r
2856 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
2857 break;\r
2858\r
2859 case EFI_IFR_SUBTRACT_OP:\r
2860 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
2861 break;\r
2862\r
2863 case EFI_IFR_MULTIPLY_OP:\r
2864 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2865 break;\r
2866\r
2867 case EFI_IFR_DIVIDE_OP:\r
2868 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2869 break;\r
2870\r
2871 case EFI_IFR_MODULO_OP:\r
2872 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
2873 Value->Value.u64 = TempValue;\r
2874 break;\r
2875\r
2876 case EFI_IFR_BITWISE_AND_OP:\r
2877 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
2878 break;\r
2879\r
2880 case EFI_IFR_BITWISE_OR_OP:\r
2881 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
2882 break;\r
2883\r
2884 case EFI_IFR_SHIFT_LEFT_OP:\r
2885 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2886 break;\r
2887\r
2888 case EFI_IFR_SHIFT_RIGHT_OP:\r
2889 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2890 break;\r
2891\r
2892 default:\r
2893 break;\r
2894 }\r
2895 break;\r
2896\r
2897 case EFI_IFR_AND_OP:\r
2898 case EFI_IFR_OR_OP:\r
2899 //\r
2900 // Two Boolean operator\r
2901 //\r
2902 Status = PopExpression (&Data2);\r
2903 if (EFI_ERROR (Status)) {\r
2573712e 2904 goto Done;\r
7936fb6a 2905 }\r
2906 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2907 Status = EFI_INVALID_PARAMETER;\r
2908 goto Done;\r
7936fb6a 2909 }\r
2910\r
2911 //\r
2912 // Pop another expression from the expression stack\r
2913 //\r
2914 Status = PopExpression (&Data1);\r
2915 if (EFI_ERROR (Status)) {\r
2573712e 2916 goto Done;\r
7936fb6a 2917 }\r
2918 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2919 Status = EFI_INVALID_PARAMETER;\r
2920 goto Done;\r
7936fb6a 2921 }\r
2922\r
2923 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
2924 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
2925 } else {\r
2926 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
2927 }\r
2928 break;\r
2929\r
2930 case EFI_IFR_EQUAL_OP:\r
2931 case EFI_IFR_NOT_EQUAL_OP:\r
2932 case EFI_IFR_GREATER_EQUAL_OP:\r
2933 case EFI_IFR_GREATER_THAN_OP:\r
2934 case EFI_IFR_LESS_EQUAL_OP:\r
2935 case EFI_IFR_LESS_THAN_OP:\r
2936 //\r
2937 // Compare two integer, string, boolean or date/time\r
2938 //\r
2939 Status = PopExpression (&Data2);\r
2940 if (EFI_ERROR (Status)) {\r
2573712e 2941 goto Done;\r
7936fb6a 2942 }\r
901ba0e7
ED
2943 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
2944 Data2.Type != EFI_IFR_TYPE_STRING && \r
2945 Data2.Type != EFI_IFR_TYPE_BUFFER) {\r
2573712e
LG
2946 Status = EFI_INVALID_PARAMETER;\r
2947 goto Done;\r
7936fb6a 2948 }\r
2949\r
2950 //\r
2951 // Pop another expression from the expression stack\r
2952 //\r
2953 Status = PopExpression (&Data1);\r
2954 if (EFI_ERROR (Status)) {\r
2573712e 2955 goto Done;\r
7936fb6a 2956 }\r
2957\r
2958 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
901ba0e7
ED
2959 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
2960 FreePool (Data1.Buffer);\r
2961 FreePool (Data2.Buffer);\r
2962 }\r
2963 \r
7936fb6a 2964 if (Result == EFI_INVALID_PARAMETER) {\r
2573712e
LG
2965 Status = EFI_INVALID_PARAMETER;\r
2966 goto Done;\r
7936fb6a 2967 }\r
2968\r
2969 switch (OpCode->Operand) {\r
2970 case EFI_IFR_EQUAL_OP:\r
2971 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2972 break;\r
2973\r
2974 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 2975 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 2976 break;\r
2977\r
2978 case EFI_IFR_GREATER_EQUAL_OP:\r
2979 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
2980 break;\r
2981\r
2982 case EFI_IFR_GREATER_THAN_OP:\r
2983 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
2984 break;\r
2985\r
2986 case EFI_IFR_LESS_EQUAL_OP:\r
2987 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
2988 break;\r
2989\r
2990 case EFI_IFR_LESS_THAN_OP:\r
2991 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
2992 break;\r
2993\r
2994 default:\r
2995 break;\r
2996 }\r
2997 break;\r
2998\r
2999 case EFI_IFR_MATCH_OP:\r
20258293
ED
3000 Status = InitializeUnicodeCollationProtocol ();\r
3001 if (EFI_ERROR (Status)) {\r
3002 goto Done;\r
3003 }\r
3004 \r
7936fb6a 3005 Status = IfrMatch (FormSet, Value);\r
3006 break;\r
3007\r
3008 case EFI_IFR_CATENATE_OP:\r
3009 Status = IfrCatenate (FormSet, Value);\r
3010 break;\r
3011\r
3012 //\r
3013 // ternary-op\r
3014 //\r
3015 case EFI_IFR_CONDITIONAL_OP:\r
3016 //\r
3017 // Pop third expression from the expression stack\r
3018 //\r
3019 Status = PopExpression (&Data3);\r
3020 if (EFI_ERROR (Status)) {\r
2573712e 3021 goto Done;\r
7936fb6a 3022 }\r
3023\r
3024 //\r
3025 // Pop second expression from the expression stack\r
3026 //\r
3027 Status = PopExpression (&Data2);\r
3028 if (EFI_ERROR (Status)) {\r
2573712e 3029 goto Done;\r
7936fb6a 3030 }\r
3031\r
3032 //\r
3033 // Pop first expression from the expression stack\r
3034 //\r
3035 Status = PopExpression (&Data1);\r
3036 if (EFI_ERROR (Status)) {\r
2573712e 3037 goto Done;\r
7936fb6a 3038 }\r
3039 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
3040 Status = EFI_INVALID_PARAMETER;\r
3041 goto Done;\r
7936fb6a 3042 }\r
3043\r
3044 if (Data1.Value.b) {\r
3045 Value = &Data3;\r
3046 } else {\r
3047 Value = &Data2;\r
3048 }\r
3049 break;\r
3050\r
3051 case EFI_IFR_FIND_OP:\r
3052 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3053 break;\r
3054\r
3055 case EFI_IFR_MID_OP:\r
3056 Status = IfrMid (FormSet, Value);\r
3057 break;\r
3058\r
3059 case EFI_IFR_TOKEN_OP:\r
3060 Status = IfrToken (FormSet, Value);\r
3061 break;\r
3062\r
3063 case EFI_IFR_SPAN_OP:\r
3064 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3065 break;\r
3066\r
2573712e
LG
3067 case EFI_IFR_MAP_OP:\r
3068 //\r
3069 // Pop the check value\r
3070 //\r
3071 Status = PopExpression (&Data1);\r
3072 if (EFI_ERROR (Status)) {\r
3073 goto Done;\r
3074 }\r
3075 //\r
3076 // Check MapExpression list is valid.\r
3077 //\r
3078 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
3079 Status = EFI_INVALID_PARAMETER;\r
3080 goto Done;\r
3081 }\r
3082 //\r
3083 // Go through map expression list.\r
3084 //\r
3085 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
3086 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3087 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3088 //\r
3089 // Evaluate the first expression in this pair.\r
3090 //\r
3091 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3092 if (EFI_ERROR (Status)) {\r
3093 goto Done;\r
3094 }\r
3095 //\r
3096 // Compare the expression value with current value\r
3097 //\r
3098 if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) {\r
3099 //\r
3100 // Try get the map value.\r
3101 //\r
3102 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3103 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3104 Status = EFI_INVALID_PARAMETER;\r
3105 goto Done;\r
3106 }\r
3107 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3108 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3109 if (EFI_ERROR (Status)) {\r
3110 goto Done;\r
3111 }\r
3112 Value = &SubExpression->Result;\r
3113 break;\r
3114 }\r
3115 //\r
3116 // Skip the second expression on this pair.\r
3117 //\r
3118 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3119 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3120 Status = EFI_INVALID_PARAMETER;\r
3121 goto Done;\r
3122 }\r
3123 //\r
3124 // Goto the first expression on next pair.\r
3125 //\r
3126 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3127 }\r
3128\r
3129 //\r
3130 // No map value is found.\r
3131 //\r
3132 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3133 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3134 Value->Value.u8 = 0;\r
3135 }\r
3136 break;\r
3137\r
7936fb6a 3138 default:\r
3139 break;\r
3140 }\r
3141 if (EFI_ERROR (Status)) {\r
2573712e 3142 goto Done;\r
7936fb6a 3143 }\r
3144\r
3145 Status = PushExpression (Value);\r
3146 if (EFI_ERROR (Status)) {\r
2573712e 3147 goto Done;\r
7936fb6a 3148 }\r
3149 }\r
3150\r
3151 //\r
3152 // Pop the final result from expression stack\r
3153 //\r
3154 Value = &Data1;\r
3155 Status = PopExpression (Value);\r
3156 if (EFI_ERROR (Status)) {\r
2573712e 3157 goto Done;\r
7936fb6a 3158 }\r
3159\r
3160 //\r
3161 // After evaluating an expression, there should be only one value left on the expression stack\r
3162 //\r
3163 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 3164 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 3165 }\r
3166\r
2573712e
LG
3167Done:\r
3168 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3169 if (!EFI_ERROR (Status)) {\r
3170 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3171 }\r
7936fb6a 3172\r
2573712e 3173 return Status;\r
7936fb6a 3174}\r
31585af4
ED
3175\r
3176/**\r
3177 Return the result of the expression list. Check the expression list and \r
3178 return the highest priority express result. \r
3179 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
3180\r
3181 @param ExpList The input expression list.\r
3182 @param Evaluate Whether need to evaluate the expression first.\r
3183 @param FormSet FormSet associated with this expression.\r
3184 @param Form Form associated with this expression. \r
3185\r
3186 @retval EXPRESS_RESULT Return the higher priority express result. \r
3187 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3188\r
3189**/\r
3190EXPRESS_RESULT \r
3191EvaluateExpressionList (\r
3192 IN FORM_EXPRESSION_LIST *ExpList,\r
3193 IN BOOLEAN Evaluate,\r
3194 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
3195 IN FORM_BROWSER_FORM *Form OPTIONAL\r
3196 )\r
3197{\r
3198 UINTN Index;\r
3199 EXPRESS_RESULT ReturnVal;\r
3200 EXPRESS_RESULT CompareOne;\r
3201 EFI_STATUS Status;\r
3202\r
3203 if (ExpList == NULL) {\r
3204 return ExpressFalse;\r
3205 }\r
3206\r
3207 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3208 Index = 0;\r
3209\r
3210 //\r
3211 // Check whether need to evaluate the expression first.\r
3212 //\r
3213 if (Evaluate) { \r
3214 while (ExpList->Count > Index) {\r
3215 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
3216 if (EFI_ERROR (Status)) {\r
3217 return ExpressFalse;\r
3218 }\r
3219 }\r
3220 }\r
3221\r
3222 //\r
3223 // Run the list of expressions.\r
3224 //\r
3225 ReturnVal = ExpressFalse;\r
3226 for (Index = 0; Index < ExpList->Count; Index++) {\r
3227 if (ExpList->Expression[Index]->Result.Type == EFI_IFR_TYPE_BOOLEAN &&\r
3228 ExpList->Expression[Index]->Result.Value.b) {\r
3229 switch (ExpList->Expression[Index]->Type) {\r
3230 case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
3231 CompareOne = ExpressSuppress;\r
3232 break;\r
3233\r
3234 case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
3235 CompareOne = ExpressGrayOut;\r
3236 break;\r
3237\r
3238 case EFI_HII_EXPRESSION_DISABLE_IF:\r
3239 CompareOne = ExpressDisable;\r
3240 break;\r
3241\r
3242 default:\r
3243 return ExpressFalse; \r
3244 }\r
3245\r
3246 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3247 }\r
3248 }\r
3249 \r
3250 return ReturnVal;\r
3251}\r