]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Invoke EFI_BROWSER_ACTION_RETRIEVE callback when read EfiVarstore question.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
8d00a0f1 4Copyright (c) 2007 - 2008, Intel Corporation\r
7936fb6a 5All rights reserved. This program and the accompanying materials\r
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
27\r
28//\r
29// Unicode collation protocol interface\r
30//\r
31EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
32\r
33\r
34/**\r
35 Grow size of the stack.\r
36\r
37 This is an internal function.\r
38\r
39 @param Stack On input: old stack; On output: new stack\r
40 @param StackPtr On input: old stack pointer; On output: new stack\r
41 pointer\r
42 @param StackEnd On input: old stack end; On output: new stack end\r
43\r
44 @retval EFI_SUCCESS Grow stack success.\r
45 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
46\r
47**/\r
48EFI_STATUS\r
49GrowStack (\r
50 IN OUT EFI_HII_VALUE **Stack,\r
51 IN OUT EFI_HII_VALUE **StackPtr,\r
52 IN OUT EFI_HII_VALUE **StackEnd\r
53 )\r
54{\r
55 UINTN Size;\r
56 EFI_HII_VALUE *NewStack;\r
57\r
58 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
59 if (*StackPtr != NULL) {\r
60 Size = Size + (*StackEnd - *Stack);\r
61 }\r
62\r
63 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
64 if (NewStack == NULL) {\r
65 return EFI_OUT_OF_RESOURCES;\r
66 }\r
67\r
68 if (*StackPtr != NULL) {\r
69 //\r
70 // Copy from Old Stack to the New Stack\r
71 //\r
72 CopyMem (\r
73 NewStack,\r
74 *Stack,\r
75 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
76 );\r
77\r
78 //\r
79 // Free The Old Stack\r
80 //\r
f4113e1f 81 FreePool (*Stack);\r
7936fb6a 82 }\r
83\r
84 //\r
85 // Make the Stack pointer point to the old data in the new stack\r
86 //\r
87 *StackPtr = NewStack + (*StackPtr - *Stack);\r
88 *Stack = NewStack;\r
89 *StackEnd = NewStack + Size;\r
90\r
91 return EFI_SUCCESS;\r
92}\r
93\r
94\r
95/**\r
96 Push an element onto the Boolean Stack.\r
97\r
98 @param Stack On input: old stack; On output: new stack\r
99 @param StackPtr On input: old stack pointer; On output: new stack\r
100 pointer\r
101 @param StackEnd On input: old stack end; On output: new stack end\r
102 @param Data Data to push.\r
103\r
104 @retval EFI_SUCCESS Push stack success.\r
105\r
106**/\r
107EFI_STATUS\r
108PushStack (\r
109 IN OUT EFI_HII_VALUE **Stack,\r
110 IN OUT EFI_HII_VALUE **StackPtr,\r
111 IN OUT EFI_HII_VALUE **StackEnd,\r
112 IN EFI_HII_VALUE *Data\r
113 )\r
114{\r
115 EFI_STATUS Status;\r
116\r
117 //\r
118 // Check for a stack overflow condition\r
119 //\r
120 if (*StackPtr >= *StackEnd) {\r
121 //\r
122 // Grow the stack\r
123 //\r
124 Status = GrowStack (Stack, StackPtr, StackEnd);\r
125 if (EFI_ERROR (Status)) {\r
126 return Status;\r
127 }\r
128 }\r
129\r
130 //\r
131 // Push the item onto the stack\r
132 //\r
133 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
134 *StackPtr = *StackPtr + 1;\r
135\r
136 return EFI_SUCCESS;\r
137}\r
138\r
139\r
140/**\r
141 Pop an element from the stack.\r
142\r
143 @param Stack On input: old stack; On output: new stack\r
144 @param StackPtr On input: old stack pointer; On output: new stack\r
145 pointer\r
146 @param StackEnd On input: old stack end; On output: new stack end\r
147 @param Data Data to pop.\r
148\r
149 @retval EFI_SUCCESS The value was popped onto the stack.\r
150 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
151\r
152**/\r
153EFI_STATUS\r
154PopStack (\r
155 IN OUT EFI_HII_VALUE **Stack,\r
156 IN OUT EFI_HII_VALUE **StackPtr,\r
157 IN OUT EFI_HII_VALUE **StackEnd,\r
158 OUT EFI_HII_VALUE *Data\r
159 )\r
160{\r
161 //\r
162 // Check for a stack underflow condition\r
163 //\r
164 if (*StackPtr == *Stack) {\r
165 return EFI_ACCESS_DENIED;\r
166 }\r
167\r
168 //\r
169 // Pop the item off the stack\r
170 //\r
171 *StackPtr = *StackPtr - 1;\r
172 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
173 return EFI_SUCCESS;\r
174}\r
175\r
176\r
177/**\r
178 Reset stack pointer to begin of the stack.\r
179\r
180**/\r
181VOID\r
182ResetScopeStack (\r
183 VOID\r
184 )\r
185{\r
186 mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
187}\r
188\r
189\r
190/**\r
191 Push an Operand onto the Stack\r
192\r
193 @param Operand Operand to push.\r
194\r
195 @retval EFI_SUCCESS The value was pushed onto the stack.\r
196 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
197 stack.\r
198\r
199**/\r
200EFI_STATUS\r
201PushScope (\r
202 IN UINT8 Operand\r
203 )\r
204{\r
205 EFI_HII_VALUE Data;\r
206\r
207 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
208 Data.Value.u8 = Operand;\r
209\r
210 return PushStack (\r
211 &mOpCodeScopeStack,\r
212 &mOpCodeScopeStackPointer,\r
213 &mOpCodeScopeStackEnd,\r
214 &Data\r
215 );\r
216}\r
217\r
218\r
219/**\r
220 Pop an Operand from the Stack\r
221\r
222 @param Operand Operand to pop.\r
223\r
224 @retval EFI_SUCCESS The value was pushed onto the stack.\r
225 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
226 stack.\r
227\r
228**/\r
229EFI_STATUS\r
230PopScope (\r
231 OUT UINT8 *Operand\r
232 )\r
233{\r
234 EFI_STATUS Status;\r
235 EFI_HII_VALUE Data;\r
236\r
237 Status = PopStack (\r
238 &mOpCodeScopeStack,\r
239 &mOpCodeScopeStackPointer,\r
240 &mOpCodeScopeStackEnd,\r
241 &Data\r
242 );\r
243\r
244 *Operand = Data.Value.u8;\r
245\r
246 return Status;\r
247}\r
248\r
249\r
250/**\r
251 Reset stack pointer to begin of the stack.\r
252\r
253**/\r
254VOID\r
255ResetExpressionStack (\r
256 VOID\r
257 )\r
258{\r
259 mExpressionEvaluationStackPointer = mExpressionEvaluationStack;\r
260}\r
261\r
262\r
263/**\r
264 Push an Expression value onto the Stack\r
265\r
266 @param Value Expression value to push.\r
267\r
268 @retval EFI_SUCCESS The value was pushed onto the stack.\r
269 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
270 stack.\r
271\r
272**/\r
273EFI_STATUS\r
274PushExpression (\r
275 IN EFI_HII_VALUE *Value\r
276 )\r
277{\r
278 return PushStack (\r
279 &mExpressionEvaluationStack,\r
280 &mExpressionEvaluationStackPointer,\r
281 &mExpressionEvaluationStackEnd,\r
282 Value\r
283 );\r
284}\r
285\r
286\r
287/**\r
288 Pop an Expression value from the stack.\r
289\r
290 @param Value Expression value to pop.\r
291\r
292 @retval EFI_SUCCESS The value was popped onto the stack.\r
293 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
294\r
295**/\r
296EFI_STATUS\r
297PopExpression (\r
298 OUT EFI_HII_VALUE *Value\r
299 )\r
300{\r
301 return PopStack (\r
302 &mExpressionEvaluationStack,\r
303 &mExpressionEvaluationStackPointer,\r
304 &mExpressionEvaluationStackEnd,\r
305 Value\r
306 );\r
307}\r
308\r
309\r
310/**\r
311 Get Form given its FormId.\r
312\r
313 @param FormSet The formset which contains this form.\r
314 @param FormId Id of this form.\r
315\r
316 @retval Pointer The form.\r
317 @retval NULL Specified Form is not found in the formset.\r
318\r
319**/\r
320FORM_BROWSER_FORM *\r
321IdToForm (\r
322 IN FORM_BROWSER_FORMSET *FormSet,\r
323 IN UINT16 FormId\r
324)\r
325{\r
326 LIST_ENTRY *Link;\r
327 FORM_BROWSER_FORM *Form;\r
328\r
329 Link = GetFirstNode (&FormSet->FormListHead);\r
330 while (!IsNull (&FormSet->FormListHead, Link)) {\r
331 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
332\r
333 if (Form->FormId == FormId) {\r
334 return Form;\r
335 }\r
336\r
337 Link = GetNextNode (&FormSet->FormListHead, Link);\r
338 }\r
339\r
340 return NULL;\r
341}\r
342\r
343\r
344/**\r
345 Search a Question in Form scope using its QuestionId.\r
346\r
347 @param Form The form which contains this Question.\r
348 @param QuestionId Id of this Question.\r
349\r
350 @retval Pointer The Question.\r
351 @retval NULL Specified Question not found in the form.\r
352\r
353**/\r
354FORM_BROWSER_STATEMENT *\r
355IdToQuestion2 (\r
356 IN FORM_BROWSER_FORM *Form,\r
357 IN UINT16 QuestionId\r
358 )\r
359{\r
360 LIST_ENTRY *Link;\r
361 FORM_BROWSER_STATEMENT *Question;\r
362\r
363 if (QuestionId == 0) {\r
364 //\r
365 // The value of zero is reserved\r
366 //\r
367 return NULL;\r
368 }\r
369\r
370 Link = GetFirstNode (&Form->StatementListHead);\r
371 while (!IsNull (&Form->StatementListHead, Link)) {\r
372 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
373\r
374 if (Question->QuestionId == QuestionId) {\r
375 return Question;\r
376 }\r
377\r
378 Link = GetNextNode (&Form->StatementListHead, Link);\r
379 }\r
380\r
381 return NULL;\r
382}\r
383\r
384\r
385/**\r
386 Search a Question in Formset scope using its QuestionId.\r
387\r
388 @param FormSet The formset which contains this form.\r
389 @param Form The form which contains this Question.\r
390 @param QuestionId Id of this Question.\r
391\r
392 @retval Pointer The Question.\r
393 @retval NULL Specified Question not found in the form.\r
394\r
395**/\r
396FORM_BROWSER_STATEMENT *\r
397IdToQuestion (\r
398 IN FORM_BROWSER_FORMSET *FormSet,\r
399 IN FORM_BROWSER_FORM *Form,\r
400 IN UINT16 QuestionId\r
401 )\r
402{\r
403 LIST_ENTRY *Link;\r
404 FORM_BROWSER_STATEMENT *Question;\r
405\r
406 //\r
407 // Search in the form scope first\r
408 //\r
409 Question = IdToQuestion2 (Form, QuestionId);\r
410 if (Question != NULL) {\r
411 return Question;\r
412 }\r
413\r
414 //\r
415 // Search in the formset scope\r
416 //\r
417 Link = GetFirstNode (&FormSet->FormListHead);\r
418 while (!IsNull (&FormSet->FormListHead, Link)) {\r
419 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
420\r
421 Question = IdToQuestion2 (Form, QuestionId);\r
422 if (Question != NULL) {\r
8d00a0f1 423 //\r
424 // EFI variable storage may be updated by Callback() asynchronous,\r
425 // to keep synchronous, always reload the Question Value.\r
426 //\r
427 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
428 GetQuestionValue (FormSet, Form, Question, FALSE);\r
429 }\r
430\r
7936fb6a 431 return Question;\r
432 }\r
433\r
434 Link = GetNextNode (&FormSet->FormListHead, Link);\r
435 }\r
436\r
437 return NULL;\r
438}\r
439\r
440\r
441/**\r
442 Get Expression given its RuleId.\r
443\r
444 @param Form The form which contains this Expression.\r
445 @param RuleId Id of this Expression.\r
446\r
447 @retval Pointer The Expression.\r
448 @retval NULL Specified Expression not found in the form.\r
449\r
450**/\r
451FORM_EXPRESSION *\r
452RuleIdToExpression (\r
453 IN FORM_BROWSER_FORM *Form,\r
454 IN UINT8 RuleId\r
455 )\r
456{\r
457 LIST_ENTRY *Link;\r
458 FORM_EXPRESSION *Expression;\r
459\r
460 Link = GetFirstNode (&Form->ExpressionListHead);\r
461 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
462 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
463\r
464 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
465 return Expression;\r
466 }\r
467\r
468 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
469 }\r
470\r
471 return NULL;\r
472}\r
473\r
474\r
475/**\r
476 Locate the Unicode Collation Protocol interface for later use.\r
477\r
478 @retval EFI_SUCCESS Protocol interface initialize success.\r
479 @retval Other Protocol interface initialize failed.\r
480\r
481**/\r
482EFI_STATUS\r
483InitializeUnicodeCollationProtocol (\r
484 VOID\r
485 )\r
486{\r
487 EFI_STATUS Status;\r
488\r
489 if (mUnicodeCollation != NULL) {\r
490 return EFI_SUCCESS;\r
491 }\r
492\r
493 //\r
494 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
495 // instances first and then select one which support English language.\r
496 // Current implementation just pick the first instance.\r
497 //\r
498 Status = gBS->LocateProtocol (\r
499 &gEfiUnicodeCollation2ProtocolGuid,\r
500 NULL,\r
501 (VOID **) &mUnicodeCollation\r
502 );\r
503 return Status;\r
504}\r
505\r
506/**\r
507 Convert the input Unicode character to upper.\r
508\r
509 @param String Th Unicode character to be converted.\r
510\r
511**/\r
512VOID\r
513IfrStrToUpper (\r
8b0fc5c1 514 IN CHAR16 *String\r
7936fb6a 515 )\r
516{\r
517 while (*String != 0) {\r
518 if ((*String >= 'a') && (*String <= 'z')) {\r
519 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
520 }\r
521 String++;\r
522 }\r
523}\r
524\r
525\r
526/**\r
527 Evaluate opcode EFI_IFR_TO_STRING.\r
528\r
529 @param FormSet Formset which contains this opcode.\r
530 @param Format String format in EFI_IFR_TO_STRING.\r
531 @param Result Evaluation result for this opcode.\r
532\r
533 @retval EFI_SUCCESS Opcode evaluation success.\r
534 @retval Other Opcode evaluation failed.\r
535\r
536**/\r
537EFI_STATUS\r
538IfrToString (\r
539 IN FORM_BROWSER_FORMSET *FormSet,\r
540 IN UINT8 Format,\r
541 OUT EFI_HII_VALUE *Result\r
542 )\r
543{\r
544 EFI_STATUS Status;\r
545 EFI_HII_VALUE Value;\r
546 CHAR16 *String;\r
547 CHAR16 *PrintFormat;\r
548 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
549 UINTN BufferSize;\r
550\r
551 Status = PopExpression (&Value);\r
552 if (EFI_ERROR (Status)) {\r
553 return Status;\r
554 }\r
555\r
556 switch (Value.Type) {\r
557 case EFI_IFR_TYPE_NUM_SIZE_8:\r
558 case EFI_IFR_TYPE_NUM_SIZE_16:\r
559 case EFI_IFR_TYPE_NUM_SIZE_32:\r
560 case EFI_IFR_TYPE_NUM_SIZE_64:\r
561 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
562 switch (Format) {\r
563 case EFI_IFR_STRING_UNSIGNED_DEC:\r
564 case EFI_IFR_STRING_SIGNED_DEC:\r
565 PrintFormat = L"%ld";\r
566 break;\r
567\r
568 case EFI_IFR_STRING_LOWERCASE_HEX:\r
569 PrintFormat = L"%lx";\r
570 break;\r
571\r
572 case EFI_IFR_STRING_UPPERCASE_HEX:\r
573 PrintFormat = L"%lX";\r
574 break;\r
575\r
576 default:\r
577 return EFI_UNSUPPORTED;\r
578 }\r
579 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
580 String = Buffer;\r
581 break;\r
582\r
583 case EFI_IFR_TYPE_STRING:\r
584 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
585 return EFI_SUCCESS;\r
586\r
587 case EFI_IFR_TYPE_BOOLEAN:\r
588 String = (Value.Value.b) ? L"True" : L"False";\r
589 break;\r
590\r
591 default:\r
592 return EFI_UNSUPPORTED;\r
593 }\r
594\r
595 Result->Type = EFI_IFR_TYPE_STRING;\r
596 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
597 return EFI_SUCCESS;\r
598}\r
599\r
600\r
601/**\r
602 Evaluate opcode EFI_IFR_TO_UINT.\r
603\r
604 @param FormSet Formset which contains this opcode.\r
605 @param Result Evaluation result for this opcode.\r
606\r
607 @retval EFI_SUCCESS Opcode evaluation success.\r
608 @retval Other Opcode evaluation failed.\r
609\r
610**/\r
611EFI_STATUS\r
612IfrToUint (\r
613 IN FORM_BROWSER_FORMSET *FormSet,\r
614 OUT EFI_HII_VALUE *Result\r
615 )\r
616{\r
617 EFI_STATUS Status;\r
618 EFI_HII_VALUE Value;\r
619 CHAR16 *String;\r
620 CHAR16 *StringPtr;\r
7936fb6a 621\r
622 Status = PopExpression (&Value);\r
623 if (EFI_ERROR (Status)) {\r
624 return Status;\r
625 }\r
626\r
627 if (Value.Type >= EFI_IFR_TYPE_OTHER) {\r
628 return EFI_UNSUPPORTED;\r
629 }\r
630\r
631 Status = EFI_SUCCESS;\r
632 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
633 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
634 if (String == NULL) {\r
635 return EFI_NOT_FOUND;\r
636 }\r
8b0fc5c1 637\r
7936fb6a 638 IfrStrToUpper (String);\r
639 StringPtr = StrStr (String, L"0X");\r
640 if (StringPtr != NULL) {\r
641 //\r
642 // Hex string\r
643 //\r
ac7e320c 644 Result->Value.u64 = StrHexToUint64 (String);\r
7936fb6a 645 } else {\r
646 //\r
ac7e320c 647 // decimal string\r
7936fb6a 648 //\r
ac7e320c 649 Result->Value.u64 = StrDecimalToUint64 (String);\r
7936fb6a 650 }\r
f4113e1f 651 FreePool (String);\r
7936fb6a 652 } else {\r
653 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
654 }\r
655\r
656 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
657 return Status;\r
658}\r
659\r
660\r
661/**\r
662 Evaluate opcode EFI_IFR_CATENATE.\r
663\r
664 @param FormSet Formset which contains this opcode.\r
665 @param Result Evaluation result for this opcode.\r
666\r
667 @retval EFI_SUCCESS Opcode evaluation success.\r
668 @retval Other Opcode evaluation failed.\r
669\r
670**/\r
671EFI_STATUS\r
672IfrCatenate (\r
673 IN FORM_BROWSER_FORMSET *FormSet,\r
674 OUT EFI_HII_VALUE *Result\r
675 )\r
676{\r
677 EFI_STATUS Status;\r
678 EFI_HII_VALUE Value;\r
679 CHAR16 *String[2];\r
680 UINTN Index;\r
681 CHAR16 *StringPtr;\r
682 UINTN Size;\r
683\r
684 //\r
685 // String[0] - The second string\r
686 // String[1] - The first string\r
687 //\r
688 String[0] = NULL;\r
689 String[1] = NULL;\r
690 StringPtr = NULL;\r
691 Status = EFI_SUCCESS;\r
692\r
693 for (Index = 0; Index < 2; Index++) {\r
694 Status = PopExpression (&Value);\r
695 if (EFI_ERROR (Status)) {\r
696 goto Done;\r
697 }\r
698\r
699 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
700 Status = EFI_UNSUPPORTED;\r
701 goto Done;\r
702 }\r
703\r
704 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 705 if (String[Index] == NULL) {\r
7936fb6a 706 Status = EFI_NOT_FOUND;\r
707 goto Done;\r
708 }\r
709 }\r
710\r
711 Size = StrSize (String[0]);\r
712 StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
713 ASSERT (StringPtr != NULL);\r
714 StrCpy (StringPtr, String[1]);\r
715 StrCat (StringPtr, String[0]);\r
716\r
717 Result->Type = EFI_IFR_TYPE_STRING;\r
718 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
719\r
720Done:\r
676df92c 721 if (String[0] != NULL) {\r
722 FreePool (String[0]);\r
723 }\r
724 if (String[1] != NULL) {\r
725 FreePool (String[1]);\r
8b0fc5c1 726 }\r
676df92c 727 if (StringPtr != NULL) {\r
728 FreePool (StringPtr);\r
729 }\r
7936fb6a 730\r
731 return Status;\r
732}\r
733\r
734\r
735/**\r
736 Evaluate opcode EFI_IFR_MATCH.\r
737\r
738 @param FormSet Formset which contains this opcode.\r
739 @param Result Evaluation result for this opcode.\r
740\r
741 @retval EFI_SUCCESS Opcode evaluation success.\r
742 @retval Other Opcode evaluation failed.\r
743\r
744**/\r
745EFI_STATUS\r
746IfrMatch (\r
747 IN FORM_BROWSER_FORMSET *FormSet,\r
748 OUT EFI_HII_VALUE *Result\r
749 )\r
750{\r
751 EFI_STATUS Status;\r
752 EFI_HII_VALUE Value;\r
753 CHAR16 *String[2];\r
754 UINTN Index;\r
755\r
756 //\r
757 // String[0] - The string to search\r
758 // String[1] - pattern\r
759 //\r
760 String[0] = NULL;\r
761 String[1] = NULL;\r
762 Status = EFI_SUCCESS;\r
763 for (Index = 0; Index < 2; Index++) {\r
764 Status = PopExpression (&Value);\r
765 if (EFI_ERROR (Status)) {\r
766 goto Done;\r
767 }\r
768\r
769 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
770 Status = EFI_UNSUPPORTED;\r
771 goto Done;\r
772 }\r
773\r
774 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
bc166db3 775 if (String [Index] == NULL) {\r
7936fb6a 776 Status = EFI_NOT_FOUND;\r
777 goto Done;\r
778 }\r
779 }\r
780\r
781 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
782 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
783\r
784Done:\r
676df92c 785 if (String[0] != NULL) {\r
786 FreePool (String[0]);\r
787 }\r
788 if (String[1] != NULL) {\r
789 FreePool (String[1]);\r
8b0fc5c1 790 }\r
7936fb6a 791\r
792 return Status;\r
793}\r
794\r
795\r
796/**\r
797 Evaluate opcode EFI_IFR_FIND.\r
798\r
799 @param FormSet Formset which contains this opcode.\r
800 @param Format Case sensitive or insensitive.\r
801 @param Result Evaluation result for this opcode.\r
802\r
803 @retval EFI_SUCCESS Opcode evaluation success.\r
804 @retval Other Opcode evaluation failed.\r
805\r
806**/\r
807EFI_STATUS\r
808IfrFind (\r
809 IN FORM_BROWSER_FORMSET *FormSet,\r
810 IN UINT8 Format,\r
811 OUT EFI_HII_VALUE *Result\r
812 )\r
813{\r
814 EFI_STATUS Status;\r
815 EFI_HII_VALUE Value;\r
816 CHAR16 *String[2];\r
817 UINTN Base;\r
818 CHAR16 *StringPtr;\r
819 UINTN Index;\r
820\r
821 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
822 return EFI_UNSUPPORTED;\r
823 }\r
824\r
825 Status = PopExpression (&Value);\r
826 if (EFI_ERROR (Status)) {\r
827 return Status;\r
828 }\r
829 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
830 return EFI_UNSUPPORTED;\r
831 }\r
832 Base = (UINTN) Value.Value.u64;\r
833\r
834 //\r
835 // String[0] - sub-string\r
836 // String[1] - The string to search\r
837 //\r
838 String[0] = NULL;\r
839 String[1] = NULL;\r
840 for (Index = 0; Index < 2; Index++) {\r
841 Status = PopExpression (&Value);\r
842 if (EFI_ERROR (Status)) {\r
843 goto Done;\r
844 }\r
845\r
846 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
847 Status = EFI_UNSUPPORTED;\r
848 goto Done;\r
849 }\r
850\r
851 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 852 if (String[Index] == NULL) {\r
7936fb6a 853 Status = EFI_NOT_FOUND;\r
854 goto Done;\r
855 }\r
856\r
857 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
858 //\r
859 // Case insensitive, convert both string to upper case\r
860 //\r
861 IfrStrToUpper (String[Index]);\r
862 }\r
863 }\r
864\r
865 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
866 if (Base >= StrLen (String[1])) {\r
867 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
868 } else {\r
869 StringPtr = StrStr (String[1] + Base, String[0]);\r
870 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
871 }\r
872\r
873Done:\r
676df92c 874 if (String[0] != NULL) {\r
875 FreePool (String[0]);\r
876 }\r
877 if (String[1] != NULL) {\r
878 FreePool (String[1]);\r
8b0fc5c1 879 }\r
7936fb6a 880\r
881 return Status;\r
882}\r
883\r
884\r
885/**\r
886 Evaluate opcode EFI_IFR_MID.\r
887\r
888 @param FormSet Formset which contains this opcode.\r
889 @param Result Evaluation result for this opcode.\r
890\r
891 @retval EFI_SUCCESS Opcode evaluation success.\r
892 @retval Other Opcode evaluation failed.\r
893\r
894**/\r
895EFI_STATUS\r
896IfrMid (\r
897 IN FORM_BROWSER_FORMSET *FormSet,\r
898 OUT EFI_HII_VALUE *Result\r
899 )\r
900{\r
901 EFI_STATUS Status;\r
902 EFI_HII_VALUE Value;\r
903 CHAR16 *String;\r
904 UINTN Base;\r
905 UINTN Length;\r
906 CHAR16 *SubString;\r
907\r
908 Status = PopExpression (&Value);\r
909 if (EFI_ERROR (Status)) {\r
910 return Status;\r
911 }\r
912 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
913 return EFI_UNSUPPORTED;\r
914 }\r
915 Length = (UINTN) Value.Value.u64;\r
916\r
917 Status = PopExpression (&Value);\r
918 if (EFI_ERROR (Status)) {\r
919 return Status;\r
920 }\r
921 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
922 return EFI_UNSUPPORTED;\r
923 }\r
924 Base = (UINTN) Value.Value.u64;\r
925\r
926 Status = PopExpression (&Value);\r
927 if (EFI_ERROR (Status)) {\r
928 return Status;\r
929 }\r
930 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
931 return EFI_UNSUPPORTED;\r
932 }\r
933 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
934 if (String == NULL) {\r
935 return EFI_NOT_FOUND;\r
936 }\r
937\r
938 if (Length == 0 || Base >= StrLen (String)) {\r
939 SubString = gEmptyString;\r
940 } else {\r
941 SubString = String + Base;\r
942 if ((Base + Length) < StrLen (String)) {\r
943 SubString[Length] = L'\0';\r
944 }\r
945 }\r
946\r
947 Result->Type = EFI_IFR_TYPE_STRING;\r
948 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
949\r
f4113e1f 950 FreePool (String);\r
7936fb6a 951\r
952 return Status;\r
953}\r
954\r
955\r
956/**\r
957 Evaluate opcode EFI_IFR_TOKEN.\r
958\r
959 @param FormSet Formset which contains this opcode.\r
960 @param Result Evaluation result for this opcode.\r
961\r
962 @retval EFI_SUCCESS Opcode evaluation success.\r
963 @retval Other Opcode evaluation failed.\r
964\r
965**/\r
966EFI_STATUS\r
967IfrToken (\r
968 IN FORM_BROWSER_FORMSET *FormSet,\r
969 OUT EFI_HII_VALUE *Result\r
970 )\r
971{\r
972 EFI_STATUS Status;\r
973 EFI_HII_VALUE Value;\r
974 CHAR16 *String[2];\r
975 UINTN Count;\r
976 CHAR16 *Delimiter;\r
977 CHAR16 *SubString;\r
978 CHAR16 *StringPtr;\r
979 UINTN Index;\r
980\r
981 Status = PopExpression (&Value);\r
982 if (EFI_ERROR (Status)) {\r
983 return Status;\r
984 }\r
985 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
986 return EFI_UNSUPPORTED;\r
987 }\r
988 Count = (UINTN) Value.Value.u64;\r
989\r
990 //\r
991 // String[0] - Delimiter\r
992 // String[1] - The string to search\r
993 //\r
994 String[0] = NULL;\r
995 String[1] = NULL;\r
996 for (Index = 0; Index < 2; Index++) {\r
997 Status = PopExpression (&Value);\r
998 if (EFI_ERROR (Status)) {\r
999 goto Done;\r
1000 }\r
1001\r
1002 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1003 Status = EFI_UNSUPPORTED;\r
1004 goto Done;\r
1005 }\r
1006\r
1007 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 1008 if (String[Index] == NULL) {\r
7936fb6a 1009 Status = EFI_NOT_FOUND;\r
1010 goto Done;\r
1011 }\r
1012 }\r
1013\r
1014 Delimiter = String[0];\r
1015 SubString = String[1];\r
1016 while (Count > 0) {\r
1017 SubString = StrStr (SubString, Delimiter);\r
1018 if (SubString != NULL) {\r
1019 //\r
1020 // Skip over the delimiter\r
1021 //\r
1022 SubString = SubString + StrLen (Delimiter);\r
1023 } else {\r
1024 break;\r
1025 }\r
1026 Count--;\r
1027 }\r
1028\r
1029 if (SubString == NULL) {\r
1030 //\r
1031 // nth delimited sub-string not found, push an empty string\r
1032 //\r
1033 SubString = gEmptyString;\r
1034 } else {\r
1035 //\r
1036 // Put a NULL terminator for nth delimited sub-string\r
1037 //\r
1038 StringPtr = StrStr (SubString, Delimiter);\r
1039 if (StringPtr != NULL) {\r
1040 *StringPtr = L'\0';\r
1041 }\r
1042 }\r
1043\r
1044 Result->Type = EFI_IFR_TYPE_STRING;\r
1045 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1046\r
1047Done:\r
676df92c 1048 if (String[0] != NULL) {\r
1049 FreePool (String[0]);\r
1050 }\r
1051 if (String[1] != NULL) {\r
1052 FreePool (String[1]);\r
8b0fc5c1 1053 }\r
7936fb6a 1054\r
1055 return Status;\r
1056}\r
1057\r
1058\r
1059/**\r
1060 Evaluate opcode EFI_IFR_SPAN.\r
1061\r
1062 @param FormSet Formset which contains this opcode.\r
1063 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\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
1071IfrSpan (\r
1072 IN FORM_BROWSER_FORMSET *FormSet,\r
1073 IN UINT8 Flags,\r
1074 OUT EFI_HII_VALUE *Result\r
1075 )\r
1076{\r
1077 EFI_STATUS Status;\r
1078 EFI_HII_VALUE Value;\r
1079 CHAR16 *String[2];\r
1080 CHAR16 *Charset;\r
1081 UINTN Base;\r
1082 UINTN Index;\r
1083 CHAR16 *StringPtr;\r
1084 BOOLEAN Found;\r
1085\r
1086 Status = PopExpression (&Value);\r
1087 if (EFI_ERROR (Status)) {\r
1088 return Status;\r
1089 }\r
1090 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1091 return EFI_UNSUPPORTED;\r
1092 }\r
1093 Base = (UINTN) Value.Value.u64;\r
1094\r
1095 //\r
1096 // String[0] - Charset\r
1097 // String[1] - The string to search\r
1098 //\r
1099 String[0] = NULL;\r
1100 String[1] = NULL;\r
1101 for (Index = 0; Index < 2; Index++) {\r
1102 Status = PopExpression (&Value);\r
1103 if (EFI_ERROR (Status)) {\r
1104 goto Done;\r
1105 }\r
1106\r
1107 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1108 Status = EFI_UNSUPPORTED;\r
1109 goto Done;\r
1110 }\r
1111\r
1112 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
bc166db3 1113 if (String [Index] == NULL) {\r
7936fb6a 1114 Status = EFI_NOT_FOUND;\r
1115 goto Done;\r
1116 }\r
1117 }\r
1118\r
1119 if (Base >= StrLen (String[1])) {\r
1120 Status = EFI_UNSUPPORTED;\r
1121 goto Done;\r
1122 }\r
1123\r
1124 Found = FALSE;\r
1125 StringPtr = String[1] + Base;\r
1126 Charset = String[0];\r
1127 while (*StringPtr != 0 && !Found) {\r
1128 Index = 0;\r
1129 while (Charset[Index] != 0) {\r
1130 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
1131 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1132 Found = TRUE;\r
1133 break;\r
1134 }\r
1135 } else {\r
1136 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1137 Found = TRUE;\r
1138 break;\r
1139 }\r
1140 }\r
1141 //\r
1142 // Skip characters pair representing low-end of a range and high-end of a range\r
1143 //\r
1144 Index += 2;\r
1145 }\r
1146\r
1147 if (!Found) {\r
1148 StringPtr++;\r
1149 }\r
1150 }\r
1151\r
1152 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1153 Result->Value.u64 = StringPtr - String[1];\r
1154\r
1155Done:\r
676df92c 1156 if (String[0] != NULL) {\r
1157 FreePool (String[0]);\r
1158 }\r
1159 if (String[1] != NULL) {\r
1160 FreePool (String[1]);\r
8b0fc5c1 1161 }\r
7936fb6a 1162\r
1163 return Status;\r
1164}\r
1165\r
1166\r
1167/**\r
1168 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1169\r
1170 @param Value HII Value to be converted.\r
1171\r
1172**/\r
1173VOID\r
1174ExtendValueToU64 (\r
1175 IN EFI_HII_VALUE *Value\r
1176 )\r
1177{\r
1178 UINT64 Temp;\r
1179\r
1180 Temp = 0;\r
1181 switch (Value->Type) {\r
1182 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1183 Temp = Value->Value.u8;\r
1184 break;\r
1185\r
1186 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1187 Temp = Value->Value.u16;\r
1188 break;\r
1189\r
1190 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1191 Temp = Value->Value.u32;\r
1192 break;\r
1193\r
1194 case EFI_IFR_TYPE_BOOLEAN:\r
1195 Temp = Value->Value.b;\r
1196 break;\r
1197\r
1198 case EFI_IFR_TYPE_TIME:\r
1199 Temp = Value->Value.u32 & 0xffffff;\r
1200 break;\r
1201\r
1202 case EFI_IFR_TYPE_DATE:\r
1203 Temp = Value->Value.u32;\r
1204 break;\r
1205\r
1206 default:\r
1207 return;\r
1208 }\r
1209\r
1210 Value->Value.u64 = Temp;\r
1211}\r
1212\r
1213\r
1214/**\r
1215 Compare two Hii value.\r
1216\r
1217 @param Value1 Expression value to compare on left-hand.\r
1218 @param Value2 Expression value to compare on right-hand.\r
1219 @param HiiHandle Only required for string compare.\r
1220\r
1221 @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.\r
1222 @retval 0 Two operators equeal.\r
1223 @return Positive value if Value1 is greater than Value2.\r
1224 @retval Negative value if Value1 is less than Value2.\r
1225\r
1226**/\r
1227INTN\r
1228CompareHiiValue (\r
1229 IN EFI_HII_VALUE *Value1,\r
1230 IN EFI_HII_VALUE *Value2,\r
1231 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
1232 )\r
1233{\r
1234 INTN Result;\r
1235 INT64 Temp64;\r
1236 CHAR16 *Str1;\r
1237 CHAR16 *Str2;\r
1238\r
1239 if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
1240 return EFI_INVALID_PARAMETER;\r
1241 }\r
1242\r
1243 if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
1244 if (Value1->Type != Value2->Type) {\r
1245 //\r
1246 // Both Operator should be type of String\r
1247 //\r
1248 return EFI_INVALID_PARAMETER;\r
1249 }\r
1250\r
1251 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
1252 //\r
1253 // StringId 0 is reserved\r
1254 //\r
1255 return EFI_INVALID_PARAMETER;\r
1256 }\r
1257\r
1258 if (Value1->Value.string == Value2->Value.string) {\r
1259 return 0;\r
1260 }\r
1261\r
1262 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
1263 if (Str1 == NULL) {\r
1264 //\r
1265 // String not found\r
1266 //\r
1267 return EFI_INVALID_PARAMETER;\r
1268 }\r
1269\r
1270 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
1271 if (Str2 == NULL) {\r
f4113e1f 1272 FreePool (Str1);\r
7936fb6a 1273 return EFI_INVALID_PARAMETER;\r
1274 }\r
1275\r
1276 Result = StrCmp (Str1, Str2);\r
1277\r
f4113e1f 1278 FreePool (Str1);\r
1279 FreePool (Str2);\r
7936fb6a 1280\r
1281 return Result;\r
1282 }\r
1283\r
1284 //\r
1285 // Take remain types(integer, boolean, date/time) as integer\r
1286 //\r
1287 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
1288 if (Temp64 > 0) {\r
1289 Result = 1;\r
1290 } else if (Temp64 < 0) {\r
1291 Result = -1;\r
1292 } else {\r
1293 Result = 0;\r
1294 }\r
1295\r
1296 return Result;\r
1297}\r
1298\r
1299\r
1300/**\r
bc166db3 1301 Evaluate the result of a HII expression.\r
1302\r
1303 If Expression is NULL, then ASSERT.\r
7936fb6a 1304\r
1305 @param FormSet FormSet associated with this expression.\r
1306 @param Form Form associated with this expression.\r
1307 @param Expression Expression to be evaluated.\r
1308\r
1309 @retval EFI_SUCCESS The expression evaluated successfuly\r
1310 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
1311 could not be found.\r
1312 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
1313 stack.\r
1314 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
1315 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
1316\r
1317**/\r
1318EFI_STATUS\r
1319EvaluateExpression (\r
1320 IN FORM_BROWSER_FORMSET *FormSet,\r
1321 IN FORM_BROWSER_FORM *Form,\r
1322 IN OUT FORM_EXPRESSION *Expression\r
1323 )\r
1324{\r
1325 EFI_STATUS Status;\r
1326 LIST_ENTRY *Link;\r
1327 EXPRESSION_OPCODE *OpCode;\r
1328 FORM_BROWSER_STATEMENT *Question;\r
1329 FORM_BROWSER_STATEMENT *Question2;\r
1330 UINT16 Index;\r
1331 EFI_HII_VALUE Data1;\r
1332 EFI_HII_VALUE Data2;\r
1333 EFI_HII_VALUE Data3;\r
1334 FORM_EXPRESSION *RuleExpression;\r
1335 EFI_HII_VALUE *Value;\r
1336 INTN Result;\r
1337 CHAR16 *StrPtr;\r
1338 UINT32 TempValue;\r
1339\r
1340 //\r
1341 // Always reset the stack before evaluating an Expression\r
1342 //\r
1343 ResetExpressionStack ();\r
1344\r
bc166db3 1345 ASSERT (Expression != NULL);\r
7936fb6a 1346 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
1347\r
1348 Link = GetFirstNode (&Expression->OpCodeListHead);\r
1349 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
1350 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
1351\r
1352 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
1353\r
1354 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
1355 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
1356 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
1357\r
1358 Value = &Data3;\r
1359 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1360 Status = EFI_SUCCESS;\r
1361\r
1362 switch (OpCode->Operand) {\r
1363 //\r
1364 // Built-in functions\r
1365 //\r
1366 case EFI_IFR_EQ_ID_VAL_OP:\r
1367 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1368 if (Question == NULL) {\r
1369 return EFI_NOT_FOUND;\r
1370 }\r
1371\r
1372 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
1373 if (Result == EFI_INVALID_PARAMETER) {\r
1374 return EFI_INVALID_PARAMETER;\r
1375 }\r
1376 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1377 break;\r
1378\r
1379 case EFI_IFR_EQ_ID_ID_OP:\r
1380 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1381 if (Question == NULL) {\r
1382 return EFI_NOT_FOUND;\r
1383 }\r
1384\r
1385 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
1386 if (Question2 == NULL) {\r
1387 return EFI_NOT_FOUND;\r
1388 }\r
1389\r
1390 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
1391 if (Result == EFI_INVALID_PARAMETER) {\r
1392 return EFI_INVALID_PARAMETER;\r
1393 }\r
1394 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1395 break;\r
1396\r
1397 case EFI_IFR_EQ_ID_LIST_OP:\r
1398 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1399 if (Question == NULL) {\r
1400 return EFI_NOT_FOUND;\r
1401 }\r
1402\r
1403 Value->Value.b = FALSE;\r
1404 for (Index =0; Index < OpCode->ListLength; Index++) {\r
1405 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
1406 Value->Value.b = TRUE;\r
1407 break;\r
1408 }\r
1409 }\r
1410 break;\r
1411\r
1412 case EFI_IFR_DUP_OP:\r
1413 Status = PopExpression (Value);\r
1414 if (EFI_ERROR (Status)) {\r
1415 return Status;\r
1416 }\r
1417\r
1418 Status = PushExpression (Value);\r
1419 break;\r
1420\r
1421 case EFI_IFR_QUESTION_REF1_OP:\r
1422 case EFI_IFR_THIS_OP:\r
1423 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1424 if (Question == NULL) {\r
1425 return EFI_NOT_FOUND;\r
1426 }\r
1427\r
1428 Value = &Question->HiiValue;\r
1429 break;\r
1430\r
1431 case EFI_IFR_QUESTION_REF3_OP:\r
1432 if (OpCode->DevicePath == 0) {\r
1433 //\r
1434 // EFI_IFR_QUESTION_REF3\r
1435 // Pop an expression from the expression stack\r
1436 //\r
1437 Status = PopExpression (Value);\r
1438 if (EFI_ERROR (Status)) {\r
1439 return Status;\r
1440 }\r
1441\r
1442 //\r
1443 // Validate the expression value\r
1444 //\r
1445 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1446 return EFI_NOT_FOUND;\r
1447 }\r
1448\r
1449 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1450 if (Question == NULL) {\r
1451 return EFI_NOT_FOUND;\r
1452 }\r
1453\r
1454 //\r
1455 // push the questions' value on to the expression stack\r
1456 //\r
1457 Value = &Question->HiiValue;\r
1458 } else {\r
1459 //\r
1460 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
1461 // since it is impractical to evaluate the value of a Question in another\r
1462 // Hii Package list.\r
1463 //\r
1464 ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
1465 }\r
1466 break;\r
1467\r
1468 case EFI_IFR_RULE_REF_OP:\r
1469 //\r
1470 // Find expression for this rule\r
1471 //\r
1472 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
1473 if (RuleExpression == NULL) {\r
1474 return EFI_NOT_FOUND;\r
1475 }\r
1476\r
1477 //\r
1478 // Evaluate this rule expression\r
1479 //\r
1480 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
1481 if (EFI_ERROR (Status)) {\r
1482 return Status;\r
1483 }\r
1484\r
1485 Value = &RuleExpression->Result;\r
1486 break;\r
1487\r
1488 case EFI_IFR_STRING_REF1_OP:\r
1489 Value->Type = EFI_IFR_TYPE_STRING;\r
1490 Value->Value.string = OpCode->Value.Value.string;\r
1491 break;\r
1492\r
1493 //\r
1494 // Constant\r
1495 //\r
1496 case EFI_IFR_TRUE_OP:\r
1497 case EFI_IFR_FALSE_OP:\r
1498 case EFI_IFR_ONE_OP:\r
1499 case EFI_IFR_ONES_OP:\r
1500 case EFI_IFR_UINT8_OP:\r
1501 case EFI_IFR_UINT16_OP:\r
1502 case EFI_IFR_UINT32_OP:\r
1503 case EFI_IFR_UINT64_OP:\r
1504 case EFI_IFR_UNDEFINED_OP:\r
1505 case EFI_IFR_VERSION_OP:\r
1506 case EFI_IFR_ZERO_OP:\r
1507 Value = &OpCode->Value;\r
1508 break;\r
1509\r
1510 //\r
1511 // unary-op\r
1512 //\r
1513 case EFI_IFR_LENGTH_OP:\r
1514 Status = PopExpression (Value);\r
1515 if (EFI_ERROR (Status)) {\r
1516 return Status;\r
1517 }\r
1518 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1519 return EFI_INVALID_PARAMETER;\r
1520 }\r
1521\r
1522 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1523 if (StrPtr == NULL) {\r
1524 return EFI_INVALID_PARAMETER;\r
1525 }\r
1526\r
1527 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1528 Value->Value.u64 = StrLen (StrPtr);\r
f4113e1f 1529 FreePool (StrPtr);\r
7936fb6a 1530 break;\r
1531\r
1532 case EFI_IFR_NOT_OP:\r
1533 Status = PopExpression (Value);\r
1534 if (EFI_ERROR (Status)) {\r
1535 return Status;\r
1536 }\r
1537 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
1538 return EFI_INVALID_PARAMETER;\r
1539 }\r
1540 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
1541 break;\r
1542\r
1543 case EFI_IFR_QUESTION_REF2_OP:\r
1544 //\r
1545 // Pop an expression from the expression stack\r
1546 //\r
1547 Status = PopExpression (Value);\r
1548 if (EFI_ERROR (Status)) {\r
1549 return Status;\r
1550 }\r
1551\r
1552 //\r
1553 // Validate the expression value\r
1554 //\r
1555 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1556 return EFI_NOT_FOUND;\r
1557 }\r
1558\r
1559 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1560 if (Question == NULL) {\r
1561 return EFI_NOT_FOUND;\r
1562 }\r
1563\r
1564 Value = &Question->HiiValue;\r
1565 break;\r
1566\r
1567 case EFI_IFR_STRING_REF2_OP:\r
1568 //\r
1569 // Pop an expression from the expression stack\r
1570 //\r
1571 Status = PopExpression (Value);\r
1572 if (EFI_ERROR (Status)) {\r
1573 return Status;\r
1574 }\r
1575\r
1576 //\r
1577 // Validate the expression value\r
1578 //\r
1579 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1580 return EFI_NOT_FOUND;\r
1581 }\r
1582\r
1583 Value->Type = EFI_IFR_TYPE_STRING;\r
1584 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
1585 if (StrPtr == NULL) {\r
1586 //\r
1587 // If String not exit, push an empty string\r
1588 //\r
1589 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
1590 } else {\r
1591 Index = (UINT16) Value->Value.u64;\r
1592 Value->Value.string = Index;\r
f4113e1f 1593 FreePool (StrPtr);\r
7936fb6a 1594 }\r
1595 break;\r
1596\r
1597 case EFI_IFR_TO_BOOLEAN_OP:\r
1598 //\r
1599 // Pop an expression from the expression stack\r
1600 //\r
1601 Status = PopExpression (Value);\r
1602 if (EFI_ERROR (Status)) {\r
1603 return Status;\r
1604 }\r
1605\r
1606 //\r
1607 // Convert an expression to a Boolean\r
1608 //\r
1609 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
1610 //\r
1611 // When converting from an unsigned integer, zero will be converted to\r
1612 // FALSE and any other value will be converted to TRUE.\r
1613 //\r
1614 Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);\r
1615\r
1616 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1617 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
1618 //\r
1619 // When converting from a string, if case-insensitive compare\r
1620 // with "true" is True, then push True. If a case-insensitive compare\r
1621 // with "false" is True, then push False.\r
1622 //\r
1623 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1624 if (StrPtr == NULL) {\r
1625 return EFI_INVALID_PARAMETER;\r
1626 }\r
1627\r
1628 if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){\r
1629 Value->Value.b = TRUE;\r
1630 } else {\r
1631 Value->Value.b = FALSE;\r
1632 }\r
f4113e1f 1633 FreePool (StrPtr);\r
7936fb6a 1634 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1635 }\r
1636 break;\r
1637\r
1638 case EFI_IFR_TO_STRING_OP:\r
1639 Status = IfrToString (FormSet, OpCode->Format, Value);\r
1640 break;\r
1641\r
1642 case EFI_IFR_TO_UINT_OP:\r
1643 Status = IfrToUint (FormSet, Value);\r
1644 break;\r
1645\r
1646 case EFI_IFR_TO_LOWER_OP:\r
1647 case EFI_IFR_TO_UPPER_OP:\r
1648 Status = InitializeUnicodeCollationProtocol ();\r
1649 if (EFI_ERROR (Status)) {\r
1650 return Status;\r
1651 }\r
1652\r
1653 Status = PopExpression (Value);\r
1654 if (EFI_ERROR (Status)) {\r
1655 return Status;\r
1656 }\r
1657\r
1658 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1659 return EFI_UNSUPPORTED;\r
1660 }\r
1661\r
1662 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1663 if (StrPtr == NULL) {\r
1664 return EFI_NOT_FOUND;\r
1665 }\r
1666\r
1667 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
1668 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
1669 } else {\r
1670 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
1671 }\r
1672 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 1673 FreePool (StrPtr);\r
7936fb6a 1674 break;\r
1675\r
1676 case EFI_IFR_BITWISE_NOT_OP:\r
1677 //\r
1678 // Pop an expression from the expression stack\r
1679 //\r
1680 Status = PopExpression (Value);\r
1681 if (EFI_ERROR (Status)) {\r
1682 return Status;\r
1683 }\r
1684 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
1685 return EFI_INVALID_PARAMETER;\r
1686 }\r
1687\r
1688 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1689 Value->Value.u64 = ~Value->Value.u64;\r
1690 break;\r
1691\r
1692 //\r
1693 // binary-op\r
1694 //\r
1695 case EFI_IFR_ADD_OP:\r
1696 case EFI_IFR_SUBTRACT_OP:\r
1697 case EFI_IFR_MULTIPLY_OP:\r
1698 case EFI_IFR_DIVIDE_OP:\r
1699 case EFI_IFR_MODULO_OP:\r
1700 case EFI_IFR_BITWISE_AND_OP:\r
1701 case EFI_IFR_BITWISE_OR_OP:\r
1702 case EFI_IFR_SHIFT_LEFT_OP:\r
1703 case EFI_IFR_SHIFT_RIGHT_OP:\r
1704 //\r
1705 // Pop an expression from the expression stack\r
1706 //\r
1707 Status = PopExpression (&Data2);\r
1708 if (EFI_ERROR (Status)) {\r
1709 return Status;\r
1710 }\r
1711 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
1712 return EFI_INVALID_PARAMETER;\r
1713 }\r
1714\r
1715 //\r
1716 // Pop another expression from the expression stack\r
1717 //\r
1718 Status = PopExpression (&Data1);\r
1719 if (EFI_ERROR (Status)) {\r
1720 return Status;\r
1721 }\r
1722 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
1723 return EFI_INVALID_PARAMETER;\r
1724 }\r
1725\r
1726 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1727\r
1728 switch (OpCode->Operand) {\r
1729 case EFI_IFR_ADD_OP:\r
1730 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
1731 break;\r
1732\r
1733 case EFI_IFR_SUBTRACT_OP:\r
1734 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
1735 break;\r
1736\r
1737 case EFI_IFR_MULTIPLY_OP:\r
1738 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
1739 break;\r
1740\r
1741 case EFI_IFR_DIVIDE_OP:\r
1742 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
1743 break;\r
1744\r
1745 case EFI_IFR_MODULO_OP:\r
1746 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
1747 Value->Value.u64 = TempValue;\r
1748 break;\r
1749\r
1750 case EFI_IFR_BITWISE_AND_OP:\r
1751 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
1752 break;\r
1753\r
1754 case EFI_IFR_BITWISE_OR_OP:\r
1755 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
1756 break;\r
1757\r
1758 case EFI_IFR_SHIFT_LEFT_OP:\r
1759 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
1760 break;\r
1761\r
1762 case EFI_IFR_SHIFT_RIGHT_OP:\r
1763 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
1764 break;\r
1765\r
1766 default:\r
1767 break;\r
1768 }\r
1769 break;\r
1770\r
1771 case EFI_IFR_AND_OP:\r
1772 case EFI_IFR_OR_OP:\r
1773 //\r
1774 // Two Boolean operator\r
1775 //\r
1776 Status = PopExpression (&Data2);\r
1777 if (EFI_ERROR (Status)) {\r
1778 return Status;\r
1779 }\r
1780 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1781 return EFI_INVALID_PARAMETER;\r
1782 }\r
1783\r
1784 //\r
1785 // Pop another expression from the expression stack\r
1786 //\r
1787 Status = PopExpression (&Data1);\r
1788 if (EFI_ERROR (Status)) {\r
1789 return Status;\r
1790 }\r
1791 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1792 return EFI_INVALID_PARAMETER;\r
1793 }\r
1794\r
1795 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
1796 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
1797 } else {\r
1798 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
1799 }\r
1800 break;\r
1801\r
1802 case EFI_IFR_EQUAL_OP:\r
1803 case EFI_IFR_NOT_EQUAL_OP:\r
1804 case EFI_IFR_GREATER_EQUAL_OP:\r
1805 case EFI_IFR_GREATER_THAN_OP:\r
1806 case EFI_IFR_LESS_EQUAL_OP:\r
1807 case EFI_IFR_LESS_THAN_OP:\r
1808 //\r
1809 // Compare two integer, string, boolean or date/time\r
1810 //\r
1811 Status = PopExpression (&Data2);\r
1812 if (EFI_ERROR (Status)) {\r
1813 return Status;\r
1814 }\r
1815 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
1816 return EFI_INVALID_PARAMETER;\r
1817 }\r
1818\r
1819 //\r
1820 // Pop another expression from the expression stack\r
1821 //\r
1822 Status = PopExpression (&Data1);\r
1823 if (EFI_ERROR (Status)) {\r
1824 return Status;\r
1825 }\r
1826\r
1827 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
1828 if (Result == EFI_INVALID_PARAMETER) {\r
1829 return EFI_INVALID_PARAMETER;\r
1830 }\r
1831\r
1832 switch (OpCode->Operand) {\r
1833 case EFI_IFR_EQUAL_OP:\r
1834 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1835 break;\r
1836\r
1837 case EFI_IFR_NOT_EQUAL_OP:\r
1838 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1839 break;\r
1840\r
1841 case EFI_IFR_GREATER_EQUAL_OP:\r
1842 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
1843 break;\r
1844\r
1845 case EFI_IFR_GREATER_THAN_OP:\r
1846 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
1847 break;\r
1848\r
1849 case EFI_IFR_LESS_EQUAL_OP:\r
1850 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
1851 break;\r
1852\r
1853 case EFI_IFR_LESS_THAN_OP:\r
1854 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
1855 break;\r
1856\r
1857 default:\r
1858 break;\r
1859 }\r
1860 break;\r
1861\r
1862 case EFI_IFR_MATCH_OP:\r
1863 Status = IfrMatch (FormSet, Value);\r
1864 break;\r
1865\r
1866 case EFI_IFR_CATENATE_OP:\r
1867 Status = IfrCatenate (FormSet, Value);\r
1868 break;\r
1869\r
1870 //\r
1871 // ternary-op\r
1872 //\r
1873 case EFI_IFR_CONDITIONAL_OP:\r
1874 //\r
1875 // Pop third expression from the expression stack\r
1876 //\r
1877 Status = PopExpression (&Data3);\r
1878 if (EFI_ERROR (Status)) {\r
1879 return Status;\r
1880 }\r
1881\r
1882 //\r
1883 // Pop second expression from the expression stack\r
1884 //\r
1885 Status = PopExpression (&Data2);\r
1886 if (EFI_ERROR (Status)) {\r
1887 return Status;\r
1888 }\r
1889\r
1890 //\r
1891 // Pop first expression from the expression stack\r
1892 //\r
1893 Status = PopExpression (&Data1);\r
1894 if (EFI_ERROR (Status)) {\r
1895 return Status;\r
1896 }\r
1897 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1898 return EFI_INVALID_PARAMETER;\r
1899 }\r
1900\r
1901 if (Data1.Value.b) {\r
1902 Value = &Data3;\r
1903 } else {\r
1904 Value = &Data2;\r
1905 }\r
1906 break;\r
1907\r
1908 case EFI_IFR_FIND_OP:\r
1909 Status = IfrFind (FormSet, OpCode->Format, Value);\r
1910 break;\r
1911\r
1912 case EFI_IFR_MID_OP:\r
1913 Status = IfrMid (FormSet, Value);\r
1914 break;\r
1915\r
1916 case EFI_IFR_TOKEN_OP:\r
1917 Status = IfrToken (FormSet, Value);\r
1918 break;\r
1919\r
1920 case EFI_IFR_SPAN_OP:\r
1921 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
1922 break;\r
1923\r
1924 default:\r
1925 break;\r
1926 }\r
1927 if (EFI_ERROR (Status)) {\r
1928 return Status;\r
1929 }\r
1930\r
1931 Status = PushExpression (Value);\r
1932 if (EFI_ERROR (Status)) {\r
1933 return Status;\r
1934 }\r
1935 }\r
1936\r
1937 //\r
1938 // Pop the final result from expression stack\r
1939 //\r
1940 Value = &Data1;\r
1941 Status = PopExpression (Value);\r
1942 if (EFI_ERROR (Status)) {\r
1943 return Status;\r
1944 }\r
1945\r
1946 //\r
1947 // After evaluating an expression, there should be only one value left on the expression stack\r
1948 //\r
1949 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
1950 return EFI_INVALID_PARAMETER;\r
1951 }\r
1952\r
1953 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
1954\r
1955 return EFI_SUCCESS;\r
1956}\r