]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Fix several bugs in DevicePathLib implementation regarding the device path node and...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
80a047f0 4Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
7936fb6a 15#include "Setup.h"\r
16\r
17//\r
18// Global stack used to evaluate boolean expresions\r
19//\r
20EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
21EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
22EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
23\r
24EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
25EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
26EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
2573712e
LG
27UINTN mExpressionEvaluationStackOffset = 0;\r
28\r
29EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
30EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
31EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
32\r
33EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
34EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
35EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
7936fb6a 36\r
31585af4
ED
37FORM_EXPRESSION **mFormExpressionStack = NULL;\r
38FORM_EXPRESSION **mFormExpressionEnd = NULL;\r
39FORM_EXPRESSION **mFormExpressionPointer = NULL;\r
40\r
41FORM_EXPRESSION **mStatementExpressionStack = NULL;\r
42FORM_EXPRESSION **mStatementExpressionEnd = NULL;\r
43FORM_EXPRESSION **mStatementExpressionPointer = NULL;\r
44\r
45FORM_EXPRESSION **mOptionExpressionStack = NULL;\r
46FORM_EXPRESSION **mOptionExpressionEnd = NULL;\r
47FORM_EXPRESSION **mOptionExpressionPointer = NULL;\r
48\r
49\r
7936fb6a 50//\r
51// Unicode collation protocol interface\r
52//\r
53EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
cbf73e50 54EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
7936fb6a 55\r
56/**\r
57 Grow size of the stack.\r
58\r
59 This is an internal function.\r
60\r
61 @param Stack On input: old stack; On output: new stack\r
62 @param StackPtr On input: old stack pointer; On output: new stack\r
63 pointer\r
64 @param StackEnd On input: old stack end; On output: new stack end\r
65\r
66 @retval EFI_SUCCESS Grow stack success.\r
67 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
68\r
69**/\r
70EFI_STATUS\r
71GrowStack (\r
72 IN OUT EFI_HII_VALUE **Stack,\r
73 IN OUT EFI_HII_VALUE **StackPtr,\r
74 IN OUT EFI_HII_VALUE **StackEnd\r
75 )\r
76{\r
77 UINTN Size;\r
78 EFI_HII_VALUE *NewStack;\r
79\r
80 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
81 if (*StackPtr != NULL) {\r
82 Size = Size + (*StackEnd - *Stack);\r
83 }\r
84\r
85 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
86 if (NewStack == NULL) {\r
87 return EFI_OUT_OF_RESOURCES;\r
88 }\r
89\r
90 if (*StackPtr != NULL) {\r
91 //\r
92 // Copy from Old Stack to the New Stack\r
93 //\r
94 CopyMem (\r
95 NewStack,\r
96 *Stack,\r
97 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
98 );\r
99\r
100 //\r
101 // Free The Old Stack\r
102 //\r
f4113e1f 103 FreePool (*Stack);\r
7936fb6a 104 }\r
105\r
106 //\r
107 // Make the Stack pointer point to the old data in the new stack\r
108 //\r
109 *StackPtr = NewStack + (*StackPtr - *Stack);\r
110 *Stack = NewStack;\r
111 *StackEnd = NewStack + Size;\r
112\r
113 return EFI_SUCCESS;\r
114}\r
115\r
116\r
117/**\r
118 Push an element onto the Boolean Stack.\r
119\r
120 @param Stack On input: old stack; On output: new stack\r
121 @param StackPtr On input: old stack pointer; On output: new stack\r
122 pointer\r
123 @param StackEnd On input: old stack end; On output: new stack end\r
124 @param Data Data to push.\r
125\r
126 @retval EFI_SUCCESS Push stack success.\r
127\r
128**/\r
129EFI_STATUS\r
130PushStack (\r
131 IN OUT EFI_HII_VALUE **Stack,\r
132 IN OUT EFI_HII_VALUE **StackPtr,\r
133 IN OUT EFI_HII_VALUE **StackEnd,\r
134 IN EFI_HII_VALUE *Data\r
135 )\r
136{\r
137 EFI_STATUS Status;\r
138\r
139 //\r
140 // Check for a stack overflow condition\r
141 //\r
142 if (*StackPtr >= *StackEnd) {\r
143 //\r
144 // Grow the stack\r
145 //\r
146 Status = GrowStack (Stack, StackPtr, StackEnd);\r
147 if (EFI_ERROR (Status)) {\r
148 return Status;\r
149 }\r
150 }\r
151\r
152 //\r
153 // Push the item onto the stack\r
154 //\r
155 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
901ba0e7
ED
156 if (Data->Type == EFI_IFR_TYPE_BUFFER) {\r
157 (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer);\r
158 ASSERT ((*StackPtr)->Buffer != NULL);\r
159 }\r
160 \r
7936fb6a 161 *StackPtr = *StackPtr + 1;\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166\r
167/**\r
168 Pop an element from the stack.\r
169\r
2573712e
LG
170 @param Stack On input: old stack\r
171 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
7936fb6a 172 @param Data Data to pop.\r
173\r
174 @retval EFI_SUCCESS The value was popped onto the stack.\r
175 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
176\r
177**/\r
178EFI_STATUS\r
179PopStack (\r
2573712e 180 IN EFI_HII_VALUE *Stack,\r
7936fb6a 181 IN OUT EFI_HII_VALUE **StackPtr,\r
7936fb6a 182 OUT EFI_HII_VALUE *Data\r
183 )\r
184{\r
185 //\r
186 // Check for a stack underflow condition\r
187 //\r
2573712e 188 if (*StackPtr == Stack) {\r
7936fb6a 189 return EFI_ACCESS_DENIED;\r
190 }\r
191\r
192 //\r
193 // Pop the item off the stack\r
194 //\r
195 *StackPtr = *StackPtr - 1;\r
196 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
197 return EFI_SUCCESS;\r
198}\r
199\r
200\r
2573712e
LG
201/**\r
202 Reset stack pointer to begin of the stack.\r
203\r
204**/\r
205VOID\r
206ResetCurrentExpressionStack (\r
207 VOID\r
208 )\r
209{\r
31585af4
ED
210 mCurrentExpressionPointer = mCurrentExpressionStack;\r
211 mFormExpressionPointer = mFormExpressionStack;\r
212 mStatementExpressionPointer = mStatementExpressionStack;\r
213 mOptionExpressionPointer = mOptionExpressionStack; \r
2573712e
LG
214}\r
215\r
216\r
217/**\r
218 Push current expression onto the Stack\r
219\r
220 @param Pointer Pointer to current expression.\r
221\r
222 @retval EFI_SUCCESS The value was pushed onto the stack.\r
223 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
224\r
225**/\r
226EFI_STATUS\r
227PushCurrentExpression (\r
228 IN VOID *Pointer\r
229 )\r
230{\r
231 EFI_HII_VALUE Data;\r
232\r
233 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
234 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
235\r
236 return PushStack (\r
237 &mCurrentExpressionStack,\r
238 &mCurrentExpressionPointer,\r
239 &mCurrentExpressionEnd,\r
240 &Data\r
241 );\r
242}\r
243\r
244\r
245/**\r
246 Pop current expression from the Stack\r
247\r
248 @param Pointer Pointer to current expression to be pop.\r
249\r
250 @retval EFI_SUCCESS The value was pushed onto the stack.\r
251 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
252\r
253**/\r
254EFI_STATUS\r
255PopCurrentExpression (\r
256 OUT VOID **Pointer\r
257 )\r
258{\r
259 EFI_STATUS Status;\r
260 EFI_HII_VALUE Data;\r
261\r
262 Status = PopStack (\r
263 mCurrentExpressionStack,\r
264 &mCurrentExpressionPointer,\r
265 &Data\r
266 );\r
267\r
268 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
269\r
270 return Status;\r
271}\r
272\r
273/**\r
274 Reset stack pointer to begin of the stack.\r
275\r
276**/\r
277VOID\r
278ResetMapExpressionListStack (\r
279 VOID\r
280 )\r
281{\r
282 mMapExpressionListPointer = mMapExpressionListStack;\r
283}\r
284\r
285\r
31585af4
ED
286/**\r
287 Grow size of the stack.\r
288\r
289 This is an internal function.\r
290\r
291 @param Stack On input: old stack; On output: new stack\r
292 @param StackPtr On input: old stack pointer; On output: new stack\r
293 pointer\r
294 @param StackEnd On input: old stack end; On output: new stack end\r
295 @param MemberSize The stack member size.\r
296 \r
297 @retval EFI_SUCCESS Grow stack success.\r
298 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
299\r
300**/\r
301EFI_STATUS\r
302GrowConditionalStack (\r
303 IN OUT FORM_EXPRESSION ***Stack,\r
304 IN OUT FORM_EXPRESSION ***StackPtr,\r
305 IN OUT FORM_EXPRESSION ***StackEnd,\r
306 IN UINTN MemberSize\r
307 )\r
308{\r
309 UINTN Size;\r
310 FORM_EXPRESSION **NewStack;\r
311\r
312 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
313 if (*StackPtr != NULL) {\r
314 Size = Size + (*StackEnd - *Stack);\r
315 }\r
316\r
317 NewStack = AllocatePool (Size * MemberSize);\r
318 if (NewStack == NULL) {\r
319 return EFI_OUT_OF_RESOURCES;\r
320 }\r
321\r
322 if (*StackPtr != NULL) {\r
323 //\r
324 // Copy from Old Stack to the New Stack\r
325 //\r
326 CopyMem (\r
327 NewStack,\r
328 *Stack,\r
329 (*StackEnd - *Stack) * MemberSize\r
330 );\r
331\r
332 //\r
333 // Free The Old Stack\r
334 //\r
335 FreePool (*Stack);\r
336 }\r
337\r
338 //\r
339 // Make the Stack pointer point to the old data in the new stack\r
340 //\r
341 *StackPtr = NewStack + (*StackPtr - *Stack);\r
342 *Stack = NewStack;\r
343 *StackEnd = NewStack + Size;\r
344\r
345 return EFI_SUCCESS;\r
346}\r
347\r
348/**\r
349 Push an element onto the Stack.\r
350\r
351 @param Stack On input: old stack; On output: new stack\r
352 @param StackPtr On input: old stack pointer; On output: new stack\r
353 pointer\r
354 @param StackEnd On input: old stack end; On output: new stack end\r
355 @param Data Data to push.\r
356\r
357 @retval EFI_SUCCESS Push stack success.\r
358\r
359**/\r
360EFI_STATUS\r
361PushConditionalStack (\r
362 IN OUT FORM_EXPRESSION ***Stack,\r
363 IN OUT FORM_EXPRESSION ***StackPtr,\r
364 IN OUT FORM_EXPRESSION ***StackEnd,\r
365 IN FORM_EXPRESSION **Data\r
366 )\r
367{\r
368 EFI_STATUS Status;\r
369\r
370 //\r
371 // Check for a stack overflow condition\r
372 //\r
373 if (*StackPtr >= *StackEnd) {\r
374 //\r
375 // Grow the stack\r
376 //\r
377 Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));\r
378 if (EFI_ERROR (Status)) {\r
379 return Status;\r
380 }\r
381 }\r
382\r
383 //\r
384 // Push the item onto the stack\r
385 //\r
386 CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *)); \r
387 *StackPtr = *StackPtr + 1;\r
388\r
389 return EFI_SUCCESS;\r
390\r
391}\r
392\r
393/**\r
394 Pop an element from the stack.\r
395\r
396 @param Stack On input: old stack\r
397 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
398 @param Data Data to pop.\r
399\r
400 @retval EFI_SUCCESS The value was popped onto the stack.\r
401 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
402\r
403**/\r
404EFI_STATUS\r
405PopConditionalStack (\r
406 IN FORM_EXPRESSION **Stack,\r
407 IN OUT FORM_EXPRESSION ***StackPtr,\r
408 OUT FORM_EXPRESSION **Data\r
409 )\r
410{\r
411 //\r
412 // Check for a stack underflow condition\r
413 //\r
414 if (*StackPtr == Stack) {\r
415 return EFI_ACCESS_DENIED;\r
416 }\r
417\r
418 //\r
419 // Pop the item off the stack\r
420 //\r
421 *StackPtr = *StackPtr - 1;\r
422 CopyMem (Data, *StackPtr, sizeof (FORM_EXPRESSION *));\r
423 return EFI_SUCCESS;\r
424\r
425}\r
426\r
427/**\r
428 Get the expression list count.\r
429 \r
430 @param Level Which type this expression belong to. Form, \r
431 statement or option?\r
432\r
433 @retval >=0 The expression count\r
434 @retval -1 Input parameter error.\r
435\r
436**/\r
437INTN \r
438GetConditionalExpressionCount (\r
439 IN EXPRESS_LEVEL Level\r
440 )\r
441{\r
442 switch (Level) {\r
443 case ExpressForm:\r
444 return mFormExpressionPointer - mFormExpressionStack;\r
445 case ExpressStatement:\r
446 return mStatementExpressionPointer - mStatementExpressionStack;\r
447 case ExpressOption:\r
448 return mOptionExpressionPointer - mOptionExpressionStack;\r
449 default:\r
450 ASSERT (FALSE);\r
451 return -1;\r
452 } \r
453}\r
454\r
455/**\r
456 Get the expression Buffer pointer.\r
457 \r
458 @param Level Which type this expression belong to. Form, \r
459 statement or option?\r
460\r
461 @retval The start pointer of the expression buffer or NULL.\r
462\r
463**/\r
464FORM_EXPRESSION **\r
465GetConditionalExpressionList (\r
466 IN EXPRESS_LEVEL Level\r
467 )\r
468{\r
469 switch (Level) {\r
470 case ExpressForm:\r
471 return mFormExpressionStack;\r
472 case ExpressStatement:\r
473 return mStatementExpressionStack;\r
474 case ExpressOption:\r
475 return mOptionExpressionStack;\r
476 default:\r
477 ASSERT (FALSE);\r
478 return NULL;\r
479 } \r
480}\r
481\r
482\r
483/**\r
484 Push the expression options onto the Stack.\r
485\r
486 @param Pointer Pointer to the current expression.\r
487 @param Level Which type this expression belong to. Form, \r
488 statement or option?\r
489\r
490 @retval EFI_SUCCESS The value was pushed onto the stack.\r
491 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
492\r
493**/\r
494EFI_STATUS\r
495PushConditionalExpression (\r
496 IN FORM_EXPRESSION *Pointer,\r
497 IN EXPRESS_LEVEL Level\r
498 )\r
499{\r
500 switch (Level) {\r
501 case ExpressForm:\r
502 return PushConditionalStack (\r
503 &mFormExpressionStack,\r
504 &mFormExpressionPointer,\r
505 &mFormExpressionEnd,\r
506 &Pointer\r
507 );\r
508 case ExpressStatement:\r
509 return PushConditionalStack (\r
510 &mStatementExpressionStack,\r
511 &mStatementExpressionPointer,\r
512 &mStatementExpressionEnd,\r
513 &Pointer\r
514 );\r
515 case ExpressOption:\r
516 return PushConditionalStack (\r
517 &mOptionExpressionStack,\r
518 &mOptionExpressionPointer,\r
519 &mOptionExpressionEnd,\r
520 &Pointer\r
521 );\r
522 default:\r
523 ASSERT (FALSE);\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
526}\r
527\r
528/**\r
529 Pop the expression options from the Stack\r
530\r
531 @param Level Which type this expression belong to. Form, \r
532 statement or option?\r
533\r
534 @retval EFI_SUCCESS The value was pushed onto the stack.\r
535 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
536\r
537**/\r
538EFI_STATUS\r
539PopConditionalExpression (\r
540 IN EXPRESS_LEVEL Level\r
541 )\r
542{\r
543 FORM_EXPRESSION *Pointer;\r
544\r
545 switch (Level) {\r
546 case ExpressForm:\r
547 return PopConditionalStack (\r
548 mFormExpressionStack,\r
549 &mFormExpressionPointer,\r
550 &Pointer\r
551 );\r
552\r
553 case ExpressStatement:\r
554 return PopConditionalStack (\r
555 mStatementExpressionStack,\r
556 &mStatementExpressionPointer,\r
557 &Pointer\r
558 );\r
559\r
560 case ExpressOption:\r
561 return PopConditionalStack (\r
562 mOptionExpressionStack,\r
563 &mOptionExpressionPointer,\r
564 &Pointer\r
565 );\r
566\r
567 default:\r
568 ASSERT (FALSE);\r
569 return EFI_INVALID_PARAMETER;\r
570 }\r
571}\r
572\r
573\r
2573712e
LG
574/**\r
575 Push the list of map expression onto the Stack\r
576\r
577 @param Pointer Pointer to the list of map expression to be pushed.\r
578\r
579 @retval EFI_SUCCESS The value was pushed onto the stack.\r
580 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
581\r
582**/\r
583EFI_STATUS\r
584PushMapExpressionList (\r
585 IN VOID *Pointer\r
586 )\r
587{\r
588 EFI_HII_VALUE Data;\r
589\r
590 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
591 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
592\r
593 return PushStack (\r
594 &mMapExpressionListStack,\r
595 &mMapExpressionListPointer,\r
596 &mMapExpressionListEnd,\r
597 &Data\r
598 );\r
599}\r
600\r
601\r
602/**\r
603 Pop the list of map expression from the Stack\r
604\r
605 @param Pointer Pointer to the list of map expression to be pop.\r
606\r
607 @retval EFI_SUCCESS The value was pushed onto the stack.\r
608 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
609\r
610**/\r
611EFI_STATUS\r
612PopMapExpressionList (\r
613 OUT VOID **Pointer\r
614 )\r
615{\r
616 EFI_STATUS Status;\r
617 EFI_HII_VALUE Data;\r
618\r
619 Status = PopStack (\r
620 mMapExpressionListStack,\r
621 &mMapExpressionListPointer,\r
622 &Data\r
623 );\r
624\r
625 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
626\r
627 return Status;\r
628}\r
629\r
7936fb6a 630/**\r
631 Reset stack pointer to begin of the stack.\r
632\r
633**/\r
634VOID\r
635ResetScopeStack (\r
636 VOID\r
637 )\r
638{\r
639 mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
640}\r
641\r
642\r
643/**\r
644 Push an Operand onto the Stack\r
645\r
646 @param Operand Operand to push.\r
647\r
648 @retval EFI_SUCCESS The value was pushed onto the stack.\r
649 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
650 stack.\r
651\r
652**/\r
653EFI_STATUS\r
654PushScope (\r
655 IN UINT8 Operand\r
656 )\r
657{\r
658 EFI_HII_VALUE Data;\r
659\r
660 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
661 Data.Value.u8 = Operand;\r
662\r
663 return PushStack (\r
664 &mOpCodeScopeStack,\r
665 &mOpCodeScopeStackPointer,\r
666 &mOpCodeScopeStackEnd,\r
667 &Data\r
668 );\r
669}\r
670\r
671\r
672/**\r
673 Pop an Operand from the Stack\r
674\r
675 @param Operand Operand to pop.\r
676\r
677 @retval EFI_SUCCESS The value was pushed onto the stack.\r
678 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
679 stack.\r
680\r
681**/\r
682EFI_STATUS\r
683PopScope (\r
684 OUT UINT8 *Operand\r
685 )\r
686{\r
687 EFI_STATUS Status;\r
688 EFI_HII_VALUE Data;\r
689\r
690 Status = PopStack (\r
2573712e 691 mOpCodeScopeStack,\r
7936fb6a 692 &mOpCodeScopeStackPointer,\r
7936fb6a 693 &Data\r
694 );\r
695\r
696 *Operand = Data.Value.u8;\r
697\r
698 return Status;\r
699}\r
700\r
701\r
7936fb6a 702/**\r
703 Push an Expression value onto the Stack\r
704\r
705 @param Value Expression value to push.\r
706\r
707 @retval EFI_SUCCESS The value was pushed onto the stack.\r
708 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
709 stack.\r
710\r
711**/\r
712EFI_STATUS\r
713PushExpression (\r
714 IN EFI_HII_VALUE *Value\r
715 )\r
716{\r
717 return PushStack (\r
718 &mExpressionEvaluationStack,\r
719 &mExpressionEvaluationStackPointer,\r
720 &mExpressionEvaluationStackEnd,\r
721 Value\r
722 );\r
723}\r
724\r
725\r
726/**\r
727 Pop an Expression value from the stack.\r
728\r
729 @param Value Expression value to pop.\r
730\r
731 @retval EFI_SUCCESS The value was popped onto the stack.\r
732 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
733\r
734**/\r
735EFI_STATUS\r
736PopExpression (\r
737 OUT EFI_HII_VALUE *Value\r
738 )\r
739{\r
740 return PopStack (\r
2573712e 741 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
7936fb6a 742 &mExpressionEvaluationStackPointer,\r
7936fb6a 743 Value\r
744 );\r
745}\r
746\r
2573712e
LG
747/**\r
748 Get current stack offset from stack start.\r
749\r
750 @return Stack offset to stack start.\r
751**/\r
752UINTN\r
753SaveExpressionEvaluationStackOffset (\r
754 )\r
755{\r
756 UINTN TempStackOffset;\r
757 TempStackOffset = mExpressionEvaluationStackOffset;\r
758 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
759 return TempStackOffset;\r
760}\r
761\r
762/**\r
763 Restore stack offset based on input stack offset\r
764\r
765 @param StackOffset Offset to stack start.\r
766\r
767**/\r
768VOID\r
769RestoreExpressionEvaluationStackOffset (\r
770 UINTN StackOffset\r
771 )\r
772{\r
773 mExpressionEvaluationStackOffset = StackOffset;\r
774}\r
7936fb6a 775\r
776/**\r
777 Get Form given its FormId.\r
778\r
779 @param FormSet The formset which contains this form.\r
780 @param FormId Id of this form.\r
781\r
782 @retval Pointer The form.\r
783 @retval NULL Specified Form is not found in the formset.\r
784\r
785**/\r
786FORM_BROWSER_FORM *\r
787IdToForm (\r
788 IN FORM_BROWSER_FORMSET *FormSet,\r
789 IN UINT16 FormId\r
7c6c064c 790 )\r
7936fb6a 791{\r
792 LIST_ENTRY *Link;\r
793 FORM_BROWSER_FORM *Form;\r
794\r
795 Link = GetFirstNode (&FormSet->FormListHead);\r
796 while (!IsNull (&FormSet->FormListHead, Link)) {\r
797 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
798\r
799 if (Form->FormId == FormId) {\r
800 return Form;\r
801 }\r
802\r
803 Link = GetNextNode (&FormSet->FormListHead, Link);\r
804 }\r
805\r
806 return NULL;\r
807}\r
808\r
809\r
810/**\r
811 Search a Question in Form scope using its QuestionId.\r
812\r
813 @param Form The form which contains this Question.\r
814 @param QuestionId Id of this Question.\r
815\r
816 @retval Pointer The Question.\r
817 @retval NULL Specified Question not found in the form.\r
818\r
819**/\r
820FORM_BROWSER_STATEMENT *\r
821IdToQuestion2 (\r
822 IN FORM_BROWSER_FORM *Form,\r
823 IN UINT16 QuestionId\r
824 )\r
825{\r
826 LIST_ENTRY *Link;\r
827 FORM_BROWSER_STATEMENT *Question;\r
828\r
db40504e 829 if (QuestionId == 0 || Form == NULL) {\r
7936fb6a 830 //\r
831 // The value of zero is reserved\r
832 //\r
833 return NULL;\r
834 }\r
835\r
836 Link = GetFirstNode (&Form->StatementListHead);\r
837 while (!IsNull (&Form->StatementListHead, Link)) {\r
838 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
839\r
840 if (Question->QuestionId == QuestionId) {\r
841 return Question;\r
842 }\r
843\r
844 Link = GetNextNode (&Form->StatementListHead, Link);\r
845 }\r
846\r
847 return NULL;\r
848}\r
849\r
850\r
851/**\r
852 Search a Question in Formset scope using its QuestionId.\r
853\r
854 @param FormSet The formset which contains this form.\r
855 @param Form The form which contains this Question.\r
856 @param QuestionId Id of this Question.\r
857\r
858 @retval Pointer The Question.\r
859 @retval NULL Specified Question not found in the form.\r
860\r
861**/\r
862FORM_BROWSER_STATEMENT *\r
863IdToQuestion (\r
864 IN FORM_BROWSER_FORMSET *FormSet,\r
865 IN FORM_BROWSER_FORM *Form,\r
866 IN UINT16 QuestionId\r
867 )\r
868{\r
869 LIST_ENTRY *Link;\r
870 FORM_BROWSER_STATEMENT *Question;\r
871\r
872 //\r
873 // Search in the form scope first\r
874 //\r
875 Question = IdToQuestion2 (Form, QuestionId);\r
876 if (Question != NULL) {\r
877 return Question;\r
878 }\r
879\r
880 //\r
881 // Search in the formset scope\r
882 //\r
883 Link = GetFirstNode (&FormSet->FormListHead);\r
884 while (!IsNull (&FormSet->FormListHead, Link)) {\r
885 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
886\r
887 Question = IdToQuestion2 (Form, QuestionId);\r
888 if (Question != NULL) {\r
8d00a0f1 889 //\r
890 // EFI variable storage may be updated by Callback() asynchronous,\r
891 // to keep synchronous, always reload the Question Value.\r
892 //\r
893 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
816a7110 894 GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
8d00a0f1 895 }\r
896\r
7936fb6a 897 return Question;\r
898 }\r
899\r
900 Link = GetNextNode (&FormSet->FormListHead, Link);\r
901 }\r
902\r
903 return NULL;\r
904}\r
905\r
906\r
907/**\r
908 Get Expression given its RuleId.\r
909\r
910 @param Form The form which contains this Expression.\r
911 @param RuleId Id of this Expression.\r
912\r
913 @retval Pointer The Expression.\r
914 @retval NULL Specified Expression not found in the form.\r
915\r
916**/\r
917FORM_EXPRESSION *\r
918RuleIdToExpression (\r
919 IN FORM_BROWSER_FORM *Form,\r
920 IN UINT8 RuleId\r
921 )\r
922{\r
923 LIST_ENTRY *Link;\r
924 FORM_EXPRESSION *Expression;\r
925\r
926 Link = GetFirstNode (&Form->ExpressionListHead);\r
927 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
928 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
929\r
930 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
931 return Expression;\r
932 }\r
933\r
934 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
935 }\r
936\r
937 return NULL;\r
938}\r
939\r
940\r
941/**\r
942 Locate the Unicode Collation Protocol interface for later use.\r
943\r
944 @retval EFI_SUCCESS Protocol interface initialize success.\r
945 @retval Other Protocol interface initialize failed.\r
946\r
947**/\r
948EFI_STATUS\r
949InitializeUnicodeCollationProtocol (\r
950 VOID\r
951 )\r
952{\r
953 EFI_STATUS Status;\r
954\r
955 if (mUnicodeCollation != NULL) {\r
956 return EFI_SUCCESS;\r
957 }\r
958\r
959 //\r
960 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
961 // instances first and then select one which support English language.\r
962 // Current implementation just pick the first instance.\r
963 //\r
964 Status = gBS->LocateProtocol (\r
965 &gEfiUnicodeCollation2ProtocolGuid,\r
966 NULL,\r
967 (VOID **) &mUnicodeCollation\r
968 );\r
969 return Status;\r
970}\r
971\r
972/**\r
973 Convert the input Unicode character to upper.\r
974\r
975 @param String Th Unicode character to be converted.\r
976\r
977**/\r
978VOID\r
979IfrStrToUpper (\r
8b0fc5c1 980 IN CHAR16 *String\r
7936fb6a 981 )\r
982{\r
983 while (*String != 0) {\r
984 if ((*String >= 'a') && (*String <= 'z')) {\r
985 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
986 }\r
987 String++;\r
988 }\r
989}\r
990\r
991\r
992/**\r
993 Evaluate opcode EFI_IFR_TO_STRING.\r
994\r
995 @param FormSet Formset which contains this opcode.\r
996 @param Format String format in EFI_IFR_TO_STRING.\r
997 @param Result Evaluation result for this opcode.\r
998\r
999 @retval EFI_SUCCESS Opcode evaluation success.\r
1000 @retval Other Opcode evaluation failed.\r
1001\r
1002**/\r
1003EFI_STATUS\r
1004IfrToString (\r
1005 IN FORM_BROWSER_FORMSET *FormSet,\r
1006 IN UINT8 Format,\r
1007 OUT EFI_HII_VALUE *Result\r
1008 )\r
1009{\r
1010 EFI_STATUS Status;\r
1011 EFI_HII_VALUE Value;\r
1012 CHAR16 *String;\r
1013 CHAR16 *PrintFormat;\r
1014 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
901ba0e7 1015 UINT8 *TmpBuf;\r
7936fb6a 1016 UINTN BufferSize;\r
1017\r
1018 Status = PopExpression (&Value);\r
1019 if (EFI_ERROR (Status)) {\r
1020 return Status;\r
1021 }\r
1022\r
1023 switch (Value.Type) {\r
1024 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1025 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1026 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1027 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1028 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
1029 switch (Format) {\r
1030 case EFI_IFR_STRING_UNSIGNED_DEC:\r
1031 case EFI_IFR_STRING_SIGNED_DEC:\r
1032 PrintFormat = L"%ld";\r
1033 break;\r
1034\r
1035 case EFI_IFR_STRING_LOWERCASE_HEX:\r
1036 PrintFormat = L"%lx";\r
1037 break;\r
1038\r
1039 case EFI_IFR_STRING_UPPERCASE_HEX:\r
1040 PrintFormat = L"%lX";\r
1041 break;\r
1042\r
1043 default:\r
8f420676
ED
1044 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1045 return EFI_SUCCESS;\r
7936fb6a 1046 }\r
1047 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
1048 String = Buffer;\r
1049 break;\r
1050\r
1051 case EFI_IFR_TYPE_STRING:\r
1052 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1053 return EFI_SUCCESS;\r
1054\r
1055 case EFI_IFR_TYPE_BOOLEAN:\r
1056 String = (Value.Value.b) ? L"True" : L"False";\r
1057 break;\r
901ba0e7
ED
1058 \r
1059 case EFI_IFR_TYPE_BUFFER:\r
1060 //\r
1061 // + 3 is base on the unicode format, the length may be odd number, \r
1062 // so need 1 byte to align, also need 2 bytes for L'\0'.\r
1063 //\r
1064 TmpBuf = AllocateZeroPool (Value.BufferLen + 3);\r
db40504e 1065 ASSERT (TmpBuf != NULL);\r
901ba0e7
ED
1066 if (Format == EFI_IFR_STRING_ASCII) {\r
1067 CopyMem (TmpBuf, Value.Buffer, Value.BufferLen);\r
1068 PrintFormat = L"%a"; \r
1069 } else {\r
1070 // Format == EFI_IFR_STRING_UNICODE\r
1071 CopyMem (TmpBuf, Value.Buffer, Value.BufferLen * sizeof (CHAR16));\r
1072 PrintFormat = L"%s"; \r
1073 }\r
dbcecd5d 1074 UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, Value.Buffer); \r
901ba0e7
ED
1075 String = Buffer; \r
1076 FreePool (TmpBuf);\r
1077 FreePool (Value.Buffer);\r
1078 break;\r
1079 \r
7936fb6a 1080 default:\r
8f420676
ED
1081 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1082 return EFI_SUCCESS;\r
7936fb6a 1083 }\r
1084\r
1085 Result->Type = EFI_IFR_TYPE_STRING;\r
1086 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
1087 return EFI_SUCCESS;\r
1088}\r
1089\r
1090\r
1091/**\r
1092 Evaluate opcode EFI_IFR_TO_UINT.\r
1093\r
1094 @param FormSet Formset which contains this opcode.\r
1095 @param Result Evaluation result for this opcode.\r
1096\r
1097 @retval EFI_SUCCESS Opcode evaluation success.\r
1098 @retval Other Opcode evaluation failed.\r
1099\r
1100**/\r
1101EFI_STATUS\r
1102IfrToUint (\r
1103 IN FORM_BROWSER_FORMSET *FormSet,\r
1104 OUT EFI_HII_VALUE *Result\r
1105 )\r
1106{\r
1107 EFI_STATUS Status;\r
1108 EFI_HII_VALUE Value;\r
1109 CHAR16 *String;\r
1110 CHAR16 *StringPtr;\r
7936fb6a 1111\r
1112 Status = PopExpression (&Value);\r
1113 if (EFI_ERROR (Status)) {\r
1114 return Status;\r
1115 }\r
1116\r
901ba0e7 1117 if (Value.Type >= EFI_IFR_TYPE_OTHER && Value.Type != EFI_IFR_TYPE_BUFFER) {\r
8f420676
ED
1118 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1119 return EFI_SUCCESS;\r
7936fb6a 1120 }\r
1121\r
1122 Status = EFI_SUCCESS;\r
1123 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
1124 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1125 if (String == NULL) {\r
1126 return EFI_NOT_FOUND;\r
1127 }\r
8b0fc5c1 1128\r
7936fb6a 1129 IfrStrToUpper (String);\r
1130 StringPtr = StrStr (String, L"0X");\r
1131 if (StringPtr != NULL) {\r
1132 //\r
1133 // Hex string\r
1134 //\r
ac7e320c 1135 Result->Value.u64 = StrHexToUint64 (String);\r
7936fb6a 1136 } else {\r
1137 //\r
ac7e320c 1138 // decimal string\r
7936fb6a 1139 //\r
ac7e320c 1140 Result->Value.u64 = StrDecimalToUint64 (String);\r
7936fb6a 1141 }\r
f4113e1f 1142 FreePool (String);\r
901ba0e7
ED
1143 } else if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1144 if (Value.BufferLen > 8) {\r
1145 FreePool (Value.Buffer);\r
8f420676
ED
1146 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1147 return EFI_SUCCESS;\r
901ba0e7
ED
1148 }\r
1149 Result->Value.u64 = *(UINT64*) Value.Buffer;\r
1150 FreePool (Value.Buffer);\r
7936fb6a 1151 } else {\r
1152 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1153 }\r
1154\r
1155 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1156 return Status;\r
1157}\r
1158\r
1159\r
1160/**\r
1161 Evaluate opcode EFI_IFR_CATENATE.\r
1162\r
1163 @param FormSet Formset which contains this opcode.\r
1164 @param Result Evaluation result for this opcode.\r
1165\r
1166 @retval EFI_SUCCESS Opcode evaluation success.\r
1167 @retval Other Opcode evaluation failed.\r
1168\r
1169**/\r
1170EFI_STATUS\r
1171IfrCatenate (\r
1172 IN FORM_BROWSER_FORMSET *FormSet,\r
1173 OUT EFI_HII_VALUE *Result\r
1174 )\r
1175{\r
1176 EFI_STATUS Status;\r
901ba0e7 1177 EFI_HII_VALUE Value[2];\r
7936fb6a 1178 CHAR16 *String[2];\r
1179 UINTN Index;\r
1180 CHAR16 *StringPtr;\r
1181 UINTN Size;\r
1182\r
1183 //\r
1184 // String[0] - The second string\r
1185 // String[1] - The first string\r
1186 //\r
1187 String[0] = NULL;\r
1188 String[1] = NULL;\r
1189 StringPtr = NULL;\r
1190 Status = EFI_SUCCESS;\r
901ba0e7 1191 ZeroMem (Value, sizeof (Value));\r
7936fb6a 1192\r
8f420676
ED
1193 Status = PopExpression (&Value[0]);\r
1194 if (EFI_ERROR (Status)) {\r
1195 goto Done;\r
1196 }\r
1197\r
1198 Status = PopExpression (&Value[1]);\r
1199 if (EFI_ERROR (Status)) {\r
1200 goto Done;\r
1201 }\r
7936fb6a 1202\r
8f420676 1203 for (Index = 0; Index < 2; Index++) {\r
901ba0e7 1204 if (Value[Index].Type != EFI_IFR_TYPE_STRING && Value[Index].Type != EFI_IFR_TYPE_BUFFER) {\r
8f420676
ED
1205 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1206 Status = EFI_SUCCESS;\r
7936fb6a 1207 goto Done;\r
1208 }\r
1209\r
901ba0e7
ED
1210 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
1211 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1212 if (String[Index] == NULL) {\r
1213 Status = EFI_NOT_FOUND;\r
1214 goto Done;\r
1215 }\r
7936fb6a 1216 }\r
1217 }\r
1218\r
901ba0e7
ED
1219 if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
1220 Size = StrSize (String[0]);\r
1221 StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
1222 ASSERT (StringPtr != NULL);\r
1223 StrCpy (StringPtr, String[1]);\r
1224 StrCat (StringPtr, String[0]);\r
7936fb6a 1225\r
901ba0e7
ED
1226 Result->Type = EFI_IFR_TYPE_STRING;\r
1227 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
1228 } else {\r
1229 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1230 Result->BufferLen = (UINT16) (Value[0].BufferLen + Value[1].BufferLen);\r
1231\r
1232 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1233 ASSERT (Result->Buffer != NULL);\r
7936fb6a 1234\r
901ba0e7
ED
1235 CopyMem (Result->Buffer, Value[0].Buffer, Value[0].BufferLen);\r
1236 CopyMem (&Result->Buffer[Value[0].BufferLen], Value[1].Buffer, Value[1].BufferLen);\r
1237 }\r
7936fb6a 1238Done:\r
901ba0e7
ED
1239 if (Value[0].Buffer != NULL) {\r
1240 FreePool (Value[0].Buffer);\r
1241 }\r
1242 if (Value[1].Buffer != NULL) {\r
1243 FreePool (Value[1].Buffer);\r
1244 }\r
676df92c 1245 if (String[0] != NULL) {\r
1246 FreePool (String[0]);\r
1247 }\r
1248 if (String[1] != NULL) {\r
1249 FreePool (String[1]);\r
8b0fc5c1 1250 }\r
676df92c 1251 if (StringPtr != NULL) {\r
1252 FreePool (StringPtr);\r
1253 }\r
7936fb6a 1254\r
1255 return Status;\r
1256}\r
1257\r
1258\r
1259/**\r
1260 Evaluate opcode EFI_IFR_MATCH.\r
1261\r
1262 @param FormSet Formset which contains this opcode.\r
1263 @param Result Evaluation result for this opcode.\r
1264\r
1265 @retval EFI_SUCCESS Opcode evaluation success.\r
1266 @retval Other Opcode evaluation failed.\r
1267\r
1268**/\r
1269EFI_STATUS\r
1270IfrMatch (\r
1271 IN FORM_BROWSER_FORMSET *FormSet,\r
1272 OUT EFI_HII_VALUE *Result\r
1273 )\r
1274{\r
1275 EFI_STATUS Status;\r
8f420676 1276 EFI_HII_VALUE Value[2];\r
7936fb6a 1277 CHAR16 *String[2];\r
1278 UINTN Index;\r
1279\r
1280 //\r
1281 // String[0] - The string to search\r
1282 // String[1] - pattern\r
1283 //\r
1284 String[0] = NULL;\r
1285 String[1] = NULL;\r
1286 Status = EFI_SUCCESS;\r
8f420676
ED
1287 ZeroMem (Value, sizeof (Value));\r
1288\r
1289 Status = PopExpression (&Value[0]);\r
1290 if (EFI_ERROR (Status)) {\r
1291 goto Done;\r
1292 }\r
1293\r
1294 Status = PopExpression (&Value[1]);\r
1295 if (EFI_ERROR (Status)) {\r
1296 goto Done;\r
1297 }\r
7936fb6a 1298\r
8f420676
ED
1299 for (Index = 0; Index < 2; Index++) {\r
1300 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
1301 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1302 Status = EFI_SUCCESS;\r
7936fb6a 1303 goto Done;\r
1304 }\r
1305\r
8f420676 1306 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
bc166db3 1307 if (String [Index] == NULL) {\r
7936fb6a 1308 Status = EFI_NOT_FOUND;\r
1309 goto Done;\r
1310 }\r
1311 }\r
1312\r
1313 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1314 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
1315\r
1316Done:\r
676df92c 1317 if (String[0] != NULL) {\r
1318 FreePool (String[0]);\r
1319 }\r
1320 if (String[1] != NULL) {\r
1321 FreePool (String[1]);\r
8b0fc5c1 1322 }\r
7936fb6a 1323\r
1324 return Status;\r
1325}\r
1326\r
1327\r
1328/**\r
1329 Evaluate opcode EFI_IFR_FIND.\r
1330\r
1331 @param FormSet Formset which contains this opcode.\r
1332 @param Format Case sensitive or insensitive.\r
1333 @param Result Evaluation result for this opcode.\r
1334\r
1335 @retval EFI_SUCCESS Opcode evaluation success.\r
1336 @retval Other Opcode evaluation failed.\r
1337\r
1338**/\r
1339EFI_STATUS\r
1340IfrFind (\r
1341 IN FORM_BROWSER_FORMSET *FormSet,\r
1342 IN UINT8 Format,\r
1343 OUT EFI_HII_VALUE *Result\r
1344 )\r
1345{\r
1346 EFI_STATUS Status;\r
8f420676 1347 EFI_HII_VALUE Value[3];\r
7936fb6a 1348 CHAR16 *String[2];\r
1349 UINTN Base;\r
1350 CHAR16 *StringPtr;\r
1351 UINTN Index;\r
1352\r
8f420676
ED
1353 ZeroMem (Value, sizeof (Value));\r
1354\r
7936fb6a 1355 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
8f420676 1356 return EFI_INVALID_PARAMETER;\r
7936fb6a 1357 }\r
1358\r
8f420676
ED
1359 Status = PopExpression (&Value[0]);\r
1360 if (EFI_ERROR (Status)) {\r
1361 return Status;\r
1362 }\r
1363\r
1364 Status = PopExpression (&Value[1]);\r
7936fb6a 1365 if (EFI_ERROR (Status)) {\r
1366 return Status;\r
1367 }\r
8f420676
ED
1368\r
1369 Status = PopExpression (&Value[2]);\r
1370 if (EFI_ERROR (Status)) {\r
1371 return Status;\r
1372 } \r
1373\r
1374 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1375 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1376 return EFI_SUCCESS;\r
7936fb6a 1377 }\r
8f420676 1378 Base = (UINTN) Value[0].Value.u64;\r
7936fb6a 1379\r
1380 //\r
1381 // String[0] - sub-string\r
1382 // String[1] - The string to search\r
1383 //\r
1384 String[0] = NULL;\r
1385 String[1] = NULL;\r
1386 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1387 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1388 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1389 Status = EFI_SUCCESS;\r
7936fb6a 1390 goto Done;\r
1391 }\r
1392\r
8f420676 1393 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
d0720b57 1394 if (String[Index] == NULL) {\r
7936fb6a 1395 Status = EFI_NOT_FOUND;\r
1396 goto Done;\r
1397 }\r
1398\r
1399 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
1400 //\r
1401 // Case insensitive, convert both string to upper case\r
1402 //\r
1403 IfrStrToUpper (String[Index]);\r
1404 }\r
1405 }\r
1406\r
1407 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1408 if (Base >= StrLen (String[1])) {\r
1409 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
1410 } else {\r
1411 StringPtr = StrStr (String[1] + Base, String[0]);\r
1412 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
1413 }\r
1414\r
1415Done:\r
676df92c 1416 if (String[0] != NULL) {\r
1417 FreePool (String[0]);\r
1418 }\r
1419 if (String[1] != NULL) {\r
1420 FreePool (String[1]);\r
8b0fc5c1 1421 }\r
7936fb6a 1422\r
1423 return Status;\r
1424}\r
1425\r
1426\r
1427/**\r
1428 Evaluate opcode EFI_IFR_MID.\r
1429\r
1430 @param FormSet Formset which contains this opcode.\r
1431 @param Result Evaluation result for this opcode.\r
1432\r
1433 @retval EFI_SUCCESS Opcode evaluation success.\r
1434 @retval Other Opcode evaluation failed.\r
1435\r
1436**/\r
1437EFI_STATUS\r
1438IfrMid (\r
1439 IN FORM_BROWSER_FORMSET *FormSet,\r
1440 OUT EFI_HII_VALUE *Result\r
1441 )\r
1442{\r
1443 EFI_STATUS Status;\r
8f420676 1444 EFI_HII_VALUE Value[3];\r
7936fb6a 1445 CHAR16 *String;\r
1446 UINTN Base;\r
1447 UINTN Length;\r
1448 CHAR16 *SubString;\r
901ba0e7 1449 UINT16 BufferLen;\r
7936fb6a 1450\r
8f420676
ED
1451 ZeroMem (Value, sizeof (Value));\r
1452\r
1453 Status = PopExpression (&Value[0]);\r
7936fb6a 1454 if (EFI_ERROR (Status)) {\r
1455 return Status;\r
1456 }\r
7936fb6a 1457\r
8f420676 1458 Status = PopExpression (&Value[1]);\r
7936fb6a 1459 if (EFI_ERROR (Status)) {\r
1460 return Status;\r
1461 }\r
7936fb6a 1462\r
8f420676 1463 Status = PopExpression (&Value[2]);\r
7936fb6a 1464 if (EFI_ERROR (Status)) {\r
1465 return Status;\r
8f420676
ED
1466 } \r
1467\r
1468 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1469 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1470 return EFI_SUCCESS;\r
7936fb6a 1471 }\r
8f420676
ED
1472 Length = (UINTN) Value[0].Value.u64;\r
1473\r
1474 if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1475 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1476 return EFI_SUCCESS;\r
7936fb6a 1477 }\r
8f420676
ED
1478 Base = (UINTN) Value[1].Value.u64;\r
1479\r
1480 if (Value[2].Type != EFI_IFR_TYPE_STRING && Value[2].Type != EFI_IFR_TYPE_BUFFER) {\r
1481 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1482 return EFI_SUCCESS;\r
1483 }\r
1484 if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
1485 String = GetToken (Value[2].Value.string, FormSet->HiiHandle);\r
901ba0e7
ED
1486 if (String == NULL) {\r
1487 return EFI_NOT_FOUND;\r
1488 }\r
7936fb6a 1489\r
901ba0e7
ED
1490 if (Length == 0 || Base >= StrLen (String)) {\r
1491 SubString = gEmptyString;\r
1492 } else {\r
1493 SubString = String + Base;\r
1494 if ((Base + Length) < StrLen (String)) {\r
1495 SubString[Length] = L'\0';\r
1496 }\r
7936fb6a 1497 }\r
7936fb6a 1498\r
901ba0e7
ED
1499 Result->Type = EFI_IFR_TYPE_STRING;\r
1500 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
7936fb6a 1501\r
901ba0e7
ED
1502 FreePool (String);\r
1503 } else {\r
8f420676 1504 BufferLen = Value[2].BufferLen;\r
901ba0e7
ED
1505 \r
1506 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1507 if (Length == 0 || Base >= BufferLen) {\r
1508 Result->BufferLen = 0;\r
1509 Result->Buffer = NULL;\r
1510 } else {\r
1511 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length); \r
1512 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1513 ASSERT (Result->Buffer != NULL);\r
8f420676 1514 CopyMem (Result->Buffer, &Value[2].Buffer[Base], Result->BufferLen);\r
901ba0e7 1515 }\r
7936fb6a 1516\r
8f420676 1517 FreePool (Value[2].Buffer);\r
901ba0e7
ED
1518 }\r
1519 \r
7936fb6a 1520 return Status;\r
1521}\r
1522\r
1523\r
1524/**\r
1525 Evaluate opcode EFI_IFR_TOKEN.\r
1526\r
1527 @param FormSet Formset which contains this opcode.\r
1528 @param Result Evaluation result for this opcode.\r
1529\r
1530 @retval EFI_SUCCESS Opcode evaluation success.\r
1531 @retval Other Opcode evaluation failed.\r
1532\r
1533**/\r
1534EFI_STATUS\r
1535IfrToken (\r
1536 IN FORM_BROWSER_FORMSET *FormSet,\r
1537 OUT EFI_HII_VALUE *Result\r
1538 )\r
1539{\r
1540 EFI_STATUS Status;\r
8f420676 1541 EFI_HII_VALUE Value[3];\r
7936fb6a 1542 CHAR16 *String[2];\r
1543 UINTN Count;\r
1544 CHAR16 *Delimiter;\r
1545 CHAR16 *SubString;\r
1546 CHAR16 *StringPtr;\r
1547 UINTN Index;\r
1548\r
8f420676
ED
1549 ZeroMem (Value, sizeof (Value));\r
1550\r
1551 Status = PopExpression (&Value[0]);\r
1552 if (EFI_ERROR (Status)) {\r
1553 return Status;\r
1554 }\r
1555\r
1556 Status = PopExpression (&Value[1]);\r
7936fb6a 1557 if (EFI_ERROR (Status)) {\r
1558 return Status;\r
1559 }\r
8f420676
ED
1560\r
1561 Status = PopExpression (&Value[2]);\r
1562 if (EFI_ERROR (Status)) {\r
1563 return Status;\r
1564 } \r
1565\r
1566 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) { \r
1567 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1568 return EFI_SUCCESS;\r
7936fb6a 1569 }\r
8f420676 1570 Count = (UINTN) Value[0].Value.u64;\r
7936fb6a 1571\r
1572 //\r
1573 // String[0] - Delimiter\r
1574 // String[1] - The string to search\r
1575 //\r
1576 String[0] = NULL;\r
1577 String[1] = NULL;\r
1578 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1579 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1580 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1581 Status = EFI_SUCCESS; \r
7936fb6a 1582 goto Done;\r
1583 }\r
1584\r
8f420676 1585 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
d0720b57 1586 if (String[Index] == NULL) {\r
7936fb6a 1587 Status = EFI_NOT_FOUND;\r
1588 goto Done;\r
1589 }\r
1590 }\r
1591\r
1592 Delimiter = String[0];\r
1593 SubString = String[1];\r
1594 while (Count > 0) {\r
1595 SubString = StrStr (SubString, Delimiter);\r
1596 if (SubString != NULL) {\r
1597 //\r
1598 // Skip over the delimiter\r
1599 //\r
1600 SubString = SubString + StrLen (Delimiter);\r
1601 } else {\r
1602 break;\r
1603 }\r
1604 Count--;\r
1605 }\r
1606\r
1607 if (SubString == NULL) {\r
1608 //\r
1609 // nth delimited sub-string not found, push an empty string\r
1610 //\r
1611 SubString = gEmptyString;\r
1612 } else {\r
1613 //\r
1614 // Put a NULL terminator for nth delimited sub-string\r
1615 //\r
1616 StringPtr = StrStr (SubString, Delimiter);\r
1617 if (StringPtr != NULL) {\r
1618 *StringPtr = L'\0';\r
1619 }\r
1620 }\r
1621\r
1622 Result->Type = EFI_IFR_TYPE_STRING;\r
1623 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1624\r
1625Done:\r
676df92c 1626 if (String[0] != NULL) {\r
1627 FreePool (String[0]);\r
1628 }\r
1629 if (String[1] != NULL) {\r
1630 FreePool (String[1]);\r
8b0fc5c1 1631 }\r
7936fb6a 1632\r
1633 return Status;\r
1634}\r
1635\r
1636\r
1637/**\r
1638 Evaluate opcode EFI_IFR_SPAN.\r
1639\r
1640 @param FormSet Formset which contains this opcode.\r
1641 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1642 @param Result Evaluation result for this opcode.\r
1643\r
1644 @retval EFI_SUCCESS Opcode evaluation success.\r
1645 @retval Other Opcode evaluation failed.\r
1646\r
1647**/\r
1648EFI_STATUS\r
1649IfrSpan (\r
1650 IN FORM_BROWSER_FORMSET *FormSet,\r
1651 IN UINT8 Flags,\r
1652 OUT EFI_HII_VALUE *Result\r
1653 )\r
1654{\r
1655 EFI_STATUS Status;\r
8f420676 1656 EFI_HII_VALUE Value[3];\r
7936fb6a 1657 CHAR16 *String[2];\r
1658 CHAR16 *Charset;\r
1659 UINTN Base;\r
1660 UINTN Index;\r
1661 CHAR16 *StringPtr;\r
1662 BOOLEAN Found;\r
1663\r
8f420676
ED
1664 ZeroMem (Value, sizeof (Value));\r
1665\r
1666 Status = PopExpression (&Value[0]);\r
1667 if (EFI_ERROR (Status)) {\r
1668 return Status;\r
1669 }\r
1670\r
1671 Status = PopExpression (&Value[1]);\r
7936fb6a 1672 if (EFI_ERROR (Status)) {\r
1673 return Status;\r
1674 }\r
8f420676
ED
1675\r
1676 Status = PopExpression (&Value[2]);\r
1677 if (EFI_ERROR (Status)) {\r
1678 return Status;\r
1679 } \r
1680\r
1681 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1682 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1683 return EFI_SUCCESS;\r
7936fb6a 1684 }\r
8f420676 1685 Base = (UINTN) Value[0].Value.u64;\r
7936fb6a 1686\r
1687 //\r
1688 // String[0] - Charset\r
1689 // String[1] - The string to search\r
1690 //\r
1691 String[0] = NULL;\r
1692 String[1] = NULL;\r
1693 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1694 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1695 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1696 Status = EFI_SUCCESS;\r
7936fb6a 1697 goto Done;\r
1698 }\r
1699\r
8f420676 1700 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
bc166db3 1701 if (String [Index] == NULL) {\r
7936fb6a 1702 Status = EFI_NOT_FOUND;\r
1703 goto Done;\r
1704 }\r
1705 }\r
1706\r
1707 if (Base >= StrLen (String[1])) {\r
8f420676
ED
1708 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1709 Status = EFI_SUCCESS;\r
7936fb6a 1710 goto Done;\r
1711 }\r
1712\r
1713 Found = FALSE;\r
1714 StringPtr = String[1] + Base;\r
1715 Charset = String[0];\r
1716 while (*StringPtr != 0 && !Found) {\r
1717 Index = 0;\r
1718 while (Charset[Index] != 0) {\r
1719 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
1720 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1721 Found = TRUE;\r
1722 break;\r
1723 }\r
1724 } else {\r
1725 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1726 Found = TRUE;\r
1727 break;\r
1728 }\r
1729 }\r
1730 //\r
1731 // Skip characters pair representing low-end of a range and high-end of a range\r
1732 //\r
1733 Index += 2;\r
1734 }\r
1735\r
1736 if (!Found) {\r
1737 StringPtr++;\r
1738 }\r
1739 }\r
1740\r
1741 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1742 Result->Value.u64 = StringPtr - String[1];\r
1743\r
1744Done:\r
676df92c 1745 if (String[0] != NULL) {\r
1746 FreePool (String[0]);\r
1747 }\r
1748 if (String[1] != NULL) {\r
1749 FreePool (String[1]);\r
8b0fc5c1 1750 }\r
7936fb6a 1751\r
1752 return Status;\r
1753}\r
1754\r
1755\r
1756/**\r
1757 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1758\r
1759 @param Value HII Value to be converted.\r
1760\r
1761**/\r
1762VOID\r
1763ExtendValueToU64 (\r
1764 IN EFI_HII_VALUE *Value\r
1765 )\r
1766{\r
1767 UINT64 Temp;\r
1768\r
1769 Temp = 0;\r
1770 switch (Value->Type) {\r
1771 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1772 Temp = Value->Value.u8;\r
1773 break;\r
1774\r
1775 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1776 Temp = Value->Value.u16;\r
1777 break;\r
1778\r
1779 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1780 Temp = Value->Value.u32;\r
1781 break;\r
1782\r
1783 case EFI_IFR_TYPE_BOOLEAN:\r
1784 Temp = Value->Value.b;\r
1785 break;\r
1786\r
1787 case EFI_IFR_TYPE_TIME:\r
1788 Temp = Value->Value.u32 & 0xffffff;\r
1789 break;\r
1790\r
1791 case EFI_IFR_TYPE_DATE:\r
1792 Temp = Value->Value.u32;\r
1793 break;\r
1794\r
1795 default:\r
1796 return;\r
1797 }\r
1798\r
1799 Value->Value.u64 = Temp;\r
1800}\r
1801\r
1802\r
1803/**\r
1804 Compare two Hii value.\r
1805\r
1806 @param Value1 Expression value to compare on left-hand.\r
1807 @param Value2 Expression value to compare on right-hand.\r
8f420676
ED
1808 @param Result Return value after compare.\r
1809 retval 0 Two operators equal.\r
1810 return Positive value if Value1 is greater than Value2.\r
1811 retval Negative value if Value1 is less than Value2.\r
7936fb6a 1812 @param HiiHandle Only required for string compare.\r
1813\r
8f420676
ED
1814 @retval other Could not perform compare on two values.\r
1815 @retval EFI_SUCCESS Compare the value success.\r
7936fb6a 1816\r
1817**/\r
8f420676 1818EFI_STATUS\r
7936fb6a 1819CompareHiiValue (\r
1820 IN EFI_HII_VALUE *Value1,\r
1821 IN EFI_HII_VALUE *Value2,\r
8f420676 1822 OUT INTN *Result,\r
7936fb6a 1823 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
1824 )\r
1825{\r
7936fb6a 1826 INT64 Temp64;\r
1827 CHAR16 *Str1;\r
1828 CHAR16 *Str2;\r
901ba0e7 1829 UINTN Len;\r
7936fb6a 1830\r
1831 if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
901ba0e7 1832 if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {\r
8f420676 1833 return EFI_UNSUPPORTED;\r
901ba0e7 1834 }\r
7936fb6a 1835 }\r
1836\r
1837 if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
1838 if (Value1->Type != Value2->Type) {\r
1839 //\r
1840 // Both Operator should be type of String\r
1841 //\r
8f420676 1842 return EFI_UNSUPPORTED;\r
7936fb6a 1843 }\r
1844\r
1845 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
1846 //\r
1847 // StringId 0 is reserved\r
1848 //\r
1849 return EFI_INVALID_PARAMETER;\r
1850 }\r
1851\r
1852 if (Value1->Value.string == Value2->Value.string) {\r
8f420676
ED
1853 *Result = 0;\r
1854 return EFI_SUCCESS;\r
7936fb6a 1855 }\r
1856\r
1857 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
1858 if (Str1 == NULL) {\r
1859 //\r
1860 // String not found\r
1861 //\r
8f420676 1862 return EFI_NOT_FOUND;\r
7936fb6a 1863 }\r
1864\r
1865 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
1866 if (Str2 == NULL) {\r
f4113e1f 1867 FreePool (Str1);\r
8f420676 1868 return EFI_NOT_FOUND;\r
7936fb6a 1869 }\r
1870\r
8f420676 1871 *Result = StrCmp (Str1, Str2);\r
7936fb6a 1872\r
f4113e1f 1873 FreePool (Str1);\r
1874 FreePool (Str2);\r
7936fb6a 1875\r
8f420676 1876 return EFI_SUCCESS;\r
7936fb6a 1877 }\r
1878\r
901ba0e7
ED
1879 if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) {\r
1880 if (Value1->Type != Value2->Type) {\r
1881 //\r
1882 // Both Operator should be type of Buffer.\r
1883 //\r
8f420676 1884 return EFI_UNSUPPORTED;\r
901ba0e7
ED
1885 }\r
1886 Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;\r
8f420676
ED
1887 *Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);\r
1888 if ((*Result == 0) && (Value1->BufferLen != Value2->BufferLen))\r
901ba0e7
ED
1889 {\r
1890 //\r
1891 // In this case, means base on samll number buffer, the data is same\r
1892 // So which value has more data, which value is bigger.\r
1893 //\r
8f420676 1894 *Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1;\r
901ba0e7 1895 }\r
8f420676 1896 return EFI_SUCCESS;\r
901ba0e7
ED
1897 } \r
1898\r
7936fb6a 1899 //\r
1900 // Take remain types(integer, boolean, date/time) as integer\r
1901 //\r
1902 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
1903 if (Temp64 > 0) {\r
8f420676 1904 *Result = 1;\r
7936fb6a 1905 } else if (Temp64 < 0) {\r
8f420676 1906 *Result = -1;\r
7936fb6a 1907 } else {\r
8f420676 1908 *Result = 0;\r
7936fb6a 1909 }\r
1910\r
8f420676 1911 return EFI_SUCCESS;\r
7936fb6a 1912}\r
1913\r
cbf73e50 1914/**\r
1915 Check if current user has the privilege specified by the permissions GUID.\r
1916\r
1917 @param[in] Guid A GUID specifying setup access permissions.\r
1918\r
1919 @retval TRUE Current user has the privilege.\r
1920 @retval FALSE Current user does not have the privilege.\r
1921**/\r
1922BOOLEAN\r
1923CheckUserPrivilege (\r
1924 IN EFI_GUID *Guid\r
1925 )\r
1926{\r
1927 EFI_STATUS Status;\r
1928 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
1929 EFI_USER_INFO_HANDLE UserInfoHandle;\r
1930 EFI_USER_INFO *UserInfo;\r
1931 EFI_GUID *UserPermissionsGuid;\r
1932 UINTN UserInfoSize;\r
1933 UINTN AccessControlDataSize;\r
1934 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
1935 UINTN RemainSize;\r
1936\r
1937 if (mUserManager == NULL) {\r
1938 Status = gBS->LocateProtocol (\r
1939 &gEfiUserManagerProtocolGuid,\r
1940 NULL,\r
1941 (VOID **) &mUserManager\r
1942 );\r
1943 if (EFI_ERROR (Status)) {\r
1944 ///\r
1945 /// If the system does not support user management, then it is assumed that\r
1946 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
1947 /// op-code is always TRUE.\r
1948 ///\r
1949 return TRUE;\r
1950 }\r
1951 }\r
1952\r
1953 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
1954 ASSERT_EFI_ERROR (Status);\r
1955\r
1956 ///\r
1957 /// Enumerate all user information of the current user profile\r
1958 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
1959 ///\r
1960 \r
1961 for (UserInfoHandle = NULL;;) {\r
1962 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
1963 if (EFI_ERROR (Status)) {\r
1964 break;\r
1965 }\r
1966\r
1967 UserInfoSize = 0;\r
1968 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
1969 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1970 continue;\r
1971 }\r
1972\r
1973 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
1974 if (UserInfo == NULL) {\r
1975 break;\r
1976 }\r
1977\r
1978 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
1979 if (EFI_ERROR (Status) ||\r
1980 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
1981 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
1982 FreePool (UserInfo);\r
1983 continue;\r
1984 }\r
1985\r
1986 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
1987 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
1988 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
3dd405be 1989 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
cbf73e50 1990 break;\r
1991 }\r
1992 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
1993 ///\r
1994 /// Check if current user has the privilege specified by the permissions GUID.\r
1995 ///\r
1996\r
1997 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
1998 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
1999 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
2000 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
2001 FreePool (UserInfo);\r
2002 return TRUE;\r
2003 }\r
2004 UserPermissionsGuid++;\r
2005 AccessControlDataSize -= sizeof (EFI_GUID);\r
2006 }\r
2007 }\r
2008 RemainSize -= AccessControl->Size;\r
2009 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
2010 }\r
2011\r
2012 FreePool (UserInfo);\r
2013 }\r
2014 return FALSE;\r
2015}\r
7936fb6a 2016\r
db40504e
ED
2017/**\r
2018 Get question value from the predefined formset.\r
2019\r
2020 @param DevicePath The driver's device path which produece the formset data.\r
2021 @param InputHiiHandle The hii handle associate with the formset data.\r
2022 @param FormSetGuid The formset guid which include the question.\r
2023 @param QuestionId The question id which need to get value from.\r
2024 @param Value The return data about question's value.\r
2025 \r
2026 @retval TRUE Get the question value success.\r
2027 @retval FALSE Get the question value failed.\r
2028**/\r
2029BOOLEAN \r
2030GetQuestionValueFromForm (\r
2031 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2032 IN EFI_HII_HANDLE InputHiiHandle,\r
2033 IN EFI_GUID *FormSetGuid,\r
2034 IN EFI_QUESTION_ID QuestionId,\r
2035 OUT EFI_HII_VALUE *Value\r
2036 )\r
2037{\r
2038 EFI_STATUS Status;\r
2039 EFI_HANDLE DriverHandle;\r
2040 EFI_HANDLE Handle;\r
2041 EFI_HII_HANDLE *HiiHandles;\r
2042 EFI_HII_HANDLE HiiHandle;\r
2043 UINTN Index;\r
2044 FORM_BROWSER_STATEMENT *Question;\r
2045 FORM_BROWSER_FORMSET *FormSet;\r
2046 FORM_BROWSER_FORM *Form;\r
2047 BOOLEAN GetTheVal;\r
2048 LIST_ENTRY *Link;\r
2049\r
2050 // \r
2051 // The input parameter DevicePath or InputHiiHandle must have one valid input. \r
2052 //\r
2053 ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) || \r
2054 (DevicePath == NULL && InputHiiHandle != NULL) );\r
2055\r
2056 GetTheVal = TRUE;\r
2057 DriverHandle = NULL;\r
2058 HiiHandle = NULL;\r
2059 Question = NULL;\r
2060 Form = NULL;\r
2061\r
2062 //\r
2063 // Get HiiHandle.\r
2064 //\r
2065 if (DevicePath != NULL) {\r
2066 //\r
2067 // 1. Get Driver handle.\r
2068 //\r
2069 Status = gBS->LocateDevicePath (\r
2070 &gEfiDevicePathProtocolGuid,\r
2071 &DevicePath,\r
2072 &DriverHandle\r
2073 );\r
2074 if (EFI_ERROR (Status) || (DriverHandle == NULL)) {\r
2075 return FALSE;\r
2076 }\r
2077\r
2078 //\r
2079 // 2. Get Hii handle\r
2080 //\r
2081 HiiHandles = HiiGetHiiHandles (NULL);\r
2082 if (HiiHandles == NULL) {\r
2083 return FALSE;\r
2084 }\r
2085\r
2086 for (Index = 0; HiiHandles[Index] != NULL; Index++) {\r
2087 Status = mHiiDatabase->GetPackageListHandle (\r
2088 mHiiDatabase,\r
2089 HiiHandles[Index],\r
2090 &Handle\r
2091 );\r
2092 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {\r
2093 HiiHandle = HiiHandles[Index];\r
2094 break;\r
2095 }\r
2096 }\r
2097 FreePool (HiiHandles);\r
2098 } else {\r
2099 HiiHandle = InputHiiHandle;\r
2100 } \r
2101 ASSERT (HiiHandle != NULL);\r
2102\r
2103 //\r
2104 // Get the formset data include this question.\r
2105 //\r
2106 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
2107 ASSERT (FormSet != NULL);\r
7c6c064c 2108 Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);\r
db40504e
ED
2109 if (EFI_ERROR (Status)) {\r
2110 GetTheVal = FALSE;\r
2111 goto Done;\r
2112 }\r
2113\r
2114 //\r
2115 // Base on the Question Id to get the question info.\r
2116 // \r
2117 Question = IdToQuestion(FormSet, NULL, QuestionId);\r
2118 if (Question == NULL) {\r
2119 GetTheVal = FALSE;\r
2120 goto Done;\r
2121 }\r
2122\r
2123 //\r
2124 // Search form in the formset scope\r
2125 //\r
2126 Link = GetFirstNode (&FormSet->FormListHead);\r
2127 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2128 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2129\r
2130 Question = IdToQuestion2 (Form, QuestionId);\r
2131 if (Question != NULL) {\r
2132 break;\r
2133 }\r
2134\r
2135 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2136 Form = NULL;\r
2137 }\r
2138 ASSERT (Form != NULL);\r
2139 \r
2140 //\r
2141 // Get the question value.\r
2142 //\r
816a7110 2143 Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithHiiDriver);\r
db40504e
ED
2144 if (EFI_ERROR (Status)) {\r
2145 GetTheVal = FALSE;\r
2146 goto Done;\r
2147 }\r
2148\r
2149 CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
2150 \r
2151Done:\r
2152 //\r
2153 // Clean the formset structure and restore the global parameter.\r
2154 //\r
2155 if (FormSet != NULL) {\r
2156 DestroyFormSet (FormSet);\r
2157 }\r
2158 \r
2159 return GetTheVal;\r
2160}\r
2161\r
7936fb6a 2162/**\r
bc166db3 2163 Evaluate the result of a HII expression.\r
2164\r
2165 If Expression is NULL, then ASSERT.\r
7936fb6a 2166\r
2167 @param FormSet FormSet associated with this expression.\r
2168 @param Form Form associated with this expression.\r
2169 @param Expression Expression to be evaluated.\r
2170\r
2171 @retval EFI_SUCCESS The expression evaluated successfuly\r
2172 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
2173 could not be found.\r
2174 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
2175 stack.\r
2176 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
2177 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
2178\r
2179**/\r
2180EFI_STATUS\r
2181EvaluateExpression (\r
2182 IN FORM_BROWSER_FORMSET *FormSet,\r
2183 IN FORM_BROWSER_FORM *Form,\r
2184 IN OUT FORM_EXPRESSION *Expression\r
2185 )\r
2186{\r
2187 EFI_STATUS Status;\r
2188 LIST_ENTRY *Link;\r
2189 EXPRESSION_OPCODE *OpCode;\r
2190 FORM_BROWSER_STATEMENT *Question;\r
2191 FORM_BROWSER_STATEMENT *Question2;\r
2192 UINT16 Index;\r
2193 EFI_HII_VALUE Data1;\r
2194 EFI_HII_VALUE Data2;\r
2195 EFI_HII_VALUE Data3;\r
2196 FORM_EXPRESSION *RuleExpression;\r
2197 EFI_HII_VALUE *Value;\r
2198 INTN Result;\r
2199 CHAR16 *StrPtr;\r
2573712e 2200 CHAR16 *NameValue;\r
7936fb6a 2201 UINT32 TempValue;\r
2573712e
LG
2202 LIST_ENTRY *SubExpressionLink;\r
2203 FORM_EXPRESSION *SubExpression;\r
2204 UINTN StackOffset;\r
2205 UINTN TempLength;\r
2206 CHAR16 TempStr[5];\r
2207 UINT8 DigitUint8;\r
2208 UINT8 *TempBuffer;\r
2209 EFI_TIME EfiTime;\r
db40504e 2210 EFI_HII_VALUE QuestionVal;\r
33efdf51 2211 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
7936fb6a 2212\r
2213 //\r
2573712e 2214 // Save current stack offset.\r
7936fb6a 2215 //\r
2573712e 2216 StackOffset = SaveExpressionEvaluationStackOffset ();\r
7936fb6a 2217\r
bc166db3 2218 ASSERT (Expression != NULL);\r
7936fb6a 2219 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
2220\r
2221 Link = GetFirstNode (&Expression->OpCodeListHead);\r
2222 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
2223 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
2224\r
2225 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
2226\r
2227 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
2228 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
2229 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
2230\r
2231 Value = &Data3;\r
2232 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2233 Status = EFI_SUCCESS;\r
2234\r
2235 switch (OpCode->Operand) {\r
2236 //\r
2237 // Built-in functions\r
2238 //\r
2239 case EFI_IFR_EQ_ID_VAL_OP:\r
2240 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2241 if (Question == NULL) {\r
8f420676
ED
2242 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2243 break;\r
7936fb6a 2244 }\r
2245\r
8f420676
ED
2246 Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);\r
2247 if (Status == EFI_UNSUPPORTED) {\r
2248 Status = EFI_SUCCESS;\r
2249 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2250 break;\r
2251 }\r
2252\r
2253 if (EFI_ERROR (Status)) {\r
2573712e 2254 goto Done;\r
7936fb6a 2255 }\r
2256 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2257 break;\r
2258\r
2259 case EFI_IFR_EQ_ID_ID_OP:\r
2260 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2261 if (Question == NULL) {\r
8f420676
ED
2262 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2263 break;\r
7936fb6a 2264 }\r
2265\r
2266 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
2267 if (Question2 == NULL) {\r
8f420676
ED
2268 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2269 break;\r
7936fb6a 2270 }\r
2271\r
8f420676
ED
2272 Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);\r
2273 if (Status == EFI_UNSUPPORTED) {\r
2274 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2275 Status = EFI_SUCCESS;\r
2276 break;\r
2277 }\r
2278 if (EFI_ERROR (Status)) {\r
2573712e 2279 goto Done;\r
7936fb6a 2280 }\r
2281 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2282 break;\r
2283\r
e8ef4283 2284 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
7936fb6a 2285 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2286 if (Question == NULL) {\r
8f420676
ED
2287 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2288 break;\r
7936fb6a 2289 }\r
2290\r
2291 Value->Value.b = FALSE;\r
2292 for (Index =0; Index < OpCode->ListLength; Index++) {\r
2293 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
2294 Value->Value.b = TRUE;\r
2295 break;\r
2296 }\r
2297 }\r
2298 break;\r
2299\r
2300 case EFI_IFR_DUP_OP:\r
2301 Status = PopExpression (Value);\r
2302 if (EFI_ERROR (Status)) {\r
2573712e 2303 goto Done;\r
7936fb6a 2304 }\r
2305\r
2306 Status = PushExpression (Value);\r
2307 break;\r
2308\r
2309 case EFI_IFR_QUESTION_REF1_OP:\r
2310 case EFI_IFR_THIS_OP:\r
2311 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2312 if (Question == NULL) {\r
2573712e
LG
2313 Status = EFI_NOT_FOUND;\r
2314 goto Done;\r
7936fb6a 2315 }\r
2316\r
2317 Value = &Question->HiiValue;\r
2318 break;\r
2319\r
cbf73e50 2320 case EFI_IFR_SECURITY_OP:\r
2321 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
2322 break;\r
2323\r
2573712e
LG
2324 case EFI_IFR_GET_OP:\r
2325 //\r
2326 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2327 //\r
2328 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2329 Value->Value.u8 = 0;\r
2330 if (OpCode->VarStorage != NULL) {\r
2331 switch (OpCode->VarStorage->Type) {\r
2332 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2333 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2334 //\r
2335 // Get value from Edit Buffer\r
2336 //\r
2337 Value->Type = OpCode->ValueType;\r
2338 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2339 break;\r
2340 case EFI_HII_VARSTORE_NAME_VALUE:\r
2341 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2342 //\r
2343 // Get value from string except for STRING value.\r
2344 //\r
816a7110 2345 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);\r
2573712e 2346 if (!EFI_ERROR (Status)) {\r
771ececd 2347 ASSERT (StrPtr != NULL);\r
2573712e
LG
2348 TempLength = StrLen (StrPtr);\r
2349 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
2350 Value->Type = OpCode->ValueType;\r
2351 TempBuffer = (UINT8 *) &Value->Value;\r
2352 ZeroMem (TempStr, sizeof (TempStr));\r
2353 for (Index = 0; Index < TempLength; Index ++) {\r
2354 TempStr[0] = StrPtr[TempLength - Index - 1];\r
2355 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
2356 if ((Index & 1) == 0) {\r
2357 TempBuffer [Index/2] = DigitUint8;\r
2358 } else {\r
771ececd 2359 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
2360 }\r
2361 }\r
2362 } \r
2363 }\r
2364 }\r
2365 break;\r
2366 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2367 //\r
2368 // Get value from variable.\r
2369 //\r
2370 TempLength = OpCode->ValueWidth;\r
2371 Value->Type = OpCode->ValueType;\r
2372 Status = gRT->GetVariable (\r
2373 OpCode->ValueName,\r
2374 &OpCode->VarStorage->Guid,\r
2375 NULL,\r
2376 &TempLength,\r
2377 &Value->Value\r
2378 );\r
2379 if (EFI_ERROR (Status)) {\r
2380 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2381 Value->Value.u8 = 0;\r
2382 }\r
cce6230f 2383 break;\r
2573712e
LG
2384 default:\r
2385 //\r
2386 // Not recognize storage.\r
2387 //\r
2388 Status = EFI_UNSUPPORTED;\r
2389 goto Done;\r
2390 }\r
2391 } else {\r
2392 //\r
2393 // For Time/Date Data\r
2394 //\r
2395 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2396 //\r
2397 // Only support Data/Time data when storage doesn't exist.\r
2398 //\r
2399 Status = EFI_UNSUPPORTED;\r
2400 goto Done;\r
2401 }\r
2402 Status = gRT->GetTime (&EfiTime, NULL);\r
2403 if (!EFI_ERROR (Status)) {\r
2404 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2405 switch (OpCode->VarStoreInfo.VarOffset) {\r
2406 case 0x00:\r
2407 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
2408 Value->Value.u16 = EfiTime.Year;\r
2409 break;\r
2410 case 0x02:\r
2411 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2412 Value->Value.u8 = EfiTime.Month;\r
2413 break;\r
2414 case 0x03:\r
2415 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2416 Value->Value.u8 = EfiTime.Day;\r
2417 break;\r
2418 default:\r
2419 //\r
2420 // Invalid Date field.\r
2421 //\r
2422 Status = EFI_INVALID_PARAMETER;\r
2423 goto Done;\r
2424 }\r
2425 } else {\r
2426 switch (OpCode->VarStoreInfo.VarOffset) {\r
2427 case 0x00:\r
2428 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2429 Value->Value.u8 = EfiTime.Hour;\r
2430 break;\r
2431 case 0x01:\r
2432 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2433 Value->Value.u8 = EfiTime.Minute;\r
2434 break;\r
2435 case 0x02:\r
2436 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2437 Value->Value.u8 = EfiTime.Second;\r
2438 break;\r
2439 default:\r
2440 //\r
2441 // Invalid Time field.\r
2442 //\r
2443 Status = EFI_INVALID_PARAMETER;\r
2444 goto Done;\r
2445 }\r
2446 }\r
2447 }\r
2448 }\r
2449\r
2450 break;\r
2451\r
7936fb6a 2452 case EFI_IFR_QUESTION_REF3_OP:\r
db40504e
ED
2453 //\r
2454 // EFI_IFR_QUESTION_REF3\r
2455 // Pop an expression from the expression stack\r
2456 //\r
2457 Status = PopExpression (Value);\r
2458 if (EFI_ERROR (Status)) {\r
2459 goto Done;\r
2460 }\r
2461 \r
2462 //\r
2463 // Validate the expression value\r
2464 //\r
2465 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2466 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2467 break;\r
db40504e
ED
2468 }\r
2469\r
2470 if (OpCode->DevicePath != 0) {\r
80a047f0 2471 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
33efdf51 2472\r
80a047f0
ED
2473 StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
2474 if (StrPtr != NULL && mPathFromText != NULL) {\r
2475 DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);\r
2476 if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {\r
2477 Value = &QuestionVal;\r
2478 }\r
2479 if (DevicePath != NULL) {\r
2480 FreePool (DevicePath);\r
2481 }\r
33efdf51
ED
2482 }\r
2483\r
80a047f0
ED
2484 if (StrPtr != NULL) {\r
2485 FreePool (StrPtr);\r
7936fb6a 2486 }\r
db40504e
ED
2487 } else if (CompareGuid (&OpCode->Guid, &gZeroGuid) != 0) {\r
2488 if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
8f420676
ED
2489 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2490 break;\r
db40504e 2491 }\r
8f420676 2492 Value = &QuestionVal;\r
db40504e 2493 } else {\r
7936fb6a 2494 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2495 if (Question == NULL) {\r
8f420676
ED
2496 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2497 break;\r
7936fb6a 2498 }\r
2499\r
2500 //\r
2501 // push the questions' value on to the expression stack\r
2502 //\r
2503 Value = &Question->HiiValue;\r
7936fb6a 2504 }\r
2505 break;\r
2506\r
2507 case EFI_IFR_RULE_REF_OP:\r
2508 //\r
2509 // Find expression for this rule\r
2510 //\r
2511 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
2512 if (RuleExpression == NULL) {\r
8f420676
ED
2513 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2514 break;\r
7936fb6a 2515 }\r
2516\r
2517 //\r
2518 // Evaluate this rule expression\r
2519 //\r
2520 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
8f420676
ED
2521 if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {\r
2522 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2523 break;\r
7936fb6a 2524 }\r
2525\r
2526 Value = &RuleExpression->Result;\r
2527 break;\r
2528\r
2529 case EFI_IFR_STRING_REF1_OP:\r
2530 Value->Type = EFI_IFR_TYPE_STRING;\r
2531 Value->Value.string = OpCode->Value.Value.string;\r
2532 break;\r
2533\r
2534 //\r
2535 // Constant\r
2536 //\r
2537 case EFI_IFR_TRUE_OP:\r
2538 case EFI_IFR_FALSE_OP:\r
2539 case EFI_IFR_ONE_OP:\r
2540 case EFI_IFR_ONES_OP:\r
2541 case EFI_IFR_UINT8_OP:\r
2542 case EFI_IFR_UINT16_OP:\r
2543 case EFI_IFR_UINT32_OP:\r
2544 case EFI_IFR_UINT64_OP:\r
2545 case EFI_IFR_UNDEFINED_OP:\r
2546 case EFI_IFR_VERSION_OP:\r
2547 case EFI_IFR_ZERO_OP:\r
2548 Value = &OpCode->Value;\r
2549 break;\r
2550\r
2551 //\r
2552 // unary-op\r
2553 //\r
2554 case EFI_IFR_LENGTH_OP:\r
2555 Status = PopExpression (Value);\r
2556 if (EFI_ERROR (Status)) {\r
2573712e 2557 goto Done;\r
7936fb6a 2558 }\r
901ba0e7 2559 if (Value->Type != EFI_IFR_TYPE_STRING && Value->Type != EFI_IFR_TYPE_BUFFER) {\r
8f420676
ED
2560 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2561 break;\r
7936fb6a 2562 }\r
2563\r
901ba0e7
ED
2564 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2565 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2566 if (StrPtr == NULL) {\r
2567 Status = EFI_INVALID_PARAMETER;\r
2568 goto Done;\r
2569 }\r
7936fb6a 2570\r
901ba0e7
ED
2571 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2572 Value->Value.u64 = StrLen (StrPtr);\r
2573 FreePool (StrPtr);\r
2574 } else {\r
2575 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2576 Value->Value.u64 = Value->BufferLen;\r
2577 FreePool (Value->Buffer);\r
2578 }\r
7936fb6a 2579 break;\r
2580\r
2581 case EFI_IFR_NOT_OP:\r
2582 Status = PopExpression (Value);\r
2583 if (EFI_ERROR (Status)) {\r
2573712e 2584 goto Done;\r
7936fb6a 2585 }\r
2586 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
2587 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2588 break;\r
7936fb6a 2589 }\r
2590 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2591 break;\r
2592\r
2593 case EFI_IFR_QUESTION_REF2_OP:\r
2594 //\r
2595 // Pop an expression from the expression stack\r
2596 //\r
2597 Status = PopExpression (Value);\r
2598 if (EFI_ERROR (Status)) {\r
2573712e 2599 goto Done;\r
7936fb6a 2600 }\r
2601\r
2602 //\r
2603 // Validate the expression value\r
2604 //\r
2605 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2606 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2607 break;\r
7936fb6a 2608 }\r
2609\r
2610 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2611 if (Question == NULL) {\r
8f420676
ED
2612 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2613 break;\r
7936fb6a 2614 }\r
2615\r
2616 Value = &Question->HiiValue;\r
2617 break;\r
2618\r
2619 case EFI_IFR_STRING_REF2_OP:\r
2620 //\r
2621 // Pop an expression from the expression stack\r
2622 //\r
2623 Status = PopExpression (Value);\r
2624 if (EFI_ERROR (Status)) {\r
2573712e 2625 goto Done;\r
7936fb6a 2626 }\r
2627\r
2628 //\r
2629 // Validate the expression value\r
2630 //\r
2631 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2632 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2633 break;\r
7936fb6a 2634 }\r
2635\r
2636 Value->Type = EFI_IFR_TYPE_STRING;\r
2637 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2638 if (StrPtr == NULL) {\r
2639 //\r
2640 // If String not exit, push an empty string\r
2641 //\r
2642 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2643 } else {\r
2644 Index = (UINT16) Value->Value.u64;\r
2645 Value->Value.string = Index;\r
f4113e1f 2646 FreePool (StrPtr);\r
7936fb6a 2647 }\r
2648 break;\r
2649\r
2650 case EFI_IFR_TO_BOOLEAN_OP:\r
2651 //\r
2652 // Pop an expression from the expression stack\r
2653 //\r
2654 Status = PopExpression (Value);\r
2655 if (EFI_ERROR (Status)) {\r
2573712e 2656 goto Done;\r
7936fb6a 2657 }\r
2658\r
2659 //\r
2660 // Convert an expression to a Boolean\r
2661 //\r
2662 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
2663 //\r
2664 // When converting from an unsigned integer, zero will be converted to\r
2665 // FALSE and any other value will be converted to TRUE.\r
2666 //\r
4140a663 2667 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);\r
7936fb6a 2668\r
2669 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2670 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2671 //\r
2672 // When converting from a string, if case-insensitive compare\r
2673 // with "true" is True, then push True. If a case-insensitive compare\r
39099cbd 2674 // with "false" is True, then push False. Otherwise, push Undefined. \r
7936fb6a 2675 //\r
2676 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2677 if (StrPtr == NULL) {\r
2573712e
LG
2678 Status = EFI_INVALID_PARAMETER;\r
2679 goto Done;\r
7936fb6a 2680 }\r
39099cbd
ED
2681 \r
2682 IfrStrToUpper (StrPtr);\r
2683 if (StrCmp (StrPtr, L"TRUE") == 0){\r
7936fb6a 2684 Value->Value.b = TRUE;\r
8f420676 2685 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 2686 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
7936fb6a 2687 Value->Value.b = FALSE;\r
8f420676 2688 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 2689 } else {\r
8f420676 2690 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
7936fb6a 2691 }\r
f4113e1f 2692 FreePool (StrPtr);\r
901ba0e7
ED
2693 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
2694 //\r
2695 // When converting from a buffer, if the buffer is all zeroes, \r
2696 // then push False. Otherwise push True. \r
2697 //\r
2698 for (Index =0; Index < Value->BufferLen; Index ++) {\r
2699 if (Value->Buffer[Index] != 0) { \r
2700 break;\r
2701 }\r
2702 }\r
2703\r
2704 if (Index >= Value->BufferLen) {\r
2705 Value->Value.b = FALSE;\r
2706 } else {\r
2707 Value->Value.b = TRUE;\r
2708 }\r
2709 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2710 FreePool (Value->Buffer);\r
7936fb6a 2711 }\r
2712 break;\r
2713\r
2714 case EFI_IFR_TO_STRING_OP:\r
2715 Status = IfrToString (FormSet, OpCode->Format, Value);\r
2716 break;\r
2717\r
2718 case EFI_IFR_TO_UINT_OP:\r
2719 Status = IfrToUint (FormSet, Value);\r
2720 break;\r
2721\r
2722 case EFI_IFR_TO_LOWER_OP:\r
2723 case EFI_IFR_TO_UPPER_OP:\r
2724 Status = InitializeUnicodeCollationProtocol ();\r
2725 if (EFI_ERROR (Status)) {\r
2573712e 2726 goto Done;\r
7936fb6a 2727 }\r
2728\r
2729 Status = PopExpression (Value);\r
2730 if (EFI_ERROR (Status)) {\r
2573712e 2731 goto Done;\r
7936fb6a 2732 }\r
2733\r
2734 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
8f420676
ED
2735 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2736 break;\r
7936fb6a 2737 }\r
2738\r
2739 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2740 if (StrPtr == NULL) {\r
2573712e
LG
2741 Status = EFI_NOT_FOUND;\r
2742 goto Done;\r
7936fb6a 2743 }\r
2744\r
2745 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
2746 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
2747 } else {\r
2748 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
2749 }\r
2750 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 2751 FreePool (StrPtr);\r
7936fb6a 2752 break;\r
2753\r
2754 case EFI_IFR_BITWISE_NOT_OP:\r
2755 //\r
2756 // Pop an expression from the expression stack\r
2757 //\r
2758 Status = PopExpression (Value);\r
2759 if (EFI_ERROR (Status)) {\r
2573712e 2760 goto Done;\r
7936fb6a 2761 }\r
2762 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
2763 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2764 break;\r
7936fb6a 2765 }\r
2766\r
2767 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2768 Value->Value.u64 = ~Value->Value.u64;\r
2769 break;\r
2770\r
2573712e
LG
2771 case EFI_IFR_SET_OP:\r
2772 //\r
2773 // Pop an expression from the expression stack\r
2774 //\r
2775 Status = PopExpression (Value);\r
2776 if (EFI_ERROR (Status)) {\r
2777 goto Done;\r
2778 }\r
2779 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
2780 Data1.Value.b = FALSE;\r
2781 //\r
2782 // Set value to var storage buffer\r
2783 //\r
2784 if (OpCode->VarStorage != NULL) {\r
2785 switch (OpCode->VarStorage->Type) {\r
2786 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2787 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2788 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
2789 Data1.Value.b = TRUE;\r
2790 break;\r
2791 case EFI_HII_VARSTORE_NAME_VALUE:\r
2792 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2793 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
2794 ASSERT (Value != NULL);\r
2795 //\r
2796 // Convert Buffer to Hex String\r
2797 //\r
2798 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
2799 StrPtr = NameValue;\r
2800 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
2801 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
2802 }\r
7c6c064c 2803 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
2573712e
LG
2804 FreePool (NameValue);\r
2805 if (!EFI_ERROR (Status)) {\r
2806 Data1.Value.b = TRUE;\r
2807 }\r
2808 }\r
2809 break;\r
2810 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2811 Status = gRT->SetVariable (\r
2812 OpCode->ValueName,\r
2813 &OpCode->VarStorage->Guid,\r
2814 OpCode->VarStorage->Attributes,\r
2815 OpCode->ValueWidth,\r
2816 &Value->Value\r
2817 );\r
2818 if (!EFI_ERROR (Status)) {\r
2819 Data1.Value.b = TRUE;\r
2820 }\r
2821 break;\r
2822 default:\r
2823 //\r
2824 // Not recognize storage.\r
2825 //\r
2826 Status = EFI_UNSUPPORTED;\r
2827 goto Done;\r
2828 break;\r
2829 }\r
2830 } else {\r
2831 //\r
2832 // For Time/Date Data\r
2833 //\r
2834 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2835 //\r
2836 // Only support Data/Time data when storage doesn't exist.\r
2837 //\r
2838 Status = EFI_UNSUPPORTED;\r
2839 goto Done;\r
2840 }\r
2841 Status = gRT->GetTime (&EfiTime, NULL);\r
2842 if (!EFI_ERROR (Status)) {\r
2843 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2844 switch (OpCode->VarStoreInfo.VarOffset) {\r
2845 case 0x00:\r
2846 EfiTime.Year = Value->Value.u16;\r
2847 break;\r
2848 case 0x02:\r
2849 EfiTime.Month = Value->Value.u8;\r
2850 break;\r
2851 case 0x03:\r
2852 EfiTime.Day = Value->Value.u8;\r
2853 break;\r
2854 default:\r
2855 //\r
2856 // Invalid Date field.\r
2857 //\r
2858 Status = EFI_INVALID_PARAMETER;\r
2859 goto Done;\r
2860 }\r
2861 } else {\r
2862 switch (OpCode->VarStoreInfo.VarOffset) {\r
2863 case 0x00:\r
2864 EfiTime.Hour = Value->Value.u8;\r
2865 break;\r
2866 case 0x01:\r
2867 EfiTime.Minute = Value->Value.u8;\r
2868 break;\r
2869 case 0x02:\r
2870 EfiTime.Second = Value->Value.u8;\r
2871 break;\r
2872 default:\r
2873 //\r
2874 // Invalid Time field.\r
2875 //\r
2876 Status = EFI_INVALID_PARAMETER;\r
2877 goto Done;\r
2878 }\r
2879 }\r
2880 Status = gRT->SetTime (&EfiTime);\r
2881 if (!EFI_ERROR (Status)) {\r
2882 Data1.Value.b = TRUE;\r
2883 }\r
2884 }\r
2885 }\r
2886 Value = &Data1;\r
2887 break;\r
2888\r
7936fb6a 2889 //\r
2890 // binary-op\r
2891 //\r
2892 case EFI_IFR_ADD_OP:\r
2893 case EFI_IFR_SUBTRACT_OP:\r
2894 case EFI_IFR_MULTIPLY_OP:\r
2895 case EFI_IFR_DIVIDE_OP:\r
2896 case EFI_IFR_MODULO_OP:\r
2897 case EFI_IFR_BITWISE_AND_OP:\r
2898 case EFI_IFR_BITWISE_OR_OP:\r
2899 case EFI_IFR_SHIFT_LEFT_OP:\r
2900 case EFI_IFR_SHIFT_RIGHT_OP:\r
2901 //\r
2902 // Pop an expression from the expression stack\r
2903 //\r
2904 Status = PopExpression (&Data2);\r
2905 if (EFI_ERROR (Status)) {\r
2573712e 2906 goto Done;\r
7936fb6a 2907 }\r
7936fb6a 2908\r
2909 //\r
2910 // Pop another expression from the expression stack\r
2911 //\r
2912 Status = PopExpression (&Data1);\r
2913 if (EFI_ERROR (Status)) {\r
2573712e 2914 goto Done;\r
7936fb6a 2915 }\r
8f420676
ED
2916\r
2917 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
2918 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2919 break;\r
2920 }\r
2921\r
2922\r
7936fb6a 2923 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
2924 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2925 break;\r
7936fb6a 2926 }\r
2927\r
2928 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2929\r
2930 switch (OpCode->Operand) {\r
2931 case EFI_IFR_ADD_OP:\r
2932 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
2933 break;\r
2934\r
2935 case EFI_IFR_SUBTRACT_OP:\r
2936 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
2937 break;\r
2938\r
2939 case EFI_IFR_MULTIPLY_OP:\r
2940 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2941 break;\r
2942\r
2943 case EFI_IFR_DIVIDE_OP:\r
2944 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2945 break;\r
2946\r
2947 case EFI_IFR_MODULO_OP:\r
2948 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
2949 Value->Value.u64 = TempValue;\r
2950 break;\r
2951\r
2952 case EFI_IFR_BITWISE_AND_OP:\r
2953 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
2954 break;\r
2955\r
2956 case EFI_IFR_BITWISE_OR_OP:\r
2957 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
2958 break;\r
2959\r
2960 case EFI_IFR_SHIFT_LEFT_OP:\r
2961 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2962 break;\r
2963\r
2964 case EFI_IFR_SHIFT_RIGHT_OP:\r
2965 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2966 break;\r
2967\r
2968 default:\r
2969 break;\r
2970 }\r
2971 break;\r
2972\r
2973 case EFI_IFR_AND_OP:\r
2974 case EFI_IFR_OR_OP:\r
2975 //\r
2976 // Two Boolean operator\r
2977 //\r
2978 Status = PopExpression (&Data2);\r
2979 if (EFI_ERROR (Status)) {\r
2573712e 2980 goto Done;\r
7936fb6a 2981 }\r
7936fb6a 2982\r
2983 //\r
2984 // Pop another expression from the expression stack\r
2985 //\r
2986 Status = PopExpression (&Data1);\r
2987 if (EFI_ERROR (Status)) {\r
2573712e 2988 goto Done;\r
7936fb6a 2989 }\r
8f420676
ED
2990\r
2991 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2992 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2993 break;\r
2994 }\r
2995\r
7936fb6a 2996 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
2997 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2998 break;\r
7936fb6a 2999 }\r
3000\r
3001 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
3002 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
3003 } else {\r
3004 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
3005 }\r
3006 break;\r
3007\r
3008 case EFI_IFR_EQUAL_OP:\r
3009 case EFI_IFR_NOT_EQUAL_OP:\r
3010 case EFI_IFR_GREATER_EQUAL_OP:\r
3011 case EFI_IFR_GREATER_THAN_OP:\r
3012 case EFI_IFR_LESS_EQUAL_OP:\r
3013 case EFI_IFR_LESS_THAN_OP:\r
3014 //\r
3015 // Compare two integer, string, boolean or date/time\r
3016 //\r
3017 Status = PopExpression (&Data2);\r
3018 if (EFI_ERROR (Status)) {\r
2573712e 3019 goto Done;\r
7936fb6a 3020 }\r
7936fb6a 3021\r
3022 //\r
3023 // Pop another expression from the expression stack\r
3024 //\r
3025 Status = PopExpression (&Data1);\r
3026 if (EFI_ERROR (Status)) {\r
2573712e 3027 goto Done;\r
7936fb6a 3028 }\r
3029\r
8f420676
ED
3030 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
3031 Data2.Type != EFI_IFR_TYPE_STRING && \r
3032 Data2.Type != EFI_IFR_TYPE_BUFFER) {\r
3033 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3034 break;\r
3035 }\r
3036\r
3037 if (Data1.Type > EFI_IFR_TYPE_BOOLEAN && \r
3038 Data1.Type != EFI_IFR_TYPE_STRING && \r
3039 Data1.Type != EFI_IFR_TYPE_BUFFER) {\r
3040 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3041 break;\r
3042 }\r
3043\r
3044 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
901ba0e7
ED
3045 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
3046 FreePool (Data1.Buffer);\r
3047 FreePool (Data2.Buffer);\r
3048 }\r
3049 \r
8f420676
ED
3050 if (Status == EFI_UNSUPPORTED) {\r
3051 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3052 Status = EFI_SUCCESS;\r
3053 break;\r
3054 }\r
3055\r
3056 if (EFI_ERROR (Status)) {\r
2573712e 3057 goto Done;\r
7936fb6a 3058 }\r
3059\r
3060 switch (OpCode->Operand) {\r
3061 case EFI_IFR_EQUAL_OP:\r
3062 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
3063 break;\r
3064\r
3065 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 3066 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 3067 break;\r
3068\r
3069 case EFI_IFR_GREATER_EQUAL_OP:\r
3070 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
3071 break;\r
3072\r
3073 case EFI_IFR_GREATER_THAN_OP:\r
3074 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
3075 break;\r
3076\r
3077 case EFI_IFR_LESS_EQUAL_OP:\r
3078 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
3079 break;\r
3080\r
3081 case EFI_IFR_LESS_THAN_OP:\r
3082 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
3083 break;\r
3084\r
3085 default:\r
3086 break;\r
3087 }\r
3088 break;\r
3089\r
3090 case EFI_IFR_MATCH_OP:\r
20258293
ED
3091 Status = InitializeUnicodeCollationProtocol ();\r
3092 if (EFI_ERROR (Status)) {\r
3093 goto Done;\r
3094 }\r
3095 \r
7936fb6a 3096 Status = IfrMatch (FormSet, Value);\r
3097 break;\r
3098\r
3099 case EFI_IFR_CATENATE_OP:\r
3100 Status = IfrCatenate (FormSet, Value);\r
3101 break;\r
3102\r
3103 //\r
3104 // ternary-op\r
3105 //\r
3106 case EFI_IFR_CONDITIONAL_OP:\r
3107 //\r
3108 // Pop third expression from the expression stack\r
3109 //\r
3110 Status = PopExpression (&Data3);\r
3111 if (EFI_ERROR (Status)) {\r
2573712e 3112 goto Done;\r
7936fb6a 3113 }\r
3114\r
3115 //\r
3116 // Pop second expression from the expression stack\r
3117 //\r
3118 Status = PopExpression (&Data2);\r
3119 if (EFI_ERROR (Status)) {\r
2573712e 3120 goto Done;\r
7936fb6a 3121 }\r
3122\r
3123 //\r
3124 // Pop first expression from the expression stack\r
3125 //\r
3126 Status = PopExpression (&Data1);\r
3127 if (EFI_ERROR (Status)) {\r
2573712e 3128 goto Done;\r
7936fb6a 3129 }\r
3130 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3131 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3132 break;\r
7936fb6a 3133 }\r
3134\r
3135 if (Data1.Value.b) {\r
3136 Value = &Data3;\r
3137 } else {\r
3138 Value = &Data2;\r
3139 }\r
3140 break;\r
3141\r
3142 case EFI_IFR_FIND_OP:\r
3143 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3144 break;\r
3145\r
3146 case EFI_IFR_MID_OP:\r
3147 Status = IfrMid (FormSet, Value);\r
3148 break;\r
3149\r
3150 case EFI_IFR_TOKEN_OP:\r
3151 Status = IfrToken (FormSet, Value);\r
3152 break;\r
3153\r
3154 case EFI_IFR_SPAN_OP:\r
3155 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3156 break;\r
3157\r
2573712e
LG
3158 case EFI_IFR_MAP_OP:\r
3159 //\r
3160 // Pop the check value\r
3161 //\r
3162 Status = PopExpression (&Data1);\r
3163 if (EFI_ERROR (Status)) {\r
3164 goto Done;\r
3165 }\r
3166 //\r
3167 // Check MapExpression list is valid.\r
3168 //\r
3169 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
3170 Status = EFI_INVALID_PARAMETER;\r
3171 goto Done;\r
3172 }\r
3173 //\r
3174 // Go through map expression list.\r
3175 //\r
3176 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
3177 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3178 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3179 //\r
3180 // Evaluate the first expression in this pair.\r
3181 //\r
3182 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3183 if (EFI_ERROR (Status)) {\r
3184 goto Done;\r
3185 }\r
3186 //\r
3187 // Compare the expression value with current value\r
3188 //\r
8f420676 3189 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
2573712e
LG
3190 //\r
3191 // Try get the map value.\r
3192 //\r
3193 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3194 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3195 Status = EFI_INVALID_PARAMETER;\r
3196 goto Done;\r
3197 }\r
3198 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3199 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3200 if (EFI_ERROR (Status)) {\r
3201 goto Done;\r
3202 }\r
3203 Value = &SubExpression->Result;\r
3204 break;\r
3205 }\r
3206 //\r
3207 // Skip the second expression on this pair.\r
3208 //\r
3209 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3210 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3211 Status = EFI_INVALID_PARAMETER;\r
3212 goto Done;\r
3213 }\r
3214 //\r
3215 // Goto the first expression on next pair.\r
3216 //\r
3217 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3218 }\r
3219\r
3220 //\r
3221 // No map value is found.\r
3222 //\r
3223 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3224 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3225 Value->Value.u8 = 0;\r
3226 }\r
3227 break;\r
3228\r
7936fb6a 3229 default:\r
3230 break;\r
3231 }\r
8f420676 3232 if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
2573712e 3233 goto Done;\r
7936fb6a 3234 }\r
3235\r
3236 Status = PushExpression (Value);\r
3237 if (EFI_ERROR (Status)) {\r
2573712e 3238 goto Done;\r
7936fb6a 3239 }\r
3240 }\r
3241\r
3242 //\r
3243 // Pop the final result from expression stack\r
3244 //\r
3245 Value = &Data1;\r
3246 Status = PopExpression (Value);\r
3247 if (EFI_ERROR (Status)) {\r
2573712e 3248 goto Done;\r
7936fb6a 3249 }\r
3250\r
3251 //\r
3252 // After evaluating an expression, there should be only one value left on the expression stack\r
3253 //\r
3254 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 3255 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 3256 }\r
3257\r
2573712e
LG
3258Done:\r
3259 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3260 if (!EFI_ERROR (Status)) {\r
3261 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3262 }\r
7936fb6a 3263\r
2573712e 3264 return Status;\r
7936fb6a 3265}\r
31585af4
ED
3266\r
3267/**\r
3268 Return the result of the expression list. Check the expression list and \r
3269 return the highest priority express result. \r
3270 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
3271\r
3272 @param ExpList The input expression list.\r
3273 @param Evaluate Whether need to evaluate the expression first.\r
3274 @param FormSet FormSet associated with this expression.\r
3275 @param Form Form associated with this expression. \r
3276\r
3277 @retval EXPRESS_RESULT Return the higher priority express result. \r
3278 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3279\r
3280**/\r
3281EXPRESS_RESULT \r
3282EvaluateExpressionList (\r
3283 IN FORM_EXPRESSION_LIST *ExpList,\r
3284 IN BOOLEAN Evaluate,\r
3285 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
3286 IN FORM_BROWSER_FORM *Form OPTIONAL\r
3287 )\r
3288{\r
3289 UINTN Index;\r
3290 EXPRESS_RESULT ReturnVal;\r
3291 EXPRESS_RESULT CompareOne;\r
3292 EFI_STATUS Status;\r
3293\r
3294 if (ExpList == NULL) {\r
3295 return ExpressFalse;\r
3296 }\r
3297\r
3298 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3299 Index = 0;\r
3300\r
3301 //\r
3302 // Check whether need to evaluate the expression first.\r
3303 //\r
3304 if (Evaluate) { \r
3305 while (ExpList->Count > Index) {\r
3306 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
3307 if (EFI_ERROR (Status)) {\r
3308 return ExpressFalse;\r
3309 }\r
3310 }\r
3311 }\r
3312\r
3313 //\r
3314 // Run the list of expressions.\r
3315 //\r
3316 ReturnVal = ExpressFalse;\r
3317 for (Index = 0; Index < ExpList->Count; Index++) {\r
3318 if (ExpList->Expression[Index]->Result.Type == EFI_IFR_TYPE_BOOLEAN &&\r
3319 ExpList->Expression[Index]->Result.Value.b) {\r
3320 switch (ExpList->Expression[Index]->Type) {\r
3321 case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
3322 CompareOne = ExpressSuppress;\r
3323 break;\r
3324\r
3325 case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
3326 CompareOne = ExpressGrayOut;\r
3327 break;\r
3328\r
3329 case EFI_HII_EXPRESSION_DISABLE_IF:\r
3330 CompareOne = ExpressDisable;\r
3331 break;\r
3332\r
3333 default:\r
3334 return ExpressFalse; \r
3335 }\r
3336\r
3337 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3338 }\r
3339 }\r
3340 \r
3341 return ReturnVal;\r
3342}\r