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