]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Fix ICC build break.
[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
bc166db3 776 if (String [Index] == NULL) {\r
7936fb6a 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
bc166db3 1114 if (String [Index] == NULL) {\r
7936fb6a 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
bc166db3 1302 Evaluate the result of a HII expression.\r
1303\r
1304 If Expression is NULL, then ASSERT.\r
7936fb6a 1305\r
1306 @param FormSet FormSet associated with this expression.\r
1307 @param Form Form associated with this expression.\r
1308 @param Expression Expression to be evaluated.\r
1309\r
1310 @retval EFI_SUCCESS The expression evaluated successfuly\r
1311 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
1312 could not be found.\r
1313 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
1314 stack.\r
1315 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
1316 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
1317\r
1318**/\r
1319EFI_STATUS\r
1320EvaluateExpression (\r
1321 IN FORM_BROWSER_FORMSET *FormSet,\r
1322 IN FORM_BROWSER_FORM *Form,\r
1323 IN OUT FORM_EXPRESSION *Expression\r
1324 )\r
1325{\r
1326 EFI_STATUS Status;\r
1327 LIST_ENTRY *Link;\r
1328 EXPRESSION_OPCODE *OpCode;\r
1329 FORM_BROWSER_STATEMENT *Question;\r
1330 FORM_BROWSER_STATEMENT *Question2;\r
1331 UINT16 Index;\r
1332 EFI_HII_VALUE Data1;\r
1333 EFI_HII_VALUE Data2;\r
1334 EFI_HII_VALUE Data3;\r
1335 FORM_EXPRESSION *RuleExpression;\r
1336 EFI_HII_VALUE *Value;\r
1337 INTN Result;\r
1338 CHAR16 *StrPtr;\r
1339 UINT32 TempValue;\r
1340\r
1341 //\r
1342 // Always reset the stack before evaluating an Expression\r
1343 //\r
1344 ResetExpressionStack ();\r
1345\r
bc166db3 1346 ASSERT (Expression != NULL);\r
7936fb6a 1347 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
1348\r
1349 Link = GetFirstNode (&Expression->OpCodeListHead);\r
1350 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
1351 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
1352\r
1353 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
1354\r
1355 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
1356 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
1357 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
1358\r
1359 Value = &Data3;\r
1360 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1361 Status = EFI_SUCCESS;\r
1362\r
1363 switch (OpCode->Operand) {\r
1364 //\r
1365 // Built-in functions\r
1366 //\r
1367 case EFI_IFR_EQ_ID_VAL_OP:\r
1368 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1369 if (Question == NULL) {\r
1370 return EFI_NOT_FOUND;\r
1371 }\r
1372\r
1373 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
1374 if (Result == EFI_INVALID_PARAMETER) {\r
1375 return EFI_INVALID_PARAMETER;\r
1376 }\r
1377 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1378 break;\r
1379\r
1380 case EFI_IFR_EQ_ID_ID_OP:\r
1381 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1382 if (Question == NULL) {\r
1383 return EFI_NOT_FOUND;\r
1384 }\r
1385\r
1386 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
1387 if (Question2 == NULL) {\r
1388 return EFI_NOT_FOUND;\r
1389 }\r
1390\r
1391 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
1392 if (Result == EFI_INVALID_PARAMETER) {\r
1393 return EFI_INVALID_PARAMETER;\r
1394 }\r
1395 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1396 break;\r
1397\r
1398 case EFI_IFR_EQ_ID_LIST_OP:\r
1399 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1400 if (Question == NULL) {\r
1401 return EFI_NOT_FOUND;\r
1402 }\r
1403\r
1404 Value->Value.b = FALSE;\r
1405 for (Index =0; Index < OpCode->ListLength; Index++) {\r
1406 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
1407 Value->Value.b = TRUE;\r
1408 break;\r
1409 }\r
1410 }\r
1411 break;\r
1412\r
1413 case EFI_IFR_DUP_OP:\r
1414 Status = PopExpression (Value);\r
1415 if (EFI_ERROR (Status)) {\r
1416 return Status;\r
1417 }\r
1418\r
1419 Status = PushExpression (Value);\r
1420 break;\r
1421\r
1422 case EFI_IFR_QUESTION_REF1_OP:\r
1423 case EFI_IFR_THIS_OP:\r
1424 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1425 if (Question == NULL) {\r
1426 return EFI_NOT_FOUND;\r
1427 }\r
1428\r
1429 Value = &Question->HiiValue;\r
1430 break;\r
1431\r
1432 case EFI_IFR_QUESTION_REF3_OP:\r
1433 if (OpCode->DevicePath == 0) {\r
1434 //\r
1435 // EFI_IFR_QUESTION_REF3\r
1436 // Pop an expression from the expression stack\r
1437 //\r
1438 Status = PopExpression (Value);\r
1439 if (EFI_ERROR (Status)) {\r
1440 return Status;\r
1441 }\r
1442\r
1443 //\r
1444 // Validate the expression value\r
1445 //\r
1446 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1447 return EFI_NOT_FOUND;\r
1448 }\r
1449\r
1450 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1451 if (Question == NULL) {\r
1452 return EFI_NOT_FOUND;\r
1453 }\r
1454\r
1455 //\r
1456 // push the questions' value on to the expression stack\r
1457 //\r
1458 Value = &Question->HiiValue;\r
1459 } else {\r
1460 //\r
1461 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
1462 // since it is impractical to evaluate the value of a Question in another\r
1463 // Hii Package list.\r
1464 //\r
1465 ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
1466 }\r
1467 break;\r
1468\r
1469 case EFI_IFR_RULE_REF_OP:\r
1470 //\r
1471 // Find expression for this rule\r
1472 //\r
1473 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
1474 if (RuleExpression == NULL) {\r
1475 return EFI_NOT_FOUND;\r
1476 }\r
1477\r
1478 //\r
1479 // Evaluate this rule expression\r
1480 //\r
1481 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
1482 if (EFI_ERROR (Status)) {\r
1483 return Status;\r
1484 }\r
1485\r
1486 Value = &RuleExpression->Result;\r
1487 break;\r
1488\r
1489 case EFI_IFR_STRING_REF1_OP:\r
1490 Value->Type = EFI_IFR_TYPE_STRING;\r
1491 Value->Value.string = OpCode->Value.Value.string;\r
1492 break;\r
1493\r
1494 //\r
1495 // Constant\r
1496 //\r
1497 case EFI_IFR_TRUE_OP:\r
1498 case EFI_IFR_FALSE_OP:\r
1499 case EFI_IFR_ONE_OP:\r
1500 case EFI_IFR_ONES_OP:\r
1501 case EFI_IFR_UINT8_OP:\r
1502 case EFI_IFR_UINT16_OP:\r
1503 case EFI_IFR_UINT32_OP:\r
1504 case EFI_IFR_UINT64_OP:\r
1505 case EFI_IFR_UNDEFINED_OP:\r
1506 case EFI_IFR_VERSION_OP:\r
1507 case EFI_IFR_ZERO_OP:\r
1508 Value = &OpCode->Value;\r
1509 break;\r
1510\r
1511 //\r
1512 // unary-op\r
1513 //\r
1514 case EFI_IFR_LENGTH_OP:\r
1515 Status = PopExpression (Value);\r
1516 if (EFI_ERROR (Status)) {\r
1517 return Status;\r
1518 }\r
1519 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1520 return EFI_INVALID_PARAMETER;\r
1521 }\r
1522\r
1523 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1524 if (StrPtr == NULL) {\r
1525 return EFI_INVALID_PARAMETER;\r
1526 }\r
1527\r
1528 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1529 Value->Value.u64 = StrLen (StrPtr);\r
f4113e1f 1530 FreePool (StrPtr);\r
7936fb6a 1531 break;\r
1532\r
1533 case EFI_IFR_NOT_OP:\r
1534 Status = PopExpression (Value);\r
1535 if (EFI_ERROR (Status)) {\r
1536 return Status;\r
1537 }\r
1538 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
1539 return EFI_INVALID_PARAMETER;\r
1540 }\r
1541 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
1542 break;\r
1543\r
1544 case EFI_IFR_QUESTION_REF2_OP:\r
1545 //\r
1546 // Pop an expression from the expression stack\r
1547 //\r
1548 Status = PopExpression (Value);\r
1549 if (EFI_ERROR (Status)) {\r
1550 return Status;\r
1551 }\r
1552\r
1553 //\r
1554 // Validate the expression value\r
1555 //\r
1556 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1557 return EFI_NOT_FOUND;\r
1558 }\r
1559\r
1560 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1561 if (Question == NULL) {\r
1562 return EFI_NOT_FOUND;\r
1563 }\r
1564\r
1565 Value = &Question->HiiValue;\r
1566 break;\r
1567\r
1568 case EFI_IFR_STRING_REF2_OP:\r
1569 //\r
1570 // Pop an expression from the expression stack\r
1571 //\r
1572 Status = PopExpression (Value);\r
1573 if (EFI_ERROR (Status)) {\r
1574 return Status;\r
1575 }\r
1576\r
1577 //\r
1578 // Validate the expression value\r
1579 //\r
1580 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1581 return EFI_NOT_FOUND;\r
1582 }\r
1583\r
1584 Value->Type = EFI_IFR_TYPE_STRING;\r
1585 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
1586 if (StrPtr == NULL) {\r
1587 //\r
1588 // If String not exit, push an empty string\r
1589 //\r
1590 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
1591 } else {\r
1592 Index = (UINT16) Value->Value.u64;\r
1593 Value->Value.string = Index;\r
f4113e1f 1594 FreePool (StrPtr);\r
7936fb6a 1595 }\r
1596 break;\r
1597\r
1598 case EFI_IFR_TO_BOOLEAN_OP:\r
1599 //\r
1600 // Pop an expression from the expression stack\r
1601 //\r
1602 Status = PopExpression (Value);\r
1603 if (EFI_ERROR (Status)) {\r
1604 return Status;\r
1605 }\r
1606\r
1607 //\r
1608 // Convert an expression to a Boolean\r
1609 //\r
1610 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
1611 //\r
1612 // When converting from an unsigned integer, zero will be converted to\r
1613 // FALSE and any other value will be converted to TRUE.\r
1614 //\r
1615 Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);\r
1616\r
1617 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1618 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
1619 //\r
1620 // When converting from a string, if case-insensitive compare\r
1621 // with "true" is True, then push True. If a case-insensitive compare\r
1622 // with "false" is True, then push False.\r
1623 //\r
1624 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1625 if (StrPtr == NULL) {\r
1626 return EFI_INVALID_PARAMETER;\r
1627 }\r
1628\r
1629 if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){\r
1630 Value->Value.b = TRUE;\r
1631 } else {\r
1632 Value->Value.b = FALSE;\r
1633 }\r
f4113e1f 1634 FreePool (StrPtr);\r
7936fb6a 1635 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1636 }\r
1637 break;\r
1638\r
1639 case EFI_IFR_TO_STRING_OP:\r
1640 Status = IfrToString (FormSet, OpCode->Format, Value);\r
1641 break;\r
1642\r
1643 case EFI_IFR_TO_UINT_OP:\r
1644 Status = IfrToUint (FormSet, Value);\r
1645 break;\r
1646\r
1647 case EFI_IFR_TO_LOWER_OP:\r
1648 case EFI_IFR_TO_UPPER_OP:\r
1649 Status = InitializeUnicodeCollationProtocol ();\r
1650 if (EFI_ERROR (Status)) {\r
1651 return Status;\r
1652 }\r
1653\r
1654 Status = PopExpression (Value);\r
1655 if (EFI_ERROR (Status)) {\r
1656 return Status;\r
1657 }\r
1658\r
1659 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1660 return EFI_UNSUPPORTED;\r
1661 }\r
1662\r
1663 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1664 if (StrPtr == NULL) {\r
1665 return EFI_NOT_FOUND;\r
1666 }\r
1667\r
1668 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
1669 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
1670 } else {\r
1671 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
1672 }\r
1673 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 1674 FreePool (StrPtr);\r
7936fb6a 1675 break;\r
1676\r
1677 case EFI_IFR_BITWISE_NOT_OP:\r
1678 //\r
1679 // Pop an expression from the expression stack\r
1680 //\r
1681 Status = PopExpression (Value);\r
1682 if (EFI_ERROR (Status)) {\r
1683 return Status;\r
1684 }\r
1685 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
1686 return EFI_INVALID_PARAMETER;\r
1687 }\r
1688\r
1689 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1690 Value->Value.u64 = ~Value->Value.u64;\r
1691 break;\r
1692\r
1693 //\r
1694 // binary-op\r
1695 //\r
1696 case EFI_IFR_ADD_OP:\r
1697 case EFI_IFR_SUBTRACT_OP:\r
1698 case EFI_IFR_MULTIPLY_OP:\r
1699 case EFI_IFR_DIVIDE_OP:\r
1700 case EFI_IFR_MODULO_OP:\r
1701 case EFI_IFR_BITWISE_AND_OP:\r
1702 case EFI_IFR_BITWISE_OR_OP:\r
1703 case EFI_IFR_SHIFT_LEFT_OP:\r
1704 case EFI_IFR_SHIFT_RIGHT_OP:\r
1705 //\r
1706 // Pop an expression from the expression stack\r
1707 //\r
1708 Status = PopExpression (&Data2);\r
1709 if (EFI_ERROR (Status)) {\r
1710 return Status;\r
1711 }\r
1712 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
1713 return EFI_INVALID_PARAMETER;\r
1714 }\r
1715\r
1716 //\r
1717 // Pop another expression from the expression stack\r
1718 //\r
1719 Status = PopExpression (&Data1);\r
1720 if (EFI_ERROR (Status)) {\r
1721 return Status;\r
1722 }\r
1723 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
1724 return EFI_INVALID_PARAMETER;\r
1725 }\r
1726\r
1727 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1728\r
1729 switch (OpCode->Operand) {\r
1730 case EFI_IFR_ADD_OP:\r
1731 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
1732 break;\r
1733\r
1734 case EFI_IFR_SUBTRACT_OP:\r
1735 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
1736 break;\r
1737\r
1738 case EFI_IFR_MULTIPLY_OP:\r
1739 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
1740 break;\r
1741\r
1742 case EFI_IFR_DIVIDE_OP:\r
1743 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
1744 break;\r
1745\r
1746 case EFI_IFR_MODULO_OP:\r
1747 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
1748 Value->Value.u64 = TempValue;\r
1749 break;\r
1750\r
1751 case EFI_IFR_BITWISE_AND_OP:\r
1752 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
1753 break;\r
1754\r
1755 case EFI_IFR_BITWISE_OR_OP:\r
1756 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
1757 break;\r
1758\r
1759 case EFI_IFR_SHIFT_LEFT_OP:\r
1760 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
1761 break;\r
1762\r
1763 case EFI_IFR_SHIFT_RIGHT_OP:\r
1764 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
1765 break;\r
1766\r
1767 default:\r
1768 break;\r
1769 }\r
1770 break;\r
1771\r
1772 case EFI_IFR_AND_OP:\r
1773 case EFI_IFR_OR_OP:\r
1774 //\r
1775 // Two Boolean operator\r
1776 //\r
1777 Status = PopExpression (&Data2);\r
1778 if (EFI_ERROR (Status)) {\r
1779 return Status;\r
1780 }\r
1781 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1782 return EFI_INVALID_PARAMETER;\r
1783 }\r
1784\r
1785 //\r
1786 // Pop another expression from the expression stack\r
1787 //\r
1788 Status = PopExpression (&Data1);\r
1789 if (EFI_ERROR (Status)) {\r
1790 return Status;\r
1791 }\r
1792 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1793 return EFI_INVALID_PARAMETER;\r
1794 }\r
1795\r
1796 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
1797 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
1798 } else {\r
1799 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
1800 }\r
1801 break;\r
1802\r
1803 case EFI_IFR_EQUAL_OP:\r
1804 case EFI_IFR_NOT_EQUAL_OP:\r
1805 case EFI_IFR_GREATER_EQUAL_OP:\r
1806 case EFI_IFR_GREATER_THAN_OP:\r
1807 case EFI_IFR_LESS_EQUAL_OP:\r
1808 case EFI_IFR_LESS_THAN_OP:\r
1809 //\r
1810 // Compare two integer, string, boolean or date/time\r
1811 //\r
1812 Status = PopExpression (&Data2);\r
1813 if (EFI_ERROR (Status)) {\r
1814 return Status;\r
1815 }\r
1816 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
1817 return EFI_INVALID_PARAMETER;\r
1818 }\r
1819\r
1820 //\r
1821 // Pop another expression from the expression stack\r
1822 //\r
1823 Status = PopExpression (&Data1);\r
1824 if (EFI_ERROR (Status)) {\r
1825 return Status;\r
1826 }\r
1827\r
1828 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
1829 if (Result == EFI_INVALID_PARAMETER) {\r
1830 return EFI_INVALID_PARAMETER;\r
1831 }\r
1832\r
1833 switch (OpCode->Operand) {\r
1834 case EFI_IFR_EQUAL_OP:\r
1835 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1836 break;\r
1837\r
1838 case EFI_IFR_NOT_EQUAL_OP:\r
1839 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1840 break;\r
1841\r
1842 case EFI_IFR_GREATER_EQUAL_OP:\r
1843 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
1844 break;\r
1845\r
1846 case EFI_IFR_GREATER_THAN_OP:\r
1847 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
1848 break;\r
1849\r
1850 case EFI_IFR_LESS_EQUAL_OP:\r
1851 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
1852 break;\r
1853\r
1854 case EFI_IFR_LESS_THAN_OP:\r
1855 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
1856 break;\r
1857\r
1858 default:\r
1859 break;\r
1860 }\r
1861 break;\r
1862\r
1863 case EFI_IFR_MATCH_OP:\r
1864 Status = IfrMatch (FormSet, Value);\r
1865 break;\r
1866\r
1867 case EFI_IFR_CATENATE_OP:\r
1868 Status = IfrCatenate (FormSet, Value);\r
1869 break;\r
1870\r
1871 //\r
1872 // ternary-op\r
1873 //\r
1874 case EFI_IFR_CONDITIONAL_OP:\r
1875 //\r
1876 // Pop third expression from the expression stack\r
1877 //\r
1878 Status = PopExpression (&Data3);\r
1879 if (EFI_ERROR (Status)) {\r
1880 return Status;\r
1881 }\r
1882\r
1883 //\r
1884 // Pop second expression from the expression stack\r
1885 //\r
1886 Status = PopExpression (&Data2);\r
1887 if (EFI_ERROR (Status)) {\r
1888 return Status;\r
1889 }\r
1890\r
1891 //\r
1892 // Pop first expression from the expression stack\r
1893 //\r
1894 Status = PopExpression (&Data1);\r
1895 if (EFI_ERROR (Status)) {\r
1896 return Status;\r
1897 }\r
1898 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1899 return EFI_INVALID_PARAMETER;\r
1900 }\r
1901\r
1902 if (Data1.Value.b) {\r
1903 Value = &Data3;\r
1904 } else {\r
1905 Value = &Data2;\r
1906 }\r
1907 break;\r
1908\r
1909 case EFI_IFR_FIND_OP:\r
1910 Status = IfrFind (FormSet, OpCode->Format, Value);\r
1911 break;\r
1912\r
1913 case EFI_IFR_MID_OP:\r
1914 Status = IfrMid (FormSet, Value);\r
1915 break;\r
1916\r
1917 case EFI_IFR_TOKEN_OP:\r
1918 Status = IfrToken (FormSet, Value);\r
1919 break;\r
1920\r
1921 case EFI_IFR_SPAN_OP:\r
1922 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
1923 break;\r
1924\r
1925 default:\r
1926 break;\r
1927 }\r
1928 if (EFI_ERROR (Status)) {\r
1929 return Status;\r
1930 }\r
1931\r
1932 Status = PushExpression (Value);\r
1933 if (EFI_ERROR (Status)) {\r
1934 return Status;\r
1935 }\r
1936 }\r
1937\r
1938 //\r
1939 // Pop the final result from expression stack\r
1940 //\r
1941 Value = &Data1;\r
1942 Status = PopExpression (Value);\r
1943 if (EFI_ERROR (Status)) {\r
1944 return Status;\r
1945 }\r
1946\r
1947 //\r
1948 // After evaluating an expression, there should be only one value left on the expression stack\r
1949 //\r
1950 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
1951 return EFI_INVALID_PARAMETER;\r
1952 }\r
1953\r
1954 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
1955\r
1956 return EFI_SUCCESS;\r
1957}\r