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