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