]> 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
4e1005ec
ED
2375 StrPtr = NULL;\r
2376\r
7936fb6a 2377 //\r
2573712e 2378 // Save current stack offset.\r
7936fb6a 2379 //\r
2573712e 2380 StackOffset = SaveExpressionEvaluationStackOffset ();\r
7936fb6a 2381\r
bc166db3 2382 ASSERT (Expression != NULL);\r
7936fb6a 2383 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
2384\r
2385 Link = GetFirstNode (&Expression->OpCodeListHead);\r
2386 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
2387 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
2388\r
2389 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
2390\r
2391 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
2392 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
2393 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
2394\r
2395 Value = &Data3;\r
2396 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2397 Status = EFI_SUCCESS;\r
2398\r
2399 switch (OpCode->Operand) {\r
2400 //\r
2401 // Built-in functions\r
2402 //\r
2403 case EFI_IFR_EQ_ID_VAL_OP:\r
2404 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2405 if (Question == NULL) {\r
8f420676
ED
2406 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2407 break;\r
7936fb6a 2408 }\r
2409\r
8f420676
ED
2410 Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);\r
2411 if (Status == EFI_UNSUPPORTED) {\r
2412 Status = EFI_SUCCESS;\r
2413 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2414 break;\r
2415 }\r
2416\r
2417 if (EFI_ERROR (Status)) {\r
2573712e 2418 goto Done;\r
7936fb6a 2419 }\r
2420 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2421 break;\r
2422\r
2423 case EFI_IFR_EQ_ID_ID_OP:\r
2424 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2425 if (Question == NULL) {\r
8f420676
ED
2426 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2427 break;\r
7936fb6a 2428 }\r
2429\r
2430 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
2431 if (Question2 == NULL) {\r
8f420676
ED
2432 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2433 break;\r
7936fb6a 2434 }\r
2435\r
8f420676
ED
2436 Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);\r
2437 if (Status == EFI_UNSUPPORTED) {\r
2438 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2439 Status = EFI_SUCCESS;\r
2440 break;\r
2441 }\r
2442 if (EFI_ERROR (Status)) {\r
2573712e 2443 goto Done;\r
7936fb6a 2444 }\r
2445 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2446 break;\r
2447\r
e8ef4283 2448 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
7936fb6a 2449 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2450 if (Question == NULL) {\r
8f420676
ED
2451 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2452 break;\r
7936fb6a 2453 }\r
2454\r
2455 Value->Value.b = FALSE;\r
2456 for (Index =0; Index < OpCode->ListLength; Index++) {\r
2457 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
2458 Value->Value.b = TRUE;\r
2459 break;\r
2460 }\r
2461 }\r
2462 break;\r
2463\r
2464 case EFI_IFR_DUP_OP:\r
2465 Status = PopExpression (Value);\r
2466 if (EFI_ERROR (Status)) {\r
2573712e 2467 goto Done;\r
7936fb6a 2468 }\r
2469\r
2470 Status = PushExpression (Value);\r
2471 break;\r
2472\r
2473 case EFI_IFR_QUESTION_REF1_OP:\r
2474 case EFI_IFR_THIS_OP:\r
2475 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2476 if (Question == NULL) {\r
2573712e
LG
2477 Status = EFI_NOT_FOUND;\r
2478 goto Done;\r
7936fb6a 2479 }\r
2480\r
2481 Value = &Question->HiiValue;\r
2482 break;\r
2483\r
cbf73e50 2484 case EFI_IFR_SECURITY_OP:\r
2485 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
2486 break;\r
2487\r
2573712e
LG
2488 case EFI_IFR_GET_OP:\r
2489 //\r
2490 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2491 //\r
2492 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2493 Value->Value.u8 = 0;\r
2494 if (OpCode->VarStorage != NULL) {\r
2495 switch (OpCode->VarStorage->Type) {\r
2496 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2497 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2498 //\r
2499 // Get value from Edit Buffer\r
2500 //\r
2501 Value->Type = OpCode->ValueType;\r
2502 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2503 break;\r
2504 case EFI_HII_VARSTORE_NAME_VALUE:\r
2505 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2506 //\r
2507 // Get value from string except for STRING value.\r
2508 //\r
816a7110 2509 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);\r
2573712e 2510 if (!EFI_ERROR (Status)) {\r
771ececd 2511 ASSERT (StrPtr != NULL);\r
2573712e
LG
2512 TempLength = StrLen (StrPtr);\r
2513 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
2514 Value->Type = OpCode->ValueType;\r
2515 TempBuffer = (UINT8 *) &Value->Value;\r
2516 ZeroMem (TempStr, sizeof (TempStr));\r
2517 for (Index = 0; Index < TempLength; Index ++) {\r
2518 TempStr[0] = StrPtr[TempLength - Index - 1];\r
2519 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
2520 if ((Index & 1) == 0) {\r
2521 TempBuffer [Index/2] = DigitUint8;\r
2522 } else {\r
771ececd 2523 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
2524 }\r
2525 }\r
2526 } \r
2527 }\r
2528 }\r
2529 break;\r
2530 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2531 //\r
2532 // Get value from variable.\r
2533 //\r
2534 TempLength = OpCode->ValueWidth;\r
2535 Value->Type = OpCode->ValueType;\r
2536 Status = gRT->GetVariable (\r
2537 OpCode->ValueName,\r
2538 &OpCode->VarStorage->Guid,\r
2539 NULL,\r
2540 &TempLength,\r
2541 &Value->Value\r
2542 );\r
2543 if (EFI_ERROR (Status)) {\r
2544 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2545 Value->Value.u8 = 0;\r
2546 }\r
cce6230f 2547 break;\r
2573712e
LG
2548 default:\r
2549 //\r
2550 // Not recognize storage.\r
2551 //\r
2552 Status = EFI_UNSUPPORTED;\r
2553 goto Done;\r
2554 }\r
2555 } else {\r
2556 //\r
2557 // For Time/Date Data\r
2558 //\r
2559 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2560 //\r
2561 // Only support Data/Time data when storage doesn't exist.\r
2562 //\r
2563 Status = EFI_UNSUPPORTED;\r
2564 goto Done;\r
2565 }\r
2566 Status = gRT->GetTime (&EfiTime, NULL);\r
2567 if (!EFI_ERROR (Status)) {\r
2568 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2569 switch (OpCode->VarStoreInfo.VarOffset) {\r
2570 case 0x00:\r
2571 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
2572 Value->Value.u16 = EfiTime.Year;\r
2573 break;\r
2574 case 0x02:\r
2575 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2576 Value->Value.u8 = EfiTime.Month;\r
2577 break;\r
2578 case 0x03:\r
2579 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2580 Value->Value.u8 = EfiTime.Day;\r
2581 break;\r
2582 default:\r
2583 //\r
2584 // Invalid Date field.\r
2585 //\r
2586 Status = EFI_INVALID_PARAMETER;\r
2587 goto Done;\r
2588 }\r
2589 } else {\r
2590 switch (OpCode->VarStoreInfo.VarOffset) {\r
2591 case 0x00:\r
2592 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2593 Value->Value.u8 = EfiTime.Hour;\r
2594 break;\r
2595 case 0x01:\r
2596 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2597 Value->Value.u8 = EfiTime.Minute;\r
2598 break;\r
2599 case 0x02:\r
2600 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2601 Value->Value.u8 = EfiTime.Second;\r
2602 break;\r
2603 default:\r
2604 //\r
2605 // Invalid Time field.\r
2606 //\r
2607 Status = EFI_INVALID_PARAMETER;\r
2608 goto Done;\r
2609 }\r
2610 }\r
2611 }\r
2612 }\r
2613\r
2614 break;\r
2615\r
7936fb6a 2616 case EFI_IFR_QUESTION_REF3_OP:\r
db40504e
ED
2617 //\r
2618 // EFI_IFR_QUESTION_REF3\r
2619 // Pop an expression from the expression stack\r
2620 //\r
2621 Status = PopExpression (Value);\r
2622 if (EFI_ERROR (Status)) {\r
2623 goto Done;\r
2624 }\r
2625 \r
2626 //\r
2627 // Validate the expression value\r
2628 //\r
2629 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2630 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2631 break;\r
db40504e
ED
2632 }\r
2633\r
2634 if (OpCode->DevicePath != 0) {\r
80a047f0 2635 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
33efdf51 2636\r
80a047f0
ED
2637 StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
2638 if (StrPtr != NULL && mPathFromText != NULL) {\r
2639 DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);\r
2640 if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {\r
2641 Value = &QuestionVal;\r
2642 }\r
2643 if (DevicePath != NULL) {\r
2644 FreePool (DevicePath);\r
2645 }\r
33efdf51
ED
2646 }\r
2647\r
80a047f0
ED
2648 if (StrPtr != NULL) {\r
2649 FreePool (StrPtr);\r
7936fb6a 2650 }\r
db40504e
ED
2651 } else if (CompareGuid (&OpCode->Guid, &gZeroGuid) != 0) {\r
2652 if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
8f420676
ED
2653 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2654 break;\r
db40504e 2655 }\r
8f420676 2656 Value = &QuestionVal;\r
db40504e 2657 } else {\r
7936fb6a 2658 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2659 if (Question == NULL) {\r
8f420676
ED
2660 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2661 break;\r
7936fb6a 2662 }\r
2663\r
2664 //\r
2665 // push the questions' value on to the expression stack\r
2666 //\r
2667 Value = &Question->HiiValue;\r
7936fb6a 2668 }\r
2669 break;\r
2670\r
2671 case EFI_IFR_RULE_REF_OP:\r
2672 //\r
2673 // Find expression for this rule\r
2674 //\r
2675 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
2676 if (RuleExpression == NULL) {\r
8f420676
ED
2677 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2678 break;\r
7936fb6a 2679 }\r
2680\r
2681 //\r
2682 // Evaluate this rule expression\r
2683 //\r
2684 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
8f420676
ED
2685 if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {\r
2686 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2687 break;\r
7936fb6a 2688 }\r
2689\r
2690 Value = &RuleExpression->Result;\r
2691 break;\r
2692\r
2693 case EFI_IFR_STRING_REF1_OP:\r
2694 Value->Type = EFI_IFR_TYPE_STRING;\r
2695 Value->Value.string = OpCode->Value.Value.string;\r
2696 break;\r
2697\r
2698 //\r
2699 // Constant\r
2700 //\r
2701 case EFI_IFR_TRUE_OP:\r
2702 case EFI_IFR_FALSE_OP:\r
2703 case EFI_IFR_ONE_OP:\r
2704 case EFI_IFR_ONES_OP:\r
2705 case EFI_IFR_UINT8_OP:\r
2706 case EFI_IFR_UINT16_OP:\r
2707 case EFI_IFR_UINT32_OP:\r
2708 case EFI_IFR_UINT64_OP:\r
2709 case EFI_IFR_UNDEFINED_OP:\r
2710 case EFI_IFR_VERSION_OP:\r
2711 case EFI_IFR_ZERO_OP:\r
2712 Value = &OpCode->Value;\r
2713 break;\r
2714\r
2715 //\r
2716 // unary-op\r
2717 //\r
2718 case EFI_IFR_LENGTH_OP:\r
2719 Status = PopExpression (Value);\r
2720 if (EFI_ERROR (Status)) {\r
2573712e 2721 goto Done;\r
7936fb6a 2722 }\r
40578d09 2723 if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) {\r
8f420676
ED
2724 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2725 break;\r
7936fb6a 2726 }\r
2727\r
901ba0e7
ED
2728 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2729 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2730 if (StrPtr == NULL) {\r
2731 Status = EFI_INVALID_PARAMETER;\r
2732 goto Done;\r
2733 }\r
7936fb6a 2734\r
901ba0e7
ED
2735 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2736 Value->Value.u64 = StrLen (StrPtr);\r
2737 FreePool (StrPtr);\r
2738 } else {\r
2739 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
40578d09 2740 Value->Value.u64 = GetLengthForValue(Value);\r
901ba0e7
ED
2741 FreePool (Value->Buffer);\r
2742 }\r
7936fb6a 2743 break;\r
2744\r
2745 case EFI_IFR_NOT_OP:\r
2746 Status = PopExpression (Value);\r
2747 if (EFI_ERROR (Status)) {\r
2573712e 2748 goto Done;\r
7936fb6a 2749 }\r
2750 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
2751 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2752 break;\r
7936fb6a 2753 }\r
2754 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2755 break;\r
2756\r
2757 case EFI_IFR_QUESTION_REF2_OP:\r
2758 //\r
2759 // Pop an expression from the expression stack\r
2760 //\r
2761 Status = PopExpression (Value);\r
2762 if (EFI_ERROR (Status)) {\r
2573712e 2763 goto Done;\r
7936fb6a 2764 }\r
2765\r
2766 //\r
2767 // Validate the expression value\r
2768 //\r
2769 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2770 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2771 break;\r
7936fb6a 2772 }\r
2773\r
2774 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2775 if (Question == NULL) {\r
8f420676
ED
2776 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2777 break;\r
7936fb6a 2778 }\r
2779\r
2780 Value = &Question->HiiValue;\r
2781 break;\r
2782\r
2783 case EFI_IFR_STRING_REF2_OP:\r
2784 //\r
2785 // Pop an expression from the expression stack\r
2786 //\r
2787 Status = PopExpression (Value);\r
2788 if (EFI_ERROR (Status)) {\r
2573712e 2789 goto Done;\r
7936fb6a 2790 }\r
2791\r
2792 //\r
2793 // Validate the expression value\r
2794 //\r
2795 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2796 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2797 break;\r
7936fb6a 2798 }\r
2799\r
2800 Value->Type = EFI_IFR_TYPE_STRING;\r
2801 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2802 if (StrPtr == NULL) {\r
2803 //\r
2804 // If String not exit, push an empty string\r
2805 //\r
2806 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2807 } else {\r
2808 Index = (UINT16) Value->Value.u64;\r
2809 Value->Value.string = Index;\r
f4113e1f 2810 FreePool (StrPtr);\r
7936fb6a 2811 }\r
2812 break;\r
2813\r
2814 case EFI_IFR_TO_BOOLEAN_OP:\r
2815 //\r
2816 // Pop an expression from the expression stack\r
2817 //\r
2818 Status = PopExpression (Value);\r
2819 if (EFI_ERROR (Status)) {\r
2573712e 2820 goto Done;\r
7936fb6a 2821 }\r
2822\r
2823 //\r
2824 // Convert an expression to a Boolean\r
2825 //\r
2826 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
2827 //\r
2828 // When converting from an unsigned integer, zero will be converted to\r
2829 // FALSE and any other value will be converted to TRUE.\r
2830 //\r
40578d09 2831 Value->Value.b = (BOOLEAN) (HiiValueToUINT64(Value) != 0);\r
7936fb6a 2832\r
2833 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2834 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2835 //\r
2836 // When converting from a string, if case-insensitive compare\r
2837 // with "true" is True, then push True. If a case-insensitive compare\r
39099cbd 2838 // with "false" is True, then push False. Otherwise, push Undefined. \r
7936fb6a 2839 //\r
2840 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2841 if (StrPtr == NULL) {\r
2573712e
LG
2842 Status = EFI_INVALID_PARAMETER;\r
2843 goto Done;\r
7936fb6a 2844 }\r
39099cbd
ED
2845 \r
2846 IfrStrToUpper (StrPtr);\r
2847 if (StrCmp (StrPtr, L"TRUE") == 0){\r
7936fb6a 2848 Value->Value.b = TRUE;\r
8f420676 2849 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 2850 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
7936fb6a 2851 Value->Value.b = FALSE;\r
8f420676 2852 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 2853 } else {\r
8f420676 2854 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
7936fb6a 2855 }\r
f4113e1f 2856 FreePool (StrPtr);\r
901ba0e7
ED
2857 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
2858 //\r
2859 // When converting from a buffer, if the buffer is all zeroes, \r
2860 // then push False. Otherwise push True. \r
2861 //\r
2862 for (Index =0; Index < Value->BufferLen; Index ++) {\r
2863 if (Value->Buffer[Index] != 0) { \r
2864 break;\r
2865 }\r
2866 }\r
2867\r
2868 if (Index >= Value->BufferLen) {\r
2869 Value->Value.b = FALSE;\r
2870 } else {\r
2871 Value->Value.b = TRUE;\r
2872 }\r
2873 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2874 FreePool (Value->Buffer);\r
7936fb6a 2875 }\r
2876 break;\r
2877\r
2878 case EFI_IFR_TO_STRING_OP:\r
2879 Status = IfrToString (FormSet, OpCode->Format, Value);\r
2880 break;\r
2881\r
2882 case EFI_IFR_TO_UINT_OP:\r
2883 Status = IfrToUint (FormSet, Value);\r
2884 break;\r
2885\r
2886 case EFI_IFR_TO_LOWER_OP:\r
2887 case EFI_IFR_TO_UPPER_OP:\r
2888 Status = InitializeUnicodeCollationProtocol ();\r
2889 if (EFI_ERROR (Status)) {\r
2573712e 2890 goto Done;\r
7936fb6a 2891 }\r
2892\r
2893 Status = PopExpression (Value);\r
2894 if (EFI_ERROR (Status)) {\r
2573712e 2895 goto Done;\r
7936fb6a 2896 }\r
2897\r
2898 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
8f420676
ED
2899 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2900 break;\r
7936fb6a 2901 }\r
2902\r
2903 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2904 if (StrPtr == NULL) {\r
2573712e
LG
2905 Status = EFI_NOT_FOUND;\r
2906 goto Done;\r
7936fb6a 2907 }\r
2908\r
2909 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
2910 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
2911 } else {\r
2912 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
2913 }\r
2914 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 2915 FreePool (StrPtr);\r
7936fb6a 2916 break;\r
2917\r
2918 case EFI_IFR_BITWISE_NOT_OP:\r
2919 //\r
2920 // Pop an expression from the expression stack\r
2921 //\r
2922 Status = PopExpression (Value);\r
2923 if (EFI_ERROR (Status)) {\r
2573712e 2924 goto Done;\r
7936fb6a 2925 }\r
2926 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
2927 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2928 break;\r
7936fb6a 2929 }\r
2930\r
2931 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
40578d09 2932 Value->Value.u64 = ~ HiiValueToUINT64(Value);\r
7936fb6a 2933 break;\r
2934\r
2573712e
LG
2935 case EFI_IFR_SET_OP:\r
2936 //\r
2937 // Pop an expression from the expression stack\r
2938 //\r
2939 Status = PopExpression (Value);\r
2940 if (EFI_ERROR (Status)) {\r
2941 goto Done;\r
2942 }\r
2943 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
2944 Data1.Value.b = FALSE;\r
2945 //\r
2946 // Set value to var storage buffer\r
2947 //\r
2948 if (OpCode->VarStorage != NULL) {\r
2949 switch (OpCode->VarStorage->Type) {\r
2950 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2951 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2952 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
2953 Data1.Value.b = TRUE;\r
2954 break;\r
2955 case EFI_HII_VARSTORE_NAME_VALUE:\r
2956 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2957 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
2958 ASSERT (Value != NULL);\r
2959 //\r
2960 // Convert Buffer to Hex String\r
2961 //\r
2962 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
2963 StrPtr = NameValue;\r
2964 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
2965 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
2966 }\r
7c6c064c 2967 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
2573712e
LG
2968 FreePool (NameValue);\r
2969 if (!EFI_ERROR (Status)) {\r
2970 Data1.Value.b = TRUE;\r
2971 }\r
2972 }\r
2973 break;\r
2974 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2975 Status = gRT->SetVariable (\r
2976 OpCode->ValueName,\r
2977 &OpCode->VarStorage->Guid,\r
2978 OpCode->VarStorage->Attributes,\r
2979 OpCode->ValueWidth,\r
2980 &Value->Value\r
2981 );\r
2982 if (!EFI_ERROR (Status)) {\r
2983 Data1.Value.b = TRUE;\r
2984 }\r
2985 break;\r
2986 default:\r
2987 //\r
2988 // Not recognize storage.\r
2989 //\r
2990 Status = EFI_UNSUPPORTED;\r
2991 goto Done;\r
2992 break;\r
2993 }\r
2994 } else {\r
2995 //\r
2996 // For Time/Date Data\r
2997 //\r
2998 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2999 //\r
3000 // Only support Data/Time data when storage doesn't exist.\r
3001 //\r
3002 Status = EFI_UNSUPPORTED;\r
3003 goto Done;\r
3004 }\r
3005 Status = gRT->GetTime (&EfiTime, NULL);\r
3006 if (!EFI_ERROR (Status)) {\r
3007 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
3008 switch (OpCode->VarStoreInfo.VarOffset) {\r
3009 case 0x00:\r
3010 EfiTime.Year = Value->Value.u16;\r
3011 break;\r
3012 case 0x02:\r
3013 EfiTime.Month = Value->Value.u8;\r
3014 break;\r
3015 case 0x03:\r
3016 EfiTime.Day = Value->Value.u8;\r
3017 break;\r
3018 default:\r
3019 //\r
3020 // Invalid Date field.\r
3021 //\r
3022 Status = EFI_INVALID_PARAMETER;\r
3023 goto Done;\r
3024 }\r
3025 } else {\r
3026 switch (OpCode->VarStoreInfo.VarOffset) {\r
3027 case 0x00:\r
3028 EfiTime.Hour = Value->Value.u8;\r
3029 break;\r
3030 case 0x01:\r
3031 EfiTime.Minute = Value->Value.u8;\r
3032 break;\r
3033 case 0x02:\r
3034 EfiTime.Second = Value->Value.u8;\r
3035 break;\r
3036 default:\r
3037 //\r
3038 // Invalid Time field.\r
3039 //\r
3040 Status = EFI_INVALID_PARAMETER;\r
3041 goto Done;\r
3042 }\r
3043 }\r
3044 Status = gRT->SetTime (&EfiTime);\r
3045 if (!EFI_ERROR (Status)) {\r
3046 Data1.Value.b = TRUE;\r
3047 }\r
3048 }\r
3049 }\r
3050 Value = &Data1;\r
3051 break;\r
3052\r
7936fb6a 3053 //\r
3054 // binary-op\r
3055 //\r
3056 case EFI_IFR_ADD_OP:\r
3057 case EFI_IFR_SUBTRACT_OP:\r
3058 case EFI_IFR_MULTIPLY_OP:\r
3059 case EFI_IFR_DIVIDE_OP:\r
3060 case EFI_IFR_MODULO_OP:\r
3061 case EFI_IFR_BITWISE_AND_OP:\r
3062 case EFI_IFR_BITWISE_OR_OP:\r
3063 case EFI_IFR_SHIFT_LEFT_OP:\r
3064 case EFI_IFR_SHIFT_RIGHT_OP:\r
3065 //\r
3066 // Pop an expression from the expression stack\r
3067 //\r
3068 Status = PopExpression (&Data2);\r
3069 if (EFI_ERROR (Status)) {\r
2573712e 3070 goto Done;\r
7936fb6a 3071 }\r
7936fb6a 3072\r
3073 //\r
3074 // Pop another expression from the expression stack\r
3075 //\r
3076 Status = PopExpression (&Data1);\r
3077 if (EFI_ERROR (Status)) {\r
2573712e 3078 goto Done;\r
7936fb6a 3079 }\r
8f420676
ED
3080\r
3081 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
3082 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3083 break;\r
3084 }\r
3085\r
3086\r
7936fb6a 3087 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
3088 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3089 break;\r
7936fb6a 3090 }\r
3091\r
3092 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
3093\r
3094 switch (OpCode->Operand) {\r
3095 case EFI_IFR_ADD_OP:\r
40578d09 3096 Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2);\r
7936fb6a 3097 break;\r
3098\r
3099 case EFI_IFR_SUBTRACT_OP:\r
40578d09 3100 Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2);\r
7936fb6a 3101 break;\r
3102\r
3103 case EFI_IFR_MULTIPLY_OP:\r
40578d09 3104 Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
7936fb6a 3105 break;\r
3106\r
3107 case EFI_IFR_DIVIDE_OP:\r
40578d09 3108 Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
7936fb6a 3109 break;\r
3110\r
3111 case EFI_IFR_MODULO_OP:\r
40578d09 3112 DivU64x32Remainder (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &TempValue);\r
7936fb6a 3113 Value->Value.u64 = TempValue;\r
3114 break;\r
3115\r
3116 case EFI_IFR_BITWISE_AND_OP:\r
40578d09 3117 Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2);\r
7936fb6a 3118 break;\r
3119\r
3120 case EFI_IFR_BITWISE_OR_OP:\r
40578d09 3121 Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2);\r
7936fb6a 3122 break;\r
3123\r
3124 case EFI_IFR_SHIFT_LEFT_OP:\r
40578d09 3125 Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
7936fb6a 3126 break;\r
3127\r
3128 case EFI_IFR_SHIFT_RIGHT_OP:\r
40578d09 3129 Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
7936fb6a 3130 break;\r
3131\r
3132 default:\r
3133 break;\r
3134 }\r
3135 break;\r
3136\r
3137 case EFI_IFR_AND_OP:\r
3138 case EFI_IFR_OR_OP:\r
3139 //\r
3140 // Two Boolean operator\r
3141 //\r
3142 Status = PopExpression (&Data2);\r
3143 if (EFI_ERROR (Status)) {\r
2573712e 3144 goto Done;\r
7936fb6a 3145 }\r
7936fb6a 3146\r
3147 //\r
3148 // Pop another expression from the expression stack\r
3149 //\r
3150 Status = PopExpression (&Data1);\r
3151 if (EFI_ERROR (Status)) {\r
2573712e 3152 goto Done;\r
7936fb6a 3153 }\r
8f420676
ED
3154\r
3155 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3156 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3157 break;\r
3158 }\r
3159\r
7936fb6a 3160 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3161 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3162 break;\r
7936fb6a 3163 }\r
3164\r
3165 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
3166 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
3167 } else {\r
3168 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
3169 }\r
3170 break;\r
3171\r
3172 case EFI_IFR_EQUAL_OP:\r
3173 case EFI_IFR_NOT_EQUAL_OP:\r
3174 case EFI_IFR_GREATER_EQUAL_OP:\r
3175 case EFI_IFR_GREATER_THAN_OP:\r
3176 case EFI_IFR_LESS_EQUAL_OP:\r
3177 case EFI_IFR_LESS_THAN_OP:\r
3178 //\r
3179 // Compare two integer, string, boolean or date/time\r
3180 //\r
3181 Status = PopExpression (&Data2);\r
3182 if (EFI_ERROR (Status)) {\r
2573712e 3183 goto Done;\r
7936fb6a 3184 }\r
7936fb6a 3185\r
3186 //\r
3187 // Pop another expression from the expression stack\r
3188 //\r
3189 Status = PopExpression (&Data1);\r
3190 if (EFI_ERROR (Status)) {\r
2573712e 3191 goto Done;\r
7936fb6a 3192 }\r
3193\r
8f420676
ED
3194 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
3195 Data2.Type != EFI_IFR_TYPE_STRING && \r
40578d09 3196 !IsTypeInBuffer(&Data2)) {\r
8f420676
ED
3197 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3198 break;\r
3199 }\r
3200\r
3201 if (Data1.Type > EFI_IFR_TYPE_BOOLEAN && \r
3202 Data1.Type != EFI_IFR_TYPE_STRING && \r
40578d09 3203 !IsTypeInBuffer(&Data1)) {\r
8f420676
ED
3204 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3205 break;\r
3206 }\r
3207\r
3208 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
901ba0e7
ED
3209 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
3210 FreePool (Data1.Buffer);\r
40578d09
ED
3211 }\r
3212 if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
901ba0e7
ED
3213 FreePool (Data2.Buffer);\r
3214 }\r
3215 \r
8f420676
ED
3216 if (Status == EFI_UNSUPPORTED) {\r
3217 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3218 Status = EFI_SUCCESS;\r
3219 break;\r
3220 }\r
3221\r
3222 if (EFI_ERROR (Status)) {\r
2573712e 3223 goto Done;\r
7936fb6a 3224 }\r
3225\r
3226 switch (OpCode->Operand) {\r
3227 case EFI_IFR_EQUAL_OP:\r
3228 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
3229 break;\r
3230\r
3231 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 3232 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 3233 break;\r
3234\r
3235 case EFI_IFR_GREATER_EQUAL_OP:\r
3236 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
3237 break;\r
3238\r
3239 case EFI_IFR_GREATER_THAN_OP:\r
3240 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
3241 break;\r
3242\r
3243 case EFI_IFR_LESS_EQUAL_OP:\r
3244 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
3245 break;\r
3246\r
3247 case EFI_IFR_LESS_THAN_OP:\r
3248 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
3249 break;\r
3250\r
3251 default:\r
3252 break;\r
3253 }\r
3254 break;\r
3255\r
3256 case EFI_IFR_MATCH_OP:\r
20258293
ED
3257 Status = InitializeUnicodeCollationProtocol ();\r
3258 if (EFI_ERROR (Status)) {\r
3259 goto Done;\r
3260 }\r
3261 \r
7936fb6a 3262 Status = IfrMatch (FormSet, Value);\r
3263 break;\r
3264\r
3265 case EFI_IFR_CATENATE_OP:\r
3266 Status = IfrCatenate (FormSet, Value);\r
3267 break;\r
3268\r
3269 //\r
3270 // ternary-op\r
3271 //\r
3272 case EFI_IFR_CONDITIONAL_OP:\r
3273 //\r
3274 // Pop third expression from the expression stack\r
3275 //\r
3276 Status = PopExpression (&Data3);\r
3277 if (EFI_ERROR (Status)) {\r
2573712e 3278 goto Done;\r
7936fb6a 3279 }\r
3280\r
3281 //\r
3282 // Pop second expression from the expression stack\r
3283 //\r
3284 Status = PopExpression (&Data2);\r
3285 if (EFI_ERROR (Status)) {\r
2573712e 3286 goto Done;\r
7936fb6a 3287 }\r
3288\r
3289 //\r
3290 // Pop first expression from the expression stack\r
3291 //\r
3292 Status = PopExpression (&Data1);\r
3293 if (EFI_ERROR (Status)) {\r
2573712e 3294 goto Done;\r
7936fb6a 3295 }\r
3296 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3297 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3298 break;\r
7936fb6a 3299 }\r
3300\r
3301 if (Data1.Value.b) {\r
3302 Value = &Data3;\r
3303 } else {\r
3304 Value = &Data2;\r
3305 }\r
3306 break;\r
3307\r
3308 case EFI_IFR_FIND_OP:\r
3309 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3310 break;\r
3311\r
3312 case EFI_IFR_MID_OP:\r
3313 Status = IfrMid (FormSet, Value);\r
3314 break;\r
3315\r
3316 case EFI_IFR_TOKEN_OP:\r
3317 Status = IfrToken (FormSet, Value);\r
3318 break;\r
3319\r
3320 case EFI_IFR_SPAN_OP:\r
3321 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3322 break;\r
3323\r
2573712e
LG
3324 case EFI_IFR_MAP_OP:\r
3325 //\r
3326 // Pop the check value\r
3327 //\r
3328 Status = PopExpression (&Data1);\r
3329 if (EFI_ERROR (Status)) {\r
3330 goto Done;\r
3331 }\r
3332 //\r
3333 // Check MapExpression list is valid.\r
3334 //\r
3335 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
3336 Status = EFI_INVALID_PARAMETER;\r
3337 goto Done;\r
3338 }\r
3339 //\r
3340 // Go through map expression list.\r
3341 //\r
3342 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
3343 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3344 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3345 //\r
3346 // Evaluate the first expression in this pair.\r
3347 //\r
3348 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3349 if (EFI_ERROR (Status)) {\r
3350 goto Done;\r
3351 }\r
3352 //\r
3353 // Compare the expression value with current value\r
3354 //\r
8f420676 3355 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
2573712e
LG
3356 //\r
3357 // Try get the map value.\r
3358 //\r
3359 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3360 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3361 Status = EFI_INVALID_PARAMETER;\r
3362 goto Done;\r
3363 }\r
3364 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3365 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3366 if (EFI_ERROR (Status)) {\r
3367 goto Done;\r
3368 }\r
3369 Value = &SubExpression->Result;\r
3370 break;\r
3371 }\r
3372 //\r
3373 // Skip the second expression on this pair.\r
3374 //\r
3375 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3376 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3377 Status = EFI_INVALID_PARAMETER;\r
3378 goto Done;\r
3379 }\r
3380 //\r
3381 // Goto the first expression on next pair.\r
3382 //\r
3383 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3384 }\r
3385\r
3386 //\r
3387 // No map value is found.\r
3388 //\r
3389 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3390 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3391 Value->Value.u8 = 0;\r
3392 }\r
3393 break;\r
3394\r
7936fb6a 3395 default:\r
3396 break;\r
3397 }\r
8f420676 3398 if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
2573712e 3399 goto Done;\r
7936fb6a 3400 }\r
3401\r
3402 Status = PushExpression (Value);\r
3403 if (EFI_ERROR (Status)) {\r
2573712e 3404 goto Done;\r
7936fb6a 3405 }\r
3406 }\r
3407\r
3408 //\r
3409 // Pop the final result from expression stack\r
3410 //\r
3411 Value = &Data1;\r
3412 Status = PopExpression (Value);\r
3413 if (EFI_ERROR (Status)) {\r
2573712e 3414 goto Done;\r
7936fb6a 3415 }\r
3416\r
3417 //\r
3418 // After evaluating an expression, there should be only one value left on the expression stack\r
3419 //\r
3420 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 3421 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 3422 }\r
3423\r
2573712e
LG
3424Done:\r
3425 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3426 if (!EFI_ERROR (Status)) {\r
3427 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3428 }\r
7936fb6a 3429\r
2573712e 3430 return Status;\r
7936fb6a 3431}\r
31585af4 3432\r
e6106e89
ED
3433/**\r
3434 Check whether the result is TRUE or FALSE.\r
3435 \r
3436 For the EFI_HII_VALUE value type is numeric, return TRUE if the\r
3437 value is not 0.\r
3438\r
3439 @param Result Input the result data.\r
3440\r
3441 @retval TRUE The result is TRUE.\r
3442 @retval FALSE The result is FALSE.\r
3443\r
3444**/\r
3445BOOLEAN\r
3446IsTrue (\r
3447 IN EFI_HII_VALUE *Result\r
3448 )\r
3449{\r
3450 switch (Result->Type) {\r
3451 case EFI_IFR_TYPE_BOOLEAN:\r
3452 return Result->Value.b;\r
3453\r
3454 case EFI_IFR_TYPE_NUM_SIZE_8:\r
4f467fd3 3455 return (BOOLEAN)(Result->Value.u8 != 0);\r
e6106e89
ED
3456\r
3457 case EFI_IFR_TYPE_NUM_SIZE_16:\r
4f467fd3 3458 return (BOOLEAN)(Result->Value.u16 != 0);\r
e6106e89
ED
3459\r
3460 case EFI_IFR_TYPE_NUM_SIZE_32:\r
4f467fd3 3461 return (BOOLEAN)(Result->Value.u32 != 0);\r
e6106e89
ED
3462\r
3463 case EFI_IFR_TYPE_NUM_SIZE_64:\r
4f467fd3 3464 return (BOOLEAN)(Result->Value.u64 != 0);\r
e6106e89
ED
3465\r
3466 default:\r
3467 return FALSE;\r
3468 }\r
3469}\r
3470\r
31585af4
ED
3471/**\r
3472 Return the result of the expression list. Check the expression list and \r
3473 return the highest priority express result. \r
3474 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
3475\r
3476 @param ExpList The input expression list.\r
3477 @param Evaluate Whether need to evaluate the expression first.\r
3478 @param FormSet FormSet associated with this expression.\r
3479 @param Form Form associated with this expression. \r
3480\r
3481 @retval EXPRESS_RESULT Return the higher priority express result. \r
3482 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3483\r
3484**/\r
3485EXPRESS_RESULT \r
3486EvaluateExpressionList (\r
3487 IN FORM_EXPRESSION_LIST *ExpList,\r
3488 IN BOOLEAN Evaluate,\r
3489 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
3490 IN FORM_BROWSER_FORM *Form OPTIONAL\r
3491 )\r
3492{\r
3493 UINTN Index;\r
3494 EXPRESS_RESULT ReturnVal;\r
3495 EXPRESS_RESULT CompareOne;\r
3496 EFI_STATUS Status;\r
3497\r
3498 if (ExpList == NULL) {\r
3499 return ExpressFalse;\r
3500 }\r
3501\r
3502 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3503 Index = 0;\r
3504\r
3505 //\r
3506 // Check whether need to evaluate the expression first.\r
3507 //\r
3508 if (Evaluate) { \r
3509 while (ExpList->Count > Index) {\r
3510 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
3511 if (EFI_ERROR (Status)) {\r
3512 return ExpressFalse;\r
3513 }\r
3514 }\r
3515 }\r
3516\r
3517 //\r
3518 // Run the list of expressions.\r
3519 //\r
3520 ReturnVal = ExpressFalse;\r
3521 for (Index = 0; Index < ExpList->Count; Index++) {\r
e6106e89 3522 if (IsTrue (&ExpList->Expression[Index]->Result)) {\r
31585af4
ED
3523 switch (ExpList->Expression[Index]->Type) {\r
3524 case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
3525 CompareOne = ExpressSuppress;\r
3526 break;\r
3527\r
3528 case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
3529 CompareOne = ExpressGrayOut;\r
3530 break;\r
3531\r
3532 case EFI_HII_EXPRESSION_DISABLE_IF:\r
3533 CompareOne = ExpressDisable;\r
3534 break;\r
3535\r
3536 default:\r
3537 return ExpressFalse; \r
3538 }\r
3539\r
3540 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3541 }\r
3542 }\r
3543 \r
3544 return ReturnVal;\r
3545}\r