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