]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
Enable buffer type when process some expression opcode which support buffer type.
[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) {
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 if (Format == EFI_IFR_STRING_ASCII) {
761 CopyMem (TmpBuf, Value.Buffer, Value.BufferLen);
762 PrintFormat = L"%a";
763 } else {
764 // Format == EFI_IFR_STRING_UNICODE
765 CopyMem (TmpBuf, Value.Buffer, Value.BufferLen * sizeof (CHAR16));
766 PrintFormat = L"%s";
767 }
768 UnicodeSPrint (Buffer, MAXIMUM_VALUE_CHARACTERS, PrintFormat, Value.Buffer);
769 String = Buffer;
770 FreePool (TmpBuf);
771 FreePool (Value.Buffer);
772 break;
773
774 default:
775 return EFI_UNSUPPORTED;
776 }
777
778 Result->Type = EFI_IFR_TYPE_STRING;
779 Result->Value.string = NewString (String, FormSet->HiiHandle);
780 return EFI_SUCCESS;
781 }
782
783
784 /**
785 Evaluate opcode EFI_IFR_TO_UINT.
786
787 @param FormSet Formset which contains this opcode.
788 @param Result Evaluation result for this opcode.
789
790 @retval EFI_SUCCESS Opcode evaluation success.
791 @retval Other Opcode evaluation failed.
792
793 **/
794 EFI_STATUS
795 IfrToUint (
796 IN FORM_BROWSER_FORMSET *FormSet,
797 OUT EFI_HII_VALUE *Result
798 )
799 {
800 EFI_STATUS Status;
801 EFI_HII_VALUE Value;
802 CHAR16 *String;
803 CHAR16 *StringPtr;
804
805 Status = PopExpression (&Value);
806 if (EFI_ERROR (Status)) {
807 return Status;
808 }
809
810 if (Value.Type >= EFI_IFR_TYPE_OTHER && Value.Type != EFI_IFR_TYPE_BUFFER) {
811 return EFI_UNSUPPORTED;
812 }
813
814 Status = EFI_SUCCESS;
815 if (Value.Type == EFI_IFR_TYPE_STRING) {
816 String = GetToken (Value.Value.string, FormSet->HiiHandle);
817 if (String == NULL) {
818 return EFI_NOT_FOUND;
819 }
820
821 IfrStrToUpper (String);
822 StringPtr = StrStr (String, L"0X");
823 if (StringPtr != NULL) {
824 //
825 // Hex string
826 //
827 Result->Value.u64 = StrHexToUint64 (String);
828 } else {
829 //
830 // decimal string
831 //
832 Result->Value.u64 = StrDecimalToUint64 (String);
833 }
834 FreePool (String);
835 } else if (Value.Type == EFI_IFR_TYPE_BUFFER) {
836 if (Value.BufferLen > 8) {
837 FreePool (Value.Buffer);
838 return EFI_UNSUPPORTED;
839 }
840 Result->Value.u64 = *(UINT64*) Value.Buffer;
841 FreePool (Value.Buffer);
842 } else {
843 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
844 }
845
846 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
847 return Status;
848 }
849
850
851 /**
852 Evaluate opcode EFI_IFR_CATENATE.
853
854 @param FormSet Formset which contains this opcode.
855 @param Result Evaluation result for this opcode.
856
857 @retval EFI_SUCCESS Opcode evaluation success.
858 @retval Other Opcode evaluation failed.
859
860 **/
861 EFI_STATUS
862 IfrCatenate (
863 IN FORM_BROWSER_FORMSET *FormSet,
864 OUT EFI_HII_VALUE *Result
865 )
866 {
867 EFI_STATUS Status;
868 EFI_HII_VALUE Value[2];
869 CHAR16 *String[2];
870 UINTN Index;
871 CHAR16 *StringPtr;
872 UINTN Size;
873
874 //
875 // String[0] - The second string
876 // String[1] - The first string
877 //
878 String[0] = NULL;
879 String[1] = NULL;
880 StringPtr = NULL;
881 Status = EFI_SUCCESS;
882 ZeroMem (Value, sizeof (Value));
883
884 for (Index = 0; Index < 2; Index++) {
885 Status = PopExpression (&Value[Index]);
886 if (EFI_ERROR (Status)) {
887 goto Done;
888 }
889
890 if (Value[Index].Type != EFI_IFR_TYPE_STRING && Value[Index].Type != EFI_IFR_TYPE_BUFFER) {
891 Status = EFI_UNSUPPORTED;
892 goto Done;
893 }
894
895 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {
896 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);
897 if (String[Index] == NULL) {
898 Status = EFI_NOT_FOUND;
899 goto Done;
900 }
901 }
902 }
903
904 if (Value[0].Type == EFI_IFR_TYPE_STRING) {
905 Size = StrSize (String[0]);
906 StringPtr= AllocatePool (StrSize (String[1]) + Size);
907 ASSERT (StringPtr != NULL);
908 StrCpy (StringPtr, String[1]);
909 StrCat (StringPtr, String[0]);
910
911 Result->Type = EFI_IFR_TYPE_STRING;
912 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);
913 } else {
914 Result->Type = EFI_IFR_TYPE_BUFFER;
915 Result->BufferLen = (UINT16) (Value[0].BufferLen + Value[1].BufferLen);
916
917 Result->Buffer = AllocateZeroPool (Result->BufferLen);
918 ASSERT (Result->Buffer != NULL);
919
920 CopyMem (Result->Buffer, Value[0].Buffer, Value[0].BufferLen);
921 CopyMem (&Result->Buffer[Value[0].BufferLen], Value[1].Buffer, Value[1].BufferLen);
922 }
923 Done:
924 if (Value[0].Buffer != NULL) {
925 FreePool (Value[0].Buffer);
926 }
927 if (Value[1].Buffer != NULL) {
928 FreePool (Value[1].Buffer);
929 }
930 if (String[0] != NULL) {
931 FreePool (String[0]);
932 }
933 if (String[1] != NULL) {
934 FreePool (String[1]);
935 }
936 if (StringPtr != NULL) {
937 FreePool (StringPtr);
938 }
939
940 return Status;
941 }
942
943
944 /**
945 Evaluate opcode EFI_IFR_MATCH.
946
947 @param FormSet Formset which contains this opcode.
948 @param Result Evaluation result for this opcode.
949
950 @retval EFI_SUCCESS Opcode evaluation success.
951 @retval Other Opcode evaluation failed.
952
953 **/
954 EFI_STATUS
955 IfrMatch (
956 IN FORM_BROWSER_FORMSET *FormSet,
957 OUT EFI_HII_VALUE *Result
958 )
959 {
960 EFI_STATUS Status;
961 EFI_HII_VALUE Value;
962 CHAR16 *String[2];
963 UINTN Index;
964
965 //
966 // String[0] - The string to search
967 // String[1] - pattern
968 //
969 String[0] = NULL;
970 String[1] = NULL;
971 Status = EFI_SUCCESS;
972 for (Index = 0; Index < 2; Index++) {
973 Status = PopExpression (&Value);
974 if (EFI_ERROR (Status)) {
975 goto Done;
976 }
977
978 if (Value.Type != EFI_IFR_TYPE_STRING) {
979 Status = EFI_UNSUPPORTED;
980 goto Done;
981 }
982
983 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
984 if (String [Index] == NULL) {
985 Status = EFI_NOT_FOUND;
986 goto Done;
987 }
988 }
989
990 Result->Type = EFI_IFR_TYPE_BOOLEAN;
991 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
992
993 Done:
994 if (String[0] != NULL) {
995 FreePool (String[0]);
996 }
997 if (String[1] != NULL) {
998 FreePool (String[1]);
999 }
1000
1001 return Status;
1002 }
1003
1004
1005 /**
1006 Evaluate opcode EFI_IFR_FIND.
1007
1008 @param FormSet Formset which contains this opcode.
1009 @param Format Case sensitive or insensitive.
1010 @param Result Evaluation result for this opcode.
1011
1012 @retval EFI_SUCCESS Opcode evaluation success.
1013 @retval Other Opcode evaluation failed.
1014
1015 **/
1016 EFI_STATUS
1017 IfrFind (
1018 IN FORM_BROWSER_FORMSET *FormSet,
1019 IN UINT8 Format,
1020 OUT EFI_HII_VALUE *Result
1021 )
1022 {
1023 EFI_STATUS Status;
1024 EFI_HII_VALUE Value;
1025 CHAR16 *String[2];
1026 UINTN Base;
1027 CHAR16 *StringPtr;
1028 UINTN Index;
1029
1030 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
1031 return EFI_UNSUPPORTED;
1032 }
1033
1034 Status = PopExpression (&Value);
1035 if (EFI_ERROR (Status)) {
1036 return Status;
1037 }
1038 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1039 return EFI_UNSUPPORTED;
1040 }
1041 Base = (UINTN) Value.Value.u64;
1042
1043 //
1044 // String[0] - sub-string
1045 // String[1] - The string to search
1046 //
1047 String[0] = NULL;
1048 String[1] = NULL;
1049 for (Index = 0; Index < 2; Index++) {
1050 Status = PopExpression (&Value);
1051 if (EFI_ERROR (Status)) {
1052 goto Done;
1053 }
1054
1055 if (Value.Type != EFI_IFR_TYPE_STRING) {
1056 Status = EFI_UNSUPPORTED;
1057 goto Done;
1058 }
1059
1060 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
1061 if (String[Index] == NULL) {
1062 Status = EFI_NOT_FOUND;
1063 goto Done;
1064 }
1065
1066 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
1067 //
1068 // Case insensitive, convert both string to upper case
1069 //
1070 IfrStrToUpper (String[Index]);
1071 }
1072 }
1073
1074 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1075 if (Base >= StrLen (String[1])) {
1076 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
1077 } else {
1078 StringPtr = StrStr (String[1] + Base, String[0]);
1079 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
1080 }
1081
1082 Done:
1083 if (String[0] != NULL) {
1084 FreePool (String[0]);
1085 }
1086 if (String[1] != NULL) {
1087 FreePool (String[1]);
1088 }
1089
1090 return Status;
1091 }
1092
1093
1094 /**
1095 Evaluate opcode EFI_IFR_MID.
1096
1097 @param FormSet Formset which contains this opcode.
1098 @param Result Evaluation result for this opcode.
1099
1100 @retval EFI_SUCCESS Opcode evaluation success.
1101 @retval Other Opcode evaluation failed.
1102
1103 **/
1104 EFI_STATUS
1105 IfrMid (
1106 IN FORM_BROWSER_FORMSET *FormSet,
1107 OUT EFI_HII_VALUE *Result
1108 )
1109 {
1110 EFI_STATUS Status;
1111 EFI_HII_VALUE Value;
1112 CHAR16 *String;
1113 UINTN Base;
1114 UINTN Length;
1115 CHAR16 *SubString;
1116 UINT8 *Buffer;
1117 UINT16 BufferLen;
1118
1119 Status = PopExpression (&Value);
1120 if (EFI_ERROR (Status)) {
1121 return Status;
1122 }
1123 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1124 return EFI_UNSUPPORTED;
1125 }
1126 Length = (UINTN) Value.Value.u64;
1127
1128 Status = PopExpression (&Value);
1129 if (EFI_ERROR (Status)) {
1130 return Status;
1131 }
1132 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1133 return EFI_UNSUPPORTED;
1134 }
1135 Base = (UINTN) Value.Value.u64;
1136
1137 Status = PopExpression (&Value);
1138 if (EFI_ERROR (Status)) {
1139 return Status;
1140 }
1141 if (Value.Type != EFI_IFR_TYPE_STRING && Value.Type != EFI_IFR_TYPE_BUFFER) {
1142 return EFI_UNSUPPORTED;
1143 }
1144 if (Value.Type == EFI_IFR_TYPE_STRING) {
1145 String = GetToken (Value.Value.string, FormSet->HiiHandle);
1146 if (String == NULL) {
1147 return EFI_NOT_FOUND;
1148 }
1149
1150 if (Length == 0 || Base >= StrLen (String)) {
1151 SubString = gEmptyString;
1152 } else {
1153 SubString = String + Base;
1154 if ((Base + Length) < StrLen (String)) {
1155 SubString[Length] = L'\0';
1156 }
1157 }
1158
1159 Result->Type = EFI_IFR_TYPE_STRING;
1160 Result->Value.string = NewString (SubString, FormSet->HiiHandle);
1161
1162 FreePool (String);
1163 } else {
1164 Buffer = Value.Buffer;
1165 BufferLen = Value.BufferLen;
1166
1167 Result->Type = EFI_IFR_TYPE_BUFFER;
1168 if (Length == 0 || Base >= BufferLen) {
1169 Result->BufferLen = 0;
1170 Result->Buffer = NULL;
1171 } else {
1172 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);
1173 Result->Buffer = AllocateZeroPool (Result->BufferLen);
1174 ASSERT (Result->Buffer != NULL);
1175 CopyMem (Result->Buffer, &Value.Buffer[Base], Result->BufferLen);
1176 }
1177
1178 FreePool (Value.Buffer);
1179 }
1180
1181 return Status;
1182 }
1183
1184
1185 /**
1186 Evaluate opcode EFI_IFR_TOKEN.
1187
1188 @param FormSet Formset which contains this opcode.
1189 @param Result Evaluation result for this opcode.
1190
1191 @retval EFI_SUCCESS Opcode evaluation success.
1192 @retval Other Opcode evaluation failed.
1193
1194 **/
1195 EFI_STATUS
1196 IfrToken (
1197 IN FORM_BROWSER_FORMSET *FormSet,
1198 OUT EFI_HII_VALUE *Result
1199 )
1200 {
1201 EFI_STATUS Status;
1202 EFI_HII_VALUE Value;
1203 CHAR16 *String[2];
1204 UINTN Count;
1205 CHAR16 *Delimiter;
1206 CHAR16 *SubString;
1207 CHAR16 *StringPtr;
1208 UINTN Index;
1209
1210 Status = PopExpression (&Value);
1211 if (EFI_ERROR (Status)) {
1212 return Status;
1213 }
1214 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1215 return EFI_UNSUPPORTED;
1216 }
1217 Count = (UINTN) Value.Value.u64;
1218
1219 //
1220 // String[0] - Delimiter
1221 // String[1] - The string to search
1222 //
1223 String[0] = NULL;
1224 String[1] = NULL;
1225 for (Index = 0; Index < 2; Index++) {
1226 Status = PopExpression (&Value);
1227 if (EFI_ERROR (Status)) {
1228 goto Done;
1229 }
1230
1231 if (Value.Type != EFI_IFR_TYPE_STRING) {
1232 Status = EFI_UNSUPPORTED;
1233 goto Done;
1234 }
1235
1236 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
1237 if (String[Index] == NULL) {
1238 Status = EFI_NOT_FOUND;
1239 goto Done;
1240 }
1241 }
1242
1243 Delimiter = String[0];
1244 SubString = String[1];
1245 while (Count > 0) {
1246 SubString = StrStr (SubString, Delimiter);
1247 if (SubString != NULL) {
1248 //
1249 // Skip over the delimiter
1250 //
1251 SubString = SubString + StrLen (Delimiter);
1252 } else {
1253 break;
1254 }
1255 Count--;
1256 }
1257
1258 if (SubString == NULL) {
1259 //
1260 // nth delimited sub-string not found, push an empty string
1261 //
1262 SubString = gEmptyString;
1263 } else {
1264 //
1265 // Put a NULL terminator for nth delimited sub-string
1266 //
1267 StringPtr = StrStr (SubString, Delimiter);
1268 if (StringPtr != NULL) {
1269 *StringPtr = L'\0';
1270 }
1271 }
1272
1273 Result->Type = EFI_IFR_TYPE_STRING;
1274 Result->Value.string = NewString (SubString, FormSet->HiiHandle);
1275
1276 Done:
1277 if (String[0] != NULL) {
1278 FreePool (String[0]);
1279 }
1280 if (String[1] != NULL) {
1281 FreePool (String[1]);
1282 }
1283
1284 return Status;
1285 }
1286
1287
1288 /**
1289 Evaluate opcode EFI_IFR_SPAN.
1290
1291 @param FormSet Formset which contains this opcode.
1292 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.
1293 @param Result Evaluation result for this opcode.
1294
1295 @retval EFI_SUCCESS Opcode evaluation success.
1296 @retval Other Opcode evaluation failed.
1297
1298 **/
1299 EFI_STATUS
1300 IfrSpan (
1301 IN FORM_BROWSER_FORMSET *FormSet,
1302 IN UINT8 Flags,
1303 OUT EFI_HII_VALUE *Result
1304 )
1305 {
1306 EFI_STATUS Status;
1307 EFI_HII_VALUE Value;
1308 CHAR16 *String[2];
1309 CHAR16 *Charset;
1310 UINTN Base;
1311 UINTN Index;
1312 CHAR16 *StringPtr;
1313 BOOLEAN Found;
1314
1315 Status = PopExpression (&Value);
1316 if (EFI_ERROR (Status)) {
1317 return Status;
1318 }
1319 if (Value.Type > EFI_IFR_TYPE_NUM_SIZE_64) {
1320 return EFI_UNSUPPORTED;
1321 }
1322 Base = (UINTN) Value.Value.u64;
1323
1324 //
1325 // String[0] - Charset
1326 // String[1] - The string to search
1327 //
1328 String[0] = NULL;
1329 String[1] = NULL;
1330 for (Index = 0; Index < 2; Index++) {
1331 Status = PopExpression (&Value);
1332 if (EFI_ERROR (Status)) {
1333 goto Done;
1334 }
1335
1336 if (Value.Type != EFI_IFR_TYPE_STRING) {
1337 Status = EFI_UNSUPPORTED;
1338 goto Done;
1339 }
1340
1341 String[Index] = GetToken (Value.Value.string, FormSet->HiiHandle);
1342 if (String [Index] == NULL) {
1343 Status = EFI_NOT_FOUND;
1344 goto Done;
1345 }
1346 }
1347
1348 if (Base >= StrLen (String[1])) {
1349 Status = EFI_UNSUPPORTED;
1350 goto Done;
1351 }
1352
1353 Found = FALSE;
1354 StringPtr = String[1] + Base;
1355 Charset = String[0];
1356 while (*StringPtr != 0 && !Found) {
1357 Index = 0;
1358 while (Charset[Index] != 0) {
1359 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {
1360 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
1361 Found = TRUE;
1362 break;
1363 }
1364 } else {
1365 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
1366 Found = TRUE;
1367 break;
1368 }
1369 }
1370 //
1371 // Skip characters pair representing low-end of a range and high-end of a range
1372 //
1373 Index += 2;
1374 }
1375
1376 if (!Found) {
1377 StringPtr++;
1378 }
1379 }
1380
1381 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
1382 Result->Value.u64 = StringPtr - String[1];
1383
1384 Done:
1385 if (String[0] != NULL) {
1386 FreePool (String[0]);
1387 }
1388 if (String[1] != NULL) {
1389 FreePool (String[1]);
1390 }
1391
1392 return Status;
1393 }
1394
1395
1396 /**
1397 Zero extend integer/boolean/date/time to UINT64 for comparing.
1398
1399 @param Value HII Value to be converted.
1400
1401 **/
1402 VOID
1403 ExtendValueToU64 (
1404 IN EFI_HII_VALUE *Value
1405 )
1406 {
1407 UINT64 Temp;
1408
1409 Temp = 0;
1410 switch (Value->Type) {
1411 case EFI_IFR_TYPE_NUM_SIZE_8:
1412 Temp = Value->Value.u8;
1413 break;
1414
1415 case EFI_IFR_TYPE_NUM_SIZE_16:
1416 Temp = Value->Value.u16;
1417 break;
1418
1419 case EFI_IFR_TYPE_NUM_SIZE_32:
1420 Temp = Value->Value.u32;
1421 break;
1422
1423 case EFI_IFR_TYPE_BOOLEAN:
1424 Temp = Value->Value.b;
1425 break;
1426
1427 case EFI_IFR_TYPE_TIME:
1428 Temp = Value->Value.u32 & 0xffffff;
1429 break;
1430
1431 case EFI_IFR_TYPE_DATE:
1432 Temp = Value->Value.u32;
1433 break;
1434
1435 default:
1436 return;
1437 }
1438
1439 Value->Value.u64 = Temp;
1440 }
1441
1442
1443 /**
1444 Compare two Hii value.
1445
1446 @param Value1 Expression value to compare on left-hand.
1447 @param Value2 Expression value to compare on right-hand.
1448 @param HiiHandle Only required for string compare.
1449
1450 @retval EFI_INVALID_PARAMETER Could not perform compare on two values.
1451 @retval 0 Two operators equal.
1452 @return Positive value if Value1 is greater than Value2.
1453 @retval Negative value if Value1 is less than Value2.
1454
1455 **/
1456 INTN
1457 CompareHiiValue (
1458 IN EFI_HII_VALUE *Value1,
1459 IN EFI_HII_VALUE *Value2,
1460 IN EFI_HII_HANDLE HiiHandle OPTIONAL
1461 )
1462 {
1463 INTN Result;
1464 INT64 Temp64;
1465 CHAR16 *Str1;
1466 CHAR16 *Str2;
1467 UINTN Len;
1468
1469 if (Value1->Type >= EFI_IFR_TYPE_OTHER || Value2->Type >= EFI_IFR_TYPE_OTHER ) {
1470 if (Value1->Type != EFI_IFR_TYPE_BUFFER && Value2->Type != EFI_IFR_TYPE_BUFFER) {
1471 return EFI_INVALID_PARAMETER;
1472 }
1473 }
1474
1475 if (Value1->Type == EFI_IFR_TYPE_STRING || Value2->Type == EFI_IFR_TYPE_STRING ) {
1476 if (Value1->Type != Value2->Type) {
1477 //
1478 // Both Operator should be type of String
1479 //
1480 return EFI_INVALID_PARAMETER;
1481 }
1482
1483 if (Value1->Value.string == 0 || Value2->Value.string == 0) {
1484 //
1485 // StringId 0 is reserved
1486 //
1487 return EFI_INVALID_PARAMETER;
1488 }
1489
1490 if (Value1->Value.string == Value2->Value.string) {
1491 return 0;
1492 }
1493
1494 Str1 = GetToken (Value1->Value.string, HiiHandle);
1495 if (Str1 == NULL) {
1496 //
1497 // String not found
1498 //
1499 return EFI_INVALID_PARAMETER;
1500 }
1501
1502 Str2 = GetToken (Value2->Value.string, HiiHandle);
1503 if (Str2 == NULL) {
1504 FreePool (Str1);
1505 return EFI_INVALID_PARAMETER;
1506 }
1507
1508 Result = StrCmp (Str1, Str2);
1509
1510 FreePool (Str1);
1511 FreePool (Str2);
1512
1513 return Result;
1514 }
1515
1516 if (Value1->Type == EFI_IFR_TYPE_BUFFER || Value2->Type == EFI_IFR_TYPE_BUFFER ) {
1517 if (Value1->Type != Value2->Type) {
1518 //
1519 // Both Operator should be type of Buffer.
1520 //
1521 return EFI_INVALID_PARAMETER;
1522 }
1523 Len = Value1->BufferLen > Value2->BufferLen ? Value2->BufferLen : Value1->BufferLen;
1524 Result = CompareMem (Value1->Buffer, Value2->Buffer, Len);
1525 if ((Result == 0) && (Value1->BufferLen != Value2->BufferLen))
1526 {
1527 //
1528 // In this case, means base on samll number buffer, the data is same
1529 // So which value has more data, which value is bigger.
1530 //
1531 Result = Value1->BufferLen > Value2->BufferLen ? 1 : -1;
1532 }
1533 return Result;
1534 }
1535
1536 //
1537 // Take remain types(integer, boolean, date/time) as integer
1538 //
1539 Temp64 = (INT64) (Value1->Value.u64 - Value2->Value.u64);
1540 if (Temp64 > 0) {
1541 Result = 1;
1542 } else if (Temp64 < 0) {
1543 Result = -1;
1544 } else {
1545 Result = 0;
1546 }
1547
1548 return Result;
1549 }
1550
1551 /**
1552 Check if current user has the privilege specified by the permissions GUID.
1553
1554 @param[in] Guid A GUID specifying setup access permissions.
1555
1556 @retval TRUE Current user has the privilege.
1557 @retval FALSE Current user does not have the privilege.
1558 **/
1559 BOOLEAN
1560 CheckUserPrivilege (
1561 IN EFI_GUID *Guid
1562 )
1563 {
1564 EFI_STATUS Status;
1565 EFI_USER_PROFILE_HANDLE UserProfileHandle;
1566 EFI_USER_INFO_HANDLE UserInfoHandle;
1567 EFI_USER_INFO *UserInfo;
1568 EFI_GUID *UserPermissionsGuid;
1569 UINTN UserInfoSize;
1570 UINTN AccessControlDataSize;
1571 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;
1572 UINTN RemainSize;
1573
1574 if (mUserManager == NULL) {
1575 Status = gBS->LocateProtocol (
1576 &gEfiUserManagerProtocolGuid,
1577 NULL,
1578 (VOID **) &mUserManager
1579 );
1580 if (EFI_ERROR (Status)) {
1581 ///
1582 /// If the system does not support user management, then it is assumed that
1583 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
1584 /// op-code is always TRUE.
1585 ///
1586 return TRUE;
1587 }
1588 }
1589
1590 Status = mUserManager->Current (mUserManager, &UserProfileHandle);
1591 ASSERT_EFI_ERROR (Status);
1592
1593 ///
1594 /// Enumerate all user information of the current user profile
1595 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
1596 ///
1597
1598 for (UserInfoHandle = NULL;;) {
1599 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);
1600 if (EFI_ERROR (Status)) {
1601 break;
1602 }
1603
1604 UserInfoSize = 0;
1605 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);
1606 if (Status != EFI_BUFFER_TOO_SMALL) {
1607 continue;
1608 }
1609
1610 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);
1611 if (UserInfo == NULL) {
1612 break;
1613 }
1614
1615 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);
1616 if (EFI_ERROR (Status) ||
1617 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||
1618 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {
1619 FreePool (UserInfo);
1620 continue;
1621 }
1622
1623 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);
1624 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);
1625 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
1626 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
1627 break;
1628 }
1629 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {
1630 ///
1631 /// Check if current user has the privilege specified by the permissions GUID.
1632 ///
1633
1634 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);
1635 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);
1636 while (AccessControlDataSize >= sizeof (EFI_GUID)) {
1637 if (CompareGuid (Guid, UserPermissionsGuid)) {
1638 FreePool (UserInfo);
1639 return TRUE;
1640 }
1641 UserPermissionsGuid++;
1642 AccessControlDataSize -= sizeof (EFI_GUID);
1643 }
1644 }
1645 RemainSize -= AccessControl->Size;
1646 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);
1647 }
1648
1649 FreePool (UserInfo);
1650 }
1651 return FALSE;
1652 }
1653
1654 /**
1655 Evaluate the result of a HII expression.
1656
1657 If Expression is NULL, then ASSERT.
1658
1659 @param FormSet FormSet associated with this expression.
1660 @param Form Form associated with this expression.
1661 @param Expression Expression to be evaluated.
1662
1663 @retval EFI_SUCCESS The expression evaluated successfuly
1664 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
1665 could not be found.
1666 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
1667 stack.
1668 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1669 @retval EFI_INVALID_PARAMETER Syntax error with the Expression
1670
1671 **/
1672 EFI_STATUS
1673 EvaluateExpression (
1674 IN FORM_BROWSER_FORMSET *FormSet,
1675 IN FORM_BROWSER_FORM *Form,
1676 IN OUT FORM_EXPRESSION *Expression
1677 )
1678 {
1679 EFI_STATUS Status;
1680 LIST_ENTRY *Link;
1681 EXPRESSION_OPCODE *OpCode;
1682 FORM_BROWSER_STATEMENT *Question;
1683 FORM_BROWSER_STATEMENT *Question2;
1684 UINT16 Index;
1685 EFI_HII_VALUE Data1;
1686 EFI_HII_VALUE Data2;
1687 EFI_HII_VALUE Data3;
1688 FORM_EXPRESSION *RuleExpression;
1689 EFI_HII_VALUE *Value;
1690 INTN Result;
1691 CHAR16 *StrPtr;
1692 CHAR16 *NameValue;
1693 UINT32 TempValue;
1694 LIST_ENTRY *SubExpressionLink;
1695 FORM_EXPRESSION *SubExpression;
1696 UINTN StackOffset;
1697 UINTN TempLength;
1698 CHAR16 TempStr[5];
1699 UINT8 DigitUint8;
1700 UINT8 *TempBuffer;
1701 EFI_TIME EfiTime;
1702
1703 //
1704 // Save current stack offset.
1705 //
1706 StackOffset = SaveExpressionEvaluationStackOffset ();
1707
1708 ASSERT (Expression != NULL);
1709 Expression->Result.Type = EFI_IFR_TYPE_OTHER;
1710
1711 Link = GetFirstNode (&Expression->OpCodeListHead);
1712 while (!IsNull (&Expression->OpCodeListHead, Link)) {
1713 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
1714
1715 Link = GetNextNode (&Expression->OpCodeListHead, Link);
1716
1717 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
1718 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
1719 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
1720
1721 Value = &Data3;
1722 Value->Type = EFI_IFR_TYPE_BOOLEAN;
1723 Status = EFI_SUCCESS;
1724
1725 switch (OpCode->Operand) {
1726 //
1727 // Built-in functions
1728 //
1729 case EFI_IFR_EQ_ID_VAL_OP:
1730 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1731 if (Question == NULL) {
1732 Status = EFI_NOT_FOUND;
1733 goto Done;
1734 }
1735
1736 Result = CompareHiiValue (&Question->HiiValue, &OpCode->Value, NULL);
1737 if (Result == EFI_INVALID_PARAMETER) {
1738 Status = EFI_INVALID_PARAMETER;
1739 goto Done;
1740 }
1741 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
1742 break;
1743
1744 case EFI_IFR_EQ_ID_ID_OP:
1745 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1746 if (Question == NULL) {
1747 Status = EFI_NOT_FOUND;
1748 goto Done;
1749 }
1750
1751 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);
1752 if (Question2 == NULL) {
1753 Status = EFI_NOT_FOUND;
1754 goto Done;
1755 }
1756
1757 Result = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, FormSet->HiiHandle);
1758 if (Result == EFI_INVALID_PARAMETER) {
1759 Status = EFI_INVALID_PARAMETER;
1760 goto Done;
1761 }
1762 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
1763 break;
1764
1765 case EFI_IFR_EQ_ID_LIST_OP:
1766 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1767 if (Question == NULL) {
1768 Status = EFI_NOT_FOUND;
1769 goto Done;
1770 }
1771
1772 Value->Value.b = FALSE;
1773 for (Index =0; Index < OpCode->ListLength; Index++) {
1774 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {
1775 Value->Value.b = TRUE;
1776 break;
1777 }
1778 }
1779 break;
1780
1781 case EFI_IFR_DUP_OP:
1782 Status = PopExpression (Value);
1783 if (EFI_ERROR (Status)) {
1784 goto Done;
1785 }
1786
1787 Status = PushExpression (Value);
1788 break;
1789
1790 case EFI_IFR_QUESTION_REF1_OP:
1791 case EFI_IFR_THIS_OP:
1792 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);
1793 if (Question == NULL) {
1794 Status = EFI_NOT_FOUND;
1795 goto Done;
1796 }
1797
1798 Value = &Question->HiiValue;
1799 break;
1800
1801 case EFI_IFR_SECURITY_OP:
1802 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);
1803 break;
1804
1805 case EFI_IFR_GET_OP:
1806 //
1807 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
1808 //
1809 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1810 Value->Value.u8 = 0;
1811 if (OpCode->VarStorage != NULL) {
1812 switch (OpCode->VarStorage->Type) {
1813 case EFI_HII_VARSTORE_BUFFER:
1814 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
1815 //
1816 // Get value from Edit Buffer
1817 //
1818 Value->Type = OpCode->ValueType;
1819 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);
1820 break;
1821 case EFI_HII_VARSTORE_NAME_VALUE:
1822 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {
1823 //
1824 // Get value from string except for STRING value.
1825 //
1826 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr);
1827 if (!EFI_ERROR (Status)) {
1828 ASSERT (StrPtr != NULL);
1829 TempLength = StrLen (StrPtr);
1830 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {
1831 Value->Type = OpCode->ValueType;
1832 TempBuffer = (UINT8 *) &Value->Value;
1833 ZeroMem (TempStr, sizeof (TempStr));
1834 for (Index = 0; Index < TempLength; Index ++) {
1835 TempStr[0] = StrPtr[TempLength - Index - 1];
1836 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);
1837 if ((Index & 1) == 0) {
1838 TempBuffer [Index/2] = DigitUint8;
1839 } else {
1840 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);
1841 }
1842 }
1843 }
1844 }
1845 }
1846 break;
1847 case EFI_HII_VARSTORE_EFI_VARIABLE:
1848 //
1849 // Get value from variable.
1850 //
1851 TempLength = OpCode->ValueWidth;
1852 Value->Type = OpCode->ValueType;
1853 Status = gRT->GetVariable (
1854 OpCode->ValueName,
1855 &OpCode->VarStorage->Guid,
1856 NULL,
1857 &TempLength,
1858 &Value->Value
1859 );
1860 if (EFI_ERROR (Status)) {
1861 Value->Type = EFI_IFR_TYPE_UNDEFINED;
1862 Value->Value.u8 = 0;
1863 }
1864 break;
1865 default:
1866 //
1867 // Not recognize storage.
1868 //
1869 Status = EFI_UNSUPPORTED;
1870 goto Done;
1871 }
1872 } else {
1873 //
1874 // For Time/Date Data
1875 //
1876 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {
1877 //
1878 // Only support Data/Time data when storage doesn't exist.
1879 //
1880 Status = EFI_UNSUPPORTED;
1881 goto Done;
1882 }
1883 Status = gRT->GetTime (&EfiTime, NULL);
1884 if (!EFI_ERROR (Status)) {
1885 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
1886 switch (OpCode->VarStoreInfo.VarOffset) {
1887 case 0x00:
1888 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
1889 Value->Value.u16 = EfiTime.Year;
1890 break;
1891 case 0x02:
1892 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1893 Value->Value.u8 = EfiTime.Month;
1894 break;
1895 case 0x03:
1896 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1897 Value->Value.u8 = EfiTime.Day;
1898 break;
1899 default:
1900 //
1901 // Invalid Date field.
1902 //
1903 Status = EFI_INVALID_PARAMETER;
1904 goto Done;
1905 }
1906 } else {
1907 switch (OpCode->VarStoreInfo.VarOffset) {
1908 case 0x00:
1909 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1910 Value->Value.u8 = EfiTime.Hour;
1911 break;
1912 case 0x01:
1913 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1914 Value->Value.u8 = EfiTime.Minute;
1915 break;
1916 case 0x02:
1917 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
1918 Value->Value.u8 = EfiTime.Second;
1919 break;
1920 default:
1921 //
1922 // Invalid Time field.
1923 //
1924 Status = EFI_INVALID_PARAMETER;
1925 goto Done;
1926 }
1927 }
1928 }
1929 }
1930
1931 break;
1932
1933 case EFI_IFR_QUESTION_REF3_OP:
1934 if (OpCode->DevicePath == 0) {
1935 //
1936 // EFI_IFR_QUESTION_REF3
1937 // Pop an expression from the expression stack
1938 //
1939 Status = PopExpression (Value);
1940 if (EFI_ERROR (Status)) {
1941 goto Done;
1942 }
1943
1944 //
1945 // Validate the expression value
1946 //
1947 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
1948 Status = EFI_NOT_FOUND;
1949 goto Done;
1950 }
1951
1952 Question = IdToQuestion (FormSet, Form, Value->Value.u16);
1953 if (Question == NULL) {
1954 Status = EFI_NOT_FOUND;
1955 goto Done;
1956 }
1957
1958 //
1959 // push the questions' value on to the expression stack
1960 //
1961 Value = &Question->HiiValue;
1962 } else {
1963 //
1964 // BUGBUG: push 0 for EFI_IFR_QUESTION_REF3_2 and EFI_IFR_QUESTION_REF3_3,
1965 // since it is impractical to evaluate the value of a Question in another
1966 // Hii Package list.
1967 //
1968 ZeroMem (Value, sizeof (EFI_HII_VALUE));
1969 }
1970 break;
1971
1972 case EFI_IFR_RULE_REF_OP:
1973 //
1974 // Find expression for this rule
1975 //
1976 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);
1977 if (RuleExpression == NULL) {
1978 Status = EFI_NOT_FOUND;
1979 goto Done;
1980 }
1981
1982 //
1983 // Evaluate this rule expression
1984 //
1985 Status = EvaluateExpression (FormSet, Form, RuleExpression);
1986 if (EFI_ERROR (Status)) {
1987 goto Done;
1988 }
1989
1990 Value = &RuleExpression->Result;
1991 break;
1992
1993 case EFI_IFR_STRING_REF1_OP:
1994 Value->Type = EFI_IFR_TYPE_STRING;
1995 Value->Value.string = OpCode->Value.Value.string;
1996 break;
1997
1998 //
1999 // Constant
2000 //
2001 case EFI_IFR_TRUE_OP:
2002 case EFI_IFR_FALSE_OP:
2003 case EFI_IFR_ONE_OP:
2004 case EFI_IFR_ONES_OP:
2005 case EFI_IFR_UINT8_OP:
2006 case EFI_IFR_UINT16_OP:
2007 case EFI_IFR_UINT32_OP:
2008 case EFI_IFR_UINT64_OP:
2009 case EFI_IFR_UNDEFINED_OP:
2010 case EFI_IFR_VERSION_OP:
2011 case EFI_IFR_ZERO_OP:
2012 Value = &OpCode->Value;
2013 break;
2014
2015 //
2016 // unary-op
2017 //
2018 case EFI_IFR_LENGTH_OP:
2019 Status = PopExpression (Value);
2020 if (EFI_ERROR (Status)) {
2021 goto Done;
2022 }
2023 if (Value->Type != EFI_IFR_TYPE_STRING && Value->Type != EFI_IFR_TYPE_BUFFER) {
2024 Status = EFI_INVALID_PARAMETER;
2025 goto Done;
2026 }
2027
2028 if (Value->Type == EFI_IFR_TYPE_STRING) {
2029 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
2030 if (StrPtr == NULL) {
2031 Status = EFI_INVALID_PARAMETER;
2032 goto Done;
2033 }
2034
2035 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2036 Value->Value.u64 = StrLen (StrPtr);
2037 FreePool (StrPtr);
2038 } else {
2039 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2040 Value->Value.u64 = Value->BufferLen;
2041 FreePool (Value->Buffer);
2042 }
2043 break;
2044
2045 case EFI_IFR_NOT_OP:
2046 Status = PopExpression (Value);
2047 if (EFI_ERROR (Status)) {
2048 goto Done;
2049 }
2050 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
2051 Status = EFI_INVALID_PARAMETER;
2052 goto Done;
2053 }
2054 Value->Value.b = (BOOLEAN) (!Value->Value.b);
2055 break;
2056
2057 case EFI_IFR_QUESTION_REF2_OP:
2058 //
2059 // Pop an expression from the expression stack
2060 //
2061 Status = PopExpression (Value);
2062 if (EFI_ERROR (Status)) {
2063 goto Done;
2064 }
2065
2066 //
2067 // Validate the expression value
2068 //
2069 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
2070 Status = EFI_NOT_FOUND;
2071 goto Done;
2072 }
2073
2074 Question = IdToQuestion (FormSet, Form, Value->Value.u16);
2075 if (Question == NULL) {
2076 Status = EFI_NOT_FOUND;
2077 goto Done;
2078 }
2079
2080 Value = &Question->HiiValue;
2081 break;
2082
2083 case EFI_IFR_STRING_REF2_OP:
2084 //
2085 // Pop an expression from the expression stack
2086 //
2087 Status = PopExpression (Value);
2088 if (EFI_ERROR (Status)) {
2089 goto Done;
2090 }
2091
2092 //
2093 // Validate the expression value
2094 //
2095 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
2096 Status = EFI_NOT_FOUND;
2097 goto Done;
2098 }
2099
2100 Value->Type = EFI_IFR_TYPE_STRING;
2101 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);
2102 if (StrPtr == NULL) {
2103 //
2104 // If String not exit, push an empty string
2105 //
2106 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);
2107 } else {
2108 Index = (UINT16) Value->Value.u64;
2109 Value->Value.string = Index;
2110 FreePool (StrPtr);
2111 }
2112 break;
2113
2114 case EFI_IFR_TO_BOOLEAN_OP:
2115 //
2116 // Pop an expression from the expression stack
2117 //
2118 Status = PopExpression (Value);
2119 if (EFI_ERROR (Status)) {
2120 goto Done;
2121 }
2122
2123 //
2124 // Convert an expression to a Boolean
2125 //
2126 if (Value->Type <= EFI_IFR_TYPE_DATE) {
2127 //
2128 // When converting from an unsigned integer, zero will be converted to
2129 // FALSE and any other value will be converted to TRUE.
2130 //
2131 Value->Value.b = (BOOLEAN) (Value->Value.u64 != 0);
2132
2133 Value->Type = EFI_IFR_TYPE_BOOLEAN;
2134 } else if (Value->Type == EFI_IFR_TYPE_STRING) {
2135 //
2136 // When converting from a string, if case-insensitive compare
2137 // with "true" is True, then push True. If a case-insensitive compare
2138 // with "false" is True, then push False. Otherwise, push Undefined.
2139 //
2140 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
2141 if (StrPtr == NULL) {
2142 Status = EFI_INVALID_PARAMETER;
2143 goto Done;
2144 }
2145
2146 IfrStrToUpper (StrPtr);
2147 if (StrCmp (StrPtr, L"TRUE") == 0){
2148 Value->Value.b = TRUE;
2149 } else if (StrCmp (StrPtr, L"FALSE") == 0) {
2150 Value->Value.b = FALSE;
2151 } else {
2152 Status = EFI_INVALID_PARAMETER;
2153 FreePool (StrPtr);
2154 goto Done;
2155 }
2156 FreePool (StrPtr);
2157 Value->Type = EFI_IFR_TYPE_BOOLEAN;
2158 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {
2159 //
2160 // When converting from a buffer, if the buffer is all zeroes,
2161 // then push False. Otherwise push True.
2162 //
2163 for (Index =0; Index < Value->BufferLen; Index ++) {
2164 if (Value->Buffer[Index] != 0) {
2165 break;
2166 }
2167 }
2168
2169 if (Index >= Value->BufferLen) {
2170 Value->Value.b = FALSE;
2171 } else {
2172 Value->Value.b = TRUE;
2173 }
2174 Value->Type = EFI_IFR_TYPE_BOOLEAN;
2175 FreePool (Value->Buffer);
2176 }
2177 break;
2178
2179 case EFI_IFR_TO_STRING_OP:
2180 Status = IfrToString (FormSet, OpCode->Format, Value);
2181 break;
2182
2183 case EFI_IFR_TO_UINT_OP:
2184 Status = IfrToUint (FormSet, Value);
2185 break;
2186
2187 case EFI_IFR_TO_LOWER_OP:
2188 case EFI_IFR_TO_UPPER_OP:
2189 Status = InitializeUnicodeCollationProtocol ();
2190 if (EFI_ERROR (Status)) {
2191 goto Done;
2192 }
2193
2194 Status = PopExpression (Value);
2195 if (EFI_ERROR (Status)) {
2196 goto Done;
2197 }
2198
2199 if (Value->Type != EFI_IFR_TYPE_STRING) {
2200 Status = EFI_UNSUPPORTED;
2201 goto Done;
2202 }
2203
2204 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);
2205 if (StrPtr == NULL) {
2206 Status = EFI_NOT_FOUND;
2207 goto Done;
2208 }
2209
2210 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
2211 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
2212 } else {
2213 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
2214 }
2215 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);
2216 FreePool (StrPtr);
2217 break;
2218
2219 case EFI_IFR_BITWISE_NOT_OP:
2220 //
2221 // Pop an expression from the expression stack
2222 //
2223 Status = PopExpression (Value);
2224 if (EFI_ERROR (Status)) {
2225 goto Done;
2226 }
2227 if (Value->Type > EFI_IFR_TYPE_DATE) {
2228 Status = EFI_INVALID_PARAMETER;
2229 goto Done;
2230 }
2231
2232 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2233 Value->Value.u64 = ~Value->Value.u64;
2234 break;
2235
2236 case EFI_IFR_SET_OP:
2237 //
2238 // Pop an expression from the expression stack
2239 //
2240 Status = PopExpression (Value);
2241 if (EFI_ERROR (Status)) {
2242 goto Done;
2243 }
2244 Data1.Type = EFI_IFR_TYPE_BOOLEAN;
2245 Data1.Value.b = FALSE;
2246 //
2247 // Set value to var storage buffer
2248 //
2249 if (OpCode->VarStorage != NULL) {
2250 switch (OpCode->VarStorage->Type) {
2251 case EFI_HII_VARSTORE_BUFFER:
2252 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
2253 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);
2254 Data1.Value.b = TRUE;
2255 break;
2256 case EFI_HII_VARSTORE_NAME_VALUE:
2257 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {
2258 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));
2259 ASSERT (Value != NULL);
2260 //
2261 // Convert Buffer to Hex String
2262 //
2263 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;
2264 StrPtr = NameValue;
2265 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {
2266 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);
2267 }
2268 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, TRUE);
2269 FreePool (NameValue);
2270 if (!EFI_ERROR (Status)) {
2271 Data1.Value.b = TRUE;
2272 }
2273 }
2274 break;
2275 case EFI_HII_VARSTORE_EFI_VARIABLE:
2276 Status = gRT->SetVariable (
2277 OpCode->ValueName,
2278 &OpCode->VarStorage->Guid,
2279 OpCode->VarStorage->Attributes,
2280 OpCode->ValueWidth,
2281 &Value->Value
2282 );
2283 if (!EFI_ERROR (Status)) {
2284 Data1.Value.b = TRUE;
2285 }
2286 break;
2287 default:
2288 //
2289 // Not recognize storage.
2290 //
2291 Status = EFI_UNSUPPORTED;
2292 goto Done;
2293 break;
2294 }
2295 } else {
2296 //
2297 // For Time/Date Data
2298 //
2299 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {
2300 //
2301 // Only support Data/Time data when storage doesn't exist.
2302 //
2303 Status = EFI_UNSUPPORTED;
2304 goto Done;
2305 }
2306 Status = gRT->GetTime (&EfiTime, NULL);
2307 if (!EFI_ERROR (Status)) {
2308 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {
2309 switch (OpCode->VarStoreInfo.VarOffset) {
2310 case 0x00:
2311 EfiTime.Year = Value->Value.u16;
2312 break;
2313 case 0x02:
2314 EfiTime.Month = Value->Value.u8;
2315 break;
2316 case 0x03:
2317 EfiTime.Day = Value->Value.u8;
2318 break;
2319 default:
2320 //
2321 // Invalid Date field.
2322 //
2323 Status = EFI_INVALID_PARAMETER;
2324 goto Done;
2325 }
2326 } else {
2327 switch (OpCode->VarStoreInfo.VarOffset) {
2328 case 0x00:
2329 EfiTime.Hour = Value->Value.u8;
2330 break;
2331 case 0x01:
2332 EfiTime.Minute = Value->Value.u8;
2333 break;
2334 case 0x02:
2335 EfiTime.Second = Value->Value.u8;
2336 break;
2337 default:
2338 //
2339 // Invalid Time field.
2340 //
2341 Status = EFI_INVALID_PARAMETER;
2342 goto Done;
2343 }
2344 }
2345 Status = gRT->SetTime (&EfiTime);
2346 if (!EFI_ERROR (Status)) {
2347 Data1.Value.b = TRUE;
2348 }
2349 }
2350 }
2351 Value = &Data1;
2352 break;
2353
2354 //
2355 // binary-op
2356 //
2357 case EFI_IFR_ADD_OP:
2358 case EFI_IFR_SUBTRACT_OP:
2359 case EFI_IFR_MULTIPLY_OP:
2360 case EFI_IFR_DIVIDE_OP:
2361 case EFI_IFR_MODULO_OP:
2362 case EFI_IFR_BITWISE_AND_OP:
2363 case EFI_IFR_BITWISE_OR_OP:
2364 case EFI_IFR_SHIFT_LEFT_OP:
2365 case EFI_IFR_SHIFT_RIGHT_OP:
2366 //
2367 // Pop an expression from the expression stack
2368 //
2369 Status = PopExpression (&Data2);
2370 if (EFI_ERROR (Status)) {
2371 goto Done;
2372 }
2373 if (Data2.Type > EFI_IFR_TYPE_DATE) {
2374 Status = EFI_INVALID_PARAMETER;
2375 goto Done;
2376 }
2377
2378 //
2379 // Pop another expression from the expression stack
2380 //
2381 Status = PopExpression (&Data1);
2382 if (EFI_ERROR (Status)) {
2383 goto Done;
2384 }
2385 if (Data1.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
2392 switch (OpCode->Operand) {
2393 case EFI_IFR_ADD_OP:
2394 Value->Value.u64 = Data1.Value.u64 + Data2.Value.u64;
2395 break;
2396
2397 case EFI_IFR_SUBTRACT_OP:
2398 Value->Value.u64 = Data1.Value.u64 - Data2.Value.u64;
2399 break;
2400
2401 case EFI_IFR_MULTIPLY_OP:
2402 Value->Value.u64 = MultU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
2403 break;
2404
2405 case EFI_IFR_DIVIDE_OP:
2406 Value->Value.u64 = DivU64x32 (Data1.Value.u64, (UINT32) Data2.Value.u64);
2407 break;
2408
2409 case EFI_IFR_MODULO_OP:
2410 DivU64x32Remainder (Data1.Value.u64, (UINT32) Data2.Value.u64, &TempValue);
2411 Value->Value.u64 = TempValue;
2412 break;
2413
2414 case EFI_IFR_BITWISE_AND_OP:
2415 Value->Value.u64 = Data1.Value.u64 & Data2.Value.u64;
2416 break;
2417
2418 case EFI_IFR_BITWISE_OR_OP:
2419 Value->Value.u64 = Data1.Value.u64 | Data2.Value.u64;
2420 break;
2421
2422 case EFI_IFR_SHIFT_LEFT_OP:
2423 Value->Value.u64 = LShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
2424 break;
2425
2426 case EFI_IFR_SHIFT_RIGHT_OP:
2427 Value->Value.u64 = RShiftU64 (Data1.Value.u64, (UINTN) Data2.Value.u64);
2428 break;
2429
2430 default:
2431 break;
2432 }
2433 break;
2434
2435 case EFI_IFR_AND_OP:
2436 case EFI_IFR_OR_OP:
2437 //
2438 // Two Boolean operator
2439 //
2440 Status = PopExpression (&Data2);
2441 if (EFI_ERROR (Status)) {
2442 goto Done;
2443 }
2444 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
2445 Status = EFI_INVALID_PARAMETER;
2446 goto Done;
2447 }
2448
2449 //
2450 // Pop another expression from the expression stack
2451 //
2452 Status = PopExpression (&Data1);
2453 if (EFI_ERROR (Status)) {
2454 goto Done;
2455 }
2456 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
2457 Status = EFI_INVALID_PARAMETER;
2458 goto Done;
2459 }
2460
2461 if (OpCode->Operand == EFI_IFR_AND_OP) {
2462 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);
2463 } else {
2464 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);
2465 }
2466 break;
2467
2468 case EFI_IFR_EQUAL_OP:
2469 case EFI_IFR_NOT_EQUAL_OP:
2470 case EFI_IFR_GREATER_EQUAL_OP:
2471 case EFI_IFR_GREATER_THAN_OP:
2472 case EFI_IFR_LESS_EQUAL_OP:
2473 case EFI_IFR_LESS_THAN_OP:
2474 //
2475 // Compare two integer, string, boolean or date/time
2476 //
2477 Status = PopExpression (&Data2);
2478 if (EFI_ERROR (Status)) {
2479 goto Done;
2480 }
2481 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN &&
2482 Data2.Type != EFI_IFR_TYPE_STRING &&
2483 Data2.Type != EFI_IFR_TYPE_BUFFER) {
2484 Status = EFI_INVALID_PARAMETER;
2485 goto Done;
2486 }
2487
2488 //
2489 // Pop another expression from the expression stack
2490 //
2491 Status = PopExpression (&Data1);
2492 if (EFI_ERROR (Status)) {
2493 goto Done;
2494 }
2495
2496 Result = CompareHiiValue (&Data1, &Data2, FormSet->HiiHandle);
2497 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {
2498 FreePool (Data1.Buffer);
2499 FreePool (Data2.Buffer);
2500 }
2501
2502 if (Result == EFI_INVALID_PARAMETER) {
2503 Status = EFI_INVALID_PARAMETER;
2504 goto Done;
2505 }
2506
2507 switch (OpCode->Operand) {
2508 case EFI_IFR_EQUAL_OP:
2509 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);
2510 break;
2511
2512 case EFI_IFR_NOT_EQUAL_OP:
2513 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);
2514 break;
2515
2516 case EFI_IFR_GREATER_EQUAL_OP:
2517 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);
2518 break;
2519
2520 case EFI_IFR_GREATER_THAN_OP:
2521 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);
2522 break;
2523
2524 case EFI_IFR_LESS_EQUAL_OP:
2525 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);
2526 break;
2527
2528 case EFI_IFR_LESS_THAN_OP:
2529 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);
2530 break;
2531
2532 default:
2533 break;
2534 }
2535 break;
2536
2537 case EFI_IFR_MATCH_OP:
2538 Status = InitializeUnicodeCollationProtocol ();
2539 if (EFI_ERROR (Status)) {
2540 goto Done;
2541 }
2542
2543 Status = IfrMatch (FormSet, Value);
2544 break;
2545
2546 case EFI_IFR_CATENATE_OP:
2547 Status = IfrCatenate (FormSet, Value);
2548 break;
2549
2550 //
2551 // ternary-op
2552 //
2553 case EFI_IFR_CONDITIONAL_OP:
2554 //
2555 // Pop third expression from the expression stack
2556 //
2557 Status = PopExpression (&Data3);
2558 if (EFI_ERROR (Status)) {
2559 goto Done;
2560 }
2561
2562 //
2563 // Pop second expression from the expression stack
2564 //
2565 Status = PopExpression (&Data2);
2566 if (EFI_ERROR (Status)) {
2567 goto Done;
2568 }
2569
2570 //
2571 // Pop first expression from the expression stack
2572 //
2573 Status = PopExpression (&Data1);
2574 if (EFI_ERROR (Status)) {
2575 goto Done;
2576 }
2577 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
2578 Status = EFI_INVALID_PARAMETER;
2579 goto Done;
2580 }
2581
2582 if (Data1.Value.b) {
2583 Value = &Data3;
2584 } else {
2585 Value = &Data2;
2586 }
2587 break;
2588
2589 case EFI_IFR_FIND_OP:
2590 Status = IfrFind (FormSet, OpCode->Format, Value);
2591 break;
2592
2593 case EFI_IFR_MID_OP:
2594 Status = IfrMid (FormSet, Value);
2595 break;
2596
2597 case EFI_IFR_TOKEN_OP:
2598 Status = IfrToken (FormSet, Value);
2599 break;
2600
2601 case EFI_IFR_SPAN_OP:
2602 Status = IfrSpan (FormSet, OpCode->Flags, Value);
2603 break;
2604
2605 case EFI_IFR_MAP_OP:
2606 //
2607 // Pop the check value
2608 //
2609 Status = PopExpression (&Data1);
2610 if (EFI_ERROR (Status)) {
2611 goto Done;
2612 }
2613 //
2614 // Check MapExpression list is valid.
2615 //
2616 if (OpCode->MapExpressionList.ForwardLink == NULL) {
2617 Status = EFI_INVALID_PARAMETER;
2618 goto Done;
2619 }
2620 //
2621 // Go through map expression list.
2622 //
2623 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);
2624 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2625 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
2626 //
2627 // Evaluate the first expression in this pair.
2628 //
2629 Status = EvaluateExpression (FormSet, Form, SubExpression);
2630 if (EFI_ERROR (Status)) {
2631 goto Done;
2632 }
2633 //
2634 // Compare the expression value with current value
2635 //
2636 if (CompareHiiValue (&Data1, &SubExpression->Result, NULL) == 0) {
2637 //
2638 // Try get the map value.
2639 //
2640 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2641 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2642 Status = EFI_INVALID_PARAMETER;
2643 goto Done;
2644 }
2645 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);
2646 Status = EvaluateExpression (FormSet, Form, SubExpression);
2647 if (EFI_ERROR (Status)) {
2648 goto Done;
2649 }
2650 Value = &SubExpression->Result;
2651 break;
2652 }
2653 //
2654 // Skip the second expression on this pair.
2655 //
2656 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2657 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2658 Status = EFI_INVALID_PARAMETER;
2659 goto Done;
2660 }
2661 //
2662 // Goto the first expression on next pair.
2663 //
2664 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
2665 }
2666
2667 //
2668 // No map value is found.
2669 //
2670 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
2671 Value->Type = EFI_IFR_TYPE_UNDEFINED;
2672 Value->Value.u8 = 0;
2673 }
2674 break;
2675
2676 default:
2677 break;
2678 }
2679 if (EFI_ERROR (Status)) {
2680 goto Done;
2681 }
2682
2683 Status = PushExpression (Value);
2684 if (EFI_ERROR (Status)) {
2685 goto Done;
2686 }
2687 }
2688
2689 //
2690 // Pop the final result from expression stack
2691 //
2692 Value = &Data1;
2693 Status = PopExpression (Value);
2694 if (EFI_ERROR (Status)) {
2695 goto Done;
2696 }
2697
2698 //
2699 // After evaluating an expression, there should be only one value left on the expression stack
2700 //
2701 if (PopExpression (Value) != EFI_ACCESS_DENIED) {
2702 Status = EFI_INVALID_PARAMETER;
2703 }
2704
2705 Done:
2706 RestoreExpressionEvaluationStackOffset (StackOffset);
2707 if (!EFI_ERROR (Status)) {
2708 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
2709 }
2710
2711 return Status;
2712 }