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