]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Update the copyright notice format
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
e5eed7d3
HT
4Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
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
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
3dd405be 1531 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
cbf73e50 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
771ececd 1732 ASSERT (StrPtr != NULL);\r
2573712e
LG
1733 TempLength = StrLen (StrPtr);\r
1734 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
1735 Value->Type = OpCode->ValueType;\r
1736 TempBuffer = (UINT8 *) &Value->Value;\r
1737 ZeroMem (TempStr, sizeof (TempStr));\r
1738 for (Index = 0; Index < TempLength; Index ++) {\r
1739 TempStr[0] = StrPtr[TempLength - Index - 1];\r
1740 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
1741 if ((Index & 1) == 0) {\r
1742 TempBuffer [Index/2] = DigitUint8;\r
1743 } else {\r
771ececd 1744 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
1745 }\r
1746 }\r
1747 } \r
1748 }\r
1749 }\r
1750 break;\r
1751 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
1752 //\r
1753 // Get value from variable.\r
1754 //\r
1755 TempLength = OpCode->ValueWidth;\r
1756 Value->Type = OpCode->ValueType;\r
1757 Status = gRT->GetVariable (\r
1758 OpCode->ValueName,\r
1759 &OpCode->VarStorage->Guid,\r
1760 NULL,\r
1761 &TempLength,\r
1762 &Value->Value\r
1763 );\r
1764 if (EFI_ERROR (Status)) {\r
1765 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
1766 Value->Value.u8 = 0;\r
1767 }\r
1768 default:\r
1769 //\r
1770 // Not recognize storage.\r
1771 //\r
1772 Status = EFI_UNSUPPORTED;\r
1773 goto Done;\r
1774 }\r
1775 } else {\r
1776 //\r
1777 // For Time/Date Data\r
1778 //\r
1779 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
1780 //\r
1781 // Only support Data/Time data when storage doesn't exist.\r
1782 //\r
1783 Status = EFI_UNSUPPORTED;\r
1784 goto Done;\r
1785 }\r
1786 Status = gRT->GetTime (&EfiTime, NULL);\r
1787 if (!EFI_ERROR (Status)) {\r
1788 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
1789 switch (OpCode->VarStoreInfo.VarOffset) {\r
1790 case 0x00:\r
1791 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
1792 Value->Value.u16 = EfiTime.Year;\r
1793 break;\r
1794 case 0x02:\r
1795 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1796 Value->Value.u8 = EfiTime.Month;\r
1797 break;\r
1798 case 0x03:\r
1799 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1800 Value->Value.u8 = EfiTime.Day;\r
1801 break;\r
1802 default:\r
1803 //\r
1804 // Invalid Date field.\r
1805 //\r
1806 Status = EFI_INVALID_PARAMETER;\r
1807 goto Done;\r
1808 }\r
1809 } else {\r
1810 switch (OpCode->VarStoreInfo.VarOffset) {\r
1811 case 0x00:\r
1812 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1813 Value->Value.u8 = EfiTime.Hour;\r
1814 break;\r
1815 case 0x01:\r
1816 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1817 Value->Value.u8 = EfiTime.Minute;\r
1818 break;\r
1819 case 0x02:\r
1820 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
1821 Value->Value.u8 = EfiTime.Second;\r
1822 break;\r
1823 default:\r
1824 //\r
1825 // Invalid Time field.\r
1826 //\r
1827 Status = EFI_INVALID_PARAMETER;\r
1828 goto Done;\r
1829 }\r
1830 }\r
1831 }\r
1832 }\r
1833\r
1834 break;\r
1835\r
7936fb6a 1836 case EFI_IFR_QUESTION_REF3_OP:\r
1837 if (OpCode->DevicePath == 0) {\r
1838 //\r
1839 // EFI_IFR_QUESTION_REF3\r
1840 // Pop an expression from the expression stack\r
1841 //\r
1842 Status = PopExpression (Value);\r
1843 if (EFI_ERROR (Status)) {\r
2573712e 1844 goto Done;\r
7936fb6a 1845 }\r
1846\r
1847 //\r
1848 // Validate the expression value\r
1849 //\r
1850 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2573712e
LG
1851 Status = EFI_NOT_FOUND;\r
1852 goto Done;\r
7936fb6a 1853 }\r
1854\r
1855 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1856 if (Question == NULL) {\r
2573712e
LG
1857 Status = EFI_NOT_FOUND;\r
1858 goto Done;\r
7936fb6a 1859 }\r
1860\r
1861 //\r
1862 // push the questions' value on to the expression stack\r
1863 //\r
1864 Value = &Question->HiiValue;\r
1865 } else {\r
1866 //\r
1867 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
1868 // since it is impractical to evaluate the value of a Question in another\r
1869 // Hii Package list.\r
1870 //\r
1871 ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
1872 }\r
1873 break;\r
1874\r
1875 case EFI_IFR_RULE_REF_OP:\r
1876 //\r
1877 // Find expression for this rule\r
1878 //\r
1879 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
1880 if (RuleExpression == NULL) {\r
2573712e
LG
1881 Status = EFI_NOT_FOUND;\r
1882 goto Done;\r
7936fb6a 1883 }\r
1884\r
1885 //\r
1886 // Evaluate this rule expression\r
1887 //\r
1888 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
1889 if (EFI_ERROR (Status)) {\r
2573712e 1890 goto Done;\r
7936fb6a 1891 }\r
1892\r
1893 Value = &RuleExpression->Result;\r
1894 break;\r
1895\r
1896 case EFI_IFR_STRING_REF1_OP:\r
1897 Value->Type = EFI_IFR_TYPE_STRING;\r
1898 Value->Value.string = OpCode->Value.Value.string;\r
1899 break;\r
1900\r
1901 //\r
1902 // Constant\r
1903 //\r
1904 case EFI_IFR_TRUE_OP:\r
1905 case EFI_IFR_FALSE_OP:\r
1906 case EFI_IFR_ONE_OP:\r
1907 case EFI_IFR_ONES_OP:\r
1908 case EFI_IFR_UINT8_OP:\r
1909 case EFI_IFR_UINT16_OP:\r
1910 case EFI_IFR_UINT32_OP:\r
1911 case EFI_IFR_UINT64_OP:\r
1912 case EFI_IFR_UNDEFINED_OP:\r
1913 case EFI_IFR_VERSION_OP:\r
1914 case EFI_IFR_ZERO_OP:\r
1915 Value = &OpCode->Value;\r
1916 break;\r
1917\r
1918 //\r
1919 // unary-op\r
1920 //\r
1921 case EFI_IFR_LENGTH_OP:\r
1922 Status = PopExpression (Value);\r
1923 if (EFI_ERROR (Status)) {\r
2573712e 1924 goto Done;\r
7936fb6a 1925 }\r
1926 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
2573712e
LG
1927 Status = EFI_INVALID_PARAMETER;\r
1928 goto Done;\r
7936fb6a 1929 }\r
1930\r
1931 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1932 if (StrPtr == NULL) {\r
2573712e
LG
1933 Status = EFI_INVALID_PARAMETER;\r
1934 goto Done;\r
7936fb6a 1935 }\r
1936\r
1937 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1938 Value->Value.u64 = StrLen (StrPtr);\r
f4113e1f 1939 FreePool (StrPtr);\r
7936fb6a 1940 break;\r
1941\r
1942 case EFI_IFR_NOT_OP:\r
1943 Status = PopExpression (Value);\r
1944 if (EFI_ERROR (Status)) {\r
2573712e 1945 goto Done;\r
7936fb6a 1946 }\r
1947 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
1948 Status = EFI_INVALID_PARAMETER;\r
1949 goto Done;\r
7936fb6a 1950 }\r
1951 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
1952 break;\r
1953\r
1954 case EFI_IFR_QUESTION_REF2_OP:\r
1955 //\r
1956 // Pop an expression from the expression stack\r
1957 //\r
1958 Status = PopExpression (Value);\r
1959 if (EFI_ERROR (Status)) {\r
2573712e 1960 goto Done;\r
7936fb6a 1961 }\r
1962\r
1963 //\r
1964 // Validate the expression value\r
1965 //\r
1966 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2573712e
LG
1967 Status = EFI_NOT_FOUND;\r
1968 goto Done;\r
7936fb6a 1969 }\r
1970\r
1971 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1972 if (Question == NULL) {\r
2573712e
LG
1973 Status = EFI_NOT_FOUND;\r
1974 goto Done;\r
7936fb6a 1975 }\r
1976\r
1977 Value = &Question->HiiValue;\r
1978 break;\r
1979\r
1980 case EFI_IFR_STRING_REF2_OP:\r
1981 //\r
1982 // Pop an expression from the expression stack\r
1983 //\r
1984 Status = PopExpression (Value);\r
1985 if (EFI_ERROR (Status)) {\r
2573712e 1986 goto Done;\r
7936fb6a 1987 }\r
1988\r
1989 //\r
1990 // Validate the expression value\r
1991 //\r
1992 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2573712e
LG
1993 Status = EFI_NOT_FOUND;\r
1994 goto Done;\r
7936fb6a 1995 }\r
1996\r
1997 Value->Type = EFI_IFR_TYPE_STRING;\r
1998 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
1999 if (StrPtr == NULL) {\r
2000 //\r
2001 // If String not exit, push an empty string\r
2002 //\r
2003 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2004 } else {\r
2005 Index = (UINT16) Value->Value.u64;\r
2006 Value->Value.string = Index;\r
f4113e1f 2007 FreePool (StrPtr);\r
7936fb6a 2008 }\r
2009 break;\r
2010\r
2011 case EFI_IFR_TO_BOOLEAN_OP:\r
2012 //\r
2013 // Pop an expression from the expression stack\r
2014 //\r
2015 Status = PopExpression (Value);\r
2016 if (EFI_ERROR (Status)) {\r
2573712e 2017 goto Done;\r
7936fb6a 2018 }\r
2019\r
2020 //\r
2021 // Convert an expression to a Boolean\r
2022 //\r
2023 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
2024 //\r
2025 // When converting from an unsigned integer, zero will be converted to\r
2026 // FALSE and any other value will be converted to TRUE.\r
2027 //\r
4140a663 2028 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);\r
7936fb6a 2029\r
2030 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2031 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2032 //\r
2033 // When converting from a string, if case-insensitive compare\r
2034 // with "true" is True, then push True. If a case-insensitive compare\r
2035 // with "false" is True, then push False.\r
2036 //\r
2037 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2038 if (StrPtr == NULL) {\r
2573712e
LG
2039 Status = EFI_INVALID_PARAMETER;\r
2040 goto Done;\r
7936fb6a 2041 }\r
2042\r
2043 if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){\r
2044 Value->Value.b = TRUE;\r
2045 } else {\r
2046 Value->Value.b = FALSE;\r
2047 }\r
f4113e1f 2048 FreePool (StrPtr);\r
7936fb6a 2049 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2050 }\r
2051 break;\r
2052\r
2053 case EFI_IFR_TO_STRING_OP:\r
2054 Status = IfrToString (FormSet, OpCode->Format, Value);\r
2055 break;\r
2056\r
2057 case EFI_IFR_TO_UINT_OP:\r
2058 Status = IfrToUint (FormSet, Value);\r
2059 break;\r
2060\r
2061 case EFI_IFR_TO_LOWER_OP:\r
2062 case EFI_IFR_TO_UPPER_OP:\r
2063 Status = InitializeUnicodeCollationProtocol ();\r
2064 if (EFI_ERROR (Status)) {\r
2573712e 2065 goto Done;\r
7936fb6a 2066 }\r
2067\r
2068 Status = PopExpression (Value);\r
2069 if (EFI_ERROR (Status)) {\r
2573712e 2070 goto Done;\r
7936fb6a 2071 }\r
2072\r
2073 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
2573712e
LG
2074 Status = EFI_UNSUPPORTED;\r
2075 goto Done;\r
7936fb6a 2076 }\r
2077\r
2078 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2079 if (StrPtr == NULL) {\r
2573712e
LG
2080 Status = EFI_NOT_FOUND;\r
2081 goto Done;\r
7936fb6a 2082 }\r
2083\r
2084 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
2085 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
2086 } else {\r
2087 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
2088 }\r
2089 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 2090 FreePool (StrPtr);\r
7936fb6a 2091 break;\r
2092\r
2093 case EFI_IFR_BITWISE_NOT_OP:\r
2094 //\r
2095 // Pop an expression from the expression stack\r
2096 //\r
2097 Status = PopExpression (Value);\r
2098 if (EFI_ERROR (Status)) {\r
2573712e 2099 goto Done;\r
7936fb6a 2100 }\r
2101 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2102 Status = EFI_INVALID_PARAMETER;\r
2103 goto Done;\r
7936fb6a 2104 }\r
2105\r
2106 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2107 Value->Value.u64 = ~Value->Value.u64;\r
2108 break;\r
2109\r
2573712e
LG
2110 case EFI_IFR_SET_OP:\r
2111 //\r
2112 // Pop an expression from the expression stack\r
2113 //\r
2114 Status = PopExpression (Value);\r
2115 if (EFI_ERROR (Status)) {\r
2116 goto Done;\r
2117 }\r
2118 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
2119 Data1.Value.b = FALSE;\r
2120 //\r
2121 // Set value to var storage buffer\r
2122 //\r
2123 if (OpCode->VarStorage != NULL) {\r
2124 switch (OpCode->VarStorage->Type) {\r
2125 case EFI_HII_VARSTORE_BUFFER:\r
2126 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
2127 Data1.Value.b = TRUE;\r
2128 break;\r
2129 case EFI_HII_VARSTORE_NAME_VALUE:\r
2130 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2131 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
2132 ASSERT (Value != NULL);\r
2133 //\r
2134 // Convert Buffer to Hex String\r
2135 //\r
2136 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
2137 StrPtr = NameValue;\r
2138 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
2139 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
2140 }\r
2141 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue);\r
2142 FreePool (NameValue);\r
2143 if (!EFI_ERROR (Status)) {\r
2144 Data1.Value.b = TRUE;\r
2145 }\r
2146 }\r
2147 break;\r
2148 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2149 Status = gRT->SetVariable (\r
2150 OpCode->ValueName,\r
2151 &OpCode->VarStorage->Guid,\r
2152 OpCode->VarStorage->Attributes,\r
2153 OpCode->ValueWidth,\r
2154 &Value->Value\r
2155 );\r
2156 if (!EFI_ERROR (Status)) {\r
2157 Data1.Value.b = TRUE;\r
2158 }\r
2159 break;\r
2160 default:\r
2161 //\r
2162 // Not recognize storage.\r
2163 //\r
2164 Status = EFI_UNSUPPORTED;\r
2165 goto Done;\r
2166 break;\r
2167 }\r
2168 } else {\r
2169 //\r
2170 // For Time/Date Data\r
2171 //\r
2172 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2173 //\r
2174 // Only support Data/Time data when storage doesn't exist.\r
2175 //\r
2176 Status = EFI_UNSUPPORTED;\r
2177 goto Done;\r
2178 }\r
2179 Status = gRT->GetTime (&EfiTime, NULL);\r
2180 if (!EFI_ERROR (Status)) {\r
2181 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2182 switch (OpCode->VarStoreInfo.VarOffset) {\r
2183 case 0x00:\r
2184 EfiTime.Year = Value->Value.u16;\r
2185 break;\r
2186 case 0x02:\r
2187 EfiTime.Month = Value->Value.u8;\r
2188 break;\r
2189 case 0x03:\r
2190 EfiTime.Day = Value->Value.u8;\r
2191 break;\r
2192 default:\r
2193 //\r
2194 // Invalid Date field.\r
2195 //\r
2196 Status = EFI_INVALID_PARAMETER;\r
2197 goto Done;\r
2198 }\r
2199 } else {\r
2200 switch (OpCode->VarStoreInfo.VarOffset) {\r
2201 case 0x00:\r
2202 EfiTime.Hour = Value->Value.u8;\r
2203 break;\r
2204 case 0x01:\r
2205 EfiTime.Minute = Value->Value.u8;\r
2206 break;\r
2207 case 0x02:\r
2208 EfiTime.Second = Value->Value.u8;\r
2209 break;\r
2210 default:\r
2211 //\r
2212 // Invalid Time field.\r
2213 //\r
2214 Status = EFI_INVALID_PARAMETER;\r
2215 goto Done;\r
2216 }\r
2217 }\r
2218 Status = gRT->SetTime (&EfiTime);\r
2219 if (!EFI_ERROR (Status)) {\r
2220 Data1.Value.b = TRUE;\r
2221 }\r
2222 }\r
2223 }\r
2224 Value = &Data1;\r
2225 break;\r
2226\r
7936fb6a 2227 //\r
2228 // binary-op\r
2229 //\r
2230 case EFI_IFR_ADD_OP:\r
2231 case EFI_IFR_SUBTRACT_OP:\r
2232 case EFI_IFR_MULTIPLY_OP:\r
2233 case EFI_IFR_DIVIDE_OP:\r
2234 case EFI_IFR_MODULO_OP:\r
2235 case EFI_IFR_BITWISE_AND_OP:\r
2236 case EFI_IFR_BITWISE_OR_OP:\r
2237 case EFI_IFR_SHIFT_LEFT_OP:\r
2238 case EFI_IFR_SHIFT_RIGHT_OP:\r
2239 //\r
2240 // Pop an expression from the expression stack\r
2241 //\r
2242 Status = PopExpression (&Data2);\r
2243 if (EFI_ERROR (Status)) {\r
2573712e 2244 goto Done;\r
7936fb6a 2245 }\r
2246 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2247 Status = EFI_INVALID_PARAMETER;\r
2248 goto Done;\r
7936fb6a 2249 }\r
2250\r
2251 //\r
2252 // Pop another expression from the expression stack\r
2253 //\r
2254 Status = PopExpression (&Data1);\r
2255 if (EFI_ERROR (Status)) {\r
2573712e 2256 goto Done;\r
7936fb6a 2257 }\r
2258 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
2573712e
LG
2259 Status = EFI_INVALID_PARAMETER;\r
2260 goto Done;\r
7936fb6a 2261 }\r
2262\r
2263 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2264\r
2265 switch (OpCode->Operand) {\r
2266 case EFI_IFR_ADD_OP:\r
2267 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
2268 break;\r
2269\r
2270 case EFI_IFR_SUBTRACT_OP:\r
2271 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
2272 break;\r
2273\r
2274 case EFI_IFR_MULTIPLY_OP:\r
2275 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2276 break;\r
2277\r
2278 case EFI_IFR_DIVIDE_OP:\r
2279 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
2280 break;\r
2281\r
2282 case EFI_IFR_MODULO_OP:\r
2283 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
2284 Value->Value.u64 = TempValue;\r
2285 break;\r
2286\r
2287 case EFI_IFR_BITWISE_AND_OP:\r
2288 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
2289 break;\r
2290\r
2291 case EFI_IFR_BITWISE_OR_OP:\r
2292 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
2293 break;\r
2294\r
2295 case EFI_IFR_SHIFT_LEFT_OP:\r
2296 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2297 break;\r
2298\r
2299 case EFI_IFR_SHIFT_RIGHT_OP:\r
2300 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
2301 break;\r
2302\r
2303 default:\r
2304 break;\r
2305 }\r
2306 break;\r
2307\r
2308 case EFI_IFR_AND_OP:\r
2309 case EFI_IFR_OR_OP:\r
2310 //\r
2311 // Two Boolean operator\r
2312 //\r
2313 Status = PopExpression (&Data2);\r
2314 if (EFI_ERROR (Status)) {\r
2573712e 2315 goto Done;\r
7936fb6a 2316 }\r
2317 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2318 Status = EFI_INVALID_PARAMETER;\r
2319 goto Done;\r
7936fb6a 2320 }\r
2321\r
2322 //\r
2323 // Pop another expression from the expression stack\r
2324 //\r
2325 Status = PopExpression (&Data1);\r
2326 if (EFI_ERROR (Status)) {\r
2573712e 2327 goto Done;\r
7936fb6a 2328 }\r
2329 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2330 Status = EFI_INVALID_PARAMETER;\r
2331 goto Done;\r
7936fb6a 2332 }\r
2333\r
2334 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
2335 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
2336 } else {\r
2337 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
2338 }\r
2339 break;\r
2340\r
2341 case EFI_IFR_EQUAL_OP:\r
2342 case EFI_IFR_NOT_EQUAL_OP:\r
2343 case EFI_IFR_GREATER_EQUAL_OP:\r
2344 case EFI_IFR_GREATER_THAN_OP:\r
2345 case EFI_IFR_LESS_EQUAL_OP:\r
2346 case EFI_IFR_LESS_THAN_OP:\r
2347 //\r
2348 // Compare two integer, string, boolean or date/time\r
2349 //\r
2350 Status = PopExpression (&Data2);\r
2351 if (EFI_ERROR (Status)) {\r
2573712e 2352 goto Done;\r
7936fb6a 2353 }\r
2354 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
2573712e
LG
2355 Status = EFI_INVALID_PARAMETER;\r
2356 goto Done;\r
7936fb6a 2357 }\r
2358\r
2359 //\r
2360 // Pop another expression from the expression stack\r
2361 //\r
2362 Status = PopExpression (&Data1);\r
2363 if (EFI_ERROR (Status)) {\r
2573712e 2364 goto Done;\r
7936fb6a 2365 }\r
2366\r
2367 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
2368 if (Result == EFI_INVALID_PARAMETER) {\r
2573712e
LG
2369 Status = EFI_INVALID_PARAMETER;\r
2370 goto Done;\r
7936fb6a 2371 }\r
2372\r
2373 switch (OpCode->Operand) {\r
2374 case EFI_IFR_EQUAL_OP:\r
2375 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2376 break;\r
2377\r
2378 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 2379 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 2380 break;\r
2381\r
2382 case EFI_IFR_GREATER_EQUAL_OP:\r
2383 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
2384 break;\r
2385\r
2386 case EFI_IFR_GREATER_THAN_OP:\r
2387 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
2388 break;\r
2389\r
2390 case EFI_IFR_LESS_EQUAL_OP:\r
2391 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
2392 break;\r
2393\r
2394 case EFI_IFR_LESS_THAN_OP:\r
2395 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
2396 break;\r
2397\r
2398 default:\r
2399 break;\r
2400 }\r
2401 break;\r
2402\r
2403 case EFI_IFR_MATCH_OP:\r
2404 Status = IfrMatch (FormSet, Value);\r
2405 break;\r
2406\r
2407 case EFI_IFR_CATENATE_OP:\r
2408 Status = IfrCatenate (FormSet, Value);\r
2409 break;\r
2410\r
2411 //\r
2412 // ternary-op\r
2413 //\r
2414 case EFI_IFR_CONDITIONAL_OP:\r
2415 //\r
2416 // Pop third expression from the expression stack\r
2417 //\r
2418 Status = PopExpression (&Data3);\r
2419 if (EFI_ERROR (Status)) {\r
2573712e 2420 goto Done;\r
7936fb6a 2421 }\r
2422\r
2423 //\r
2424 // Pop second expression from the expression stack\r
2425 //\r
2426 Status = PopExpression (&Data2);\r
2427 if (EFI_ERROR (Status)) {\r
2573712e 2428 goto Done;\r
7936fb6a 2429 }\r
2430\r
2431 //\r
2432 // Pop first expression from the expression stack\r
2433 //\r
2434 Status = PopExpression (&Data1);\r
2435 if (EFI_ERROR (Status)) {\r
2573712e 2436 goto Done;\r
7936fb6a 2437 }\r
2438 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2573712e
LG
2439 Status = EFI_INVALID_PARAMETER;\r
2440 goto Done;\r
7936fb6a 2441 }\r
2442\r
2443 if (Data1.Value.b) {\r
2444 Value = &Data3;\r
2445 } else {\r
2446 Value = &Data2;\r
2447 }\r
2448 break;\r
2449\r
2450 case EFI_IFR_FIND_OP:\r
2451 Status = IfrFind (FormSet, OpCode->Format, Value);\r
2452 break;\r
2453\r
2454 case EFI_IFR_MID_OP:\r
2455 Status = IfrMid (FormSet, Value);\r
2456 break;\r
2457\r
2458 case EFI_IFR_TOKEN_OP:\r
2459 Status = IfrToken (FormSet, Value);\r
2460 break;\r
2461\r
2462 case EFI_IFR_SPAN_OP:\r
2463 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
2464 break;\r
2465\r
2573712e
LG
2466 case EFI_IFR_MAP_OP:\r
2467 //\r
2468 // Pop the check value\r
2469 //\r
2470 Status = PopExpression (&Data1);\r
2471 if (EFI_ERROR (Status)) {\r
2472 goto Done;\r
2473 }\r
2474 //\r
2475 // Check MapExpression list is valid.\r
2476 //\r
2477 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
2478 Status = EFI_INVALID_PARAMETER;\r
2479 goto Done;\r
2480 }\r
2481 //\r
2482 // Go through map expression list.\r
2483 //\r
2484 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
2485 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2486 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
2487 //\r
2488 // Evaluate the first expression in this pair.\r
2489 //\r
2490 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
2491 if (EFI_ERROR (Status)) {\r
2492 goto Done;\r
2493 }\r
2494 //\r
2495 // Compare the expression value with current value\r
2496 //\r
2497 if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) {\r
2498 //\r
2499 // Try get the map value.\r
2500 //\r
2501 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2502 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2503 Status = EFI_INVALID_PARAMETER;\r
2504 goto Done;\r
2505 }\r
2506 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
2507 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
2508 if (EFI_ERROR (Status)) {\r
2509 goto Done;\r
2510 }\r
2511 Value = &SubExpression->Result;\r
2512 break;\r
2513 }\r
2514 //\r
2515 // Skip the second expression on this pair.\r
2516 //\r
2517 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2518 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2519 Status = EFI_INVALID_PARAMETER;\r
2520 goto Done;\r
2521 }\r
2522 //\r
2523 // Goto the first expression on next pair.\r
2524 //\r
2525 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
2526 }\r
2527\r
2528 //\r
2529 // No map value is found.\r
2530 //\r
2531 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
2532 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2533 Value->Value.u8 = 0;\r
2534 }\r
2535 break;\r
2536\r
7936fb6a 2537 default:\r
2538 break;\r
2539 }\r
2540 if (EFI_ERROR (Status)) {\r
2573712e 2541 goto Done;\r
7936fb6a 2542 }\r
2543\r
2544 Status = PushExpression (Value);\r
2545 if (EFI_ERROR (Status)) {\r
2573712e 2546 goto Done;\r
7936fb6a 2547 }\r
2548 }\r
2549\r
2550 //\r
2551 // Pop the final result from expression stack\r
2552 //\r
2553 Value = &Data1;\r
2554 Status = PopExpression (Value);\r
2555 if (EFI_ERROR (Status)) {\r
2573712e 2556 goto Done;\r
7936fb6a 2557 }\r
2558\r
2559 //\r
2560 // After evaluating an expression, there should be only one value left on the expression stack\r
2561 //\r
2562 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 2563 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 2564 }\r
2565\r
2573712e
LG
2566Done:\r
2567 RestoreExpressionEvaluationStackOffset (StackOffset);\r
2568 if (!EFI_ERROR (Status)) {\r
2569 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
2570 }\r
7936fb6a 2571\r
2573712e 2572 return Status;\r
7936fb6a 2573}\r