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