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