]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
ShellPkg: Add ShellHexStrToUintn to allow for simple conversion of hex numbers.
[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
1802\r
1803/**\r
1804 Compare two Hii value.\r
1805\r
1806 @param Value1 Expression value to compare on left-hand.\r
1807 @param Value2 Expression value to compare on right-hand.\r
8f420676
ED
1808 @param Result Return value after compare.\r
1809 retval 0 Two operators equal.\r
1810 return Positive value if Value1 is greater than Value2.\r
1811 retval Negative value if Value1 is less than Value2.\r
7936fb6a 1812 @param HiiHandle Only required for string compare.\r
1813\r
8f420676
ED
1814 @retval other Could not perform compare on two values.\r
1815 @retval EFI_SUCCESS Compare the value success.\r
7936fb6a 1816\r
1817**/\r
8f420676 1818EFI_STATUS\r
7936fb6a 1819CompareHiiValue (\r
1820 IN EFI_HII_VALUE *Value1,\r
1821 IN EFI_HII_VALUE *Value2,\r
8f420676 1822 OUT INTN *Result,\r
7936fb6a 1823 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
1824 )\r
1825{\r
7936fb6a 1826 INT64 Temp64;\r
1827 CHAR16 *Str1;\r
1828 CHAR16 *Str2;\r
901ba0e7 1829 UINTN Len;\r
7936fb6a 1830\r
1831 if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
901ba0e7 1832 if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {\r
8f420676 1833 return EFI_UNSUPPORTED;\r
901ba0e7 1834 }\r
7936fb6a 1835 }\r
1836\r
1837 if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
1838 if (Value1->Type != Value2->Type) {\r
1839 //\r
1840 // Both Operator should be type of String\r
1841 //\r
8f420676 1842 return EFI_UNSUPPORTED;\r
7936fb6a 1843 }\r
1844\r
1845 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
1846 //\r
1847 // StringId 0 is reserved\r
1848 //\r
1849 return EFI_INVALID_PARAMETER;\r
1850 }\r
1851\r
1852 if (Value1->Value.string == Value2->Value.string) {\r
8f420676
ED
1853 *Result = 0;\r
1854 return EFI_SUCCESS;\r
7936fb6a 1855 }\r
1856\r
1857 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
1858 if (Str1 == NULL) {\r
1859 //\r
1860 // String not found\r
1861 //\r
8f420676 1862 return EFI_NOT_FOUND;\r
7936fb6a 1863 }\r
1864\r
1865 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
1866 if (Str2 == NULL) {\r
f4113e1f 1867 FreePool (Str1);\r
8f420676 1868 return EFI_NOT_FOUND;\r
7936fb6a 1869 }\r
1870\r
8f420676 1871 *Result = StrCmp (Str1, Str2);\r
7936fb6a 1872\r
f4113e1f 1873 FreePool (Str1);\r
1874 FreePool (Str2);\r
7936fb6a 1875\r
8f420676 1876 return EFI_SUCCESS;\r
7936fb6a 1877 }\r
1878\r
901ba0e7
ED
1879 if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) {\r
1880 if (Value1->Type != Value2->Type) {\r
1881 //\r
1882 // Both Operator should be type of Buffer.\r
1883 //\r
8f420676 1884 return EFI_UNSUPPORTED;\r
901ba0e7
ED
1885 }\r
1886 Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;\r
8f420676
ED
1887 *Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);\r
1888 if ((*Result == 0) && (Value1->BufferLen != Value2->BufferLen))\r
901ba0e7
ED
1889 {\r
1890 //\r
1891 // In this case, means base on samll number buffer, the data is same\r
1892 // So which value has more data, which value is bigger.\r
1893 //\r
8f420676 1894 *Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1;\r
901ba0e7 1895 }\r
8f420676 1896 return EFI_SUCCESS;\r
901ba0e7
ED
1897 } \r
1898\r
7936fb6a 1899 //\r
1900 // Take remain types(integer, boolean, date/time) as integer\r
1901 //\r
1902 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
1903 if (Temp64 > 0) {\r
8f420676 1904 *Result = 1;\r
7936fb6a 1905 } else if (Temp64 < 0) {\r
8f420676 1906 *Result = -1;\r
7936fb6a 1907 } else {\r
8f420676 1908 *Result = 0;\r
7936fb6a 1909 }\r
1910\r
8f420676 1911 return EFI_SUCCESS;\r
7936fb6a 1912}\r
1913\r
cbf73e50 1914/**\r
1915 Check if current user has the privilege specified by the permissions GUID.\r
1916\r
1917 @param[in] Guid A GUID specifying setup access permissions.\r
1918\r
1919 @retval TRUE Current user has the privilege.\r
1920 @retval FALSE Current user does not have the privilege.\r
1921**/\r
1922BOOLEAN\r
1923CheckUserPrivilege (\r
1924 IN EFI_GUID *Guid\r
1925 )\r
1926{\r
1927 EFI_STATUS Status;\r
1928 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
1929 EFI_USER_INFO_HANDLE UserInfoHandle;\r
1930 EFI_USER_INFO *UserInfo;\r
1931 EFI_GUID *UserPermissionsGuid;\r
1932 UINTN UserInfoSize;\r
1933 UINTN AccessControlDataSize;\r
1934 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
1935 UINTN RemainSize;\r
1936\r
1937 if (mUserManager == NULL) {\r
1938 Status = gBS->LocateProtocol (\r
1939 &gEfiUserManagerProtocolGuid,\r
1940 NULL,\r
1941 (VOID **) &mUserManager\r
1942 );\r
1943 if (EFI_ERROR (Status)) {\r
1944 ///\r
1945 /// If the system does not support user management, then it is assumed that\r
1946 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
1947 /// op-code is always TRUE.\r
1948 ///\r
1949 return TRUE;\r
1950 }\r
1951 }\r
1952\r
1953 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
1954 ASSERT_EFI_ERROR (Status);\r
1955\r
1956 ///\r
1957 /// Enumerate all user information of the current user profile\r
1958 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
1959 ///\r
1960 \r
1961 for (UserInfoHandle = NULL;;) {\r
1962 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
1963 if (EFI_ERROR (Status)) {\r
1964 break;\r
1965 }\r
1966\r
1967 UserInfoSize = 0;\r
1968 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
1969 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1970 continue;\r
1971 }\r
1972\r
1973 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
1974 if (UserInfo == NULL) {\r
1975 break;\r
1976 }\r
1977\r
1978 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
1979 if (EFI_ERROR (Status) ||\r
1980 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
1981 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
1982 FreePool (UserInfo);\r
1983 continue;\r
1984 }\r
1985\r
1986 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
1987 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
1988 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
3dd405be 1989 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
cbf73e50 1990 break;\r
1991 }\r
1992 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
1993 ///\r
1994 /// Check if current user has the privilege specified by the permissions GUID.\r
1995 ///\r
1996\r
1997 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
1998 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
1999 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
2000 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
2001 FreePool (UserInfo);\r
2002 return TRUE;\r
2003 }\r
2004 UserPermissionsGuid++;\r
2005 AccessControlDataSize -= sizeof (EFI_GUID);\r
2006 }\r
2007 }\r
2008 RemainSize -= AccessControl->Size;\r
2009 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
2010 }\r
2011\r
2012 FreePool (UserInfo);\r
2013 }\r
2014 return FALSE;\r
2015}\r
7936fb6a 2016\r
db40504e
ED
2017/**\r
2018 Get question value from the predefined formset.\r
2019\r
2020 @param DevicePath The driver's device path which produece the formset data.\r
2021 @param InputHiiHandle The hii handle associate with the formset data.\r
2022 @param FormSetGuid The formset guid which include the question.\r
2023 @param QuestionId The question id which need to get value from.\r
2024 @param Value The return data about question's value.\r
2025 \r
2026 @retval TRUE Get the question value success.\r
2027 @retval FALSE Get the question value failed.\r
2028**/\r
2029BOOLEAN \r
2030GetQuestionValueFromForm (\r
2031 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2032 IN EFI_HII_HANDLE InputHiiHandle,\r
2033 IN EFI_GUID *FormSetGuid,\r
2034 IN EFI_QUESTION_ID QuestionId,\r
2035 OUT EFI_HII_VALUE *Value\r
2036 )\r
2037{\r
2038 EFI_STATUS Status;\r
db40504e 2039 EFI_HII_HANDLE HiiHandle;\r
db40504e
ED
2040 FORM_BROWSER_STATEMENT *Question;\r
2041 FORM_BROWSER_FORMSET *FormSet;\r
2042 FORM_BROWSER_FORM *Form;\r
2043 BOOLEAN GetTheVal;\r
2044 LIST_ENTRY *Link;\r
2045\r
2046 // \r
2047 // The input parameter DevicePath or InputHiiHandle must have one valid input. \r
2048 //\r
2049 ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) || \r
2050 (DevicePath == NULL && InputHiiHandle != NULL) );\r
2051\r
2052 GetTheVal = TRUE;\r
db40504e
ED
2053 HiiHandle = NULL;\r
2054 Question = NULL;\r
2055 Form = NULL;\r
2056\r
2057 //\r
2058 // Get HiiHandle.\r
2059 //\r
2060 if (DevicePath != NULL) {\r
07d7dbae
ED
2061 HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
2062 if (HiiHandle == NULL) {\r
db40504e
ED
2063 return FALSE;\r
2064 }\r
db40504e
ED
2065 } else {\r
2066 HiiHandle = InputHiiHandle;\r
2067 } \r
2068 ASSERT (HiiHandle != NULL);\r
2069\r
2070 //\r
2071 // Get the formset data include this question.\r
2072 //\r
2073 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
2074 ASSERT (FormSet != NULL);\r
7c6c064c 2075 Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);\r
db40504e
ED
2076 if (EFI_ERROR (Status)) {\r
2077 GetTheVal = FALSE;\r
2078 goto Done;\r
2079 }\r
2080\r
2081 //\r
2082 // Base on the Question Id to get the question info.\r
2083 // \r
2084 Question = IdToQuestion(FormSet, NULL, QuestionId);\r
2085 if (Question == NULL) {\r
2086 GetTheVal = FALSE;\r
2087 goto Done;\r
2088 }\r
2089\r
2090 //\r
2091 // Search form in the formset scope\r
2092 //\r
2093 Link = GetFirstNode (&FormSet->FormListHead);\r
2094 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2095 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2096\r
2097 Question = IdToQuestion2 (Form, QuestionId);\r
2098 if (Question != NULL) {\r
2099 break;\r
2100 }\r
2101\r
2102 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2103 Form = NULL;\r
2104 }\r
2105 ASSERT (Form != NULL);\r
2106 \r
2107 //\r
2108 // Get the question value.\r
2109 //\r
816a7110 2110 Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithHiiDriver);\r
db40504e
ED
2111 if (EFI_ERROR (Status)) {\r
2112 GetTheVal = FALSE;\r
2113 goto Done;\r
2114 }\r
2115\r
2116 CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
2117 \r
2118Done:\r
2119 //\r
2120 // Clean the formset structure and restore the global parameter.\r
2121 //\r
2122 if (FormSet != NULL) {\r
2123 DestroyFormSet (FormSet);\r
2124 }\r
2125 \r
2126 return GetTheVal;\r
2127}\r
2128\r
7936fb6a 2129/**\r
bc166db3 2130 Evaluate the result of a HII expression.\r
2131\r
2132 If Expression is NULL, then ASSERT.\r
7936fb6a 2133\r
2134 @param FormSet FormSet associated with this expression.\r
2135 @param Form Form associated with this expression.\r
2136 @param Expression Expression to be evaluated.\r
2137\r
2138 @retval EFI_SUCCESS The expression evaluated successfuly\r
2139 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
2140 could not be found.\r
2141 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
2142 stack.\r
2143 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
2144 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
2145\r
2146**/\r
2147EFI_STATUS\r
2148EvaluateExpression (\r
2149 IN FORM_BROWSER_FORMSET *FormSet,\r
2150 IN FORM_BROWSER_FORM *Form,\r
2151 IN OUT FORM_EXPRESSION *Expression\r
2152 )\r
2153{\r
2154 EFI_STATUS Status;\r
2155 LIST_ENTRY *Link;\r
2156 EXPRESSION_OPCODE *OpCode;\r
2157 FORM_BROWSER_STATEMENT *Question;\r
2158 FORM_BROWSER_STATEMENT *Question2;\r
2159 UINT16 Index;\r
2160 EFI_HII_VALUE Data1;\r
2161 EFI_HII_VALUE Data2;\r
2162 EFI_HII_VALUE Data3;\r
2163 FORM_EXPRESSION *RuleExpression;\r
2164 EFI_HII_VALUE *Value;\r
2165 INTN Result;\r
2166 CHAR16 *StrPtr;\r
2573712e 2167 CHAR16 *NameValue;\r
7936fb6a 2168 UINT32 TempValue;\r
2573712e
LG
2169 LIST_ENTRY *SubExpressionLink;\r
2170 FORM_EXPRESSION *SubExpression;\r
2171 UINTN StackOffset;\r
2172 UINTN TempLength;\r
2173 CHAR16 TempStr[5];\r
2174 UINT8 DigitUint8;\r
2175 UINT8 *TempBuffer;\r
2176 EFI_TIME EfiTime;\r
db40504e 2177 EFI_HII_VALUE QuestionVal;\r
33efdf51 2178 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
7936fb6a 2179\r
2180 //\r
2573712e 2181 // Save current stack offset.\r
7936fb6a 2182 //\r
2573712e 2183 StackOffset = SaveExpressionEvaluationStackOffset ();\r
7936fb6a 2184\r
bc166db3 2185 ASSERT (Expression != NULL);\r
7936fb6a 2186 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
2187\r
2188 Link = GetFirstNode (&Expression->OpCodeListHead);\r
2189 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
2190 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
2191\r
2192 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
2193\r
2194 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
2195 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
2196 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
2197\r
2198 Value = &Data3;\r
2199 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2200 Status = EFI_SUCCESS;\r
2201\r
2202 switch (OpCode->Operand) {\r
2203 //\r
2204 // Built-in functions\r
2205 //\r
2206 case EFI_IFR_EQ_ID_VAL_OP:\r
2207 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2208 if (Question == NULL) {\r
8f420676
ED
2209 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2210 break;\r
7936fb6a 2211 }\r
2212\r
8f420676
ED
2213 Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);\r
2214 if (Status == EFI_UNSUPPORTED) {\r
2215 Status = EFI_SUCCESS;\r
2216 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2217 break;\r
2218 }\r
2219\r
2220 if (EFI_ERROR (Status)) {\r
2573712e 2221 goto Done;\r
7936fb6a 2222 }\r
2223 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2224 break;\r
2225\r
2226 case EFI_IFR_EQ_ID_ID_OP:\r
2227 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2228 if (Question == NULL) {\r
8f420676
ED
2229 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2230 break;\r
7936fb6a 2231 }\r
2232\r
2233 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
2234 if (Question2 == NULL) {\r
8f420676
ED
2235 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2236 break;\r
7936fb6a 2237 }\r
2238\r
8f420676
ED
2239 Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);\r
2240 if (Status == EFI_UNSUPPORTED) {\r
2241 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2242 Status = EFI_SUCCESS;\r
2243 break;\r
2244 }\r
2245 if (EFI_ERROR (Status)) {\r
2573712e 2246 goto Done;\r
7936fb6a 2247 }\r
2248 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2249 break;\r
2250\r
e8ef4283 2251 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
7936fb6a 2252 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2253 if (Question == NULL) {\r
8f420676
ED
2254 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2255 break;\r
7936fb6a 2256 }\r
2257\r
2258 Value->Value.b = FALSE;\r
2259 for (Index =0; Index < OpCode->ListLength; Index++) {\r
2260 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
2261 Value->Value.b = TRUE;\r
2262 break;\r
2263 }\r
2264 }\r
2265 break;\r
2266\r
2267 case EFI_IFR_DUP_OP:\r
2268 Status = PopExpression (Value);\r
2269 if (EFI_ERROR (Status)) {\r
2573712e 2270 goto Done;\r
7936fb6a 2271 }\r
2272\r
2273 Status = PushExpression (Value);\r
2274 break;\r
2275\r
2276 case EFI_IFR_QUESTION_REF1_OP:\r
2277 case EFI_IFR_THIS_OP:\r
2278 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2279 if (Question == NULL) {\r
2573712e
LG
2280 Status = EFI_NOT_FOUND;\r
2281 goto Done;\r
7936fb6a 2282 }\r
2283\r
2284 Value = &Question->HiiValue;\r
2285 break;\r
2286\r
cbf73e50 2287 case EFI_IFR_SECURITY_OP:\r
2288 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
2289 break;\r
2290\r
2573712e
LG
2291 case EFI_IFR_GET_OP:\r
2292 //\r
2293 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2294 //\r
2295 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2296 Value->Value.u8 = 0;\r
2297 if (OpCode->VarStorage != NULL) {\r
2298 switch (OpCode->VarStorage->Type) {\r
2299 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2300 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2301 //\r
2302 // Get value from Edit Buffer\r
2303 //\r
2304 Value->Type = OpCode->ValueType;\r
2305 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2306 break;\r
2307 case EFI_HII_VARSTORE_NAME_VALUE:\r
2308 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2309 //\r
2310 // Get value from string except for STRING value.\r
2311 //\r
816a7110 2312 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);\r
2573712e 2313 if (!EFI_ERROR (Status)) {\r
771ececd 2314 ASSERT (StrPtr != NULL);\r
2573712e
LG
2315 TempLength = StrLen (StrPtr);\r
2316 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
2317 Value->Type = OpCode->ValueType;\r
2318 TempBuffer = (UINT8 *) &Value->Value;\r
2319 ZeroMem (TempStr, sizeof (TempStr));\r
2320 for (Index = 0; Index < TempLength; Index ++) {\r
2321 TempStr[0] = StrPtr[TempLength - Index - 1];\r
2322 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
2323 if ((Index & 1) == 0) {\r
2324 TempBuffer [Index/2] = DigitUint8;\r
2325 } else {\r
771ececd 2326 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
2327 }\r
2328 }\r
2329 } \r
2330 }\r
2331 }\r
2332 break;\r
2333 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2334 //\r
2335 // Get value from variable.\r
2336 //\r
2337 TempLength = OpCode->ValueWidth;\r
2338 Value->Type = OpCode->ValueType;\r
2339 Status = gRT->GetVariable (\r
2340 OpCode->ValueName,\r
2341 &OpCode->VarStorage->Guid,\r
2342 NULL,\r
2343 &TempLength,\r
2344 &Value->Value\r
2345 );\r
2346 if (EFI_ERROR (Status)) {\r
2347 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2348 Value->Value.u8 = 0;\r
2349 }\r
cce6230f 2350 break;\r
2573712e
LG
2351 default:\r
2352 //\r
2353 // Not recognize storage.\r
2354 //\r
2355 Status = EFI_UNSUPPORTED;\r
2356 goto Done;\r
2357 }\r
2358 } else {\r
2359 //\r
2360 // For Time/Date Data\r
2361 //\r
2362 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2363 //\r
2364 // Only support Data/Time data when storage doesn't exist.\r
2365 //\r
2366 Status = EFI_UNSUPPORTED;\r
2367 goto Done;\r
2368 }\r
2369 Status = gRT->GetTime (&EfiTime, NULL);\r
2370 if (!EFI_ERROR (Status)) {\r
2371 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2372 switch (OpCode->VarStoreInfo.VarOffset) {\r
2373 case 0x00:\r
2374 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
2375 Value->Value.u16 = EfiTime.Year;\r
2376 break;\r
2377 case 0x02:\r
2378 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2379 Value->Value.u8 = EfiTime.Month;\r
2380 break;\r
2381 case 0x03:\r
2382 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2383 Value->Value.u8 = EfiTime.Day;\r
2384 break;\r
2385 default:\r
2386 //\r
2387 // Invalid Date field.\r
2388 //\r
2389 Status = EFI_INVALID_PARAMETER;\r
2390 goto Done;\r
2391 }\r
2392 } else {\r
2393 switch (OpCode->VarStoreInfo.VarOffset) {\r
2394 case 0x00:\r
2395 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2396 Value->Value.u8 = EfiTime.Hour;\r
2397 break;\r
2398 case 0x01:\r
2399 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2400 Value->Value.u8 = EfiTime.Minute;\r
2401 break;\r
2402 case 0x02:\r
2403 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2404 Value->Value.u8 = EfiTime.Second;\r
2405 break;\r
2406 default:\r
2407 //\r
2408 // Invalid Time field.\r
2409 //\r
2410 Status = EFI_INVALID_PARAMETER;\r
2411 goto Done;\r
2412 }\r
2413 }\r
2414 }\r
2415 }\r
2416\r
2417 break;\r
2418\r
7936fb6a 2419 case EFI_IFR_QUESTION_REF3_OP:\r
db40504e
ED
2420 //\r
2421 // EFI_IFR_QUESTION_REF3\r
2422 // Pop an expression from the expression stack\r
2423 //\r
2424 Status = PopExpression (Value);\r
2425 if (EFI_ERROR (Status)) {\r
2426 goto Done;\r
2427 }\r
2428 \r
2429 //\r
2430 // Validate the expression value\r
2431 //\r
2432 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2433 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2434 break;\r
db40504e
ED
2435 }\r
2436\r
2437 if (OpCode->DevicePath != 0) {\r
80a047f0 2438 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
33efdf51 2439\r
80a047f0
ED
2440 StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
2441 if (StrPtr != NULL && mPathFromText != NULL) {\r
2442 DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);\r
2443 if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {\r
2444 Value = &QuestionVal;\r
2445 }\r
2446 if (DevicePath != NULL) {\r
2447 FreePool (DevicePath);\r
2448 }\r
33efdf51
ED
2449 }\r
2450\r
80a047f0
ED
2451 if (StrPtr != NULL) {\r
2452 FreePool (StrPtr);\r
7936fb6a 2453 }\r
db40504e
ED
2454 } else if (CompareGuid (&OpCode->Guid, &gZeroGuid) != 0) {\r
2455 if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
8f420676
ED
2456 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2457 break;\r
db40504e 2458 }\r
8f420676 2459 Value = &QuestionVal;\r
db40504e 2460 } else {\r
7936fb6a 2461 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2462 if (Question == NULL) {\r
8f420676
ED
2463 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2464 break;\r
7936fb6a 2465 }\r
2466\r
2467 //\r
2468 // push the questions' value on to the expression stack\r
2469 //\r
2470 Value = &Question->HiiValue;\r
7936fb6a 2471 }\r
2472 break;\r
2473\r
2474 case EFI_IFR_RULE_REF_OP:\r
2475 //\r
2476 // Find expression for this rule\r
2477 //\r
2478 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
2479 if (RuleExpression == NULL) {\r
8f420676
ED
2480 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2481 break;\r
7936fb6a 2482 }\r
2483\r
2484 //\r
2485 // Evaluate this rule expression\r
2486 //\r
2487 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
8f420676
ED
2488 if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {\r
2489 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2490 break;\r
7936fb6a 2491 }\r
2492\r
2493 Value = &RuleExpression->Result;\r
2494 break;\r
2495\r
2496 case EFI_IFR_STRING_REF1_OP:\r
2497 Value->Type = EFI_IFR_TYPE_STRING;\r
2498 Value->Value.string = OpCode->Value.Value.string;\r
2499 break;\r
2500\r
2501 //\r
2502 // Constant\r
2503 //\r
2504 case EFI_IFR_TRUE_OP:\r
2505 case EFI_IFR_FALSE_OP:\r
2506 case EFI_IFR_ONE_OP:\r
2507 case EFI_IFR_ONES_OP:\r
2508 case EFI_IFR_UINT8_OP:\r
2509 case EFI_IFR_UINT16_OP:\r
2510 case EFI_IFR_UINT32_OP:\r
2511 case EFI_IFR_UINT64_OP:\r
2512 case EFI_IFR_UNDEFINED_OP:\r
2513 case EFI_IFR_VERSION_OP:\r
2514 case EFI_IFR_ZERO_OP:\r
2515 Value = &OpCode->Value;\r
2516 break;\r
2517\r
2518 //\r
2519 // unary-op\r
2520 //\r
2521 case EFI_IFR_LENGTH_OP:\r
2522 Status = PopExpression (Value);\r
2523 if (EFI_ERROR (Status)) {\r
2573712e 2524 goto Done;\r
7936fb6a 2525 }\r
901ba0e7 2526 if (Value->Type != EFI_IFR_TYPE_STRING && Value->Type != EFI_IFR_TYPE_BUFFER) {\r
8f420676
ED
2527 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2528 break;\r
7936fb6a 2529 }\r
2530\r
901ba0e7
ED
2531 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2532 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2533 if (StrPtr == NULL) {\r
2534 Status = EFI_INVALID_PARAMETER;\r
2535 goto Done;\r
2536 }\r
7936fb6a 2537\r
901ba0e7
ED
2538 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2539 Value->Value.u64 = StrLen (StrPtr);\r
2540 FreePool (StrPtr);\r
2541 } else {\r
2542 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2543 Value->Value.u64 = Value->BufferLen;\r
2544 FreePool (Value->Buffer);\r
2545 }\r
7936fb6a 2546 break;\r
2547\r
2548 case EFI_IFR_NOT_OP:\r
2549 Status = PopExpression (Value);\r
2550 if (EFI_ERROR (Status)) {\r
2573712e 2551 goto Done;\r
7936fb6a 2552 }\r
2553 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
2554 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2555 break;\r
7936fb6a 2556 }\r
2557 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2558 break;\r
2559\r
2560 case EFI_IFR_QUESTION_REF2_OP:\r
2561 //\r
2562 // Pop an expression from the expression stack\r
2563 //\r
2564 Status = PopExpression (Value);\r
2565 if (EFI_ERROR (Status)) {\r
2573712e 2566 goto Done;\r
7936fb6a 2567 }\r
2568\r
2569 //\r
2570 // Validate the expression value\r
2571 //\r
2572 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2573 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2574 break;\r
7936fb6a 2575 }\r
2576\r
2577 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2578 if (Question == NULL) {\r
8f420676
ED
2579 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2580 break;\r
7936fb6a 2581 }\r
2582\r
2583 Value = &Question->HiiValue;\r
2584 break;\r
2585\r
2586 case EFI_IFR_STRING_REF2_OP:\r
2587 //\r
2588 // Pop an expression from the expression stack\r
2589 //\r
2590 Status = PopExpression (Value);\r
2591 if (EFI_ERROR (Status)) {\r
2573712e 2592 goto Done;\r
7936fb6a 2593 }\r
2594\r
2595 //\r
2596 // Validate the expression value\r
2597 //\r
2598 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2599 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2600 break;\r
7936fb6a 2601 }\r
2602\r
2603 Value->Type = EFI_IFR_TYPE_STRING;\r
2604 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2605 if (StrPtr == NULL) {\r
2606 //\r
2607 // If String not exit, push an empty string\r
2608 //\r
2609 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2610 } else {\r
2611 Index = (UINT16) Value->Value.u64;\r
2612 Value->Value.string = Index;\r
f4113e1f 2613 FreePool (StrPtr);\r
7936fb6a 2614 }\r
2615 break;\r
2616\r
2617 case EFI_IFR_TO_BOOLEAN_OP:\r
2618 //\r
2619 // Pop an expression from the expression stack\r
2620 //\r
2621 Status = PopExpression (Value);\r
2622 if (EFI_ERROR (Status)) {\r
2573712e 2623 goto Done;\r
7936fb6a 2624 }\r
2625\r
2626 //\r
2627 // Convert an expression to a Boolean\r
2628 //\r
2629 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
2630 //\r
2631 // When converting from an unsigned integer, zero will be converted to\r
2632 // FALSE and any other value will be converted to TRUE.\r
2633 //\r
4140a663 2634 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);\r
7936fb6a 2635\r
2636 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2637 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2638 //\r
2639 // When converting from a string, if case-insensitive compare\r
2640 // with "true" is True, then push True. If a case-insensitive compare\r
39099cbd 2641 // with "false" is True, then push False. Otherwise, push Undefined. \r
7936fb6a 2642 //\r
2643 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2644 if (StrPtr == NULL) {\r
2573712e
LG
2645 Status = EFI_INVALID_PARAMETER;\r
2646 goto Done;\r
7936fb6a 2647 }\r
39099cbd
ED
2648 \r
2649 IfrStrToUpper (StrPtr);\r
2650 if (StrCmp (StrPtr, L"TRUE") == 0){\r
7936fb6a 2651 Value->Value.b = TRUE;\r
8f420676 2652 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 2653 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
7936fb6a 2654 Value->Value.b = FALSE;\r
8f420676 2655 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 2656 } else {\r
8f420676 2657 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
7936fb6a 2658 }\r
f4113e1f 2659 FreePool (StrPtr);\r
901ba0e7
ED
2660 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
2661 //\r
2662 // When converting from a buffer, if the buffer is all zeroes, \r
2663 // then push False. Otherwise push True. \r
2664 //\r
2665 for (Index =0; Index < Value->BufferLen; Index ++) {\r
2666 if (Value->Buffer[Index] != 0) { \r
2667 break;\r
2668 }\r
2669 }\r
2670\r
2671 if (Index >= Value->BufferLen) {\r
2672 Value->Value.b = FALSE;\r
2673 } else {\r
2674 Value->Value.b = TRUE;\r
2675 }\r
2676 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2677 FreePool (Value->Buffer);\r
7936fb6a 2678 }\r
2679 break;\r
2680\r
2681 case EFI_IFR_TO_STRING_OP:\r
2682 Status = IfrToString (FormSet, OpCode->Format, Value);\r
2683 break;\r
2684\r
2685 case EFI_IFR_TO_UINT_OP:\r
2686 Status = IfrToUint (FormSet, Value);\r
2687 break;\r
2688\r
2689 case EFI_IFR_TO_LOWER_OP:\r
2690 case EFI_IFR_TO_UPPER_OP:\r
2691 Status = InitializeUnicodeCollationProtocol ();\r
2692 if (EFI_ERROR (Status)) {\r
2573712e 2693 goto Done;\r
7936fb6a 2694 }\r
2695\r
2696 Status = PopExpression (Value);\r
2697 if (EFI_ERROR (Status)) {\r
2573712e 2698 goto Done;\r
7936fb6a 2699 }\r
2700\r
2701 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
8f420676
ED
2702 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2703 break;\r
7936fb6a 2704 }\r
2705\r
2706 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2707 if (StrPtr == NULL) {\r
2573712e
LG
2708 Status = EFI_NOT_FOUND;\r
2709 goto Done;\r
7936fb6a 2710 }\r
2711\r
2712 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
2713 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
2714 } else {\r
2715 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
2716 }\r
2717 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 2718 FreePool (StrPtr);\r
7936fb6a 2719 break;\r
2720\r
2721 case EFI_IFR_BITWISE_NOT_OP:\r
2722 //\r
2723 // Pop an expression from the expression stack\r
2724 //\r
2725 Status = PopExpression (Value);\r
2726 if (EFI_ERROR (Status)) {\r
2573712e 2727 goto Done;\r
7936fb6a 2728 }\r
2729 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
2730 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2731 break;\r
7936fb6a 2732 }\r
2733\r
2734 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2735 Value->Value.u64 = ~Value->Value.u64;\r
2736 break;\r
2737\r
2573712e
LG
2738 case EFI_IFR_SET_OP:\r
2739 //\r
2740 // Pop an expression from the expression stack\r
2741 //\r
2742 Status = PopExpression (Value);\r
2743 if (EFI_ERROR (Status)) {\r
2744 goto Done;\r
2745 }\r
2746 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
2747 Data1.Value.b = FALSE;\r
2748 //\r
2749 // Set value to var storage buffer\r
2750 //\r
2751 if (OpCode->VarStorage != NULL) {\r
2752 switch (OpCode->VarStorage->Type) {\r
2753 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2754 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2755 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
2756 Data1.Value.b = TRUE;\r
2757 break;\r
2758 case EFI_HII_VARSTORE_NAME_VALUE:\r
2759 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2760 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
2761 ASSERT (Value != NULL);\r
2762 //\r
2763 // Convert Buffer to Hex String\r
2764 //\r
2765 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
2766 StrPtr = NameValue;\r
2767 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
2768 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
2769 }\r
7c6c064c 2770 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
2573712e
LG
2771 FreePool (NameValue);\r
2772 if (!EFI_ERROR (Status)) {\r
2773 Data1.Value.b = TRUE;\r
2774 }\r
2775 }\r
2776 break;\r
2777 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2778 Status = gRT->SetVariable (\r
2779 OpCode->ValueName,\r
2780 &OpCode->VarStorage->Guid,\r
2781 OpCode->VarStorage->Attributes,\r
2782 OpCode->ValueWidth,\r
2783 &Value->Value\r
2784 );\r
2785 if (!EFI_ERROR (Status)) {\r
2786 Data1.Value.b = TRUE;\r
2787 }\r
2788 break;\r
2789 default:\r
2790 //\r
2791 // Not recognize storage.\r
2792 //\r
2793 Status = EFI_UNSUPPORTED;\r
2794 goto Done;\r
2795 break;\r
2796 }\r
2797 } else {\r
2798 //\r
2799 // For Time/Date Data\r
2800 //\r
2801 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2802 //\r
2803 // Only support Data/Time data when storage doesn't exist.\r
2804 //\r
2805 Status = EFI_UNSUPPORTED;\r
2806 goto Done;\r
2807 }\r
2808 Status = gRT->GetTime (&EfiTime, NULL);\r
2809 if (!EFI_ERROR (Status)) {\r
2810 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2811 switch (OpCode->VarStoreInfo.VarOffset) {\r
2812 case 0x00:\r
2813 EfiTime.Year = Value->Value.u16;\r
2814 break;\r
2815 case 0x02:\r
2816 EfiTime.Month = Value->Value.u8;\r
2817 break;\r
2818 case 0x03:\r
2819 EfiTime.Day = Value->Value.u8;\r
2820 break;\r
2821 default:\r
2822 //\r
2823 // Invalid Date field.\r
2824 //\r
2825 Status = EFI_INVALID_PARAMETER;\r
2826 goto Done;\r
2827 }\r
2828 } else {\r
2829 switch (OpCode->VarStoreInfo.VarOffset) {\r
2830 case 0x00:\r
2831 EfiTime.Hour = Value->Value.u8;\r
2832 break;\r
2833 case 0x01:\r
2834 EfiTime.Minute = Value->Value.u8;\r
2835 break;\r
2836 case 0x02:\r
2837 EfiTime.Second = Value->Value.u8;\r
2838 break;\r
2839 default:\r
2840 //\r
2841 // Invalid Time field.\r
2842 //\r
2843 Status = EFI_INVALID_PARAMETER;\r
2844 goto Done;\r
2845 }\r
2846 }\r
2847 Status = gRT->SetTime (&EfiTime);\r
2848 if (!EFI_ERROR (Status)) {\r
2849 Data1.Value.b = TRUE;\r
2850 }\r
2851 }\r
2852 }\r
2853 Value = &Data1;\r
2854 break;\r
2855\r
7936fb6a 2856 //\r
2857 // binary-op\r
2858 //\r
2859 case EFI_IFR_ADD_OP:\r
2860 case EFI_IFR_SUBTRACT_OP:\r
2861 case EFI_IFR_MULTIPLY_OP:\r
2862 case EFI_IFR_DIVIDE_OP:\r
2863 case EFI_IFR_MODULO_OP:\r
2864 case EFI_IFR_BITWISE_AND_OP:\r
2865 case EFI_IFR_BITWISE_OR_OP:\r
2866 case EFI_IFR_SHIFT_LEFT_OP:\r
2867 case EFI_IFR_SHIFT_RIGHT_OP:\r
2868 //\r
2869 // Pop an expression from the expression stack\r
2870 //\r
2871 Status = PopExpression (&Data2);\r
2872 if (EFI_ERROR (Status)) {\r
2573712e 2873 goto Done;\r
7936fb6a 2874 }\r
7936fb6a 2875\r
2876 //\r
2877 // Pop another expression from the expression stack\r
2878 //\r
2879 Status = PopExpression (&Data1);\r
2880 if (EFI_ERROR (Status)) {\r
2573712e 2881 goto Done;\r
7936fb6a 2882 }\r
8f420676
ED
2883\r
2884 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
2885 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2886 break;\r
2887 }\r
2888\r
2889\r
7936fb6a 2890 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
2891 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2892 break;\r
7936fb6a 2893 }\r
2894\r
2895 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2896\r
2897 switch (OpCode->Operand) {\r
2898 case EFI_IFR_ADD_OP:\r
2899 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
2900 break;\r
2901\r
2902 case EFI_IFR_SUBTRACT_OP:\r
2903 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
2904 break;\r
2905\r
2906 case EFI_IFR_MULTIPLY_OP:\r
2907 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2908 break;\r
2909\r
2910 case EFI_IFR_DIVIDE_OP:\r
2911 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2912 break;\r
2913\r
2914 case EFI_IFR_MODULO_OP:\r
2915 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
2916 Value->Value.u64 = TempValue;\r
2917 break;\r
2918\r
2919 case EFI_IFR_BITWISE_AND_OP:\r
2920 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
2921 break;\r
2922\r
2923 case EFI_IFR_BITWISE_OR_OP:\r
2924 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
2925 break;\r
2926\r
2927 case EFI_IFR_SHIFT_LEFT_OP:\r
2928 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2929 break;\r
2930\r
2931 case EFI_IFR_SHIFT_RIGHT_OP:\r
2932 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2933 break;\r
2934\r
2935 default:\r
2936 break;\r
2937 }\r
2938 break;\r
2939\r
2940 case EFI_IFR_AND_OP:\r
2941 case EFI_IFR_OR_OP:\r
2942 //\r
2943 // Two Boolean operator\r
2944 //\r
2945 Status = PopExpression (&Data2);\r
2946 if (EFI_ERROR (Status)) {\r
2573712e 2947 goto Done;\r
7936fb6a 2948 }\r
7936fb6a 2949\r
2950 //\r
2951 // Pop another expression from the expression stack\r
2952 //\r
2953 Status = PopExpression (&Data1);\r
2954 if (EFI_ERROR (Status)) {\r
2573712e 2955 goto Done;\r
7936fb6a 2956 }\r
8f420676
ED
2957\r
2958 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2959 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2960 break;\r
2961 }\r
2962\r
7936fb6a 2963 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
2964 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2965 break;\r
7936fb6a 2966 }\r
2967\r
2968 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
2969 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
2970 } else {\r
2971 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
2972 }\r
2973 break;\r
2974\r
2975 case EFI_IFR_EQUAL_OP:\r
2976 case EFI_IFR_NOT_EQUAL_OP:\r
2977 case EFI_IFR_GREATER_EQUAL_OP:\r
2978 case EFI_IFR_GREATER_THAN_OP:\r
2979 case EFI_IFR_LESS_EQUAL_OP:\r
2980 case EFI_IFR_LESS_THAN_OP:\r
2981 //\r
2982 // Compare two integer, string, boolean or date/time\r
2983 //\r
2984 Status = PopExpression (&Data2);\r
2985 if (EFI_ERROR (Status)) {\r
2573712e 2986 goto Done;\r
7936fb6a 2987 }\r
7936fb6a 2988\r
2989 //\r
2990 // Pop another expression from the expression stack\r
2991 //\r
2992 Status = PopExpression (&Data1);\r
2993 if (EFI_ERROR (Status)) {\r
2573712e 2994 goto Done;\r
7936fb6a 2995 }\r
2996\r
8f420676
ED
2997 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
2998 Data2.Type != EFI_IFR_TYPE_STRING && \r
2999 Data2.Type != EFI_IFR_TYPE_BUFFER) {\r
3000 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3001 break;\r
3002 }\r
3003\r
3004 if (Data1.Type > EFI_IFR_TYPE_BOOLEAN && \r
3005 Data1.Type != EFI_IFR_TYPE_STRING && \r
3006 Data1.Type != EFI_IFR_TYPE_BUFFER) {\r
3007 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3008 break;\r
3009 }\r
3010\r
3011 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
901ba0e7
ED
3012 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
3013 FreePool (Data1.Buffer);\r
3014 FreePool (Data2.Buffer);\r
3015 }\r
3016 \r
8f420676
ED
3017 if (Status == EFI_UNSUPPORTED) {\r
3018 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3019 Status = EFI_SUCCESS;\r
3020 break;\r
3021 }\r
3022\r
3023 if (EFI_ERROR (Status)) {\r
2573712e 3024 goto Done;\r
7936fb6a 3025 }\r
3026\r
3027 switch (OpCode->Operand) {\r
3028 case EFI_IFR_EQUAL_OP:\r
3029 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
3030 break;\r
3031\r
3032 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 3033 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 3034 break;\r
3035\r
3036 case EFI_IFR_GREATER_EQUAL_OP:\r
3037 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
3038 break;\r
3039\r
3040 case EFI_IFR_GREATER_THAN_OP:\r
3041 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
3042 break;\r
3043\r
3044 case EFI_IFR_LESS_EQUAL_OP:\r
3045 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
3046 break;\r
3047\r
3048 case EFI_IFR_LESS_THAN_OP:\r
3049 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
3050 break;\r
3051\r
3052 default:\r
3053 break;\r
3054 }\r
3055 break;\r
3056\r
3057 case EFI_IFR_MATCH_OP:\r
20258293
ED
3058 Status = InitializeUnicodeCollationProtocol ();\r
3059 if (EFI_ERROR (Status)) {\r
3060 goto Done;\r
3061 }\r
3062 \r
7936fb6a 3063 Status = IfrMatch (FormSet, Value);\r
3064 break;\r
3065\r
3066 case EFI_IFR_CATENATE_OP:\r
3067 Status = IfrCatenate (FormSet, Value);\r
3068 break;\r
3069\r
3070 //\r
3071 // ternary-op\r
3072 //\r
3073 case EFI_IFR_CONDITIONAL_OP:\r
3074 //\r
3075 // Pop third expression from the expression stack\r
3076 //\r
3077 Status = PopExpression (&Data3);\r
3078 if (EFI_ERROR (Status)) {\r
2573712e 3079 goto Done;\r
7936fb6a 3080 }\r
3081\r
3082 //\r
3083 // Pop second expression from the expression stack\r
3084 //\r
3085 Status = PopExpression (&Data2);\r
3086 if (EFI_ERROR (Status)) {\r
2573712e 3087 goto Done;\r
7936fb6a 3088 }\r
3089\r
3090 //\r
3091 // Pop first expression from the expression stack\r
3092 //\r
3093 Status = PopExpression (&Data1);\r
3094 if (EFI_ERROR (Status)) {\r
2573712e 3095 goto Done;\r
7936fb6a 3096 }\r
3097 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3098 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3099 break;\r
7936fb6a 3100 }\r
3101\r
3102 if (Data1.Value.b) {\r
3103 Value = &Data3;\r
3104 } else {\r
3105 Value = &Data2;\r
3106 }\r
3107 break;\r
3108\r
3109 case EFI_IFR_FIND_OP:\r
3110 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3111 break;\r
3112\r
3113 case EFI_IFR_MID_OP:\r
3114 Status = IfrMid (FormSet, Value);\r
3115 break;\r
3116\r
3117 case EFI_IFR_TOKEN_OP:\r
3118 Status = IfrToken (FormSet, Value);\r
3119 break;\r
3120\r
3121 case EFI_IFR_SPAN_OP:\r
3122 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3123 break;\r
3124\r
2573712e
LG
3125 case EFI_IFR_MAP_OP:\r
3126 //\r
3127 // Pop the check value\r
3128 //\r
3129 Status = PopExpression (&Data1);\r
3130 if (EFI_ERROR (Status)) {\r
3131 goto Done;\r
3132 }\r
3133 //\r
3134 // Check MapExpression list is valid.\r
3135 //\r
3136 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
3137 Status = EFI_INVALID_PARAMETER;\r
3138 goto Done;\r
3139 }\r
3140 //\r
3141 // Go through map expression list.\r
3142 //\r
3143 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
3144 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3145 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3146 //\r
3147 // Evaluate the first expression in this pair.\r
3148 //\r
3149 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3150 if (EFI_ERROR (Status)) {\r
3151 goto Done;\r
3152 }\r
3153 //\r
3154 // Compare the expression value with current value\r
3155 //\r
8f420676 3156 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
2573712e
LG
3157 //\r
3158 // Try get the map value.\r
3159 //\r
3160 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3161 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3162 Status = EFI_INVALID_PARAMETER;\r
3163 goto Done;\r
3164 }\r
3165 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3166 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3167 if (EFI_ERROR (Status)) {\r
3168 goto Done;\r
3169 }\r
3170 Value = &SubExpression->Result;\r
3171 break;\r
3172 }\r
3173 //\r
3174 // Skip the second expression on this pair.\r
3175 //\r
3176 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3177 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3178 Status = EFI_INVALID_PARAMETER;\r
3179 goto Done;\r
3180 }\r
3181 //\r
3182 // Goto the first expression on next pair.\r
3183 //\r
3184 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3185 }\r
3186\r
3187 //\r
3188 // No map value is found.\r
3189 //\r
3190 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3191 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3192 Value->Value.u8 = 0;\r
3193 }\r
3194 break;\r
3195\r
7936fb6a 3196 default:\r
3197 break;\r
3198 }\r
8f420676 3199 if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
2573712e 3200 goto Done;\r
7936fb6a 3201 }\r
3202\r
3203 Status = PushExpression (Value);\r
3204 if (EFI_ERROR (Status)) {\r
2573712e 3205 goto Done;\r
7936fb6a 3206 }\r
3207 }\r
3208\r
3209 //\r
3210 // Pop the final result from expression stack\r
3211 //\r
3212 Value = &Data1;\r
3213 Status = PopExpression (Value);\r
3214 if (EFI_ERROR (Status)) {\r
2573712e 3215 goto Done;\r
7936fb6a 3216 }\r
3217\r
3218 //\r
3219 // After evaluating an expression, there should be only one value left on the expression stack\r
3220 //\r
3221 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 3222 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 3223 }\r
3224\r
2573712e
LG
3225Done:\r
3226 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3227 if (!EFI_ERROR (Status)) {\r
3228 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3229 }\r
7936fb6a 3230\r
2573712e 3231 return Status;\r
7936fb6a 3232}\r
31585af4
ED
3233\r
3234/**\r
3235 Return the result of the expression list. Check the expression list and \r
3236 return the highest priority express result. \r
3237 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
3238\r
3239 @param ExpList The input expression list.\r
3240 @param Evaluate Whether need to evaluate the expression first.\r
3241 @param FormSet FormSet associated with this expression.\r
3242 @param Form Form associated with this expression. \r
3243\r
3244 @retval EXPRESS_RESULT Return the higher priority express result. \r
3245 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3246\r
3247**/\r
3248EXPRESS_RESULT \r
3249EvaluateExpressionList (\r
3250 IN FORM_EXPRESSION_LIST *ExpList,\r
3251 IN BOOLEAN Evaluate,\r
3252 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
3253 IN FORM_BROWSER_FORM *Form OPTIONAL\r
3254 )\r
3255{\r
3256 UINTN Index;\r
3257 EXPRESS_RESULT ReturnVal;\r
3258 EXPRESS_RESULT CompareOne;\r
3259 EFI_STATUS Status;\r
3260\r
3261 if (ExpList == NULL) {\r
3262 return ExpressFalse;\r
3263 }\r
3264\r
3265 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3266 Index = 0;\r
3267\r
3268 //\r
3269 // Check whether need to evaluate the expression first.\r
3270 //\r
3271 if (Evaluate) { \r
3272 while (ExpList->Count > Index) {\r
3273 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
3274 if (EFI_ERROR (Status)) {\r
3275 return ExpressFalse;\r
3276 }\r
3277 }\r
3278 }\r
3279\r
3280 //\r
3281 // Run the list of expressions.\r
3282 //\r
3283 ReturnVal = ExpressFalse;\r
3284 for (Index = 0; Index < ExpList->Count; Index++) {\r
3285 if (ExpList->Expression[Index]->Result.Type == EFI_IFR_TYPE_BOOLEAN &&\r
3286 ExpList->Expression[Index]->Result.Value.b) {\r
3287 switch (ExpList->Expression[Index]->Type) {\r
3288 case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
3289 CompareOne = ExpressSuppress;\r
3290 break;\r
3291\r
3292 case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
3293 CompareOne = ExpressGrayOut;\r
3294 break;\r
3295\r
3296 case EFI_HII_EXPRESSION_DISABLE_IF:\r
3297 CompareOne = ExpressDisable;\r
3298 break;\r
3299\r
3300 default:\r
3301 return ExpressFalse; \r
3302 }\r
3303\r
3304 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3305 }\r
3306 }\r
3307 \r
3308 return ReturnVal;\r
3309}\r