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