]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
MdeModulePkg: Fix Typo.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
9bd22b08 4Copyright (c) 2007 - 2015, 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
7c6c064c 790 )\r
7936fb6a 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
816a7110 894 GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
8d00a0f1 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
40578d09
ED
991/**\r
992 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
993\r
994 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
995 EFI_IFR_TYPE_BUFFER when do the value compare.\r
996\r
997 @param Value Expression value to compare on.\r
998\r
999 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
1000 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
1001\r
1002**/\r
1003BOOLEAN\r
1004IsTypeInBuffer (\r
1005 IN EFI_HII_VALUE *Value\r
1006 )\r
1007{\r
1008 switch (Value->Type) {\r
1009 case EFI_IFR_TYPE_BUFFER:\r
1010 case EFI_IFR_TYPE_DATE:\r
1011 case EFI_IFR_TYPE_TIME:\r
1012 case EFI_IFR_TYPE_REF:\r
1013 return TRUE;\r
1014\r
1015 default:\r
1016 return FALSE;\r
1017 }\r
1018}\r
1019\r
1020/**\r
1021 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64\r
1022\r
1023 @param Value Expression value to compare on.\r
1024\r
1025 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
1026 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
1027\r
1028**/\r
1029BOOLEAN\r
1030IsTypeInUINT64 (\r
1031 IN EFI_HII_VALUE *Value\r
1032 )\r
1033{\r
1034 switch (Value->Type) {\r
1035 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1036 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1037 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1038 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1039 case EFI_IFR_TYPE_BOOLEAN:\r
1040 return TRUE;\r
1041\r
1042 default:\r
1043 return FALSE;\r
1044 }\r
1045}\r
1046\r
1047/**\r
1048 Return the buffer length for this value.\r
1049\r
1050 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
1051 EFI_IFR_TYPE_BUFFER when do the value compare.\r
1052\r
1053 @param Value Expression value to compare on.\r
1054 \r
1055 @retval BufLen Return the buffer length.\r
1056\r
1057**/\r
1058UINT16\r
1059GetLengthForValue (\r
1060 IN EFI_HII_VALUE *Value\r
1061 )\r
1062{\r
1063 switch (Value->Type) {\r
1064 case EFI_IFR_TYPE_BUFFER:\r
1065 return Value->BufferLen;\r
1066\r
1067 case EFI_IFR_TYPE_DATE:\r
1068 return (UINT16) sizeof (EFI_HII_DATE);\r
1069\r
1070 case EFI_IFR_TYPE_TIME:\r
1071 return (UINT16) sizeof (EFI_HII_TIME);\r
1072\r
1073 case EFI_IFR_TYPE_REF:\r
1074 return (UINT16) sizeof (EFI_HII_REF);\r
1075\r
1076 default:\r
1077 return 0;\r
1078 }\r
1079}\r
1080\r
1081/**\r
1082 Return the buffer pointer for this value.\r
1083\r
1084 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
1085 EFI_IFR_TYPE_BUFFER when do the value compare.\r
1086\r
1087 @param Value Expression value to compare on.\r
1088\r
1089 @retval Buf Return the buffer pointer.\r
1090\r
1091**/\r
1092UINT8 *\r
1093GetBufferForValue (\r
1094 IN EFI_HII_VALUE *Value\r
1095 )\r
1096{\r
1097 switch (Value->Type) {\r
1098 case EFI_IFR_TYPE_BUFFER:\r
1099 return Value->Buffer;\r
1100\r
1101 case EFI_IFR_TYPE_DATE:\r
1102 return (UINT8 *) (&Value->Value.date);\r
1103\r
1104 case EFI_IFR_TYPE_TIME:\r
1105 return (UINT8 *) (&Value->Value.time);\r
1106\r
1107 case EFI_IFR_TYPE_REF:\r
1108 return (UINT8 *) (&Value->Value.ref);\r
1109\r
1110 default:\r
1111 return NULL;\r
1112 }\r
1113}\r
7936fb6a 1114\r
1115/**\r
1116 Evaluate opcode EFI_IFR_TO_STRING.\r
1117\r
1118 @param FormSet Formset which contains this opcode.\r
1119 @param Format String format in EFI_IFR_TO_STRING.\r
1120 @param Result Evaluation result for this opcode.\r
1121\r
1122 @retval EFI_SUCCESS Opcode evaluation success.\r
1123 @retval Other Opcode evaluation failed.\r
1124\r
1125**/\r
1126EFI_STATUS\r
1127IfrToString (\r
1128 IN FORM_BROWSER_FORMSET *FormSet,\r
1129 IN UINT8 Format,\r
1130 OUT EFI_HII_VALUE *Result\r
1131 )\r
1132{\r
1133 EFI_STATUS Status;\r
1134 EFI_HII_VALUE Value;\r
1135 CHAR16 *String;\r
1136 CHAR16 *PrintFormat;\r
1137 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
901ba0e7 1138 UINT8 *TmpBuf;\r
40578d09
ED
1139 UINT8 *SrcBuf;\r
1140 UINTN SrcLen;\r
7936fb6a 1141 UINTN BufferSize;\r
1142\r
1143 Status = PopExpression (&Value);\r
1144 if (EFI_ERROR (Status)) {\r
1145 return Status;\r
1146 }\r
1147\r
1148 switch (Value.Type) {\r
1149 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1150 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1151 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1152 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1153 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
1154 switch (Format) {\r
1155 case EFI_IFR_STRING_UNSIGNED_DEC:\r
1156 case EFI_IFR_STRING_SIGNED_DEC:\r
1157 PrintFormat = L"%ld";\r
1158 break;\r
1159\r
1160 case EFI_IFR_STRING_LOWERCASE_HEX:\r
1161 PrintFormat = L"%lx";\r
1162 break;\r
1163\r
1164 case EFI_IFR_STRING_UPPERCASE_HEX:\r
1165 PrintFormat = L"%lX";\r
1166 break;\r
1167\r
1168 default:\r
8f420676
ED
1169 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1170 return EFI_SUCCESS;\r
7936fb6a 1171 }\r
1172 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
1173 String = Buffer;\r
1174 break;\r
1175\r
1176 case EFI_IFR_TYPE_STRING:\r
1177 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1178 return EFI_SUCCESS;\r
1179\r
1180 case EFI_IFR_TYPE_BOOLEAN:\r
1181 String = (Value.Value.b) ? L"True" : L"False";\r
1182 break;\r
901ba0e7
ED
1183 \r
1184 case EFI_IFR_TYPE_BUFFER:\r
40578d09
ED
1185 case EFI_IFR_TYPE_DATE:\r
1186 case EFI_IFR_TYPE_TIME:\r
1187 case EFI_IFR_TYPE_REF:\r
901ba0e7
ED
1188 //\r
1189 // + 3 is base on the unicode format, the length may be odd number, \r
1190 // so need 1 byte to align, also need 2 bytes for L'\0'.\r
1191 //\r
40578d09
ED
1192 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1193 SrcLen = Value.BufferLen;\r
1194 SrcBuf = Value.Buffer;\r
1195 } else {\r
1196 SrcBuf = GetBufferForValue(&Value);\r
1197 SrcLen = GetLengthForValue(&Value);\r
1198 }\r
1199\r
1200 TmpBuf = AllocateZeroPool (SrcLen + 3);\r
db40504e 1201 ASSERT (TmpBuf != NULL);\r
901ba0e7 1202 if (Format == EFI_IFR_STRING_ASCII) {\r
40578d09 1203 CopyMem (TmpBuf, SrcBuf, SrcLen);\r
901ba0e7
ED
1204 PrintFormat = L"%a"; \r
1205 } else {\r
1206 // Format == EFI_IFR_STRING_UNICODE\r
40578d09 1207 CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16));\r
901ba0e7
ED
1208 PrintFormat = L"%s"; \r
1209 }\r
40578d09 1210 UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf);\r
901ba0e7
ED
1211 String = Buffer; \r
1212 FreePool (TmpBuf);\r
40578d09
ED
1213 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1214 FreePool (Value.Buffer);\r
1215 }\r
901ba0e7
ED
1216 break;\r
1217 \r
7936fb6a 1218 default:\r
8f420676
ED
1219 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1220 return EFI_SUCCESS;\r
7936fb6a 1221 }\r
1222\r
1223 Result->Type = EFI_IFR_TYPE_STRING;\r
1224 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
1225 return EFI_SUCCESS;\r
1226}\r
1227\r
1228\r
1229/**\r
1230 Evaluate opcode EFI_IFR_TO_UINT.\r
1231\r
1232 @param FormSet Formset which contains this opcode.\r
1233 @param Result Evaluation result for this opcode.\r
1234\r
1235 @retval EFI_SUCCESS Opcode evaluation success.\r
1236 @retval Other Opcode evaluation failed.\r
1237\r
1238**/\r
1239EFI_STATUS\r
1240IfrToUint (\r
1241 IN FORM_BROWSER_FORMSET *FormSet,\r
1242 OUT EFI_HII_VALUE *Result\r
1243 )\r
1244{\r
1245 EFI_STATUS Status;\r
1246 EFI_HII_VALUE Value;\r
1247 CHAR16 *String;\r
1248 CHAR16 *StringPtr;\r
7936fb6a 1249\r
1250 Status = PopExpression (&Value);\r
1251 if (EFI_ERROR (Status)) {\r
1252 return Status;\r
1253 }\r
1254\r
40578d09 1255 if (Value.Type >= EFI_IFR_TYPE_OTHER && !IsTypeInBuffer(&Value)) {\r
8f420676
ED
1256 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1257 return EFI_SUCCESS;\r
7936fb6a 1258 }\r
1259\r
1260 Status = EFI_SUCCESS;\r
1261 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
1262 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1263 if (String == NULL) {\r
1264 return EFI_NOT_FOUND;\r
1265 }\r
8b0fc5c1 1266\r
7936fb6a 1267 IfrStrToUpper (String);\r
1268 StringPtr = StrStr (String, L"0X");\r
1269 if (StringPtr != NULL) {\r
1270 //\r
1271 // Hex string\r
1272 //\r
ac7e320c 1273 Result->Value.u64 = StrHexToUint64 (String);\r
7936fb6a 1274 } else {\r
1275 //\r
ac7e320c 1276 // decimal string\r
7936fb6a 1277 //\r
ac7e320c 1278 Result->Value.u64 = StrDecimalToUint64 (String);\r
7936fb6a 1279 }\r
f4113e1f 1280 FreePool (String);\r
40578d09
ED
1281 } else if (IsTypeInBuffer(&Value)) {\r
1282 if (GetLengthForValue (&Value) > 8) {\r
1283 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1284 FreePool (Value.Buffer);\r
1285 }\r
8f420676
ED
1286 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1287 return EFI_SUCCESS;\r
901ba0e7 1288 }\r
40578d09
ED
1289 Result->Value.u64 = *(UINT64*) GetBufferForValue (&Value);\r
1290 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1291 FreePool (Value.Buffer);\r
1292 }\r
7936fb6a 1293 } else {\r
1294 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1295 }\r
1296\r
1297 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1298 return Status;\r
1299}\r
1300\r
1301\r
1302/**\r
1303 Evaluate opcode EFI_IFR_CATENATE.\r
1304\r
1305 @param FormSet Formset which contains this opcode.\r
1306 @param Result Evaluation result for this opcode.\r
1307\r
1308 @retval EFI_SUCCESS Opcode evaluation success.\r
1309 @retval Other Opcode evaluation failed.\r
1310\r
1311**/\r
1312EFI_STATUS\r
1313IfrCatenate (\r
1314 IN FORM_BROWSER_FORMSET *FormSet,\r
1315 OUT EFI_HII_VALUE *Result\r
1316 )\r
1317{\r
1318 EFI_STATUS Status;\r
901ba0e7 1319 EFI_HII_VALUE Value[2];\r
7936fb6a 1320 CHAR16 *String[2];\r
1321 UINTN Index;\r
1322 CHAR16 *StringPtr;\r
1323 UINTN Size;\r
40578d09
ED
1324 UINT16 Length0;\r
1325 UINT16 Length1;\r
784952b1 1326 UINT8 *TmpBuf;\r
7936fb6a 1327\r
1328 //\r
1329 // String[0] - The second string\r
1330 // String[1] - The first string\r
1331 //\r
1332 String[0] = NULL;\r
1333 String[1] = NULL;\r
1334 StringPtr = NULL;\r
1335 Status = EFI_SUCCESS;\r
901ba0e7 1336 ZeroMem (Value, sizeof (Value));\r
7936fb6a 1337\r
8f420676
ED
1338 Status = PopExpression (&Value[0]);\r
1339 if (EFI_ERROR (Status)) {\r
1340 goto Done;\r
1341 }\r
1342\r
1343 Status = PopExpression (&Value[1]);\r
1344 if (EFI_ERROR (Status)) {\r
1345 goto Done;\r
1346 }\r
7936fb6a 1347\r
8f420676 1348 for (Index = 0; Index < 2; Index++) {\r
40578d09 1349 if (Value[Index].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[Index])) {\r
8f420676
ED
1350 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1351 Status = EFI_SUCCESS;\r
7936fb6a 1352 goto Done;\r
1353 }\r
1354\r
901ba0e7
ED
1355 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
1356 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1357 if (String[Index] == NULL) {\r
1358 Status = EFI_NOT_FOUND;\r
1359 goto Done;\r
1360 }\r
7936fb6a 1361 }\r
1362 }\r
1363\r
901ba0e7
ED
1364 if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
1365 Size = StrSize (String[0]);\r
1366 StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
1367 ASSERT (StringPtr != NULL);\r
1368 StrCpy (StringPtr, String[1]);\r
1369 StrCat (StringPtr, String[0]);\r
7936fb6a 1370\r
901ba0e7
ED
1371 Result->Type = EFI_IFR_TYPE_STRING;\r
1372 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
1373 } else {\r
1374 Result->Type = EFI_IFR_TYPE_BUFFER;\r
40578d09
ED
1375 Length0 = GetLengthForValue(&Value[0]);\r
1376 Length1 = GetLengthForValue(&Value[1]);\r
1377 Result->BufferLen = (UINT16) (Length0 + Length1);\r
901ba0e7
ED
1378\r
1379 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1380 ASSERT (Result->Buffer != NULL);\r
7936fb6a 1381\r
784952b1
ED
1382 TmpBuf = GetBufferForValue(&Value[0]);\r
1383 ASSERT (TmpBuf != NULL);\r
1384 CopyMem (Result->Buffer, TmpBuf, Length0);\r
1385 TmpBuf = GetBufferForValue(&Value[1]);\r
1386 ASSERT (TmpBuf != NULL);\r
1387 CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);\r
901ba0e7 1388 }\r
7936fb6a 1389Done:\r
901ba0e7
ED
1390 if (Value[0].Buffer != NULL) {\r
1391 FreePool (Value[0].Buffer);\r
1392 }\r
1393 if (Value[1].Buffer != NULL) {\r
1394 FreePool (Value[1].Buffer);\r
1395 }\r
676df92c 1396 if (String[0] != NULL) {\r
1397 FreePool (String[0]);\r
1398 }\r
1399 if (String[1] != NULL) {\r
1400 FreePool (String[1]);\r
8b0fc5c1 1401 }\r
676df92c 1402 if (StringPtr != NULL) {\r
1403 FreePool (StringPtr);\r
1404 }\r
7936fb6a 1405\r
1406 return Status;\r
1407}\r
1408\r
1409\r
1410/**\r
1411 Evaluate opcode EFI_IFR_MATCH.\r
1412\r
1413 @param FormSet Formset which contains this opcode.\r
1414 @param Result Evaluation result for this opcode.\r
1415\r
1416 @retval EFI_SUCCESS Opcode evaluation success.\r
1417 @retval Other Opcode evaluation failed.\r
1418\r
1419**/\r
1420EFI_STATUS\r
1421IfrMatch (\r
1422 IN FORM_BROWSER_FORMSET *FormSet,\r
1423 OUT EFI_HII_VALUE *Result\r
1424 )\r
1425{\r
1426 EFI_STATUS Status;\r
8f420676 1427 EFI_HII_VALUE Value[2];\r
7936fb6a 1428 CHAR16 *String[2];\r
1429 UINTN Index;\r
1430\r
1431 //\r
1432 // String[0] - The string to search\r
1433 // String[1] - pattern\r
1434 //\r
1435 String[0] = NULL;\r
1436 String[1] = NULL;\r
1437 Status = EFI_SUCCESS;\r
8f420676
ED
1438 ZeroMem (Value, sizeof (Value));\r
1439\r
1440 Status = PopExpression (&Value[0]);\r
1441 if (EFI_ERROR (Status)) {\r
1442 goto Done;\r
1443 }\r
1444\r
1445 Status = PopExpression (&Value[1]);\r
1446 if (EFI_ERROR (Status)) {\r
1447 goto Done;\r
1448 }\r
7936fb6a 1449\r
8f420676
ED
1450 for (Index = 0; Index < 2; Index++) {\r
1451 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
1452 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1453 Status = EFI_SUCCESS;\r
7936fb6a 1454 goto Done;\r
1455 }\r
1456\r
8f420676 1457 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
bc166db3 1458 if (String [Index] == NULL) {\r
7936fb6a 1459 Status = EFI_NOT_FOUND;\r
1460 goto Done;\r
1461 }\r
1462 }\r
1463\r
1464 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1465 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
1466\r
1467Done:\r
676df92c 1468 if (String[0] != NULL) {\r
1469 FreePool (String[0]);\r
1470 }\r
1471 if (String[1] != NULL) {\r
1472 FreePool (String[1]);\r
8b0fc5c1 1473 }\r
7936fb6a 1474\r
1475 return Status;\r
1476}\r
1477\r
9bd22b08
ED
1478/**\r
1479 Evaluate opcode EFI_IFR_MATCH2.\r
1480\r
1481 @param FormSet Formset which contains this opcode.\r
1482 @param SyntaxType Syntax type for match2.\r
1483 @param Result Evaluation result for this opcode.\r
1484\r
1485 @retval EFI_SUCCESS Opcode evaluation success.\r
1486 @retval Other Opcode evaluation failed.\r
1487\r
1488**/\r
1489EFI_STATUS\r
1490IfrMatch2 (\r
1491 IN FORM_BROWSER_FORMSET *FormSet,\r
1492 IN EFI_GUID *SyntaxType,\r
1493 OUT EFI_HII_VALUE *Result\r
1494 )\r
1495{\r
1496 EFI_STATUS Status;\r
1497 EFI_HII_VALUE Value[2];\r
1498 CHAR16 *String[2];\r
1499 UINTN Index;\r
1500 UINTN GuidIndex;\r
1501 EFI_HANDLE *HandleBuffer;\r
1502 UINTN BufferSize;\r
1503 EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol;\r
1504 UINTN RegExSyntaxTypeListSize;\r
1505 EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList;\r
1506 UINTN CapturesCount;\r
1507\r
1508 //\r
1509 // String[0] - The string to search\r
1510 // String[1] - pattern\r
1511 //\r
1512 String[0] = NULL;\r
1513 String[1] = NULL;\r
1514 HandleBuffer = NULL;\r
1515 RegExSyntaxTypeList = NULL;\r
1516 Status = EFI_SUCCESS;\r
1517 ZeroMem (Value, sizeof (Value));\r
1518\r
1519 Status = PopExpression (&Value[0]);\r
1520 if (EFI_ERROR (Status)) {\r
1521 goto Done;\r
1522 }\r
1523\r
1524 Status = PopExpression (&Value[1]);\r
1525 if (EFI_ERROR (Status)) {\r
1526 goto Done;\r
1527 }\r
1528\r
1529 for (Index = 0; Index < 2; Index++) {\r
1530 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
1531 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1532 Status = EFI_SUCCESS;\r
1533 goto Done;\r
1534 }\r
1535\r
1536 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1537 if (String [Index] == NULL) {\r
1538 Status = EFI_NOT_FOUND;\r
1539 goto Done;\r
1540 }\r
1541 }\r
1542\r
1543 BufferSize = 0;\r
1544 HandleBuffer = NULL;\r
1545 Status = gBS->LocateHandle(\r
1546 ByProtocol,\r
1547 &gEfiRegularExpressionProtocolGuid,\r
1548 NULL,\r
1549 &BufferSize,\r
1550 HandleBuffer);\r
1551 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1552 HandleBuffer = AllocateZeroPool(BufferSize);\r
1553 if (HandleBuffer == NULL) {\r
1554 Status = EFI_OUT_OF_RESOURCES;\r
1555 goto Done;\r
1556 }\r
1557 Status = gBS->LocateHandle(\r
1558 ByProtocol,\r
1559 &gEfiRegularExpressionProtocolGuid,\r
1560 NULL,\r
1561 &BufferSize,\r
1562 HandleBuffer);\r
1563\r
1564 } else if (EFI_ERROR (Status)) {\r
1a03ab8a 1565 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
9bd22b08
ED
1566 Status = EFI_SUCCESS;\r
1567 goto Done;\r
1568 }\r
1569\r
1570 for ( Index = 0; Index < BufferSize / sizeof(EFI_HANDLE); Index ++) {\r
1571 Status = gBS->HandleProtocol (\r
1572 HandleBuffer[Index],\r
1573 &gEfiRegularExpressionProtocolGuid,\r
1574 (VOID**)&RegularExpressionProtocol\r
1575 );\r
1576 if (EFI_ERROR (Status)) {\r
1577 goto Done;\r
1578 }\r
1579\r
1580 RegExSyntaxTypeListSize = 0;\r
1581 RegExSyntaxTypeList = NULL;\r
1582\r
1583 Status = RegularExpressionProtocol->GetInfo (\r
1584 RegularExpressionProtocol, \r
1585 &RegExSyntaxTypeListSize, \r
1586 RegExSyntaxTypeList\r
1587 );\r
1588 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1589 RegExSyntaxTypeList = AllocateZeroPool(RegExSyntaxTypeListSize);\r
1590 if (RegExSyntaxTypeList == NULL) {\r
1591 Status = EFI_OUT_OF_RESOURCES;\r
1592 goto Done;\r
1593 }\r
1594 Status = RegularExpressionProtocol->GetInfo (\r
1595 RegularExpressionProtocol, \r
1596 &RegExSyntaxTypeListSize, \r
1597 RegExSyntaxTypeList\r
1598 );\r
1599 } else if (EFI_ERROR (Status)) {\r
1600 goto Done;\r
1601 }\r
1602\r
1603 for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof(EFI_GUID); GuidIndex++) {\r
1604 if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {\r
1605 //\r
1606 // Find the match type, return the value.\r
1607 //\r
1608 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1609 Status = RegularExpressionProtocol->MatchString (\r
1610 RegularExpressionProtocol, \r
1611 String[0],\r
1612 String[1],\r
1613 SyntaxType,\r
1614 &Result->Value.b,\r
1615 NULL,\r
1616 &CapturesCount\r
1617 );\r
1618 goto Done;\r
1619 }\r
1620 }\r
1621\r
1622 if (RegExSyntaxTypeList != NULL) {\r
1623 FreePool (RegExSyntaxTypeList);\r
1624 }\r
1625 }\r
1626\r
1627 //\r
1628 // Type specified by SyntaxType is not supported \r
1629 // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.\r
1630 //\r
1a03ab8a 1631 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
9bd22b08
ED
1632 Status = EFI_SUCCESS;\r
1633\r
1634Done:\r
1635 if (String[0] != NULL) {\r
1636 FreePool (String[0]);\r
1637 }\r
1638 if (String[1] != NULL) {\r
1639 FreePool (String[1]);\r
1640 }\r
1641 if (RegExSyntaxTypeList != NULL) {\r
1642 FreePool (RegExSyntaxTypeList);\r
1643 }\r
1644 if (HandleBuffer != NULL) {\r
1645 FreePool (HandleBuffer);\r
1646 }\r
1647 return Status;\r
1648}\r
7936fb6a 1649\r
1650/**\r
1651 Evaluate opcode EFI_IFR_FIND.\r
1652\r
1653 @param FormSet Formset which contains this opcode.\r
1654 @param Format Case sensitive or insensitive.\r
1655 @param Result Evaluation result for this opcode.\r
1656\r
1657 @retval EFI_SUCCESS Opcode evaluation success.\r
1658 @retval Other Opcode evaluation failed.\r
1659\r
1660**/\r
1661EFI_STATUS\r
1662IfrFind (\r
1663 IN FORM_BROWSER_FORMSET *FormSet,\r
1664 IN UINT8 Format,\r
1665 OUT EFI_HII_VALUE *Result\r
1666 )\r
1667{\r
1668 EFI_STATUS Status;\r
8f420676 1669 EFI_HII_VALUE Value[3];\r
7936fb6a 1670 CHAR16 *String[2];\r
1671 UINTN Base;\r
1672 CHAR16 *StringPtr;\r
1673 UINTN Index;\r
1674\r
8f420676
ED
1675 ZeroMem (Value, sizeof (Value));\r
1676\r
7936fb6a 1677 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
8f420676 1678 return EFI_INVALID_PARAMETER;\r
7936fb6a 1679 }\r
1680\r
8f420676
ED
1681 Status = PopExpression (&Value[0]);\r
1682 if (EFI_ERROR (Status)) {\r
1683 return Status;\r
1684 }\r
1685\r
1686 Status = PopExpression (&Value[1]);\r
7936fb6a 1687 if (EFI_ERROR (Status)) {\r
1688 return Status;\r
1689 }\r
8f420676
ED
1690\r
1691 Status = PopExpression (&Value[2]);\r
1692 if (EFI_ERROR (Status)) {\r
1693 return Status;\r
1694 } \r
1695\r
1696 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1697 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1698 return EFI_SUCCESS;\r
7936fb6a 1699 }\r
8f420676 1700 Base = (UINTN) Value[0].Value.u64;\r
7936fb6a 1701\r
1702 //\r
1703 // String[0] - sub-string\r
1704 // String[1] - The string to search\r
1705 //\r
1706 String[0] = NULL;\r
1707 String[1] = NULL;\r
1708 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1709 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1710 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1711 Status = EFI_SUCCESS;\r
7936fb6a 1712 goto Done;\r
1713 }\r
1714\r
8f420676 1715 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
d0720b57 1716 if (String[Index] == NULL) {\r
7936fb6a 1717 Status = EFI_NOT_FOUND;\r
1718 goto Done;\r
1719 }\r
1720\r
1721 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
1722 //\r
1723 // Case insensitive, convert both string to upper case\r
1724 //\r
1725 IfrStrToUpper (String[Index]);\r
1726 }\r
1727 }\r
1728\r
1729 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1730 if (Base >= StrLen (String[1])) {\r
1731 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
1732 } else {\r
1733 StringPtr = StrStr (String[1] + Base, String[0]);\r
1734 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
1735 }\r
1736\r
1737Done:\r
676df92c 1738 if (String[0] != NULL) {\r
1739 FreePool (String[0]);\r
1740 }\r
1741 if (String[1] != NULL) {\r
1742 FreePool (String[1]);\r
8b0fc5c1 1743 }\r
7936fb6a 1744\r
1745 return Status;\r
1746}\r
1747\r
1748\r
1749/**\r
1750 Evaluate opcode EFI_IFR_MID.\r
1751\r
1752 @param FormSet Formset which contains this opcode.\r
1753 @param Result Evaluation result for this opcode.\r
1754\r
1755 @retval EFI_SUCCESS Opcode evaluation success.\r
1756 @retval Other Opcode evaluation failed.\r
1757\r
1758**/\r
1759EFI_STATUS\r
1760IfrMid (\r
1761 IN FORM_BROWSER_FORMSET *FormSet,\r
1762 OUT EFI_HII_VALUE *Result\r
1763 )\r
1764{\r
1765 EFI_STATUS Status;\r
8f420676 1766 EFI_HII_VALUE Value[3];\r
7936fb6a 1767 CHAR16 *String;\r
1768 UINTN Base;\r
1769 UINTN Length;\r
1770 CHAR16 *SubString;\r
901ba0e7 1771 UINT16 BufferLen;\r
40578d09 1772 UINT8 *Buffer;\r
7936fb6a 1773\r
8f420676
ED
1774 ZeroMem (Value, sizeof (Value));\r
1775\r
1776 Status = PopExpression (&Value[0]);\r
7936fb6a 1777 if (EFI_ERROR (Status)) {\r
1778 return Status;\r
1779 }\r
7936fb6a 1780\r
8f420676 1781 Status = PopExpression (&Value[1]);\r
7936fb6a 1782 if (EFI_ERROR (Status)) {\r
1783 return Status;\r
1784 }\r
7936fb6a 1785\r
8f420676 1786 Status = PopExpression (&Value[2]);\r
7936fb6a 1787 if (EFI_ERROR (Status)) {\r
1788 return Status;\r
8f420676
ED
1789 } \r
1790\r
1791 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1792 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1793 return EFI_SUCCESS;\r
7936fb6a 1794 }\r
8f420676
ED
1795 Length = (UINTN) Value[0].Value.u64;\r
1796\r
1797 if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1798 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1799 return EFI_SUCCESS;\r
7936fb6a 1800 }\r
8f420676
ED
1801 Base = (UINTN) Value[1].Value.u64;\r
1802\r
40578d09 1803 if (Value[2].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[2])) {\r
8f420676
ED
1804 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1805 return EFI_SUCCESS;\r
1806 }\r
1807 if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
1808 String = GetToken (Value[2].Value.string, FormSet->HiiHandle);\r
901ba0e7
ED
1809 if (String == NULL) {\r
1810 return EFI_NOT_FOUND;\r
1811 }\r
7936fb6a 1812\r
901ba0e7
ED
1813 if (Length == 0 || Base >= StrLen (String)) {\r
1814 SubString = gEmptyString;\r
1815 } else {\r
1816 SubString = String + Base;\r
1817 if ((Base + Length) < StrLen (String)) {\r
1818 SubString[Length] = L'\0';\r
1819 }\r
7936fb6a 1820 }\r
7936fb6a 1821\r
901ba0e7
ED
1822 Result->Type = EFI_IFR_TYPE_STRING;\r
1823 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
7936fb6a 1824\r
901ba0e7
ED
1825 FreePool (String);\r
1826 } else {\r
40578d09
ED
1827 BufferLen = GetLengthForValue (&Value[2]);\r
1828 Buffer = GetBufferForValue (&Value[2]);\r
1829\r
901ba0e7
ED
1830 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1831 if (Length == 0 || Base >= BufferLen) {\r
1832 Result->BufferLen = 0;\r
1833 Result->Buffer = NULL;\r
1834 } else {\r
1835 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length); \r
1836 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1837 ASSERT (Result->Buffer != NULL);\r
40578d09 1838 CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
901ba0e7 1839 }\r
7936fb6a 1840\r
40578d09
ED
1841 if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
1842 FreePool (Value[2].Buffer);\r
1843 }\r
901ba0e7
ED
1844 }\r
1845 \r
7936fb6a 1846 return Status;\r
1847}\r
1848\r
1849\r
1850/**\r
1851 Evaluate opcode EFI_IFR_TOKEN.\r
1852\r
1853 @param FormSet Formset which contains this opcode.\r
1854 @param Result Evaluation result for this opcode.\r
1855\r
1856 @retval EFI_SUCCESS Opcode evaluation success.\r
1857 @retval Other Opcode evaluation failed.\r
1858\r
1859**/\r
1860EFI_STATUS\r
1861IfrToken (\r
1862 IN FORM_BROWSER_FORMSET *FormSet,\r
1863 OUT EFI_HII_VALUE *Result\r
1864 )\r
1865{\r
1866 EFI_STATUS Status;\r
8f420676 1867 EFI_HII_VALUE Value[3];\r
7936fb6a 1868 CHAR16 *String[2];\r
1869 UINTN Count;\r
1870 CHAR16 *Delimiter;\r
1871 CHAR16 *SubString;\r
1872 CHAR16 *StringPtr;\r
1873 UINTN Index;\r
1874\r
8f420676
ED
1875 ZeroMem (Value, sizeof (Value));\r
1876\r
1877 Status = PopExpression (&Value[0]);\r
1878 if (EFI_ERROR (Status)) {\r
1879 return Status;\r
1880 }\r
1881\r
1882 Status = PopExpression (&Value[1]);\r
7936fb6a 1883 if (EFI_ERROR (Status)) {\r
1884 return Status;\r
1885 }\r
8f420676
ED
1886\r
1887 Status = PopExpression (&Value[2]);\r
1888 if (EFI_ERROR (Status)) {\r
1889 return Status;\r
1890 } \r
1891\r
1892 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) { \r
1893 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1894 return EFI_SUCCESS;\r
7936fb6a 1895 }\r
8f420676 1896 Count = (UINTN) Value[0].Value.u64;\r
7936fb6a 1897\r
1898 //\r
1899 // String[0] - Delimiter\r
1900 // String[1] - The string to search\r
1901 //\r
1902 String[0] = NULL;\r
1903 String[1] = NULL;\r
1904 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1905 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1906 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1907 Status = EFI_SUCCESS; \r
7936fb6a 1908 goto Done;\r
1909 }\r
1910\r
8f420676 1911 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
d0720b57 1912 if (String[Index] == NULL) {\r
7936fb6a 1913 Status = EFI_NOT_FOUND;\r
1914 goto Done;\r
1915 }\r
1916 }\r
1917\r
1918 Delimiter = String[0];\r
1919 SubString = String[1];\r
1920 while (Count > 0) {\r
1921 SubString = StrStr (SubString, Delimiter);\r
1922 if (SubString != NULL) {\r
1923 //\r
1924 // Skip over the delimiter\r
1925 //\r
1926 SubString = SubString + StrLen (Delimiter);\r
1927 } else {\r
1928 break;\r
1929 }\r
1930 Count--;\r
1931 }\r
1932\r
1933 if (SubString == NULL) {\r
1934 //\r
1935 // nth delimited sub-string not found, push an empty string\r
1936 //\r
1937 SubString = gEmptyString;\r
1938 } else {\r
1939 //\r
1940 // Put a NULL terminator for nth delimited sub-string\r
1941 //\r
1942 StringPtr = StrStr (SubString, Delimiter);\r
1943 if (StringPtr != NULL) {\r
1944 *StringPtr = L'\0';\r
1945 }\r
1946 }\r
1947\r
1948 Result->Type = EFI_IFR_TYPE_STRING;\r
1949 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1950\r
1951Done:\r
676df92c 1952 if (String[0] != NULL) {\r
1953 FreePool (String[0]);\r
1954 }\r
1955 if (String[1] != NULL) {\r
1956 FreePool (String[1]);\r
8b0fc5c1 1957 }\r
7936fb6a 1958\r
1959 return Status;\r
1960}\r
1961\r
1962\r
1963/**\r
1964 Evaluate opcode EFI_IFR_SPAN.\r
1965\r
1966 @param FormSet Formset which contains this opcode.\r
1967 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1968 @param Result Evaluation result for this opcode.\r
1969\r
1970 @retval EFI_SUCCESS Opcode evaluation success.\r
1971 @retval Other Opcode evaluation failed.\r
1972\r
1973**/\r
1974EFI_STATUS\r
1975IfrSpan (\r
1976 IN FORM_BROWSER_FORMSET *FormSet,\r
1977 IN UINT8 Flags,\r
1978 OUT EFI_HII_VALUE *Result\r
1979 )\r
1980{\r
1981 EFI_STATUS Status;\r
8f420676 1982 EFI_HII_VALUE Value[3];\r
7936fb6a 1983 CHAR16 *String[2];\r
1984 CHAR16 *Charset;\r
1985 UINTN Base;\r
1986 UINTN Index;\r
1987 CHAR16 *StringPtr;\r
1988 BOOLEAN Found;\r
1989\r
8f420676
ED
1990 ZeroMem (Value, sizeof (Value));\r
1991\r
1992 Status = PopExpression (&Value[0]);\r
1993 if (EFI_ERROR (Status)) {\r
1994 return Status;\r
1995 }\r
1996\r
1997 Status = PopExpression (&Value[1]);\r
7936fb6a 1998 if (EFI_ERROR (Status)) {\r
1999 return Status;\r
2000 }\r
8f420676
ED
2001\r
2002 Status = PopExpression (&Value[2]);\r
2003 if (EFI_ERROR (Status)) {\r
2004 return Status;\r
2005 } \r
2006\r
2007 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
2008 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2009 return EFI_SUCCESS;\r
7936fb6a 2010 }\r
8f420676 2011 Base = (UINTN) Value[0].Value.u64;\r
7936fb6a 2012\r
2013 //\r
2014 // String[0] - Charset\r
2015 // String[1] - The string to search\r
2016 //\r
2017 String[0] = NULL;\r
2018 String[1] = NULL;\r
2019 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
2020 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
2021 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2022 Status = EFI_SUCCESS;\r
7936fb6a 2023 goto Done;\r
2024 }\r
2025\r
8f420676 2026 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
bc166db3 2027 if (String [Index] == NULL) {\r
7936fb6a 2028 Status = EFI_NOT_FOUND;\r
2029 goto Done;\r
2030 }\r
2031 }\r
2032\r
2033 if (Base >= StrLen (String[1])) {\r
8f420676
ED
2034 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2035 Status = EFI_SUCCESS;\r
7936fb6a 2036 goto Done;\r
2037 }\r
2038\r
2039 Found = FALSE;\r
2040 StringPtr = String[1] + Base;\r
2041 Charset = String[0];\r
2042 while (*StringPtr != 0 && !Found) {\r
2043 Index = 0;\r
2044 while (Charset[Index] != 0) {\r
2045 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
2046 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
2047 Found = TRUE;\r
2048 break;\r
2049 }\r
2050 } else {\r
2051 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
2052 Found = TRUE;\r
2053 break;\r
2054 }\r
2055 }\r
2056 //\r
2057 // Skip characters pair representing low-end of a range and high-end of a range\r
2058 //\r
2059 Index += 2;\r
2060 }\r
2061\r
2062 if (!Found) {\r
2063 StringPtr++;\r
2064 }\r
2065 }\r
2066\r
2067 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2068 Result->Value.u64 = StringPtr - String[1];\r
2069\r
2070Done:\r
676df92c 2071 if (String[0] != NULL) {\r
2072 FreePool (String[0]);\r
2073 }\r
2074 if (String[1] != NULL) {\r
2075 FreePool (String[1]);\r
8b0fc5c1 2076 }\r
7936fb6a 2077\r
2078 return Status;\r
2079}\r
2080\r
2081\r
2082/**\r
2083 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
2084\r
2085 @param Value HII Value to be converted.\r
2086\r
2087**/\r
2088VOID\r
2089ExtendValueToU64 (\r
2090 IN EFI_HII_VALUE *Value\r
2091 )\r
2092{\r
2093 UINT64 Temp;\r
2094\r
2095 Temp = 0;\r
2096 switch (Value->Type) {\r
2097 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2098 Temp = Value->Value.u8;\r
2099 break;\r
2100\r
2101 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2102 Temp = Value->Value.u16;\r
2103 break;\r
2104\r
2105 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2106 Temp = Value->Value.u32;\r
2107 break;\r
2108\r
2109 case EFI_IFR_TYPE_BOOLEAN:\r
2110 Temp = Value->Value.b;\r
2111 break;\r
2112\r
2113 case EFI_IFR_TYPE_TIME:\r
2114 Temp = Value->Value.u32 & 0xffffff;\r
2115 break;\r
2116\r
2117 case EFI_IFR_TYPE_DATE:\r
2118 Temp = Value->Value.u32;\r
2119 break;\r
2120\r
2121 default:\r
2122 return;\r
2123 }\r
2124\r
2125 Value->Value.u64 = Temp;\r
2126}\r
2127\r
d63a9eb4
ED
2128/**\r
2129 Get UINT64 type value.\r
2130\r
2131 @param Value Input Hii value.\r
2132\r
2133 @retval UINT64 Return the UINT64 type value.\r
2134\r
2135**/\r
2136UINT64\r
2137HiiValueToUINT64 (\r
2138 IN EFI_HII_VALUE *Value\r
2139 )\r
2140{\r
2141 UINT64 RetVal;\r
2142\r
2143 RetVal = 0;\r
2144\r
2145 switch (Value->Type) {\r
2146 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2147 RetVal = Value->Value.u8;\r
2148 break;\r
2149\r
2150 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2151 RetVal = Value->Value.u16;\r
2152 break;\r
2153\r
2154 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2155 RetVal = Value->Value.u32;\r
2156 break;\r
2157\r
2158 case EFI_IFR_TYPE_BOOLEAN:\r
2159 RetVal = Value->Value.b;\r
2160 break;\r
2161\r
2162 case EFI_IFR_TYPE_DATE:\r
2163 RetVal = *(UINT64*) &Value->Value.date;\r
2164 break;\r
2165\r
2166 case EFI_IFR_TYPE_TIME:\r
2167 RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;\r
2168 break;\r
2169\r
2170 default:\r
2171 RetVal = Value->Value.u64;\r
2172 break;\r
2173 }\r
2174\r
2175 return RetVal;\r
2176}\r
7936fb6a 2177\r
2178/**\r
2179 Compare two Hii value.\r
2180\r
2181 @param Value1 Expression value to compare on left-hand.\r
2182 @param Value2 Expression value to compare on right-hand.\r
8f420676
ED
2183 @param Result Return value after compare.\r
2184 retval 0 Two operators equal.\r
2185 return Positive value if Value1 is greater than Value2.\r
2186 retval Negative value if Value1 is less than Value2.\r
7936fb6a 2187 @param HiiHandle Only required for string compare.\r
2188\r
8f420676
ED
2189 @retval other Could not perform compare on two values.\r
2190 @retval EFI_SUCCESS Compare the value success.\r
7936fb6a 2191\r
2192**/\r
8f420676 2193EFI_STATUS\r
7936fb6a 2194CompareHiiValue (\r
2195 IN EFI_HII_VALUE *Value1,\r
2196 IN EFI_HII_VALUE *Value2,\r
8f420676 2197 OUT INTN *Result,\r
7936fb6a 2198 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
2199 )\r
2200{\r
7936fb6a 2201 INT64 Temp64;\r
2202 CHAR16 *Str1;\r
2203 CHAR16 *Str2;\r
901ba0e7 2204 UINTN Len;\r
40578d09
ED
2205 UINT8 *Buf1;\r
2206 UINT16 Buf1Len;\r
2207 UINT8 *Buf2;\r
2208 UINT16 Buf2Len;\r
7936fb6a 2209\r
40578d09 2210 if (Value1->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {\r
7936fb6a 2211 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
2212 //\r
2213 // StringId 0 is reserved\r
2214 //\r
2215 return EFI_INVALID_PARAMETER;\r
2216 }\r
2217\r
2218 if (Value1->Value.string == Value2->Value.string) {\r
8f420676
ED
2219 *Result = 0;\r
2220 return EFI_SUCCESS;\r
7936fb6a 2221 }\r
2222\r
2223 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
2224 if (Str1 == NULL) {\r
2225 //\r
2226 // String not found\r
2227 //\r
8f420676 2228 return EFI_NOT_FOUND;\r
7936fb6a 2229 }\r
2230\r
2231 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
2232 if (Str2 == NULL) {\r
f4113e1f 2233 FreePool (Str1);\r
8f420676 2234 return EFI_NOT_FOUND;\r
7936fb6a 2235 }\r
2236\r
8f420676 2237 *Result = StrCmp (Str1, Str2);\r
7936fb6a 2238\r
f4113e1f 2239 FreePool (Str1);\r
2240 FreePool (Str2);\r
7936fb6a 2241\r
8f420676 2242 return EFI_SUCCESS;\r
7936fb6a 2243 }\r
2244\r
40578d09
ED
2245 //\r
2246 // Take types(date, time, ref, buffer) as buffer\r
2247 //\r
2248 if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {\r
2249 Buf1 = GetBufferForValue(Value1);\r
2250 Buf1Len = GetLengthForValue(Value1);\r
2251 Buf2 = GetBufferForValue(Value2);\r
2252 Buf2Len = GetLengthForValue(Value2);\r
2253 \r
2254 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
2255 *Result = CompareMem (Buf1, Buf2, Len);\r
2256 if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
901ba0e7
ED
2257 //\r
2258 // In this case, means base on samll number buffer, the data is same\r
2259 // So which value has more data, which value is bigger.\r
2260 //\r
40578d09 2261 *Result = Buf1Len > Buf2Len ? 1 : -1;\r
901ba0e7 2262 }\r
8f420676 2263 return EFI_SUCCESS;\r
901ba0e7
ED
2264 } \r
2265\r
7936fb6a 2266 //\r
40578d09 2267 // Take types(integer, boolean) as integer\r
7936fb6a 2268 //\r
40578d09
ED
2269 if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {\r
2270 Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);\r
2271 if (Temp64 > 0) {\r
2272 *Result = 1;\r
2273 } else if (Temp64 < 0) {\r
2274 *Result = -1;\r
2275 } else {\r
2276 *Result = 0;\r
2277 }\r
2278\r
2279 return EFI_SUCCESS;\r
7936fb6a 2280 }\r
2281\r
40578d09 2282 return EFI_UNSUPPORTED;\r
7936fb6a 2283}\r
2284\r
cbf73e50 2285/**\r
2286 Check if current user has the privilege specified by the permissions GUID.\r
2287\r
2288 @param[in] Guid A GUID specifying setup access permissions.\r
2289\r
2290 @retval TRUE Current user has the privilege.\r
2291 @retval FALSE Current user does not have the privilege.\r
2292**/\r
2293BOOLEAN\r
2294CheckUserPrivilege (\r
2295 IN EFI_GUID *Guid\r
2296 )\r
2297{\r
2298 EFI_STATUS Status;\r
2299 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
2300 EFI_USER_INFO_HANDLE UserInfoHandle;\r
2301 EFI_USER_INFO *UserInfo;\r
2302 EFI_GUID *UserPermissionsGuid;\r
2303 UINTN UserInfoSize;\r
2304 UINTN AccessControlDataSize;\r
2305 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
2306 UINTN RemainSize;\r
2307\r
2308 if (mUserManager == NULL) {\r
2309 Status = gBS->LocateProtocol (\r
2310 &gEfiUserManagerProtocolGuid,\r
2311 NULL,\r
2312 (VOID **) &mUserManager\r
2313 );\r
2314 if (EFI_ERROR (Status)) {\r
2315 ///\r
2316 /// If the system does not support user management, then it is assumed that\r
2317 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
2318 /// op-code is always TRUE.\r
2319 ///\r
2320 return TRUE;\r
2321 }\r
2322 }\r
2323\r
2324 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
2325 ASSERT_EFI_ERROR (Status);\r
2326\r
2327 ///\r
2328 /// Enumerate all user information of the current user profile\r
2329 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
2330 ///\r
2331 \r
2332 for (UserInfoHandle = NULL;;) {\r
2333 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
2334 if (EFI_ERROR (Status)) {\r
2335 break;\r
2336 }\r
2337\r
2338 UserInfoSize = 0;\r
2339 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
2340 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2341 continue;\r
2342 }\r
2343\r
2344 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
2345 if (UserInfo == NULL) {\r
2346 break;\r
2347 }\r
2348\r
2349 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
2350 if (EFI_ERROR (Status) ||\r
2351 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
2352 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
2353 FreePool (UserInfo);\r
2354 continue;\r
2355 }\r
2356\r
2357 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
2358 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
2359 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
3dd405be 2360 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
cbf73e50 2361 break;\r
2362 }\r
2363 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
2364 ///\r
2365 /// Check if current user has the privilege specified by the permissions GUID.\r
2366 ///\r
2367\r
2368 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
2369 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
2370 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
2371 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
2372 FreePool (UserInfo);\r
2373 return TRUE;\r
2374 }\r
2375 UserPermissionsGuid++;\r
2376 AccessControlDataSize -= sizeof (EFI_GUID);\r
2377 }\r
2378 }\r
2379 RemainSize -= AccessControl->Size;\r
2380 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
2381 }\r
2382\r
2383 FreePool (UserInfo);\r
2384 }\r
2385 return FALSE;\r
2386}\r
7936fb6a 2387\r
db40504e
ED
2388/**\r
2389 Get question value from the predefined formset.\r
2390\r
2391 @param DevicePath The driver's device path which produece the formset data.\r
2392 @param InputHiiHandle The hii handle associate with the formset data.\r
2393 @param FormSetGuid The formset guid which include the question.\r
2394 @param QuestionId The question id which need to get value from.\r
2395 @param Value The return data about question's value.\r
2396 \r
2397 @retval TRUE Get the question value success.\r
2398 @retval FALSE Get the question value failed.\r
2399**/\r
2400BOOLEAN \r
2401GetQuestionValueFromForm (\r
2402 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2403 IN EFI_HII_HANDLE InputHiiHandle,\r
2404 IN EFI_GUID *FormSetGuid,\r
2405 IN EFI_QUESTION_ID QuestionId,\r
2406 OUT EFI_HII_VALUE *Value\r
2407 )\r
2408{\r
2409 EFI_STATUS Status;\r
db40504e 2410 EFI_HII_HANDLE HiiHandle;\r
db40504e
ED
2411 FORM_BROWSER_STATEMENT *Question;\r
2412 FORM_BROWSER_FORMSET *FormSet;\r
2413 FORM_BROWSER_FORM *Form;\r
2414 BOOLEAN GetTheVal;\r
2415 LIST_ENTRY *Link;\r
2416\r
2417 // \r
2418 // The input parameter DevicePath or InputHiiHandle must have one valid input. \r
2419 //\r
2420 ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) || \r
2421 (DevicePath == NULL && InputHiiHandle != NULL) );\r
2422\r
2423 GetTheVal = TRUE;\r
db40504e
ED
2424 HiiHandle = NULL;\r
2425 Question = NULL;\r
2426 Form = NULL;\r
2427\r
2428 //\r
2429 // Get HiiHandle.\r
2430 //\r
2431 if (DevicePath != NULL) {\r
07d7dbae
ED
2432 HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
2433 if (HiiHandle == NULL) {\r
db40504e
ED
2434 return FALSE;\r
2435 }\r
db40504e
ED
2436 } else {\r
2437 HiiHandle = InputHiiHandle;\r
2438 } \r
2439 ASSERT (HiiHandle != NULL);\r
2440\r
2441 //\r
2442 // Get the formset data include this question.\r
2443 //\r
2444 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
2445 ASSERT (FormSet != NULL);\r
7c6c064c 2446 Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);\r
db40504e
ED
2447 if (EFI_ERROR (Status)) {\r
2448 GetTheVal = FALSE;\r
2449 goto Done;\r
2450 }\r
2451\r
2452 //\r
2453 // Base on the Question Id to get the question info.\r
2454 // \r
2455 Question = IdToQuestion(FormSet, NULL, QuestionId);\r
2456 if (Question == NULL) {\r
2457 GetTheVal = FALSE;\r
2458 goto Done;\r
2459 }\r
2460\r
2461 //\r
2462 // Search form in the formset scope\r
2463 //\r
2464 Link = GetFirstNode (&FormSet->FormListHead);\r
2465 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2466 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2467\r
2468 Question = IdToQuestion2 (Form, QuestionId);\r
2469 if (Question != NULL) {\r
2470 break;\r
2471 }\r
2472\r
2473 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2474 Form = NULL;\r
2475 }\r
2476 ASSERT (Form != NULL);\r
2477 \r
2478 //\r
2479 // Get the question value.\r
2480 //\r
816a7110 2481 Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithHiiDriver);\r
db40504e
ED
2482 if (EFI_ERROR (Status)) {\r
2483 GetTheVal = FALSE;\r
2484 goto Done;\r
2485 }\r
2486\r
2487 CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
2488 \r
2489Done:\r
2490 //\r
2491 // Clean the formset structure and restore the global parameter.\r
2492 //\r
2493 if (FormSet != NULL) {\r
2494 DestroyFormSet (FormSet);\r
2495 }\r
2496 \r
2497 return GetTheVal;\r
2498}\r
2499\r
7936fb6a 2500/**\r
bc166db3 2501 Evaluate the result of a HII expression.\r
2502\r
2503 If Expression is NULL, then ASSERT.\r
7936fb6a 2504\r
2505 @param FormSet FormSet associated with this expression.\r
2506 @param Form Form associated with this expression.\r
2507 @param Expression Expression to be evaluated.\r
2508\r
2509 @retval EFI_SUCCESS The expression evaluated successfuly\r
2510 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
2511 could not be found.\r
2512 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
2513 stack.\r
2514 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
2515 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
2516\r
2517**/\r
2518EFI_STATUS\r
2519EvaluateExpression (\r
2520 IN FORM_BROWSER_FORMSET *FormSet,\r
2521 IN FORM_BROWSER_FORM *Form,\r
2522 IN OUT FORM_EXPRESSION *Expression\r
2523 )\r
2524{\r
2525 EFI_STATUS Status;\r
2526 LIST_ENTRY *Link;\r
2527 EXPRESSION_OPCODE *OpCode;\r
2528 FORM_BROWSER_STATEMENT *Question;\r
2529 FORM_BROWSER_STATEMENT *Question2;\r
2530 UINT16 Index;\r
2531 EFI_HII_VALUE Data1;\r
2532 EFI_HII_VALUE Data2;\r
2533 EFI_HII_VALUE Data3;\r
2534 FORM_EXPRESSION *RuleExpression;\r
2535 EFI_HII_VALUE *Value;\r
2536 INTN Result;\r
2537 CHAR16 *StrPtr;\r
2573712e 2538 CHAR16 *NameValue;\r
7936fb6a 2539 UINT32 TempValue;\r
2573712e
LG
2540 LIST_ENTRY *SubExpressionLink;\r
2541 FORM_EXPRESSION *SubExpression;\r
2542 UINTN StackOffset;\r
2543 UINTN TempLength;\r
2544 CHAR16 TempStr[5];\r
2545 UINT8 DigitUint8;\r
2546 UINT8 *TempBuffer;\r
2547 EFI_TIME EfiTime;\r
db40504e 2548 EFI_HII_VALUE QuestionVal;\r
33efdf51 2549 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
7936fb6a 2550\r
4e1005ec
ED
2551 StrPtr = NULL;\r
2552\r
7936fb6a 2553 //\r
2573712e 2554 // Save current stack offset.\r
7936fb6a 2555 //\r
2573712e 2556 StackOffset = SaveExpressionEvaluationStackOffset ();\r
7936fb6a 2557\r
bc166db3 2558 ASSERT (Expression != NULL);\r
7936fb6a 2559 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
2560\r
2561 Link = GetFirstNode (&Expression->OpCodeListHead);\r
2562 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
2563 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
2564\r
2565 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
2566\r
2567 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
2568 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
2569 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
2570\r
2571 Value = &Data3;\r
2572 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2573 Status = EFI_SUCCESS;\r
2574\r
2575 switch (OpCode->Operand) {\r
2576 //\r
2577 // Built-in functions\r
2578 //\r
2579 case EFI_IFR_EQ_ID_VAL_OP:\r
2580 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2581 if (Question == NULL) {\r
8f420676
ED
2582 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2583 break;\r
7936fb6a 2584 }\r
2585\r
8f420676
ED
2586 Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);\r
2587 if (Status == EFI_UNSUPPORTED) {\r
2588 Status = EFI_SUCCESS;\r
2589 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2590 break;\r
2591 }\r
2592\r
2593 if (EFI_ERROR (Status)) {\r
2573712e 2594 goto Done;\r
7936fb6a 2595 }\r
2596 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2597 break;\r
2598\r
2599 case EFI_IFR_EQ_ID_ID_OP:\r
2600 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2601 if (Question == NULL) {\r
8f420676
ED
2602 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2603 break;\r
7936fb6a 2604 }\r
2605\r
2606 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
2607 if (Question2 == NULL) {\r
8f420676
ED
2608 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2609 break;\r
7936fb6a 2610 }\r
2611\r
8f420676
ED
2612 Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);\r
2613 if (Status == EFI_UNSUPPORTED) {\r
2614 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2615 Status = EFI_SUCCESS;\r
2616 break;\r
2617 }\r
2618 if (EFI_ERROR (Status)) {\r
2573712e 2619 goto Done;\r
7936fb6a 2620 }\r
2621 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2622 break;\r
2623\r
e8ef4283 2624 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
7936fb6a 2625 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2626 if (Question == NULL) {\r
8f420676
ED
2627 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2628 break;\r
7936fb6a 2629 }\r
2630\r
2631 Value->Value.b = FALSE;\r
2632 for (Index =0; Index < OpCode->ListLength; Index++) {\r
2633 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
2634 Value->Value.b = TRUE;\r
2635 break;\r
2636 }\r
2637 }\r
2638 break;\r
2639\r
2640 case EFI_IFR_DUP_OP:\r
2641 Status = PopExpression (Value);\r
2642 if (EFI_ERROR (Status)) {\r
2573712e 2643 goto Done;\r
7936fb6a 2644 }\r
2645\r
2646 Status = PushExpression (Value);\r
2647 break;\r
2648\r
2649 case EFI_IFR_QUESTION_REF1_OP:\r
2650 case EFI_IFR_THIS_OP:\r
2651 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2652 if (Question == NULL) {\r
2573712e
LG
2653 Status = EFI_NOT_FOUND;\r
2654 goto Done;\r
7936fb6a 2655 }\r
2656\r
2657 Value = &Question->HiiValue;\r
2658 break;\r
2659\r
cbf73e50 2660 case EFI_IFR_SECURITY_OP:\r
2661 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
2662 break;\r
2663\r
2573712e
LG
2664 case EFI_IFR_GET_OP:\r
2665 //\r
2666 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2667 //\r
2668 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2669 Value->Value.u8 = 0;\r
2670 if (OpCode->VarStorage != NULL) {\r
2671 switch (OpCode->VarStorage->Type) {\r
2672 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2673 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2674 //\r
2675 // Get value from Edit Buffer\r
2676 //\r
2677 Value->Type = OpCode->ValueType;\r
2678 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2679 break;\r
2680 case EFI_HII_VARSTORE_NAME_VALUE:\r
2681 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2682 //\r
2683 // Get value from string except for STRING value.\r
2684 //\r
816a7110 2685 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);\r
2573712e 2686 if (!EFI_ERROR (Status)) {\r
771ececd 2687 ASSERT (StrPtr != NULL);\r
2573712e
LG
2688 TempLength = StrLen (StrPtr);\r
2689 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
2690 Value->Type = OpCode->ValueType;\r
2691 TempBuffer = (UINT8 *) &Value->Value;\r
2692 ZeroMem (TempStr, sizeof (TempStr));\r
2693 for (Index = 0; Index < TempLength; Index ++) {\r
2694 TempStr[0] = StrPtr[TempLength - Index - 1];\r
2695 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
2696 if ((Index & 1) == 0) {\r
2697 TempBuffer [Index/2] = DigitUint8;\r
2698 } else {\r
771ececd 2699 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
2700 }\r
2701 }\r
2702 } \r
2703 }\r
2704 }\r
2705 break;\r
2706 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2707 //\r
2708 // Get value from variable.\r
2709 //\r
2710 TempLength = OpCode->ValueWidth;\r
2711 Value->Type = OpCode->ValueType;\r
2712 Status = gRT->GetVariable (\r
2713 OpCode->ValueName,\r
2714 &OpCode->VarStorage->Guid,\r
2715 NULL,\r
2716 &TempLength,\r
2717 &Value->Value\r
2718 );\r
2719 if (EFI_ERROR (Status)) {\r
2720 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2721 Value->Value.u8 = 0;\r
2722 }\r
cce6230f 2723 break;\r
2573712e
LG
2724 default:\r
2725 //\r
2726 // Not recognize storage.\r
2727 //\r
2728 Status = EFI_UNSUPPORTED;\r
2729 goto Done;\r
2730 }\r
2731 } else {\r
2732 //\r
2733 // For Time/Date Data\r
2734 //\r
2735 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2736 //\r
2737 // Only support Data/Time data when storage doesn't exist.\r
2738 //\r
2739 Status = EFI_UNSUPPORTED;\r
2740 goto Done;\r
2741 }\r
2742 Status = gRT->GetTime (&EfiTime, NULL);\r
2743 if (!EFI_ERROR (Status)) {\r
2744 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2745 switch (OpCode->VarStoreInfo.VarOffset) {\r
2746 case 0x00:\r
2747 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
2748 Value->Value.u16 = EfiTime.Year;\r
2749 break;\r
2750 case 0x02:\r
2751 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2752 Value->Value.u8 = EfiTime.Month;\r
2753 break;\r
2754 case 0x03:\r
2755 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2756 Value->Value.u8 = EfiTime.Day;\r
2757 break;\r
2758 default:\r
2759 //\r
2760 // Invalid Date field.\r
2761 //\r
2762 Status = EFI_INVALID_PARAMETER;\r
2763 goto Done;\r
2764 }\r
2765 } else {\r
2766 switch (OpCode->VarStoreInfo.VarOffset) {\r
2767 case 0x00:\r
2768 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2769 Value->Value.u8 = EfiTime.Hour;\r
2770 break;\r
2771 case 0x01:\r
2772 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2773 Value->Value.u8 = EfiTime.Minute;\r
2774 break;\r
2775 case 0x02:\r
2776 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2777 Value->Value.u8 = EfiTime.Second;\r
2778 break;\r
2779 default:\r
2780 //\r
2781 // Invalid Time field.\r
2782 //\r
2783 Status = EFI_INVALID_PARAMETER;\r
2784 goto Done;\r
2785 }\r
2786 }\r
2787 }\r
2788 }\r
2789\r
2790 break;\r
2791\r
7936fb6a 2792 case EFI_IFR_QUESTION_REF3_OP:\r
db40504e
ED
2793 //\r
2794 // EFI_IFR_QUESTION_REF3\r
2795 // Pop an expression from the expression stack\r
2796 //\r
2797 Status = PopExpression (Value);\r
2798 if (EFI_ERROR (Status)) {\r
2799 goto Done;\r
2800 }\r
2801 \r
2802 //\r
2803 // Validate the expression value\r
2804 //\r
2805 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2806 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2807 break;\r
db40504e
ED
2808 }\r
2809\r
2810 if (OpCode->DevicePath != 0) {\r
80a047f0 2811 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
33efdf51 2812\r
80a047f0
ED
2813 StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
2814 if (StrPtr != NULL && mPathFromText != NULL) {\r
2815 DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);\r
2816 if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {\r
2817 Value = &QuestionVal;\r
2818 }\r
2819 if (DevicePath != NULL) {\r
2820 FreePool (DevicePath);\r
2821 }\r
33efdf51
ED
2822 }\r
2823\r
80a047f0
ED
2824 if (StrPtr != NULL) {\r
2825 FreePool (StrPtr);\r
7936fb6a 2826 }\r
db40504e
ED
2827 } else if (CompareGuid (&OpCode->Guid, &gZeroGuid) != 0) {\r
2828 if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
8f420676
ED
2829 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2830 break;\r
db40504e 2831 }\r
8f420676 2832 Value = &QuestionVal;\r
db40504e 2833 } else {\r
7936fb6a 2834 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2835 if (Question == NULL) {\r
8f420676
ED
2836 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2837 break;\r
7936fb6a 2838 }\r
2839\r
2840 //\r
2841 // push the questions' value on to the expression stack\r
2842 //\r
2843 Value = &Question->HiiValue;\r
7936fb6a 2844 }\r
2845 break;\r
2846\r
2847 case EFI_IFR_RULE_REF_OP:\r
2848 //\r
2849 // Find expression for this rule\r
2850 //\r
2851 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
2852 if (RuleExpression == NULL) {\r
8f420676
ED
2853 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2854 break;\r
7936fb6a 2855 }\r
2856\r
2857 //\r
2858 // Evaluate this rule expression\r
2859 //\r
2860 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
8f420676
ED
2861 if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {\r
2862 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2863 break;\r
7936fb6a 2864 }\r
2865\r
2866 Value = &RuleExpression->Result;\r
2867 break;\r
2868\r
2869 case EFI_IFR_STRING_REF1_OP:\r
2870 Value->Type = EFI_IFR_TYPE_STRING;\r
2871 Value->Value.string = OpCode->Value.Value.string;\r
2872 break;\r
2873\r
2874 //\r
2875 // Constant\r
2876 //\r
2877 case EFI_IFR_TRUE_OP:\r
2878 case EFI_IFR_FALSE_OP:\r
2879 case EFI_IFR_ONE_OP:\r
2880 case EFI_IFR_ONES_OP:\r
2881 case EFI_IFR_UINT8_OP:\r
2882 case EFI_IFR_UINT16_OP:\r
2883 case EFI_IFR_UINT32_OP:\r
2884 case EFI_IFR_UINT64_OP:\r
2885 case EFI_IFR_UNDEFINED_OP:\r
2886 case EFI_IFR_VERSION_OP:\r
2887 case EFI_IFR_ZERO_OP:\r
2888 Value = &OpCode->Value;\r
2889 break;\r
2890\r
2891 //\r
2892 // unary-op\r
2893 //\r
2894 case EFI_IFR_LENGTH_OP:\r
2895 Status = PopExpression (Value);\r
2896 if (EFI_ERROR (Status)) {\r
2573712e 2897 goto Done;\r
7936fb6a 2898 }\r
40578d09 2899 if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) {\r
8f420676
ED
2900 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2901 break;\r
7936fb6a 2902 }\r
2903\r
901ba0e7
ED
2904 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2905 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2906 if (StrPtr == NULL) {\r
2907 Status = EFI_INVALID_PARAMETER;\r
2908 goto Done;\r
2909 }\r
7936fb6a 2910\r
901ba0e7
ED
2911 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2912 Value->Value.u64 = StrLen (StrPtr);\r
2913 FreePool (StrPtr);\r
2914 } else {\r
2915 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
40578d09 2916 Value->Value.u64 = GetLengthForValue(Value);\r
901ba0e7
ED
2917 FreePool (Value->Buffer);\r
2918 }\r
7936fb6a 2919 break;\r
2920\r
2921 case EFI_IFR_NOT_OP:\r
2922 Status = PopExpression (Value);\r
2923 if (EFI_ERROR (Status)) {\r
2573712e 2924 goto Done;\r
7936fb6a 2925 }\r
2926 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
2927 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2928 break;\r
7936fb6a 2929 }\r
2930 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2931 break;\r
2932\r
2933 case EFI_IFR_QUESTION_REF2_OP:\r
2934 //\r
2935 // Pop an expression from the expression stack\r
2936 //\r
2937 Status = PopExpression (Value);\r
2938 if (EFI_ERROR (Status)) {\r
2573712e 2939 goto Done;\r
7936fb6a 2940 }\r
2941\r
2942 //\r
2943 // Validate the expression value\r
2944 //\r
2945 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2946 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2947 break;\r
7936fb6a 2948 }\r
2949\r
2950 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2951 if (Question == NULL) {\r
8f420676
ED
2952 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2953 break;\r
7936fb6a 2954 }\r
2955\r
2956 Value = &Question->HiiValue;\r
2957 break;\r
2958\r
2959 case EFI_IFR_STRING_REF2_OP:\r
2960 //\r
2961 // Pop an expression from the expression stack\r
2962 //\r
2963 Status = PopExpression (Value);\r
2964 if (EFI_ERROR (Status)) {\r
2573712e 2965 goto Done;\r
7936fb6a 2966 }\r
2967\r
2968 //\r
2969 // Validate the expression value\r
2970 //\r
2971 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2972 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2973 break;\r
7936fb6a 2974 }\r
2975\r
2976 Value->Type = EFI_IFR_TYPE_STRING;\r
2977 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2978 if (StrPtr == NULL) {\r
2979 //\r
2980 // If String not exit, push an empty string\r
2981 //\r
2982 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2983 } else {\r
2984 Index = (UINT16) Value->Value.u64;\r
2985 Value->Value.string = Index;\r
f4113e1f 2986 FreePool (StrPtr);\r
7936fb6a 2987 }\r
2988 break;\r
2989\r
2990 case EFI_IFR_TO_BOOLEAN_OP:\r
2991 //\r
2992 // Pop an expression from the expression stack\r
2993 //\r
2994 Status = PopExpression (Value);\r
2995 if (EFI_ERROR (Status)) {\r
2573712e 2996 goto Done;\r
7936fb6a 2997 }\r
2998\r
2999 //\r
3000 // Convert an expression to a Boolean\r
3001 //\r
3002 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
3003 //\r
3004 // When converting from an unsigned integer, zero will be converted to\r
3005 // FALSE and any other value will be converted to TRUE.\r
3006 //\r
40578d09 3007 Value->Value.b = (BOOLEAN) (HiiValueToUINT64(Value) != 0);\r
7936fb6a 3008\r
3009 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3010 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
3011 //\r
3012 // When converting from a string, if case-insensitive compare\r
3013 // with "true" is True, then push True. If a case-insensitive compare\r
39099cbd 3014 // with "false" is True, then push False. Otherwise, push Undefined. \r
7936fb6a 3015 //\r
3016 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
3017 if (StrPtr == NULL) {\r
2573712e
LG
3018 Status = EFI_INVALID_PARAMETER;\r
3019 goto Done;\r
7936fb6a 3020 }\r
39099cbd
ED
3021 \r
3022 IfrStrToUpper (StrPtr);\r
3023 if (StrCmp (StrPtr, L"TRUE") == 0){\r
7936fb6a 3024 Value->Value.b = TRUE;\r
8f420676 3025 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 3026 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
7936fb6a 3027 Value->Value.b = FALSE;\r
8f420676 3028 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 3029 } else {\r
8f420676 3030 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
7936fb6a 3031 }\r
f4113e1f 3032 FreePool (StrPtr);\r
901ba0e7
ED
3033 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
3034 //\r
3035 // When converting from a buffer, if the buffer is all zeroes, \r
3036 // then push False. Otherwise push True. \r
3037 //\r
3038 for (Index =0; Index < Value->BufferLen; Index ++) {\r
3039 if (Value->Buffer[Index] != 0) { \r
3040 break;\r
3041 }\r
3042 }\r
3043\r
3044 if (Index >= Value->BufferLen) {\r
3045 Value->Value.b = FALSE;\r
3046 } else {\r
3047 Value->Value.b = TRUE;\r
3048 }\r
3049 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3050 FreePool (Value->Buffer);\r
7936fb6a 3051 }\r
3052 break;\r
3053\r
3054 case EFI_IFR_TO_STRING_OP:\r
3055 Status = IfrToString (FormSet, OpCode->Format, Value);\r
3056 break;\r
3057\r
3058 case EFI_IFR_TO_UINT_OP:\r
3059 Status = IfrToUint (FormSet, Value);\r
3060 break;\r
3061\r
3062 case EFI_IFR_TO_LOWER_OP:\r
3063 case EFI_IFR_TO_UPPER_OP:\r
3064 Status = InitializeUnicodeCollationProtocol ();\r
3065 if (EFI_ERROR (Status)) {\r
2573712e 3066 goto Done;\r
7936fb6a 3067 }\r
3068\r
3069 Status = PopExpression (Value);\r
3070 if (EFI_ERROR (Status)) {\r
2573712e 3071 goto Done;\r
7936fb6a 3072 }\r
3073\r
3074 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
8f420676
ED
3075 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3076 break;\r
7936fb6a 3077 }\r
3078\r
3079 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
3080 if (StrPtr == NULL) {\r
2573712e
LG
3081 Status = EFI_NOT_FOUND;\r
3082 goto Done;\r
7936fb6a 3083 }\r
3084\r
3085 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
3086 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
3087 } else {\r
3088 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
3089 }\r
3090 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 3091 FreePool (StrPtr);\r
7936fb6a 3092 break;\r
3093\r
3094 case EFI_IFR_BITWISE_NOT_OP:\r
3095 //\r
3096 // Pop an expression from the expression stack\r
3097 //\r
3098 Status = PopExpression (Value);\r
3099 if (EFI_ERROR (Status)) {\r
2573712e 3100 goto Done;\r
7936fb6a 3101 }\r
3102 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
3103 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3104 break;\r
7936fb6a 3105 }\r
3106\r
3107 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
40578d09 3108 Value->Value.u64 = ~ HiiValueToUINT64(Value);\r
7936fb6a 3109 break;\r
3110\r
2573712e
LG
3111 case EFI_IFR_SET_OP:\r
3112 //\r
3113 // Pop an expression from the expression stack\r
3114 //\r
3115 Status = PopExpression (Value);\r
3116 if (EFI_ERROR (Status)) {\r
3117 goto Done;\r
3118 }\r
3119 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
3120 Data1.Value.b = FALSE;\r
3121 //\r
3122 // Set value to var storage buffer\r
3123 //\r
3124 if (OpCode->VarStorage != NULL) {\r
3125 switch (OpCode->VarStorage->Type) {\r
3126 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 3127 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
3128 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
3129 Data1.Value.b = TRUE;\r
3130 break;\r
3131 case EFI_HII_VARSTORE_NAME_VALUE:\r
3132 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
3133 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
3134 ASSERT (Value != NULL);\r
3135 //\r
3136 // Convert Buffer to Hex String\r
3137 //\r
3138 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
3139 StrPtr = NameValue;\r
3140 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
3141 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
3142 }\r
7c6c064c 3143 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
2573712e
LG
3144 FreePool (NameValue);\r
3145 if (!EFI_ERROR (Status)) {\r
3146 Data1.Value.b = TRUE;\r
3147 }\r
3148 }\r
3149 break;\r
3150 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
3151 Status = gRT->SetVariable (\r
3152 OpCode->ValueName,\r
3153 &OpCode->VarStorage->Guid,\r
3154 OpCode->VarStorage->Attributes,\r
3155 OpCode->ValueWidth,\r
3156 &Value->Value\r
3157 );\r
3158 if (!EFI_ERROR (Status)) {\r
3159 Data1.Value.b = TRUE;\r
3160 }\r
3161 break;\r
3162 default:\r
3163 //\r
3164 // Not recognize storage.\r
3165 //\r
3166 Status = EFI_UNSUPPORTED;\r
3167 goto Done;\r
3168 break;\r
3169 }\r
3170 } else {\r
3171 //\r
3172 // For Time/Date Data\r
3173 //\r
3174 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
3175 //\r
3176 // Only support Data/Time data when storage doesn't exist.\r
3177 //\r
3178 Status = EFI_UNSUPPORTED;\r
3179 goto Done;\r
3180 }\r
3181 Status = gRT->GetTime (&EfiTime, NULL);\r
3182 if (!EFI_ERROR (Status)) {\r
3183 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
3184 switch (OpCode->VarStoreInfo.VarOffset) {\r
3185 case 0x00:\r
3186 EfiTime.Year = Value->Value.u16;\r
3187 break;\r
3188 case 0x02:\r
3189 EfiTime.Month = Value->Value.u8;\r
3190 break;\r
3191 case 0x03:\r
3192 EfiTime.Day = Value->Value.u8;\r
3193 break;\r
3194 default:\r
3195 //\r
3196 // Invalid Date field.\r
3197 //\r
3198 Status = EFI_INVALID_PARAMETER;\r
3199 goto Done;\r
3200 }\r
3201 } else {\r
3202 switch (OpCode->VarStoreInfo.VarOffset) {\r
3203 case 0x00:\r
3204 EfiTime.Hour = Value->Value.u8;\r
3205 break;\r
3206 case 0x01:\r
3207 EfiTime.Minute = Value->Value.u8;\r
3208 break;\r
3209 case 0x02:\r
3210 EfiTime.Second = Value->Value.u8;\r
3211 break;\r
3212 default:\r
3213 //\r
3214 // Invalid Time field.\r
3215 //\r
3216 Status = EFI_INVALID_PARAMETER;\r
3217 goto Done;\r
3218 }\r
3219 }\r
3220 Status = gRT->SetTime (&EfiTime);\r
3221 if (!EFI_ERROR (Status)) {\r
3222 Data1.Value.b = TRUE;\r
3223 }\r
3224 }\r
3225 }\r
3226 Value = &Data1;\r
3227 break;\r
3228\r
7936fb6a 3229 //\r
3230 // binary-op\r
3231 //\r
3232 case EFI_IFR_ADD_OP:\r
3233 case EFI_IFR_SUBTRACT_OP:\r
3234 case EFI_IFR_MULTIPLY_OP:\r
3235 case EFI_IFR_DIVIDE_OP:\r
3236 case EFI_IFR_MODULO_OP:\r
3237 case EFI_IFR_BITWISE_AND_OP:\r
3238 case EFI_IFR_BITWISE_OR_OP:\r
3239 case EFI_IFR_SHIFT_LEFT_OP:\r
3240 case EFI_IFR_SHIFT_RIGHT_OP:\r
3241 //\r
3242 // Pop an expression from the expression stack\r
3243 //\r
3244 Status = PopExpression (&Data2);\r
3245 if (EFI_ERROR (Status)) {\r
2573712e 3246 goto Done;\r
7936fb6a 3247 }\r
7936fb6a 3248\r
3249 //\r
3250 // Pop another expression from the expression stack\r
3251 //\r
3252 Status = PopExpression (&Data1);\r
3253 if (EFI_ERROR (Status)) {\r
2573712e 3254 goto Done;\r
7936fb6a 3255 }\r
8f420676
ED
3256\r
3257 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
3258 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3259 break;\r
3260 }\r
3261\r
3262\r
7936fb6a 3263 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
3264 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3265 break;\r
7936fb6a 3266 }\r
3267\r
3268 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
3269\r
3270 switch (OpCode->Operand) {\r
3271 case EFI_IFR_ADD_OP:\r
40578d09 3272 Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2);\r
7936fb6a 3273 break;\r
3274\r
3275 case EFI_IFR_SUBTRACT_OP:\r
40578d09 3276 Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2);\r
7936fb6a 3277 break;\r
3278\r
3279 case EFI_IFR_MULTIPLY_OP:\r
40578d09 3280 Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
7936fb6a 3281 break;\r
3282\r
3283 case EFI_IFR_DIVIDE_OP:\r
40578d09 3284 Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
7936fb6a 3285 break;\r
3286\r
3287 case EFI_IFR_MODULO_OP:\r
40578d09 3288 DivU64x32Remainder (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &TempValue);\r
7936fb6a 3289 Value->Value.u64 = TempValue;\r
3290 break;\r
3291\r
3292 case EFI_IFR_BITWISE_AND_OP:\r
40578d09 3293 Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2);\r
7936fb6a 3294 break;\r
3295\r
3296 case EFI_IFR_BITWISE_OR_OP:\r
40578d09 3297 Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2);\r
7936fb6a 3298 break;\r
3299\r
3300 case EFI_IFR_SHIFT_LEFT_OP:\r
40578d09 3301 Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
7936fb6a 3302 break;\r
3303\r
3304 case EFI_IFR_SHIFT_RIGHT_OP:\r
40578d09 3305 Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
7936fb6a 3306 break;\r
3307\r
3308 default:\r
3309 break;\r
3310 }\r
3311 break;\r
3312\r
3313 case EFI_IFR_AND_OP:\r
3314 case EFI_IFR_OR_OP:\r
3315 //\r
3316 // Two Boolean operator\r
3317 //\r
3318 Status = PopExpression (&Data2);\r
3319 if (EFI_ERROR (Status)) {\r
2573712e 3320 goto Done;\r
7936fb6a 3321 }\r
7936fb6a 3322\r
3323 //\r
3324 // Pop another expression from the expression stack\r
3325 //\r
3326 Status = PopExpression (&Data1);\r
3327 if (EFI_ERROR (Status)) {\r
2573712e 3328 goto Done;\r
7936fb6a 3329 }\r
8f420676
ED
3330\r
3331 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3332 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3333 break;\r
3334 }\r
3335\r
7936fb6a 3336 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3337 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3338 break;\r
7936fb6a 3339 }\r
3340\r
3341 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
3342 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
3343 } else {\r
3344 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
3345 }\r
3346 break;\r
3347\r
3348 case EFI_IFR_EQUAL_OP:\r
3349 case EFI_IFR_NOT_EQUAL_OP:\r
3350 case EFI_IFR_GREATER_EQUAL_OP:\r
3351 case EFI_IFR_GREATER_THAN_OP:\r
3352 case EFI_IFR_LESS_EQUAL_OP:\r
3353 case EFI_IFR_LESS_THAN_OP:\r
3354 //\r
3355 // Compare two integer, string, boolean or date/time\r
3356 //\r
3357 Status = PopExpression (&Data2);\r
3358 if (EFI_ERROR (Status)) {\r
2573712e 3359 goto Done;\r
7936fb6a 3360 }\r
7936fb6a 3361\r
3362 //\r
3363 // Pop another expression from the expression stack\r
3364 //\r
3365 Status = PopExpression (&Data1);\r
3366 if (EFI_ERROR (Status)) {\r
2573712e 3367 goto Done;\r
7936fb6a 3368 }\r
3369\r
8f420676
ED
3370 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
3371 Data2.Type != EFI_IFR_TYPE_STRING && \r
40578d09 3372 !IsTypeInBuffer(&Data2)) {\r
8f420676
ED
3373 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3374 break;\r
3375 }\r
3376\r
3377 if (Data1.Type > EFI_IFR_TYPE_BOOLEAN && \r
3378 Data1.Type != EFI_IFR_TYPE_STRING && \r
40578d09 3379 !IsTypeInBuffer(&Data1)) {\r
8f420676
ED
3380 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3381 break;\r
3382 }\r
3383\r
3384 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
901ba0e7
ED
3385 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
3386 FreePool (Data1.Buffer);\r
40578d09
ED
3387 }\r
3388 if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
901ba0e7
ED
3389 FreePool (Data2.Buffer);\r
3390 }\r
3391 \r
8f420676
ED
3392 if (Status == EFI_UNSUPPORTED) {\r
3393 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3394 Status = EFI_SUCCESS;\r
3395 break;\r
3396 }\r
3397\r
3398 if (EFI_ERROR (Status)) {\r
2573712e 3399 goto Done;\r
7936fb6a 3400 }\r
3401\r
3402 switch (OpCode->Operand) {\r
3403 case EFI_IFR_EQUAL_OP:\r
3404 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
3405 break;\r
3406\r
3407 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 3408 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 3409 break;\r
3410\r
3411 case EFI_IFR_GREATER_EQUAL_OP:\r
3412 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
3413 break;\r
3414\r
3415 case EFI_IFR_GREATER_THAN_OP:\r
3416 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
3417 break;\r
3418\r
3419 case EFI_IFR_LESS_EQUAL_OP:\r
3420 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
3421 break;\r
3422\r
3423 case EFI_IFR_LESS_THAN_OP:\r
3424 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
3425 break;\r
3426\r
3427 default:\r
3428 break;\r
3429 }\r
3430 break;\r
3431\r
3432 case EFI_IFR_MATCH_OP:\r
20258293
ED
3433 Status = InitializeUnicodeCollationProtocol ();\r
3434 if (EFI_ERROR (Status)) {\r
3435 goto Done;\r
3436 }\r
3437 \r
7936fb6a 3438 Status = IfrMatch (FormSet, Value);\r
3439 break;\r
3440\r
9bd22b08
ED
3441 case EFI_IFR_MATCH2_OP:\r
3442 Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);\r
3443 break;\r
3444\r
7936fb6a 3445 case EFI_IFR_CATENATE_OP:\r
3446 Status = IfrCatenate (FormSet, Value);\r
3447 break;\r
3448\r
3449 //\r
3450 // ternary-op\r
3451 //\r
3452 case EFI_IFR_CONDITIONAL_OP:\r
3453 //\r
3454 // Pop third expression from the expression stack\r
3455 //\r
3456 Status = PopExpression (&Data3);\r
3457 if (EFI_ERROR (Status)) {\r
2573712e 3458 goto Done;\r
7936fb6a 3459 }\r
3460\r
3461 //\r
3462 // Pop second expression from the expression stack\r
3463 //\r
3464 Status = PopExpression (&Data2);\r
3465 if (EFI_ERROR (Status)) {\r
2573712e 3466 goto Done;\r
7936fb6a 3467 }\r
3468\r
3469 //\r
3470 // Pop first expression from the expression stack\r
3471 //\r
3472 Status = PopExpression (&Data1);\r
3473 if (EFI_ERROR (Status)) {\r
2573712e 3474 goto Done;\r
7936fb6a 3475 }\r
3476 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3477 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3478 break;\r
7936fb6a 3479 }\r
3480\r
3481 if (Data1.Value.b) {\r
3482 Value = &Data3;\r
3483 } else {\r
3484 Value = &Data2;\r
3485 }\r
3486 break;\r
3487\r
3488 case EFI_IFR_FIND_OP:\r
3489 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3490 break;\r
3491\r
3492 case EFI_IFR_MID_OP:\r
3493 Status = IfrMid (FormSet, Value);\r
3494 break;\r
3495\r
3496 case EFI_IFR_TOKEN_OP:\r
3497 Status = IfrToken (FormSet, Value);\r
3498 break;\r
3499\r
3500 case EFI_IFR_SPAN_OP:\r
3501 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3502 break;\r
3503\r
2573712e
LG
3504 case EFI_IFR_MAP_OP:\r
3505 //\r
3506 // Pop the check value\r
3507 //\r
3508 Status = PopExpression (&Data1);\r
3509 if (EFI_ERROR (Status)) {\r
3510 goto Done;\r
3511 }\r
3512 //\r
3513 // Check MapExpression list is valid.\r
3514 //\r
3515 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
3516 Status = EFI_INVALID_PARAMETER;\r
3517 goto Done;\r
3518 }\r
3519 //\r
3520 // Go through map expression list.\r
3521 //\r
3522 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
3523 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3524 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3525 //\r
3526 // Evaluate the first expression in this pair.\r
3527 //\r
3528 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3529 if (EFI_ERROR (Status)) {\r
3530 goto Done;\r
3531 }\r
3532 //\r
3533 // Compare the expression value with current value\r
3534 //\r
8f420676 3535 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
2573712e
LG
3536 //\r
3537 // Try get the map value.\r
3538 //\r
3539 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3540 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3541 Status = EFI_INVALID_PARAMETER;\r
3542 goto Done;\r
3543 }\r
3544 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3545 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3546 if (EFI_ERROR (Status)) {\r
3547 goto Done;\r
3548 }\r
3549 Value = &SubExpression->Result;\r
3550 break;\r
3551 }\r
3552 //\r
3553 // Skip the second expression on this pair.\r
3554 //\r
3555 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3556 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3557 Status = EFI_INVALID_PARAMETER;\r
3558 goto Done;\r
3559 }\r
3560 //\r
3561 // Goto the first expression on next pair.\r
3562 //\r
3563 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3564 }\r
3565\r
3566 //\r
3567 // No map value is found.\r
3568 //\r
3569 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3570 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3571 Value->Value.u8 = 0;\r
3572 }\r
3573 break;\r
3574\r
7936fb6a 3575 default:\r
3576 break;\r
3577 }\r
8f420676 3578 if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
2573712e 3579 goto Done;\r
7936fb6a 3580 }\r
3581\r
3582 Status = PushExpression (Value);\r
3583 if (EFI_ERROR (Status)) {\r
2573712e 3584 goto Done;\r
7936fb6a 3585 }\r
3586 }\r
3587\r
3588 //\r
3589 // Pop the final result from expression stack\r
3590 //\r
3591 Value = &Data1;\r
3592 Status = PopExpression (Value);\r
3593 if (EFI_ERROR (Status)) {\r
2573712e 3594 goto Done;\r
7936fb6a 3595 }\r
3596\r
3597 //\r
3598 // After evaluating an expression, there should be only one value left on the expression stack\r
3599 //\r
3600 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 3601 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 3602 }\r
3603\r
2573712e
LG
3604Done:\r
3605 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3606 if (!EFI_ERROR (Status)) {\r
3607 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3608 }\r
7936fb6a 3609\r
2573712e 3610 return Status;\r
7936fb6a 3611}\r
31585af4 3612\r
e6106e89
ED
3613/**\r
3614 Check whether the result is TRUE or FALSE.\r
3615 \r
3616 For the EFI_HII_VALUE value type is numeric, return TRUE if the\r
3617 value is not 0.\r
3618\r
3619 @param Result Input the result data.\r
3620\r
3621 @retval TRUE The result is TRUE.\r
3622 @retval FALSE The result is FALSE.\r
3623\r
3624**/\r
3625BOOLEAN\r
3626IsTrue (\r
3627 IN EFI_HII_VALUE *Result\r
3628 )\r
3629{\r
3630 switch (Result->Type) {\r
3631 case EFI_IFR_TYPE_BOOLEAN:\r
3632 return Result->Value.b;\r
3633\r
3634 case EFI_IFR_TYPE_NUM_SIZE_8:\r
4f467fd3 3635 return (BOOLEAN)(Result->Value.u8 != 0);\r
e6106e89
ED
3636\r
3637 case EFI_IFR_TYPE_NUM_SIZE_16:\r
4f467fd3 3638 return (BOOLEAN)(Result->Value.u16 != 0);\r
e6106e89
ED
3639\r
3640 case EFI_IFR_TYPE_NUM_SIZE_32:\r
4f467fd3 3641 return (BOOLEAN)(Result->Value.u32 != 0);\r
e6106e89
ED
3642\r
3643 case EFI_IFR_TYPE_NUM_SIZE_64:\r
4f467fd3 3644 return (BOOLEAN)(Result->Value.u64 != 0);\r
e6106e89
ED
3645\r
3646 default:\r
3647 return FALSE;\r
3648 }\r
3649}\r
3650\r
31585af4
ED
3651/**\r
3652 Return the result of the expression list. Check the expression list and \r
3653 return the highest priority express result. \r
3654 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
3655\r
3656 @param ExpList The input expression list.\r
3657 @param Evaluate Whether need to evaluate the expression first.\r
3658 @param FormSet FormSet associated with this expression.\r
3659 @param Form Form associated with this expression. \r
3660\r
3661 @retval EXPRESS_RESULT Return the higher priority express result. \r
3662 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3663\r
3664**/\r
3665EXPRESS_RESULT \r
3666EvaluateExpressionList (\r
3667 IN FORM_EXPRESSION_LIST *ExpList,\r
3668 IN BOOLEAN Evaluate,\r
3669 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
3670 IN FORM_BROWSER_FORM *Form OPTIONAL\r
3671 )\r
3672{\r
3673 UINTN Index;\r
3674 EXPRESS_RESULT ReturnVal;\r
3675 EXPRESS_RESULT CompareOne;\r
3676 EFI_STATUS Status;\r
3677\r
3678 if (ExpList == NULL) {\r
3679 return ExpressFalse;\r
3680 }\r
3681\r
3682 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3683 Index = 0;\r
3684\r
3685 //\r
3686 // Check whether need to evaluate the expression first.\r
3687 //\r
3688 if (Evaluate) { \r
3689 while (ExpList->Count > Index) {\r
3690 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
3691 if (EFI_ERROR (Status)) {\r
3692 return ExpressFalse;\r
3693 }\r
3694 }\r
3695 }\r
3696\r
3697 //\r
3698 // Run the list of expressions.\r
3699 //\r
3700 ReturnVal = ExpressFalse;\r
3701 for (Index = 0; Index < ExpList->Count; Index++) {\r
e6106e89 3702 if (IsTrue (&ExpList->Expression[Index]->Result)) {\r
31585af4
ED
3703 switch (ExpList->Expression[Index]->Type) {\r
3704 case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
3705 CompareOne = ExpressSuppress;\r
3706 break;\r
3707\r
3708 case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
3709 CompareOne = ExpressGrayOut;\r
3710 break;\r
3711\r
3712 case EFI_HII_EXPRESSION_DISABLE_IF:\r
3713 CompareOne = ExpressDisable;\r
3714 break;\r
3715\r
3716 default:\r
3717 return ExpressFalse; \r
3718 }\r
3719\r
3720 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3721 }\r
3722 }\r
3723 \r
3724 return ReturnVal;\r
3725}\r