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