]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/FrameworkHiiToUefiHiiThunk/UefiIfrParserExpression.c
Update FrameworkHiiToUefiHiiThunk to produce Framework HII Protocol and Framework...
[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
735 SafeFreePool (String[0]);\r
736 SafeFreePool (String[1]);\r
737 SafeFreePool (StringPtr);\r
738\r
739 return Status;\r
740}\r
741\r
742\r
743/**\r
744 Evaluate opcode EFI_IFR_MATCH.\r
745\r
746 @param FormSet Formset which contains this opcode.\r
747 @param Result Evaluation result for this opcode.\r
748\r
749 @retval EFI_SUCCESS Opcode evaluation success.\r
750 @retval Other Opcode evaluation failed.\r
751\r
752**/\r
753EFI_STATUS\r
754IfrMatch (\r
755 IN FORM_BROWSER_FORMSET *FormSet,\r
756 OUT EFI_HII_VALUE *Result\r
757 )\r
758{\r
759 EFI_STATUS Status;\r
760 EFI_HII_VALUE Value;\r
761 CHAR16 *String[2];\r
762 UINTN Index;\r
763\r
764 //\r
765 // String[0] - The string to search\r
766 // String[1] - pattern\r
767 //\r
768 String[0] = NULL;\r
769 String[1] = NULL;\r
770 Status = EFI_SUCCESS;\r
771 for (Index = 0; Index < 2; Index++) {\r
772 Status = PopExpression (&Value);\r
773 if (EFI_ERROR (Status)) {\r
774 goto Done;\r
775 }\r
776\r
777 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
778 Status = EFI_UNSUPPORTED;\r
779 goto Done;\r
780 }\r
781\r
782 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
783 if (String== NULL) {\r
784 Status = EFI_NOT_FOUND;\r
785 goto Done;\r
786 }\r
787 }\r
788\r
789 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
790 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
791\r
792Done:\r
793 SafeFreePool (String[0]);\r
794 SafeFreePool (String[1]);\r
795\r
796 return Status;\r
797}\r
798\r
799\r
800/**\r
801 Evaluate opcode EFI_IFR_FIND.\r
802\r
803 @param FormSet Formset which contains this opcode.\r
804 @param Format Case sensitive or insensitive.\r
805 @param Result Evaluation result for this opcode.\r
806\r
807 @retval EFI_SUCCESS Opcode evaluation success.\r
808 @retval Other Opcode evaluation failed.\r
809\r
810**/\r
811EFI_STATUS\r
812IfrFind (\r
813 IN FORM_BROWSER_FORMSET *FormSet,\r
814 IN UINT8 Format,\r
815 OUT EFI_HII_VALUE *Result\r
816 )\r
817{\r
818 EFI_STATUS Status;\r
819 EFI_HII_VALUE Value;\r
820 CHAR16 *String[2];\r
821 UINTN Base;\r
822 CHAR16 *StringPtr;\r
823 UINTN Index;\r
824\r
825 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
826 return EFI_UNSUPPORTED;\r
827 }\r
828\r
829 Status = PopExpression (&Value);\r
830 if (EFI_ERROR (Status)) {\r
831 return Status;\r
832 }\r
833 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
834 return EFI_UNSUPPORTED;\r
835 }\r
836 Base = (UINTN) Value.Value.u64;\r
837\r
838 //\r
839 // String[0] - sub-string\r
840 // String[1] - The string to search\r
841 //\r
842 String[0] = NULL;\r
843 String[1] = NULL;\r
844 for (Index = 0; Index < 2; Index++) {\r
845 Status = PopExpression (&Value);\r
846 if (EFI_ERROR (Status)) {\r
847 goto Done;\r
848 }\r
849\r
850 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
851 Status = EFI_UNSUPPORTED;\r
852 goto Done;\r
853 }\r
854\r
855 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
856 if (String== NULL) {\r
857 Status = EFI_NOT_FOUND;\r
858 goto Done;\r
859 }\r
860\r
861 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
862 //\r
863 // Case insensitive, convert both string to upper case\r
864 //\r
865 IfrStrToUpper (String[Index]);\r
866 }\r
867 }\r
868\r
869 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
870 if (Base >= StrLen (String[1])) {\r
871 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
872 } else {\r
873 StringPtr = StrStr (String[1] + Base, String[0]);\r
874 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
875 }\r
876\r
877Done:\r
878 SafeFreePool (String[0]);\r
879 SafeFreePool (String[1]);\r
880\r
881 return Status;\r
882}\r
883\r
884\r
885/**\r
886 Evaluate opcode EFI_IFR_MID.\r
887\r
888 @param FormSet Formset which contains this opcode.\r
889 @param Result Evaluation result for this opcode.\r
890\r
891 @retval EFI_SUCCESS Opcode evaluation success.\r
892 @retval Other Opcode evaluation failed.\r
893\r
894**/\r
895EFI_STATUS\r
896IfrMid (\r
897 IN FORM_BROWSER_FORMSET *FormSet,\r
898 OUT EFI_HII_VALUE *Result\r
899 )\r
900{\r
901 EFI_STATUS Status;\r
902 EFI_HII_VALUE Value;\r
903 CHAR16 *String;\r
904 UINTN Base;\r
905 UINTN Length;\r
906 CHAR16 *SubString;\r
907\r
908 Status = PopExpression (&Value);\r
909 if (EFI_ERROR (Status)) {\r
910 return Status;\r
911 }\r
912 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
913 return EFI_UNSUPPORTED;\r
914 }\r
915 Length = (UINTN) Value.Value.u64;\r
916\r
917 Status = PopExpression (&Value);\r
918 if (EFI_ERROR (Status)) {\r
919 return Status;\r
920 }\r
921 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
922 return EFI_UNSUPPORTED;\r
923 }\r
924 Base = (UINTN) Value.Value.u64;\r
925\r
926 Status = PopExpression (&Value);\r
927 if (EFI_ERROR (Status)) {\r
928 return Status;\r
929 }\r
930 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
931 return EFI_UNSUPPORTED;\r
932 }\r
933 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
934 if (String == NULL) {\r
935 return EFI_NOT_FOUND;\r
936 }\r
937\r
938 if (Length == 0 || Base >= StrLen (String)) {\r
939 SubString = gEmptyString;\r
940 } else {\r
941 SubString = String + Base;\r
942 if ((Base + Length) < StrLen (String)) {\r
943 SubString[Length] = L'\0';\r
944 }\r
945 }\r
946\r
947 Result->Type = EFI_IFR_TYPE_STRING;\r
948 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
949\r
950 gBS->FreePool (String);\r
951\r
952 return Status;\r
953}\r
954\r
955\r
956/**\r
957 Evaluate opcode EFI_IFR_TOKEN.\r
958\r
959 @param FormSet Formset which contains this opcode.\r
960 @param Result Evaluation result for this opcode.\r
961\r
962 @retval EFI_SUCCESS Opcode evaluation success.\r
963 @retval Other Opcode evaluation failed.\r
964\r
965**/\r
966EFI_STATUS\r
967IfrToken (\r
968 IN FORM_BROWSER_FORMSET *FormSet,\r
969 OUT EFI_HII_VALUE *Result\r
970 )\r
971{\r
972 EFI_STATUS Status;\r
973 EFI_HII_VALUE Value;\r
974 CHAR16 *String[2];\r
975 UINTN Count;\r
976 CHAR16 *Delimiter;\r
977 CHAR16 *SubString;\r
978 CHAR16 *StringPtr;\r
979 UINTN Index;\r
980\r
981 Status = PopExpression (&Value);\r
982 if (EFI_ERROR (Status)) {\r
983 return Status;\r
984 }\r
985 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
986 return EFI_UNSUPPORTED;\r
987 }\r
988 Count = (UINTN) Value.Value.u64;\r
989\r
990 //\r
991 // String[0] - Delimiter\r
992 // String[1] - The string to search\r
993 //\r
994 String[0] = NULL;\r
995 String[1] = NULL;\r
996 for (Index = 0; Index < 2; Index++) {\r
997 Status = PopExpression (&Value);\r
998 if (EFI_ERROR (Status)) {\r
999 goto Done;\r
1000 }\r
1001\r
1002 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1003 Status = EFI_UNSUPPORTED;\r
1004 goto Done;\r
1005 }\r
1006\r
1007 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1008 if (String== NULL) {\r
1009 Status = EFI_NOT_FOUND;\r
1010 goto Done;\r
1011 }\r
1012 }\r
1013\r
1014 Delimiter = String[0];\r
1015 SubString = String[1];\r
1016 while (Count > 0) {\r
1017 SubString = StrStr (SubString, Delimiter);\r
1018 if (SubString != NULL) {\r
1019 //\r
1020 // Skip over the delimiter\r
1021 //\r
1022 SubString = SubString + StrLen (Delimiter);\r
1023 } else {\r
1024 break;\r
1025 }\r
1026 Count--;\r
1027 }\r
1028\r
1029 if (SubString == NULL) {\r
1030 //\r
1031 // nth delimited sub-string not found, push an empty string\r
1032 //\r
1033 SubString = gEmptyString;\r
1034 } else {\r
1035 //\r
1036 // Put a NULL terminator for nth delimited sub-string\r
1037 //\r
1038 StringPtr = StrStr (SubString, Delimiter);\r
1039 if (StringPtr != NULL) {\r
1040 *StringPtr = L'\0';\r
1041 }\r
1042 }\r
1043\r
1044 Result->Type = EFI_IFR_TYPE_STRING;\r
1045 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1046\r
1047Done:\r
1048 SafeFreePool (String[0]);\r
1049 SafeFreePool (String[1]);\r
1050\r
1051 return Status;\r
1052}\r
1053\r
1054\r
1055/**\r
1056 Evaluate opcode EFI_IFR_SPAN.\r
1057\r
1058 @param FormSet Formset which contains this opcode.\r
1059 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1060 @param Result Evaluation result for this opcode.\r
1061\r
1062 @retval EFI_SUCCESS Opcode evaluation success.\r
1063 @retval Other Opcode evaluation failed.\r
1064\r
1065**/\r
1066EFI_STATUS\r
1067IfrSpan (\r
1068 IN FORM_BROWSER_FORMSET *FormSet,\r
1069 IN UINT8 Flags,\r
1070 OUT EFI_HII_VALUE *Result\r
1071 )\r
1072{\r
1073 EFI_STATUS Status;\r
1074 EFI_HII_VALUE Value;\r
1075 CHAR16 *String[2];\r
1076 CHAR16 *Charset;\r
1077 UINTN Base;\r
1078 UINTN Index;\r
1079 CHAR16 *StringPtr;\r
1080 BOOLEAN Found;\r
1081\r
1082 Status = PopExpression (&Value);\r
1083 if (EFI_ERROR (Status)) {\r
1084 return Status;\r
1085 }\r
1086 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1087 return EFI_UNSUPPORTED;\r
1088 }\r
1089 Base = (UINTN) Value.Value.u64;\r
1090\r
1091 //\r
1092 // String[0] - Charset\r
1093 // String[1] - The string to search\r
1094 //\r
1095 String[0] = NULL;\r
1096 String[1] = NULL;\r
1097 for (Index = 0; Index < 2; Index++) {\r
1098 Status = PopExpression (&Value);\r
1099 if (EFI_ERROR (Status)) {\r
1100 goto Done;\r
1101 }\r
1102\r
1103 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1104 Status = EFI_UNSUPPORTED;\r
1105 goto Done;\r
1106 }\r
1107\r
1108 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1109 if (String== NULL) {\r
1110 Status = EFI_NOT_FOUND;\r
1111 goto Done;\r
1112 }\r
1113 }\r
1114\r
1115 if (Base >= StrLen (String[1])) {\r
1116 Status = EFI_UNSUPPORTED;\r
1117 goto Done;\r
1118 }\r
1119\r
1120 Found = FALSE;\r
1121 StringPtr = String[1] + Base;\r
1122 Charset = String[0];\r
1123 while (*StringPtr != 0 && !Found) {\r
1124 Index = 0;\r
1125 while (Charset[Index] != 0) {\r
1126 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
1127 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1128 Found = TRUE;\r
1129 break;\r
1130 }\r
1131 } else {\r
1132 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1133 Found = TRUE;\r
1134 break;\r
1135 }\r
1136 }\r
1137 //\r
1138 // Skip characters pair representing low-end of a range and high-end of a range\r
1139 //\r
1140 Index += 2;\r
1141 }\r
1142\r
1143 if (!Found) {\r
1144 StringPtr++;\r
1145 }\r
1146 }\r
1147\r
1148 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1149 Result->Value.u64 = StringPtr - String[1];\r
1150\r
1151Done:\r
1152 SafeFreePool (String[0]);\r
1153 SafeFreePool (String[1]);\r
1154\r
1155 return Status;\r
1156}\r
1157\r
1158\r
1159/**\r
1160 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1161\r
1162 @param Value HII Value to be converted.\r
1163\r
1164 @return None.\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 @retval 0 Value1 is greater than Value2\r
1218 @retval 0 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