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