]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
The consumer for smbios recorder should *not* make assumption the SMBIOS structure...
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
cbf73e50 4Copyright (c) 2007 - 2009, Intel Corporation\r
7936fb6a 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
7936fb6a 15#include "Setup.h"\r
16\r
17//\r
18// Global stack used to evaluate boolean expresions\r
19//\r
20EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
21EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
22EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
23\r
24EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
25EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
26EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
27\r
28//\r
29// Unicode collation protocol interface\r
30//\r
31EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
cbf73e50 32EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
7936fb6a 33\r
34/**\r
35 Grow size of the stack.\r
36\r
37 This is an internal function.\r
38\r
39 @param Stack On input: old stack; On output: new stack\r
40 @param StackPtr On input: old stack pointer; On output: new stack\r
41 pointer\r
42 @param StackEnd On input: old stack end; On output: new stack end\r
43\r
44 @retval EFI_SUCCESS Grow stack success.\r
45 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
46\r
47**/\r
48EFI_STATUS\r
49GrowStack (\r
50 IN OUT EFI_HII_VALUE **Stack,\r
51 IN OUT EFI_HII_VALUE **StackPtr,\r
52 IN OUT EFI_HII_VALUE **StackEnd\r
53 )\r
54{\r
55 UINTN Size;\r
56 EFI_HII_VALUE *NewStack;\r
57\r
58 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
59 if (*StackPtr != NULL) {\r
60 Size = Size + (*StackEnd - *Stack);\r
61 }\r
62\r
63 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
64 if (NewStack == NULL) {\r
65 return EFI_OUT_OF_RESOURCES;\r
66 }\r
67\r
68 if (*StackPtr != NULL) {\r
69 //\r
70 // Copy from Old Stack to the New Stack\r
71 //\r
72 CopyMem (\r
73 NewStack,\r
74 *Stack,\r
75 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
76 );\r
77\r
78 //\r
79 // Free The Old Stack\r
80 //\r
f4113e1f 81 FreePool (*Stack);\r
7936fb6a 82 }\r
83\r
84 //\r
85 // Make the Stack pointer point to the old data in the new stack\r
86 //\r
87 *StackPtr = NewStack + (*StackPtr - *Stack);\r
88 *Stack = NewStack;\r
89 *StackEnd = NewStack + Size;\r
90\r
91 return EFI_SUCCESS;\r
92}\r
93\r
94\r
95/**\r
96 Push an element onto the Boolean Stack.\r
97\r
98 @param Stack On input: old stack; On output: new stack\r
99 @param StackPtr On input: old stack pointer; On output: new stack\r
100 pointer\r
101 @param StackEnd On input: old stack end; On output: new stack end\r
102 @param Data Data to push.\r
103\r
104 @retval EFI_SUCCESS Push stack success.\r
105\r
106**/\r
107EFI_STATUS\r
108PushStack (\r
109 IN OUT EFI_HII_VALUE **Stack,\r
110 IN OUT EFI_HII_VALUE **StackPtr,\r
111 IN OUT EFI_HII_VALUE **StackEnd,\r
112 IN EFI_HII_VALUE *Data\r
113 )\r
114{\r
115 EFI_STATUS Status;\r
116\r
117 //\r
118 // Check for a stack overflow condition\r
119 //\r
120 if (*StackPtr >= *StackEnd) {\r
121 //\r
122 // Grow the stack\r
123 //\r
124 Status = GrowStack (Stack, StackPtr, StackEnd);\r
125 if (EFI_ERROR (Status)) {\r
126 return Status;\r
127 }\r
128 }\r
129\r
130 //\r
131 // Push the item onto the stack\r
132 //\r
133 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
134 *StackPtr = *StackPtr + 1;\r
135\r
136 return EFI_SUCCESS;\r
137}\r
138\r
139\r
140/**\r
141 Pop an element from the stack.\r
142\r
143 @param Stack On input: old stack; On output: new stack\r
144 @param StackPtr On input: old stack pointer; On output: new stack\r
145 pointer\r
146 @param StackEnd On input: old stack end; On output: new stack end\r
147 @param Data Data to pop.\r
148\r
149 @retval EFI_SUCCESS The value was popped onto the stack.\r
150 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
151\r
152**/\r
153EFI_STATUS\r
154PopStack (\r
155 IN OUT EFI_HII_VALUE **Stack,\r
156 IN OUT EFI_HII_VALUE **StackPtr,\r
157 IN OUT EFI_HII_VALUE **StackEnd,\r
158 OUT EFI_HII_VALUE *Data\r
159 )\r
160{\r
161 //\r
162 // Check for a stack underflow condition\r
163 //\r
164 if (*StackPtr == *Stack) {\r
165 return EFI_ACCESS_DENIED;\r
166 }\r
167\r
168 //\r
169 // Pop the item off the stack\r
170 //\r
171 *StackPtr = *StackPtr - 1;\r
172 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
173 return EFI_SUCCESS;\r
174}\r
175\r
176\r
177/**\r
178 Reset stack pointer to begin of the stack.\r
179\r
180**/\r
181VOID\r
182ResetScopeStack (\r
183 VOID\r
184 )\r
185{\r
186 mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
187}\r
188\r
189\r
190/**\r
191 Push an Operand onto the Stack\r
192\r
193 @param Operand Operand to push.\r
194\r
195 @retval EFI_SUCCESS The value was pushed onto the stack.\r
196 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
197 stack.\r
198\r
199**/\r
200EFI_STATUS\r
201PushScope (\r
202 IN UINT8 Operand\r
203 )\r
204{\r
205 EFI_HII_VALUE Data;\r
206\r
207 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
208 Data.Value.u8 = Operand;\r
209\r
210 return PushStack (\r
211 &mOpCodeScopeStack,\r
212 &mOpCodeScopeStackPointer,\r
213 &mOpCodeScopeStackEnd,\r
214 &Data\r
215 );\r
216}\r
217\r
218\r
219/**\r
220 Pop an Operand from the Stack\r
221\r
222 @param Operand Operand to pop.\r
223\r
224 @retval EFI_SUCCESS The value was pushed onto the stack.\r
225 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
226 stack.\r
227\r
228**/\r
229EFI_STATUS\r
230PopScope (\r
231 OUT UINT8 *Operand\r
232 )\r
233{\r
234 EFI_STATUS Status;\r
235 EFI_HII_VALUE Data;\r
236\r
237 Status = PopStack (\r
238 &mOpCodeScopeStack,\r
239 &mOpCodeScopeStackPointer,\r
240 &mOpCodeScopeStackEnd,\r
241 &Data\r
242 );\r
243\r
244 *Operand = Data.Value.u8;\r
245\r
246 return Status;\r
247}\r
248\r
249\r
250/**\r
251 Reset stack pointer to begin of the stack.\r
252\r
253**/\r
254VOID\r
255ResetExpressionStack (\r
256 VOID\r
257 )\r
258{\r
259 mExpressionEvaluationStackPointer = mExpressionEvaluationStack;\r
260}\r
261\r
262\r
263/**\r
264 Push an Expression value onto the Stack\r
265\r
266 @param Value Expression value to push.\r
267\r
268 @retval EFI_SUCCESS The value was pushed onto the stack.\r
269 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
270 stack.\r
271\r
272**/\r
273EFI_STATUS\r
274PushExpression (\r
275 IN EFI_HII_VALUE *Value\r
276 )\r
277{\r
278 return PushStack (\r
279 &mExpressionEvaluationStack,\r
280 &mExpressionEvaluationStackPointer,\r
281 &mExpressionEvaluationStackEnd,\r
282 Value\r
283 );\r
284}\r
285\r
286\r
287/**\r
288 Pop an Expression value from the stack.\r
289\r
290 @param Value Expression value to pop.\r
291\r
292 @retval EFI_SUCCESS The value was popped onto the stack.\r
293 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
294\r
295**/\r
296EFI_STATUS\r
297PopExpression (\r
298 OUT EFI_HII_VALUE *Value\r
299 )\r
300{\r
301 return PopStack (\r
302 &mExpressionEvaluationStack,\r
303 &mExpressionEvaluationStackPointer,\r
304 &mExpressionEvaluationStackEnd,\r
305 Value\r
306 );\r
307}\r
308\r
309\r
310/**\r
311 Get Form given its FormId.\r
312\r
313 @param FormSet The formset which contains this form.\r
314 @param FormId Id of this form.\r
315\r
316 @retval Pointer The form.\r
317 @retval NULL Specified Form is not found in the formset.\r
318\r
319**/\r
320FORM_BROWSER_FORM *\r
321IdToForm (\r
322 IN FORM_BROWSER_FORMSET *FormSet,\r
323 IN UINT16 FormId\r
324)\r
325{\r
326 LIST_ENTRY *Link;\r
327 FORM_BROWSER_FORM *Form;\r
328\r
329 Link = GetFirstNode (&FormSet->FormListHead);\r
330 while (!IsNull (&FormSet->FormListHead, Link)) {\r
331 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
332\r
333 if (Form->FormId == FormId) {\r
334 return Form;\r
335 }\r
336\r
337 Link = GetNextNode (&FormSet->FormListHead, Link);\r
338 }\r
339\r
340 return NULL;\r
341}\r
342\r
343\r
344/**\r
345 Search a Question in Form scope using its QuestionId.\r
346\r
347 @param Form The form which contains this Question.\r
348 @param QuestionId Id of this Question.\r
349\r
350 @retval Pointer The Question.\r
351 @retval NULL Specified Question not found in the form.\r
352\r
353**/\r
354FORM_BROWSER_STATEMENT *\r
355IdToQuestion2 (\r
356 IN FORM_BROWSER_FORM *Form,\r
357 IN UINT16 QuestionId\r
358 )\r
359{\r
360 LIST_ENTRY *Link;\r
361 FORM_BROWSER_STATEMENT *Question;\r
362\r
363 if (QuestionId == 0) {\r
364 //\r
365 // The value of zero is reserved\r
366 //\r
367 return NULL;\r
368 }\r
369\r
370 Link = GetFirstNode (&Form->StatementListHead);\r
371 while (!IsNull (&Form->StatementListHead, Link)) {\r
372 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
373\r
374 if (Question->QuestionId == QuestionId) {\r
375 return Question;\r
376 }\r
377\r
378 Link = GetNextNode (&Form->StatementListHead, Link);\r
379 }\r
380\r
381 return NULL;\r
382}\r
383\r
384\r
385/**\r
386 Search a Question in Formset scope using its QuestionId.\r
387\r
388 @param FormSet The formset which contains this form.\r
389 @param Form The form which contains this Question.\r
390 @param QuestionId Id of this Question.\r
391\r
392 @retval Pointer The Question.\r
393 @retval NULL Specified Question not found in the form.\r
394\r
395**/\r
396FORM_BROWSER_STATEMENT *\r
397IdToQuestion (\r
398 IN FORM_BROWSER_FORMSET *FormSet,\r
399 IN FORM_BROWSER_FORM *Form,\r
400 IN UINT16 QuestionId\r
401 )\r
402{\r
403 LIST_ENTRY *Link;\r
404 FORM_BROWSER_STATEMENT *Question;\r
405\r
406 //\r
407 // Search in the form scope first\r
408 //\r
409 Question = IdToQuestion2 (Form, QuestionId);\r
410 if (Question != NULL) {\r
411 return Question;\r
412 }\r
413\r
414 //\r
415 // Search in the formset scope\r
416 //\r
417 Link = GetFirstNode (&FormSet->FormListHead);\r
418 while (!IsNull (&FormSet->FormListHead, Link)) {\r
419 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
420\r
421 Question = IdToQuestion2 (Form, QuestionId);\r
422 if (Question != NULL) {\r
8d00a0f1 423 //\r
424 // EFI variable storage may be updated by Callback() asynchronous,\r
425 // to keep synchronous, always reload the Question Value.\r
426 //\r
427 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
428 GetQuestionValue (FormSet, Form, Question, FALSE);\r
429 }\r
430\r
7936fb6a 431 return Question;\r
432 }\r
433\r
434 Link = GetNextNode (&FormSet->FormListHead, Link);\r
435 }\r
436\r
437 return NULL;\r
438}\r
439\r
440\r
441/**\r
442 Get Expression given its RuleId.\r
443\r
444 @param Form The form which contains this Expression.\r
445 @param RuleId Id of this Expression.\r
446\r
447 @retval Pointer The Expression.\r
448 @retval NULL Specified Expression not found in the form.\r
449\r
450**/\r
451FORM_EXPRESSION *\r
452RuleIdToExpression (\r
453 IN FORM_BROWSER_FORM *Form,\r
454 IN UINT8 RuleId\r
455 )\r
456{\r
457 LIST_ENTRY *Link;\r
458 FORM_EXPRESSION *Expression;\r
459\r
460 Link = GetFirstNode (&Form->ExpressionListHead);\r
461 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
462 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
463\r
464 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
465 return Expression;\r
466 }\r
467\r
468 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
469 }\r
470\r
471 return NULL;\r
472}\r
473\r
474\r
475/**\r
476 Locate the Unicode Collation Protocol interface for later use.\r
477\r
478 @retval EFI_SUCCESS Protocol interface initialize success.\r
479 @retval Other Protocol interface initialize failed.\r
480\r
481**/\r
482EFI_STATUS\r
483InitializeUnicodeCollationProtocol (\r
484 VOID\r
485 )\r
486{\r
487 EFI_STATUS Status;\r
488\r
489 if (mUnicodeCollation != NULL) {\r
490 return EFI_SUCCESS;\r
491 }\r
492\r
493 //\r
494 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
495 // instances first and then select one which support English language.\r
496 // Current implementation just pick the first instance.\r
497 //\r
498 Status = gBS->LocateProtocol (\r
499 &gEfiUnicodeCollation2ProtocolGuid,\r
500 NULL,\r
501 (VOID **) &mUnicodeCollation\r
502 );\r
503 return Status;\r
504}\r
505\r
506/**\r
507 Convert the input Unicode character to upper.\r
508\r
509 @param String Th Unicode character to be converted.\r
510\r
511**/\r
512VOID\r
513IfrStrToUpper (\r
8b0fc5c1 514 IN CHAR16 *String\r
7936fb6a 515 )\r
516{\r
517 while (*String != 0) {\r
518 if ((*String >= 'a') && (*String <= 'z')) {\r
519 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
520 }\r
521 String++;\r
522 }\r
523}\r
524\r
525\r
526/**\r
527 Evaluate opcode EFI_IFR_TO_STRING.\r
528\r
529 @param FormSet Formset which contains this opcode.\r
530 @param Format String format in EFI_IFR_TO_STRING.\r
531 @param Result Evaluation result for this opcode.\r
532\r
533 @retval EFI_SUCCESS Opcode evaluation success.\r
534 @retval Other Opcode evaluation failed.\r
535\r
536**/\r
537EFI_STATUS\r
538IfrToString (\r
539 IN FORM_BROWSER_FORMSET *FormSet,\r
540 IN UINT8 Format,\r
541 OUT EFI_HII_VALUE *Result\r
542 )\r
543{\r
544 EFI_STATUS Status;\r
545 EFI_HII_VALUE Value;\r
546 CHAR16 *String;\r
547 CHAR16 *PrintFormat;\r
548 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
549 UINTN BufferSize;\r
550\r
551 Status = PopExpression (&Value);\r
552 if (EFI_ERROR (Status)) {\r
553 return Status;\r
554 }\r
555\r
556 switch (Value.Type) {\r
557 case EFI_IFR_TYPE_NUM_SIZE_8:\r
558 case EFI_IFR_TYPE_NUM_SIZE_16:\r
559 case EFI_IFR_TYPE_NUM_SIZE_32:\r
560 case EFI_IFR_TYPE_NUM_SIZE_64:\r
561 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
562 switch (Format) {\r
563 case EFI_IFR_STRING_UNSIGNED_DEC:\r
564 case EFI_IFR_STRING_SIGNED_DEC:\r
565 PrintFormat = L"%ld";\r
566 break;\r
567\r
568 case EFI_IFR_STRING_LOWERCASE_HEX:\r
569 PrintFormat = L"%lx";\r
570 break;\r
571\r
572 case EFI_IFR_STRING_UPPERCASE_HEX:\r
573 PrintFormat = L"%lX";\r
574 break;\r
575\r
576 default:\r
577 return EFI_UNSUPPORTED;\r
578 }\r
579 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
580 String = Buffer;\r
581 break;\r
582\r
583 case EFI_IFR_TYPE_STRING:\r
584 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
585 return EFI_SUCCESS;\r
586\r
587 case EFI_IFR_TYPE_BOOLEAN:\r
588 String = (Value.Value.b) ? L"True" : L"False";\r
589 break;\r
590\r
591 default:\r
592 return EFI_UNSUPPORTED;\r
593 }\r
594\r
595 Result->Type = EFI_IFR_TYPE_STRING;\r
596 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
597 return EFI_SUCCESS;\r
598}\r
599\r
600\r
601/**\r
602 Evaluate opcode EFI_IFR_TO_UINT.\r
603\r
604 @param FormSet Formset which contains this opcode.\r
605 @param Result Evaluation result for this opcode.\r
606\r
607 @retval EFI_SUCCESS Opcode evaluation success.\r
608 @retval Other Opcode evaluation failed.\r
609\r
610**/\r
611EFI_STATUS\r
612IfrToUint (\r
613 IN FORM_BROWSER_FORMSET *FormSet,\r
614 OUT EFI_HII_VALUE *Result\r
615 )\r
616{\r
617 EFI_STATUS Status;\r
618 EFI_HII_VALUE Value;\r
619 CHAR16 *String;\r
620 CHAR16 *StringPtr;\r
7936fb6a 621\r
622 Status = PopExpression (&Value);\r
623 if (EFI_ERROR (Status)) {\r
624 return Status;\r
625 }\r
626\r
627 if (Value.Type >= EFI_IFR_TYPE_OTHER) {\r
628 return EFI_UNSUPPORTED;\r
629 }\r
630\r
631 Status = EFI_SUCCESS;\r
632 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
633 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
634 if (String == NULL) {\r
635 return EFI_NOT_FOUND;\r
636 }\r
8b0fc5c1 637\r
7936fb6a 638 IfrStrToUpper (String);\r
639 StringPtr = StrStr (String, L"0X");\r
640 if (StringPtr != NULL) {\r
641 //\r
642 // Hex string\r
643 //\r
ac7e320c 644 Result->Value.u64 = StrHexToUint64 (String);\r
7936fb6a 645 } else {\r
646 //\r
ac7e320c 647 // decimal string\r
7936fb6a 648 //\r
ac7e320c 649 Result->Value.u64 = StrDecimalToUint64 (String);\r
7936fb6a 650 }\r
f4113e1f 651 FreePool (String);\r
7936fb6a 652 } else {\r
653 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
654 }\r
655\r
656 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
657 return Status;\r
658}\r
659\r
660\r
661/**\r
662 Evaluate opcode EFI_IFR_CATENATE.\r
663\r
664 @param FormSet Formset which contains this opcode.\r
665 @param Result Evaluation result for this opcode.\r
666\r
667 @retval EFI_SUCCESS Opcode evaluation success.\r
668 @retval Other Opcode evaluation failed.\r
669\r
670**/\r
671EFI_STATUS\r
672IfrCatenate (\r
673 IN FORM_BROWSER_FORMSET *FormSet,\r
674 OUT EFI_HII_VALUE *Result\r
675 )\r
676{\r
677 EFI_STATUS Status;\r
678 EFI_HII_VALUE Value;\r
679 CHAR16 *String[2];\r
680 UINTN Index;\r
681 CHAR16 *StringPtr;\r
682 UINTN Size;\r
683\r
684 //\r
685 // String[0] - The second string\r
686 // String[1] - The first string\r
687 //\r
688 String[0] = NULL;\r
689 String[1] = NULL;\r
690 StringPtr = NULL;\r
691 Status = EFI_SUCCESS;\r
692\r
693 for (Index = 0; Index < 2; Index++) {\r
694 Status = PopExpression (&Value);\r
695 if (EFI_ERROR (Status)) {\r
696 goto Done;\r
697 }\r
698\r
699 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
700 Status = EFI_UNSUPPORTED;\r
701 goto Done;\r
702 }\r
703\r
704 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 705 if (String[Index] == NULL) {\r
7936fb6a 706 Status = EFI_NOT_FOUND;\r
707 goto Done;\r
708 }\r
709 }\r
710\r
711 Size = StrSize (String[0]);\r
712 StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
713 ASSERT (StringPtr != NULL);\r
714 StrCpy (StringPtr, String[1]);\r
715 StrCat (StringPtr, String[0]);\r
716\r
717 Result->Type = EFI_IFR_TYPE_STRING;\r
718 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
719\r
720Done:\r
676df92c 721 if (String[0] != NULL) {\r
722 FreePool (String[0]);\r
723 }\r
724 if (String[1] != NULL) {\r
725 FreePool (String[1]);\r
8b0fc5c1 726 }\r
676df92c 727 if (StringPtr != NULL) {\r
728 FreePool (StringPtr);\r
729 }\r
7936fb6a 730\r
731 return Status;\r
732}\r
733\r
734\r
735/**\r
736 Evaluate opcode EFI_IFR_MATCH.\r
737\r
738 @param FormSet Formset which contains this opcode.\r
739 @param Result Evaluation result for this opcode.\r
740\r
741 @retval EFI_SUCCESS Opcode evaluation success.\r
742 @retval Other Opcode evaluation failed.\r
743\r
744**/\r
745EFI_STATUS\r
746IfrMatch (\r
747 IN FORM_BROWSER_FORMSET *FormSet,\r
748 OUT EFI_HII_VALUE *Result\r
749 )\r
750{\r
751 EFI_STATUS Status;\r
752 EFI_HII_VALUE Value;\r
753 CHAR16 *String[2];\r
754 UINTN Index;\r
755\r
756 //\r
757 // String[0] - The string to search\r
758 // String[1] - pattern\r
759 //\r
760 String[0] = NULL;\r
761 String[1] = NULL;\r
762 Status = EFI_SUCCESS;\r
763 for (Index = 0; Index < 2; Index++) {\r
764 Status = PopExpression (&Value);\r
765 if (EFI_ERROR (Status)) {\r
766 goto Done;\r
767 }\r
768\r
769 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
770 Status = EFI_UNSUPPORTED;\r
771 goto Done;\r
772 }\r
773\r
774 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
bc166db3 775 if (String [Index] == NULL) {\r
7936fb6a 776 Status = EFI_NOT_FOUND;\r
777 goto Done;\r
778 }\r
779 }\r
780\r
781 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
782 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
783\r
784Done:\r
676df92c 785 if (String[0] != NULL) {\r
786 FreePool (String[0]);\r
787 }\r
788 if (String[1] != NULL) {\r
789 FreePool (String[1]);\r
8b0fc5c1 790 }\r
7936fb6a 791\r
792 return Status;\r
793}\r
794\r
795\r
796/**\r
797 Evaluate opcode EFI_IFR_FIND.\r
798\r
799 @param FormSet Formset which contains this opcode.\r
800 @param Format Case sensitive or insensitive.\r
801 @param Result Evaluation result for this opcode.\r
802\r
803 @retval EFI_SUCCESS Opcode evaluation success.\r
804 @retval Other Opcode evaluation failed.\r
805\r
806**/\r
807EFI_STATUS\r
808IfrFind (\r
809 IN FORM_BROWSER_FORMSET *FormSet,\r
810 IN UINT8 Format,\r
811 OUT EFI_HII_VALUE *Result\r
812 )\r
813{\r
814 EFI_STATUS Status;\r
815 EFI_HII_VALUE Value;\r
816 CHAR16 *String[2];\r
817 UINTN Base;\r
818 CHAR16 *StringPtr;\r
819 UINTN Index;\r
820\r
821 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
822 return EFI_UNSUPPORTED;\r
823 }\r
824\r
825 Status = PopExpression (&Value);\r
826 if (EFI_ERROR (Status)) {\r
827 return Status;\r
828 }\r
829 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
830 return EFI_UNSUPPORTED;\r
831 }\r
832 Base = (UINTN) Value.Value.u64;\r
833\r
834 //\r
835 // String[0] - sub-string\r
836 // String[1] - The string to search\r
837 //\r
838 String[0] = NULL;\r
839 String[1] = NULL;\r
840 for (Index = 0; Index < 2; Index++) {\r
841 Status = PopExpression (&Value);\r
842 if (EFI_ERROR (Status)) {\r
843 goto Done;\r
844 }\r
845\r
846 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
847 Status = EFI_UNSUPPORTED;\r
848 goto Done;\r
849 }\r
850\r
851 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 852 if (String[Index] == NULL) {\r
7936fb6a 853 Status = EFI_NOT_FOUND;\r
854 goto Done;\r
855 }\r
856\r
857 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
858 //\r
859 // Case insensitive, convert both string to upper case\r
860 //\r
861 IfrStrToUpper (String[Index]);\r
862 }\r
863 }\r
864\r
865 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
866 if (Base >= StrLen (String[1])) {\r
867 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
868 } else {\r
869 StringPtr = StrStr (String[1] + Base, String[0]);\r
870 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
871 }\r
872\r
873Done:\r
676df92c 874 if (String[0] != NULL) {\r
875 FreePool (String[0]);\r
876 }\r
877 if (String[1] != NULL) {\r
878 FreePool (String[1]);\r
8b0fc5c1 879 }\r
7936fb6a 880\r
881 return Status;\r
882}\r
883\r
884\r
885/**\r
886 Evaluate opcode EFI_IFR_MID.\r
887\r
888 @param FormSet Formset which contains this opcode.\r
889 @param Result Evaluation result for this opcode.\r
890\r
891 @retval EFI_SUCCESS Opcode evaluation success.\r
892 @retval Other Opcode evaluation failed.\r
893\r
894**/\r
895EFI_STATUS\r
896IfrMid (\r
897 IN FORM_BROWSER_FORMSET *FormSet,\r
898 OUT EFI_HII_VALUE *Result\r
899 )\r
900{\r
901 EFI_STATUS Status;\r
902 EFI_HII_VALUE Value;\r
903 CHAR16 *String;\r
904 UINTN Base;\r
905 UINTN Length;\r
906 CHAR16 *SubString;\r
907\r
908 Status = PopExpression (&Value);\r
909 if (EFI_ERROR (Status)) {\r
910 return Status;\r
911 }\r
912 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
913 return EFI_UNSUPPORTED;\r
914 }\r
915 Length = (UINTN) Value.Value.u64;\r
916\r
917 Status = PopExpression (&Value);\r
918 if (EFI_ERROR (Status)) {\r
919 return Status;\r
920 }\r
921 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
922 return EFI_UNSUPPORTED;\r
923 }\r
924 Base = (UINTN) Value.Value.u64;\r
925\r
926 Status = PopExpression (&Value);\r
927 if (EFI_ERROR (Status)) {\r
928 return Status;\r
929 }\r
930 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
931 return EFI_UNSUPPORTED;\r
932 }\r
933 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
934 if (String == NULL) {\r
935 return EFI_NOT_FOUND;\r
936 }\r
937\r
938 if (Length == 0 || Base >= StrLen (String)) {\r
939 SubString = gEmptyString;\r
940 } else {\r
941 SubString = String + Base;\r
942 if ((Base + Length) < StrLen (String)) {\r
943 SubString[Length] = L'\0';\r
944 }\r
945 }\r
946\r
947 Result->Type = EFI_IFR_TYPE_STRING;\r
948 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
949\r
f4113e1f 950 FreePool (String);\r
7936fb6a 951\r
952 return Status;\r
953}\r
954\r
955\r
956/**\r
957 Evaluate opcode EFI_IFR_TOKEN.\r
958\r
959 @param FormSet Formset which contains this opcode.\r
960 @param Result Evaluation result for this opcode.\r
961\r
962 @retval EFI_SUCCESS Opcode evaluation success.\r
963 @retval Other Opcode evaluation failed.\r
964\r
965**/\r
966EFI_STATUS\r
967IfrToken (\r
968 IN FORM_BROWSER_FORMSET *FormSet,\r
969 OUT EFI_HII_VALUE *Result\r
970 )\r
971{\r
972 EFI_STATUS Status;\r
973 EFI_HII_VALUE Value;\r
974 CHAR16 *String[2];\r
975 UINTN Count;\r
976 CHAR16 *Delimiter;\r
977 CHAR16 *SubString;\r
978 CHAR16 *StringPtr;\r
979 UINTN Index;\r
980\r
981 Status = PopExpression (&Value);\r
982 if (EFI_ERROR (Status)) {\r
983 return Status;\r
984 }\r
985 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
986 return EFI_UNSUPPORTED;\r
987 }\r
988 Count = (UINTN) Value.Value.u64;\r
989\r
990 //\r
991 // String[0] - Delimiter\r
992 // String[1] - The string to search\r
993 //\r
994 String[0] = NULL;\r
995 String[1] = NULL;\r
996 for (Index = 0; Index < 2; Index++) {\r
997 Status = PopExpression (&Value);\r
998 if (EFI_ERROR (Status)) {\r
999 goto Done;\r
1000 }\r
1001\r
1002 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1003 Status = EFI_UNSUPPORTED;\r
1004 goto Done;\r
1005 }\r
1006\r
1007 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
d0720b57 1008 if (String[Index] == NULL) {\r
7936fb6a 1009 Status = EFI_NOT_FOUND;\r
1010 goto Done;\r
1011 }\r
1012 }\r
1013\r
1014 Delimiter = String[0];\r
1015 SubString = String[1];\r
1016 while (Count > 0) {\r
1017 SubString = StrStr (SubString, Delimiter);\r
1018 if (SubString != NULL) {\r
1019 //\r
1020 // Skip over the delimiter\r
1021 //\r
1022 SubString = SubString + StrLen (Delimiter);\r
1023 } else {\r
1024 break;\r
1025 }\r
1026 Count--;\r
1027 }\r
1028\r
1029 if (SubString == NULL) {\r
1030 //\r
1031 // nth delimited sub-string not found, push an empty string\r
1032 //\r
1033 SubString = gEmptyString;\r
1034 } else {\r
1035 //\r
1036 // Put a NULL terminator for nth delimited sub-string\r
1037 //\r
1038 StringPtr = StrStr (SubString, Delimiter);\r
1039 if (StringPtr != NULL) {\r
1040 *StringPtr = L'\0';\r
1041 }\r
1042 }\r
1043\r
1044 Result->Type = EFI_IFR_TYPE_STRING;\r
1045 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1046\r
1047Done:\r
676df92c 1048 if (String[0] != NULL) {\r
1049 FreePool (String[0]);\r
1050 }\r
1051 if (String[1] != NULL) {\r
1052 FreePool (String[1]);\r
8b0fc5c1 1053 }\r
7936fb6a 1054\r
1055 return Status;\r
1056}\r
1057\r
1058\r
1059/**\r
1060 Evaluate opcode EFI_IFR_SPAN.\r
1061\r
1062 @param FormSet Formset which contains this opcode.\r
1063 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1064 @param Result Evaluation result for this opcode.\r
1065\r
1066 @retval EFI_SUCCESS Opcode evaluation success.\r
1067 @retval Other Opcode evaluation failed.\r
1068\r
1069**/\r
1070EFI_STATUS\r
1071IfrSpan (\r
1072 IN FORM_BROWSER_FORMSET *FormSet,\r
1073 IN UINT8 Flags,\r
1074 OUT EFI_HII_VALUE *Result\r
1075 )\r
1076{\r
1077 EFI_STATUS Status;\r
1078 EFI_HII_VALUE Value;\r
1079 CHAR16 *String[2];\r
1080 CHAR16 *Charset;\r
1081 UINTN Base;\r
1082 UINTN Index;\r
1083 CHAR16 *StringPtr;\r
1084 BOOLEAN Found;\r
1085\r
1086 Status = PopExpression (&Value);\r
1087 if (EFI_ERROR (Status)) {\r
1088 return Status;\r
1089 }\r
1090 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1091 return EFI_UNSUPPORTED;\r
1092 }\r
1093 Base = (UINTN) Value.Value.u64;\r
1094\r
1095 //\r
1096 // String[0] - Charset\r
1097 // String[1] - The string to search\r
1098 //\r
1099 String[0] = NULL;\r
1100 String[1] = NULL;\r
1101 for (Index = 0; Index < 2; Index++) {\r
1102 Status = PopExpression (&Value);\r
1103 if (EFI_ERROR (Status)) {\r
1104 goto Done;\r
1105 }\r
1106\r
1107 if (Value.Type != EFI_IFR_TYPE_STRING) {\r
1108 Status = EFI_UNSUPPORTED;\r
1109 goto Done;\r
1110 }\r
1111\r
1112 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);\r
bc166db3 1113 if (String [Index] == NULL) {\r
7936fb6a 1114 Status = EFI_NOT_FOUND;\r
1115 goto Done;\r
1116 }\r
1117 }\r
1118\r
1119 if (Base >= StrLen (String[1])) {\r
1120 Status = EFI_UNSUPPORTED;\r
1121 goto Done;\r
1122 }\r
1123\r
1124 Found = FALSE;\r
1125 StringPtr = String[1] + Base;\r
1126 Charset = String[0];\r
1127 while (*StringPtr != 0 && !Found) {\r
1128 Index = 0;\r
1129 while (Charset[Index] != 0) {\r
1130 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
1131 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1132 Found = TRUE;\r
1133 break;\r
1134 }\r
1135 } else {\r
1136 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1137 Found = TRUE;\r
1138 break;\r
1139 }\r
1140 }\r
1141 //\r
1142 // Skip characters pair representing low-end of a range and high-end of a range\r
1143 //\r
1144 Index += 2;\r
1145 }\r
1146\r
1147 if (!Found) {\r
1148 StringPtr++;\r
1149 }\r
1150 }\r
1151\r
1152 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1153 Result->Value.u64 = StringPtr - String[1];\r
1154\r
1155Done:\r
676df92c 1156 if (String[0] != NULL) {\r
1157 FreePool (String[0]);\r
1158 }\r
1159 if (String[1] != NULL) {\r
1160 FreePool (String[1]);\r
8b0fc5c1 1161 }\r
7936fb6a 1162\r
1163 return Status;\r
1164}\r
1165\r
1166\r
1167/**\r
1168 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1169\r
1170 @param Value HII Value to be converted.\r
1171\r
1172**/\r
1173VOID\r
1174ExtendValueToU64 (\r
1175 IN EFI_HII_VALUE *Value\r
1176 )\r
1177{\r
1178 UINT64 Temp;\r
1179\r
1180 Temp = 0;\r
1181 switch (Value->Type) {\r
1182 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1183 Temp = Value->Value.u8;\r
1184 break;\r
1185\r
1186 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1187 Temp = Value->Value.u16;\r
1188 break;\r
1189\r
1190 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1191 Temp = Value->Value.u32;\r
1192 break;\r
1193\r
1194 case EFI_IFR_TYPE_BOOLEAN:\r
1195 Temp = Value->Value.b;\r
1196 break;\r
1197\r
1198 case EFI_IFR_TYPE_TIME:\r
1199 Temp = Value->Value.u32 & 0xffffff;\r
1200 break;\r
1201\r
1202 case EFI_IFR_TYPE_DATE:\r
1203 Temp = Value->Value.u32;\r
1204 break;\r
1205\r
1206 default:\r
1207 return;\r
1208 }\r
1209\r
1210 Value->Value.u64 = Temp;\r
1211}\r
1212\r
1213\r
1214/**\r
1215 Compare two Hii value.\r
1216\r
1217 @param Value1 Expression value to compare on left-hand.\r
1218 @param Value2 Expression value to compare on right-hand.\r
1219 @param HiiHandle Only required for string compare.\r
1220\r
1221 @retval EFI_INVALID_PARAMETER Could not perform comparation on two values.\r
1222 @retval 0 Two operators equeal.\r
1223 @return Positive value if Value1 is greater than Value2.\r
1224 @retval Negative value if Value1 is less than Value2.\r
1225\r
1226**/\r
1227INTN\r
1228CompareHiiValue (\r
1229 IN EFI_HII_VALUE *Value1,\r
1230 IN EFI_HII_VALUE *Value2,\r
1231 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
1232 )\r
1233{\r
1234 INTN Result;\r
1235 INT64 Temp64;\r
1236 CHAR16 *Str1;\r
1237 CHAR16 *Str2;\r
1238\r
1239 if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {\r
1240 return EFI_INVALID_PARAMETER;\r
1241 }\r
1242\r
1243 if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {\r
1244 if (Value1->Type != Value2->Type) {\r
1245 //\r
1246 // Both Operator should be type of String\r
1247 //\r
1248 return EFI_INVALID_PARAMETER;\r
1249 }\r
1250\r
1251 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
1252 //\r
1253 // StringId 0 is reserved\r
1254 //\r
1255 return EFI_INVALID_PARAMETER;\r
1256 }\r
1257\r
1258 if (Value1->Value.string == Value2->Value.string) {\r
1259 return 0;\r
1260 }\r
1261\r
1262 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
1263 if (Str1 == NULL) {\r
1264 //\r
1265 // String not found\r
1266 //\r
1267 return EFI_INVALID_PARAMETER;\r
1268 }\r
1269\r
1270 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
1271 if (Str2 == NULL) {\r
f4113e1f 1272 FreePool (Str1);\r
7936fb6a 1273 return EFI_INVALID_PARAMETER;\r
1274 }\r
1275\r
1276 Result = StrCmp (Str1, Str2);\r
1277\r
f4113e1f 1278 FreePool (Str1);\r
1279 FreePool (Str2);\r
7936fb6a 1280\r
1281 return Result;\r
1282 }\r
1283\r
1284 //\r
1285 // Take remain types(integer, boolean, date/time) as integer\r
1286 //\r
1287 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);\r
1288 if (Temp64 > 0) {\r
1289 Result = 1;\r
1290 } else if (Temp64 < 0) {\r
1291 Result = -1;\r
1292 } else {\r
1293 Result = 0;\r
1294 }\r
1295\r
1296 return Result;\r
1297}\r
1298\r
cbf73e50 1299/**\r
1300 Check if current user has the privilege specified by the permissions GUID.\r
1301\r
1302 @param[in] Guid A GUID specifying setup access permissions.\r
1303\r
1304 @retval TRUE Current user has the privilege.\r
1305 @retval FALSE Current user does not have the privilege.\r
1306**/\r
1307BOOLEAN\r
1308CheckUserPrivilege (\r
1309 IN EFI_GUID *Guid\r
1310 )\r
1311{\r
1312 EFI_STATUS Status;\r
1313 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
1314 EFI_USER_INFO_HANDLE UserInfoHandle;\r
1315 EFI_USER_INFO *UserInfo;\r
1316 EFI_GUID *UserPermissionsGuid;\r
1317 UINTN UserInfoSize;\r
1318 UINTN AccessControlDataSize;\r
1319 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
1320 UINTN RemainSize;\r
1321\r
1322 if (mUserManager == NULL) {\r
1323 Status = gBS->LocateProtocol (\r
1324 &gEfiUserManagerProtocolGuid,\r
1325 NULL,\r
1326 (VOID **) &mUserManager\r
1327 );\r
1328 if (EFI_ERROR (Status)) {\r
1329 ///\r
1330 /// If the system does not support user management, then it is assumed that\r
1331 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
1332 /// op-code is always TRUE.\r
1333 ///\r
1334 return TRUE;\r
1335 }\r
1336 }\r
1337\r
1338 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
1339 ASSERT_EFI_ERROR (Status);\r
1340\r
1341 ///\r
1342 /// Enumerate all user information of the current user profile\r
1343 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
1344 ///\r
1345 \r
1346 for (UserInfoHandle = NULL;;) {\r
1347 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
1348 if (EFI_ERROR (Status)) {\r
1349 break;\r
1350 }\r
1351\r
1352 UserInfoSize = 0;\r
1353 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
1354 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1355 continue;\r
1356 }\r
1357\r
1358 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
1359 if (UserInfo == NULL) {\r
1360 break;\r
1361 }\r
1362\r
1363 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
1364 if (EFI_ERROR (Status) ||\r
1365 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
1366 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
1367 FreePool (UserInfo);\r
1368 continue;\r
1369 }\r
1370\r
1371 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
1372 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
1373 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
1374 if (RemainSize < AccessControl->Size || AccessControl->Size <= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
1375 break;\r
1376 }\r
1377 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
1378 ///\r
1379 /// Check if current user has the privilege specified by the permissions GUID.\r
1380 ///\r
1381\r
1382 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
1383 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
1384 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
1385 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
1386 FreePool (UserInfo);\r
1387 return TRUE;\r
1388 }\r
1389 UserPermissionsGuid++;\r
1390 AccessControlDataSize -= sizeof (EFI_GUID);\r
1391 }\r
1392 }\r
1393 RemainSize -= AccessControl->Size;\r
1394 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
1395 }\r
1396\r
1397 FreePool (UserInfo);\r
1398 }\r
1399 return FALSE;\r
1400}\r
7936fb6a 1401\r
1402/**\r
bc166db3 1403 Evaluate the result of a HII expression.\r
1404\r
1405 If Expression is NULL, then ASSERT.\r
7936fb6a 1406\r
1407 @param FormSet FormSet associated with this expression.\r
1408 @param Form Form associated with this expression.\r
1409 @param Expression Expression to be evaluated.\r
1410\r
1411 @retval EFI_SUCCESS The expression evaluated successfuly\r
1412 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
1413 could not be found.\r
1414 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
1415 stack.\r
1416 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
1417 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
1418\r
1419**/\r
1420EFI_STATUS\r
1421EvaluateExpression (\r
1422 IN FORM_BROWSER_FORMSET *FormSet,\r
1423 IN FORM_BROWSER_FORM *Form,\r
1424 IN OUT FORM_EXPRESSION *Expression\r
1425 )\r
1426{\r
1427 EFI_STATUS Status;\r
1428 LIST_ENTRY *Link;\r
1429 EXPRESSION_OPCODE *OpCode;\r
1430 FORM_BROWSER_STATEMENT *Question;\r
1431 FORM_BROWSER_STATEMENT *Question2;\r
1432 UINT16 Index;\r
1433 EFI_HII_VALUE Data1;\r
1434 EFI_HII_VALUE Data2;\r
1435 EFI_HII_VALUE Data3;\r
1436 FORM_EXPRESSION *RuleExpression;\r
1437 EFI_HII_VALUE *Value;\r
1438 INTN Result;\r
1439 CHAR16 *StrPtr;\r
1440 UINT32 TempValue;\r
1441\r
1442 //\r
1443 // Always reset the stack before evaluating an Expression\r
1444 //\r
1445 ResetExpressionStack ();\r
1446\r
bc166db3 1447 ASSERT (Expression != NULL);\r
7936fb6a 1448 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
1449\r
1450 Link = GetFirstNode (&Expression->OpCodeListHead);\r
1451 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
1452 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
1453\r
1454 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
1455\r
1456 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
1457 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
1458 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
1459\r
1460 Value = &Data3;\r
1461 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1462 Status = EFI_SUCCESS;\r
1463\r
1464 switch (OpCode->Operand) {\r
1465 //\r
1466 // Built-in functions\r
1467 //\r
1468 case EFI_IFR_EQ_ID_VAL_OP:\r
1469 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1470 if (Question == NULL) {\r
1471 return EFI_NOT_FOUND;\r
1472 }\r
1473\r
1474 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);\r
1475 if (Result == EFI_INVALID_PARAMETER) {\r
1476 return EFI_INVALID_PARAMETER;\r
1477 }\r
1478 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1479 break;\r
1480\r
1481 case EFI_IFR_EQ_ID_ID_OP:\r
1482 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1483 if (Question == NULL) {\r
1484 return EFI_NOT_FOUND;\r
1485 }\r
1486\r
1487 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
1488 if (Question2 == NULL) {\r
1489 return EFI_NOT_FOUND;\r
1490 }\r
1491\r
1492 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);\r
1493 if (Result == EFI_INVALID_PARAMETER) {\r
1494 return EFI_INVALID_PARAMETER;\r
1495 }\r
1496 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1497 break;\r
1498\r
1499 case EFI_IFR_EQ_ID_LIST_OP:\r
1500 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1501 if (Question == NULL) {\r
1502 return EFI_NOT_FOUND;\r
1503 }\r
1504\r
1505 Value->Value.b = FALSE;\r
1506 for (Index =0; Index < OpCode->ListLength; Index++) {\r
1507 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
1508 Value->Value.b = TRUE;\r
1509 break;\r
1510 }\r
1511 }\r
1512 break;\r
1513\r
1514 case EFI_IFR_DUP_OP:\r
1515 Status = PopExpression (Value);\r
1516 if (EFI_ERROR (Status)) {\r
1517 return Status;\r
1518 }\r
1519\r
1520 Status = PushExpression (Value);\r
1521 break;\r
1522\r
1523 case EFI_IFR_QUESTION_REF1_OP:\r
1524 case EFI_IFR_THIS_OP:\r
1525 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
1526 if (Question == NULL) {\r
1527 return EFI_NOT_FOUND;\r
1528 }\r
1529\r
1530 Value = &Question->HiiValue;\r
1531 break;\r
1532\r
cbf73e50 1533 case EFI_IFR_SECURITY_OP:\r
1534 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
1535 break;\r
1536\r
7936fb6a 1537 case EFI_IFR_QUESTION_REF3_OP:\r
1538 if (OpCode->DevicePath == 0) {\r
1539 //\r
1540 // EFI_IFR_QUESTION_REF3\r
1541 // Pop an expression from the expression stack\r
1542 //\r
1543 Status = PopExpression (Value);\r
1544 if (EFI_ERROR (Status)) {\r
1545 return Status;\r
1546 }\r
1547\r
1548 //\r
1549 // Validate the expression value\r
1550 //\r
1551 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1552 return EFI_NOT_FOUND;\r
1553 }\r
1554\r
1555 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1556 if (Question == NULL) {\r
1557 return EFI_NOT_FOUND;\r
1558 }\r
1559\r
1560 //\r
1561 // push the questions' value on to the expression stack\r
1562 //\r
1563 Value = &Question->HiiValue;\r
1564 } else {\r
1565 //\r
1566 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,\r
1567 // since it is impractical to evaluate the value of a Question in another\r
1568 // Hii Package list.\r
1569 //\r
1570 ZeroMem (Value, sizeof (EFI_HII_VALUE));\r
1571 }\r
1572 break;\r
1573\r
1574 case EFI_IFR_RULE_REF_OP:\r
1575 //\r
1576 // Find expression for this rule\r
1577 //\r
1578 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
1579 if (RuleExpression == NULL) {\r
1580 return EFI_NOT_FOUND;\r
1581 }\r
1582\r
1583 //\r
1584 // Evaluate this rule expression\r
1585 //\r
1586 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
1587 if (EFI_ERROR (Status)) {\r
1588 return Status;\r
1589 }\r
1590\r
1591 Value = &RuleExpression->Result;\r
1592 break;\r
1593\r
1594 case EFI_IFR_STRING_REF1_OP:\r
1595 Value->Type = EFI_IFR_TYPE_STRING;\r
1596 Value->Value.string = OpCode->Value.Value.string;\r
1597 break;\r
1598\r
1599 //\r
1600 // Constant\r
1601 //\r
1602 case EFI_IFR_TRUE_OP:\r
1603 case EFI_IFR_FALSE_OP:\r
1604 case EFI_IFR_ONE_OP:\r
1605 case EFI_IFR_ONES_OP:\r
1606 case EFI_IFR_UINT8_OP:\r
1607 case EFI_IFR_UINT16_OP:\r
1608 case EFI_IFR_UINT32_OP:\r
1609 case EFI_IFR_UINT64_OP:\r
1610 case EFI_IFR_UNDEFINED_OP:\r
1611 case EFI_IFR_VERSION_OP:\r
1612 case EFI_IFR_ZERO_OP:\r
1613 Value = &OpCode->Value;\r
1614 break;\r
1615\r
1616 //\r
1617 // unary-op\r
1618 //\r
1619 case EFI_IFR_LENGTH_OP:\r
1620 Status = PopExpression (Value);\r
1621 if (EFI_ERROR (Status)) {\r
1622 return Status;\r
1623 }\r
1624 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1625 return EFI_INVALID_PARAMETER;\r
1626 }\r
1627\r
1628 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1629 if (StrPtr == NULL) {\r
1630 return EFI_INVALID_PARAMETER;\r
1631 }\r
1632\r
1633 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1634 Value->Value.u64 = StrLen (StrPtr);\r
f4113e1f 1635 FreePool (StrPtr);\r
7936fb6a 1636 break;\r
1637\r
1638 case EFI_IFR_NOT_OP:\r
1639 Status = PopExpression (Value);\r
1640 if (EFI_ERROR (Status)) {\r
1641 return Status;\r
1642 }\r
1643 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
1644 return EFI_INVALID_PARAMETER;\r
1645 }\r
1646 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
1647 break;\r
1648\r
1649 case EFI_IFR_QUESTION_REF2_OP:\r
1650 //\r
1651 // Pop an expression from the expression stack\r
1652 //\r
1653 Status = PopExpression (Value);\r
1654 if (EFI_ERROR (Status)) {\r
1655 return Status;\r
1656 }\r
1657\r
1658 //\r
1659 // Validate the expression value\r
1660 //\r
1661 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1662 return EFI_NOT_FOUND;\r
1663 }\r
1664\r
1665 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
1666 if (Question == NULL) {\r
1667 return EFI_NOT_FOUND;\r
1668 }\r
1669\r
1670 Value = &Question->HiiValue;\r
1671 break;\r
1672\r
1673 case EFI_IFR_STRING_REF2_OP:\r
1674 //\r
1675 // Pop an expression from the expression stack\r
1676 //\r
1677 Status = PopExpression (Value);\r
1678 if (EFI_ERROR (Status)) {\r
1679 return Status;\r
1680 }\r
1681\r
1682 //\r
1683 // Validate the expression value\r
1684 //\r
1685 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
1686 return EFI_NOT_FOUND;\r
1687 }\r
1688\r
1689 Value->Type = EFI_IFR_TYPE_STRING;\r
1690 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
1691 if (StrPtr == NULL) {\r
1692 //\r
1693 // If String not exit, push an empty string\r
1694 //\r
1695 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
1696 } else {\r
1697 Index = (UINT16) Value->Value.u64;\r
1698 Value->Value.string = Index;\r
f4113e1f 1699 FreePool (StrPtr);\r
7936fb6a 1700 }\r
1701 break;\r
1702\r
1703 case EFI_IFR_TO_BOOLEAN_OP:\r
1704 //\r
1705 // Pop an expression from the expression stack\r
1706 //\r
1707 Status = PopExpression (Value);\r
1708 if (EFI_ERROR (Status)) {\r
1709 return Status;\r
1710 }\r
1711\r
1712 //\r
1713 // Convert an expression to a Boolean\r
1714 //\r
1715 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
1716 //\r
1717 // When converting from an unsigned integer, zero will be converted to\r
1718 // FALSE and any other value will be converted to TRUE.\r
1719 //\r
1720 Value->Value.b = (BOOLEAN) ((Value->Value.u64) ? TRUE : FALSE);\r
1721\r
1722 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1723 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
1724 //\r
1725 // When converting from a string, if case-insensitive compare\r
1726 // with "true" is True, then push True. If a case-insensitive compare\r
1727 // with "false" is True, then push False.\r
1728 //\r
1729 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1730 if (StrPtr == NULL) {\r
1731 return EFI_INVALID_PARAMETER;\r
1732 }\r
1733\r
1734 if ((StrCmp (StrPtr, L"true") == 0) || (StrCmp (StrPtr, L"false") == 0)){\r
1735 Value->Value.b = TRUE;\r
1736 } else {\r
1737 Value->Value.b = FALSE;\r
1738 }\r
f4113e1f 1739 FreePool (StrPtr);\r
7936fb6a 1740 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
1741 }\r
1742 break;\r
1743\r
1744 case EFI_IFR_TO_STRING_OP:\r
1745 Status = IfrToString (FormSet, OpCode->Format, Value);\r
1746 break;\r
1747\r
1748 case EFI_IFR_TO_UINT_OP:\r
1749 Status = IfrToUint (FormSet, Value);\r
1750 break;\r
1751\r
1752 case EFI_IFR_TO_LOWER_OP:\r
1753 case EFI_IFR_TO_UPPER_OP:\r
1754 Status = InitializeUnicodeCollationProtocol ();\r
1755 if (EFI_ERROR (Status)) {\r
1756 return Status;\r
1757 }\r
1758\r
1759 Status = PopExpression (Value);\r
1760 if (EFI_ERROR (Status)) {\r
1761 return Status;\r
1762 }\r
1763\r
1764 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
1765 return EFI_UNSUPPORTED;\r
1766 }\r
1767\r
1768 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
1769 if (StrPtr == NULL) {\r
1770 return EFI_NOT_FOUND;\r
1771 }\r
1772\r
1773 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
1774 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
1775 } else {\r
1776 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
1777 }\r
1778 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 1779 FreePool (StrPtr);\r
7936fb6a 1780 break;\r
1781\r
1782 case EFI_IFR_BITWISE_NOT_OP:\r
1783 //\r
1784 // Pop an expression from the expression stack\r
1785 //\r
1786 Status = PopExpression (Value);\r
1787 if (EFI_ERROR (Status)) {\r
1788 return Status;\r
1789 }\r
1790 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
1791 return EFI_INVALID_PARAMETER;\r
1792 }\r
1793\r
1794 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1795 Value->Value.u64 = ~Value->Value.u64;\r
1796 break;\r
1797\r
1798 //\r
1799 // binary-op\r
1800 //\r
1801 case EFI_IFR_ADD_OP:\r
1802 case EFI_IFR_SUBTRACT_OP:\r
1803 case EFI_IFR_MULTIPLY_OP:\r
1804 case EFI_IFR_DIVIDE_OP:\r
1805 case EFI_IFR_MODULO_OP:\r
1806 case EFI_IFR_BITWISE_AND_OP:\r
1807 case EFI_IFR_BITWISE_OR_OP:\r
1808 case EFI_IFR_SHIFT_LEFT_OP:\r
1809 case EFI_IFR_SHIFT_RIGHT_OP:\r
1810 //\r
1811 // Pop an expression from the expression stack\r
1812 //\r
1813 Status = PopExpression (&Data2);\r
1814 if (EFI_ERROR (Status)) {\r
1815 return Status;\r
1816 }\r
1817 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
1818 return EFI_INVALID_PARAMETER;\r
1819 }\r
1820\r
1821 //\r
1822 // Pop another expression from the expression stack\r
1823 //\r
1824 Status = PopExpression (&Data1);\r
1825 if (EFI_ERROR (Status)) {\r
1826 return Status;\r
1827 }\r
1828 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
1829 return EFI_INVALID_PARAMETER;\r
1830 }\r
1831\r
1832 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1833\r
1834 switch (OpCode->Operand) {\r
1835 case EFI_IFR_ADD_OP:\r
1836 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;\r
1837 break;\r
1838\r
1839 case EFI_IFR_SUBTRACT_OP:\r
1840 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;\r
1841 break;\r
1842\r
1843 case EFI_IFR_MULTIPLY_OP:\r
1844 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
1845 break;\r
1846\r
1847 case EFI_IFR_DIVIDE_OP:\r
1848 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);\r
1849 break;\r
1850\r
1851 case EFI_IFR_MODULO_OP:\r
1852 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);\r
1853 Value->Value.u64 = TempValue;\r
1854 break;\r
1855\r
1856 case EFI_IFR_BITWISE_AND_OP:\r
1857 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;\r
1858 break;\r
1859\r
1860 case EFI_IFR_BITWISE_OR_OP:\r
1861 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;\r
1862 break;\r
1863\r
1864 case EFI_IFR_SHIFT_LEFT_OP:\r
1865 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
1866 break;\r
1867\r
1868 case EFI_IFR_SHIFT_RIGHT_OP:\r
1869 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);\r
1870 break;\r
1871\r
1872 default:\r
1873 break;\r
1874 }\r
1875 break;\r
1876\r
1877 case EFI_IFR_AND_OP:\r
1878 case EFI_IFR_OR_OP:\r
1879 //\r
1880 // Two Boolean operator\r
1881 //\r
1882 Status = PopExpression (&Data2);\r
1883 if (EFI_ERROR (Status)) {\r
1884 return Status;\r
1885 }\r
1886 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1887 return EFI_INVALID_PARAMETER;\r
1888 }\r
1889\r
1890 //\r
1891 // Pop another expression from the expression stack\r
1892 //\r
1893 Status = PopExpression (&Data1);\r
1894 if (EFI_ERROR (Status)) {\r
1895 return Status;\r
1896 }\r
1897 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
1898 return EFI_INVALID_PARAMETER;\r
1899 }\r
1900\r
1901 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
1902 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
1903 } else {\r
1904 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
1905 }\r
1906 break;\r
1907\r
1908 case EFI_IFR_EQUAL_OP:\r
1909 case EFI_IFR_NOT_EQUAL_OP:\r
1910 case EFI_IFR_GREATER_EQUAL_OP:\r
1911 case EFI_IFR_GREATER_THAN_OP:\r
1912 case EFI_IFR_LESS_EQUAL_OP:\r
1913 case EFI_IFR_LESS_THAN_OP:\r
1914 //\r
1915 // Compare two integer, string, boolean or date/time\r
1916 //\r
1917 Status = PopExpression (&Data2);\r
1918 if (EFI_ERROR (Status)) {\r
1919 return Status;\r
1920 }\r
1921 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && Data2.Type != EFI_IFR_TYPE_STRING) {\r
1922 return EFI_INVALID_PARAMETER;\r
1923 }\r
1924\r
1925 //\r
1926 // Pop another expression from the expression stack\r
1927 //\r
1928 Status = PopExpression (&Data1);\r
1929 if (EFI_ERROR (Status)) {\r
1930 return Status;\r
1931 }\r
1932\r
1933 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);\r
1934 if (Result == EFI_INVALID_PARAMETER) {\r
1935 return EFI_INVALID_PARAMETER;\r
1936 }\r
1937\r
1938 switch (OpCode->Operand) {\r
1939 case EFI_IFR_EQUAL_OP:\r
1940 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1941 break;\r
1942\r
1943 case EFI_IFR_NOT_EQUAL_OP:\r
1944 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
1945 break;\r
1946\r
1947 case EFI_IFR_GREATER_EQUAL_OP:\r
1948 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
1949 break;\r
1950\r
1951 case EFI_IFR_GREATER_THAN_OP:\r
1952 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
1953 break;\r
1954\r
1955 case EFI_IFR_LESS_EQUAL_OP:\r
1956 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
1957 break;\r
1958\r
1959 case EFI_IFR_LESS_THAN_OP:\r
1960 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
1961 break;\r
1962\r
1963 default:\r
1964 break;\r
1965 }\r
1966 break;\r
1967\r
1968 case EFI_IFR_MATCH_OP:\r
1969 Status = IfrMatch (FormSet, Value);\r
1970 break;\r
1971\r
1972 case EFI_IFR_CATENATE_OP:\r
1973 Status = IfrCatenate (FormSet, Value);\r
1974 break;\r
1975\r
1976 //\r
1977 // ternary-op\r
1978 //\r
1979 case EFI_IFR_CONDITIONAL_OP:\r
1980 //\r
1981 // Pop third expression from the expression stack\r
1982 //\r
1983 Status = PopExpression (&Data3);\r
1984 if (EFI_ERROR (Status)) {\r
1985 return Status;\r
1986 }\r
1987\r
1988 //\r
1989 // Pop second expression from the expression stack\r
1990 //\r
1991 Status = PopExpression (&Data2);\r
1992 if (EFI_ERROR (Status)) {\r
1993 return Status;\r
1994 }\r
1995\r
1996 //\r
1997 // Pop first expression from the expression stack\r
1998 //\r
1999 Status = PopExpression (&Data1);\r
2000 if (EFI_ERROR (Status)) {\r
2001 return Status;\r
2002 }\r
2003 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
2004 return EFI_INVALID_PARAMETER;\r
2005 }\r
2006\r
2007 if (Data1.Value.b) {\r
2008 Value = &Data3;\r
2009 } else {\r
2010 Value = &Data2;\r
2011 }\r
2012 break;\r
2013\r
2014 case EFI_IFR_FIND_OP:\r
2015 Status = IfrFind (FormSet, OpCode->Format, Value);\r
2016 break;\r
2017\r
2018 case EFI_IFR_MID_OP:\r
2019 Status = IfrMid (FormSet, Value);\r
2020 break;\r
2021\r
2022 case EFI_IFR_TOKEN_OP:\r
2023 Status = IfrToken (FormSet, Value);\r
2024 break;\r
2025\r
2026 case EFI_IFR_SPAN_OP:\r
2027 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
2028 break;\r
2029\r
2030 default:\r
2031 break;\r
2032 }\r
2033 if (EFI_ERROR (Status)) {\r
2034 return Status;\r
2035 }\r
2036\r
2037 Status = PushExpression (Value);\r
2038 if (EFI_ERROR (Status)) {\r
2039 return Status;\r
2040 }\r
2041 }\r
2042\r
2043 //\r
2044 // Pop the final result from expression stack\r
2045 //\r
2046 Value = &Data1;\r
2047 Status = PopExpression (Value);\r
2048 if (EFI_ERROR (Status)) {\r
2049 return Status;\r
2050 }\r
2051\r
2052 //\r
2053 // After evaluating an expression, there should be only one value left on the expression stack\r
2054 //\r
2055 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2056 return EFI_INVALID_PARAMETER;\r
2057 }\r
2058\r
2059 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
2060\r
2061 return EFI_SUCCESS;\r
2062}\r