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