]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Update comments in BaseExtractGuidedSectionLib library instance to say its used memor...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
b18e7050 4Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
7936fb6a 15#include "Setup.h"\r
16\r
17//\r
18// Global stack used to evaluate boolean expresions\r
19//\r
20EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
21EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
22EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
23\r
24EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
25EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
26EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
2573712e
LG
27UINTN mExpressionEvaluationStackOffset = 0;\r
28\r
29EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
30EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
31EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
32\r
33EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
34EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
35EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
7936fb6a 36\r
37//\r
38// Unicode collation protocol interface\r
39//\r
40EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
cbf73e50 41EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
7936fb6a 42\r
43/**\r
44 Grow size of the stack.\r
45\r
46 This is an internal function.\r
47\r
48 @param Stack On input: old stack; On output: new stack\r
49 @param StackPtr On input: old stack pointer; On output: new stack\r
50 pointer\r
51 @param StackEnd On input: old stack end; On output: new stack end\r
52\r
53 @retval EFI_SUCCESS Grow stack success.\r
54 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
55\r
56**/\r
57EFI_STATUS\r
58GrowStack (\r
59 IN OUT EFI_HII_VALUE **Stack,\r
60 IN OUT EFI_HII_VALUE **StackPtr,\r
61 IN OUT EFI_HII_VALUE **StackEnd\r
62 )\r
63{\r
64 UINTN Size;\r
65 EFI_HII_VALUE *NewStack;\r
66\r
67 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
68 if (*StackPtr != NULL) {\r
69 Size = Size + (*StackEnd - *Stack);\r
70 }\r
71\r
72 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
73 if (NewStack == NULL) {\r
74 return EFI_OUT_OF_RESOURCES;\r
75 }\r
76\r
77 if (*StackPtr != NULL) {\r
78 //\r
79 // Copy from Old Stack to the New Stack\r
80 //\r
81 CopyMem (\r
82 NewStack,\r
83 *Stack,\r
84 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
85 );\r
86\r
87 //\r
88 // Free The Old Stack\r
89 //\r
f4113e1f 90 FreePool (*Stack);\r
7936fb6a 91 }\r
92\r
93 //\r
94 // Make the Stack pointer point to the old data in the new stack\r
95 //\r
96 *StackPtr = NewStack + (*StackPtr - *Stack);\r
97 *Stack = NewStack;\r
98 *StackEnd = NewStack + Size;\r
99\r
100 return EFI_SUCCESS;\r
101}\r
102\r
103\r
104/**\r
105 Push an element onto the Boolean Stack.\r
106\r
107 @param Stack On input: old stack; On output: new stack\r
108 @param StackPtr On input: old stack pointer; On output: new stack\r
109 pointer\r
110 @param StackEnd On input: old stack end; On output: new stack end\r
111 @param Data Data to push.\r
112\r
113 @retval EFI_SUCCESS Push stack success.\r
114\r
115**/\r
116EFI_STATUS\r
117PushStack (\r
118 IN OUT EFI_HII_VALUE **Stack,\r
119 IN OUT EFI_HII_VALUE **StackPtr,\r
120 IN OUT EFI_HII_VALUE **StackEnd,\r
121 IN EFI_HII_VALUE *Data\r
122 )\r
123{\r
124 EFI_STATUS Status;\r
125\r
126 //\r
127 // Check for a stack overflow condition\r
128 //\r
129 if (*StackPtr >= *StackEnd) {\r
130 //\r
131 // Grow the stack\r
132 //\r
133 Status = GrowStack (Stack, StackPtr, StackEnd);\r
134 if (EFI_ERROR (Status)) {\r
135 return Status;\r
136 }\r
137 }\r
138\r
139 //\r
140 // Push the item onto the stack\r
141 //\r
142 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
901ba0e7
ED
143 if (Data->Type == EFI_IFR_TYPE_BUFFER) {\r
144 (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer);\r
145 ASSERT ((*StackPtr)->Buffer != NULL);\r
146 }\r
147 \r
7936fb6a 148 *StackPtr = *StackPtr + 1;\r
149\r
150 return EFI_SUCCESS;\r
151}\r
152\r
153\r
154/**\r
155 Pop an element from the stack.\r
156\r
2573712e
LG
157 @param Stack On input: old stack\r
158 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
7936fb6a 159 @param Data Data to pop.\r
160\r
161 @retval EFI_SUCCESS The value was popped onto the stack.\r
162 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
163\r
164**/\r
165EFI_STATUS\r
166PopStack (\r
2573712e 167 IN EFI_HII_VALUE *Stack,\r
7936fb6a 168 IN OUT EFI_HII_VALUE **StackPtr,\r
7936fb6a 169 OUT EFI_HII_VALUE *Data\r
170 )\r
171{\r
172 //\r
173 // Check for a stack underflow condition\r
174 //\r
2573712e 175 if (*StackPtr == Stack) {\r
7936fb6a 176 return EFI_ACCESS_DENIED;\r
177 }\r
178\r
179 //\r
180 // Pop the item off the stack\r
181 //\r
182 *StackPtr = *StackPtr - 1;\r
183 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
184 return EFI_SUCCESS;\r
185}\r
186\r
187\r
2573712e
LG
188/**\r
189 Reset stack pointer to begin of the stack.\r
190\r
191**/\r
192VOID\r
193ResetCurrentExpressionStack (\r
194 VOID\r
195 )\r
196{\r
197 mCurrentExpressionPointer = mCurrentExpressionStack;\r
198}\r
199\r
200\r
201/**\r
202 Push current expression onto the Stack\r
203\r
204 @param Pointer Pointer to current expression.\r
205\r
206 @retval EFI_SUCCESS The value was pushed onto the stack.\r
207 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
208\r
209**/\r
210EFI_STATUS\r
211PushCurrentExpression (\r
212 IN VOID *Pointer\r
213 )\r
214{\r
215 EFI_HII_VALUE Data;\r
216\r
217 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
218 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
219\r
220 return PushStack (\r
221 &mCurrentExpressionStack,\r
222 &mCurrentExpressionPointer,\r
223 &mCurrentExpressionEnd,\r
224 &Data\r
225 );\r
226}\r
227\r
228\r
229/**\r
230 Pop current expression from the Stack\r
231\r
232 @param Pointer Pointer to current expression to be pop.\r
233\r
234 @retval EFI_SUCCESS The value was pushed onto the stack.\r
235 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
236\r
237**/\r
238EFI_STATUS\r
239PopCurrentExpression (\r
240 OUT VOID **Pointer\r
241 )\r
242{\r
243 EFI_STATUS Status;\r
244 EFI_HII_VALUE Data;\r
245\r
246 Status = PopStack (\r
247 mCurrentExpressionStack,\r
248 &mCurrentExpressionPointer,\r
249 &Data\r
250 );\r
251\r
252 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
253\r
254 return Status;\r
255}\r
256\r
257/**\r
258 Reset stack pointer to begin of the stack.\r
259\r
260**/\r
261VOID\r
262ResetMapExpressionListStack (\r
263 VOID\r
264 )\r
265{\r
266 mMapExpressionListPointer = mMapExpressionListStack;\r
267}\r
268\r
269\r
270/**\r
271 Push the list of map expression onto the Stack\r
272\r
273 @param Pointer Pointer to the list of map expression to be pushed.\r
274\r
275 @retval EFI_SUCCESS The value was pushed onto the stack.\r
276 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
277\r
278**/\r
279EFI_STATUS\r
280PushMapExpressionList (\r
281 IN VOID *Pointer\r
282 )\r
283{\r
284 EFI_HII_VALUE Data;\r
285\r
286 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
287 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
288\r
289 return PushStack (\r
290 &mMapExpressionListStack,\r
291 &mMapExpressionListPointer,\r
292 &mMapExpressionListEnd,\r
293 &Data\r
294 );\r
295}\r
296\r
297\r
298/**\r
299 Pop the list of map expression from the Stack\r
300\r
301 @param Pointer Pointer to the list of map expression to be pop.\r
302\r
303 @retval EFI_SUCCESS The value was pushed onto the stack.\r
304 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
305\r
306**/\r
307EFI_STATUS\r
308PopMapExpressionList (\r
309 OUT VOID **Pointer\r
310 )\r
311{\r
312 EFI_STATUS Status;\r
313 EFI_HII_VALUE Data;\r
314\r
315 Status = PopStack (\r
316 mMapExpressionListStack,\r
317 &mMapExpressionListPointer,\r
318 &Data\r
319 );\r
320\r
321 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
322\r
323 return Status;\r
324}\r
325\r
7936fb6a 326/**\r
327 Reset stack pointer to begin of the stack.\r
328\r
329**/\r
330VOID\r
331ResetScopeStack (\r
332 VOID\r
333 )\r
334{\r
335 mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
336}\r
337\r
338\r
339/**\r
340 Push an Operand onto the Stack\r
341\r
342 @param Operand Operand to push.\r
343\r
344 @retval EFI_SUCCESS The value was pushed onto the stack.\r
345 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
346 stack.\r
347\r
348**/\r
349EFI_STATUS\r
350PushScope (\r
351 IN UINT8 Operand\r
352 )\r
353{\r
354 EFI_HII_VALUE Data;\r
355\r
356 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
357 Data.Value.u8 = Operand;\r
358\r
359 return PushStack (\r
360 &mOpCodeScopeStack,\r
361 &mOpCodeScopeStackPointer,\r
362 &mOpCodeScopeStackEnd,\r
363 &Data\r
364 );\r
365}\r
366\r
367\r
368/**\r
369 Pop an Operand from the Stack\r
370\r
371 @param Operand Operand to pop.\r
372\r
373 @retval EFI_SUCCESS The value was pushed onto the stack.\r
374 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
375 stack.\r
376\r
377**/\r
378EFI_STATUS\r
379PopScope (\r
380 OUT UINT8 *Operand\r
381 )\r
382{\r
383 EFI_STATUS Status;\r
384 EFI_HII_VALUE Data;\r
385\r
386 Status = PopStack (\r
2573712e 387 mOpCodeScopeStack,\r
7936fb6a 388 &mOpCodeScopeStackPointer,\r
7936fb6a 389 &Data\r
390 );\r
391\r
392 *Operand = Data.Value.u8;\r
393\r
394 return Status;\r
395}\r
396\r
397\r
7936fb6a 398/**\r
399 Push an Expression value onto the Stack\r
400\r
401 @param Value Expression value to push.\r
402\r
403 @retval EFI_SUCCESS The value was pushed onto the stack.\r
404 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
405 stack.\r
406\r
407**/\r
408EFI_STATUS\r
409PushExpression (\r
410 IN EFI_HII_VALUE *Value\r
411 )\r
412{\r
413 return PushStack (\r
414 &mExpressionEvaluationStack,\r
415 &mExpressionEvaluationStackPointer,\r
416 &mExpressionEvaluationStackEnd,\r
417 Value\r
418 );\r
419}\r
420\r
421\r
422/**\r
423 Pop an Expression value from the stack.\r
424\r
425 @param Value Expression value to pop.\r
426\r
427 @retval EFI_SUCCESS The value was popped onto the stack.\r
428 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
429\r
430**/\r
431EFI_STATUS\r
432PopExpression (\r
433 OUT EFI_HII_VALUE *Value\r
434 )\r
435{\r
436 return PopStack (\r
2573712e 437 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
7936fb6a 438 &mExpressionEvaluationStackPointer,\r
7936fb6a 439 Value\r
440 );\r
441}\r
442\r
2573712e
LG
443/**\r
444 Get current stack offset from stack start.\r
445\r
446 @return Stack offset to stack start.\r
447**/\r
448UINTN\r
449SaveExpressionEvaluationStackOffset (\r
450 )\r
451{\r
452 UINTN TempStackOffset;\r
453 TempStackOffset = mExpressionEvaluationStackOffset;\r
454 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
455 return TempStackOffset;\r
456}\r
457\r
458/**\r
459 Restore stack offset based on input stack offset\r
460\r
461 @param StackOffset Offset to stack start.\r
462\r
463**/\r
464VOID\r
465RestoreExpressionEvaluationStackOffset (\r
466 UINTN StackOffset\r
467 )\r
468{\r
469 mExpressionEvaluationStackOffset = StackOffset;\r
470}\r
7936fb6a 471\r
472/**\r
473 Get Form given its FormId.\r
474\r
475 @param FormSet The formset which contains this form.\r
476 @param FormId Id of this form.\r
477\r
478 @retval Pointer The form.\r
479 @retval NULL Specified Form is not found in the formset.\r
480\r
481**/\r
482FORM_BROWSER_FORM *\r
483IdToForm (\r
484 IN FORM_BROWSER_FORMSET *FormSet,\r
485 IN UINT16 FormId\r
486)\r
487{\r
488 LIST_ENTRY *Link;\r
489 FORM_BROWSER_FORM *Form;\r
490\r
491 Link = GetFirstNode (&FormSet->FormListHead);\r
492 while (!IsNull (&FormSet->FormListHead, Link)) {\r
493 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
494\r
495 if (Form->FormId == FormId) {\r
496 return Form;\r
497 }\r
498\r
499 Link = GetNextNode (&FormSet->FormListHead, Link);\r
500 }\r
501\r
502 return NULL;\r
503}\r
504\r
505\r
506/**\r
507 Search a Question in Form scope using its QuestionId.\r
508\r
509 @param Form The form which contains this Question.\r
510 @param QuestionId Id of this Question.\r
511\r
512 @retval Pointer The Question.\r
513 @retval NULL Specified Question not found in the form.\r
514\r
515**/\r
516FORM_BROWSER_STATEMENT *\r
517IdToQuestion2 (\r
518 IN FORM_BROWSER_FORM *Form,\r
519 IN UINT16 QuestionId\r
520 )\r
521{\r
522 LIST_ENTRY *Link;\r
523 FORM_BROWSER_STATEMENT *Question;\r
524\r
525 if (QuestionId == 0) {\r
526 //\r
527 // The value of zero is reserved\r
528 //\r
529 return NULL;\r
530 }\r
531\r
532 Link = GetFirstNode (&Form->StatementListHead);\r
533 while (!IsNull (&Form->StatementListHead, Link)) {\r
534 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
535\r
536 if (Question->QuestionId == QuestionId) {\r
537 return Question;\r
538 }\r
539\r
540 Link = GetNextNode (&Form->StatementListHead, Link);\r
541 }\r
542\r
543 return NULL;\r
544}\r
545\r
546\r
547/**\r
548 Search a Question in Formset scope using its QuestionId.\r
549\r
550 @param FormSet The formset which contains this form.\r
551 @param Form The form which contains this Question.\r
552 @param QuestionId Id of this Question.\r
553\r
554 @retval Pointer The Question.\r
555 @retval NULL Specified Question not found in the form.\r
556\r
557**/\r
558FORM_BROWSER_STATEMENT *\r
559IdToQuestion (\r
560 IN FORM_BROWSER_FORMSET *FormSet,\r
561 IN FORM_BROWSER_FORM *Form,\r
562 IN UINT16 QuestionId\r
563 )\r
564{\r
565 LIST_ENTRY *Link;\r
566 FORM_BROWSER_STATEMENT *Question;\r
567\r
568 //\r
569 // Search in the form scope first\r
570 //\r
571 Question = IdToQuestion2 (Form, QuestionId);\r
572 if (Question != NULL) {\r
573 return Question;\r
574 }\r
575\r
576 //\r
577 // Search in the formset scope\r
578 //\r
579 Link = GetFirstNode (&FormSet->FormListHead);\r
580 while (!IsNull (&FormSet->FormListHead, Link)) {\r
581 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
582\r
583 Question = IdToQuestion2 (Form, QuestionId);\r
584 if (Question != NULL) {\r
8d00a0f1 585 //\r
586 // EFI variable storage may be updated by Callback() asynchronous,\r
587 // to keep synchronous, always reload the Question Value.\r
588 //\r
589 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
590 GetQuestionValue (FormSet, Form, Question, FALSE);\r
591 }\r
592\r
7936fb6a 593 return Question;\r
594 }\r
595\r
596 Link = GetNextNode (&FormSet->FormListHead, Link);\r
597 }\r
598\r
599 return NULL;\r
600}\r
601\r
602\r
603/**\r
604 Get Expression given its RuleId.\r
605\r
606 @param Form The form which contains this Expression.\r
607 @param RuleId Id of this Expression.\r
608\r
609 @retval Pointer The Expression.\r
610 @retval NULL Specified Expression not found in the form.\r
611\r
612**/\r
613FORM_EXPRESSION *\r
614RuleIdToExpression (\r
615 IN FORM_BROWSER_FORM *Form,\r
616 IN UINT8 RuleId\r
617 )\r
618{\r
619 LIST_ENTRY *Link;\r
620 FORM_EXPRESSION *Expression;\r
621\r
622 Link = GetFirstNode (&Form->ExpressionListHead);\r
623 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
624 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
625\r
626 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
627 return Expression;\r
628 }\r
629\r
630 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
631 }\r
632\r
633 return NULL;\r
634}\r
635\r
636\r
637/**\r
638 Locate the Unicode Collation Protocol interface for later use.\r
639\r
640 @retval EFI_SUCCESS Protocol interface initialize success.\r
641 @retval Other Protocol interface initialize failed.\r
642\r
643**/\r
644EFI_STATUS\r
645InitializeUnicodeCollationProtocol (\r
646 VOID\r
647 )\r
648{\r
649 EFI_STATUS Status;\r
650\r
651 if (mUnicodeCollation != NULL) {\r
652 return EFI_SUCCESS;\r
653 }\r
654\r
655 //\r
656 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
657 // instances first and then select one which support English language.\r
658 // Current implementation just pick the first instance.\r
659 //\r
660 Status = gBS->LocateProtocol (\r
661 &gEfiUnicodeCollation2ProtocolGuid,\r
662 NULL,\r
663 (VOID **) &mUnicodeCollation\r
664 );\r
665 return Status;\r
666}\r
667\r
668/**\r
669 Convert the input Unicode character to upper.\r
670\r
671 @param String Th Unicode character to be converted.\r
672\r
673**/\r
674VOID\r
675IfrStrToUpper (\r
8b0fc5c1 676 IN CHAR16 *String\r
7936fb6a 677 )\r
678{\r
679 while (*String != 0) {\r
680 if ((*String >= 'a') && (*String <= 'z')) {\r
681 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
682 }\r
683 String++;\r
684 }\r
685}\r
686\r
687\r
688/**\r
689 Evaluate opcode EFI_IFR_TO_STRING.\r
690\r
691 @param FormSet Formset which contains this opcode.\r
692 @param Format String format in EFI_IFR_TO_STRING.\r
693 @param Result Evaluation result for this opcode.\r
694\r
695 @retval EFI_SUCCESS Opcode evaluation success.\r
696 @retval Other Opcode evaluation failed.\r
697\r
698**/\r
699EFI_STATUS\r
700IfrToString (\r
701 IN FORM_BROWSER_FORMSET *FormSet,\r
702 IN UINT8 Format,\r
703 OUT EFI_HII_VALUE *Result\r
704 )\r
705{\r
706 EFI_STATUS Status;\r
707 EFI_HII_VALUE Value;\r
708 CHAR16 *String;\r
709 CHAR16 *PrintFormat;\r
710 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
901ba0e7 711 UINT8 *TmpBuf;\r
7936fb6a 712 UINTN BufferSize;\r
713\r
714 Status = PopExpression (&Value);\r
715 if (EFI_ERROR (Status)) {\r
716 return Status;\r
717 }\r
718\r
719 switch (Value.Type) {\r
720 case EFI_IFR_TYPE_NUM_SIZE_8:\r
721 case EFI_IFR_TYPE_NUM_SIZE_16:\r
722 case EFI_IFR_TYPE_NUM_SIZE_32:\r
723 case EFI_IFR_TYPE_NUM_SIZE_64:\r
724 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
725 switch (Format) {\r
726 case EFI_IFR_STRING_UNSIGNED_DEC:\r
727 case EFI_IFR_STRING_SIGNED_DEC:\r
728 PrintFormat = L"%ld";\r
729 break;\r
730\r
731 case EFI_IFR_STRING_LOWERCASE_HEX:\r
732 PrintFormat = L"%lx";\r
733 break;\r
734\r
735 case EFI_IFR_STRING_UPPERCASE_HEX:\r
736 PrintFormat = L"%lX";\r
737 break;\r
738\r
739 default:\r
740 return EFI_UNSUPPORTED;\r
741 }\r
742 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
743 String = Buffer;\r
744 break;\r
745\r
746 case EFI_IFR_TYPE_STRING:\r
747 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
748 return EFI_SUCCESS;\r
749\r
750 case EFI_IFR_TYPE_BOOLEAN:\r
751 String = (Value.Value.b) ? L"True" : L"False";\r
752 break;\r
901ba0e7
ED
753 \r
754 case EFI_IFR_TYPE_BUFFER:\r
755 //\r
756 // + 3 is base on the unicode format, the length may be odd number, \r
757 // so need 1 byte to align, also need 2 bytes for L'\0'.\r
758 //\r
759 TmpBuf = AllocateZeroPool (Value.BufferLen + 3);\r
760 if (Format == EFI_IFR_STRING_ASCII) {\r
761 CopyMem (TmpBuf, Value.Buffer, Value.BufferLen);\r
762 PrintFormat = L"%a"; \r
763 } else {\r
764 // Format == EFI_IFR_STRING_UNICODE\r
765 CopyMem (TmpBuf, Value.Buffer, Value.BufferLen * sizeof (CHAR16));\r
766 PrintFormat = L"%s"; \r
767 }\r
768 UnicodeSPrint (Buffer, MAXIMUM_VALUE_CHARACTERS, PrintFormat, Value.Buffer); \r
769 String = Buffer; \r
770 FreePool (TmpBuf);\r
771 FreePool (Value.Buffer);\r
772 break;\r
773 \r
7936fb6a 774 default:\r
775 return EFI_UNSUPPORTED;\r
776 }\r
777\r
778 Result->Type = EFI_IFR_TYPE_STRING;\r
779 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
780 return EFI_SUCCESS;\r
781}\r
782\r
783\r
784/**\r
785 Evaluate opcode EFI_IFR_TO_UINT.\r
786\r
787 @param FormSet Formset which contains this opcode.\r
788 @param Result Evaluation result for this opcode.\r
789\r
790 @retval EFI_SUCCESS Opcode evaluation success.\r
791 @retval Other Opcode evaluation failed.\r
792\r
793**/\r
794EFI_STATUS\r
795IfrToUint (\r
796 IN FORM_BROWSER_FORMSET *FormSet,\r
797 OUT EFI_HII_VALUE *Result\r
798 )\r
799{\r
800 EFI_STATUS Status;\r
801 EFI_HII_VALUE Value;\r
802 CHAR16 *String;\r
803 CHAR16 *StringPtr;\r
7936fb6a 804\r
805 Status = PopExpression (&Value);\r
806 if (EFI_ERROR (Status)) {\r
807 return Status;\r
808 }\r
809\r
901ba0e7 810 if (Value.Type >= EFI_IFR_TYPE_OTHER && Value.Type != EFI_IFR_TYPE_BUFFER) {\r
7936fb6a 811 return EFI_UNSUPPORTED;\r
812 }\r
813\r
814 Status = EFI_SUCCESS;\r
815 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
816 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
817 if (String == NULL) {\r
818 return EFI_NOT_FOUND;\r
819 }\r
8b0fc5c1 820\r
7936fb6a 821 IfrStrToUpper (String);\r
822 StringPtr = StrStr (String, L"0X");\r
823 if (StringPtr != NULL) {\r
824 //\r
825 // Hex string\r
826 //\r
ac7e320c 827 Result->Value.u64 = StrHexToUint64 (String);\r
7936fb6a 828 } else {\r
829 //\r
ac7e320c 830 // decimal string\r
7936fb6a 831 //\r
ac7e320c 832 Result->Value.u64 = StrDecimalToUint64 (String);\r
7936fb6a 833 }\r
f4113e1f 834 FreePool (String);\r
901ba0e7
ED
835 } else if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
836 if (Value.BufferLen > 8) {\r
837 FreePool (Value.Buffer);\r
838 return EFI_UNSUPPORTED;\r
839 }\r
840 Result->Value.u64 = *(UINT64*) Value.Buffer;\r
841 FreePool (Value.Buffer);\r
7936fb6a 842 } else {\r
843 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
844 }\r
845\r
846 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
847 return Status;\r
848}\r
849\r
850\r
851/**\r
852 Evaluate opcode EFI_IFR_CATENATE.\r
853\r
854 @param FormSet Formset which contains this opcode.\r
855 @param Result Evaluation result for this opcode.\r
856\r
857 @retval EFI_SUCCESS Opcode evaluation success.\r
858 @retval Other Opcode evaluation failed.\r
859\r
860**/\r
861EFI_STATUS\r
862IfrCatenate (\r
863 IN FORM_BROWSER_FORMSET *FormSet,\r
864 OUT EFI_HII_VALUE *Result\r
865 )\r
866{\r
867 EFI_STATUS Status;\r
901ba0e7 868 EFI_HII_VALUE Value[2];\r
7936fb6a 869 CHAR16 *String[2];\r
870 UINTN Index;\r
871 CHAR16 *StringPtr;\r
872 UINTN Size;\r
873\r
874 //\r
875 // String[0] - The second string\r
876 // String[1] - The first string\r
877 //\r
878 String[0] = NULL;\r
879 String[1] = NULL;\r
880 StringPtr = NULL;\r
881 Status = EFI_SUCCESS;\r
901ba0e7 882 ZeroMem (Value, sizeof (Value));\r
7936fb6a 883\r
884 for (Index = 0; Index < 2; Index++) {\r
901ba0e7 885 Status = PopExpression (&Value[Index]);\r
7936fb6a 886 if (EFI_ERROR (Status)) {\r
887 goto Done;\r
888 }\r
889\r
901ba0e7 890 if (Value[Index].Type != EFI_IFR_TYPE_STRING && Value[Index].Type != EFI_IFR_TYPE_BUFFER) {\r
7936fb6a 891 Status = EFI_UNSUPPORTED;\r
892 goto Done;\r
893 }\r
894\r
901ba0e7
ED
895 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
896 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
897 if (String[Index] == NULL) {\r
898 Status = EFI_NOT_FOUND;\r
899 goto Done;\r
900 }\r
7936fb6a 901 }\r
902 }\r
903\r
901ba0e7
ED
904 if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
905 Size = StrSize (String[0]);\r
906 StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
907 ASSERT (StringPtr != NULL);\r
908 StrCpy (StringPtr, String[1]);\r
909 StrCat (StringPtr, String[0]);\r
7936fb6a 910\r
901ba0e7
ED
911 Result->Type = EFI_IFR_TYPE_STRING;\r
912 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
913 } else {\r
914 Result->Type = EFI_IFR_TYPE_BUFFER;\r
915 Result->BufferLen = (UINT16) (Value[0].BufferLen + Value[1].BufferLen);\r
916\r
917 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
918 ASSERT (Result->Buffer != NULL);\r
7936fb6a 919\r
901ba0e7
ED
920 CopyMem (Result->Buffer, Value[0].Buffer, Value[0].BufferLen);\r
921 CopyMem (&Result->Buffer[Value[0].BufferLen], Value[1].Buffer, Value[1].BufferLen);\r
922 }\r
7936fb6a 923Done:\r
901ba0e7
ED
924 if (Value[0].Buffer != NULL) {\r
925 FreePool (Value[0].Buffer);\r
926 }\r
927 if (Value[1].Buffer != NULL) {\r
928 FreePool (Value[1].Buffer);\r
929 }\r
676df92c 930 if (String[0] != NULL) {\r
931 FreePool (String[0]);\r
932 }\r
933 if (String[1] != NULL) {\r
934 FreePool (String[1]);\r
8b0fc5c1 935 }\r
676df92c 936 if (StringPtr != NULL) {\r
937 FreePool (StringPtr);\r
938 }\r
7936fb6a 939\r
940 return Status;\r
941}\r
942\r
943\r
944/**\r
945 Evaluate opcode EFI_IFR_MATCH.\r
946\r
947 @param FormSet Formset which contains this opcode.\r
948 @param Result Evaluation result for this opcode.\r
949\r
950 @retval EFI_SUCCESS Opcode evaluation success.\r
951 @retval Other Opcode evaluation failed.\r
952\r
953**/\r
954EFI_STATUS\r
955IfrMatch (\r
956 IN FORM_BROWSER_FORMSET *FormSet,\r
957 OUT EFI_HII_VALUE *Result\r
958 )\r
959{\r
960 EFI_STATUS Status;\r
961 EFI_HII_VALUE Value;\r
962 CHAR16 *String[2];\r
963 UINTN Index;\r
964\r
965 //\r
966 // String[0] - The string to search\r
967 // String[1] - pattern\r
968 //\r
969 String[0] = NULL;\r
970 String[1] = NULL;\r
971 Status = EFI_SUCCESS;\r
972 for (Index = 0; Index < 2; Index++) {\r
973 Status = PopExpression (&Value);\r
974 if (EFI_ERROR (Status)) {\r
975 goto Done;\r
976 }\r
977\r
978 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
979 Status = EFI_UNSUPPORTED;\r
980 goto Done;\r
981 }\r
982\r
983 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
bc166db3 984 if (String [Index] == NULL) {\r
7936fb6a 985 Status = EFI_NOT_FOUND;\r
986 goto Done;\r
987 }\r
988 }\r
989\r
990 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
991 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
992\r
993Done:\r
676df92c 994 if (String[0] != NULL) {\r
995 FreePool (String[0]);\r
996 }\r
997 if (String[1] != NULL) {\r
998 FreePool (String[1]);\r
8b0fc5c1 999 }\r
7936fb6a 1000\r
1001 return Status;\r
1002}\r
1003\r
1004\r
1005/**\r
1006 Evaluate opcode EFI_IFR_FIND.\r
1007\r
1008 @param FormSet Formset which contains this opcode.\r
1009 @param Format Case sensitive or insensitive.\r
1010 @param Result Evaluation result for this opcode.\r
1011\r
1012 @retval EFI_SUCCESS Opcode evaluation success.\r
1013 @retval Other Opcode evaluation failed.\r
1014\r
1015**/\r
1016EFI_STATUS\r
1017IfrFind (\r
1018 IN FORM_BROWSER_FORMSET *FormSet,\r
1019 IN UINT8 Format,\r
1020 OUT EFI_HII_VALUE *Result\r
1021 )\r
1022{\r
1023 EFI_STATUS Status;\r
1024 EFI_HII_VALUE Value;\r
1025 CHAR16 *String[2];\r
1026 UINTN Base;\r
1027 CHAR16 *StringPtr;\r
1028 UINTN Index;\r
1029\r
1030 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
1031 return EFI_UNSUPPORTED;\r
1032 }\r
1033\r
1034 Status = PopExpression (&Value);\r
1035 if (EFI_ERROR (Status)) {\r
1036 return Status;\r
1037 }\r
1038 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1039 return EFI_UNSUPPORTED;\r
1040 }\r
1041 Base = (UINTN) Value.Value.u64;\r
1042\r
1043 //\r
1044 // String[0] - sub-string\r
1045 // String[1] - The string to search\r
1046 //\r
1047 String[0] = NULL;\r
1048 String[1] = NULL;\r
1049 for (Index = 0; Index < 2; Index++) {\r
1050 Status = PopExpression (&Value);\r
1051 if (EFI_ERROR (Status)) {\r
1052 goto Done;\r
1053 }\r
1054\r
1055 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1056 Status = EFI_UNSUPPORTED;\r
1057 goto Done;\r
1058 }\r
1059\r
1060 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 1061 if (String[Index] == NULL) {\r
7936fb6a 1062 Status = EFI_NOT_FOUND;\r
1063 goto Done;\r
1064 }\r
1065\r
1066 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
1067 //\r
1068 // Case insensitive, convert both string to upper case\r
1069 //\r
1070 IfrStrToUpper (String[Index]);\r
1071 }\r
1072 }\r
1073\r
1074 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1075 if (Base >= StrLen (String[1])) {\r
1076 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
1077 } else {\r
1078 StringPtr = StrStr (String[1] + Base, String[0]);\r
1079 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
1080 }\r
1081\r
1082Done:\r
676df92c 1083 if (String[0] != NULL) {\r
1084 FreePool (String[0]);\r
1085 }\r
1086 if (String[1] != NULL) {\r
1087 FreePool (String[1]);\r
8b0fc5c1 1088 }\r
7936fb6a 1089\r
1090 return Status;\r
1091}\r
1092\r
1093\r
1094/**\r
1095 Evaluate opcode EFI_IFR_MID.\r
1096\r
1097 @param FormSet Formset which contains this opcode.\r
1098 @param Result Evaluation result for this opcode.\r
1099\r
1100 @retval EFI_SUCCESS Opcode evaluation success.\r
1101 @retval Other Opcode evaluation failed.\r
1102\r
1103**/\r
1104EFI_STATUS\r
1105IfrMid (\r
1106 IN FORM_BROWSER_FORMSET *FormSet,\r
1107 OUT EFI_HII_VALUE *Result\r
1108 )\r
1109{\r
1110 EFI_STATUS Status;\r
1111 EFI_HII_VALUE Value;\r
1112 CHAR16 *String;\r
1113 UINTN Base;\r
1114 UINTN Length;\r
1115 CHAR16 *SubString;\r
901ba0e7
ED
1116 UINT8 *Buffer;\r
1117 UINT16 BufferLen;\r
7936fb6a 1118\r
1119 Status = PopExpression (&Value);\r
1120 if (EFI_ERROR (Status)) {\r
1121 return Status;\r
1122 }\r
1123 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1124 return EFI_UNSUPPORTED;\r
1125 }\r
1126 Length = (UINTN) Value.Value.u64;\r
1127\r
1128 Status = PopExpression (&Value);\r
1129 if (EFI_ERROR (Status)) {\r
1130 return Status;\r
1131 }\r
1132 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1133 return EFI_UNSUPPORTED;\r
1134 }\r
1135 Base = (UINTN) Value.Value.u64;\r
1136\r
1137 Status = PopExpression (&Value);\r
1138 if (EFI_ERROR (Status)) {\r
1139 return Status;\r
1140 }\r
901ba0e7 1141 if (Value.Type != EFI_IFR_TYPE_STRING && Value.Type != EFI_IFR_TYPE_BUFFER) {\r
7936fb6a 1142 return EFI_UNSUPPORTED;\r
1143 }\r
901ba0e7
ED
1144 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
1145 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1146 if (String == NULL) {\r
1147 return EFI_NOT_FOUND;\r
1148 }\r
7936fb6a 1149\r
901ba0e7
ED
1150 if (Length == 0 || Base >= StrLen (String)) {\r
1151 SubString = gEmptyString;\r
1152 } else {\r
1153 SubString = String + Base;\r
1154 if ((Base + Length) < StrLen (String)) {\r
1155 SubString[Length] = L'\0';\r
1156 }\r
7936fb6a 1157 }\r
7936fb6a 1158\r
901ba0e7
ED
1159 Result->Type = EFI_IFR_TYPE_STRING;\r
1160 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
7936fb6a 1161\r
901ba0e7
ED
1162 FreePool (String);\r
1163 } else {\r
1164 Buffer = Value.Buffer;\r
1165 BufferLen = Value.BufferLen;\r
1166 \r
1167 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1168 if (Length == 0 || Base >= BufferLen) {\r
1169 Result->BufferLen = 0;\r
1170 Result->Buffer = NULL;\r
1171 } else {\r
1172 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length); \r
1173 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1174 ASSERT (Result->Buffer != NULL);\r
1175 CopyMem (Result->Buffer, &Value.Buffer[Base], Result->BufferLen);\r
1176 }\r
7936fb6a 1177\r
901ba0e7
ED
1178 FreePool (Value.Buffer);\r
1179 }\r
1180 \r
7936fb6a 1181 return Status;\r
1182}\r
1183\r
1184\r
1185/**\r
1186 Evaluate opcode EFI_IFR_TOKEN.\r
1187\r
1188 @param FormSet Formset which contains this opcode.\r
1189 @param Result Evaluation result for this opcode.\r
1190\r
1191 @retval EFI_SUCCESS Opcode evaluation success.\r
1192 @retval Other Opcode evaluation failed.\r
1193\r
1194**/\r
1195EFI_STATUS\r
1196IfrToken (\r
1197 IN FORM_BROWSER_FORMSET *FormSet,\r
1198 OUT EFI_HII_VALUE *Result\r
1199 )\r
1200{\r
1201 EFI_STATUS Status;\r
1202 EFI_HII_VALUE Value;\r
1203 CHAR16 *String[2];\r
1204 UINTN Count;\r
1205 CHAR16 *Delimiter;\r
1206 CHAR16 *SubString;\r
1207 CHAR16 *StringPtr;\r
1208 UINTN Index;\r
1209\r
1210 Status = PopExpression (&Value);\r
1211 if (EFI_ERROR (Status)) {\r
1212 return Status;\r
1213 }\r
1214 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1215 return EFI_UNSUPPORTED;\r
1216 }\r
1217 Count = (UINTN) Value.Value.u64;\r
1218\r
1219 //\r
1220 // String[0] - Delimiter\r
1221 // String[1] - The string to search\r
1222 //\r
1223 String[0] = NULL;\r
1224 String[1] = NULL;\r
1225 for (Index = 0; Index < 2; Index++) {\r
1226 Status = PopExpression (&Value);\r
1227 if (EFI_ERROR (Status)) {\r
1228 goto Done;\r
1229 }\r
1230\r
1231 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1232 Status = EFI_UNSUPPORTED;\r
1233 goto Done;\r
1234 }\r
1235\r
1236 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 1237 if (String[Index] == NULL) {\r
7936fb6a 1238 Status = EFI_NOT_FOUND;\r
1239 goto Done;\r
1240 }\r
1241 }\r
1242\r
1243 Delimiter = String[0];\r
1244 SubString = String[1];\r
1245 while (Count > 0) {\r
1246 SubString = StrStr (SubString, Delimiter);\r
1247 if (SubString != NULL) {\r
1248 //\r
1249 // Skip over the delimiter\r
1250 //\r
1251 SubString = SubString + StrLen (Delimiter);\r
1252 } else {\r
1253 break;\r
1254 }\r
1255 Count--;\r
1256 }\r
1257\r
1258 if (SubString == NULL) {\r
1259 //\r
1260 // nth delimited sub-string not found, push an empty string\r
1261 //\r
1262 SubString = gEmptyString;\r
1263 } else {\r
1264 //\r
1265 // Put a NULL terminator for nth delimited sub-string\r
1266 //\r
1267 StringPtr = StrStr (SubString, Delimiter);\r
1268 if (StringPtr != NULL) {\r
1269 *StringPtr = L'\0';\r
1270 }\r
1271 }\r
1272\r
1273 Result->Type = EFI_IFR_TYPE_STRING;\r
1274 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1275\r
1276Done:\r
676df92c 1277 if (String[0] != NULL) {\r
1278 FreePool (String[0]);\r
1279 }\r
1280 if (String[1] != NULL) {\r
1281 FreePool (String[1]);\r
8b0fc5c1 1282 }\r
7936fb6a 1283\r
1284 return Status;\r
1285}\r
1286\r
1287\r
1288/**\r
1289 Evaluate opcode EFI_IFR_SPAN.\r
1290\r
1291 @param FormSet Formset which contains this opcode.\r
1292 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1293 @param Result Evaluation result for this opcode.\r
1294\r
1295 @retval EFI_SUCCESS Opcode evaluation success.\r
1296 @retval Other Opcode evaluation failed.\r
1297\r
1298**/\r
1299EFI_STATUS\r
1300IfrSpan (\r
1301 IN FORM_BROWSER_FORMSET *FormSet,\r
1302 IN UINT8 Flags,\r
1303 OUT EFI_HII_VALUE *Result\r
1304 )\r
1305{\r
1306 EFI_STATUS Status;\r
1307 EFI_HII_VALUE Value;\r
1308 CHAR16 *String[2];\r
1309 CHAR16 *Charset;\r
1310 UINTN Base;\r
1311 UINTN Index;\r
1312 CHAR16 *StringPtr;\r
1313 BOOLEAN Found;\r
1314\r
1315 Status = PopExpression (&Value);\r
1316 if (EFI_ERROR (Status)) {\r
1317 return Status;\r
1318 }\r
1319 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1320 return EFI_UNSUPPORTED;\r
1321 }\r
1322 Base = (UINTN) Value.Value.u64;\r
1323\r
1324 //\r
1325 // String[0] - Charset\r
1326 // String[1] - The string to search\r
1327 //\r
1328 String[0] = NULL;\r
1329 String[1] = NULL;\r
1330 for (Index = 0; Index < 2; Index++) {\r
1331 Status = PopExpression (&Value);\r
1332 if (EFI_ERROR (Status)) {\r
1333 goto Done;\r
1334 }\r
1335\r
1336 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1337 Status = EFI_UNSUPPORTED;\r
1338 goto Done;\r
1339 }\r
1340\r
1341 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
bc166db3 1342 if (String [Index] == NULL) {\r
7936fb6a 1343 Status = EFI_NOT_FOUND;\r
1344 goto Done;\r
1345 }\r
1346 }\r
1347\r
1348 if (Base >= StrLen (String[1])) {\r
1349 Status = EFI_UNSUPPORTED;\r
1350 goto Done;\r
1351 }\r
1352\r
1353 Found = FALSE;\r
1354 StringPtr = String[1] + Base;\r
1355 Charset = String[0];\r
1356 while (*StringPtr != 0 && !Found) {\r
1357 Index = 0;\r
1358 while (Charset[Index] != 0) {\r
1359 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
1360 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1361 Found = TRUE;\r
1362 break;\r
1363 }\r
1364 } else {\r
1365 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1366 Found = TRUE;\r
1367 break;\r
1368 }\r
1369 }\r
1370 //\r
1371 // Skip characters pair representing low-end of a range and high-end of a range\r
1372 //\r
1373 Index += 2;\r
1374 }\r
1375\r
1376 if (!Found) {\r
1377 StringPtr++;\r
1378 }\r
1379 }\r
1380\r
1381 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1382 Result->Value.u64 = StringPtr - String[1];\r
1383\r
1384Done:\r
676df92c 1385 if (String[0] != NULL) {\r
1386 FreePool (String[0]);\r
1387 }\r
1388 if (String[1] != NULL) {\r
1389 FreePool (String[1]);\r
8b0fc5c1 1390 }\r
7936fb6a 1391\r
1392 return Status;\r
1393}\r
1394\r
1395\r
1396/**\r
1397 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1398\r
1399 @param Value HII Value to be converted.\r
1400\r
1401**/\r
1402VOID\r
1403ExtendValueToU64 (\r
1404 IN EFI_HII_VALUE *Value\r
1405 )\r
1406{\r
1407 UINT64 Temp;\r
1408\r
1409 Temp = 0;\r
1410 switch (Value->Type) {\r
1411 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1412 Temp = Value->Value.u8;\r
1413 break;\r
1414\r
1415 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1416 Temp = Value->Value.u16;\r
1417 break;\r
1418\r
1419 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1420 Temp = Value->Value.u32;\r
1421 break;\r
1422\r
1423 case EFI_IFR_TYPE_BOOLEAN:\r
1424 Temp = Value->Value.b;\r
1425 break;\r
1426\r
1427 case EFI_IFR_TYPE_TIME:\r
1428 Temp = Value->Value.u32 & 0xffffff;\r
1429 break;\r
1430\r
1431 case EFI_IFR_TYPE_DATE:\r
1432 Temp = Value->Value.u32;\r
1433 break;\r
1434\r
1435 default:\r
1436 return;\r
1437 }\r
1438\r
1439 Value->Value.u64 = Temp;\r
1440}\r
1441\r
1442\r
1443/**\r
1444 Compare two Hii value.\r
1445\r
1446 @param Value1 Expression value to compare on left-hand.\r
1447 @param Value2 Expression value to compare on right-hand.\r
1448 @param HiiHandle Only required for string compare.\r
1449\r
2573712e
LG
1450 @retval EFI_INVALID_PARAMETER Could not perform compare on two values.\r
1451 @retval 0 Two operators equal.\r
7936fb6a 1452 @return Positive value if Value1 is greater than Value2.\r
1453 @retval Negative value if Value1 is less than Value2.\r
1454\r
1455**/\r
1456INTN\r
1457CompareHiiValue (\r
1458 IN EFI_HII_VALUE *Value1,\r
1459 IN EFI_HII_VALUE *Value2,\r
1460 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
1461 )\r
1462{\r
1463 INTN Result;\r
1464 INT64 Temp64;\r
1465 CHAR16 *Str1;\r
1466 CHAR16 *Str2;\r
901ba0e7 1467 UINTN Len;\r
7936fb6a 1468\r
1469 if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
901ba0e7
ED
1470 if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {\r
1471 return EFI_INVALID_PARAMETER;\r
1472 }\r
7936fb6a 1473 }\r
1474\r
1475 if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
1476 if (Value1->Type != Value2->Type) {\r
1477 //\r
1478 // Both Operator should be type of String\r
1479 //\r
1480 return EFI_INVALID_PARAMETER;\r
1481 }\r
1482\r
1483 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
1484 //\r
1485 // StringId 0 is reserved\r
1486 //\r
1487 return EFI_INVALID_PARAMETER;\r
1488 }\r
1489\r
1490 if (Value1->Value.string == Value2->Value.string) {\r
1491 return 0;\r
1492 }\r
1493\r
1494 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
1495 if (Str1 == NULL) {\r
1496 //\r
1497 // String not found\r
1498 //\r
1499 return EFI_INVALID_PARAMETER;\r
1500 }\r
1501\r
1502 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
1503 if (Str2 == NULL) {\r
f4113e1f 1504 FreePool (Str1);\r
7936fb6a 1505 return EFI_INVALID_PARAMETER;\r
1506 }\r
1507\r
1508 Result = StrCmp (Str1, Str2);\r
1509\r
f4113e1f 1510 FreePool (Str1);\r
1511 FreePool (Str2);\r
7936fb6a 1512\r
1513 return Result;\r
1514 }\r
1515\r
901ba0e7
ED
1516 if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) {\r
1517 if (Value1->Type != Value2->Type) {\r
1518 //\r
1519 // Both Operator should be type of Buffer.\r
1520 //\r
1521 return EFI_INVALID_PARAMETER;\r
1522 }\r
1523 Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;\r
1524 Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);\r
1525 if ((Result == 0) && (Value1->BufferLen != Value2->BufferLen))\r
1526 {\r
1527 //\r
1528 // In this case, means base on samll number buffer, the data is same\r
1529 // So which value has more data, which value is bigger.\r
1530 //\r
1531 Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1;\r
1532 }\r
1533 return Result;\r
1534 } \r
1535\r
7936fb6a 1536 //\r
1537 // Take remain types(integer, boolean, date/time) as integer\r
1538 //\r
1539 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
1540 if (Temp64 > 0) {\r
1541 Result = 1;\r
1542 } else if (Temp64 < 0) {\r
1543 Result = -1;\r
1544 } else {\r
1545 Result = 0;\r
1546 }\r
1547\r
1548 return Result;\r
1549}\r
1550\r
cbf73e50 1551/**\r
1552 Check if current user has the privilege specified by the permissions GUID.\r
1553\r
1554 @param[in] Guid A GUID specifying setup access permissions.\r
1555\r
1556 @retval TRUE Current user has the privilege.\r
1557 @retval FALSE Current user does not have the privilege.\r
1558**/\r
1559BOOLEAN\r
1560CheckUserPrivilege (\r
1561 IN EFI_GUID *Guid\r
1562 )\r
1563{\r
1564 EFI_STATUS Status;\r
1565 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
1566 EFI_USER_INFO_HANDLE UserInfoHandle;\r
1567 EFI_USER_INFO *UserInfo;\r
1568 EFI_GUID *UserPermissionsGuid;\r
1569 UINTN UserInfoSize;\r
1570 UINTN AccessControlDataSize;\r
1571 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
1572 UINTN RemainSize;\r
1573\r
1574 if (mUserManager == NULL) {\r
1575 Status = gBS->LocateProtocol (\r
1576 &gEfiUserManagerProtocolGuid,\r
1577 NULL,\r
1578 (VOID **) &mUserManager\r
1579 );\r
1580 if (EFI_ERROR (Status)) {\r
1581 ///\r
1582 /// If the system does not support user management, then it is assumed that\r
1583 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
1584 /// op-code is always TRUE.\r
1585 ///\r
1586 return TRUE;\r
1587 }\r
1588 }\r
1589\r
1590 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
1591 ASSERT_EFI_ERROR (Status);\r
1592\r
1593 ///\r
1594 /// Enumerate all user information of the current user profile\r
1595 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
1596 ///\r
1597 \r
1598 for (UserInfoHandle = NULL;;) {\r
1599 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
1600 if (EFI_ERROR (Status)) {\r
1601 break;\r
1602 }\r
1603\r
1604 UserInfoSize = 0;\r
1605 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
1606 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1607 continue;\r
1608 }\r
1609\r
1610 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
1611 if (UserInfo == NULL) {\r
1612 break;\r
1613 }\r
1614\r
1615 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
1616 if (EFI_ERROR (Status) ||\r
1617 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
1618 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
1619 FreePool (UserInfo);\r
1620 continue;\r
1621 }\r
1622\r
1623 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
1624 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
1625 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
3dd405be 1626 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
cbf73e50 1627 break;\r
1628 }\r
1629 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
1630 ///\r
1631 /// Check if current user has the privilege specified by the permissions GUID.\r
1632 ///\r
1633\r
1634 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
1635 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
1636 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
1637 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
1638 FreePool (UserInfo);\r
1639 return TRUE;\r
1640 }\r
1641 UserPermissionsGuid++;\r
1642 AccessControlDataSize -= sizeof (EFI_GUID);\r
1643 }\r
1644 }\r
1645 RemainSize -= AccessControl->Size;\r
1646 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
1647 }\r
1648\r
1649 FreePool (UserInfo);\r
1650 }\r
1651 return FALSE;\r
1652}\r
7936fb6a 1653\r
1654/**\r
bc166db3 1655 Evaluate the result of a HII expression.\r
1656\r
1657 If Expression is NULL, then ASSERT.\r
7936fb6a 1658\r
1659 @param FormSet FormSet associated with this expression.\r
1660 @param Form Form associated with this expression.\r
1661 @param Expression Expression to be evaluated.\r
1662\r
1663 @retval EFI_SUCCESS The expression evaluated successfuly\r
1664 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
1665 could not be found.\r
1666 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
1667 stack.\r
1668 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
1669 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
1670\r
1671**/\r
1672EFI_STATUS\r
1673EvaluateExpression (\r
1674 IN FORM_BROWSER_FORMSET *FormSet,\r
1675 IN FORM_BROWSER_FORM *Form,\r
1676 IN OUT FORM_EXPRESSION *Expression\r
1677 )\r
1678{\r
1679 EFI_STATUS Status;\r
1680 LIST_ENTRY *Link;\r
1681 EXPRESSION_OPCODE *OpCode;\r
1682 FORM_BROWSER_STATEMENT *Question;\r
1683 FORM_BROWSER_STATEMENT *Question2;\r
1684 UINT16 Index;\r
1685 EFI_HII_VALUE Data1;\r
1686 EFI_HII_VALUE Data2;\r
1687 EFI_HII_VALUE Data3;\r
1688 FORM_EXPRESSION *RuleExpression;\r
1689 EFI_HII_VALUE *Value;\r
1690 INTN Result;\r
1691 CHAR16 *StrPtr;\r
2573712e 1692 CHAR16 *NameValue;\r
7936fb6a 1693 UINT32 TempValue;\r
2573712e
LG
1694 LIST_ENTRY *SubExpressionLink;\r
1695 FORM_EXPRESSION *SubExpression;\r
1696 UINTN StackOffset;\r
1697 UINTN TempLength;\r
1698 CHAR16 TempStr[5];\r
1699 UINT8 DigitUint8;\r
1700 UINT8 *TempBuffer;\r
1701 EFI_TIME EfiTime;\r
7936fb6a 1702\r
1703 //\r
2573712e 1704 // Save current stack offset.\r
7936fb6a 1705 //\r
2573712e 1706 StackOffset = SaveExpressionEvaluationStackOffset ();\r
7936fb6a 1707\r
bc166db3 1708 ASSERT (Expression != NULL);\r
7936fb6a 1709 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
1710\r
1711 Link = GetFirstNode (&Expression->OpCodeListHead);\r
1712 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
1713 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
1714\r
1715 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
1716\r
1717 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
1718 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
1719 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
1720\r
1721 Value = &Data3;\r
1722 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1723 Status = EFI_SUCCESS;\r
1724\r
1725 switch (OpCode->Operand) {\r
1726 //\r
1727 // Built-in functions\r
1728 //\r
1729 case EFI_IFR_EQ_ID_VAL_OP:\r
1730 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1731 if (Question == NULL) {\r
2573712e
LG
1732 Status = EFI_NOT_FOUND;\r
1733 goto Done;\r
7936fb6a 1734 }\r
1735\r
1736 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
1737 if (Result == EFI_INVALID_PARAMETER) {\r
2573712e
LG
1738 Status = EFI_INVALID_PARAMETER;\r
1739 goto Done;\r
7936fb6a 1740 }\r
1741 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1742 break;\r
1743\r
1744 case EFI_IFR_EQ_ID_ID_OP:\r
1745 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1746 if (Question == NULL) {\r
2573712e
LG
1747 Status = EFI_NOT_FOUND;\r
1748 goto Done;\r
7936fb6a 1749 }\r
1750\r
1751 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
1752 if (Question2 == NULL) {\r
2573712e
LG
1753 Status = EFI_NOT_FOUND;\r
1754 goto Done;\r
7936fb6a 1755 }\r
1756\r
1757 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
1758 if (Result == EFI_INVALID_PARAMETER) {\r
2573712e
LG
1759 Status = EFI_INVALID_PARAMETER;\r
1760 goto Done;\r
7936fb6a 1761 }\r
1762 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1763 break;\r
1764\r
1765 case EFI_IFR_EQ_ID_LIST_OP:\r
1766 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1767 if (Question == NULL) {\r
2573712e
LG
1768 Status = EFI_NOT_FOUND;\r
1769 goto Done;\r
7936fb6a 1770 }\r
1771\r
1772 Value->Value.b = FALSE;\r
1773 for (Index =0; Index < OpCode->ListLength; Index++) {\r
1774 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
1775 Value->Value.b = TRUE;\r
1776 break;\r
1777 }\r
1778 }\r
1779 break;\r
1780\r
1781 case EFI_IFR_DUP_OP:\r
1782 Status = PopExpression (Value);\r
1783 if (EFI_ERROR (Status)) {\r
2573712e 1784 goto Done;\r
7936fb6a 1785 }\r
1786\r
1787 Status = PushExpression (Value);\r
1788 break;\r
1789\r
1790 case EFI_IFR_QUESTION_REF1_OP:\r
1791 case EFI_IFR_THIS_OP:\r
1792 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1793 if (Question == NULL) {\r
2573712e
LG
1794 Status = EFI_NOT_FOUND;\r
1795 goto Done;\r
7936fb6a 1796 }\r
1797\r
1798 Value = &Question->HiiValue;\r
1799 break;\r
1800\r
cbf73e50 1801 case EFI_IFR_SECURITY_OP:\r
1802 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
1803 break;\r
1804\r
2573712e
LG
1805 case EFI_IFR_GET_OP:\r
1806 //\r
1807 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
1808 //\r
1809 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
1810 Value->Value.u8 = 0;\r
1811 if (OpCode->VarStorage != NULL) {\r
1812 switch (OpCode->VarStorage->Type) {\r
1813 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 1814 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
1815 //\r
1816 // Get value from Edit Buffer\r
1817 //\r
1818 Value->Type = OpCode->ValueType;\r
1819 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
1820 break;\r
1821 case EFI_HII_VARSTORE_NAME_VALUE:\r
1822 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
1823 //\r
1824 // Get value from string except for STRING value.\r
1825 //\r
1826 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr);\r
1827 if (!EFI_ERROR (Status)) {\r
771ececd 1828 ASSERT (StrPtr != NULL);\r
2573712e
LG
1829 TempLength = StrLen (StrPtr);\r
1830 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
1831 Value->Type = OpCode->ValueType;\r
1832 TempBuffer = (UINT8 *) &Value->Value;\r
1833 ZeroMem (TempStr, sizeof (TempStr));\r
1834 for (Index = 0; Index < TempLength; Index ++) {\r
1835 TempStr[0] = StrPtr[TempLength - Index - 1];\r
1836 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
1837 if ((Index & 1) == 0) {\r
1838 TempBuffer [Index/2] = DigitUint8;\r
1839 } else {\r
771ececd 1840 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
1841 }\r
1842 }\r
1843 } \r
1844 }\r
1845 }\r
1846 break;\r
1847 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1848 //\r
1849 // Get value from variable.\r
1850 //\r
1851 TempLength = OpCode->ValueWidth;\r
1852 Value->Type = OpCode->ValueType;\r
1853 Status = gRT->GetVariable (\r
1854 OpCode->ValueName,\r
1855 &OpCode->VarStorage->Guid,\r
1856 NULL,\r
1857 &TempLength,\r
1858 &Value->Value\r
1859 );\r
1860 if (EFI_ERROR (Status)) {\r
1861 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
1862 Value->Value.u8 = 0;\r
1863 }\r
cce6230f 1864 break;\r
2573712e
LG
1865 default:\r
1866 //\r
1867 // Not recognize storage.\r
1868 //\r
1869 Status = EFI_UNSUPPORTED;\r
1870 goto Done;\r
1871 }\r
1872 } else {\r
1873 //\r
1874 // For Time/Date Data\r
1875 //\r
1876 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
1877 //\r
1878 // Only support Data/Time data when storage doesn't exist.\r
1879 //\r
1880 Status = EFI_UNSUPPORTED;\r
1881 goto Done;\r
1882 }\r
1883 Status = gRT->GetTime (&EfiTime, NULL);\r
1884 if (!EFI_ERROR (Status)) {\r
1885 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
1886 switch (OpCode->VarStoreInfo.VarOffset) {\r
1887 case 0x00:\r
1888 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
1889 Value->Value.u16 = EfiTime.Year;\r
1890 break;\r
1891 case 0x02:\r
1892 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1893 Value->Value.u8 = EfiTime.Month;\r
1894 break;\r
1895 case 0x03:\r
1896 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1897 Value->Value.u8 = EfiTime.Day;\r
1898 break;\r
1899 default:\r
1900 //\r
1901 // Invalid Date field.\r
1902 //\r
1903 Status = EFI_INVALID_PARAMETER;\r
1904 goto Done;\r
1905 }\r
1906 } else {\r
1907 switch (OpCode->VarStoreInfo.VarOffset) {\r
1908 case 0x00:\r
1909 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1910 Value->Value.u8 = EfiTime.Hour;\r
1911 break;\r
1912 case 0x01:\r
1913 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1914 Value->Value.u8 = EfiTime.Minute;\r
1915 break;\r
1916 case 0x02:\r
1917 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1918 Value->Value.u8 = EfiTime.Second;\r
1919 break;\r
1920 default:\r
1921 //\r
1922 // Invalid Time field.\r
1923 //\r
1924 Status = EFI_INVALID_PARAMETER;\r
1925 goto Done;\r
1926 }\r
1927 }\r
1928 }\r
1929 }\r
1930\r
1931 break;\r
1932\r
7936fb6a 1933 case EFI_IFR_QUESTION_REF3_OP:\r
1934 if (OpCode->DevicePath == 0) {\r
1935 //\r
1936 // EFI_IFR_QUESTION_REF3\r
1937 // Pop an expression from the expression stack\r
1938 //\r
1939 Status = PopExpression (Value);\r
1940 if (EFI_ERROR (Status)) {\r
2573712e 1941 goto Done;\r
7936fb6a 1942 }\r
1943\r
1944 //\r
1945 // Validate the expression value\r
1946 //\r
1947 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2573712e
LG
1948 Status = EFI_NOT_FOUND;\r
1949 goto Done;\r
7936fb6a 1950 }\r
1951\r
1952 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1953 if (Question == NULL) {\r
2573712e
LG
1954 Status = EFI_NOT_FOUND;\r
1955 goto Done;\r
7936fb6a 1956 }\r
1957\r
1958 //\r
1959 // push the questions' value on to the expression stack\r
1960 //\r
1961 Value = &Question->HiiValue;\r
1962 } else {\r
1963 //\r
1964 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
1965 // since it is impractical to evaluate the value of a Question in another\r
1966 // Hii Package list.\r
1967 //\r
1968 ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
1969 }\r
1970 break;\r
1971\r
1972 case EFI_IFR_RULE_REF_OP:\r
1973 //\r
1974 // Find expression for this rule\r
1975 //\r
1976 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
1977 if (RuleExpression == NULL) {\r
2573712e
LG
1978 Status = EFI_NOT_FOUND;\r
1979 goto Done;\r
7936fb6a 1980 }\r
1981\r
1982 //\r
1983 // Evaluate this rule expression\r
1984 //\r
1985 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
1986 if (EFI_ERROR (Status)) {\r
2573712e 1987 goto Done;\r
7936fb6a 1988 }\r
1989\r
1990 Value = &RuleExpression->Result;\r
1991 break;\r
1992\r
1993 case EFI_IFR_STRING_REF1_OP:\r
1994 Value->Type = EFI_IFR_TYPE_STRING;\r
1995 Value->Value.string = OpCode->Value.Value.string;\r
1996 break;\r
1997\r
1998 //\r
1999 // Constant\r
2000 //\r
2001 case EFI_IFR_TRUE_OP:\r
2002 case EFI_IFR_FALSE_OP:\r
2003 case EFI_IFR_ONE_OP:\r
2004 case EFI_IFR_ONES_OP:\r
2005 case EFI_IFR_UINT8_OP:\r
2006 case EFI_IFR_UINT16_OP:\r
2007 case EFI_IFR_UINT32_OP:\r
2008 case EFI_IFR_UINT64_OP:\r
2009 case EFI_IFR_UNDEFINED_OP:\r
2010 case EFI_IFR_VERSION_OP:\r
2011 case EFI_IFR_ZERO_OP:\r
2012 Value = &OpCode->Value;\r
2013 break;\r
2014\r
2015 //\r
2016 // unary-op\r
2017 //\r
2018 case EFI_IFR_LENGTH_OP:\r
2019 Status = PopExpression (Value);\r
2020 if (EFI_ERROR (Status)) {\r
2573712e 2021 goto Done;\r
7936fb6a 2022 }\r
901ba0e7 2023 if (Value->Type != EFI_IFR_TYPE_STRING && Value->Type != EFI_IFR_TYPE_BUFFER) {\r
2573712e
LG
2024 Status = EFI_INVALID_PARAMETER;\r
2025 goto Done;\r
7936fb6a 2026 }\r
2027\r
901ba0e7
ED
2028 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2029 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2030 if (StrPtr == NULL) {\r
2031 Status = EFI_INVALID_PARAMETER;\r
2032 goto Done;\r
2033 }\r
7936fb6a 2034\r
901ba0e7
ED
2035 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2036 Value->Value.u64 = StrLen (StrPtr);\r
2037 FreePool (StrPtr);\r
2038 } else {\r
2039 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2040 Value->Value.u64 = Value->BufferLen;\r
2041 FreePool (Value->Buffer);\r
2042 }\r
7936fb6a 2043 break;\r
2044\r
2045 case EFI_IFR_NOT_OP:\r
2046 Status = PopExpression (Value);\r
2047 if (EFI_ERROR (Status)) {\r
2573712e 2048 goto Done;\r
7936fb6a 2049 }\r
2050 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2051 Status = EFI_INVALID_PARAMETER;\r
2052 goto Done;\r
7936fb6a 2053 }\r
2054 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2055 break;\r
2056\r
2057 case EFI_IFR_QUESTION_REF2_OP:\r
2058 //\r
2059 // Pop an expression from the expression stack\r
2060 //\r
2061 Status = PopExpression (Value);\r
2062 if (EFI_ERROR (Status)) {\r
2573712e 2063 goto Done;\r
7936fb6a 2064 }\r
2065\r
2066 //\r
2067 // Validate the expression value\r
2068 //\r
2069 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2573712e
LG
2070 Status = EFI_NOT_FOUND;\r
2071 goto Done;\r
7936fb6a 2072 }\r
2073\r
2074 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2075 if (Question == NULL) {\r
2573712e
LG
2076 Status = EFI_NOT_FOUND;\r
2077 goto Done;\r
7936fb6a 2078 }\r
2079\r
2080 Value = &Question->HiiValue;\r
2081 break;\r
2082\r
2083 case EFI_IFR_STRING_REF2_OP:\r
2084 //\r
2085 // Pop an expression from the expression stack\r
2086 //\r
2087 Status = PopExpression (Value);\r
2088 if (EFI_ERROR (Status)) {\r
2573712e 2089 goto Done;\r
7936fb6a 2090 }\r
2091\r
2092 //\r
2093 // Validate the expression value\r
2094 //\r
2095 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2573712e
LG
2096 Status = EFI_NOT_FOUND;\r
2097 goto Done;\r
7936fb6a 2098 }\r
2099\r
2100 Value->Type = EFI_IFR_TYPE_STRING;\r
2101 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2102 if (StrPtr == NULL) {\r
2103 //\r
2104 // If String not exit, push an empty string\r
2105 //\r
2106 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2107 } else {\r
2108 Index = (UINT16) Value->Value.u64;\r
2109 Value->Value.string = Index;\r
f4113e1f 2110 FreePool (StrPtr);\r
7936fb6a 2111 }\r
2112 break;\r
2113\r
2114 case EFI_IFR_TO_BOOLEAN_OP:\r
2115 //\r
2116 // Pop an expression from the expression stack\r
2117 //\r
2118 Status = PopExpression (Value);\r
2119 if (EFI_ERROR (Status)) {\r
2573712e 2120 goto Done;\r
7936fb6a 2121 }\r
2122\r
2123 //\r
2124 // Convert an expression to a Boolean\r
2125 //\r
2126 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
2127 //\r
2128 // When converting from an unsigned integer, zero will be converted to\r
2129 // FALSE and any other value will be converted to TRUE.\r
2130 //\r
4140a663 2131 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);\r
7936fb6a 2132\r
2133 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2134 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2135 //\r
2136 // When converting from a string, if case-insensitive compare\r
2137 // with "true" is True, then push True. If a case-insensitive compare\r
39099cbd 2138 // with "false" is True, then push False. Otherwise, push Undefined. \r
7936fb6a 2139 //\r
2140 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2141 if (StrPtr == NULL) {\r
2573712e
LG
2142 Status = EFI_INVALID_PARAMETER;\r
2143 goto Done;\r
7936fb6a 2144 }\r
39099cbd
ED
2145 \r
2146 IfrStrToUpper (StrPtr);\r
2147 if (StrCmp (StrPtr, L"TRUE") == 0){\r
7936fb6a 2148 Value->Value.b = TRUE;\r
39099cbd 2149 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
7936fb6a 2150 Value->Value.b = FALSE;\r
39099cbd
ED
2151 } else {\r
2152 Status = EFI_INVALID_PARAMETER;\r
2153 FreePool (StrPtr);\r
2154 goto Done;\r
7936fb6a 2155 }\r
f4113e1f 2156 FreePool (StrPtr);\r
7936fb6a 2157 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
901ba0e7
ED
2158 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
2159 //\r
2160 // When converting from a buffer, if the buffer is all zeroes, \r
2161 // then push False. Otherwise push True. \r
2162 //\r
2163 for (Index =0; Index < Value->BufferLen; Index ++) {\r
2164 if (Value->Buffer[Index] != 0) { \r
2165 break;\r
2166 }\r
2167 }\r
2168\r
2169 if (Index >= Value->BufferLen) {\r
2170 Value->Value.b = FALSE;\r
2171 } else {\r
2172 Value->Value.b = TRUE;\r
2173 }\r
2174 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2175 FreePool (Value->Buffer);\r
7936fb6a 2176 }\r
2177 break;\r
2178\r
2179 case EFI_IFR_TO_STRING_OP:\r
2180 Status = IfrToString (FormSet, OpCode->Format, Value);\r
2181 break;\r
2182\r
2183 case EFI_IFR_TO_UINT_OP:\r
2184 Status = IfrToUint (FormSet, Value);\r
2185 break;\r
2186\r
2187 case EFI_IFR_TO_LOWER_OP:\r
2188 case EFI_IFR_TO_UPPER_OP:\r
2189 Status = InitializeUnicodeCollationProtocol ();\r
2190 if (EFI_ERROR (Status)) {\r
2573712e 2191 goto Done;\r
7936fb6a 2192 }\r
2193\r
2194 Status = PopExpression (Value);\r
2195 if (EFI_ERROR (Status)) {\r
2573712e 2196 goto Done;\r
7936fb6a 2197 }\r
2198\r
2199 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
2573712e
LG
2200 Status = EFI_UNSUPPORTED;\r
2201 goto Done;\r
7936fb6a 2202 }\r
2203\r
2204 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2205 if (StrPtr == NULL) {\r
2573712e
LG
2206 Status = EFI_NOT_FOUND;\r
2207 goto Done;\r
7936fb6a 2208 }\r
2209\r
2210 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
2211 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
2212 } else {\r
2213 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
2214 }\r
2215 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 2216 FreePool (StrPtr);\r
7936fb6a 2217 break;\r
2218\r
2219 case EFI_IFR_BITWISE_NOT_OP:\r
2220 //\r
2221 // Pop an expression from the expression stack\r
2222 //\r
2223 Status = PopExpression (Value);\r
2224 if (EFI_ERROR (Status)) {\r
2573712e 2225 goto Done;\r
7936fb6a 2226 }\r
2227 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2228 Status = EFI_INVALID_PARAMETER;\r
2229 goto Done;\r
7936fb6a 2230 }\r
2231\r
2232 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2233 Value->Value.u64 = ~Value->Value.u64;\r
2234 break;\r
2235\r
2573712e
LG
2236 case EFI_IFR_SET_OP:\r
2237 //\r
2238 // Pop an expression from the expression stack\r
2239 //\r
2240 Status = PopExpression (Value);\r
2241 if (EFI_ERROR (Status)) {\r
2242 goto Done;\r
2243 }\r
2244 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
2245 Data1.Value.b = FALSE;\r
2246 //\r
2247 // Set value to var storage buffer\r
2248 //\r
2249 if (OpCode->VarStorage != NULL) {\r
2250 switch (OpCode->VarStorage->Type) {\r
2251 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2252 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2253 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
2254 Data1.Value.b = TRUE;\r
2255 break;\r
2256 case EFI_HII_VARSTORE_NAME_VALUE:\r
2257 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2258 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
2259 ASSERT (Value != NULL);\r
2260 //\r
2261 // Convert Buffer to Hex String\r
2262 //\r
2263 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
2264 StrPtr = NameValue;\r
2265 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
2266 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
2267 }\r
b18e7050 2268 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, TRUE);\r
2573712e
LG
2269 FreePool (NameValue);\r
2270 if (!EFI_ERROR (Status)) {\r
2271 Data1.Value.b = TRUE;\r
2272 }\r
2273 }\r
2274 break;\r
2275 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2276 Status = gRT->SetVariable (\r
2277 OpCode->ValueName,\r
2278 &OpCode->VarStorage->Guid,\r
2279 OpCode->VarStorage->Attributes,\r
2280 OpCode->ValueWidth,\r
2281 &Value->Value\r
2282 );\r
2283 if (!EFI_ERROR (Status)) {\r
2284 Data1.Value.b = TRUE;\r
2285 }\r
2286 break;\r
2287 default:\r
2288 //\r
2289 // Not recognize storage.\r
2290 //\r
2291 Status = EFI_UNSUPPORTED;\r
2292 goto Done;\r
2293 break;\r
2294 }\r
2295 } else {\r
2296 //\r
2297 // For Time/Date Data\r
2298 //\r
2299 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2300 //\r
2301 // Only support Data/Time data when storage doesn't exist.\r
2302 //\r
2303 Status = EFI_UNSUPPORTED;\r
2304 goto Done;\r
2305 }\r
2306 Status = gRT->GetTime (&EfiTime, NULL);\r
2307 if (!EFI_ERROR (Status)) {\r
2308 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2309 switch (OpCode->VarStoreInfo.VarOffset) {\r
2310 case 0x00:\r
2311 EfiTime.Year = Value->Value.u16;\r
2312 break;\r
2313 case 0x02:\r
2314 EfiTime.Month = Value->Value.u8;\r
2315 break;\r
2316 case 0x03:\r
2317 EfiTime.Day = Value->Value.u8;\r
2318 break;\r
2319 default:\r
2320 //\r
2321 // Invalid Date field.\r
2322 //\r
2323 Status = EFI_INVALID_PARAMETER;\r
2324 goto Done;\r
2325 }\r
2326 } else {\r
2327 switch (OpCode->VarStoreInfo.VarOffset) {\r
2328 case 0x00:\r
2329 EfiTime.Hour = Value->Value.u8;\r
2330 break;\r
2331 case 0x01:\r
2332 EfiTime.Minute = Value->Value.u8;\r
2333 break;\r
2334 case 0x02:\r
2335 EfiTime.Second = Value->Value.u8;\r
2336 break;\r
2337 default:\r
2338 //\r
2339 // Invalid Time field.\r
2340 //\r
2341 Status = EFI_INVALID_PARAMETER;\r
2342 goto Done;\r
2343 }\r
2344 }\r
2345 Status = gRT->SetTime (&EfiTime);\r
2346 if (!EFI_ERROR (Status)) {\r
2347 Data1.Value.b = TRUE;\r
2348 }\r
2349 }\r
2350 }\r
2351 Value = &Data1;\r
2352 break;\r
2353\r
7936fb6a 2354 //\r
2355 // binary-op\r
2356 //\r
2357 case EFI_IFR_ADD_OP:\r
2358 case EFI_IFR_SUBTRACT_OP:\r
2359 case EFI_IFR_MULTIPLY_OP:\r
2360 case EFI_IFR_DIVIDE_OP:\r
2361 case EFI_IFR_MODULO_OP:\r
2362 case EFI_IFR_BITWISE_AND_OP:\r
2363 case EFI_IFR_BITWISE_OR_OP:\r
2364 case EFI_IFR_SHIFT_LEFT_OP:\r
2365 case EFI_IFR_SHIFT_RIGHT_OP:\r
2366 //\r
2367 // Pop an expression from the expression stack\r
2368 //\r
2369 Status = PopExpression (&Data2);\r
2370 if (EFI_ERROR (Status)) {\r
2573712e 2371 goto Done;\r
7936fb6a 2372 }\r
2373 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2374 Status = EFI_INVALID_PARAMETER;\r
2375 goto Done;\r
7936fb6a 2376 }\r
2377\r
2378 //\r
2379 // Pop another expression from the expression stack\r
2380 //\r
2381 Status = PopExpression (&Data1);\r
2382 if (EFI_ERROR (Status)) {\r
2573712e 2383 goto Done;\r
7936fb6a 2384 }\r
2385 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2386 Status = EFI_INVALID_PARAMETER;\r
2387 goto Done;\r
7936fb6a 2388 }\r
2389\r
2390 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2391\r
2392 switch (OpCode->Operand) {\r
2393 case EFI_IFR_ADD_OP:\r
2394 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
2395 break;\r
2396\r
2397 case EFI_IFR_SUBTRACT_OP:\r
2398 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
2399 break;\r
2400\r
2401 case EFI_IFR_MULTIPLY_OP:\r
2402 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2403 break;\r
2404\r
2405 case EFI_IFR_DIVIDE_OP:\r
2406 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2407 break;\r
2408\r
2409 case EFI_IFR_MODULO_OP:\r
2410 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
2411 Value->Value.u64 = TempValue;\r
2412 break;\r
2413\r
2414 case EFI_IFR_BITWISE_AND_OP:\r
2415 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
2416 break;\r
2417\r
2418 case EFI_IFR_BITWISE_OR_OP:\r
2419 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
2420 break;\r
2421\r
2422 case EFI_IFR_SHIFT_LEFT_OP:\r
2423 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2424 break;\r
2425\r
2426 case EFI_IFR_SHIFT_RIGHT_OP:\r
2427 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2428 break;\r
2429\r
2430 default:\r
2431 break;\r
2432 }\r
2433 break;\r
2434\r
2435 case EFI_IFR_AND_OP:\r
2436 case EFI_IFR_OR_OP:\r
2437 //\r
2438 // Two Boolean operator\r
2439 //\r
2440 Status = PopExpression (&Data2);\r
2441 if (EFI_ERROR (Status)) {\r
2573712e 2442 goto Done;\r
7936fb6a 2443 }\r
2444 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2445 Status = EFI_INVALID_PARAMETER;\r
2446 goto Done;\r
7936fb6a 2447 }\r
2448\r
2449 //\r
2450 // Pop another expression from the expression stack\r
2451 //\r
2452 Status = PopExpression (&Data1);\r
2453 if (EFI_ERROR (Status)) {\r
2573712e 2454 goto Done;\r
7936fb6a 2455 }\r
2456 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2457 Status = EFI_INVALID_PARAMETER;\r
2458 goto Done;\r
7936fb6a 2459 }\r
2460\r
2461 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
2462 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
2463 } else {\r
2464 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
2465 }\r
2466 break;\r
2467\r
2468 case EFI_IFR_EQUAL_OP:\r
2469 case EFI_IFR_NOT_EQUAL_OP:\r
2470 case EFI_IFR_GREATER_EQUAL_OP:\r
2471 case EFI_IFR_GREATER_THAN_OP:\r
2472 case EFI_IFR_LESS_EQUAL_OP:\r
2473 case EFI_IFR_LESS_THAN_OP:\r
2474 //\r
2475 // Compare two integer, string, boolean or date/time\r
2476 //\r
2477 Status = PopExpression (&Data2);\r
2478 if (EFI_ERROR (Status)) {\r
2573712e 2479 goto Done;\r
7936fb6a 2480 }\r
901ba0e7
ED
2481 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
2482 Data2.Type != EFI_IFR_TYPE_STRING && \r
2483 Data2.Type != EFI_IFR_TYPE_BUFFER) {\r
2573712e
LG
2484 Status = EFI_INVALID_PARAMETER;\r
2485 goto Done;\r
7936fb6a 2486 }\r
2487\r
2488 //\r
2489 // Pop another expression from the expression stack\r
2490 //\r
2491 Status = PopExpression (&Data1);\r
2492 if (EFI_ERROR (Status)) {\r
2573712e 2493 goto Done;\r
7936fb6a 2494 }\r
2495\r
2496 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
901ba0e7
ED
2497 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
2498 FreePool (Data1.Buffer);\r
2499 FreePool (Data2.Buffer);\r
2500 }\r
2501 \r
7936fb6a 2502 if (Result == EFI_INVALID_PARAMETER) {\r
2573712e
LG
2503 Status = EFI_INVALID_PARAMETER;\r
2504 goto Done;\r
7936fb6a 2505 }\r
2506\r
2507 switch (OpCode->Operand) {\r
2508 case EFI_IFR_EQUAL_OP:\r
2509 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2510 break;\r
2511\r
2512 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 2513 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 2514 break;\r
2515\r
2516 case EFI_IFR_GREATER_EQUAL_OP:\r
2517 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
2518 break;\r
2519\r
2520 case EFI_IFR_GREATER_THAN_OP:\r
2521 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
2522 break;\r
2523\r
2524 case EFI_IFR_LESS_EQUAL_OP:\r
2525 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
2526 break;\r
2527\r
2528 case EFI_IFR_LESS_THAN_OP:\r
2529 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
2530 break;\r
2531\r
2532 default:\r
2533 break;\r
2534 }\r
2535 break;\r
2536\r
2537 case EFI_IFR_MATCH_OP:\r
20258293
ED
2538 Status = InitializeUnicodeCollationProtocol ();\r
2539 if (EFI_ERROR (Status)) {\r
2540 goto Done;\r
2541 }\r
2542 \r
7936fb6a 2543 Status = IfrMatch (FormSet, Value);\r
2544 break;\r
2545\r
2546 case EFI_IFR_CATENATE_OP:\r
2547 Status = IfrCatenate (FormSet, Value);\r
2548 break;\r
2549\r
2550 //\r
2551 // ternary-op\r
2552 //\r
2553 case EFI_IFR_CONDITIONAL_OP:\r
2554 //\r
2555 // Pop third expression from the expression stack\r
2556 //\r
2557 Status = PopExpression (&Data3);\r
2558 if (EFI_ERROR (Status)) {\r
2573712e 2559 goto Done;\r
7936fb6a 2560 }\r
2561\r
2562 //\r
2563 // Pop second expression from the expression stack\r
2564 //\r
2565 Status = PopExpression (&Data2);\r
2566 if (EFI_ERROR (Status)) {\r
2573712e 2567 goto Done;\r
7936fb6a 2568 }\r
2569\r
2570 //\r
2571 // Pop first expression from the expression stack\r
2572 //\r
2573 Status = PopExpression (&Data1);\r
2574 if (EFI_ERROR (Status)) {\r
2573712e 2575 goto Done;\r
7936fb6a 2576 }\r
2577 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2578 Status = EFI_INVALID_PARAMETER;\r
2579 goto Done;\r
7936fb6a 2580 }\r
2581\r
2582 if (Data1.Value.b) {\r
2583 Value = &Data3;\r
2584 } else {\r
2585 Value = &Data2;\r
2586 }\r
2587 break;\r
2588\r
2589 case EFI_IFR_FIND_OP:\r
2590 Status = IfrFind (FormSet, OpCode->Format, Value);\r
2591 break;\r
2592\r
2593 case EFI_IFR_MID_OP:\r
2594 Status = IfrMid (FormSet, Value);\r
2595 break;\r
2596\r
2597 case EFI_IFR_TOKEN_OP:\r
2598 Status = IfrToken (FormSet, Value);\r
2599 break;\r
2600\r
2601 case EFI_IFR_SPAN_OP:\r
2602 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
2603 break;\r
2604\r
2573712e
LG
2605 case EFI_IFR_MAP_OP:\r
2606 //\r
2607 // Pop the check value\r
2608 //\r
2609 Status = PopExpression (&Data1);\r
2610 if (EFI_ERROR (Status)) {\r
2611 goto Done;\r
2612 }\r
2613 //\r
2614 // Check MapExpression list is valid.\r
2615 //\r
2616 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
2617 Status = EFI_INVALID_PARAMETER;\r
2618 goto Done;\r
2619 }\r
2620 //\r
2621 // Go through map expression list.\r
2622 //\r
2623 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
2624 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2625 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
2626 //\r
2627 // Evaluate the first expression in this pair.\r
2628 //\r
2629 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
2630 if (EFI_ERROR (Status)) {\r
2631 goto Done;\r
2632 }\r
2633 //\r
2634 // Compare the expression value with current value\r
2635 //\r
2636 if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) {\r
2637 //\r
2638 // Try get the map value.\r
2639 //\r
2640 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2641 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2642 Status = EFI_INVALID_PARAMETER;\r
2643 goto Done;\r
2644 }\r
2645 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
2646 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
2647 if (EFI_ERROR (Status)) {\r
2648 goto Done;\r
2649 }\r
2650 Value = &SubExpression->Result;\r
2651 break;\r
2652 }\r
2653 //\r
2654 // Skip the second expression on this pair.\r
2655 //\r
2656 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2657 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2658 Status = EFI_INVALID_PARAMETER;\r
2659 goto Done;\r
2660 }\r
2661 //\r
2662 // Goto the first expression on next pair.\r
2663 //\r
2664 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2665 }\r
2666\r
2667 //\r
2668 // No map value is found.\r
2669 //\r
2670 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2671 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2672 Value->Value.u8 = 0;\r
2673 }\r
2674 break;\r
2675\r
7936fb6a 2676 default:\r
2677 break;\r
2678 }\r
2679 if (EFI_ERROR (Status)) {\r
2573712e 2680 goto Done;\r
7936fb6a 2681 }\r
2682\r
2683 Status = PushExpression (Value);\r
2684 if (EFI_ERROR (Status)) {\r
2573712e 2685 goto Done;\r
7936fb6a 2686 }\r
2687 }\r
2688\r
2689 //\r
2690 // Pop the final result from expression stack\r
2691 //\r
2692 Value = &Data1;\r
2693 Status = PopExpression (Value);\r
2694 if (EFI_ERROR (Status)) {\r
2573712e 2695 goto Done;\r
7936fb6a 2696 }\r
2697\r
2698 //\r
2699 // After evaluating an expression, there should be only one value left on the expression stack\r
2700 //\r
2701 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 2702 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 2703 }\r
2704\r
2573712e
LG
2705Done:\r
2706 RestoreExpressionEvaluationStackOffset (StackOffset);\r
2707 if (!EFI_ERROR (Status)) {\r
2708 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
2709 }\r
7936fb6a 2710\r
2573712e 2711 return Status;\r
7936fb6a 2712}\r