]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Add comments to MdeModulePkg.dec, Correct minor comments for other files and Add...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
4Copyright (c) 2007, Intel Corporation\r
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
82 gBS->FreePool (*Stack);\r
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
424 return Question;\r
425 }\r
426\r
427 Link = GetNextNode (&FormSet->FormListHead, Link);\r
428 }\r
429\r
430 return NULL;\r
431}\r
432\r
433\r
434/**\r
435 Get Expression given its RuleId.\r
436\r
437 @param Form The form which contains this Expression.\r
438 @param RuleId Id of this Expression.\r
439\r
440 @retval Pointer The Expression.\r
441 @retval NULL Specified Expression not found in the form.\r
442\r
443**/\r
444FORM_EXPRESSION *\r
445RuleIdToExpression (\r
446 IN FORM_BROWSER_FORM *Form,\r
447 IN UINT8 RuleId\r
448 )\r
449{\r
450 LIST_ENTRY *Link;\r
451 FORM_EXPRESSION *Expression;\r
452\r
453 Link = GetFirstNode (&Form->ExpressionListHead);\r
454 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
455 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
456\r
457 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
458 return Expression;\r
459 }\r
460\r
461 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
462 }\r
463\r
464 return NULL;\r
465}\r
466\r
467\r
468/**\r
469 Locate the Unicode Collation Protocol interface for later use.\r
470\r
471 @retval EFI_SUCCESS Protocol interface initialize success.\r
472 @retval Other Protocol interface initialize failed.\r
473\r
474**/\r
475EFI_STATUS\r
476InitializeUnicodeCollationProtocol (\r
477 VOID\r
478 )\r
479{\r
480 EFI_STATUS Status;\r
481\r
482 if (mUnicodeCollation != NULL) {\r
483 return EFI_SUCCESS;\r
484 }\r
485\r
486 //\r
487 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
488 // instances first and then select one which support English language.\r
489 // Current implementation just pick the first instance.\r
490 //\r
491 Status = gBS->LocateProtocol (\r
492 &gEfiUnicodeCollation2ProtocolGuid,\r
493 NULL,\r
494 (VOID **) &mUnicodeCollation\r
495 );\r
496 return Status;\r
497}\r
498\r
499/**\r
500 Convert the input Unicode character to upper.\r
501\r
502 @param String Th Unicode character to be converted.\r
503\r
504**/\r
505VOID\r
506IfrStrToUpper (\r
507 CHAR16 *String\r
508 )\r
509{\r
510 while (*String != 0) {\r
511 if ((*String >= 'a') && (*String <= 'z')) {\r
512 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
513 }\r
514 String++;\r
515 }\r
516}\r
517\r
518\r
519/**\r
520 Evaluate opcode EFI_IFR_TO_STRING.\r
521\r
522 @param FormSet Formset which contains this opcode.\r
523 @param Format String format in EFI_IFR_TO_STRING.\r
524 @param Result Evaluation result for this opcode.\r
525\r
526 @retval EFI_SUCCESS Opcode evaluation success.\r
527 @retval Other Opcode evaluation failed.\r
528\r
529**/\r
530EFI_STATUS\r
531IfrToString (\r
532 IN FORM_BROWSER_FORMSET *FormSet,\r
533 IN UINT8 Format,\r
534 OUT EFI_HII_VALUE *Result\r
535 )\r
536{\r
537 EFI_STATUS Status;\r
538 EFI_HII_VALUE Value;\r
539 CHAR16 *String;\r
540 CHAR16 *PrintFormat;\r
541 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
542 UINTN BufferSize;\r
543\r
544 Status = PopExpression (&Value);\r
545 if (EFI_ERROR (Status)) {\r
546 return Status;\r
547 }\r
548\r
549 switch (Value.Type) {\r
550 case EFI_IFR_TYPE_NUM_SIZE_8:\r
551 case EFI_IFR_TYPE_NUM_SIZE_16:\r
552 case EFI_IFR_TYPE_NUM_SIZE_32:\r
553 case EFI_IFR_TYPE_NUM_SIZE_64:\r
554 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
555 switch (Format) {\r
556 case EFI_IFR_STRING_UNSIGNED_DEC:\r
557 case EFI_IFR_STRING_SIGNED_DEC:\r
558 PrintFormat = L"%ld";\r
559 break;\r
560\r
561 case EFI_IFR_STRING_LOWERCASE_HEX:\r
562 PrintFormat = L"%lx";\r
563 break;\r
564\r
565 case EFI_IFR_STRING_UPPERCASE_HEX:\r
566 PrintFormat = L"%lX";\r
567 break;\r
568\r
569 default:\r
570 return EFI_UNSUPPORTED;\r
571 }\r
572 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
573 String = Buffer;\r
574 break;\r
575\r
576 case EFI_IFR_TYPE_STRING:\r
577 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
578 return EFI_SUCCESS;\r
579\r
580 case EFI_IFR_TYPE_BOOLEAN:\r
581 String = (Value.Value.b) ? L"True" : L"False";\r
582 break;\r
583\r
584 default:\r
585 return EFI_UNSUPPORTED;\r
586 }\r
587\r
588 Result->Type = EFI_IFR_TYPE_STRING;\r
589 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
590 return EFI_SUCCESS;\r
591}\r
592\r
593\r
594/**\r
595 Evaluate opcode EFI_IFR_TO_UINT.\r
596\r
597 @param FormSet Formset which contains this opcode.\r
598 @param Result Evaluation result for this opcode.\r
599\r
600 @retval EFI_SUCCESS Opcode evaluation success.\r
601 @retval Other Opcode evaluation failed.\r
602\r
603**/\r
604EFI_STATUS\r
605IfrToUint (\r
606 IN FORM_BROWSER_FORMSET *FormSet,\r
607 OUT EFI_HII_VALUE *Result\r
608 )\r
609{\r
610 EFI_STATUS Status;\r
611 EFI_HII_VALUE Value;\r
612 CHAR16 *String;\r
613 CHAR16 *StringPtr;\r
614 UINTN BufferSize;\r
615\r
616 Status = PopExpression (&Value);\r
617 if (EFI_ERROR (Status)) {\r
618 return Status;\r
619 }\r
620\r
621 if (Value.Type >= EFI_IFR_TYPE_OTHER) {\r
622 return EFI_UNSUPPORTED;\r
623 }\r
624\r
625 Status = EFI_SUCCESS;\r
626 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
627 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
628 if (String == NULL) {\r
629 return EFI_NOT_FOUND;\r
630 }\r
631\r
632 IfrStrToUpper (String);\r
633 StringPtr = StrStr (String, L"0X");\r
634 if (StringPtr != NULL) {\r
635 //\r
636 // Hex string\r
637 //\r
638 BufferSize = sizeof (UINT64);\r
639 Status = HexStringToBuf ((UINT8 *) &Result->Value.u64, &BufferSize, StringPtr + 2, NULL);\r
640 } else {\r
641 //\r
642 // BUGBUG: Need handle decimal string\r
643 //\r
644 }\r
645 gBS->FreePool (String);\r
646 } else {\r
647 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
648 }\r
649\r
650 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
651 return Status;\r
652}\r
653\r
654\r
655/**\r
656 Evaluate opcode EFI_IFR_CATENATE.\r
657\r
658 @param FormSet Formset which contains this opcode.\r
659 @param Result Evaluation result for this opcode.\r
660\r
661 @retval EFI_SUCCESS Opcode evaluation success.\r
662 @retval Other Opcode evaluation failed.\r
663\r
664**/\r
665EFI_STATUS\r
666IfrCatenate (\r
667 IN FORM_BROWSER_FORMSET *FormSet,\r
668 OUT EFI_HII_VALUE *Result\r
669 )\r
670{\r
671 EFI_STATUS Status;\r
672 EFI_HII_VALUE Value;\r
673 CHAR16 *String[2];\r
674 UINTN Index;\r
675 CHAR16 *StringPtr;\r
676 UINTN Size;\r
677\r
678 //\r
679 // String[0] - The second string\r
680 // String[1] - The first string\r
681 //\r
682 String[0] = NULL;\r
683 String[1] = NULL;\r
684 StringPtr = NULL;\r
685 Status = EFI_SUCCESS;\r
686\r
687 for (Index = 0; Index < 2; Index++) {\r
688 Status = PopExpression (&Value);\r
689 if (EFI_ERROR (Status)) {\r
690 goto Done;\r
691 }\r
692\r
693 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
694 Status = EFI_UNSUPPORTED;\r
695 goto Done;\r
696 }\r
697\r
698 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
699 if (String== NULL) {\r
700 Status = EFI_NOT_FOUND;\r
701 goto Done;\r
702 }\r
703 }\r
704\r
705 Size = StrSize (String[0]);\r
706 StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
707 ASSERT (StringPtr != NULL);\r
708 StrCpy (StringPtr, String[1]);\r
709 StrCat (StringPtr, String[0]);\r
710\r
711 Result->Type = EFI_IFR_TYPE_STRING;\r
712 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
713\r
714Done:\r
715 SafeFreePool (String[0]);\r
716 SafeFreePool (String[1]);\r
717 SafeFreePool (StringPtr);\r
718\r
719 return Status;\r
720}\r
721\r
722\r
723/**\r
724 Evaluate opcode EFI_IFR_MATCH.\r
725\r
726 @param FormSet Formset which contains this opcode.\r
727 @param Result Evaluation result for this opcode.\r
728\r
729 @retval EFI_SUCCESS Opcode evaluation success.\r
730 @retval Other Opcode evaluation failed.\r
731\r
732**/\r
733EFI_STATUS\r
734IfrMatch (\r
735 IN FORM_BROWSER_FORMSET *FormSet,\r
736 OUT EFI_HII_VALUE *Result\r
737 )\r
738{\r
739 EFI_STATUS Status;\r
740 EFI_HII_VALUE Value;\r
741 CHAR16 *String[2];\r
742 UINTN Index;\r
743\r
744 //\r
745 // String[0] - The string to search\r
746 // String[1] - pattern\r
747 //\r
748 String[0] = NULL;\r
749 String[1] = NULL;\r
750 Status = EFI_SUCCESS;\r
751 for (Index = 0; Index < 2; Index++) {\r
752 Status = PopExpression (&Value);\r
753 if (EFI_ERROR (Status)) {\r
754 goto Done;\r
755 }\r
756\r
757 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
758 Status = EFI_UNSUPPORTED;\r
759 goto Done;\r
760 }\r
761\r
762 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
763 if (String== NULL) {\r
764 Status = EFI_NOT_FOUND;\r
765 goto Done;\r
766 }\r
767 }\r
768\r
769 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
770 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
771\r
772Done:\r
773 SafeFreePool (String[0]);\r
774 SafeFreePool (String[1]);\r
775\r
776 return Status;\r
777}\r
778\r
779\r
780/**\r
781 Evaluate opcode EFI_IFR_FIND.\r
782\r
783 @param FormSet Formset which contains this opcode.\r
784 @param Format Case sensitive or insensitive.\r
785 @param Result Evaluation result for this opcode.\r
786\r
787 @retval EFI_SUCCESS Opcode evaluation success.\r
788 @retval Other Opcode evaluation failed.\r
789\r
790**/\r
791EFI_STATUS\r
792IfrFind (\r
793 IN FORM_BROWSER_FORMSET *FormSet,\r
794 IN UINT8 Format,\r
795 OUT EFI_HII_VALUE *Result\r
796 )\r
797{\r
798 EFI_STATUS Status;\r
799 EFI_HII_VALUE Value;\r
800 CHAR16 *String[2];\r
801 UINTN Base;\r
802 CHAR16 *StringPtr;\r
803 UINTN Index;\r
804\r
805 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
806 return EFI_UNSUPPORTED;\r
807 }\r
808\r
809 Status = PopExpression (&Value);\r
810 if (EFI_ERROR (Status)) {\r
811 return Status;\r
812 }\r
813 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
814 return EFI_UNSUPPORTED;\r
815 }\r
816 Base = (UINTN) Value.Value.u64;\r
817\r
818 //\r
819 // String[0] - sub-string\r
820 // String[1] - The string to search\r
821 //\r
822 String[0] = NULL;\r
823 String[1] = NULL;\r
824 for (Index = 0; Index < 2; Index++) {\r
825 Status = PopExpression (&Value);\r
826 if (EFI_ERROR (Status)) {\r
827 goto Done;\r
828 }\r
829\r
830 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
831 Status = EFI_UNSUPPORTED;\r
832 goto Done;\r
833 }\r
834\r
835 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
836 if (String== NULL) {\r
837 Status = EFI_NOT_FOUND;\r
838 goto Done;\r
839 }\r
840\r
841 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
842 //\r
843 // Case insensitive, convert both string to upper case\r
844 //\r
845 IfrStrToUpper (String[Index]);\r
846 }\r
847 }\r
848\r
849 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
850 if (Base >= StrLen (String[1])) {\r
851 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
852 } else {\r
853 StringPtr = StrStr (String[1] + Base, String[0]);\r
854 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
855 }\r
856\r
857Done:\r
858 SafeFreePool (String[0]);\r
859 SafeFreePool (String[1]);\r
860\r
861 return Status;\r
862}\r
863\r
864\r
865/**\r
866 Evaluate opcode EFI_IFR_MID.\r
867\r
868 @param FormSet Formset which contains this opcode.\r
869 @param Result Evaluation result for this opcode.\r
870\r
871 @retval EFI_SUCCESS Opcode evaluation success.\r
872 @retval Other Opcode evaluation failed.\r
873\r
874**/\r
875EFI_STATUS\r
876IfrMid (\r
877 IN FORM_BROWSER_FORMSET *FormSet,\r
878 OUT EFI_HII_VALUE *Result\r
879 )\r
880{\r
881 EFI_STATUS Status;\r
882 EFI_HII_VALUE Value;\r
883 CHAR16 *String;\r
884 UINTN Base;\r
885 UINTN Length;\r
886 CHAR16 *SubString;\r
887\r
888 Status = PopExpression (&Value);\r
889 if (EFI_ERROR (Status)) {\r
890 return Status;\r
891 }\r
892 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
893 return EFI_UNSUPPORTED;\r
894 }\r
895 Length = (UINTN) Value.Value.u64;\r
896\r
897 Status = PopExpression (&Value);\r
898 if (EFI_ERROR (Status)) {\r
899 return Status;\r
900 }\r
901 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
902 return EFI_UNSUPPORTED;\r
903 }\r
904 Base = (UINTN) Value.Value.u64;\r
905\r
906 Status = PopExpression (&Value);\r
907 if (EFI_ERROR (Status)) {\r
908 return Status;\r
909 }\r
910 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
911 return EFI_UNSUPPORTED;\r
912 }\r
913 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
914 if (String == NULL) {\r
915 return EFI_NOT_FOUND;\r
916 }\r
917\r
918 if (Length == 0 || Base >= StrLen (String)) {\r
919 SubString = gEmptyString;\r
920 } else {\r
921 SubString = String + Base;\r
922 if ((Base + Length) < StrLen (String)) {\r
923 SubString[Length] = L'\0';\r
924 }\r
925 }\r
926\r
927 Result->Type = EFI_IFR_TYPE_STRING;\r
928 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
929\r
930 gBS->FreePool (String);\r
931\r
932 return Status;\r
933}\r
934\r
935\r
936/**\r
937 Evaluate opcode EFI_IFR_TOKEN.\r
938\r
939 @param FormSet Formset which contains this opcode.\r
940 @param Result Evaluation result for this opcode.\r
941\r
942 @retval EFI_SUCCESS Opcode evaluation success.\r
943 @retval Other Opcode evaluation failed.\r
944\r
945**/\r
946EFI_STATUS\r
947IfrToken (\r
948 IN FORM_BROWSER_FORMSET *FormSet,\r
949 OUT EFI_HII_VALUE *Result\r
950 )\r
951{\r
952 EFI_STATUS Status;\r
953 EFI_HII_VALUE Value;\r
954 CHAR16 *String[2];\r
955 UINTN Count;\r
956 CHAR16 *Delimiter;\r
957 CHAR16 *SubString;\r
958 CHAR16 *StringPtr;\r
959 UINTN Index;\r
960\r
961 Status = PopExpression (&Value);\r
962 if (EFI_ERROR (Status)) {\r
963 return Status;\r
964 }\r
965 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
966 return EFI_UNSUPPORTED;\r
967 }\r
968 Count = (UINTN) Value.Value.u64;\r
969\r
970 //\r
971 // String[0] - Delimiter\r
972 // String[1] - The string to search\r
973 //\r
974 String[0] = NULL;\r
975 String[1] = NULL;\r
976 for (Index = 0; Index < 2; Index++) {\r
977 Status = PopExpression (&Value);\r
978 if (EFI_ERROR (Status)) {\r
979 goto Done;\r
980 }\r
981\r
982 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
983 Status = EFI_UNSUPPORTED;\r
984 goto Done;\r
985 }\r
986\r
987 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
988 if (String== NULL) {\r
989 Status = EFI_NOT_FOUND;\r
990 goto Done;\r
991 }\r
992 }\r
993\r
994 Delimiter = String[0];\r
995 SubString = String[1];\r
996 while (Count > 0) {\r
997 SubString = StrStr (SubString, Delimiter);\r
998 if (SubString != NULL) {\r
999 //\r
1000 // Skip over the delimiter\r
1001 //\r
1002 SubString = SubString + StrLen (Delimiter);\r
1003 } else {\r
1004 break;\r
1005 }\r
1006 Count--;\r
1007 }\r
1008\r
1009 if (SubString == NULL) {\r
1010 //\r
1011 // nth delimited sub-string not found, push an empty string\r
1012 //\r
1013 SubString = gEmptyString;\r
1014 } else {\r
1015 //\r
1016 // Put a NULL terminator for nth delimited sub-string\r
1017 //\r
1018 StringPtr = StrStr (SubString, Delimiter);\r
1019 if (StringPtr != NULL) {\r
1020 *StringPtr = L'\0';\r
1021 }\r
1022 }\r
1023\r
1024 Result->Type = EFI_IFR_TYPE_STRING;\r
1025 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1026\r
1027Done:\r
1028 SafeFreePool (String[0]);\r
1029 SafeFreePool (String[1]);\r
1030\r
1031 return Status;\r
1032}\r
1033\r
1034\r
1035/**\r
1036 Evaluate opcode EFI_IFR_SPAN.\r
1037\r
1038 @param FormSet Formset which contains this opcode.\r
1039 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1040 @param Result Evaluation result for this opcode.\r
1041\r
1042 @retval EFI_SUCCESS Opcode evaluation success.\r
1043 @retval Other Opcode evaluation failed.\r
1044\r
1045**/\r
1046EFI_STATUS\r
1047IfrSpan (\r
1048 IN FORM_BROWSER_FORMSET *FormSet,\r
1049 IN UINT8 Flags,\r
1050 OUT EFI_HII_VALUE *Result\r
1051 )\r
1052{\r
1053 EFI_STATUS Status;\r
1054 EFI_HII_VALUE Value;\r
1055 CHAR16 *String[2];\r
1056 CHAR16 *Charset;\r
1057 UINTN Base;\r
1058 UINTN Index;\r
1059 CHAR16 *StringPtr;\r
1060 BOOLEAN Found;\r
1061\r
1062 Status = PopExpression (&Value);\r
1063 if (EFI_ERROR (Status)) {\r
1064 return Status;\r
1065 }\r
1066 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1067 return EFI_UNSUPPORTED;\r
1068 }\r
1069 Base = (UINTN) Value.Value.u64;\r
1070\r
1071 //\r
1072 // String[0] - Charset\r
1073 // String[1] - The string to search\r
1074 //\r
1075 String[0] = NULL;\r
1076 String[1] = NULL;\r
1077 for (Index = 0; Index < 2; Index++) {\r
1078 Status = PopExpression (&Value);\r
1079 if (EFI_ERROR (Status)) {\r
1080 goto Done;\r
1081 }\r
1082\r
1083 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1084 Status = EFI_UNSUPPORTED;\r
1085 goto Done;\r
1086 }\r
1087\r
1088 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1089 if (String== NULL) {\r
1090 Status = EFI_NOT_FOUND;\r
1091 goto Done;\r
1092 }\r
1093 }\r
1094\r
1095 if (Base >= StrLen (String[1])) {\r
1096 Status = EFI_UNSUPPORTED;\r
1097 goto Done;\r
1098 }\r
1099\r
1100 Found = FALSE;\r
1101 StringPtr = String[1] + Base;\r
1102 Charset = String[0];\r
1103 while (*StringPtr != 0 && !Found) {\r
1104 Index = 0;\r
1105 while (Charset[Index] != 0) {\r
1106 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
1107 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1108 Found = TRUE;\r
1109 break;\r
1110 }\r
1111 } else {\r
1112 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1113 Found = TRUE;\r
1114 break;\r
1115 }\r
1116 }\r
1117 //\r
1118 // Skip characters pair representing low-end of a range and high-end of a range\r
1119 //\r
1120 Index += 2;\r
1121 }\r
1122\r
1123 if (!Found) {\r
1124 StringPtr++;\r
1125 }\r
1126 }\r
1127\r
1128 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1129 Result->Value.u64 = StringPtr - String[1];\r
1130\r
1131Done:\r
1132 SafeFreePool (String[0]);\r
1133 SafeFreePool (String[1]);\r
1134\r
1135 return Status;\r
1136}\r
1137\r
1138\r
1139/**\r
1140 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1141\r
1142 @param Value HII Value to be converted.\r
1143\r
1144**/\r
1145VOID\r
1146ExtendValueToU64 (\r
1147 IN EFI_HII_VALUE *Value\r
1148 )\r
1149{\r
1150 UINT64 Temp;\r
1151\r
1152 Temp = 0;\r
1153 switch (Value->Type) {\r
1154 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1155 Temp = Value->Value.u8;\r
1156 break;\r
1157\r
1158 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1159 Temp = Value->Value.u16;\r
1160 break;\r
1161\r
1162 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1163 Temp = Value->Value.u32;\r
1164 break;\r
1165\r
1166 case EFI_IFR_TYPE_BOOLEAN:\r
1167 Temp = Value->Value.b;\r
1168 break;\r
1169\r
1170 case EFI_IFR_TYPE_TIME:\r
1171 Temp = Value->Value.u32 & 0xffffff;\r
1172 break;\r
1173\r
1174 case EFI_IFR_TYPE_DATE:\r
1175 Temp = Value->Value.u32;\r
1176 break;\r
1177\r
1178 default:\r
1179 return;\r
1180 }\r
1181\r
1182 Value->Value.u64 = Temp;\r
1183}\r
1184\r
1185\r
1186/**\r
1187 Compare two Hii value.\r
1188\r
1189 @param Value1 Expression value to compare on left-hand.\r
1190 @param Value2 Expression value to compare on right-hand.\r
1191 @param HiiHandle Only required for string compare.\r
1192\r
1193 @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.\r
1194 @retval 0 Two operators equeal.\r
1195 @return Positive value if Value1 is greater than Value2.\r
1196 @retval Negative value if Value1 is less than Value2.\r
1197\r
1198**/\r
1199INTN\r
1200CompareHiiValue (\r
1201 IN EFI_HII_VALUE *Value1,\r
1202 IN EFI_HII_VALUE *Value2,\r
1203 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
1204 )\r
1205{\r
1206 INTN Result;\r
1207 INT64 Temp64;\r
1208 CHAR16 *Str1;\r
1209 CHAR16 *Str2;\r
1210\r
1211 if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
1212 return EFI_INVALID_PARAMETER;\r
1213 }\r
1214\r
1215 if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
1216 if (Value1->Type != Value2->Type) {\r
1217 //\r
1218 // Both Operator should be type of String\r
1219 //\r
1220 return EFI_INVALID_PARAMETER;\r
1221 }\r
1222\r
1223 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
1224 //\r
1225 // StringId 0 is reserved\r
1226 //\r
1227 return EFI_INVALID_PARAMETER;\r
1228 }\r
1229\r
1230 if (Value1->Value.string == Value2->Value.string) {\r
1231 return 0;\r
1232 }\r
1233\r
1234 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
1235 if (Str1 == NULL) {\r
1236 //\r
1237 // String not found\r
1238 //\r
1239 return EFI_INVALID_PARAMETER;\r
1240 }\r
1241\r
1242 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
1243 if (Str2 == NULL) {\r
1244 gBS->FreePool (Str1);\r
1245 return EFI_INVALID_PARAMETER;\r
1246 }\r
1247\r
1248 Result = StrCmp (Str1, Str2);\r
1249\r
1250 gBS->FreePool (Str1);\r
1251 gBS->FreePool (Str2);\r
1252\r
1253 return Result;\r
1254 }\r
1255\r
1256 //\r
1257 // Take remain types(integer, boolean, date/time) as integer\r
1258 //\r
1259 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
1260 if (Temp64 > 0) {\r
1261 Result = 1;\r
1262 } else if (Temp64 < 0) {\r
1263 Result = -1;\r
1264 } else {\r
1265 Result = 0;\r
1266 }\r
1267\r
1268 return Result;\r
1269}\r
1270\r
1271\r
1272/**\r
1273 Evaluate the result of a HII expression\r
1274\r
1275 @param FormSet FormSet associated with this expression.\r
1276 @param Form Form associated with this expression.\r
1277 @param Expression Expression to be evaluated.\r
1278\r
1279 @retval EFI_SUCCESS The expression evaluated successfuly\r
1280 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
1281 could not be found.\r
1282 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
1283 stack.\r
1284 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
1285 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
1286\r
1287**/\r
1288EFI_STATUS\r
1289EvaluateExpression (\r
1290 IN FORM_BROWSER_FORMSET *FormSet,\r
1291 IN FORM_BROWSER_FORM *Form,\r
1292 IN OUT FORM_EXPRESSION *Expression\r
1293 )\r
1294{\r
1295 EFI_STATUS Status;\r
1296 LIST_ENTRY *Link;\r
1297 EXPRESSION_OPCODE *OpCode;\r
1298 FORM_BROWSER_STATEMENT *Question;\r
1299 FORM_BROWSER_STATEMENT *Question2;\r
1300 UINT16 Index;\r
1301 EFI_HII_VALUE Data1;\r
1302 EFI_HII_VALUE Data2;\r
1303 EFI_HII_VALUE Data3;\r
1304 FORM_EXPRESSION *RuleExpression;\r
1305 EFI_HII_VALUE *Value;\r
1306 INTN Result;\r
1307 CHAR16 *StrPtr;\r
1308 UINT32 TempValue;\r
1309\r
1310 //\r
1311 // Always reset the stack before evaluating an Expression\r
1312 //\r
1313 ResetExpressionStack ();\r
1314\r
1315 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
1316\r
1317 Link = GetFirstNode (&Expression->OpCodeListHead);\r
1318 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
1319 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
1320\r
1321 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
1322\r
1323 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
1324 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
1325 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
1326\r
1327 Value = &Data3;\r
1328 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1329 Status = EFI_SUCCESS;\r
1330\r
1331 switch (OpCode->Operand) {\r
1332 //\r
1333 // Built-in functions\r
1334 //\r
1335 case EFI_IFR_EQ_ID_VAL_OP:\r
1336 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1337 if (Question == NULL) {\r
1338 return EFI_NOT_FOUND;\r
1339 }\r
1340\r
1341 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
1342 if (Result == EFI_INVALID_PARAMETER) {\r
1343 return EFI_INVALID_PARAMETER;\r
1344 }\r
1345 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1346 break;\r
1347\r
1348 case EFI_IFR_EQ_ID_ID_OP:\r
1349 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1350 if (Question == NULL) {\r
1351 return EFI_NOT_FOUND;\r
1352 }\r
1353\r
1354 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
1355 if (Question2 == NULL) {\r
1356 return EFI_NOT_FOUND;\r
1357 }\r
1358\r
1359 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
1360 if (Result == EFI_INVALID_PARAMETER) {\r
1361 return EFI_INVALID_PARAMETER;\r
1362 }\r
1363 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1364 break;\r
1365\r
1366 case EFI_IFR_EQ_ID_LIST_OP:\r
1367 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1368 if (Question == NULL) {\r
1369 return EFI_NOT_FOUND;\r
1370 }\r
1371\r
1372 Value->Value.b = FALSE;\r
1373 for (Index =0; Index < OpCode->ListLength; Index++) {\r
1374 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
1375 Value->Value.b = TRUE;\r
1376 break;\r
1377 }\r
1378 }\r
1379 break;\r
1380\r
1381 case EFI_IFR_DUP_OP:\r
1382 Status = PopExpression (Value);\r
1383 if (EFI_ERROR (Status)) {\r
1384 return Status;\r
1385 }\r
1386\r
1387 Status = PushExpression (Value);\r
1388 break;\r
1389\r
1390 case EFI_IFR_QUESTION_REF1_OP:\r
1391 case EFI_IFR_THIS_OP:\r
1392 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1393 if (Question == NULL) {\r
1394 return EFI_NOT_FOUND;\r
1395 }\r
1396\r
1397 Value = &Question->HiiValue;\r
1398 break;\r
1399\r
1400 case EFI_IFR_QUESTION_REF3_OP:\r
1401 if (OpCode->DevicePath == 0) {\r
1402 //\r
1403 // EFI_IFR_QUESTION_REF3\r
1404 // Pop an expression from the expression stack\r
1405 //\r
1406 Status = PopExpression (Value);\r
1407 if (EFI_ERROR (Status)) {\r
1408 return Status;\r
1409 }\r
1410\r
1411 //\r
1412 // Validate the expression value\r
1413 //\r
1414 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1415 return EFI_NOT_FOUND;\r
1416 }\r
1417\r
1418 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1419 if (Question == NULL) {\r
1420 return EFI_NOT_FOUND;\r
1421 }\r
1422\r
1423 //\r
1424 // push the questions' value on to the expression stack\r
1425 //\r
1426 Value = &Question->HiiValue;\r
1427 } else {\r
1428 //\r
1429 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
1430 // since it is impractical to evaluate the value of a Question in another\r
1431 // Hii Package list.\r
1432 //\r
1433 ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
1434 }\r
1435 break;\r
1436\r
1437 case EFI_IFR_RULE_REF_OP:\r
1438 //\r
1439 // Find expression for this rule\r
1440 //\r
1441 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
1442 if (RuleExpression == NULL) {\r
1443 return EFI_NOT_FOUND;\r
1444 }\r
1445\r
1446 //\r
1447 // Evaluate this rule expression\r
1448 //\r
1449 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
1450 if (EFI_ERROR (Status)) {\r
1451 return Status;\r
1452 }\r
1453\r
1454 Value = &RuleExpression->Result;\r
1455 break;\r
1456\r
1457 case EFI_IFR_STRING_REF1_OP:\r
1458 Value->Type = EFI_IFR_TYPE_STRING;\r
1459 Value->Value.string = OpCode->Value.Value.string;\r
1460 break;\r
1461\r
1462 //\r
1463 // Constant\r
1464 //\r
1465 case EFI_IFR_TRUE_OP:\r
1466 case EFI_IFR_FALSE_OP:\r
1467 case EFI_IFR_ONE_OP:\r
1468 case EFI_IFR_ONES_OP:\r
1469 case EFI_IFR_UINT8_OP:\r
1470 case EFI_IFR_UINT16_OP:\r
1471 case EFI_IFR_UINT32_OP:\r
1472 case EFI_IFR_UINT64_OP:\r
1473 case EFI_IFR_UNDEFINED_OP:\r
1474 case EFI_IFR_VERSION_OP:\r
1475 case EFI_IFR_ZERO_OP:\r
1476 Value = &OpCode->Value;\r
1477 break;\r
1478\r
1479 //\r
1480 // unary-op\r
1481 //\r
1482 case EFI_IFR_LENGTH_OP:\r
1483 Status = PopExpression (Value);\r
1484 if (EFI_ERROR (Status)) {\r
1485 return Status;\r
1486 }\r
1487 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1488 return EFI_INVALID_PARAMETER;\r
1489 }\r
1490\r
1491 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1492 if (StrPtr == NULL) {\r
1493 return EFI_INVALID_PARAMETER;\r
1494 }\r
1495\r
1496 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1497 Value->Value.u64 = StrLen (StrPtr);\r
1498 gBS->FreePool (StrPtr);\r
1499 break;\r
1500\r
1501 case EFI_IFR_NOT_OP:\r
1502 Status = PopExpression (Value);\r
1503 if (EFI_ERROR (Status)) {\r
1504 return Status;\r
1505 }\r
1506 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
1507 return EFI_INVALID_PARAMETER;\r
1508 }\r
1509 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
1510 break;\r
1511\r
1512 case EFI_IFR_QUESTION_REF2_OP:\r
1513 //\r
1514 // Pop an expression from the expression stack\r
1515 //\r
1516 Status = PopExpression (Value);\r
1517 if (EFI_ERROR (Status)) {\r
1518 return Status;\r
1519 }\r
1520\r
1521 //\r
1522 // Validate the expression value\r
1523 //\r
1524 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1525 return EFI_NOT_FOUND;\r
1526 }\r
1527\r
1528 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1529 if (Question == NULL) {\r
1530 return EFI_NOT_FOUND;\r
1531 }\r
1532\r
1533 Value = &Question->HiiValue;\r
1534 break;\r
1535\r
1536 case EFI_IFR_STRING_REF2_OP:\r
1537 //\r
1538 // Pop an expression from the expression stack\r
1539 //\r
1540 Status = PopExpression (Value);\r
1541 if (EFI_ERROR (Status)) {\r
1542 return Status;\r
1543 }\r
1544\r
1545 //\r
1546 // Validate the expression value\r
1547 //\r
1548 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1549 return EFI_NOT_FOUND;\r
1550 }\r
1551\r
1552 Value->Type = EFI_IFR_TYPE_STRING;\r
1553 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
1554 if (StrPtr == NULL) {\r
1555 //\r
1556 // If String not exit, push an empty string\r
1557 //\r
1558 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
1559 } else {\r
1560 Index = (UINT16) Value->Value.u64;\r
1561 Value->Value.string = Index;\r
1562 gBS->FreePool (StrPtr);\r
1563 }\r
1564 break;\r
1565\r
1566 case EFI_IFR_TO_BOOLEAN_OP:\r
1567 //\r
1568 // Pop an expression from the expression stack\r
1569 //\r
1570 Status = PopExpression (Value);\r
1571 if (EFI_ERROR (Status)) {\r
1572 return Status;\r
1573 }\r
1574\r
1575 //\r
1576 // Convert an expression to a Boolean\r
1577 //\r
1578 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
1579 //\r
1580 // When converting from an unsigned integer, zero will be converted to\r
1581 // FALSE and any other value will be converted to TRUE.\r
1582 //\r
1583 Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);\r
1584\r
1585 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1586 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
1587 //\r
1588 // When converting from a string, if case-insensitive compare\r
1589 // with "true" is True, then push True. If a case-insensitive compare\r
1590 // with "false" is True, then push False.\r
1591 //\r
1592 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1593 if (StrPtr == NULL) {\r
1594 return EFI_INVALID_PARAMETER;\r
1595 }\r
1596\r
1597 if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){\r
1598 Value->Value.b = TRUE;\r
1599 } else {\r
1600 Value->Value.b = FALSE;\r
1601 }\r
1602 gBS->FreePool (StrPtr);\r
1603 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1604 }\r
1605 break;\r
1606\r
1607 case EFI_IFR_TO_STRING_OP:\r
1608 Status = IfrToString (FormSet, OpCode->Format, Value);\r
1609 break;\r
1610\r
1611 case EFI_IFR_TO_UINT_OP:\r
1612 Status = IfrToUint (FormSet, Value);\r
1613 break;\r
1614\r
1615 case EFI_IFR_TO_LOWER_OP:\r
1616 case EFI_IFR_TO_UPPER_OP:\r
1617 Status = InitializeUnicodeCollationProtocol ();\r
1618 if (EFI_ERROR (Status)) {\r
1619 return Status;\r
1620 }\r
1621\r
1622 Status = PopExpression (Value);\r
1623 if (EFI_ERROR (Status)) {\r
1624 return Status;\r
1625 }\r
1626\r
1627 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1628 return EFI_UNSUPPORTED;\r
1629 }\r
1630\r
1631 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1632 if (StrPtr == NULL) {\r
1633 return EFI_NOT_FOUND;\r
1634 }\r
1635\r
1636 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
1637 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
1638 } else {\r
1639 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
1640 }\r
1641 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
1642 gBS->FreePool (StrPtr);\r
1643 break;\r
1644\r
1645 case EFI_IFR_BITWISE_NOT_OP:\r
1646 //\r
1647 // Pop an expression from the expression stack\r
1648 //\r
1649 Status = PopExpression (Value);\r
1650 if (EFI_ERROR (Status)) {\r
1651 return Status;\r
1652 }\r
1653 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
1654 return EFI_INVALID_PARAMETER;\r
1655 }\r
1656\r
1657 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1658 Value->Value.u64 = ~Value->Value.u64;\r
1659 break;\r
1660\r
1661 //\r
1662 // binary-op\r
1663 //\r
1664 case EFI_IFR_ADD_OP:\r
1665 case EFI_IFR_SUBTRACT_OP:\r
1666 case EFI_IFR_MULTIPLY_OP:\r
1667 case EFI_IFR_DIVIDE_OP:\r
1668 case EFI_IFR_MODULO_OP:\r
1669 case EFI_IFR_BITWISE_AND_OP:\r
1670 case EFI_IFR_BITWISE_OR_OP:\r
1671 case EFI_IFR_SHIFT_LEFT_OP:\r
1672 case EFI_IFR_SHIFT_RIGHT_OP:\r
1673 //\r
1674 // Pop an expression from the expression stack\r
1675 //\r
1676 Status = PopExpression (&Data2);\r
1677 if (EFI_ERROR (Status)) {\r
1678 return Status;\r
1679 }\r
1680 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
1681 return EFI_INVALID_PARAMETER;\r
1682 }\r
1683\r
1684 //\r
1685 // Pop another expression from the expression stack\r
1686 //\r
1687 Status = PopExpression (&Data1);\r
1688 if (EFI_ERROR (Status)) {\r
1689 return Status;\r
1690 }\r
1691 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
1692 return EFI_INVALID_PARAMETER;\r
1693 }\r
1694\r
1695 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1696\r
1697 switch (OpCode->Operand) {\r
1698 case EFI_IFR_ADD_OP:\r
1699 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
1700 break;\r
1701\r
1702 case EFI_IFR_SUBTRACT_OP:\r
1703 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
1704 break;\r
1705\r
1706 case EFI_IFR_MULTIPLY_OP:\r
1707 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
1708 break;\r
1709\r
1710 case EFI_IFR_DIVIDE_OP:\r
1711 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
1712 break;\r
1713\r
1714 case EFI_IFR_MODULO_OP:\r
1715 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
1716 Value->Value.u64 = TempValue;\r
1717 break;\r
1718\r
1719 case EFI_IFR_BITWISE_AND_OP:\r
1720 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
1721 break;\r
1722\r
1723 case EFI_IFR_BITWISE_OR_OP:\r
1724 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
1725 break;\r
1726\r
1727 case EFI_IFR_SHIFT_LEFT_OP:\r
1728 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
1729 break;\r
1730\r
1731 case EFI_IFR_SHIFT_RIGHT_OP:\r
1732 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
1733 break;\r
1734\r
1735 default:\r
1736 break;\r
1737 }\r
1738 break;\r
1739\r
1740 case EFI_IFR_AND_OP:\r
1741 case EFI_IFR_OR_OP:\r
1742 //\r
1743 // Two Boolean operator\r
1744 //\r
1745 Status = PopExpression (&Data2);\r
1746 if (EFI_ERROR (Status)) {\r
1747 return Status;\r
1748 }\r
1749 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1750 return EFI_INVALID_PARAMETER;\r
1751 }\r
1752\r
1753 //\r
1754 // Pop another expression from the expression stack\r
1755 //\r
1756 Status = PopExpression (&Data1);\r
1757 if (EFI_ERROR (Status)) {\r
1758 return Status;\r
1759 }\r
1760 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1761 return EFI_INVALID_PARAMETER;\r
1762 }\r
1763\r
1764 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
1765 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
1766 } else {\r
1767 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
1768 }\r
1769 break;\r
1770\r
1771 case EFI_IFR_EQUAL_OP:\r
1772 case EFI_IFR_NOT_EQUAL_OP:\r
1773 case EFI_IFR_GREATER_EQUAL_OP:\r
1774 case EFI_IFR_GREATER_THAN_OP:\r
1775 case EFI_IFR_LESS_EQUAL_OP:\r
1776 case EFI_IFR_LESS_THAN_OP:\r
1777 //\r
1778 // Compare two integer, string, boolean or date/time\r
1779 //\r
1780 Status = PopExpression (&Data2);\r
1781 if (EFI_ERROR (Status)) {\r
1782 return Status;\r
1783 }\r
1784 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
1785 return EFI_INVALID_PARAMETER;\r
1786 }\r
1787\r
1788 //\r
1789 // Pop another expression from the expression stack\r
1790 //\r
1791 Status = PopExpression (&Data1);\r
1792 if (EFI_ERROR (Status)) {\r
1793 return Status;\r
1794 }\r
1795\r
1796 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
1797 if (Result == EFI_INVALID_PARAMETER) {\r
1798 return EFI_INVALID_PARAMETER;\r
1799 }\r
1800\r
1801 switch (OpCode->Operand) {\r
1802 case EFI_IFR_EQUAL_OP:\r
1803 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1804 break;\r
1805\r
1806 case EFI_IFR_NOT_EQUAL_OP:\r
1807 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1808 break;\r
1809\r
1810 case EFI_IFR_GREATER_EQUAL_OP:\r
1811 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
1812 break;\r
1813\r
1814 case EFI_IFR_GREATER_THAN_OP:\r
1815 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
1816 break;\r
1817\r
1818 case EFI_IFR_LESS_EQUAL_OP:\r
1819 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
1820 break;\r
1821\r
1822 case EFI_IFR_LESS_THAN_OP:\r
1823 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
1824 break;\r
1825\r
1826 default:\r
1827 break;\r
1828 }\r
1829 break;\r
1830\r
1831 case EFI_IFR_MATCH_OP:\r
1832 Status = IfrMatch (FormSet, Value);\r
1833 break;\r
1834\r
1835 case EFI_IFR_CATENATE_OP:\r
1836 Status = IfrCatenate (FormSet, Value);\r
1837 break;\r
1838\r
1839 //\r
1840 // ternary-op\r
1841 //\r
1842 case EFI_IFR_CONDITIONAL_OP:\r
1843 //\r
1844 // Pop third expression from the expression stack\r
1845 //\r
1846 Status = PopExpression (&Data3);\r
1847 if (EFI_ERROR (Status)) {\r
1848 return Status;\r
1849 }\r
1850\r
1851 //\r
1852 // Pop second expression from the expression stack\r
1853 //\r
1854 Status = PopExpression (&Data2);\r
1855 if (EFI_ERROR (Status)) {\r
1856 return Status;\r
1857 }\r
1858\r
1859 //\r
1860 // Pop first expression from the expression stack\r
1861 //\r
1862 Status = PopExpression (&Data1);\r
1863 if (EFI_ERROR (Status)) {\r
1864 return Status;\r
1865 }\r
1866 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1867 return EFI_INVALID_PARAMETER;\r
1868 }\r
1869\r
1870 if (Data1.Value.b) {\r
1871 Value = &Data3;\r
1872 } else {\r
1873 Value = &Data2;\r
1874 }\r
1875 break;\r
1876\r
1877 case EFI_IFR_FIND_OP:\r
1878 Status = IfrFind (FormSet, OpCode->Format, Value);\r
1879 break;\r
1880\r
1881 case EFI_IFR_MID_OP:\r
1882 Status = IfrMid (FormSet, Value);\r
1883 break;\r
1884\r
1885 case EFI_IFR_TOKEN_OP:\r
1886 Status = IfrToken (FormSet, Value);\r
1887 break;\r
1888\r
1889 case EFI_IFR_SPAN_OP:\r
1890 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
1891 break;\r
1892\r
1893 default:\r
1894 break;\r
1895 }\r
1896 if (EFI_ERROR (Status)) {\r
1897 return Status;\r
1898 }\r
1899\r
1900 Status = PushExpression (Value);\r
1901 if (EFI_ERROR (Status)) {\r
1902 return Status;\r
1903 }\r
1904 }\r
1905\r
1906 //\r
1907 // Pop the final result from expression stack\r
1908 //\r
1909 Value = &Data1;\r
1910 Status = PopExpression (Value);\r
1911 if (EFI_ERROR (Status)) {\r
1912 return Status;\r
1913 }\r
1914\r
1915 //\r
1916 // After evaluating an expression, there should be only one value left on the expression stack\r
1917 //\r
1918 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
1919 return EFI_INVALID_PARAMETER;\r
1920 }\r
1921\r
1922 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
1923\r
1924 return EFI_SUCCESS;\r
1925}\r