]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/FCE/Expression.c
Revert "BaseTools/FMMT: Add a tool FMMT"
[mirror_edk2.git] / BaseTools / Source / C / FCE / Expression.c
CommitLineData
3c59d946
SZ
1/** @file\r
2\r
3 Utility functions for expression evaluation.\r
4\r
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "IfrParse.h"\r
11\r
12#define gEmptyString L""\r
13//\r
14// Global stack used to evaluate boolean expresions\r
15//\r
16EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
17EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
18EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
19\r
20EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
21EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
22EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
23UINTN mExpressionEvaluationStackOffset = 0;\r
24\r
25EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
26EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
27EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
28\r
29EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
30EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
31EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
32\r
33/**\r
34 Get Value for given Name from a NameValue Storage.\r
35\r
36 @param Storage The NameValue Storage.\r
37 @param Name The Name.\r
38 @param Value The retured Value.\r
39\r
40 @retval EFI_SUCCESS Value found for given Name.\r
41 @retval EFI_NOT_FOUND No such Name found in NameValue storage.\r
42\r
43**/\r
44EFI_STATUS\r
45GetValueByName (\r
46 IN FORMSET_STORAGE *Storage,\r
47 IN CHAR16 *Name,\r
48 IN OUT CHAR16 **Value\r
49 )\r
50{\r
51 LIST_ENTRY *Link;\r
52 NAME_VALUE_NODE *Node;\r
53\r
54 *Value = NULL;\r
55\r
56 Link = GetFirstNode (&Storage->NameValueListHead);\r
57 while (!IsNull (&Storage->NameValueListHead, Link)) {\r
58 Node = NAME_VALUE_NODE_FROM_LINK (Link);\r
59\r
60 if (FceStrCmp (Name, Node->Name) == 0) {\r
61 NewStringCpy (Value, Node->EditValue);\r
62 return EFI_SUCCESS;\r
63 }\r
64\r
65 Link = GetNextNode (&Storage->NameValueListHead, Link);\r
66 }\r
67\r
68 return EFI_NOT_FOUND;\r
69}\r
70\r
71/**\r
72 Grow size of the stack.\r
73\r
74 This is an internal function.\r
75\r
76 @param Stack On input: old stack; On output: new stack\r
77 @param StackPtr On input: old stack pointer; On output: new stack\r
78 pointer\r
79 @param StackEnd On input: old stack end; On output: new stack end\r
80\r
81 @retval EFI_SUCCESS Grow stack success.\r
82 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
83\r
84**/\r
85EFI_STATUS\r
86GrowStack (\r
87 IN OUT EFI_HII_VALUE **Stack,\r
88 IN OUT EFI_HII_VALUE **StackPtr,\r
89 IN OUT EFI_HII_VALUE **StackEnd\r
90 )\r
91{\r
92 UINTN Size;\r
93 EFI_HII_VALUE *NewStack;\r
94\r
95 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
96 if (*StackPtr != NULL) {\r
97 Size = Size + (*StackEnd - *Stack);\r
98 }\r
99\r
100 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
101 if (NewStack == NULL) {\r
102 return EFI_OUT_OF_RESOURCES;\r
103 }\r
104\r
105 if (*StackPtr != NULL) {\r
106 //\r
107 // Copy from Old Stack to the New Stack\r
108 //\r
109 CopyMem (\r
110 NewStack,\r
111 *Stack,\r
112 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
113 );\r
114\r
115 //\r
116 // Free The Old Stack\r
117 //\r
118 FreePool (*Stack);\r
119 }\r
120\r
121 //\r
122 // Make the Stack pointer point to the old data in the new stack\r
123 //\r
124 *StackPtr = NewStack + (*StackPtr - *Stack);\r
125 *Stack = NewStack;\r
126 *StackEnd = NewStack + Size;\r
127\r
128 return EFI_SUCCESS;\r
129}\r
130\r
131\r
132/**\r
133 Push an element onto the Boolean Stack.\r
134\r
135 @param Stack On input: old stack; On output: new stack\r
136 @param StackPtr On input: old stack pointer; On output: new stack\r
137 pointer\r
138 @param StackEnd On input: old stack end; On output: new stack end\r
139 @param Data Data to push.\r
140\r
141 @retval EFI_SUCCESS Push stack success.\r
142\r
143**/\r
144EFI_STATUS\r
145PushStack (\r
146 IN OUT EFI_HII_VALUE **Stack,\r
147 IN OUT EFI_HII_VALUE **StackPtr,\r
148 IN OUT EFI_HII_VALUE **StackEnd,\r
149 IN EFI_HII_VALUE *Data\r
150 )\r
151{\r
152 EFI_STATUS Status;\r
153\r
154 //\r
155 // Check for a stack overflow condition\r
156 //\r
157 if (*StackPtr >= *StackEnd) {\r
158 //\r
159 // Grow the stack\r
160 //\r
161 Status = GrowStack (Stack, StackPtr, StackEnd);\r
162 if (EFI_ERROR (Status)) {\r
163 return Status;\r
164 }\r
165 }\r
166\r
167 //\r
168 // Push the item onto the stack\r
169 //\r
170 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
171 *StackPtr = *StackPtr + 1;\r
172\r
173 return EFI_SUCCESS;\r
174}\r
175\r
176\r
177/**\r
178 Pop an element from the stack.\r
179\r
180 @param Stack On input: old stack\r
181 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
182 @param Data Data to pop.\r
183\r
184 @retval EFI_SUCCESS The value was popped onto the stack.\r
185 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
186\r
187**/\r
188EFI_STATUS\r
189PopStack (\r
190 IN EFI_HII_VALUE *Stack,\r
191 IN OUT EFI_HII_VALUE **StackPtr,\r
192 OUT EFI_HII_VALUE *Data\r
193 )\r
194{\r
195 //\r
196 // Check for a stack underflow condition\r
197 //\r
198 if (*StackPtr == Stack) {\r
199 return EFI_ACCESS_DENIED;\r
200 }\r
201\r
202 //\r
203 // Pop the item off the stack\r
204 //\r
205 *StackPtr = *StackPtr - 1;\r
206 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
207 return EFI_SUCCESS;\r
208}\r
209\r
210\r
211/**\r
212 Reset stack pointer to begin of the stack.\r
213\r
214**/\r
215VOID\r
216ResetCurrentExpressionStack (\r
217 VOID\r
218 )\r
219{\r
220 mCurrentExpressionPointer = mCurrentExpressionStack;\r
221}\r
222\r
223\r
224/**\r
225 Push current expression onto the Stack\r
226\r
227 @param Pointer Pointer to current expression.\r
228\r
229 @retval EFI_SUCCESS The value was pushed onto the stack.\r
230 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
231\r
232**/\r
233EFI_STATUS\r
234PushCurrentExpression (\r
235 IN VOID *Pointer\r
236 )\r
237{\r
238 EFI_HII_VALUE Data;\r
239\r
240 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
241 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
242\r
243 return PushStack (\r
244 &mCurrentExpressionStack,\r
245 &mCurrentExpressionPointer,\r
246 &mCurrentExpressionEnd,\r
247 &Data\r
248 );\r
249}\r
250\r
251\r
252/**\r
253 Pop current expression from the Stack\r
254\r
255 @param Pointer Pointer to current expression to be pop.\r
256\r
257 @retval EFI_SUCCESS The value was pushed onto the stack.\r
258 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
259\r
260**/\r
261EFI_STATUS\r
262PopCurrentExpression (\r
263 OUT VOID **Pointer\r
264 )\r
265{\r
266 EFI_STATUS Status;\r
267 EFI_HII_VALUE Data;\r
268\r
269 Status = PopStack (\r
270 mCurrentExpressionStack,\r
271 &mCurrentExpressionPointer,\r
272 &Data\r
273 );\r
274\r
275 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
276\r
277 return Status;\r
278}\r
279\r
280/**\r
281 Reset stack pointer to begin of the stack.\r
282\r
283**/\r
284VOID\r
285ResetMapExpressionListStack (\r
286 VOID\r
287 )\r
288{\r
289 mMapExpressionListPointer = mMapExpressionListStack;\r
290}\r
291\r
292\r
293/**\r
294 Push the list of map expression onto the Stack\r
295\r
296 @param Pointer Pointer to the list of map expression to be pushed.\r
297\r
298 @retval EFI_SUCCESS The value was pushed onto the stack.\r
299 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
300\r
301**/\r
302EFI_STATUS\r
303PushMapExpressionList (\r
304 IN VOID *Pointer\r
305 )\r
306{\r
307 EFI_HII_VALUE Data;\r
308\r
309 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
310 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
311\r
312 return PushStack (\r
313 &mMapExpressionListStack,\r
314 &mMapExpressionListPointer,\r
315 &mMapExpressionListEnd,\r
316 &Data\r
317 );\r
318}\r
319\r
320\r
321/**\r
322 Pop the list of map expression from the Stack\r
323\r
324 @param Pointer Pointer to the list of map expression to be pop.\r
325\r
326 @retval EFI_SUCCESS The value was pushed onto the stack.\r
327 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
328\r
329**/\r
330EFI_STATUS\r
331PopMapExpressionList (\r
332 OUT VOID **Pointer\r
333 )\r
334{\r
335 EFI_STATUS Status;\r
336 EFI_HII_VALUE Data;\r
337\r
338 Status = PopStack (\r
339 mMapExpressionListStack,\r
340 &mMapExpressionListPointer,\r
341 &Data\r
342 );\r
343\r
344 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
345\r
346 return Status;\r
347}\r
348\r
349/**\r
350 Reset stack pointer to begin of the stack.\r
351\r
352**/\r
353VOID\r
354ResetScopeStack (\r
355 VOID\r
356 )\r
357{\r
358 mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
359}\r
360\r
361\r
362/**\r
363 Push an Operand onto the Stack\r
364\r
365 @param Operand Operand to push.\r
366\r
367 @retval EFI_SUCCESS The value was pushed onto the stack.\r
368 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
369 stack.\r
370\r
371**/\r
372EFI_STATUS\r
373PushScope (\r
374 IN UINT8 Operand\r
375 )\r
376{\r
377 EFI_HII_VALUE Data;\r
378\r
379 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
380 Data.Value.u8 = Operand;\r
381\r
382 return PushStack (\r
383 &mOpCodeScopeStack,\r
384 &mOpCodeScopeStackPointer,\r
385 &mOpCodeScopeStackEnd,\r
386 &Data\r
387 );\r
388}\r
389\r
390\r
391/**\r
392 Pop an Operand from the Stack\r
393\r
394 @param Operand Operand to pop.\r
395\r
396 @retval EFI_SUCCESS The value was pushed onto the stack.\r
397 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
398 stack.\r
399\r
400**/\r
401EFI_STATUS\r
402PopScope (\r
403 OUT UINT8 *Operand\r
404 )\r
405{\r
406 EFI_STATUS Status;\r
407 EFI_HII_VALUE Data;\r
408\r
409 Status = PopStack (\r
410 mOpCodeScopeStack,\r
411 &mOpCodeScopeStackPointer,\r
412 &Data\r
413 );\r
414\r
415 *Operand = Data.Value.u8;\r
416\r
417 return Status;\r
418}\r
419\r
420\r
421/**\r
422 Push an Expression value onto the Stack\r
423\r
424 @param Value Expression value to push.\r
425\r
426 @retval EFI_SUCCESS The value was pushed onto the stack.\r
427 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
428 stack.\r
429\r
430**/\r
431EFI_STATUS\r
432PushExpression (\r
433 IN EFI_HII_VALUE *Value\r
434 )\r
435{\r
436 return PushStack (\r
437 &mExpressionEvaluationStack,\r
438 &mExpressionEvaluationStackPointer,\r
439 &mExpressionEvaluationStackEnd,\r
440 Value\r
441 );\r
442}\r
443\r
444\r
445/**\r
446 Pop an Expression value from the stack.\r
447\r
448 @param Value Expression value to pop.\r
449\r
450 @retval EFI_SUCCESS The value was popped onto the stack.\r
451 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
452\r
453**/\r
454EFI_STATUS\r
455PopExpression (\r
456 OUT EFI_HII_VALUE *Value\r
457 )\r
458{\r
459 return PopStack (\r
460 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
461 &mExpressionEvaluationStackPointer,\r
462 Value\r
463 );\r
464}\r
465\r
466/**\r
467 Get current stack offset from stack start.\r
468\r
469 @return Stack offset to stack start.\r
470**/\r
471UINTN\r
472SaveExpressionEvaluationStackOffset (\r
473 )\r
474{\r
475 UINTN TempStackOffset;\r
476 TempStackOffset = mExpressionEvaluationStackOffset;\r
477 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
478 return TempStackOffset;\r
479}\r
480\r
481/**\r
482 Restore stack offset based on input stack offset\r
483\r
484 @param StackOffset Offset to stack start.\r
485\r
486**/\r
487VOID\r
488RestoreExpressionEvaluationStackOffset (\r
489 UINTN StackOffset\r
490 )\r
491{\r
492 mExpressionEvaluationStackOffset = StackOffset;\r
493}\r
494\r
495\r
496/**\r
497 Search a Question in Form scope using its QuestionId.\r
498\r
499 @param Form The form which contains this Question.\r
500 @param QuestionId Id of this Question.\r
501\r
502 @retval Pointer The Question.\r
503 @retval NULL Specified Question not found in the form.\r
504\r
505**/\r
506FORM_BROWSER_STATEMENT *\r
507IdToQuestion2 (\r
508 IN FORM_BROWSER_FORM *Form,\r
509 IN UINT16 QuestionId\r
510 )\r
511{\r
512 LIST_ENTRY *Link;\r
513 FORM_BROWSER_STATEMENT *Question;\r
514\r
515 if (QuestionId == 0) {\r
516 //\r
517 // The value of zero is reserved\r
518 //\r
519 return NULL;\r
520 }\r
521\r
522 Link = GetFirstNode (&Form->StatementListHead);\r
523 while (!IsNull (&Form->StatementListHead, Link)) {\r
524 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
525\r
526 if (Question->QuestionId == QuestionId) {\r
527 return Question;\r
528 }\r
529\r
530 Link = GetNextNode (&Form->StatementListHead, Link);\r
531 }\r
532\r
533 return NULL;\r
534}\r
535\r
536\r
537/**\r
538 Search a Question in Formset scope using its QuestionId.\r
539\r
540 @param FormSet The formset which contains this form.\r
541 @param Form The form which contains this Question.\r
542 @param QuestionId Id of this Question.\r
543\r
544 @retval Pointer The Question.\r
545 @retval NULL Specified Question not found in the form.\r
546\r
547**/\r
548FORM_BROWSER_STATEMENT *\r
549IdToQuestion (\r
550 IN FORM_BROWSER_FORMSET *FormSet,\r
551 IN FORM_BROWSER_FORM *Form,\r
552 IN UINT16 QuestionId\r
553 )\r
554{\r
555 LIST_ENTRY *Link;\r
556 FORM_BROWSER_STATEMENT *Question;\r
557\r
558 //\r
559 // Search in the form scope first\r
560 //\r
561 Question = IdToQuestion2 (Form, QuestionId);\r
562 if (Question != NULL) {\r
563 return Question;\r
564 }\r
565\r
566 //\r
567 // Search in the formset scope\r
568 //\r
569 Link = GetFirstNode (&FormSet->FormListHead);\r
570 while (!IsNull (&FormSet->FormListHead, Link)) {\r
571 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
572\r
573 Question = IdToQuestion2 (Form, QuestionId);\r
574 if (Question != NULL) {\r
575 return Question;\r
576 }\r
577\r
578 Link = GetNextNode (&FormSet->FormListHead, Link);\r
579 }\r
580\r
581 return NULL;\r
582}\r
583\r
584\r
585/**\r
586 Get Expression given its RuleId.\r
587\r
588 @param Form The form which contains this Expression.\r
589 @param RuleId Id of this Expression.\r
590\r
591 @retval Pointer The Expression.\r
592 @retval NULL Specified Expression not found in the form.\r
593\r
594**/\r
595FORM_EXPRESSION *\r
596RuleIdToExpression (\r
597 IN FORM_BROWSER_FORM *Form,\r
598 IN UINT8 RuleId\r
599 )\r
600{\r
601 LIST_ENTRY *Link;\r
602 FORM_EXPRESSION *Expression;\r
603\r
604 Link = GetFirstNode (&Form->ExpressionListHead);\r
605 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
606 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
607\r
608 if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression->RuleId == RuleId)) {\r
609 return Expression;\r
610 }\r
611\r
612 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
613 }\r
614\r
615 return NULL;\r
616}\r
617\r
618/**\r
619 Convert the input Unicode character to upper.\r
620\r
621 @param String Th Unicode character to be converted.\r
622\r
623**/\r
624VOID\r
625IfrStrToUpper (\r
626 IN CHAR16 *String\r
627 )\r
628{\r
629 while (*String != 0) {\r
630 if ((*String >= 'a') && (*String <= 'z')) {\r
631 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
632 }\r
633 String++;\r
634 }\r
635}\r
636\r
637/**\r
638 Evaluate opcode EFI_IFR_TO_STRING.\r
639\r
640 @param FormSet Formset which contains this opcode.\r
641 @param Format String format in EFI_IFR_TO_STRING.\r
642 @param Result Evaluation result for this opcode.\r
643\r
644 @retval EFI_SUCCESS Opcode evaluation success.\r
645 @retval Other Opcode evaluation failed.\r
646\r
647**/\r
648EFI_STATUS\r
649IfrToString (\r
650 IN FORM_BROWSER_FORMSET *FormSet,\r
651 IN UINT8 Format,\r
652 OUT EFI_HII_VALUE *Result\r
653 )\r
654{\r
655 EFI_STATUS Status;\r
656 EFI_HII_VALUE Value;\r
657 CHAR16 *PrintFormat;\r
658 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
659 UINTN BufferSize;\r
660\r
661 Status = PopExpression (&Value);\r
662 if (EFI_ERROR (Status)) {\r
663 return Status;\r
664 }\r
665\r
666 switch (Value.Type) {\r
667 case EFI_IFR_TYPE_NUM_SIZE_8:\r
668 case EFI_IFR_TYPE_NUM_SIZE_16:\r
669 case EFI_IFR_TYPE_NUM_SIZE_32:\r
670 case EFI_IFR_TYPE_NUM_SIZE_64:\r
671 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
672 switch (Format) {\r
673 case EFI_IFR_STRING_UNSIGNED_DEC:\r
674 case EFI_IFR_STRING_SIGNED_DEC:\r
675 PrintFormat = L"%ld";\r
676 break;\r
677\r
678 case EFI_IFR_STRING_LOWERCASE_HEX:\r
679 PrintFormat = L"%lx";\r
680 break;\r
681\r
682 case EFI_IFR_STRING_UPPERCASE_HEX:\r
683 PrintFormat = L"%lX";\r
684 break;\r
685\r
686 default:\r
687 return EFI_UNSUPPORTED;\r
688 }\r
689 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
690 break;\r
691\r
692 case EFI_IFR_TYPE_STRING:\r
693 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
694 return EFI_SUCCESS;\r
695\r
696 case EFI_IFR_TYPE_BOOLEAN:\r
697 break;\r
698\r
699 default:\r
700 return EFI_UNSUPPORTED;\r
701 }\r
702\r
703 Result->Type = EFI_IFR_TYPE_STRING;\r
704 //Result->Value.string = NewString (String, FormSet->HiiHandle);\r
705 return EFI_SUCCESS;\r
706}\r
707\r
708/**\r
709 Evaluate opcode EFI_IFR_TO_UINT.\r
710\r
711 @param FormSet Formset which contains this opcode.\r
712 @param Result Evaluation result for this opcode.\r
713\r
714 @retval EFI_SUCCESS Opcode evaluation success.\r
715 @retval Other Opcode evaluation failed.\r
716\r
717**/\r
718EFI_STATUS\r
719IfrToUint (\r
720 IN FORM_BROWSER_FORMSET *FormSet,\r
721 OUT EFI_HII_VALUE *Result\r
722 )\r
723{\r
724 EFI_STATUS Status;\r
725 EFI_HII_VALUE Value;\r
726 CHAR16 *String;\r
727 CHAR16 *StringPtr;\r
728\r
729 Status = PopExpression (&Value);\r
730 if (EFI_ERROR (Status)) {\r
731 return Status;\r
732 }\r
733\r
734 if (Value.Type >= EFI_IFR_TYPE_OTHER) {\r
735 return EFI_UNSUPPORTED;\r
736 }\r
737\r
738 Status = EFI_SUCCESS;\r
739 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
740 String = GetToken (Value.Value.string, FormSet->UnicodeBinary);\r
741 if (String == NULL) {\r
742 return EFI_NOT_FOUND;\r
743 }\r
744\r
745 IfrStrToUpper (String);\r
746 StringPtr = StrStr (String, L"0X");\r
747 if (StringPtr != NULL) {\r
748 //\r
749 // Hex string\r
750 //\r
751 Result->Value.u64 = FceStrHexToUint64 (String);\r
752 } else {\r
753 //\r
754 // decimal string\r
755 //\r
756 Result->Value.u64 = FceStrDecimalToUint64 (String);\r
757 }\r
758 FreePool (String);\r
759 } else {\r
760 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
761 }\r
762\r
763 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
764 return Status;\r
765}\r
766\r
767/**\r
768 Evaluate opcode EFI_IFR_CATENATE.\r
769\r
770 @param FormSet Formset which contains this opcode.\r
771 @param Result Evaluation result for this opcode.\r
772\r
773 @retval EFI_SUCCESS Opcode evaluation success.\r
774 @retval Other Opcode evaluation failed.\r
775\r
776**/\r
777EFI_STATUS\r
778IfrCatenate (\r
779 IN FORM_BROWSER_FORMSET *FormSet,\r
780 OUT EFI_HII_VALUE *Result\r
781 )\r
782{\r
783 EFI_STATUS Status;\r
784 EFI_HII_VALUE Value;\r
785 CHAR16 *String[2];\r
786 UINTN Index;\r
787 CHAR16 *StringPtr;\r
788 UINTN Size;\r
789\r
790 //\r
791 // String[0] - The second string\r
792 // String[1] - The first string\r
793 //\r
794 String[0] = NULL;\r
795 String[1] = NULL;\r
796 StringPtr = NULL;\r
797 Status = EFI_SUCCESS;\r
798\r
799 for (Index = 0; Index < 2; Index++) {\r
800 Status = PopExpression (&Value);\r
801 if (EFI_ERROR (Status)) {\r
802 goto Done;\r
803 }\r
804\r
805 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
806 Status = EFI_UNSUPPORTED;\r
807 goto Done;\r
808 }\r
809\r
810 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);\r
811 if (String[Index] == NULL) {\r
812 Status = EFI_NOT_FOUND;\r
813 goto Done;\r
814 }\r
815 }\r
816\r
817 Size = FceStrSize (String[0]);\r
818 StringPtr= AllocatePool (FceStrSize (String[1]) + Size);\r
819 ASSERT (StringPtr != NULL);\r
820 StrCpy (StringPtr, String[1]);\r
821 StrCat (StringPtr, String[0]);\r
822\r
823 Result->Type = EFI_IFR_TYPE_STRING;\r
824 //Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
825\r
826Done:\r
827 if (String[0] != NULL) {\r
828 FreePool (String[0]);\r
829 }\r
830 if (String[1] != NULL) {\r
831 FreePool (String[1]);\r
832 }\r
833 if (StringPtr != NULL) {\r
834 FreePool (StringPtr);\r
835 }\r
836\r
837 return Status;\r
838}\r
839\r
840/**\r
841 Evaluate opcode EFI_IFR_MATCH.\r
842\r
843 @param FormSet Formset which contains this opcode.\r
844 @param Result Evaluation result for this opcode.\r
845\r
846 @retval EFI_SUCCESS Opcode evaluation success.\r
847 @retval Other Opcode evaluation failed.\r
848\r
849**/\r
850EFI_STATUS\r
851IfrMatch (\r
852 IN FORM_BROWSER_FORMSET *FormSet,\r
853 OUT EFI_HII_VALUE *Result\r
854 )\r
855{\r
856 EFI_STATUS Status;\r
857 EFI_HII_VALUE Value;\r
858 CHAR16 *String[2];\r
859 UINTN Index;\r
860\r
861 //\r
862 // String[0] - The string to search\r
863 // String[1] - pattern\r
864 //\r
865 String[0] = NULL;\r
866 String[1] = NULL;\r
867 Status = EFI_SUCCESS;\r
868 for (Index = 0; Index < 2; Index++) {\r
869 Status = PopExpression (&Value);\r
870 if (EFI_ERROR (Status)) {\r
871 goto Done;\r
872 }\r
873\r
874 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
875 Status = EFI_UNSUPPORTED;\r
876 goto Done;\r
877 }\r
878\r
879 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);\r
880 if (String [Index] == NULL) {\r
881 Status = EFI_NOT_FOUND;\r
882 goto Done;\r
883 }\r
884 }\r
885\r
886 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
887 Result->Value.b = MetaiMatch (String[0], String[1]);\r
888\r
889Done:\r
890 if (String[0] != NULL) {\r
891 FreePool (String[0]);\r
892 }\r
893 if (String[1] != NULL) {\r
894 FreePool (String[1]);\r
895 }\r
896\r
897 return Status;\r
898}\r
899\r
900\r
901/**\r
902 Evaluate opcode EFI_IFR_FIND.\r
903\r
904 @param FormSet Formset which contains this opcode.\r
905 @param Format Case sensitive or insensitive.\r
906 @param Result Evaluation result for this opcode.\r
907\r
908 @retval EFI_SUCCESS Opcode evaluation success.\r
909 @retval Other Opcode evaluation failed.\r
910\r
911**/\r
912EFI_STATUS\r
913IfrFind (\r
914 IN FORM_BROWSER_FORMSET *FormSet,\r
915 IN UINT8 Format,\r
916 OUT EFI_HII_VALUE *Result\r
917 )\r
918{\r
919 EFI_STATUS Status;\r
920 EFI_HII_VALUE Value;\r
921 CHAR16 *String[2];\r
922 UINTN Base;\r
923 CHAR16 *StringPtr;\r
924 UINTN Index;\r
925\r
926 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
927 return EFI_UNSUPPORTED;\r
928 }\r
929\r
930 Status = PopExpression (&Value);\r
931 if (EFI_ERROR (Status)) {\r
932 return Status;\r
933 }\r
934 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
935 return EFI_UNSUPPORTED;\r
936 }\r
937 Base = (UINTN) Value.Value.u64;\r
938\r
939 //\r
940 // String[0] - sub-string\r
941 // String[1] - The string to search\r
942 //\r
943 String[0] = NULL;\r
944 String[1] = NULL;\r
945 for (Index = 0; Index < 2; Index++) {\r
946 Status = PopExpression (&Value);\r
947 if (EFI_ERROR (Status)) {\r
948 goto Done;\r
949 }\r
950\r
951 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
952 Status = EFI_UNSUPPORTED;\r
953 goto Done;\r
954 }\r
955\r
956 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);\r
957 if (String[Index] == NULL) {\r
958 Status = EFI_NOT_FOUND;\r
959 goto Done;\r
960 }\r
961\r
962 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
963 //\r
964 // Case insensitive, convert both string to upper case\r
965 //\r
966 IfrStrToUpper (String[Index]);\r
967 }\r
968 }\r
969\r
970 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
971 if (Base >= FceStrLen (String[1])) {\r
972 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
973 } else {\r
974 StringPtr = StrStr (String[1] + Base, String[0]);\r
975 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
976 }\r
977\r
978Done:\r
979 if (String[0] != NULL) {\r
980 FreePool (String[0]);\r
981 }\r
982 if (String[1] != NULL) {\r
983 FreePool (String[1]);\r
984 }\r
985\r
986 return Status;\r
987}\r
988\r
989\r
990/**\r
991 Evaluate opcode EFI_IFR_MID.\r
992\r
993 @param FormSet Formset which contains this opcode.\r
994 @param Result Evaluation result for this opcode.\r
995\r
996 @retval EFI_SUCCESS Opcode evaluation success.\r
997 @retval Other Opcode evaluation failed.\r
998\r
999**/\r
1000EFI_STATUS\r
1001IfrMid (\r
1002 IN FORM_BROWSER_FORMSET *FormSet,\r
1003 OUT EFI_HII_VALUE *Result\r
1004 )\r
1005{\r
1006 EFI_STATUS Status;\r
1007 EFI_HII_VALUE Value;\r
1008 CHAR16 *String;\r
1009 UINTN Base;\r
1010 UINTN Length;\r
1011 CHAR16 *SubString;\r
1012\r
1013 Status = PopExpression (&Value);\r
1014 if (EFI_ERROR (Status)) {\r
1015 return Status;\r
1016 }\r
1017 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1018 return EFI_UNSUPPORTED;\r
1019 }\r
1020 Length = (UINTN) Value.Value.u64;\r
1021\r
1022 Status = PopExpression (&Value);\r
1023 if (EFI_ERROR (Status)) {\r
1024 return Status;\r
1025 }\r
1026 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1027 return EFI_UNSUPPORTED;\r
1028 }\r
1029 Base = (UINTN) Value.Value.u64;\r
1030\r
1031 Status = PopExpression (&Value);\r
1032 if (EFI_ERROR (Status)) {\r
1033 return Status;\r
1034 }\r
1035 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1036 return EFI_UNSUPPORTED;\r
1037 }\r
1038 String = GetToken (Value.Value.string, FormSet->UnicodeBinary);\r
1039 if (String == NULL) {\r
1040 return EFI_NOT_FOUND;\r
1041 }\r
1042\r
1043 if ((Length == 0) || (Base >= FceStrLen (String))) {\r
1044 SubString = gEmptyString;\r
1045 } else {\r
1046 SubString = String + Base;\r
1047 if ((Base + Length) < FceStrLen (String)) {\r
1048 SubString[Length] = L'\0';\r
1049 }\r
1050 }\r
1051\r
1052 Result->Type = EFI_IFR_TYPE_STRING;\r
1053 //Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1054\r
1055 FreePool (String);\r
1056\r
1057 return Status;\r
1058}\r
1059\r
1060/**\r
1061 Evaluate opcode EFI_IFR_TOKEN.\r
1062\r
1063 @param FormSet Formset which contains this opcode.\r
1064 @param Result Evaluation result for this opcode.\r
1065\r
1066 @retval EFI_SUCCESS Opcode evaluation success.\r
1067 @retval Other Opcode evaluation failed.\r
1068\r
1069**/\r
1070EFI_STATUS\r
1071IfrToken (\r
1072 IN FORM_BROWSER_FORMSET *FormSet,\r
1073 OUT EFI_HII_VALUE *Result\r
1074 )\r
1075{\r
1076 EFI_STATUS Status;\r
1077 EFI_HII_VALUE Value;\r
1078 CHAR16 *String[2];\r
1079 UINTN Count;\r
1080 CHAR16 *Delimiter;\r
1081 CHAR16 *SubString;\r
1082 CHAR16 *StringPtr;\r
1083 UINTN Index;\r
1084\r
1085 Status = PopExpression (&Value);\r
1086 if (EFI_ERROR (Status)) {\r
1087 return Status;\r
1088 }\r
1089 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1090 return EFI_UNSUPPORTED;\r
1091 }\r
1092 Count = (UINTN) Value.Value.u64;\r
1093\r
1094 //\r
1095 // String[0] - Delimiter\r
1096 // String[1] - The string to search\r
1097 //\r
1098 String[0] = NULL;\r
1099 String[1] = NULL;\r
1100 for (Index = 0; Index < 2; Index++) {\r
1101 Status = PopExpression (&Value);\r
1102 if (EFI_ERROR (Status)) {\r
1103 goto Done;\r
1104 }\r
1105\r
1106 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1107 Status = EFI_UNSUPPORTED;\r
1108 goto Done;\r
1109 }\r
1110\r
1111 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);\r
1112 if (String[Index] == NULL) {\r
1113 Status = EFI_NOT_FOUND;\r
1114 goto Done;\r
1115 }\r
1116 }\r
1117\r
1118 Delimiter = String[0];\r
1119 SubString = String[1];\r
1120 while (Count > 0) {\r
1121 SubString = StrStr (SubString, Delimiter);\r
1122 if (SubString != NULL) {\r
1123 //\r
1124 // Skip over the delimiter\r
1125 //\r
1126 SubString = SubString + FceStrLen (Delimiter);\r
1127 } else {\r
1128 break;\r
1129 }\r
1130 Count--;\r
1131 }\r
1132\r
1133 if (SubString == NULL) {\r
1134 //\r
1135 // nth delimited sub-string not found, push an empty string\r
1136 //\r
1137 SubString = gEmptyString;\r
1138 } else {\r
1139 //\r
1140 // Put a NULL terminator for nth delimited sub-string\r
1141 //\r
1142 StringPtr = StrStr (SubString, Delimiter);\r
1143 if (StringPtr != NULL) {\r
1144 *StringPtr = L'\0';\r
1145 }\r
1146 }\r
1147\r
1148 Result->Type = EFI_IFR_TYPE_STRING;\r
1149 //Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1150\r
1151Done:\r
1152 if (String[0] != NULL) {\r
1153 FreePool (String[0]);\r
1154 }\r
1155 if (String[1] != NULL) {\r
1156 FreePool (String[1]);\r
1157 }\r
1158\r
1159 return Status;\r
1160}\r
1161\r
1162\r
1163/**\r
1164 Evaluate opcode EFI_IFR_SPAN.\r
1165\r
1166 @param FormSet Formset which contains this opcode.\r
1167 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1168 @param Result Evaluation result for this opcode.\r
1169\r
1170 @retval EFI_SUCCESS Opcode evaluation success.\r
1171 @retval Other Opcode evaluation failed.\r
1172\r
1173**/\r
1174EFI_STATUS\r
1175IfrSpan (\r
1176 IN FORM_BROWSER_FORMSET *FormSet,\r
1177 IN UINT8 Flags,\r
1178 OUT EFI_HII_VALUE *Result\r
1179 )\r
1180{\r
1181 EFI_STATUS Status;\r
1182 EFI_HII_VALUE Value;\r
1183 CHAR16 *String[2];\r
1184 CHAR16 *Charset;\r
1185 UINTN Base;\r
1186 UINTN Index;\r
1187 CHAR16 *StringPtr;\r
1188 BOOLEAN Found;\r
1189\r
1190 Status = PopExpression (&Value);\r
1191 if (EFI_ERROR (Status)) {\r
1192 return Status;\r
1193 }\r
1194 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1195 return EFI_UNSUPPORTED;\r
1196 }\r
1197 Base = (UINTN) Value.Value.u64;\r
1198\r
1199 //\r
1200 // String[0] - Charset\r
1201 // String[1] - The string to search\r
1202 //\r
1203 String[0] = NULL;\r
1204 String[1] = NULL;\r
1205 for (Index = 0; Index < 2; Index++) {\r
1206 Status = PopExpression (&Value);\r
1207 if (EFI_ERROR (Status)) {\r
1208 goto Done;\r
1209 }\r
1210\r
1211 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1212 Status = EFI_UNSUPPORTED;\r
1213 goto Done;\r
1214 }\r
1215\r
1216 String[Index] = GetToken (Value.Value.string, FormSet->UnicodeBinary);\r
1217 if (String [Index] == NULL) {\r
1218 Status = EFI_NOT_FOUND;\r
1219 goto Done;\r
1220 }\r
1221 }\r
1222\r
1223 if (Base >= FceStrLen (String[1])) {\r
1224 Status = EFI_UNSUPPORTED;\r
1225 goto Done;\r
1226 }\r
1227\r
1228 Found = FALSE;\r
1229 StringPtr = String[1] + Base;\r
1230 Charset = String[0];\r
1231 while (*StringPtr != 0 && !Found) {\r
1232 Index = 0;\r
1233 while (Charset[Index] != 0) {\r
1234 if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1])) {\r
1235 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1236 Found = TRUE;\r
1237 break;\r
1238 }\r
1239 } else {\r
1240 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1241 Found = TRUE;\r
1242 break;\r
1243 }\r
1244 }\r
1245 //\r
1246 // Skip characters pair representing low-end of a range and high-end of a range\r
1247 //\r
1248 Index += 2;\r
1249 }\r
1250\r
1251 if (!Found) {\r
1252 StringPtr++;\r
1253 }\r
1254 }\r
1255\r
1256 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1257 Result->Value.u64 = StringPtr - String[1];\r
1258\r
1259Done:\r
1260 if (String[0] != NULL) {\r
1261 FreePool (String[0]);\r
1262 }\r
1263 if (String[1] != NULL) {\r
1264 FreePool (String[1]);\r
1265 }\r
1266\r
1267 return Status;\r
1268}\r
1269\r
1270\r
1271/**\r
1272 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1273\r
1274 @param Value HII Value to be converted.\r
1275\r
1276**/\r
1277VOID\r
1278ExtendValueToU64 (\r
1279 IN EFI_HII_VALUE *Value\r
1280 )\r
1281{\r
1282 UINT64 Temp;\r
1283\r
1284 Temp = 0;\r
1285 switch (Value->Type) {\r
1286 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1287 Temp = Value->Value.u8;\r
1288 break;\r
1289\r
1290 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1291 Temp = Value->Value.u16;\r
1292 break;\r
1293\r
1294 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1295 Temp = Value->Value.u32;\r
1296 break;\r
1297\r
1298 case EFI_IFR_TYPE_BOOLEAN:\r
1299 Temp = Value->Value.b;\r
1300 break;\r
1301\r
1302 case EFI_IFR_TYPE_TIME:\r
1303 Temp = Value->Value.u32 & 0xffffff;\r
1304 break;\r
1305\r
1306 case EFI_IFR_TYPE_DATE:\r
1307 Temp = Value->Value.u32;\r
1308 break;\r
1309\r
1310 default:\r
1311 return;\r
1312 }\r
1313\r
1314 Value->Value.u64 = Temp;\r
1315}\r
1316\r
1317\r
1318/**\r
1319 Compare two Hii value.\r
1320\r
1321 @param Value1 Expression value to compare on left-hand.\r
1322 @param Value2 Expression value to compare on right-hand.\r
1323 @param FormSet The pointer to the Formset.\r
1324\r
1325 @retval EFI_INVALID_PARAMETER Could not perform compare on two values.\r
1326 @retval 0 Two operators equal.\r
1327 @return Positive value if Value1 is greater than Value2.\r
1328 @retval Negative value if Value1 is less than Value2.\r
1329\r
1330**/\r
1331INTN\r
1332CompareHiiValue (\r
1333 IN EFI_HII_VALUE *Value1,\r
1334 IN EFI_HII_VALUE *Value2,\r
1335 IN FORM_BROWSER_FORMSET *FormSet\r
1336 )\r
1337{\r
1338 INTN Result;\r
1339 INT64 Temp64;\r
1340 CHAR16 *Str1;\r
1341 CHAR16 *Str2;\r
1342\r
1343 if ((Value1->Type >= EFI_IFR_TYPE_OTHER) || (Value2->Type >= EFI_IFR_TYPE_OTHER) ) {\r
1344 return EFI_INVALID_PARAMETER;\r
1345 }\r
1346\r
1347 if ((Value1->Type == EFI_IFR_TYPE_STRING) || (Value2->Type == EFI_IFR_TYPE_STRING) ) {\r
1348 if (Value1->Type != Value2->Type) {\r
1349 //\r
1350 // Both Operator should be type of String\r
1351 //\r
1352 return EFI_INVALID_PARAMETER;\r
1353 }\r
1354\r
1355 if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {\r
1356 //\r
1357 // StringId 0 is reserved\r
1358 //\r
1359 return EFI_INVALID_PARAMETER;\r
1360 }\r
1361\r
1362 if (Value1->Value.string == Value2->Value.string) {\r
1363 return 0;\r
1364 }\r
1365\r
1366 Str1 = GetToken (Value1->Value.string, FormSet->UnicodeBinary);\r
1367 if (Str1 == NULL) {\r
1368 //\r
1369 // String not found\r
1370 //\r
1371 return EFI_INVALID_PARAMETER;\r
1372 }\r
1373\r
1374 Str2 = GetToken (Value2->Value.string, FormSet->UnicodeBinary);\r
1375 if (Str2 == NULL) {\r
1376 FreePool (Str1);\r
1377 return EFI_INVALID_PARAMETER;\r
1378 }\r
1379\r
1380 Result = FceStrCmp (Str1, Str2);\r
1381\r
1382 FreePool (Str1);\r
1383 FreePool (Str2);\r
1384\r
1385 return Result;\r
1386 }\r
1387\r
1388 //\r
1389 // Take remain types(integer, boolean, date/time) as integer\r
1390 //\r
1391 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
1392 if (Temp64 > 0) {\r
1393 Result = 1;\r
1394 } else if (Temp64 < 0) {\r
1395 Result = -1;\r
1396 } else {\r
1397 Result = 0;\r
1398 }\r
1399\r
1400 return Result;\r
1401}\r
1402\r
1403/**\r
1404 Tell whether this Operand is an constant Expression or not\r
1405\r
1406 @param Operand Operand of an IFR OpCode.\r
1407\r
1408 @retval TRUE This is an Expression OpCode.\r
1409 @retval FALSE Not an Expression OpCode.\r
1410\r
1411**/\r
1412BOOLEAN\r
1413IsConstantExpressionOpCode (\r
1414 IN UINT8 Operand\r
1415 )\r
1416{\r
1417 if ((Operand == EFI_IFR_EQ_ID_VAL_OP) ||\r
1418 (Operand == EFI_IFR_EQ_ID_ID_OP) ||\r
1419 (Operand == EFI_IFR_EQ_ID_VAL_LIST_OP )||\r
1420 (Operand == EFI_IFR_QUESTION_REF1_OP) ||\r
1421 (Operand == EFI_IFR_QUESTION_REF2_OP) ||\r
1422 (Operand == EFI_IFR_QUESTION_REF3_OP) ||\r
1423 (Operand == EFI_IFR_THIS_OP ) ||\r
1424 (Operand == EFI_IFR_SECURITY_OP) ||\r
1425 (Operand == EFI_IFR_GET_OP) ||\r
1426 (Operand == EFI_IFR_SET_OP)\r
1427 ) {\r
1428 return FALSE;\r
1429 } else {\r
1430 return TRUE;\r
1431 }\r
1432}\r
1433\r
1434/**\r
1435 Update the HiiValue of question from its variable.\r
1436\r
1437 @param FormSet FormSet associated with this expression.\r
1438 @param Question The pointer to the Question\r
1439\r
1440 @return EFI_SUCCESS\r
1441 @return EFI_NOT_FOUND\r
1442**/\r
1443EFI_STATUS\r
1444UpdateHiiValue (\r
1445 IN FORM_BROWSER_FORMSET *FormSet,\r
1446 IN FORM_BROWSER_STATEMENT *Question\r
1447 )\r
1448{\r
1449 EFI_STATUS Status;\r
1450 FORMSET_STORAGE *VarList;\r
1451 UINT8 *VarBuffer;\r
1452 EFI_HII_VALUE *HiiValue;\r
1453\r
1454 Status = EFI_SUCCESS;\r
1455 HiiValue = &Question->HiiValue;\r
1456\r
1457 Status = SearchVarStorage (\r
1458 Question,\r
1459 NULL,\r
1460 Question->VarStoreInfo.VarOffset,\r
1461 FormSet->StorageListHead,\r
1462 (CHAR8 **)&VarBuffer,\r
1463 &VarList\r
1464 );\r
1465 if (EFI_ERROR(Status)) {\r
1466 return Status;\r
1467 }\r
1468 if (Question->QuestionReferToBitField) {\r
1469 GetBitsQuestionValue (Question, VarBuffer, &HiiValue->Value.u32);\r
1470 } else {\r
1471 CopyMem (&HiiValue->Value.u64, VarBuffer, Question->StorageWidth);\r
1472 }\r
1473 return Status;\r
1474}\r
1475/**\r
1476 Evaluate the result of a HII expression.\r
1477\r
1478 If Expression is NULL, then ASSERT.\r
1479\r
1480 @param FormSet FormSet associated with this expression.\r
1481 @param Form Form associated with this expression.\r
1482 @param Expression Expression to be evaluated.\r
1483 @param ConstantExpression The pointer to the flag of constant expression. If constant, will return TRUE.\r
1484\r
1485 @retval EFI_SUCCESS The expression evaluated successfuly\r
1486 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
1487 could not be found.\r
1488 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
1489 stack.\r
1490 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
1491 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
1492\r
1493**/\r
1494EFI_STATUS\r
1495EvaluateExpression (\r
1496 IN FORM_BROWSER_FORMSET *FormSet,\r
1497 IN FORM_BROWSER_FORM *Form,\r
1498 IN OUT FORM_EXPRESSION *Expression,\r
1499 IN OUT BOOLEAN *ConstantExpression\r
1500 )\r
1501{\r
1502 EFI_STATUS Status;\r
1503 LIST_ENTRY *Link;\r
1504 EXPRESSION_OPCODE *OpCode;\r
1505 FORM_BROWSER_STATEMENT *Question;\r
1506 FORM_BROWSER_STATEMENT *Question2;\r
1507 UINT16 Index;\r
1508 EFI_HII_VALUE Data1;\r
1509 EFI_HII_VALUE Data2;\r
1510 EFI_HII_VALUE Data3;\r
1511 FORM_EXPRESSION *RuleExpression;\r
1512 EFI_HII_VALUE *Value;\r
1513 INTN Result;\r
1514 CHAR16 *StrPtr;\r
1515 UINT32 TempValue;\r
1516 LIST_ENTRY *SubExpressionLink;\r
1517 FORM_EXPRESSION *SubExpression;\r
1518 UINTN StackOffset;\r
1519 UINTN TempLength;\r
1520 CHAR16 TempStr[5];\r
1521 UINT8 DigitUint8;\r
1522 UINT8 *TempBuffer;\r
1523\r
1524 //\r
1525 // Save current stack offset.\r
1526 //\r
1527 StackOffset = SaveExpressionEvaluationStackOffset ();\r
1528\r
1529 ASSERT (Expression != NULL);\r
1530 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
1531\r
1532 Link = GetFirstNode (&Expression->OpCodeListHead);\r
1533 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
1534 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
1535\r
1536 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
1537\r
1538 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
1539 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
1540 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
1541\r
1542 Value = &Data3;\r
1543 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1544 Status = EFI_SUCCESS;\r
1545\r
1546 //\r
1547 // Check whether it is a constant expression or not\r
1548 //\r
1549 if (*ConstantExpression) {\r
1550 *ConstantExpression = IsConstantExpressionOpCode (OpCode->Operand);\r
1551 }\r
1552\r
1553 switch (OpCode->Operand) {\r
1554 //\r
1555 // Built-in functions\r
1556 //\r
1557 case EFI_IFR_EQ_ID_VAL_OP:\r
1558 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1559 if (Question == NULL) {\r
1560 Status = EFI_NOT_FOUND;\r
1561 goto Done;\r
1562 }\r
1563 UpdateHiiValue (FormSet, Question);\r
1564 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, FormSet);\r
1565 if ((EFI_STATUS)Result == EFI_INVALID_PARAMETER) {\r
1566 Status = EFI_INVALID_PARAMETER;\r
1567 goto Done;\r
1568 }\r
1569 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1570 break;\r
1571\r
1572 case EFI_IFR_EQ_ID_ID_OP:\r
1573 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1574 if (Question == NULL) {\r
1575 Status = EFI_NOT_FOUND;\r
1576 goto Done;\r
1577 }\r
1578\r
1579 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
1580 if (Question2 == NULL) {\r
1581 Status = EFI_NOT_FOUND;\r
1582 goto Done;\r
1583 }\r
1584 UpdateHiiValue (FormSet, Question);\r
1585 UpdateHiiValue (FormSet, Question2);\r
1586 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet);\r
1587 if ((EFI_STATUS)Result == EFI_INVALID_PARAMETER) {\r
1588 Status = EFI_INVALID_PARAMETER;\r
1589 goto Done;\r
1590 }\r
1591 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1592 break;\r
1593\r
1594 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
1595\r
1596 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1597 if (Question == NULL) {\r
1598 Status = EFI_NOT_FOUND;\r
1599 goto Done;\r
1600 }\r
1601 UpdateHiiValue (FormSet, Question);\r
1602 Value->Value.b = FALSE;\r
1603 for (Index =0; Index < OpCode->ListLength; Index++) {\r
1604 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
1605 Value->Value.b = TRUE;\r
1606 break;\r
1607 }\r
1608 }\r
1609 break;\r
1610\r
1611 case EFI_IFR_DUP_OP:\r
1612 Status = PopExpression (Value);\r
1613 if (EFI_ERROR (Status)) {\r
1614 goto Done;\r
1615 }\r
1616\r
1617 Status = PushExpression (Value);\r
1618 break;\r
1619\r
1620 case EFI_IFR_QUESTION_REF1_OP:\r
1621 case EFI_IFR_THIS_OP:\r
1622 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1623 if (Question == NULL) {\r
1624 Status = EFI_NOT_FOUND;\r
1625 goto Done;\r
1626 }\r
1627 UpdateHiiValue (FormSet, Question);\r
1628 Value = &Question->HiiValue;\r
1629 break;\r
1630\r
1631 case EFI_IFR_SECURITY_OP:\r
1632 //\r
1633 // Do nothing, as no need for static scaning\r
1634 //\r
1635 break;\r
1636\r
1637 case EFI_IFR_GET_OP:\r
1638 //\r
1639 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
1640 //\r
1641 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
1642 Value->Value.u8 = 0;\r
1643 if (OpCode->VarStorage != NULL) {\r
1644 switch (OpCode->VarStorage->Type) {\r
1645 case EFI_IFR_VARSTORE_OP:\r
1646 //\r
1647 // Get value from Buffer\r
1648 //\r
1649 Value->Type = OpCode->ValueType;\r
1650 CopyMem (&Value->Value, OpCode->VarStorage->Buffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
1651 break;\r
1652\r
1653 case EFI_IFR_VARSTORE_EFI_OP:\r
1654 //\r
1655 // Get value from Buffer\r
1656 //\r
1657 if (OpCode->VarStorage->NewEfiVarstore) {\r
1658 Value->Type = OpCode->ValueType;\r
1659 CopyMem (&Value->Value, OpCode->VarStorage->Buffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
1660 } else {\r
1661 CopyMem (&Value->Value, OpCode->VarStorage->Buffer, OpCode->ValueWidth);\r
1662 }\r
1663\r
1664\r
1665 break;\r
1666 case EFI_HII_VARSTORE_NAME_VALUE:\r
1667 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
1668 //\r
1669 // Get value from string except for STRING value.\r
1670 //\r
1671 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr);\r
1672 if (!EFI_ERROR (Status)) {\r
1673 ASSERT (StrPtr != NULL);\r
1674 TempLength = FceStrLen (StrPtr);\r
1675 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
1676 Value->Type = OpCode->ValueType;\r
1677 TempBuffer = (UINT8 *) &Value->Value;\r
1678 ZeroMem (TempStr, sizeof (TempStr));\r
1679 for (Index = 0; Index < TempLength; Index ++) {\r
1680 TempStr[0] = StrPtr[TempLength - Index - 1];\r
1681 DigitUint8 = (UINT8) FceStrHexToUint64 (TempStr);\r
1682 if ((Index & 1) == 0) {\r
1683 TempBuffer [Index/2] = DigitUint8;\r
1684 } else {\r
1685 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
1686 }\r
1687 }\r
1688 }\r
1689 free (StrPtr);\r
1690 StrPtr = NULL;\r
1691 }\r
1692 }\r
1693 break;\r
1694 default:\r
1695 //\r
1696 // Not recognize storage.\r
1697 //\r
1698 Status = EFI_UNSUPPORTED;\r
1699 goto Done;\r
1700 }\r
1701 }\r
1702\r
1703 break;\r
1704\r
1705 case EFI_IFR_QUESTION_REF3_OP:\r
1706 if (OpCode->DevicePath == 0) {\r
1707 //\r
1708 // EFI_IFR_QUESTION_REF3\r
1709 // Pop an expression from the expression stack\r
1710 //\r
1711 Status = PopExpression (Value);\r
1712 if (EFI_ERROR (Status)) {\r
1713 goto Done;\r
1714 }\r
1715\r
1716 //\r
1717 // Validate the expression value\r
1718 //\r
1719 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1720 Status = EFI_NOT_FOUND;\r
1721 goto Done;\r
1722 }\r
1723\r
1724 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1725 if (Question == NULL) {\r
1726 Status = EFI_NOT_FOUND;\r
1727 goto Done;\r
1728 }\r
1729\r
1730 //\r
1731 // push the questions' value on to the expression stack\r
1732 //\r
1733 Value = &Question->HiiValue;\r
1734 } else {\r
1735 //\r
1736 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
1737 // since it is impractical to evaluate the value of a Question in another\r
1738 // Hii Package list.\r
1739 //\r
1740 ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
1741 }\r
1742 break;\r
1743\r
1744 case EFI_IFR_RULE_REF_OP:\r
1745 //\r
1746 // Find expression for this rule\r
1747 //\r
1748 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
1749 if (RuleExpression == NULL) {\r
1750 Status = EFI_NOT_FOUND;\r
1751 goto Done;\r
1752 }\r
1753\r
1754 //\r
1755 // Evaluate this rule expression\r
1756 //\r
1757 Status = EvaluateExpression (FormSet, Form, RuleExpression, ConstantExpression);\r
1758 if (EFI_ERROR (Status)) {\r
1759 goto Done;\r
1760 }\r
1761\r
1762 Value = &RuleExpression->Result;\r
1763 break;\r
1764\r
1765 case EFI_IFR_STRING_REF1_OP:\r
1766 Value->Type = EFI_IFR_TYPE_STRING;\r
1767 Value->Value.string = OpCode->Value.Value.string;\r
1768 break;\r
1769\r
1770 //\r
1771 // Constant\r
1772 //\r
1773 case EFI_IFR_TRUE_OP:\r
1774 case EFI_IFR_FALSE_OP:\r
1775 case EFI_IFR_ONE_OP:\r
1776 case EFI_IFR_ONES_OP:\r
1777 case EFI_IFR_UINT8_OP:\r
1778 case EFI_IFR_UINT16_OP:\r
1779 case EFI_IFR_UINT32_OP:\r
1780 case EFI_IFR_UINT64_OP:\r
1781 case EFI_IFR_UNDEFINED_OP:\r
1782 case EFI_IFR_VERSION_OP:\r
1783 case EFI_IFR_ZERO_OP:\r
1784 Value = &OpCode->Value;\r
1785 break;\r
1786\r
1787 //\r
1788 // unary-op\r
1789 //\r
1790 case EFI_IFR_LENGTH_OP:\r
1791 Status = PopExpression (Value);\r
1792 if (EFI_ERROR (Status)) {\r
1793 goto Done;\r
1794 }\r
1795 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1796 Status = EFI_INVALID_PARAMETER;\r
1797 goto Done;\r
1798 }\r
1799\r
1800 StrPtr = GetToken (Value->Value.string, FormSet->UnicodeBinary);\r
1801 if (StrPtr == NULL) {\r
1802 Status = EFI_INVALID_PARAMETER;\r
1803 goto Done;\r
1804 }\r
1805\r
1806 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1807 Value->Value.u64 = FceStrLen (StrPtr);\r
1808 FreePool (StrPtr);\r
1809 break;\r
1810\r
1811 case EFI_IFR_NOT_OP:\r
1812 Status = PopExpression (Value);\r
1813 if (EFI_ERROR (Status)) {\r
1814 goto Done;\r
1815 }\r
1816 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
1817 Status = EFI_INVALID_PARAMETER;\r
1818 goto Done;\r
1819 }\r
1820 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
1821 break;\r
1822\r
1823 case EFI_IFR_QUESTION_REF2_OP:\r
1824 //\r
1825 // Pop an expression from the expression stack\r
1826 //\r
1827 Status = PopExpression (Value);\r
1828 if (EFI_ERROR (Status)) {\r
1829 goto Done;\r
1830 }\r
1831\r
1832 //\r
1833 // Validate the expression value\r
1834 //\r
1835 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1836 Status = EFI_NOT_FOUND;\r
1837 goto Done;\r
1838 }\r
1839\r
1840 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1841 if (Question == NULL) {\r
1842 Status = EFI_NOT_FOUND;\r
1843 goto Done;\r
1844 }\r
1845\r
1846 Value = &Question->HiiValue;\r
1847 break;\r
1848\r
1849 case EFI_IFR_STRING_REF2_OP:\r
1850 //\r
1851 // Pop an expression from the expression stack\r
1852 //\r
1853 Status = PopExpression (Value);\r
1854 if (EFI_ERROR (Status)) {\r
1855 goto Done;\r
1856 }\r
1857\r
1858 //\r
1859 // Validate the expression value\r
1860 //\r
1861 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1862 Status = EFI_NOT_FOUND;\r
1863 goto Done;\r
1864 }\r
1865\r
1866 Value->Type = EFI_IFR_TYPE_STRING;\r
1867 StrPtr = GetToken (Value->Value.u16, FormSet->UnicodeBinary);\r
1868 if (StrPtr == NULL) {\r
1869 //\r
1870 // If String not exit, push an empty string\r
1871 //\r
1872 //Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
1873 } else {\r
1874 Index = (UINT16) Value->Value.u64;\r
1875 Value->Value.string = Index;\r
1876 FreePool (StrPtr);\r
1877 }\r
1878 break;\r
1879\r
1880 case EFI_IFR_TO_BOOLEAN_OP:\r
1881 //\r
1882 // Pop an expression from the expression stack\r
1883 //\r
1884 Status = PopExpression (Value);\r
1885 if (EFI_ERROR (Status)) {\r
1886 goto Done;\r
1887 }\r
1888\r
1889 //\r
1890 // Convert an expression to a Boolean\r
1891 //\r
1892 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
1893 //\r
1894 // When converting from an unsigned integer, zero will be converted to\r
1895 // FALSE and any other value will be converted to TRUE.\r
1896 //\r
1897 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);\r
1898\r
1899 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1900 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
1901 //\r
1902 // When converting from a string, if case-insensitive compare\r
1903 // with "true" is True, then push True. If a case-insensitive compare\r
1904 // with "false" is True, then push False. Otherwise, push Undefined.\r
1905 //\r
1906 StrPtr = GetToken (Value->Value.string, FormSet->UnicodeBinary);\r
1907 if (StrPtr == NULL) {\r
1908 Status = EFI_INVALID_PARAMETER;\r
1909 goto Done;\r
1910 }\r
1911\r
1912 IfrStrToUpper (StrPtr);\r
1913 if (FceStrCmp (StrPtr, L"TRUE") == 0){\r
1914 Value->Value.b = TRUE;\r
1915 } else if (FceStrCmp (StrPtr, L"FALSE") == 0) {\r
1916 Value->Value.b = FALSE;\r
1917 } else {\r
1918 Status = EFI_INVALID_PARAMETER;\r
1919 FreePool (StrPtr);\r
1920 goto Done;\r
1921 }\r
1922 FreePool (StrPtr);\r
1923 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1924 }\r
1925 break;\r
1926\r
1927 case EFI_IFR_TO_STRING_OP:\r
1928 //Status = IfrToString (FormSet, OpCode->Format, Value);\r
1929 break;\r
1930\r
1931 case EFI_IFR_TO_UINT_OP:\r
1932 Status = IfrToUint (FormSet, Value);\r
1933 break;\r
1934\r
1935 case EFI_IFR_TO_LOWER_OP:\r
1936 case EFI_IFR_TO_UPPER_OP:\r
1937\r
1938 Status = PopExpression (Value);\r
1939 if (EFI_ERROR (Status)) {\r
1940 goto Done;\r
1941 }\r
1942\r
1943 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1944 Status = EFI_UNSUPPORTED;\r
1945 goto Done;\r
1946 }\r
1947\r
1948 StrPtr = GetToken (Value->Value.string, FormSet->UnicodeBinary);\r
1949 if (StrPtr == NULL) {\r
1950 Status = EFI_NOT_FOUND;\r
1951 goto Done;\r
1952 }\r
1953 //\r
1954 // Do nothing here, as these two Opcode are to change or update the String Package\r
1955 //\r
1956 FreePool (StrPtr);\r
1957 break;\r
1958\r
1959 case EFI_IFR_BITWISE_NOT_OP:\r
1960 //\r
1961 // Pop an expression from the expression stack\r
1962 //\r
1963 Status = PopExpression (Value);\r
1964 if (EFI_ERROR (Status)) {\r
1965 goto Done;\r
1966 }\r
1967 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
1968 Status = EFI_INVALID_PARAMETER;\r
1969 goto Done;\r
1970 }\r
1971\r
1972 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1973 Value->Value.u64 = ~Value->Value.u64;\r
1974 break;\r
1975\r
1976 case EFI_IFR_SET_OP:\r
1977 //\r
1978 // Pop an expression from the expression stack\r
1979 //\r
1980 Status = PopExpression (Value);\r
1981 if (EFI_ERROR (Status)) {\r
1982 goto Done;\r
1983 }\r
1984 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
1985 Data1.Value.b = FALSE;\r
1986 //\r
1987 // Not support SetOpcode for static scaning\r
1988 //\r
1989 if (OpCode->VarStorage != NULL) {\r
1990 switch (OpCode->VarStorage->Type) {\r
1991\r
1992 case EFI_IFR_VARSTORE_OP:\r
1993 CopyMem (OpCode->VarStorage->Buffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
1994 Data1.Value.b = TRUE;\r
1995 break;\r
1996 case EFI_IFR_VARSTORE_EFI_OP:\r
1997 if (OpCode->VarStorage->NewEfiVarstore) {\r
1998 CopyMem (OpCode->VarStorage->Buffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
1999 Data1.Value.b = TRUE;\r
2000 } else {\r
2001 CopyMem (OpCode->VarStorage->Buffer, &Value->Value, OpCode->ValueWidth);\r
2002 Data1.Value.b = TRUE;\r
2003 }\r
2004 break;\r
2005 case EFI_HII_VARSTORE_NAME_VALUE:\r
2006\r
2007 break;\r
2008 break;\r
2009 default:\r
2010 //\r
2011 // Not recognize storage.\r
2012 //\r
2013 Status = EFI_UNSUPPORTED;\r
2014 goto Done;\r
2015 break;\r
2016 }\r
2017 Value = &Data1;\r
2018 }\r
2019 break;\r
2020\r
2021 //\r
2022 // binary-op\r
2023 //\r
2024 case EFI_IFR_ADD_OP:\r
2025 case EFI_IFR_SUBTRACT_OP:\r
2026 case EFI_IFR_MULTIPLY_OP:\r
2027 case EFI_IFR_DIVIDE_OP:\r
2028 case EFI_IFR_MODULO_OP:\r
2029 case EFI_IFR_BITWISE_AND_OP:\r
2030 case EFI_IFR_BITWISE_OR_OP:\r
2031 case EFI_IFR_SHIFT_LEFT_OP:\r
2032 case EFI_IFR_SHIFT_RIGHT_OP:\r
2033 //\r
2034 // Pop an expression from the expression stack\r
2035 //\r
2036 Status = PopExpression (&Data2);\r
2037 if (EFI_ERROR (Status)) {\r
2038 goto Done;\r
2039 }\r
2040 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
2041 Status = EFI_INVALID_PARAMETER;\r
2042 goto Done;\r
2043 }\r
2044\r
2045 //\r
2046 // Pop another expression from the expression stack\r
2047 //\r
2048 Status = PopExpression (&Data1);\r
2049 if (EFI_ERROR (Status)) {\r
2050 goto Done;\r
2051 }\r
2052 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
2053 Status = EFI_INVALID_PARAMETER;\r
2054 goto Done;\r
2055 }\r
2056\r
2057 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2058\r
2059 switch (OpCode->Operand) {\r
2060 case EFI_IFR_ADD_OP:\r
2061 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
2062 break;\r
2063\r
2064 case EFI_IFR_SUBTRACT_OP:\r
2065 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
2066 break;\r
2067\r
2068 case EFI_IFR_MULTIPLY_OP:\r
2069 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2070 break;\r
2071\r
2072 case EFI_IFR_DIVIDE_OP:\r
2073 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2074 break;\r
2075\r
2076 case EFI_IFR_MODULO_OP:\r
2077 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
2078 Value->Value.u64 = TempValue;\r
2079 break;\r
2080\r
2081 case EFI_IFR_BITWISE_AND_OP:\r
2082 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
2083 break;\r
2084\r
2085 case EFI_IFR_BITWISE_OR_OP:\r
2086 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
2087 break;\r
2088\r
2089 case EFI_IFR_SHIFT_LEFT_OP:\r
2090 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2091 break;\r
2092\r
2093 case EFI_IFR_SHIFT_RIGHT_OP:\r
2094 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2095 break;\r
2096\r
2097 default:\r
2098 break;\r
2099 }\r
2100 break;\r
2101\r
2102 case EFI_IFR_AND_OP:\r
2103 case EFI_IFR_OR_OP:\r
2104 //\r
2105 // Two Boolean operator\r
2106 //\r
2107 Status = PopExpression (&Data2);\r
2108 if (EFI_ERROR (Status)) {\r
2109 goto Done;\r
2110 }\r
2111 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2112 Status = EFI_INVALID_PARAMETER;\r
2113 goto Done;\r
2114 }\r
2115\r
2116 //\r
2117 // Pop another expression from the expression stack\r
2118 //\r
2119 Status = PopExpression (&Data1);\r
2120 if (EFI_ERROR (Status)) {\r
2121 goto Done;\r
2122 }\r
2123 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2124 Status = EFI_INVALID_PARAMETER;\r
2125 goto Done;\r
2126 }\r
2127\r
2128 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
2129 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
2130 } else {\r
2131 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
2132 }\r
2133 break;\r
2134\r
2135 case EFI_IFR_EQUAL_OP:\r
2136 case EFI_IFR_NOT_EQUAL_OP:\r
2137 case EFI_IFR_GREATER_EQUAL_OP:\r
2138 case EFI_IFR_GREATER_THAN_OP:\r
2139 case EFI_IFR_LESS_EQUAL_OP:\r
2140 case EFI_IFR_LESS_THAN_OP:\r
2141 //\r
2142 // Compare two integer, string, boolean or date/time\r
2143 //\r
2144 Status = PopExpression (&Data2);\r
2145 if (EFI_ERROR (Status)) {\r
2146 goto Done;\r
2147 }\r
2148 if ((Data2.Type > EFI_IFR_TYPE_BOOLEAN) && (Data2.Type != EFI_IFR_TYPE_STRING)) {\r
2149 Status = EFI_INVALID_PARAMETER;\r
2150 goto Done;\r
2151 }\r
2152\r
2153 //\r
2154 // Pop another expression from the expression stack\r
2155 //\r
2156 Status = PopExpression (&Data1);\r
2157 if (EFI_ERROR (Status)) {\r
2158 goto Done;\r
2159 }\r
2160\r
2161 Result = CompareHiiValue (&Data1, &Data2, FormSet);\r
2162 if ((EFI_STATUS)Result == EFI_INVALID_PARAMETER) {\r
2163 Status = EFI_INVALID_PARAMETER;\r
2164 goto Done;\r
2165 }\r
2166\r
2167 switch (OpCode->Operand) {\r
2168 case EFI_IFR_EQUAL_OP:\r
2169 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2170 break;\r
2171\r
2172 case EFI_IFR_NOT_EQUAL_OP:\r
2173 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
2174 break;\r
2175\r
2176 case EFI_IFR_GREATER_EQUAL_OP:\r
2177 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
2178 break;\r
2179\r
2180 case EFI_IFR_GREATER_THAN_OP:\r
2181 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
2182 break;\r
2183\r
2184 case EFI_IFR_LESS_EQUAL_OP:\r
2185 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
2186 break;\r
2187\r
2188 case EFI_IFR_LESS_THAN_OP:\r
2189 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
2190 break;\r
2191\r
2192 default:\r
2193 break;\r
2194 }\r
2195 break;\r
2196\r
2197 case EFI_IFR_MATCH_OP:\r
2198 Status = IfrMatch (FormSet, Value);\r
2199 break;\r
2200\r
2201 case EFI_IFR_CATENATE_OP:\r
2202 Status = IfrCatenate (FormSet, Value);\r
2203 break;\r
2204\r
2205 //\r
2206 // ternary-op\r
2207 //\r
2208 case EFI_IFR_CONDITIONAL_OP:\r
2209 //\r
2210 // Pop third expression from the expression stack\r
2211 //\r
2212 Status = PopExpression (&Data3);\r
2213 if (EFI_ERROR (Status)) {\r
2214 goto Done;\r
2215 }\r
2216\r
2217 //\r
2218 // Pop second expression from the expression stack\r
2219 //\r
2220 Status = PopExpression (&Data2);\r
2221 if (EFI_ERROR (Status)) {\r
2222 goto Done;\r
2223 }\r
2224\r
2225 //\r
2226 // Pop first expression from the expression stack\r
2227 //\r
2228 Status = PopExpression (&Data1);\r
2229 if (EFI_ERROR (Status)) {\r
2230 goto Done;\r
2231 }\r
2232 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2233 Status = EFI_INVALID_PARAMETER;\r
2234 goto Done;\r
2235 }\r
2236\r
2237 if (Data1.Value.b) {\r
2238 Value = &Data3;\r
2239 } else {\r
2240 Value = &Data2;\r
2241 }\r
2242 break;\r
2243\r
2244 case EFI_IFR_FIND_OP:\r
2245 Status = IfrFind (FormSet, OpCode->Format, Value);\r
2246 break;\r
2247\r
2248 case EFI_IFR_MID_OP:\r
2249 Status = IfrMid (FormSet, Value);\r
2250 break;\r
2251\r
2252 case EFI_IFR_TOKEN_OP:\r
2253 Status = IfrToken (FormSet, Value);\r
2254 break;\r
2255\r
2256 case EFI_IFR_SPAN_OP:\r
2257 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
2258 break;\r
2259\r
2260 case EFI_IFR_MAP_OP:\r
2261 //\r
2262 // Pop the check value\r
2263 //\r
2264 Status = PopExpression (&Data1);\r
2265 if (EFI_ERROR (Status)) {\r
2266 goto Done;\r
2267 }\r
2268 //\r
2269 // Check MapExpression list is valid.\r
2270 //\r
2271 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
2272 Status = EFI_INVALID_PARAMETER;\r
2273 goto Done;\r
2274 }\r
2275 //\r
2276 // Go through map expression list.\r
2277 //\r
2278 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
2279 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2280 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
2281 //\r
2282 // Evaluate the first expression in this pair.\r
2283 //\r
2284 Status = EvaluateExpression (FormSet, Form, SubExpression, ConstantExpression);\r
2285 if (EFI_ERROR (Status)) {\r
2286 goto Done;\r
2287 }\r
2288 //\r
2289 // Compare the expression value with current value\r
2290 //\r
2291 if (CompareHiiValue (&Data1, &SubExpression->Result, FormSet) == 0) {\r
2292 //\r
2293 // Try get the map value.\r
2294 //\r
2295 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2296 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2297 Status = EFI_INVALID_PARAMETER;\r
2298 goto Done;\r
2299 }\r
2300 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
2301 Status = EvaluateExpression (FormSet, Form, SubExpression, ConstantExpression);\r
2302 if (EFI_ERROR (Status)) {\r
2303 goto Done;\r
2304 }\r
2305 Value = &SubExpression->Result;\r
2306 break;\r
2307 }\r
2308 //\r
2309 // Skip the second expression on this pair.\r
2310 //\r
2311 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2312 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2313 Status = EFI_INVALID_PARAMETER;\r
2314 goto Done;\r
2315 }\r
2316 //\r
2317 // Goto the first expression on next pair.\r
2318 //\r
2319 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2320 }\r
2321\r
2322 //\r
2323 // No map value is found.\r
2324 //\r
2325 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2326 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2327 Value->Value.u8 = 0;\r
2328 }\r
2329 break;\r
2330\r
2331 default:\r
2332 break;\r
2333 }\r
2334 if (EFI_ERROR (Status)) {\r
2335 goto Done;\r
2336 }\r
2337\r
2338 Status = PushExpression (Value);\r
2339 if (EFI_ERROR (Status)) {\r
2340 goto Done;\r
2341 }\r
2342 }\r
2343\r
2344 //\r
2345 // Pop the final result from expression stack\r
2346 //\r
2347 Value = &Data1;\r
2348 Status = PopExpression (Value);\r
2349 if (EFI_ERROR (Status)) {\r
2350 goto Done;\r
2351 }\r
2352\r
2353 //\r
2354 // After evaluating an expression, there should be only one value left on the expression stack\r
2355 //\r
2356 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2357 Status = EFI_INVALID_PARAMETER;\r
2358 }\r
2359\r
2360Done:\r
2361 RestoreExpressionEvaluationStackOffset (StackOffset);\r
2362 if (!EFI_ERROR (Status)) {\r
2363 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
2364 }\r
2365\r
2366 return Status;\r
2367}\r