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