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