]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
... / ...
CommitLineData
1/** @file\r
2Utility functions for expression evaluation.\r
3\r
4Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Setup.h"\r
16\r
17//\r
18// Global stack used to evaluate boolean expresions\r
19//\r
20EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
21EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
22EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
23\r
24EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
25EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
26EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
27UINTN mExpressionEvaluationStackOffset = 0;\r
28\r
29EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
30EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
31EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
32\r
33EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
34EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
35EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
36\r
37FORM_EXPRESSION **mFormExpressionStack = NULL;\r
38FORM_EXPRESSION **mFormExpressionEnd = NULL;\r
39FORM_EXPRESSION **mFormExpressionPointer = NULL;\r
40\r
41FORM_EXPRESSION **mStatementExpressionStack = NULL;\r
42FORM_EXPRESSION **mStatementExpressionEnd = NULL;\r
43FORM_EXPRESSION **mStatementExpressionPointer = NULL;\r
44\r
45FORM_EXPRESSION **mOptionExpressionStack = NULL;\r
46FORM_EXPRESSION **mOptionExpressionEnd = NULL;\r
47FORM_EXPRESSION **mOptionExpressionPointer = NULL;\r
48\r
49\r
50//\r
51// Unicode collation protocol interface\r
52//\r
53EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
54EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
55\r
56/**\r
57 Grow size of the stack.\r
58\r
59 This is an internal function.\r
60\r
61 @param Stack On input: old stack; On output: new stack\r
62 @param StackPtr On input: old stack pointer; On output: new stack\r
63 pointer\r
64 @param StackEnd On input: old stack end; On output: new stack end\r
65\r
66 @retval EFI_SUCCESS Grow stack success.\r
67 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
68\r
69**/\r
70EFI_STATUS\r
71GrowStack (\r
72 IN OUT EFI_HII_VALUE **Stack,\r
73 IN OUT EFI_HII_VALUE **StackPtr,\r
74 IN OUT EFI_HII_VALUE **StackEnd\r
75 )\r
76{\r
77 UINTN Size;\r
78 EFI_HII_VALUE *NewStack;\r
79\r
80 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
81 if (*StackPtr != NULL) {\r
82 Size = Size + (*StackEnd - *Stack);\r
83 }\r
84\r
85 NewStack = AllocatePool (Size * sizeof (EFI_HII_VALUE));\r
86 if (NewStack == NULL) {\r
87 return EFI_OUT_OF_RESOURCES;\r
88 }\r
89\r
90 if (*StackPtr != NULL) {\r
91 //\r
92 // Copy from Old Stack to the New Stack\r
93 //\r
94 CopyMem (\r
95 NewStack,\r
96 *Stack,\r
97 (*StackEnd - *Stack) * sizeof (EFI_HII_VALUE)\r
98 );\r
99\r
100 //\r
101 // Free The Old Stack\r
102 //\r
103 FreePool (*Stack);\r
104 }\r
105\r
106 //\r
107 // Make the Stack pointer point to the old data in the new stack\r
108 //\r
109 *StackPtr = NewStack + (*StackPtr - *Stack);\r
110 *Stack = NewStack;\r
111 *StackEnd = NewStack + Size;\r
112\r
113 return EFI_SUCCESS;\r
114}\r
115\r
116\r
117/**\r
118 Push an element onto the Boolean Stack.\r
119\r
120 @param Stack On input: old stack; On output: new stack\r
121 @param StackPtr On input: old stack pointer; On output: new stack\r
122 pointer\r
123 @param StackEnd On input: old stack end; On output: new stack end\r
124 @param Data Data to push.\r
125\r
126 @retval EFI_SUCCESS Push stack success.\r
127\r
128**/\r
129EFI_STATUS\r
130PushStack (\r
131 IN OUT EFI_HII_VALUE **Stack,\r
132 IN OUT EFI_HII_VALUE **StackPtr,\r
133 IN OUT EFI_HII_VALUE **StackEnd,\r
134 IN EFI_HII_VALUE *Data\r
135 )\r
136{\r
137 EFI_STATUS Status;\r
138\r
139 //\r
140 // Check for a stack overflow condition\r
141 //\r
142 if (*StackPtr >= *StackEnd) {\r
143 //\r
144 // Grow the stack\r
145 //\r
146 Status = GrowStack (Stack, StackPtr, StackEnd);\r
147 if (EFI_ERROR (Status)) {\r
148 return Status;\r
149 }\r
150 }\r
151\r
152 //\r
153 // Push the item onto the stack\r
154 //\r
155 CopyMem (*StackPtr, Data, sizeof (EFI_HII_VALUE));\r
156 if (Data->Type == EFI_IFR_TYPE_BUFFER) {\r
157 (*StackPtr)->Buffer = AllocateCopyPool(Data->BufferLen, Data->Buffer);\r
158 ASSERT ((*StackPtr)->Buffer != NULL);\r
159 }\r
160\r
161 *StackPtr = *StackPtr + 1;\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166\r
167/**\r
168 Pop an element from the stack.\r
169\r
170 @param Stack On input: old stack\r
171 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
172 @param Data Data to pop.\r
173\r
174 @retval EFI_SUCCESS The value was popped onto the stack.\r
175 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
176\r
177**/\r
178EFI_STATUS\r
179PopStack (\r
180 IN EFI_HII_VALUE *Stack,\r
181 IN OUT EFI_HII_VALUE **StackPtr,\r
182 OUT EFI_HII_VALUE *Data\r
183 )\r
184{\r
185 //\r
186 // Check for a stack underflow condition\r
187 //\r
188 if (*StackPtr == Stack) {\r
189 return EFI_ACCESS_DENIED;\r
190 }\r
191\r
192 //\r
193 // Pop the item off the stack\r
194 //\r
195 *StackPtr = *StackPtr - 1;\r
196 CopyMem (Data, *StackPtr, sizeof (EFI_HII_VALUE));\r
197 return EFI_SUCCESS;\r
198}\r
199\r
200\r
201/**\r
202 Reset stack pointer to begin of the stack.\r
203\r
204**/\r
205VOID\r
206ResetCurrentExpressionStack (\r
207 VOID\r
208 )\r
209{\r
210 mCurrentExpressionPointer = mCurrentExpressionStack;\r
211 mFormExpressionPointer = mFormExpressionStack;\r
212 mStatementExpressionPointer = mStatementExpressionStack;\r
213 mOptionExpressionPointer = mOptionExpressionStack;\r
214}\r
215\r
216\r
217/**\r
218 Push current expression onto the Stack\r
219\r
220 @param Pointer Pointer to current expression.\r
221\r
222 @retval EFI_SUCCESS The value was pushed onto the stack.\r
223 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
224\r
225**/\r
226EFI_STATUS\r
227PushCurrentExpression (\r
228 IN VOID *Pointer\r
229 )\r
230{\r
231 EFI_HII_VALUE Data;\r
232\r
233 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
234 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
235\r
236 return PushStack (\r
237 &mCurrentExpressionStack,\r
238 &mCurrentExpressionPointer,\r
239 &mCurrentExpressionEnd,\r
240 &Data\r
241 );\r
242}\r
243\r
244\r
245/**\r
246 Pop current expression from the Stack\r
247\r
248 @param Pointer Pointer to current expression to be pop.\r
249\r
250 @retval EFI_SUCCESS The value was pushed onto the stack.\r
251 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
252\r
253**/\r
254EFI_STATUS\r
255PopCurrentExpression (\r
256 OUT VOID **Pointer\r
257 )\r
258{\r
259 EFI_STATUS Status;\r
260 EFI_HII_VALUE Data;\r
261\r
262 Status = PopStack (\r
263 mCurrentExpressionStack,\r
264 &mCurrentExpressionPointer,\r
265 &Data\r
266 );\r
267\r
268 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
269\r
270 return Status;\r
271}\r
272\r
273/**\r
274 Reset stack pointer to begin of the stack.\r
275\r
276**/\r
277VOID\r
278ResetMapExpressionListStack (\r
279 VOID\r
280 )\r
281{\r
282 mMapExpressionListPointer = mMapExpressionListStack;\r
283}\r
284\r
285\r
286/**\r
287 Grow size of the stack.\r
288\r
289 This is an internal function.\r
290\r
291 @param Stack On input: old stack; On output: new stack\r
292 @param StackPtr On input: old stack pointer; On output: new stack\r
293 pointer\r
294 @param StackEnd On input: old stack end; On output: new stack end\r
295 @param MemberSize The stack member size.\r
296\r
297 @retval EFI_SUCCESS Grow stack success.\r
298 @retval EFI_OUT_OF_RESOURCES No enough memory for stack space.\r
299\r
300**/\r
301EFI_STATUS\r
302GrowConditionalStack (\r
303 IN OUT FORM_EXPRESSION ***Stack,\r
304 IN OUT FORM_EXPRESSION ***StackPtr,\r
305 IN OUT FORM_EXPRESSION ***StackEnd,\r
306 IN UINTN MemberSize\r
307 )\r
308{\r
309 UINTN Size;\r
310 FORM_EXPRESSION **NewStack;\r
311\r
312 Size = EXPRESSION_STACK_SIZE_INCREMENT;\r
313 if (*StackPtr != NULL) {\r
314 Size = Size + (*StackEnd - *Stack);\r
315 }\r
316\r
317 NewStack = AllocatePool (Size * MemberSize);\r
318 if (NewStack == NULL) {\r
319 return EFI_OUT_OF_RESOURCES;\r
320 }\r
321\r
322 if (*StackPtr != NULL) {\r
323 //\r
324 // Copy from Old Stack to the New Stack\r
325 //\r
326 CopyMem (\r
327 NewStack,\r
328 *Stack,\r
329 (*StackEnd - *Stack) * MemberSize\r
330 );\r
331\r
332 //\r
333 // Free The Old Stack\r
334 //\r
335 FreePool (*Stack);\r
336 }\r
337\r
338 //\r
339 // Make the Stack pointer point to the old data in the new stack\r
340 //\r
341 *StackPtr = NewStack + (*StackPtr - *Stack);\r
342 *Stack = NewStack;\r
343 *StackEnd = NewStack + Size;\r
344\r
345 return EFI_SUCCESS;\r
346}\r
347\r
348/**\r
349 Push an element onto the Stack.\r
350\r
351 @param Stack On input: old stack; On output: new stack\r
352 @param StackPtr On input: old stack pointer; On output: new stack\r
353 pointer\r
354 @param StackEnd On input: old stack end; On output: new stack end\r
355 @param Data Data to push.\r
356\r
357 @retval EFI_SUCCESS Push stack success.\r
358\r
359**/\r
360EFI_STATUS\r
361PushConditionalStack (\r
362 IN OUT FORM_EXPRESSION ***Stack,\r
363 IN OUT FORM_EXPRESSION ***StackPtr,\r
364 IN OUT FORM_EXPRESSION ***StackEnd,\r
365 IN FORM_EXPRESSION **Data\r
366 )\r
367{\r
368 EFI_STATUS Status;\r
369\r
370 //\r
371 // Check for a stack overflow condition\r
372 //\r
373 if (*StackPtr >= *StackEnd) {\r
374 //\r
375 // Grow the stack\r
376 //\r
377 Status = GrowConditionalStack (Stack, StackPtr, StackEnd, sizeof (FORM_EXPRESSION *));\r
378 if (EFI_ERROR (Status)) {\r
379 return Status;\r
380 }\r
381 }\r
382\r
383 //\r
384 // Push the item onto the stack\r
385 //\r
386 CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *));\r
387 *StackPtr = *StackPtr + 1;\r
388\r
389 return EFI_SUCCESS;\r
390\r
391}\r
392\r
393/**\r
394 Pop an element from the stack.\r
395\r
396 @param Stack On input: old stack\r
397 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
398 @param Data Data to pop.\r
399\r
400 @retval EFI_SUCCESS The value was popped onto the stack.\r
401 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
402\r
403**/\r
404EFI_STATUS\r
405PopConditionalStack (\r
406 IN FORM_EXPRESSION **Stack,\r
407 IN OUT FORM_EXPRESSION ***StackPtr,\r
408 OUT FORM_EXPRESSION **Data\r
409 )\r
410{\r
411 //\r
412 // Check for a stack underflow condition\r
413 //\r
414 if (*StackPtr == Stack) {\r
415 return EFI_ACCESS_DENIED;\r
416 }\r
417\r
418 //\r
419 // Pop the item off the stack\r
420 //\r
421 *StackPtr = *StackPtr - 1;\r
422 CopyMem (Data, *StackPtr, sizeof (FORM_EXPRESSION *));\r
423 return EFI_SUCCESS;\r
424\r
425}\r
426\r
427/**\r
428 Get the expression list count.\r
429\r
430 @param Level Which type this expression belong to. Form,\r
431 statement or option?\r
432\r
433 @retval >=0 The expression count\r
434 @retval -1 Input parameter error.\r
435\r
436**/\r
437INTN\r
438GetConditionalExpressionCount (\r
439 IN EXPRESS_LEVEL Level\r
440 )\r
441{\r
442 switch (Level) {\r
443 case ExpressForm:\r
444 return mFormExpressionPointer - mFormExpressionStack;\r
445 case ExpressStatement:\r
446 return mStatementExpressionPointer - mStatementExpressionStack;\r
447 case ExpressOption:\r
448 return mOptionExpressionPointer - mOptionExpressionStack;\r
449 default:\r
450 ASSERT (FALSE);\r
451 return -1;\r
452 }\r
453}\r
454\r
455/**\r
456 Get the expression Buffer pointer.\r
457\r
458 @param Level Which type this expression belong to. Form,\r
459 statement or option?\r
460\r
461 @retval The start pointer of the expression buffer or NULL.\r
462\r
463**/\r
464FORM_EXPRESSION **\r
465GetConditionalExpressionList (\r
466 IN EXPRESS_LEVEL Level\r
467 )\r
468{\r
469 switch (Level) {\r
470 case ExpressForm:\r
471 return mFormExpressionStack;\r
472 case ExpressStatement:\r
473 return mStatementExpressionStack;\r
474 case ExpressOption:\r
475 return mOptionExpressionStack;\r
476 default:\r
477 ASSERT (FALSE);\r
478 return NULL;\r
479 }\r
480}\r
481\r
482\r
483/**\r
484 Push the expression options onto the Stack.\r
485\r
486 @param Pointer Pointer to the current expression.\r
487 @param Level Which type this expression belong to. Form,\r
488 statement or option?\r
489\r
490 @retval EFI_SUCCESS The value was pushed onto the stack.\r
491 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
492\r
493**/\r
494EFI_STATUS\r
495PushConditionalExpression (\r
496 IN FORM_EXPRESSION *Pointer,\r
497 IN EXPRESS_LEVEL Level\r
498 )\r
499{\r
500 switch (Level) {\r
501 case ExpressForm:\r
502 return PushConditionalStack (\r
503 &mFormExpressionStack,\r
504 &mFormExpressionPointer,\r
505 &mFormExpressionEnd,\r
506 &Pointer\r
507 );\r
508 case ExpressStatement:\r
509 return PushConditionalStack (\r
510 &mStatementExpressionStack,\r
511 &mStatementExpressionPointer,\r
512 &mStatementExpressionEnd,\r
513 &Pointer\r
514 );\r
515 case ExpressOption:\r
516 return PushConditionalStack (\r
517 &mOptionExpressionStack,\r
518 &mOptionExpressionPointer,\r
519 &mOptionExpressionEnd,\r
520 &Pointer\r
521 );\r
522 default:\r
523 ASSERT (FALSE);\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
526}\r
527\r
528/**\r
529 Pop the expression options from the Stack\r
530\r
531 @param Level Which type this expression belong to. Form,\r
532 statement or option?\r
533\r
534 @retval EFI_SUCCESS The value was pushed onto the stack.\r
535 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
536\r
537**/\r
538EFI_STATUS\r
539PopConditionalExpression (\r
540 IN EXPRESS_LEVEL Level\r
541 )\r
542{\r
543 FORM_EXPRESSION *Pointer;\r
544\r
545 switch (Level) {\r
546 case ExpressForm:\r
547 return PopConditionalStack (\r
548 mFormExpressionStack,\r
549 &mFormExpressionPointer,\r
550 &Pointer\r
551 );\r
552\r
553 case ExpressStatement:\r
554 return PopConditionalStack (\r
555 mStatementExpressionStack,\r
556 &mStatementExpressionPointer,\r
557 &Pointer\r
558 );\r
559\r
560 case ExpressOption:\r
561 return PopConditionalStack (\r
562 mOptionExpressionStack,\r
563 &mOptionExpressionPointer,\r
564 &Pointer\r
565 );\r
566\r
567 default:\r
568 ASSERT (FALSE);\r
569 return EFI_INVALID_PARAMETER;\r
570 }\r
571}\r
572\r
573\r
574/**\r
575 Push the list of map expression onto the Stack\r
576\r
577 @param Pointer Pointer to the list of map expression to be pushed.\r
578\r
579 @retval EFI_SUCCESS The value was pushed onto the stack.\r
580 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
581\r
582**/\r
583EFI_STATUS\r
584PushMapExpressionList (\r
585 IN VOID *Pointer\r
586 )\r
587{\r
588 EFI_HII_VALUE Data;\r
589\r
590 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
591 Data.Value.u64 = (UINT64) (UINTN) Pointer;\r
592\r
593 return PushStack (\r
594 &mMapExpressionListStack,\r
595 &mMapExpressionListPointer,\r
596 &mMapExpressionListEnd,\r
597 &Data\r
598 );\r
599}\r
600\r
601\r
602/**\r
603 Pop the list of map expression from the Stack\r
604\r
605 @param Pointer Pointer to the list of map expression to be pop.\r
606\r
607 @retval EFI_SUCCESS The value was pushed onto the stack.\r
608 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.\r
609\r
610**/\r
611EFI_STATUS\r
612PopMapExpressionList (\r
613 OUT VOID **Pointer\r
614 )\r
615{\r
616 EFI_STATUS Status;\r
617 EFI_HII_VALUE Data;\r
618\r
619 Status = PopStack (\r
620 mMapExpressionListStack,\r
621 &mMapExpressionListPointer,\r
622 &Data\r
623 );\r
624\r
625 *Pointer = (VOID *) (UINTN) Data.Value.u64;\r
626\r
627 return Status;\r
628}\r
629\r
630/**\r
631 Reset stack pointer to begin of the stack.\r
632\r
633**/\r
634VOID\r
635ResetScopeStack (\r
636 VOID\r
637 )\r
638{\r
639 mOpCodeScopeStackPointer = mOpCodeScopeStack;\r
640}\r
641\r
642\r
643/**\r
644 Push an Operand onto the Stack\r
645\r
646 @param Operand Operand to push.\r
647\r
648 @retval EFI_SUCCESS The value was pushed onto the stack.\r
649 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
650 stack.\r
651\r
652**/\r
653EFI_STATUS\r
654PushScope (\r
655 IN UINT8 Operand\r
656 )\r
657{\r
658 EFI_HII_VALUE Data;\r
659\r
660 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
661 Data.Value.u8 = Operand;\r
662\r
663 return PushStack (\r
664 &mOpCodeScopeStack,\r
665 &mOpCodeScopeStackPointer,\r
666 &mOpCodeScopeStackEnd,\r
667 &Data\r
668 );\r
669}\r
670\r
671\r
672/**\r
673 Pop an Operand from the Stack\r
674\r
675 @param Operand Operand to pop.\r
676\r
677 @retval EFI_SUCCESS The value was pushed onto the stack.\r
678 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
679 stack.\r
680\r
681**/\r
682EFI_STATUS\r
683PopScope (\r
684 OUT UINT8 *Operand\r
685 )\r
686{\r
687 EFI_STATUS Status;\r
688 EFI_HII_VALUE Data;\r
689\r
690 Status = PopStack (\r
691 mOpCodeScopeStack,\r
692 &mOpCodeScopeStackPointer,\r
693 &Data\r
694 );\r
695\r
696 *Operand = Data.Value.u8;\r
697\r
698 return Status;\r
699}\r
700\r
701\r
702/**\r
703 Push an Expression value onto the Stack\r
704\r
705 @param Value Expression value to push.\r
706\r
707 @retval EFI_SUCCESS The value was pushed onto the stack.\r
708 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
709 stack.\r
710\r
711**/\r
712EFI_STATUS\r
713PushExpression (\r
714 IN EFI_HII_VALUE *Value\r
715 )\r
716{\r
717 return PushStack (\r
718 &mExpressionEvaluationStack,\r
719 &mExpressionEvaluationStackPointer,\r
720 &mExpressionEvaluationStackEnd,\r
721 Value\r
722 );\r
723}\r
724\r
725\r
726/**\r
727 Pop an Expression value from the stack.\r
728\r
729 @param Value Expression value to pop.\r
730\r
731 @retval EFI_SUCCESS The value was popped onto the stack.\r
732 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
733\r
734**/\r
735EFI_STATUS\r
736PopExpression (\r
737 OUT EFI_HII_VALUE *Value\r
738 )\r
739{\r
740 return PopStack (\r
741 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
742 &mExpressionEvaluationStackPointer,\r
743 Value\r
744 );\r
745}\r
746\r
747/**\r
748 Get current stack offset from stack start.\r
749\r
750 @return Stack offset to stack start.\r
751**/\r
752UINTN\r
753SaveExpressionEvaluationStackOffset (\r
754 VOID\r
755 )\r
756{\r
757 UINTN TempStackOffset;\r
758 TempStackOffset = mExpressionEvaluationStackOffset;\r
759 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
760 return TempStackOffset;\r
761}\r
762\r
763/**\r
764 Restore stack offset based on input stack offset\r
765\r
766 @param StackOffset Offset to stack start.\r
767\r
768**/\r
769VOID\r
770RestoreExpressionEvaluationStackOffset (\r
771 UINTN StackOffset\r
772 )\r
773{\r
774 mExpressionEvaluationStackOffset = StackOffset;\r
775}\r
776\r
777/**\r
778 Get Form given its FormId.\r
779\r
780 @param FormSet The formset which contains this form.\r
781 @param FormId Id of this form.\r
782\r
783 @retval Pointer The form.\r
784 @retval NULL Specified Form is not found in the formset.\r
785\r
786**/\r
787FORM_BROWSER_FORM *\r
788IdToForm (\r
789 IN FORM_BROWSER_FORMSET *FormSet,\r
790 IN UINT16 FormId\r
791 )\r
792{\r
793 LIST_ENTRY *Link;\r
794 FORM_BROWSER_FORM *Form;\r
795\r
796 Link = GetFirstNode (&FormSet->FormListHead);\r
797 while (!IsNull (&FormSet->FormListHead, Link)) {\r
798 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
799\r
800 if (Form->FormId == FormId) {\r
801 return Form;\r
802 }\r
803\r
804 Link = GetNextNode (&FormSet->FormListHead, Link);\r
805 }\r
806\r
807 return NULL;\r
808}\r
809\r
810\r
811/**\r
812 Search a Question in Form scope using its QuestionId.\r
813\r
814 @param Form The form which contains this Question.\r
815 @param QuestionId Id of this Question.\r
816\r
817 @retval Pointer The Question.\r
818 @retval NULL Specified Question not found in the form.\r
819\r
820**/\r
821FORM_BROWSER_STATEMENT *\r
822IdToQuestion2 (\r
823 IN FORM_BROWSER_FORM *Form,\r
824 IN UINT16 QuestionId\r
825 )\r
826{\r
827 LIST_ENTRY *Link;\r
828 FORM_BROWSER_STATEMENT *Question;\r
829\r
830 if (QuestionId == 0 || Form == NULL) {\r
831 //\r
832 // The value of zero is reserved\r
833 //\r
834 return NULL;\r
835 }\r
836\r
837 Link = GetFirstNode (&Form->StatementListHead);\r
838 while (!IsNull (&Form->StatementListHead, Link)) {\r
839 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
840\r
841 if (Question->QuestionId == QuestionId) {\r
842 return Question;\r
843 }\r
844\r
845 Link = GetNextNode (&Form->StatementListHead, Link);\r
846 }\r
847\r
848 return NULL;\r
849}\r
850\r
851\r
852/**\r
853 Search a Question in Formset scope using its QuestionId.\r
854\r
855 @param FormSet The formset which contains this form.\r
856 @param Form The form which contains this Question.\r
857 @param QuestionId Id of this Question.\r
858\r
859 @retval Pointer The Question.\r
860 @retval NULL Specified Question not found in the form.\r
861\r
862**/\r
863FORM_BROWSER_STATEMENT *\r
864IdToQuestion (\r
865 IN FORM_BROWSER_FORMSET *FormSet,\r
866 IN FORM_BROWSER_FORM *Form,\r
867 IN UINT16 QuestionId\r
868 )\r
869{\r
870 LIST_ENTRY *Link;\r
871 FORM_BROWSER_STATEMENT *Question;\r
872\r
873 //\r
874 // Search in the form scope first\r
875 //\r
876 Question = IdToQuestion2 (Form, QuestionId);\r
877 if (Question != NULL) {\r
878 return Question;\r
879 }\r
880\r
881 //\r
882 // Search in the formset scope\r
883 //\r
884 Link = GetFirstNode (&FormSet->FormListHead);\r
885 while (!IsNull (&FormSet->FormListHead, Link)) {\r
886 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
887\r
888 Question = IdToQuestion2 (Form, QuestionId);\r
889 if (Question != NULL) {\r
890 //\r
891 // EFI variable storage may be updated by Callback() asynchronous,\r
892 // to keep synchronous, always reload the Question Value.\r
893 //\r
894 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
895 GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
896 }\r
897\r
898 return Question;\r
899 }\r
900\r
901 Link = GetNextNode (&FormSet->FormListHead, Link);\r
902 }\r
903\r
904 return NULL;\r
905}\r
906\r
907\r
908/**\r
909 Get Expression given its RuleId.\r
910\r
911 @param Form The form which contains this Expression.\r
912 @param RuleId Id of this Expression.\r
913\r
914 @retval Pointer The Expression.\r
915 @retval NULL Specified Expression not found in the form.\r
916\r
917**/\r
918FORM_EXPRESSION *\r
919RuleIdToExpression (\r
920 IN FORM_BROWSER_FORM *Form,\r
921 IN UINT8 RuleId\r
922 )\r
923{\r
924 LIST_ENTRY *Link;\r
925 FORM_EXPRESSION *Expression;\r
926\r
927 Link = GetFirstNode (&Form->ExpressionListHead);\r
928 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
929 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
930\r
931 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
932 return Expression;\r
933 }\r
934\r
935 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
936 }\r
937\r
938 return NULL;\r
939}\r
940\r
941\r
942/**\r
943 Locate the Unicode Collation Protocol interface for later use.\r
944\r
945 @retval EFI_SUCCESS Protocol interface initialize success.\r
946 @retval Other Protocol interface initialize failed.\r
947\r
948**/\r
949EFI_STATUS\r
950InitializeUnicodeCollationProtocol (\r
951 VOID\r
952 )\r
953{\r
954 EFI_STATUS Status;\r
955\r
956 if (mUnicodeCollation != NULL) {\r
957 return EFI_SUCCESS;\r
958 }\r
959\r
960 //\r
961 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
962 // instances first and then select one which support English language.\r
963 // Current implementation just pick the first instance.\r
964 //\r
965 Status = gBS->LocateProtocol (\r
966 &gEfiUnicodeCollation2ProtocolGuid,\r
967 NULL,\r
968 (VOID **) &mUnicodeCollation\r
969 );\r
970 return Status;\r
971}\r
972\r
973/**\r
974 Convert the input Unicode character to upper.\r
975\r
976 @param String Th Unicode character to be converted.\r
977\r
978**/\r
979VOID\r
980IfrStrToUpper (\r
981 IN CHAR16 *String\r
982 )\r
983{\r
984 while (*String != 0) {\r
985 if ((*String >= 'a') && (*String <= 'z')) {\r
986 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
987 }\r
988 String++;\r
989 }\r
990}\r
991\r
992/**\r
993 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
994\r
995 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
996 EFI_IFR_TYPE_BUFFER when do the value compare.\r
997\r
998 @param Value Expression value to compare on.\r
999\r
1000 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
1001 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
1002\r
1003**/\r
1004BOOLEAN\r
1005IsTypeInBuffer (\r
1006 IN EFI_HII_VALUE *Value\r
1007 )\r
1008{\r
1009 switch (Value->Type) {\r
1010 case EFI_IFR_TYPE_BUFFER:\r
1011 case EFI_IFR_TYPE_DATE:\r
1012 case EFI_IFR_TYPE_TIME:\r
1013 case EFI_IFR_TYPE_REF:\r
1014 return TRUE;\r
1015\r
1016 default:\r
1017 return FALSE;\r
1018 }\r
1019}\r
1020\r
1021/**\r
1022 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64\r
1023\r
1024 @param Value Expression value to compare on.\r
1025\r
1026 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
1027 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
1028\r
1029**/\r
1030BOOLEAN\r
1031IsTypeInUINT64 (\r
1032 IN EFI_HII_VALUE *Value\r
1033 )\r
1034{\r
1035 switch (Value->Type) {\r
1036 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1037 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1038 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1039 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1040 case EFI_IFR_TYPE_BOOLEAN:\r
1041 return TRUE;\r
1042\r
1043 default:\r
1044 return FALSE;\r
1045 }\r
1046}\r
1047\r
1048/**\r
1049 Return the buffer length for this value.\r
1050\r
1051 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
1052 EFI_IFR_TYPE_BUFFER when do the value compare.\r
1053\r
1054 @param Value Expression value to compare on.\r
1055\r
1056 @retval BufLen Return the buffer length.\r
1057\r
1058**/\r
1059UINT16\r
1060GetLengthForValue (\r
1061 IN EFI_HII_VALUE *Value\r
1062 )\r
1063{\r
1064 switch (Value->Type) {\r
1065 case EFI_IFR_TYPE_BUFFER:\r
1066 return Value->BufferLen;\r
1067\r
1068 case EFI_IFR_TYPE_DATE:\r
1069 return (UINT16) sizeof (EFI_HII_DATE);\r
1070\r
1071 case EFI_IFR_TYPE_TIME:\r
1072 return (UINT16) sizeof (EFI_HII_TIME);\r
1073\r
1074 case EFI_IFR_TYPE_REF:\r
1075 return (UINT16) sizeof (EFI_HII_REF);\r
1076\r
1077 default:\r
1078 return 0;\r
1079 }\r
1080}\r
1081\r
1082/**\r
1083 Return the buffer pointer for this value.\r
1084\r
1085 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
1086 EFI_IFR_TYPE_BUFFER when do the value compare.\r
1087\r
1088 @param Value Expression value to compare on.\r
1089\r
1090 @retval Buf Return the buffer pointer.\r
1091\r
1092**/\r
1093UINT8 *\r
1094GetBufferForValue (\r
1095 IN EFI_HII_VALUE *Value\r
1096 )\r
1097{\r
1098 switch (Value->Type) {\r
1099 case EFI_IFR_TYPE_BUFFER:\r
1100 return Value->Buffer;\r
1101\r
1102 case EFI_IFR_TYPE_DATE:\r
1103 return (UINT8 *) (&Value->Value.date);\r
1104\r
1105 case EFI_IFR_TYPE_TIME:\r
1106 return (UINT8 *) (&Value->Value.time);\r
1107\r
1108 case EFI_IFR_TYPE_REF:\r
1109 return (UINT8 *) (&Value->Value.ref);\r
1110\r
1111 default:\r
1112 return NULL;\r
1113 }\r
1114}\r
1115\r
1116/**\r
1117 Evaluate opcode EFI_IFR_TO_STRING.\r
1118\r
1119 @param FormSet Formset which contains this opcode.\r
1120 @param Format String format in EFI_IFR_TO_STRING.\r
1121 @param Result Evaluation result for this opcode.\r
1122\r
1123 @retval EFI_SUCCESS Opcode evaluation success.\r
1124 @retval Other Opcode evaluation failed.\r
1125\r
1126**/\r
1127EFI_STATUS\r
1128IfrToString (\r
1129 IN FORM_BROWSER_FORMSET *FormSet,\r
1130 IN UINT8 Format,\r
1131 OUT EFI_HII_VALUE *Result\r
1132 )\r
1133{\r
1134 EFI_STATUS Status;\r
1135 EFI_HII_VALUE Value;\r
1136 CHAR16 *String;\r
1137 CHAR16 *PrintFormat;\r
1138 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
1139 UINT8 *TmpBuf;\r
1140 UINT8 *SrcBuf;\r
1141 UINTN SrcLen;\r
1142 UINTN BufferSize;\r
1143\r
1144 Status = PopExpression (&Value);\r
1145 if (EFI_ERROR (Status)) {\r
1146 return Status;\r
1147 }\r
1148\r
1149 switch (Value.Type) {\r
1150 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1151 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1152 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1153 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1154 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
1155 switch (Format) {\r
1156 case EFI_IFR_STRING_UNSIGNED_DEC:\r
1157 case EFI_IFR_STRING_SIGNED_DEC:\r
1158 PrintFormat = L"%ld";\r
1159 break;\r
1160\r
1161 case EFI_IFR_STRING_LOWERCASE_HEX:\r
1162 PrintFormat = L"%lx";\r
1163 break;\r
1164\r
1165 case EFI_IFR_STRING_UPPERCASE_HEX:\r
1166 PrintFormat = L"%lX";\r
1167 break;\r
1168\r
1169 default:\r
1170 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1171 return EFI_SUCCESS;\r
1172 }\r
1173 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
1174 String = Buffer;\r
1175 break;\r
1176\r
1177 case EFI_IFR_TYPE_STRING:\r
1178 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1179 return EFI_SUCCESS;\r
1180\r
1181 case EFI_IFR_TYPE_BOOLEAN:\r
1182 String = (Value.Value.b) ? L"True" : L"False";\r
1183 break;\r
1184\r
1185 case EFI_IFR_TYPE_BUFFER:\r
1186 case EFI_IFR_TYPE_DATE:\r
1187 case EFI_IFR_TYPE_TIME:\r
1188 case EFI_IFR_TYPE_REF:\r
1189 //\r
1190 // + 3 is base on the unicode format, the length may be odd number,\r
1191 // so need 1 byte to align, also need 2 bytes for L'\0'.\r
1192 //\r
1193 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1194 SrcLen = Value.BufferLen;\r
1195 SrcBuf = Value.Buffer;\r
1196 } else {\r
1197 SrcBuf = GetBufferForValue(&Value);\r
1198 SrcLen = GetLengthForValue(&Value);\r
1199 }\r
1200\r
1201 TmpBuf = AllocateZeroPool (SrcLen + 3);\r
1202 ASSERT (TmpBuf != NULL);\r
1203 if (Format == EFI_IFR_STRING_ASCII) {\r
1204 CopyMem (TmpBuf, SrcBuf, SrcLen);\r
1205 PrintFormat = L"%a";\r
1206 } else {\r
1207 // Format == EFI_IFR_STRING_UNICODE\r
1208 CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16));\r
1209 PrintFormat = L"%s";\r
1210 }\r
1211 UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf);\r
1212 String = Buffer;\r
1213 FreePool (TmpBuf);\r
1214 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1215 FreePool (Value.Buffer);\r
1216 }\r
1217 break;\r
1218\r
1219 default:\r
1220 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1221 return EFI_SUCCESS;\r
1222 }\r
1223\r
1224 Result->Type = EFI_IFR_TYPE_STRING;\r
1225 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
1226 return EFI_SUCCESS;\r
1227}\r
1228\r
1229\r
1230/**\r
1231 Evaluate opcode EFI_IFR_TO_UINT.\r
1232\r
1233 @param FormSet Formset which contains this opcode.\r
1234 @param Result Evaluation result for this opcode.\r
1235\r
1236 @retval EFI_SUCCESS Opcode evaluation success.\r
1237 @retval Other Opcode evaluation failed.\r
1238\r
1239**/\r
1240EFI_STATUS\r
1241IfrToUint (\r
1242 IN FORM_BROWSER_FORMSET *FormSet,\r
1243 OUT EFI_HII_VALUE *Result\r
1244 )\r
1245{\r
1246 EFI_STATUS Status;\r
1247 EFI_HII_VALUE Value;\r
1248 CHAR16 *String;\r
1249 CHAR16 *StringPtr;\r
1250\r
1251 Status = PopExpression (&Value);\r
1252 if (EFI_ERROR (Status)) {\r
1253 return Status;\r
1254 }\r
1255\r
1256 if (Value.Type >= EFI_IFR_TYPE_OTHER && !IsTypeInBuffer(&Value)) {\r
1257 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1258 return EFI_SUCCESS;\r
1259 }\r
1260\r
1261 Status = EFI_SUCCESS;\r
1262 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
1263 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1264 if (String == NULL) {\r
1265 return EFI_NOT_FOUND;\r
1266 }\r
1267\r
1268 IfrStrToUpper (String);\r
1269 StringPtr = StrStr (String, L"0X");\r
1270 if (StringPtr != NULL) {\r
1271 //\r
1272 // Hex string\r
1273 //\r
1274 Result->Value.u64 = StrHexToUint64 (String);\r
1275 } else {\r
1276 //\r
1277 // decimal string\r
1278 //\r
1279 Result->Value.u64 = StrDecimalToUint64 (String);\r
1280 }\r
1281 FreePool (String);\r
1282 } else if (IsTypeInBuffer(&Value)) {\r
1283 if (GetLengthForValue (&Value) > 8) {\r
1284 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1285 FreePool (Value.Buffer);\r
1286 }\r
1287 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1288 return EFI_SUCCESS;\r
1289 }\r
1290 Result->Value.u64 = *(UINT64*) GetBufferForValue (&Value);\r
1291 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1292 FreePool (Value.Buffer);\r
1293 }\r
1294 } else {\r
1295 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1296 }\r
1297\r
1298 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1299 return Status;\r
1300}\r
1301\r
1302\r
1303/**\r
1304 Evaluate opcode EFI_IFR_CATENATE.\r
1305\r
1306 @param FormSet Formset which contains this opcode.\r
1307 @param Result Evaluation result for this opcode.\r
1308\r
1309 @retval EFI_SUCCESS Opcode evaluation success.\r
1310 @retval Other Opcode evaluation failed.\r
1311\r
1312**/\r
1313EFI_STATUS\r
1314IfrCatenate (\r
1315 IN FORM_BROWSER_FORMSET *FormSet,\r
1316 OUT EFI_HII_VALUE *Result\r
1317 )\r
1318{\r
1319 EFI_STATUS Status;\r
1320 EFI_HII_VALUE Value[2];\r
1321 CHAR16 *String[2];\r
1322 UINTN Index;\r
1323 CHAR16 *StringPtr;\r
1324 UINTN Size;\r
1325 UINT16 Length0;\r
1326 UINT16 Length1;\r
1327 UINT8 *TmpBuf;\r
1328 UINTN MaxLen;\r
1329\r
1330 //\r
1331 // String[0] - The second string\r
1332 // String[1] - The first string\r
1333 //\r
1334 String[0] = NULL;\r
1335 String[1] = NULL;\r
1336 StringPtr = NULL;\r
1337 Status = EFI_SUCCESS;\r
1338 ZeroMem (Value, sizeof (Value));\r
1339\r
1340 Status = PopExpression (&Value[0]);\r
1341 if (EFI_ERROR (Status)) {\r
1342 goto Done;\r
1343 }\r
1344\r
1345 Status = PopExpression (&Value[1]);\r
1346 if (EFI_ERROR (Status)) {\r
1347 goto Done;\r
1348 }\r
1349\r
1350 for (Index = 0; Index < 2; Index++) {\r
1351 if (Value[Index].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[Index])) {\r
1352 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1353 Status = EFI_SUCCESS;\r
1354 goto Done;\r
1355 }\r
1356\r
1357 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
1358 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1359 if (String[Index] == NULL) {\r
1360 Status = EFI_NOT_FOUND;\r
1361 goto Done;\r
1362 }\r
1363 }\r
1364 }\r
1365\r
1366 if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
1367 Size = StrSize (String[0]);\r
1368 MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);\r
1369 StringPtr= AllocatePool (MaxLen * sizeof (CHAR16));\r
1370 ASSERT (StringPtr != NULL);\r
1371 StrCpyS (StringPtr, MaxLen, String[1]);\r
1372 StrCatS (StringPtr, MaxLen, String[0]);\r
1373\r
1374 Result->Type = EFI_IFR_TYPE_STRING;\r
1375 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
1376 } else {\r
1377 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1378 Length0 = GetLengthForValue(&Value[0]);\r
1379 Length1 = GetLengthForValue(&Value[1]);\r
1380 Result->BufferLen = (UINT16) (Length0 + Length1);\r
1381\r
1382 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1383 ASSERT (Result->Buffer != NULL);\r
1384\r
1385 TmpBuf = GetBufferForValue(&Value[0]);\r
1386 ASSERT (TmpBuf != NULL);\r
1387 CopyMem (Result->Buffer, TmpBuf, Length0);\r
1388 TmpBuf = GetBufferForValue(&Value[1]);\r
1389 ASSERT (TmpBuf != NULL);\r
1390 CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);\r
1391 }\r
1392Done:\r
1393 if (Value[0].Buffer != NULL) {\r
1394 FreePool (Value[0].Buffer);\r
1395 }\r
1396 if (Value[1].Buffer != NULL) {\r
1397 FreePool (Value[1].Buffer);\r
1398 }\r
1399 if (String[0] != NULL) {\r
1400 FreePool (String[0]);\r
1401 }\r
1402 if (String[1] != NULL) {\r
1403 FreePool (String[1]);\r
1404 }\r
1405 if (StringPtr != NULL) {\r
1406 FreePool (StringPtr);\r
1407 }\r
1408\r
1409 return Status;\r
1410}\r
1411\r
1412\r
1413/**\r
1414 Evaluate opcode EFI_IFR_MATCH.\r
1415\r
1416 @param FormSet Formset which contains this opcode.\r
1417 @param Result Evaluation result for this opcode.\r
1418\r
1419 @retval EFI_SUCCESS Opcode evaluation success.\r
1420 @retval Other Opcode evaluation failed.\r
1421\r
1422**/\r
1423EFI_STATUS\r
1424IfrMatch (\r
1425 IN FORM_BROWSER_FORMSET *FormSet,\r
1426 OUT EFI_HII_VALUE *Result\r
1427 )\r
1428{\r
1429 EFI_STATUS Status;\r
1430 EFI_HII_VALUE Value[2];\r
1431 CHAR16 *String[2];\r
1432 UINTN Index;\r
1433\r
1434 //\r
1435 // String[0] - The string to search\r
1436 // String[1] - pattern\r
1437 //\r
1438 String[0] = NULL;\r
1439 String[1] = NULL;\r
1440 Status = EFI_SUCCESS;\r
1441 ZeroMem (Value, sizeof (Value));\r
1442\r
1443 Status = PopExpression (&Value[0]);\r
1444 if (EFI_ERROR (Status)) {\r
1445 goto Done;\r
1446 }\r
1447\r
1448 Status = PopExpression (&Value[1]);\r
1449 if (EFI_ERROR (Status)) {\r
1450 goto Done;\r
1451 }\r
1452\r
1453 for (Index = 0; Index < 2; Index++) {\r
1454 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
1455 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1456 Status = EFI_SUCCESS;\r
1457 goto Done;\r
1458 }\r
1459\r
1460 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1461 if (String [Index] == NULL) {\r
1462 Status = EFI_NOT_FOUND;\r
1463 goto Done;\r
1464 }\r
1465 }\r
1466\r
1467 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1468 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
1469\r
1470Done:\r
1471 if (String[0] != NULL) {\r
1472 FreePool (String[0]);\r
1473 }\r
1474 if (String[1] != NULL) {\r
1475 FreePool (String[1]);\r
1476 }\r
1477\r
1478 return Status;\r
1479}\r
1480\r
1481/**\r
1482 Evaluate opcode EFI_IFR_MATCH2.\r
1483\r
1484 @param FormSet Formset which contains this opcode.\r
1485 @param SyntaxType Syntax type for match2.\r
1486 @param Result Evaluation result for this opcode.\r
1487\r
1488 @retval EFI_SUCCESS Opcode evaluation success.\r
1489 @retval Other Opcode evaluation failed.\r
1490\r
1491**/\r
1492EFI_STATUS\r
1493IfrMatch2 (\r
1494 IN FORM_BROWSER_FORMSET *FormSet,\r
1495 IN EFI_GUID *SyntaxType,\r
1496 OUT EFI_HII_VALUE *Result\r
1497 )\r
1498{\r
1499 EFI_STATUS Status;\r
1500 EFI_HII_VALUE Value[2];\r
1501 CHAR16 *String[2];\r
1502 UINTN Index;\r
1503 UINTN GuidIndex;\r
1504 EFI_HANDLE *HandleBuffer;\r
1505 UINTN BufferSize;\r
1506 EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol;\r
1507 UINTN RegExSyntaxTypeListSize;\r
1508 EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList;\r
1509 UINTN CapturesCount;\r
1510\r
1511 //\r
1512 // String[0] - The string to search\r
1513 // String[1] - pattern\r
1514 //\r
1515 String[0] = NULL;\r
1516 String[1] = NULL;\r
1517 HandleBuffer = NULL;\r
1518 RegExSyntaxTypeList = NULL;\r
1519 Status = EFI_SUCCESS;\r
1520 ZeroMem (Value, sizeof (Value));\r
1521\r
1522 Status = PopExpression (&Value[0]);\r
1523 if (EFI_ERROR (Status)) {\r
1524 goto Done;\r
1525 }\r
1526\r
1527 Status = PopExpression (&Value[1]);\r
1528 if (EFI_ERROR (Status)) {\r
1529 goto Done;\r
1530 }\r
1531\r
1532 for (Index = 0; Index < 2; Index++) {\r
1533 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
1534 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1535 Status = EFI_SUCCESS;\r
1536 goto Done;\r
1537 }\r
1538\r
1539 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1540 if (String [Index] == NULL) {\r
1541 Status = EFI_NOT_FOUND;\r
1542 goto Done;\r
1543 }\r
1544 }\r
1545\r
1546 BufferSize = 0;\r
1547 HandleBuffer = NULL;\r
1548 Status = gBS->LocateHandle(\r
1549 ByProtocol,\r
1550 &gEfiRegularExpressionProtocolGuid,\r
1551 NULL,\r
1552 &BufferSize,\r
1553 HandleBuffer);\r
1554 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1555 HandleBuffer = AllocateZeroPool(BufferSize);\r
1556 if (HandleBuffer == NULL) {\r
1557 Status = EFI_OUT_OF_RESOURCES;\r
1558 goto Done;\r
1559 }\r
1560 Status = gBS->LocateHandle(\r
1561 ByProtocol,\r
1562 &gEfiRegularExpressionProtocolGuid,\r
1563 NULL,\r
1564 &BufferSize,\r
1565 HandleBuffer);\r
1566\r
1567 }\r
1568\r
1569 if (EFI_ERROR (Status)) {\r
1570 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1571 Status = EFI_SUCCESS;\r
1572 goto Done;\r
1573 }\r
1574\r
1575 ASSERT (HandleBuffer != NULL);\r
1576 for ( Index = 0; Index < BufferSize / sizeof(EFI_HANDLE); Index ++) {\r
1577 Status = gBS->HandleProtocol (\r
1578 HandleBuffer[Index],\r
1579 &gEfiRegularExpressionProtocolGuid,\r
1580 (VOID**)&RegularExpressionProtocol\r
1581 );\r
1582 if (EFI_ERROR (Status)) {\r
1583 goto Done;\r
1584 }\r
1585\r
1586 RegExSyntaxTypeListSize = 0;\r
1587 RegExSyntaxTypeList = NULL;\r
1588\r
1589 Status = RegularExpressionProtocol->GetInfo (\r
1590 RegularExpressionProtocol,\r
1591 &RegExSyntaxTypeListSize,\r
1592 RegExSyntaxTypeList\r
1593 );\r
1594 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1595 RegExSyntaxTypeList = AllocateZeroPool(RegExSyntaxTypeListSize);\r
1596 if (RegExSyntaxTypeList == NULL) {\r
1597 Status = EFI_OUT_OF_RESOURCES;\r
1598 goto Done;\r
1599 }\r
1600 Status = RegularExpressionProtocol->GetInfo (\r
1601 RegularExpressionProtocol,\r
1602 &RegExSyntaxTypeListSize,\r
1603 RegExSyntaxTypeList\r
1604 );\r
1605 } else if (EFI_ERROR (Status)) {\r
1606 goto Done;\r
1607 }\r
1608\r
1609 for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof(EFI_GUID); GuidIndex++) {\r
1610 if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {\r
1611 //\r
1612 // Find the match type, return the value.\r
1613 //\r
1614 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1615 Status = RegularExpressionProtocol->MatchString (\r
1616 RegularExpressionProtocol,\r
1617 String[0],\r
1618 String[1],\r
1619 SyntaxType,\r
1620 &Result->Value.b,\r
1621 NULL,\r
1622 &CapturesCount\r
1623 );\r
1624 goto Done;\r
1625 }\r
1626 }\r
1627\r
1628 if (RegExSyntaxTypeList != NULL) {\r
1629 FreePool (RegExSyntaxTypeList);\r
1630 }\r
1631 }\r
1632\r
1633 //\r
1634 // Type specified by SyntaxType is not supported\r
1635 // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.\r
1636 //\r
1637 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1638 Status = EFI_SUCCESS;\r
1639\r
1640Done:\r
1641 if (String[0] != NULL) {\r
1642 FreePool (String[0]);\r
1643 }\r
1644 if (String[1] != NULL) {\r
1645 FreePool (String[1]);\r
1646 }\r
1647 if (RegExSyntaxTypeList != NULL) {\r
1648 FreePool (RegExSyntaxTypeList);\r
1649 }\r
1650 if (HandleBuffer != NULL) {\r
1651 FreePool (HandleBuffer);\r
1652 }\r
1653 return Status;\r
1654}\r
1655\r
1656/**\r
1657 Evaluate opcode EFI_IFR_FIND.\r
1658\r
1659 @param FormSet Formset which contains this opcode.\r
1660 @param Format Case sensitive or insensitive.\r
1661 @param Result Evaluation result for this opcode.\r
1662\r
1663 @retval EFI_SUCCESS Opcode evaluation success.\r
1664 @retval Other Opcode evaluation failed.\r
1665\r
1666**/\r
1667EFI_STATUS\r
1668IfrFind (\r
1669 IN FORM_BROWSER_FORMSET *FormSet,\r
1670 IN UINT8 Format,\r
1671 OUT EFI_HII_VALUE *Result\r
1672 )\r
1673{\r
1674 EFI_STATUS Status;\r
1675 EFI_HII_VALUE Value[3];\r
1676 CHAR16 *String[2];\r
1677 UINTN Base;\r
1678 CHAR16 *StringPtr;\r
1679 UINTN Index;\r
1680\r
1681 ZeroMem (Value, sizeof (Value));\r
1682\r
1683 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
1684 return EFI_INVALID_PARAMETER;\r
1685 }\r
1686\r
1687 Status = PopExpression (&Value[0]);\r
1688 if (EFI_ERROR (Status)) {\r
1689 return Status;\r
1690 }\r
1691\r
1692 Status = PopExpression (&Value[1]);\r
1693 if (EFI_ERROR (Status)) {\r
1694 return Status;\r
1695 }\r
1696\r
1697 Status = PopExpression (&Value[2]);\r
1698 if (EFI_ERROR (Status)) {\r
1699 return Status;\r
1700 }\r
1701\r
1702 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1703 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1704 return EFI_SUCCESS;\r
1705 }\r
1706 Base = (UINTN) Value[0].Value.u64;\r
1707\r
1708 //\r
1709 // String[0] - sub-string\r
1710 // String[1] - The string to search\r
1711 //\r
1712 String[0] = NULL;\r
1713 String[1] = NULL;\r
1714 for (Index = 0; Index < 2; Index++) {\r
1715 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1716 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1717 Status = EFI_SUCCESS;\r
1718 goto Done;\r
1719 }\r
1720\r
1721 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
1722 if (String[Index] == NULL) {\r
1723 Status = EFI_NOT_FOUND;\r
1724 goto Done;\r
1725 }\r
1726\r
1727 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
1728 //\r
1729 // Case insensitive, convert both string to upper case\r
1730 //\r
1731 IfrStrToUpper (String[Index]);\r
1732 }\r
1733 }\r
1734\r
1735 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1736 if (Base >= StrLen (String[1])) {\r
1737 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
1738 } else {\r
1739 StringPtr = StrStr (String[1] + Base, String[0]);\r
1740 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
1741 }\r
1742\r
1743Done:\r
1744 if (String[0] != NULL) {\r
1745 FreePool (String[0]);\r
1746 }\r
1747 if (String[1] != NULL) {\r
1748 FreePool (String[1]);\r
1749 }\r
1750\r
1751 return Status;\r
1752}\r
1753\r
1754\r
1755/**\r
1756 Evaluate opcode EFI_IFR_MID.\r
1757\r
1758 @param FormSet Formset which contains this opcode.\r
1759 @param Result Evaluation result for this opcode.\r
1760\r
1761 @retval EFI_SUCCESS Opcode evaluation success.\r
1762 @retval Other Opcode evaluation failed.\r
1763\r
1764**/\r
1765EFI_STATUS\r
1766IfrMid (\r
1767 IN FORM_BROWSER_FORMSET *FormSet,\r
1768 OUT EFI_HII_VALUE *Result\r
1769 )\r
1770{\r
1771 EFI_STATUS Status;\r
1772 EFI_HII_VALUE Value[3];\r
1773 CHAR16 *String;\r
1774 UINTN Base;\r
1775 UINTN Length;\r
1776 CHAR16 *SubString;\r
1777 UINT16 BufferLen;\r
1778 UINT8 *Buffer;\r
1779\r
1780 ZeroMem (Value, sizeof (Value));\r
1781\r
1782 Status = PopExpression (&Value[0]);\r
1783 if (EFI_ERROR (Status)) {\r
1784 return Status;\r
1785 }\r
1786\r
1787 Status = PopExpression (&Value[1]);\r
1788 if (EFI_ERROR (Status)) {\r
1789 return Status;\r
1790 }\r
1791\r
1792 Status = PopExpression (&Value[2]);\r
1793 if (EFI_ERROR (Status)) {\r
1794 return Status;\r
1795 }\r
1796\r
1797 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1798 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1799 return EFI_SUCCESS;\r
1800 }\r
1801 Length = (UINTN) Value[0].Value.u64;\r
1802\r
1803 if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1804 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1805 return EFI_SUCCESS;\r
1806 }\r
1807 Base = (UINTN) Value[1].Value.u64;\r
1808\r
1809 if (Value[2].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[2])) {\r
1810 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1811 return EFI_SUCCESS;\r
1812 }\r
1813 if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
1814 String = GetToken (Value[2].Value.string, FormSet->HiiHandle);\r
1815 if (String == NULL) {\r
1816 return EFI_NOT_FOUND;\r
1817 }\r
1818\r
1819 if (Length == 0 || Base >= StrLen (String)) {\r
1820 SubString = gEmptyString;\r
1821 } else {\r
1822 SubString = String + Base;\r
1823 if ((Base + Length) < StrLen (String)) {\r
1824 SubString[Length] = L'\0';\r
1825 }\r
1826 }\r
1827\r
1828 Result->Type = EFI_IFR_TYPE_STRING;\r
1829 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1830\r
1831 FreePool (String);\r
1832 } else {\r
1833 BufferLen = GetLengthForValue (&Value[2]);\r
1834 Buffer = GetBufferForValue (&Value[2]);\r
1835\r
1836 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1837 if (Length == 0 || Base >= BufferLen) {\r
1838 Result->BufferLen = 0;\r
1839 Result->Buffer = NULL;\r
1840 } else {\r
1841 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);\r
1842 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1843 ASSERT (Result->Buffer != NULL);\r
1844 CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
1845 }\r
1846\r
1847 if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
1848 FreePool (Value[2].Buffer);\r
1849 }\r
1850 }\r
1851\r
1852 return Status;\r
1853}\r
1854\r
1855\r
1856/**\r
1857 Evaluate opcode EFI_IFR_TOKEN.\r
1858\r
1859 @param FormSet Formset which contains this opcode.\r
1860 @param Result Evaluation result for this opcode.\r
1861\r
1862 @retval EFI_SUCCESS Opcode evaluation success.\r
1863 @retval Other Opcode evaluation failed.\r
1864\r
1865**/\r
1866EFI_STATUS\r
1867IfrToken (\r
1868 IN FORM_BROWSER_FORMSET *FormSet,\r
1869 OUT EFI_HII_VALUE *Result\r
1870 )\r
1871{\r
1872 EFI_STATUS Status;\r
1873 EFI_HII_VALUE Value[3];\r
1874 CHAR16 *String[2];\r
1875 UINTN Count;\r
1876 CHAR16 *Delimiter;\r
1877 CHAR16 *SubString;\r
1878 CHAR16 *StringPtr;\r
1879 UINTN Index;\r
1880\r
1881 ZeroMem (Value, sizeof (Value));\r
1882\r
1883 Status = PopExpression (&Value[0]);\r
1884 if (EFI_ERROR (Status)) {\r
1885 return Status;\r
1886 }\r
1887\r
1888 Status = PopExpression (&Value[1]);\r
1889 if (EFI_ERROR (Status)) {\r
1890 return Status;\r
1891 }\r
1892\r
1893 Status = PopExpression (&Value[2]);\r
1894 if (EFI_ERROR (Status)) {\r
1895 return Status;\r
1896 }\r
1897\r
1898 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1899 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1900 return EFI_SUCCESS;\r
1901 }\r
1902 Count = (UINTN) Value[0].Value.u64;\r
1903\r
1904 //\r
1905 // String[0] - Delimiter\r
1906 // String[1] - The string to search\r
1907 //\r
1908 String[0] = NULL;\r
1909 String[1] = NULL;\r
1910 for (Index = 0; Index < 2; Index++) {\r
1911 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1912 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1913 Status = EFI_SUCCESS;\r
1914 goto Done;\r
1915 }\r
1916\r
1917 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
1918 if (String[Index] == NULL) {\r
1919 Status = EFI_NOT_FOUND;\r
1920 goto Done;\r
1921 }\r
1922 }\r
1923\r
1924 Delimiter = String[0];\r
1925 SubString = String[1];\r
1926 while (Count > 0) {\r
1927 SubString = StrStr (SubString, Delimiter);\r
1928 if (SubString != NULL) {\r
1929 //\r
1930 // Skip over the delimiter\r
1931 //\r
1932 SubString = SubString + StrLen (Delimiter);\r
1933 } else {\r
1934 break;\r
1935 }\r
1936 Count--;\r
1937 }\r
1938\r
1939 if (SubString == NULL) {\r
1940 //\r
1941 // nth delimited sub-string not found, push an empty string\r
1942 //\r
1943 SubString = gEmptyString;\r
1944 } else {\r
1945 //\r
1946 // Put a NULL terminator for nth delimited sub-string\r
1947 //\r
1948 StringPtr = StrStr (SubString, Delimiter);\r
1949 if (StringPtr != NULL) {\r
1950 *StringPtr = L'\0';\r
1951 }\r
1952 }\r
1953\r
1954 Result->Type = EFI_IFR_TYPE_STRING;\r
1955 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1956\r
1957Done:\r
1958 if (String[0] != NULL) {\r
1959 FreePool (String[0]);\r
1960 }\r
1961 if (String[1] != NULL) {\r
1962 FreePool (String[1]);\r
1963 }\r
1964\r
1965 return Status;\r
1966}\r
1967\r
1968\r
1969/**\r
1970 Evaluate opcode EFI_IFR_SPAN.\r
1971\r
1972 @param FormSet Formset which contains this opcode.\r
1973 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1974 @param Result Evaluation result for this opcode.\r
1975\r
1976 @retval EFI_SUCCESS Opcode evaluation success.\r
1977 @retval Other Opcode evaluation failed.\r
1978\r
1979**/\r
1980EFI_STATUS\r
1981IfrSpan (\r
1982 IN FORM_BROWSER_FORMSET *FormSet,\r
1983 IN UINT8 Flags,\r
1984 OUT EFI_HII_VALUE *Result\r
1985 )\r
1986{\r
1987 EFI_STATUS Status;\r
1988 EFI_HII_VALUE Value[3];\r
1989 CHAR16 *String[2];\r
1990 CHAR16 *Charset;\r
1991 UINTN Base;\r
1992 UINTN Index;\r
1993 CHAR16 *StringPtr;\r
1994 BOOLEAN Found;\r
1995\r
1996 ZeroMem (Value, sizeof (Value));\r
1997\r
1998 Status = PopExpression (&Value[0]);\r
1999 if (EFI_ERROR (Status)) {\r
2000 return Status;\r
2001 }\r
2002\r
2003 Status = PopExpression (&Value[1]);\r
2004 if (EFI_ERROR (Status)) {\r
2005 return Status;\r
2006 }\r
2007\r
2008 Status = PopExpression (&Value[2]);\r
2009 if (EFI_ERROR (Status)) {\r
2010 return Status;\r
2011 }\r
2012\r
2013 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
2014 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2015 return EFI_SUCCESS;\r
2016 }\r
2017 Base = (UINTN) Value[0].Value.u64;\r
2018\r
2019 //\r
2020 // String[0] - Charset\r
2021 // String[1] - The string to search\r
2022 //\r
2023 String[0] = NULL;\r
2024 String[1] = NULL;\r
2025 for (Index = 0; Index < 2; Index++) {\r
2026 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
2027 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2028 Status = EFI_SUCCESS;\r
2029 goto Done;\r
2030 }\r
2031\r
2032 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
2033 if (String [Index] == NULL) {\r
2034 Status = EFI_NOT_FOUND;\r
2035 goto Done;\r
2036 }\r
2037 }\r
2038\r
2039 if (Base >= StrLen (String[1])) {\r
2040 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2041 Status = EFI_SUCCESS;\r
2042 goto Done;\r
2043 }\r
2044\r
2045 Found = FALSE;\r
2046 StringPtr = String[1] + Base;\r
2047 Charset = String[0];\r
2048 while (*StringPtr != 0 && !Found) {\r
2049 Index = 0;\r
2050 while (Charset[Index] != 0) {\r
2051 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
2052 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
2053 Found = TRUE;\r
2054 break;\r
2055 }\r
2056 } else {\r
2057 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
2058 Found = TRUE;\r
2059 break;\r
2060 }\r
2061 }\r
2062 //\r
2063 // Skip characters pair representing low-end of a range and high-end of a range\r
2064 //\r
2065 Index += 2;\r
2066 }\r
2067\r
2068 if (!Found) {\r
2069 StringPtr++;\r
2070 }\r
2071 }\r
2072\r
2073 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2074 Result->Value.u64 = StringPtr - String[1];\r
2075\r
2076Done:\r
2077 if (String[0] != NULL) {\r
2078 FreePool (String[0]);\r
2079 }\r
2080 if (String[1] != NULL) {\r
2081 FreePool (String[1]);\r
2082 }\r
2083\r
2084 return Status;\r
2085}\r
2086\r
2087\r
2088/**\r
2089 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
2090\r
2091 @param Value HII Value to be converted.\r
2092\r
2093**/\r
2094VOID\r
2095ExtendValueToU64 (\r
2096 IN EFI_HII_VALUE *Value\r
2097 )\r
2098{\r
2099 UINT64 Temp;\r
2100\r
2101 Temp = 0;\r
2102 switch (Value->Type) {\r
2103 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2104 Temp = Value->Value.u8;\r
2105 break;\r
2106\r
2107 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2108 Temp = Value->Value.u16;\r
2109 break;\r
2110\r
2111 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2112 Temp = Value->Value.u32;\r
2113 break;\r
2114\r
2115 case EFI_IFR_TYPE_BOOLEAN:\r
2116 Temp = Value->Value.b;\r
2117 break;\r
2118\r
2119 case EFI_IFR_TYPE_TIME:\r
2120 Temp = Value->Value.u32 & 0xffffff;\r
2121 break;\r
2122\r
2123 case EFI_IFR_TYPE_DATE:\r
2124 Temp = Value->Value.u32;\r
2125 break;\r
2126\r
2127 default:\r
2128 return;\r
2129 }\r
2130\r
2131 Value->Value.u64 = Temp;\r
2132}\r
2133\r
2134/**\r
2135 Get UINT64 type value.\r
2136\r
2137 @param Value Input Hii value.\r
2138\r
2139 @retval UINT64 Return the UINT64 type value.\r
2140\r
2141**/\r
2142UINT64\r
2143HiiValueToUINT64 (\r
2144 IN EFI_HII_VALUE *Value\r
2145 )\r
2146{\r
2147 UINT64 RetVal;\r
2148\r
2149 RetVal = 0;\r
2150\r
2151 switch (Value->Type) {\r
2152 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2153 RetVal = Value->Value.u8;\r
2154 break;\r
2155\r
2156 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2157 RetVal = Value->Value.u16;\r
2158 break;\r
2159\r
2160 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2161 RetVal = Value->Value.u32;\r
2162 break;\r
2163\r
2164 case EFI_IFR_TYPE_BOOLEAN:\r
2165 RetVal = Value->Value.b;\r
2166 break;\r
2167\r
2168 case EFI_IFR_TYPE_DATE:\r
2169 RetVal = *(UINT64*) &Value->Value.date;\r
2170 break;\r
2171\r
2172 case EFI_IFR_TYPE_TIME:\r
2173 RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;\r
2174 break;\r
2175\r
2176 default:\r
2177 RetVal = Value->Value.u64;\r
2178 break;\r
2179 }\r
2180\r
2181 return RetVal;\r
2182}\r
2183\r
2184/**\r
2185 Compare two Hii value.\r
2186\r
2187 @param Value1 Expression value to compare on left-hand.\r
2188 @param Value2 Expression value to compare on right-hand.\r
2189 @param Result Return value after compare.\r
2190 retval 0 Two operators equal.\r
2191 return Positive value if Value1 is greater than Value2.\r
2192 retval Negative value if Value1 is less than Value2.\r
2193 @param HiiHandle Only required for string compare.\r
2194\r
2195 @retval other Could not perform compare on two values.\r
2196 @retval EFI_SUCCESS Compare the value success.\r
2197\r
2198**/\r
2199EFI_STATUS\r
2200CompareHiiValue (\r
2201 IN EFI_HII_VALUE *Value1,\r
2202 IN EFI_HII_VALUE *Value2,\r
2203 OUT INTN *Result,\r
2204 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
2205 )\r
2206{\r
2207 INT64 Temp64;\r
2208 CHAR16 *Str1;\r
2209 CHAR16 *Str2;\r
2210 UINTN Len;\r
2211 UINT8 *Buf1;\r
2212 UINT16 Buf1Len;\r
2213 UINT8 *Buf2;\r
2214 UINT16 Buf2Len;\r
2215\r
2216 if (Value1->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {\r
2217 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
2218 //\r
2219 // StringId 0 is reserved\r
2220 //\r
2221 return EFI_INVALID_PARAMETER;\r
2222 }\r
2223\r
2224 if (Value1->Value.string == Value2->Value.string) {\r
2225 *Result = 0;\r
2226 return EFI_SUCCESS;\r
2227 }\r
2228\r
2229 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
2230 if (Str1 == NULL) {\r
2231 //\r
2232 // String not found\r
2233 //\r
2234 return EFI_NOT_FOUND;\r
2235 }\r
2236\r
2237 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
2238 if (Str2 == NULL) {\r
2239 FreePool (Str1);\r
2240 return EFI_NOT_FOUND;\r
2241 }\r
2242\r
2243 *Result = StrCmp (Str1, Str2);\r
2244\r
2245 FreePool (Str1);\r
2246 FreePool (Str2);\r
2247\r
2248 return EFI_SUCCESS;\r
2249 }\r
2250\r
2251 //\r
2252 // Take types(date, time, ref, buffer) as buffer\r
2253 //\r
2254 if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {\r
2255 Buf1 = GetBufferForValue(Value1);\r
2256 Buf1Len = GetLengthForValue(Value1);\r
2257 Buf2 = GetBufferForValue(Value2);\r
2258 Buf2Len = GetLengthForValue(Value2);\r
2259\r
2260 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
2261 *Result = CompareMem (Buf1, Buf2, Len);\r
2262 if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
2263 //\r
2264 // In this case, means base on samll number buffer, the data is same\r
2265 // So which value has more data, which value is bigger.\r
2266 //\r
2267 *Result = Buf1Len > Buf2Len ? 1 : -1;\r
2268 }\r
2269 return EFI_SUCCESS;\r
2270 }\r
2271\r
2272 //\r
2273 // Take types(integer, boolean) as integer\r
2274 //\r
2275 if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {\r
2276 Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);\r
2277 if (Temp64 > 0) {\r
2278 *Result = 1;\r
2279 } else if (Temp64 < 0) {\r
2280 *Result = -1;\r
2281 } else {\r
2282 *Result = 0;\r
2283 }\r
2284\r
2285 return EFI_SUCCESS;\r
2286 }\r
2287\r
2288 return EFI_UNSUPPORTED;\r
2289}\r
2290\r
2291/**\r
2292 Check if current user has the privilege specified by the permissions GUID.\r
2293\r
2294 @param[in] Guid A GUID specifying setup access permissions.\r
2295\r
2296 @retval TRUE Current user has the privilege.\r
2297 @retval FALSE Current user does not have the privilege.\r
2298**/\r
2299BOOLEAN\r
2300CheckUserPrivilege (\r
2301 IN EFI_GUID *Guid\r
2302 )\r
2303{\r
2304 EFI_STATUS Status;\r
2305 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
2306 EFI_USER_INFO_HANDLE UserInfoHandle;\r
2307 EFI_USER_INFO *UserInfo;\r
2308 EFI_GUID *UserPermissionsGuid;\r
2309 UINTN UserInfoSize;\r
2310 UINTN AccessControlDataSize;\r
2311 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
2312 UINTN RemainSize;\r
2313\r
2314 if (mUserManager == NULL) {\r
2315 Status = gBS->LocateProtocol (\r
2316 &gEfiUserManagerProtocolGuid,\r
2317 NULL,\r
2318 (VOID **) &mUserManager\r
2319 );\r
2320 if (EFI_ERROR (Status)) {\r
2321 ///\r
2322 /// If the system does not support user management, then it is assumed that\r
2323 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
2324 /// op-code is always TRUE.\r
2325 ///\r
2326 return TRUE;\r
2327 }\r
2328 }\r
2329\r
2330 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
2331 ASSERT_EFI_ERROR (Status);\r
2332\r
2333 ///\r
2334 /// Enumerate all user information of the current user profile\r
2335 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
2336 ///\r
2337\r
2338 for (UserInfoHandle = NULL;;) {\r
2339 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
2340 if (EFI_ERROR (Status)) {\r
2341 break;\r
2342 }\r
2343\r
2344 UserInfoSize = 0;\r
2345 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
2346 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2347 continue;\r
2348 }\r
2349\r
2350 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
2351 if (UserInfo == NULL) {\r
2352 break;\r
2353 }\r
2354\r
2355 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
2356 if (EFI_ERROR (Status) ||\r
2357 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
2358 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
2359 FreePool (UserInfo);\r
2360 continue;\r
2361 }\r
2362\r
2363 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
2364 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
2365 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
2366 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
2367 break;\r
2368 }\r
2369 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
2370 ///\r
2371 /// Check if current user has the privilege specified by the permissions GUID.\r
2372 ///\r
2373\r
2374 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
2375 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
2376 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
2377 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
2378 FreePool (UserInfo);\r
2379 return TRUE;\r
2380 }\r
2381 UserPermissionsGuid++;\r
2382 AccessControlDataSize -= sizeof (EFI_GUID);\r
2383 }\r
2384 }\r
2385 RemainSize -= AccessControl->Size;\r
2386 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
2387 }\r
2388\r
2389 FreePool (UserInfo);\r
2390 }\r
2391 return FALSE;\r
2392}\r
2393\r
2394/**\r
2395 Get question value from the predefined formset.\r
2396\r
2397 @param DevicePath The driver's device path which produece the formset data.\r
2398 @param InputHiiHandle The hii handle associate with the formset data.\r
2399 @param FormSetGuid The formset guid which include the question.\r
2400 @param QuestionId The question id which need to get value from.\r
2401 @param Value The return data about question's value.\r
2402\r
2403 @retval TRUE Get the question value success.\r
2404 @retval FALSE Get the question value failed.\r
2405**/\r
2406BOOLEAN\r
2407GetQuestionValueFromForm (\r
2408 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2409 IN EFI_HII_HANDLE InputHiiHandle,\r
2410 IN EFI_GUID *FormSetGuid,\r
2411 IN EFI_QUESTION_ID QuestionId,\r
2412 OUT EFI_HII_VALUE *Value\r
2413 )\r
2414{\r
2415 EFI_STATUS Status;\r
2416 EFI_HII_HANDLE HiiHandle;\r
2417 FORM_BROWSER_STATEMENT *Question;\r
2418 FORM_BROWSER_FORMSET *FormSet;\r
2419 FORM_BROWSER_FORM *Form;\r
2420 BOOLEAN GetTheVal;\r
2421 LIST_ENTRY *Link;\r
2422\r
2423 //\r
2424 // The input parameter DevicePath or InputHiiHandle must have one valid input.\r
2425 //\r
2426 ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) ||\r
2427 (DevicePath == NULL && InputHiiHandle != NULL) );\r
2428\r
2429 GetTheVal = TRUE;\r
2430 HiiHandle = NULL;\r
2431 Question = NULL;\r
2432 Form = NULL;\r
2433\r
2434 //\r
2435 // Get HiiHandle.\r
2436 //\r
2437 if (DevicePath != NULL) {\r
2438 HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
2439 if (HiiHandle == NULL) {\r
2440 return FALSE;\r
2441 }\r
2442 } else {\r
2443 HiiHandle = InputHiiHandle;\r
2444 }\r
2445 ASSERT (HiiHandle != NULL);\r
2446\r
2447 //\r
2448 // Get the formset data include this question.\r
2449 //\r
2450 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
2451 ASSERT (FormSet != NULL);\r
2452 Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);\r
2453 if (EFI_ERROR (Status)) {\r
2454 GetTheVal = FALSE;\r
2455 goto Done;\r
2456 }\r
2457\r
2458 //\r
2459 // Base on the Question Id to get the question info.\r
2460 //\r
2461 Question = IdToQuestion(FormSet, NULL, QuestionId);\r
2462 if (Question == NULL) {\r
2463 GetTheVal = FALSE;\r
2464 goto Done;\r
2465 }\r
2466\r
2467 //\r
2468 // Search form in the formset scope\r
2469 //\r
2470 Link = GetFirstNode (&FormSet->FormListHead);\r
2471 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2472 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2473\r
2474 Question = IdToQuestion2 (Form, QuestionId);\r
2475 if (Question != NULL) {\r
2476 break;\r
2477 }\r
2478\r
2479 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2480 Form = NULL;\r
2481 }\r
2482 ASSERT (Form != NULL);\r
2483\r
2484 //\r
2485 // Get the question value.\r
2486 //\r
2487 Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithEditBuffer);\r
2488 if (EFI_ERROR (Status)) {\r
2489 GetTheVal = FALSE;\r
2490 goto Done;\r
2491 }\r
2492\r
2493 CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
2494\r
2495Done:\r
2496 //\r
2497 // Clean the formset structure and restore the global parameter.\r
2498 //\r
2499 if (FormSet != NULL) {\r
2500 DestroyFormSet (FormSet);\r
2501 }\r
2502\r
2503 return GetTheVal;\r
2504}\r
2505\r
2506/**\r
2507 Evaluate the result of a HII expression.\r
2508\r
2509 If Expression is NULL, then ASSERT.\r
2510\r
2511 @param FormSet FormSet associated with this expression.\r
2512 @param Form Form associated with this expression.\r
2513 @param Expression Expression to be evaluated.\r
2514\r
2515 @retval EFI_SUCCESS The expression evaluated successfuly\r
2516 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
2517 could not be found.\r
2518 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
2519 stack.\r
2520 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
2521 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
2522\r
2523**/\r
2524EFI_STATUS\r
2525EvaluateExpression (\r
2526 IN FORM_BROWSER_FORMSET *FormSet,\r
2527 IN FORM_BROWSER_FORM *Form,\r
2528 IN OUT FORM_EXPRESSION *Expression\r
2529 )\r
2530{\r
2531 EFI_STATUS Status;\r
2532 LIST_ENTRY *Link;\r
2533 EXPRESSION_OPCODE *OpCode;\r
2534 FORM_BROWSER_STATEMENT *Question;\r
2535 FORM_BROWSER_STATEMENT *Question2;\r
2536 UINT16 Index;\r
2537 EFI_HII_VALUE Data1;\r
2538 EFI_HII_VALUE Data2;\r
2539 EFI_HII_VALUE Data3;\r
2540 FORM_EXPRESSION *RuleExpression;\r
2541 EFI_HII_VALUE *Value;\r
2542 INTN Result;\r
2543 CHAR16 *StrPtr;\r
2544 CHAR16 *NameValue;\r
2545 UINT32 TempValue;\r
2546 LIST_ENTRY *SubExpressionLink;\r
2547 FORM_EXPRESSION *SubExpression;\r
2548 UINTN StackOffset;\r
2549 UINTN TempLength;\r
2550 CHAR16 TempStr[5];\r
2551 UINT8 DigitUint8;\r
2552 UINT8 *TempBuffer;\r
2553 EFI_TIME EfiTime;\r
2554 EFI_HII_VALUE QuestionVal;\r
2555 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2556\r
2557 StrPtr = NULL;\r
2558\r
2559 //\r
2560 // Save current stack offset.\r
2561 //\r
2562 StackOffset = SaveExpressionEvaluationStackOffset ();\r
2563\r
2564 ASSERT (Expression != NULL);\r
2565 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
2566\r
2567 Link = GetFirstNode (&Expression->OpCodeListHead);\r
2568 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
2569 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
2570\r
2571 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
2572\r
2573 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
2574 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
2575 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
2576\r
2577 Value = &Data3;\r
2578 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2579 Status = EFI_SUCCESS;\r
2580\r
2581 switch (OpCode->Operand) {\r
2582 //\r
2583 // Built-in functions\r
2584 //\r
2585 case EFI_IFR_EQ_ID_VAL_OP:\r
2586 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2587 if (Question == NULL) {\r
2588 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2589 break;\r
2590 }\r
2591\r
2592 Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);\r
2593 if (Status == EFI_UNSUPPORTED) {\r
2594 Status = EFI_SUCCESS;\r
2595 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2596 break;\r
2597 }\r
2598\r
2599 if (EFI_ERROR (Status)) {\r
2600 goto Done;\r
2601 }\r
2602 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2603 break;\r
2604\r
2605 case EFI_IFR_EQ_ID_ID_OP:\r
2606 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2607 if (Question == NULL) {\r
2608 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2609 break;\r
2610 }\r
2611\r
2612 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
2613 if (Question2 == NULL) {\r
2614 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2615 break;\r
2616 }\r
2617\r
2618 Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);\r
2619 if (Status == EFI_UNSUPPORTED) {\r
2620 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2621 Status = EFI_SUCCESS;\r
2622 break;\r
2623 }\r
2624 if (EFI_ERROR (Status)) {\r
2625 goto Done;\r
2626 }\r
2627 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2628 break;\r
2629\r
2630 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
2631 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2632 if (Question == NULL) {\r
2633 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2634 break;\r
2635 }\r
2636\r
2637 Value->Value.b = FALSE;\r
2638 for (Index =0; Index < OpCode->ListLength; Index++) {\r
2639 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
2640 Value->Value.b = TRUE;\r
2641 break;\r
2642 }\r
2643 }\r
2644 break;\r
2645\r
2646 case EFI_IFR_DUP_OP:\r
2647 Status = PopExpression (Value);\r
2648 if (EFI_ERROR (Status)) {\r
2649 goto Done;\r
2650 }\r
2651\r
2652 Status = PushExpression (Value);\r
2653 break;\r
2654\r
2655 case EFI_IFR_QUESTION_REF1_OP:\r
2656 case EFI_IFR_THIS_OP:\r
2657 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2658 if (Question == NULL) {\r
2659 Status = EFI_NOT_FOUND;\r
2660 goto Done;\r
2661 }\r
2662\r
2663 Value = &Question->HiiValue;\r
2664 break;\r
2665\r
2666 case EFI_IFR_SECURITY_OP:\r
2667 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
2668 break;\r
2669\r
2670 case EFI_IFR_GET_OP:\r
2671 //\r
2672 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2673 //\r
2674 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2675 Value->Value.u8 = 0;\r
2676 if (OpCode->VarStorage != NULL) {\r
2677 switch (OpCode->VarStorage->Type) {\r
2678 case EFI_HII_VARSTORE_BUFFER:\r
2679 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2680 //\r
2681 // Get value from Edit Buffer\r
2682 //\r
2683 Value->Type = OpCode->ValueType;\r
2684 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2685 break;\r
2686 case EFI_HII_VARSTORE_NAME_VALUE:\r
2687 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2688 //\r
2689 // Get value from string except for STRING value.\r
2690 //\r
2691 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);\r
2692 if (!EFI_ERROR (Status)) {\r
2693 ASSERT (StrPtr != NULL);\r
2694 TempLength = StrLen (StrPtr);\r
2695 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
2696 Value->Type = OpCode->ValueType;\r
2697 TempBuffer = (UINT8 *) &Value->Value;\r
2698 ZeroMem (TempStr, sizeof (TempStr));\r
2699 for (Index = 0; Index < TempLength; Index ++) {\r
2700 TempStr[0] = StrPtr[TempLength - Index - 1];\r
2701 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
2702 if ((Index & 1) == 0) {\r
2703 TempBuffer [Index/2] = DigitUint8;\r
2704 } else {\r
2705 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2706 }\r
2707 }\r
2708 }\r
2709 }\r
2710 }\r
2711 break;\r
2712 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2713 //\r
2714 // Get value from variable.\r
2715 //\r
2716 TempLength = OpCode->ValueWidth;\r
2717 Value->Type = OpCode->ValueType;\r
2718 Status = gRT->GetVariable (\r
2719 OpCode->ValueName,\r
2720 &OpCode->VarStorage->Guid,\r
2721 NULL,\r
2722 &TempLength,\r
2723 &Value->Value\r
2724 );\r
2725 if (EFI_ERROR (Status)) {\r
2726 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2727 Value->Value.u8 = 0;\r
2728 }\r
2729 break;\r
2730 default:\r
2731 //\r
2732 // Not recognize storage.\r
2733 //\r
2734 Status = EFI_UNSUPPORTED;\r
2735 goto Done;\r
2736 }\r
2737 } else {\r
2738 //\r
2739 // For Time/Date Data\r
2740 //\r
2741 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2742 //\r
2743 // Only support Data/Time data when storage doesn't exist.\r
2744 //\r
2745 Status = EFI_UNSUPPORTED;\r
2746 goto Done;\r
2747 }\r
2748 Status = gRT->GetTime (&EfiTime, NULL);\r
2749 if (!EFI_ERROR (Status)) {\r
2750 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2751 switch (OpCode->VarStoreInfo.VarOffset) {\r
2752 case 0x00:\r
2753 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
2754 Value->Value.u16 = EfiTime.Year;\r
2755 break;\r
2756 case 0x02:\r
2757 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2758 Value->Value.u8 = EfiTime.Month;\r
2759 break;\r
2760 case 0x03:\r
2761 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2762 Value->Value.u8 = EfiTime.Day;\r
2763 break;\r
2764 default:\r
2765 //\r
2766 // Invalid Date field.\r
2767 //\r
2768 Status = EFI_INVALID_PARAMETER;\r
2769 goto Done;\r
2770 }\r
2771 } else {\r
2772 switch (OpCode->VarStoreInfo.VarOffset) {\r
2773 case 0x00:\r
2774 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2775 Value->Value.u8 = EfiTime.Hour;\r
2776 break;\r
2777 case 0x01:\r
2778 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2779 Value->Value.u8 = EfiTime.Minute;\r
2780 break;\r
2781 case 0x02:\r
2782 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2783 Value->Value.u8 = EfiTime.Second;\r
2784 break;\r
2785 default:\r
2786 //\r
2787 // Invalid Time field.\r
2788 //\r
2789 Status = EFI_INVALID_PARAMETER;\r
2790 goto Done;\r
2791 }\r
2792 }\r
2793 }\r
2794 }\r
2795\r
2796 break;\r
2797\r
2798 case EFI_IFR_QUESTION_REF3_OP:\r
2799 //\r
2800 // EFI_IFR_QUESTION_REF3\r
2801 // Pop an expression from the expression stack\r
2802 //\r
2803 Status = PopExpression (Value);\r
2804 if (EFI_ERROR (Status)) {\r
2805 goto Done;\r
2806 }\r
2807\r
2808 //\r
2809 // Validate the expression value\r
2810 //\r
2811 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2812 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2813 break;\r
2814 }\r
2815\r
2816 if (OpCode->DevicePath != 0) {\r
2817 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2818\r
2819 StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
2820 if (StrPtr != NULL && mPathFromText != NULL) {\r
2821 DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);\r
2822 if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {\r
2823 Value = &QuestionVal;\r
2824 }\r
2825 if (DevicePath != NULL) {\r
2826 FreePool (DevicePath);\r
2827 }\r
2828 }\r
2829\r
2830 if (StrPtr != NULL) {\r
2831 FreePool (StrPtr);\r
2832 }\r
2833 } else if (IsZeroGuid (&OpCode->Guid)) {\r
2834 if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
2835 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2836 break;\r
2837 }\r
2838 Value = &QuestionVal;\r
2839 } else {\r
2840 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2841 if (Question == NULL) {\r
2842 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2843 break;\r
2844 }\r
2845\r
2846 //\r
2847 // push the questions' value on to the expression stack\r
2848 //\r
2849 Value = &Question->HiiValue;\r
2850 }\r
2851 break;\r
2852\r
2853 case EFI_IFR_RULE_REF_OP:\r
2854 //\r
2855 // Find expression for this rule\r
2856 //\r
2857 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
2858 if (RuleExpression == NULL) {\r
2859 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2860 break;\r
2861 }\r
2862\r
2863 //\r
2864 // Evaluate this rule expression\r
2865 //\r
2866 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
2867 if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {\r
2868 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2869 break;\r
2870 }\r
2871\r
2872 Value = &RuleExpression->Result;\r
2873 break;\r
2874\r
2875 case EFI_IFR_STRING_REF1_OP:\r
2876 Value->Type = EFI_IFR_TYPE_STRING;\r
2877 Value->Value.string = OpCode->Value.Value.string;\r
2878 break;\r
2879\r
2880 //\r
2881 // Constant\r
2882 //\r
2883 case EFI_IFR_TRUE_OP:\r
2884 case EFI_IFR_FALSE_OP:\r
2885 case EFI_IFR_ONE_OP:\r
2886 case EFI_IFR_ONES_OP:\r
2887 case EFI_IFR_UINT8_OP:\r
2888 case EFI_IFR_UINT16_OP:\r
2889 case EFI_IFR_UINT32_OP:\r
2890 case EFI_IFR_UINT64_OP:\r
2891 case EFI_IFR_UNDEFINED_OP:\r
2892 case EFI_IFR_VERSION_OP:\r
2893 case EFI_IFR_ZERO_OP:\r
2894 Value = &OpCode->Value;\r
2895 break;\r
2896\r
2897 //\r
2898 // unary-op\r
2899 //\r
2900 case EFI_IFR_LENGTH_OP:\r
2901 Status = PopExpression (Value);\r
2902 if (EFI_ERROR (Status)) {\r
2903 goto Done;\r
2904 }\r
2905 if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) {\r
2906 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2907 break;\r
2908 }\r
2909\r
2910 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2911 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2912 if (StrPtr == NULL) {\r
2913 Status = EFI_INVALID_PARAMETER;\r
2914 goto Done;\r
2915 }\r
2916\r
2917 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2918 Value->Value.u64 = StrLen (StrPtr);\r
2919 FreePool (StrPtr);\r
2920 } else {\r
2921 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2922 Value->Value.u64 = GetLengthForValue(Value);\r
2923 FreePool (Value->Buffer);\r
2924 }\r
2925 break;\r
2926\r
2927 case EFI_IFR_NOT_OP:\r
2928 Status = PopExpression (Value);\r
2929 if (EFI_ERROR (Status)) {\r
2930 goto Done;\r
2931 }\r
2932 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
2933 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2934 break;\r
2935 }\r
2936 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2937 break;\r
2938\r
2939 case EFI_IFR_QUESTION_REF2_OP:\r
2940 //\r
2941 // Pop an expression from the expression stack\r
2942 //\r
2943 Status = PopExpression (Value);\r
2944 if (EFI_ERROR (Status)) {\r
2945 goto Done;\r
2946 }\r
2947\r
2948 //\r
2949 // Validate the expression value\r
2950 //\r
2951 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2952 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2953 break;\r
2954 }\r
2955\r
2956 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2957 if (Question == NULL) {\r
2958 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2959 break;\r
2960 }\r
2961\r
2962 Value = &Question->HiiValue;\r
2963 break;\r
2964\r
2965 case EFI_IFR_STRING_REF2_OP:\r
2966 //\r
2967 // Pop an expression from the expression stack\r
2968 //\r
2969 Status = PopExpression (Value);\r
2970 if (EFI_ERROR (Status)) {\r
2971 goto Done;\r
2972 }\r
2973\r
2974 //\r
2975 // Validate the expression value\r
2976 //\r
2977 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
2978 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2979 break;\r
2980 }\r
2981\r
2982 Value->Type = EFI_IFR_TYPE_STRING;\r
2983 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2984 if (StrPtr == NULL) {\r
2985 //\r
2986 // If String not exit, push an empty string\r
2987 //\r
2988 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2989 } else {\r
2990 Index = (UINT16) Value->Value.u64;\r
2991 Value->Value.string = Index;\r
2992 FreePool (StrPtr);\r
2993 }\r
2994 break;\r
2995\r
2996 case EFI_IFR_TO_BOOLEAN_OP:\r
2997 //\r
2998 // Pop an expression from the expression stack\r
2999 //\r
3000 Status = PopExpression (Value);\r
3001 if (EFI_ERROR (Status)) {\r
3002 goto Done;\r
3003 }\r
3004\r
3005 //\r
3006 // Convert an expression to a Boolean\r
3007 //\r
3008 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
3009 //\r
3010 // When converting from an unsigned integer, zero will be converted to\r
3011 // FALSE and any other value will be converted to TRUE.\r
3012 //\r
3013 Value->Value.b = (BOOLEAN) (HiiValueToUINT64(Value) != 0);\r
3014\r
3015 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3016 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
3017 //\r
3018 // When converting from a string, if case-insensitive compare\r
3019 // with "true" is True, then push True. If a case-insensitive compare\r
3020 // with "false" is True, then push False. Otherwise, push Undefined.\r
3021 //\r
3022 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
3023 if (StrPtr == NULL) {\r
3024 Status = EFI_INVALID_PARAMETER;\r
3025 goto Done;\r
3026 }\r
3027\r
3028 IfrStrToUpper (StrPtr);\r
3029 if (StrCmp (StrPtr, L"TRUE") == 0){\r
3030 Value->Value.b = TRUE;\r
3031 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3032 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
3033 Value->Value.b = FALSE;\r
3034 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3035 } else {\r
3036 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3037 }\r
3038 FreePool (StrPtr);\r
3039 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
3040 //\r
3041 // When converting from a buffer, if the buffer is all zeroes,\r
3042 // then push False. Otherwise push True.\r
3043 //\r
3044 for (Index =0; Index < Value->BufferLen; Index ++) {\r
3045 if (Value->Buffer[Index] != 0) {\r
3046 break;\r
3047 }\r
3048 }\r
3049\r
3050 if (Index >= Value->BufferLen) {\r
3051 Value->Value.b = FALSE;\r
3052 } else {\r
3053 Value->Value.b = TRUE;\r
3054 }\r
3055 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3056 FreePool (Value->Buffer);\r
3057 }\r
3058 break;\r
3059\r
3060 case EFI_IFR_TO_STRING_OP:\r
3061 Status = IfrToString (FormSet, OpCode->Format, Value);\r
3062 break;\r
3063\r
3064 case EFI_IFR_TO_UINT_OP:\r
3065 Status = IfrToUint (FormSet, Value);\r
3066 break;\r
3067\r
3068 case EFI_IFR_TO_LOWER_OP:\r
3069 case EFI_IFR_TO_UPPER_OP:\r
3070 Status = InitializeUnicodeCollationProtocol ();\r
3071 if (EFI_ERROR (Status)) {\r
3072 goto Done;\r
3073 }\r
3074\r
3075 Status = PopExpression (Value);\r
3076 if (EFI_ERROR (Status)) {\r
3077 goto Done;\r
3078 }\r
3079\r
3080 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
3081 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3082 break;\r
3083 }\r
3084\r
3085 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
3086 if (StrPtr == NULL) {\r
3087 Status = EFI_NOT_FOUND;\r
3088 goto Done;\r
3089 }\r
3090\r
3091 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
3092 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
3093 } else {\r
3094 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
3095 }\r
3096 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
3097 FreePool (StrPtr);\r
3098 break;\r
3099\r
3100 case EFI_IFR_BITWISE_NOT_OP:\r
3101 //\r
3102 // Pop an expression from the expression stack\r
3103 //\r
3104 Status = PopExpression (Value);\r
3105 if (EFI_ERROR (Status)) {\r
3106 goto Done;\r
3107 }\r
3108 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
3109 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3110 break;\r
3111 }\r
3112\r
3113 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
3114 Value->Value.u64 = ~ HiiValueToUINT64(Value);\r
3115 break;\r
3116\r
3117 case EFI_IFR_SET_OP:\r
3118 //\r
3119 // Pop an expression from the expression stack\r
3120 //\r
3121 Status = PopExpression (Value);\r
3122 if (EFI_ERROR (Status)) {\r
3123 goto Done;\r
3124 }\r
3125 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
3126 Data1.Value.b = FALSE;\r
3127 //\r
3128 // Set value to var storage buffer\r
3129 //\r
3130 if (OpCode->VarStorage != NULL) {\r
3131 switch (OpCode->VarStorage->Type) {\r
3132 case EFI_HII_VARSTORE_BUFFER:\r
3133 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
3134 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
3135 Data1.Value.b = TRUE;\r
3136 break;\r
3137 case EFI_HII_VARSTORE_NAME_VALUE:\r
3138 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
3139 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
3140 ASSERT (NameValue != NULL);\r
3141 //\r
3142 // Convert Buffer to Hex String\r
3143 //\r
3144 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
3145 StrPtr = NameValue;\r
3146 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
3147 UnicodeValueToStringS (\r
3148 StrPtr,\r
3149 (OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),\r
3150 PREFIX_ZERO | RADIX_HEX,\r
3151 *TempBuffer,\r
3152 2\r
3153 );\r
3154 StrPtr += StrnLenS (StrPtr, OpCode->ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));\r
3155 }\r
3156 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
3157 FreePool (NameValue);\r
3158 if (!EFI_ERROR (Status)) {\r
3159 Data1.Value.b = TRUE;\r
3160 }\r
3161 }\r
3162 break;\r
3163 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
3164 Status = gRT->SetVariable (\r
3165 OpCode->ValueName,\r
3166 &OpCode->VarStorage->Guid,\r
3167 OpCode->VarStorage->Attributes,\r
3168 OpCode->ValueWidth,\r
3169 &Value->Value\r
3170 );\r
3171 if (!EFI_ERROR (Status)) {\r
3172 Data1.Value.b = TRUE;\r
3173 }\r
3174 break;\r
3175 default:\r
3176 //\r
3177 // Not recognize storage.\r
3178 //\r
3179 Status = EFI_UNSUPPORTED;\r
3180 goto Done;\r
3181 }\r
3182 } else {\r
3183 //\r
3184 // For Time/Date Data\r
3185 //\r
3186 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
3187 //\r
3188 // Only support Data/Time data when storage doesn't exist.\r
3189 //\r
3190 Status = EFI_UNSUPPORTED;\r
3191 goto Done;\r
3192 }\r
3193 Status = gRT->GetTime (&EfiTime, NULL);\r
3194 if (!EFI_ERROR (Status)) {\r
3195 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
3196 switch (OpCode->VarStoreInfo.VarOffset) {\r
3197 case 0x00:\r
3198 EfiTime.Year = Value->Value.u16;\r
3199 break;\r
3200 case 0x02:\r
3201 EfiTime.Month = Value->Value.u8;\r
3202 break;\r
3203 case 0x03:\r
3204 EfiTime.Day = Value->Value.u8;\r
3205 break;\r
3206 default:\r
3207 //\r
3208 // Invalid Date field.\r
3209 //\r
3210 Status = EFI_INVALID_PARAMETER;\r
3211 goto Done;\r
3212 }\r
3213 } else {\r
3214 switch (OpCode->VarStoreInfo.VarOffset) {\r
3215 case 0x00:\r
3216 EfiTime.Hour = Value->Value.u8;\r
3217 break;\r
3218 case 0x01:\r
3219 EfiTime.Minute = Value->Value.u8;\r
3220 break;\r
3221 case 0x02:\r
3222 EfiTime.Second = Value->Value.u8;\r
3223 break;\r
3224 default:\r
3225 //\r
3226 // Invalid Time field.\r
3227 //\r
3228 Status = EFI_INVALID_PARAMETER;\r
3229 goto Done;\r
3230 }\r
3231 }\r
3232 Status = gRT->SetTime (&EfiTime);\r
3233 if (!EFI_ERROR (Status)) {\r
3234 Data1.Value.b = TRUE;\r
3235 }\r
3236 }\r
3237 }\r
3238 Value = &Data1;\r
3239 break;\r
3240\r
3241 //\r
3242 // binary-op\r
3243 //\r
3244 case EFI_IFR_ADD_OP:\r
3245 case EFI_IFR_SUBTRACT_OP:\r
3246 case EFI_IFR_MULTIPLY_OP:\r
3247 case EFI_IFR_DIVIDE_OP:\r
3248 case EFI_IFR_MODULO_OP:\r
3249 case EFI_IFR_BITWISE_AND_OP:\r
3250 case EFI_IFR_BITWISE_OR_OP:\r
3251 case EFI_IFR_SHIFT_LEFT_OP:\r
3252 case EFI_IFR_SHIFT_RIGHT_OP:\r
3253 //\r
3254 // Pop an expression from the expression stack\r
3255 //\r
3256 Status = PopExpression (&Data2);\r
3257 if (EFI_ERROR (Status)) {\r
3258 goto Done;\r
3259 }\r
3260\r
3261 //\r
3262 // Pop another expression from the expression stack\r
3263 //\r
3264 Status = PopExpression (&Data1);\r
3265 if (EFI_ERROR (Status)) {\r
3266 goto Done;\r
3267 }\r
3268\r
3269 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
3270 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3271 break;\r
3272 }\r
3273\r
3274\r
3275 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
3276 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3277 break;\r
3278 }\r
3279\r
3280 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
3281\r
3282 switch (OpCode->Operand) {\r
3283 case EFI_IFR_ADD_OP:\r
3284 Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2);\r
3285 break;\r
3286\r
3287 case EFI_IFR_SUBTRACT_OP:\r
3288 Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2);\r
3289 break;\r
3290\r
3291 case EFI_IFR_MULTIPLY_OP:\r
3292 Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
3293 break;\r
3294\r
3295 case EFI_IFR_DIVIDE_OP:\r
3296 Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
3297 break;\r
3298\r
3299 case EFI_IFR_MODULO_OP:\r
3300 DivU64x32Remainder (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &TempValue);\r
3301 Value->Value.u64 = TempValue;\r
3302 break;\r
3303\r
3304 case EFI_IFR_BITWISE_AND_OP:\r
3305 Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2);\r
3306 break;\r
3307\r
3308 case EFI_IFR_BITWISE_OR_OP:\r
3309 Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2);\r
3310 break;\r
3311\r
3312 case EFI_IFR_SHIFT_LEFT_OP:\r
3313 Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
3314 break;\r
3315\r
3316 case EFI_IFR_SHIFT_RIGHT_OP:\r
3317 Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
3318 break;\r
3319\r
3320 default:\r
3321 break;\r
3322 }\r
3323 break;\r
3324\r
3325 case EFI_IFR_AND_OP:\r
3326 case EFI_IFR_OR_OP:\r
3327 //\r
3328 // Two Boolean operator\r
3329 //\r
3330 Status = PopExpression (&Data2);\r
3331 if (EFI_ERROR (Status)) {\r
3332 goto Done;\r
3333 }\r
3334\r
3335 //\r
3336 // Pop another expression from the expression stack\r
3337 //\r
3338 Status = PopExpression (&Data1);\r
3339 if (EFI_ERROR (Status)) {\r
3340 goto Done;\r
3341 }\r
3342\r
3343 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3344 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3345 break;\r
3346 }\r
3347\r
3348 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3349 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3350 break;\r
3351 }\r
3352\r
3353 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
3354 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
3355 } else {\r
3356 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
3357 }\r
3358 break;\r
3359\r
3360 case EFI_IFR_EQUAL_OP:\r
3361 case EFI_IFR_NOT_EQUAL_OP:\r
3362 case EFI_IFR_GREATER_EQUAL_OP:\r
3363 case EFI_IFR_GREATER_THAN_OP:\r
3364 case EFI_IFR_LESS_EQUAL_OP:\r
3365 case EFI_IFR_LESS_THAN_OP:\r
3366 //\r
3367 // Compare two integer, string, boolean or date/time\r
3368 //\r
3369 Status = PopExpression (&Data2);\r
3370 if (EFI_ERROR (Status)) {\r
3371 goto Done;\r
3372 }\r
3373\r
3374 //\r
3375 // Pop another expression from the expression stack\r
3376 //\r
3377 Status = PopExpression (&Data1);\r
3378 if (EFI_ERROR (Status)) {\r
3379 goto Done;\r
3380 }\r
3381\r
3382 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN &&\r
3383 Data2.Type != EFI_IFR_TYPE_STRING &&\r
3384 !IsTypeInBuffer(&Data2)) {\r
3385 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3386 break;\r
3387 }\r
3388\r
3389 if (Data1.Type > EFI_IFR_TYPE_BOOLEAN &&\r
3390 Data1.Type != EFI_IFR_TYPE_STRING &&\r
3391 !IsTypeInBuffer(&Data1)) {\r
3392 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3393 break;\r
3394 }\r
3395\r
3396 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
3397 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
3398 FreePool (Data1.Buffer);\r
3399 }\r
3400 if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
3401 FreePool (Data2.Buffer);\r
3402 }\r
3403\r
3404 if (Status == EFI_UNSUPPORTED) {\r
3405 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3406 Status = EFI_SUCCESS;\r
3407 break;\r
3408 }\r
3409\r
3410 if (EFI_ERROR (Status)) {\r
3411 goto Done;\r
3412 }\r
3413\r
3414 switch (OpCode->Operand) {\r
3415 case EFI_IFR_EQUAL_OP:\r
3416 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
3417 break;\r
3418\r
3419 case EFI_IFR_NOT_EQUAL_OP:\r
3420 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
3421 break;\r
3422\r
3423 case EFI_IFR_GREATER_EQUAL_OP:\r
3424 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
3425 break;\r
3426\r
3427 case EFI_IFR_GREATER_THAN_OP:\r
3428 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
3429 break;\r
3430\r
3431 case EFI_IFR_LESS_EQUAL_OP:\r
3432 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
3433 break;\r
3434\r
3435 case EFI_IFR_LESS_THAN_OP:\r
3436 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
3437 break;\r
3438\r
3439 default:\r
3440 break;\r
3441 }\r
3442 break;\r
3443\r
3444 case EFI_IFR_MATCH_OP:\r
3445 Status = InitializeUnicodeCollationProtocol ();\r
3446 if (EFI_ERROR (Status)) {\r
3447 goto Done;\r
3448 }\r
3449\r
3450 Status = IfrMatch (FormSet, Value);\r
3451 break;\r
3452\r
3453 case EFI_IFR_MATCH2_OP:\r
3454 Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);\r
3455 break;\r
3456\r
3457 case EFI_IFR_CATENATE_OP:\r
3458 Status = IfrCatenate (FormSet, Value);\r
3459 break;\r
3460\r
3461 //\r
3462 // ternary-op\r
3463 //\r
3464 case EFI_IFR_CONDITIONAL_OP:\r
3465 //\r
3466 // Pop third expression from the expression stack\r
3467 //\r
3468 Status = PopExpression (&Data3);\r
3469 if (EFI_ERROR (Status)) {\r
3470 goto Done;\r
3471 }\r
3472\r
3473 //\r
3474 // Pop second expression from the expression stack\r
3475 //\r
3476 Status = PopExpression (&Data2);\r
3477 if (EFI_ERROR (Status)) {\r
3478 goto Done;\r
3479 }\r
3480\r
3481 //\r
3482 // Pop first expression from the expression stack\r
3483 //\r
3484 Status = PopExpression (&Data1);\r
3485 if (EFI_ERROR (Status)) {\r
3486 goto Done;\r
3487 }\r
3488 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3489 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3490 break;\r
3491 }\r
3492\r
3493 if (Data1.Value.b) {\r
3494 Value = &Data3;\r
3495 } else {\r
3496 Value = &Data2;\r
3497 }\r
3498 break;\r
3499\r
3500 case EFI_IFR_FIND_OP:\r
3501 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3502 break;\r
3503\r
3504 case EFI_IFR_MID_OP:\r
3505 Status = IfrMid (FormSet, Value);\r
3506 break;\r
3507\r
3508 case EFI_IFR_TOKEN_OP:\r
3509 Status = IfrToken (FormSet, Value);\r
3510 break;\r
3511\r
3512 case EFI_IFR_SPAN_OP:\r
3513 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3514 break;\r
3515\r
3516 case EFI_IFR_MAP_OP:\r
3517 //\r
3518 // Pop the check value\r
3519 //\r
3520 Status = PopExpression (&Data1);\r
3521 if (EFI_ERROR (Status)) {\r
3522 goto Done;\r
3523 }\r
3524 //\r
3525 // Check MapExpression list is valid.\r
3526 //\r
3527 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
3528 Status = EFI_INVALID_PARAMETER;\r
3529 goto Done;\r
3530 }\r
3531 //\r
3532 // Go through map expression list.\r
3533 //\r
3534 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
3535 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3536 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3537 //\r
3538 // Evaluate the first expression in this pair.\r
3539 //\r
3540 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3541 if (EFI_ERROR (Status)) {\r
3542 goto Done;\r
3543 }\r
3544 //\r
3545 // Compare the expression value with current value\r
3546 //\r
3547 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
3548 //\r
3549 // Try get the map value.\r
3550 //\r
3551 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3552 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3553 Status = EFI_INVALID_PARAMETER;\r
3554 goto Done;\r
3555 }\r
3556 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3557 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3558 if (EFI_ERROR (Status)) {\r
3559 goto Done;\r
3560 }\r
3561 Value = &SubExpression->Result;\r
3562 break;\r
3563 }\r
3564 //\r
3565 // Skip the second expression on this pair.\r
3566 //\r
3567 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3568 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3569 Status = EFI_INVALID_PARAMETER;\r
3570 goto Done;\r
3571 }\r
3572 //\r
3573 // Goto the first expression on next pair.\r
3574 //\r
3575 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3576 }\r
3577\r
3578 //\r
3579 // No map value is found.\r
3580 //\r
3581 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3582 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3583 Value->Value.u8 = 0;\r
3584 }\r
3585 break;\r
3586\r
3587 default:\r
3588 break;\r
3589 }\r
3590 if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
3591 goto Done;\r
3592 }\r
3593\r
3594 Status = PushExpression (Value);\r
3595 if (EFI_ERROR (Status)) {\r
3596 goto Done;\r
3597 }\r
3598 }\r
3599\r
3600 //\r
3601 // Pop the final result from expression stack\r
3602 //\r
3603 Value = &Data1;\r
3604 Status = PopExpression (Value);\r
3605 if (EFI_ERROR (Status)) {\r
3606 goto Done;\r
3607 }\r
3608\r
3609 //\r
3610 // After evaluating an expression, there should be only one value left on the expression stack\r
3611 //\r
3612 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
3613 Status = EFI_INVALID_PARAMETER;\r
3614 }\r
3615\r
3616Done:\r
3617 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3618 if (!EFI_ERROR (Status)) {\r
3619 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3620 }\r
3621\r
3622 return Status;\r
3623}\r
3624\r
3625/**\r
3626 Check whether the result is TRUE or FALSE.\r
3627\r
3628 For the EFI_HII_VALUE value type is numeric, return TRUE if the\r
3629 value is not 0.\r
3630\r
3631 @param Result Input the result data.\r
3632\r
3633 @retval TRUE The result is TRUE.\r
3634 @retval FALSE The result is FALSE.\r
3635\r
3636**/\r
3637BOOLEAN\r
3638IsTrue (\r
3639 IN EFI_HII_VALUE *Result\r
3640 )\r
3641{\r
3642 switch (Result->Type) {\r
3643 case EFI_IFR_TYPE_BOOLEAN:\r
3644 return Result->Value.b;\r
3645\r
3646 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3647 return (BOOLEAN)(Result->Value.u8 != 0);\r
3648\r
3649 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3650 return (BOOLEAN)(Result->Value.u16 != 0);\r
3651\r
3652 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3653 return (BOOLEAN)(Result->Value.u32 != 0);\r
3654\r
3655 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3656 return (BOOLEAN)(Result->Value.u64 != 0);\r
3657\r
3658 default:\r
3659 return FALSE;\r
3660 }\r
3661}\r
3662\r
3663/**\r
3664 Return the result of the expression list. Check the expression list and\r
3665 return the highest priority express result.\r
3666 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
3667\r
3668 @param ExpList The input expression list.\r
3669 @param Evaluate Whether need to evaluate the expression first.\r
3670 @param FormSet FormSet associated with this expression.\r
3671 @param Form Form associated with this expression.\r
3672\r
3673 @retval EXPRESS_RESULT Return the higher priority express result.\r
3674 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3675\r
3676**/\r
3677EXPRESS_RESULT\r
3678EvaluateExpressionList (\r
3679 IN FORM_EXPRESSION_LIST *ExpList,\r
3680 IN BOOLEAN Evaluate,\r
3681 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
3682 IN FORM_BROWSER_FORM *Form OPTIONAL\r
3683 )\r
3684{\r
3685 UINTN Index;\r
3686 EXPRESS_RESULT ReturnVal;\r
3687 EXPRESS_RESULT CompareOne;\r
3688 EFI_STATUS Status;\r
3689\r
3690 if (ExpList == NULL) {\r
3691 return ExpressFalse;\r
3692 }\r
3693\r
3694 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3695 Index = 0;\r
3696\r
3697 //\r
3698 // Check whether need to evaluate the expression first.\r
3699 //\r
3700 if (Evaluate) {\r
3701 while (ExpList->Count > Index) {\r
3702 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
3703 if (EFI_ERROR (Status)) {\r
3704 return ExpressFalse;\r
3705 }\r
3706 }\r
3707 }\r
3708\r
3709 //\r
3710 // Run the list of expressions.\r
3711 //\r
3712 ReturnVal = ExpressFalse;\r
3713 for (Index = 0; Index < ExpList->Count; Index++) {\r
3714 if (IsTrue (&ExpList->Expression[Index]->Result)) {\r
3715 switch (ExpList->Expression[Index]->Type) {\r
3716 case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
3717 CompareOne = ExpressSuppress;\r
3718 break;\r
3719\r
3720 case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
3721 CompareOne = ExpressGrayOut;\r
3722 break;\r
3723\r
3724 case EFI_HII_EXPRESSION_DISABLE_IF:\r
3725 CompareOne = ExpressDisable;\r
3726 break;\r
3727\r
3728 default:\r
3729 return ExpressFalse;\r
3730 }\r
3731\r
3732 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3733 }\r
3734 }\r
3735\r
3736 return ReturnVal;\r
3737}\r