]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
MdePkg: Add Regular Expression Protocol and match2 opcode definition.
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
CommitLineData
7936fb6a 1/** @file\r
2Utility functions for expression evaluation.\r
3\r
40578d09 4Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7936fb6a 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
7936fb6a 15#include "Setup.h"\r
16\r
17//\r
18// Global stack used to evaluate boolean expresions\r
19//\r
20EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
21EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
22EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
23\r
24EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
25EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
26EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
2573712e
LG
27UINTN mExpressionEvaluationStackOffset = 0;\r
28\r
29EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
30EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
31EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
32\r
33EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
34EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
35EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
7936fb6a 36\r
31585af4
ED
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
7936fb6a 50//\r
51// Unicode collation protocol interface\r
52//\r
53EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
cbf73e50 54EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
7936fb6a 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
f4113e1f 103 FreePool (*Stack);\r
7936fb6a 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
901ba0e7
ED
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
7936fb6a 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
2573712e
LG
170 @param Stack On input: old stack\r
171 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
7936fb6a 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
2573712e 180 IN EFI_HII_VALUE *Stack,\r
7936fb6a 181 IN OUT EFI_HII_VALUE **StackPtr,\r
7936fb6a 182 OUT EFI_HII_VALUE *Data\r
183 )\r
184{\r
185 //\r
186 // Check for a stack underflow condition\r
187 //\r
2573712e 188 if (*StackPtr == Stack) {\r
7936fb6a 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
2573712e
LG
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
31585af4
ED
210 mCurrentExpressionPointer = mCurrentExpressionStack;\r
211 mFormExpressionPointer = mFormExpressionStack;\r
212 mStatementExpressionPointer = mStatementExpressionStack;\r
213 mOptionExpressionPointer = mOptionExpressionStack; \r
2573712e
LG
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
31585af4
ED
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
2573712e
LG
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
7936fb6a 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
2573712e 691 mOpCodeScopeStack,\r
7936fb6a 692 &mOpCodeScopeStackPointer,\r
7936fb6a 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
7936fb6a 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
2573712e 741 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
7936fb6a 742 &mExpressionEvaluationStackPointer,\r
7936fb6a 743 Value\r
744 );\r
745}\r
746\r
2573712e
LG
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 )\r
755{\r
756 UINTN TempStackOffset;\r
757 TempStackOffset = mExpressionEvaluationStackOffset;\r
758 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;\r
759 return TempStackOffset;\r
760}\r
761\r
762/**\r
763 Restore stack offset based on input stack offset\r
764\r
765 @param StackOffset Offset to stack start.\r
766\r
767**/\r
768VOID\r
769RestoreExpressionEvaluationStackOffset (\r
770 UINTN StackOffset\r
771 )\r
772{\r
773 mExpressionEvaluationStackOffset = StackOffset;\r
774}\r
7936fb6a 775\r
776/**\r
777 Get Form given its FormId.\r
778\r
779 @param FormSet The formset which contains this form.\r
780 @param FormId Id of this form.\r
781\r
782 @retval Pointer The form.\r
783 @retval NULL Specified Form is not found in the formset.\r
784\r
785**/\r
786FORM_BROWSER_FORM *\r
787IdToForm (\r
788 IN FORM_BROWSER_FORMSET *FormSet,\r
789 IN UINT16 FormId\r
7c6c064c 790 )\r
7936fb6a 791{\r
792 LIST_ENTRY *Link;\r
793 FORM_BROWSER_FORM *Form;\r
794\r
795 Link = GetFirstNode (&FormSet->FormListHead);\r
796 while (!IsNull (&FormSet->FormListHead, Link)) {\r
797 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
798\r
799 if (Form->FormId == FormId) {\r
800 return Form;\r
801 }\r
802\r
803 Link = GetNextNode (&FormSet->FormListHead, Link);\r
804 }\r
805\r
806 return NULL;\r
807}\r
808\r
809\r
810/**\r
811 Search a Question in Form scope using its QuestionId.\r
812\r
813 @param Form The form which contains this Question.\r
814 @param QuestionId Id of this Question.\r
815\r
816 @retval Pointer The Question.\r
817 @retval NULL Specified Question not found in the form.\r
818\r
819**/\r
820FORM_BROWSER_STATEMENT *\r
821IdToQuestion2 (\r
822 IN FORM_BROWSER_FORM *Form,\r
823 IN UINT16 QuestionId\r
824 )\r
825{\r
826 LIST_ENTRY *Link;\r
827 FORM_BROWSER_STATEMENT *Question;\r
828\r
db40504e 829 if (QuestionId == 0 || Form == NULL) {\r
7936fb6a 830 //\r
831 // The value of zero is reserved\r
832 //\r
833 return NULL;\r
834 }\r
835\r
836 Link = GetFirstNode (&Form->StatementListHead);\r
837 while (!IsNull (&Form->StatementListHead, Link)) {\r
838 Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);\r
839\r
840 if (Question->QuestionId == QuestionId) {\r
841 return Question;\r
842 }\r
843\r
844 Link = GetNextNode (&Form->StatementListHead, Link);\r
845 }\r
846\r
847 return NULL;\r
848}\r
849\r
850\r
851/**\r
852 Search a Question in Formset scope using its QuestionId.\r
853\r
854 @param FormSet The formset which contains this form.\r
855 @param Form The form which contains this Question.\r
856 @param QuestionId Id of this Question.\r
857\r
858 @retval Pointer The Question.\r
859 @retval NULL Specified Question not found in the form.\r
860\r
861**/\r
862FORM_BROWSER_STATEMENT *\r
863IdToQuestion (\r
864 IN FORM_BROWSER_FORMSET *FormSet,\r
865 IN FORM_BROWSER_FORM *Form,\r
866 IN UINT16 QuestionId\r
867 )\r
868{\r
869 LIST_ENTRY *Link;\r
870 FORM_BROWSER_STATEMENT *Question;\r
871\r
872 //\r
873 // Search in the form scope first\r
874 //\r
875 Question = IdToQuestion2 (Form, QuestionId);\r
876 if (Question != NULL) {\r
877 return Question;\r
878 }\r
879\r
880 //\r
881 // Search in the formset scope\r
882 //\r
883 Link = GetFirstNode (&FormSet->FormListHead);\r
884 while (!IsNull (&FormSet->FormListHead, Link)) {\r
885 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
886\r
887 Question = IdToQuestion2 (Form, QuestionId);\r
888 if (Question != NULL) {\r
8d00a0f1 889 //\r
890 // EFI variable storage may be updated by Callback() asynchronous,\r
891 // to keep synchronous, always reload the Question Value.\r
892 //\r
893 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {\r
816a7110 894 GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
8d00a0f1 895 }\r
896\r
7936fb6a 897 return Question;\r
898 }\r
899\r
900 Link = GetNextNode (&FormSet->FormListHead, Link);\r
901 }\r
902\r
903 return NULL;\r
904}\r
905\r
906\r
907/**\r
908 Get Expression given its RuleId.\r
909\r
910 @param Form The form which contains this Expression.\r
911 @param RuleId Id of this Expression.\r
912\r
913 @retval Pointer The Expression.\r
914 @retval NULL Specified Expression not found in the form.\r
915\r
916**/\r
917FORM_EXPRESSION *\r
918RuleIdToExpression (\r
919 IN FORM_BROWSER_FORM *Form,\r
920 IN UINT8 RuleId\r
921 )\r
922{\r
923 LIST_ENTRY *Link;\r
924 FORM_EXPRESSION *Expression;\r
925\r
926 Link = GetFirstNode (&Form->ExpressionListHead);\r
927 while (!IsNull (&Form->ExpressionListHead, Link)) {\r
928 Expression = FORM_EXPRESSION_FROM_LINK (Link);\r
929\r
930 if (Expression->Type == EFI_HII_EXPRESSION_RULE && Expression->RuleId == RuleId) {\r
931 return Expression;\r
932 }\r
933\r
934 Link = GetNextNode (&Form->ExpressionListHead, Link);\r
935 }\r
936\r
937 return NULL;\r
938}\r
939\r
940\r
941/**\r
942 Locate the Unicode Collation Protocol interface for later use.\r
943\r
944 @retval EFI_SUCCESS Protocol interface initialize success.\r
945 @retval Other Protocol interface initialize failed.\r
946\r
947**/\r
948EFI_STATUS\r
949InitializeUnicodeCollationProtocol (\r
950 VOID\r
951 )\r
952{\r
953 EFI_STATUS Status;\r
954\r
955 if (mUnicodeCollation != NULL) {\r
956 return EFI_SUCCESS;\r
957 }\r
958\r
959 //\r
960 // BUGBUG: Proper impelmentation is to locate all Unicode Collation Protocol\r
961 // instances first and then select one which support English language.\r
962 // Current implementation just pick the first instance.\r
963 //\r
964 Status = gBS->LocateProtocol (\r
965 &gEfiUnicodeCollation2ProtocolGuid,\r
966 NULL,\r
967 (VOID **) &mUnicodeCollation\r
968 );\r
969 return Status;\r
970}\r
971\r
972/**\r
973 Convert the input Unicode character to upper.\r
974\r
975 @param String Th Unicode character to be converted.\r
976\r
977**/\r
978VOID\r
979IfrStrToUpper (\r
8b0fc5c1 980 IN CHAR16 *String\r
7936fb6a 981 )\r
982{\r
983 while (*String != 0) {\r
984 if ((*String >= 'a') && (*String <= 'z')) {\r
985 *String = (UINT16) ((*String) & ((UINT16) ~0x20));\r
986 }\r
987 String++;\r
988 }\r
989}\r
990\r
40578d09
ED
991/**\r
992 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
993\r
994 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
995 EFI_IFR_TYPE_BUFFER when do the value compare.\r
996\r
997 @param Value Expression value to compare on.\r
998\r
999 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
1000 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
1001\r
1002**/\r
1003BOOLEAN\r
1004IsTypeInBuffer (\r
1005 IN EFI_HII_VALUE *Value\r
1006 )\r
1007{\r
1008 switch (Value->Type) {\r
1009 case EFI_IFR_TYPE_BUFFER:\r
1010 case EFI_IFR_TYPE_DATE:\r
1011 case EFI_IFR_TYPE_TIME:\r
1012 case EFI_IFR_TYPE_REF:\r
1013 return TRUE;\r
1014\r
1015 default:\r
1016 return FALSE;\r
1017 }\r
1018}\r
1019\r
1020/**\r
1021 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64\r
1022\r
1023 @param Value Expression value to compare on.\r
1024\r
1025 @retval TRUE This value type can be transter to EFI_IFR_TYPE_BUFFER type.\r
1026 @retval FALSE This value type can't be transter to EFI_IFR_TYPE_BUFFER type.\r
1027\r
1028**/\r
1029BOOLEAN\r
1030IsTypeInUINT64 (\r
1031 IN EFI_HII_VALUE *Value\r
1032 )\r
1033{\r
1034 switch (Value->Type) {\r
1035 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1036 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1037 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1038 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1039 case EFI_IFR_TYPE_BOOLEAN:\r
1040 return TRUE;\r
1041\r
1042 default:\r
1043 return FALSE;\r
1044 }\r
1045}\r
1046\r
1047/**\r
1048 Return the buffer length for this value.\r
1049\r
1050 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
1051 EFI_IFR_TYPE_BUFFER when do the value compare.\r
1052\r
1053 @param Value Expression value to compare on.\r
1054 \r
1055 @retval BufLen Return the buffer length.\r
1056\r
1057**/\r
1058UINT16\r
1059GetLengthForValue (\r
1060 IN EFI_HII_VALUE *Value\r
1061 )\r
1062{\r
1063 switch (Value->Type) {\r
1064 case EFI_IFR_TYPE_BUFFER:\r
1065 return Value->BufferLen;\r
1066\r
1067 case EFI_IFR_TYPE_DATE:\r
1068 return (UINT16) sizeof (EFI_HII_DATE);\r
1069\r
1070 case EFI_IFR_TYPE_TIME:\r
1071 return (UINT16) sizeof (EFI_HII_TIME);\r
1072\r
1073 case EFI_IFR_TYPE_REF:\r
1074 return (UINT16) sizeof (EFI_HII_REF);\r
1075\r
1076 default:\r
1077 return 0;\r
1078 }\r
1079}\r
1080\r
1081/**\r
1082 Return the buffer pointer for this value.\r
1083\r
1084 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to \r
1085 EFI_IFR_TYPE_BUFFER when do the value compare.\r
1086\r
1087 @param Value Expression value to compare on.\r
1088\r
1089 @retval Buf Return the buffer pointer.\r
1090\r
1091**/\r
1092UINT8 *\r
1093GetBufferForValue (\r
1094 IN EFI_HII_VALUE *Value\r
1095 )\r
1096{\r
1097 switch (Value->Type) {\r
1098 case EFI_IFR_TYPE_BUFFER:\r
1099 return Value->Buffer;\r
1100\r
1101 case EFI_IFR_TYPE_DATE:\r
1102 return (UINT8 *) (&Value->Value.date);\r
1103\r
1104 case EFI_IFR_TYPE_TIME:\r
1105 return (UINT8 *) (&Value->Value.time);\r
1106\r
1107 case EFI_IFR_TYPE_REF:\r
1108 return (UINT8 *) (&Value->Value.ref);\r
1109\r
1110 default:\r
1111 return NULL;\r
1112 }\r
1113}\r
7936fb6a 1114\r
1115/**\r
1116 Evaluate opcode EFI_IFR_TO_STRING.\r
1117\r
1118 @param FormSet Formset which contains this opcode.\r
1119 @param Format String format in EFI_IFR_TO_STRING.\r
1120 @param Result Evaluation result for this opcode.\r
1121\r
1122 @retval EFI_SUCCESS Opcode evaluation success.\r
1123 @retval Other Opcode evaluation failed.\r
1124\r
1125**/\r
1126EFI_STATUS\r
1127IfrToString (\r
1128 IN FORM_BROWSER_FORMSET *FormSet,\r
1129 IN UINT8 Format,\r
1130 OUT EFI_HII_VALUE *Result\r
1131 )\r
1132{\r
1133 EFI_STATUS Status;\r
1134 EFI_HII_VALUE Value;\r
1135 CHAR16 *String;\r
1136 CHAR16 *PrintFormat;\r
1137 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];\r
901ba0e7 1138 UINT8 *TmpBuf;\r
40578d09
ED
1139 UINT8 *SrcBuf;\r
1140 UINTN SrcLen;\r
7936fb6a 1141 UINTN BufferSize;\r
1142\r
1143 Status = PopExpression (&Value);\r
1144 if (EFI_ERROR (Status)) {\r
1145 return Status;\r
1146 }\r
1147\r
1148 switch (Value.Type) {\r
1149 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1150 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1151 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1152 case EFI_IFR_TYPE_NUM_SIZE_64:\r
1153 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);\r
1154 switch (Format) {\r
1155 case EFI_IFR_STRING_UNSIGNED_DEC:\r
1156 case EFI_IFR_STRING_SIGNED_DEC:\r
1157 PrintFormat = L"%ld";\r
1158 break;\r
1159\r
1160 case EFI_IFR_STRING_LOWERCASE_HEX:\r
1161 PrintFormat = L"%lx";\r
1162 break;\r
1163\r
1164 case EFI_IFR_STRING_UPPERCASE_HEX:\r
1165 PrintFormat = L"%lX";\r
1166 break;\r
1167\r
1168 default:\r
8f420676
ED
1169 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1170 return EFI_SUCCESS;\r
7936fb6a 1171 }\r
1172 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
1173 String = Buffer;\r
1174 break;\r
1175\r
1176 case EFI_IFR_TYPE_STRING:\r
1177 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1178 return EFI_SUCCESS;\r
1179\r
1180 case EFI_IFR_TYPE_BOOLEAN:\r
1181 String = (Value.Value.b) ? L"True" : L"False";\r
1182 break;\r
901ba0e7
ED
1183 \r
1184 case EFI_IFR_TYPE_BUFFER:\r
40578d09
ED
1185 case EFI_IFR_TYPE_DATE:\r
1186 case EFI_IFR_TYPE_TIME:\r
1187 case EFI_IFR_TYPE_REF:\r
901ba0e7
ED
1188 //\r
1189 // + 3 is base on the unicode format, the length may be odd number, \r
1190 // so need 1 byte to align, also need 2 bytes for L'\0'.\r
1191 //\r
40578d09
ED
1192 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1193 SrcLen = Value.BufferLen;\r
1194 SrcBuf = Value.Buffer;\r
1195 } else {\r
1196 SrcBuf = GetBufferForValue(&Value);\r
1197 SrcLen = GetLengthForValue(&Value);\r
1198 }\r
1199\r
1200 TmpBuf = AllocateZeroPool (SrcLen + 3);\r
db40504e 1201 ASSERT (TmpBuf != NULL);\r
901ba0e7 1202 if (Format == EFI_IFR_STRING_ASCII) {\r
40578d09 1203 CopyMem (TmpBuf, SrcBuf, SrcLen);\r
901ba0e7
ED
1204 PrintFormat = L"%a"; \r
1205 } else {\r
1206 // Format == EFI_IFR_STRING_UNICODE\r
40578d09 1207 CopyMem (TmpBuf, SrcBuf, SrcLen * sizeof (CHAR16));\r
901ba0e7
ED
1208 PrintFormat = L"%s"; \r
1209 }\r
40578d09 1210 UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, TmpBuf);\r
901ba0e7
ED
1211 String = Buffer; \r
1212 FreePool (TmpBuf);\r
40578d09
ED
1213 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1214 FreePool (Value.Buffer);\r
1215 }\r
901ba0e7
ED
1216 break;\r
1217 \r
7936fb6a 1218 default:\r
8f420676
ED
1219 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1220 return EFI_SUCCESS;\r
7936fb6a 1221 }\r
1222\r
1223 Result->Type = EFI_IFR_TYPE_STRING;\r
1224 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
1225 return EFI_SUCCESS;\r
1226}\r
1227\r
1228\r
1229/**\r
1230 Evaluate opcode EFI_IFR_TO_UINT.\r
1231\r
1232 @param FormSet Formset which contains this opcode.\r
1233 @param Result Evaluation result for this opcode.\r
1234\r
1235 @retval EFI_SUCCESS Opcode evaluation success.\r
1236 @retval Other Opcode evaluation failed.\r
1237\r
1238**/\r
1239EFI_STATUS\r
1240IfrToUint (\r
1241 IN FORM_BROWSER_FORMSET *FormSet,\r
1242 OUT EFI_HII_VALUE *Result\r
1243 )\r
1244{\r
1245 EFI_STATUS Status;\r
1246 EFI_HII_VALUE Value;\r
1247 CHAR16 *String;\r
1248 CHAR16 *StringPtr;\r
7936fb6a 1249\r
1250 Status = PopExpression (&Value);\r
1251 if (EFI_ERROR (Status)) {\r
1252 return Status;\r
1253 }\r
1254\r
40578d09 1255 if (Value.Type >= EFI_IFR_TYPE_OTHER && !IsTypeInBuffer(&Value)) {\r
8f420676
ED
1256 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1257 return EFI_SUCCESS;\r
7936fb6a 1258 }\r
1259\r
1260 Status = EFI_SUCCESS;\r
1261 if (Value.Type == EFI_IFR_TYPE_STRING) {\r
1262 String = GetToken (Value.Value.string, FormSet->HiiHandle);\r
1263 if (String == NULL) {\r
1264 return EFI_NOT_FOUND;\r
1265 }\r
8b0fc5c1 1266\r
7936fb6a 1267 IfrStrToUpper (String);\r
1268 StringPtr = StrStr (String, L"0X");\r
1269 if (StringPtr != NULL) {\r
1270 //\r
1271 // Hex string\r
1272 //\r
ac7e320c 1273 Result->Value.u64 = StrHexToUint64 (String);\r
7936fb6a 1274 } else {\r
1275 //\r
ac7e320c 1276 // decimal string\r
7936fb6a 1277 //\r
ac7e320c 1278 Result->Value.u64 = StrDecimalToUint64 (String);\r
7936fb6a 1279 }\r
f4113e1f 1280 FreePool (String);\r
40578d09
ED
1281 } else if (IsTypeInBuffer(&Value)) {\r
1282 if (GetLengthForValue (&Value) > 8) {\r
1283 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1284 FreePool (Value.Buffer);\r
1285 }\r
8f420676
ED
1286 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1287 return EFI_SUCCESS;\r
901ba0e7 1288 }\r
40578d09
ED
1289 Result->Value.u64 = *(UINT64*) GetBufferForValue (&Value);\r
1290 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1291 FreePool (Value.Buffer);\r
1292 }\r
7936fb6a 1293 } else {\r
1294 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1295 }\r
1296\r
1297 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1298 return Status;\r
1299}\r
1300\r
1301\r
1302/**\r
1303 Evaluate opcode EFI_IFR_CATENATE.\r
1304\r
1305 @param FormSet Formset which contains this opcode.\r
1306 @param Result Evaluation result for this opcode.\r
1307\r
1308 @retval EFI_SUCCESS Opcode evaluation success.\r
1309 @retval Other Opcode evaluation failed.\r
1310\r
1311**/\r
1312EFI_STATUS\r
1313IfrCatenate (\r
1314 IN FORM_BROWSER_FORMSET *FormSet,\r
1315 OUT EFI_HII_VALUE *Result\r
1316 )\r
1317{\r
1318 EFI_STATUS Status;\r
901ba0e7 1319 EFI_HII_VALUE Value[2];\r
7936fb6a 1320 CHAR16 *String[2];\r
1321 UINTN Index;\r
1322 CHAR16 *StringPtr;\r
1323 UINTN Size;\r
40578d09
ED
1324 UINT16 Length0;\r
1325 UINT16 Length1;\r
784952b1 1326 UINT8 *TmpBuf;\r
7936fb6a 1327\r
1328 //\r
1329 // String[0] - The second string\r
1330 // String[1] - The first string\r
1331 //\r
1332 String[0] = NULL;\r
1333 String[1] = NULL;\r
1334 StringPtr = NULL;\r
1335 Status = EFI_SUCCESS;\r
901ba0e7 1336 ZeroMem (Value, sizeof (Value));\r
7936fb6a 1337\r
8f420676
ED
1338 Status = PopExpression (&Value[0]);\r
1339 if (EFI_ERROR (Status)) {\r
1340 goto Done;\r
1341 }\r
1342\r
1343 Status = PopExpression (&Value[1]);\r
1344 if (EFI_ERROR (Status)) {\r
1345 goto Done;\r
1346 }\r
7936fb6a 1347\r
8f420676 1348 for (Index = 0; Index < 2; Index++) {\r
40578d09 1349 if (Value[Index].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[Index])) {\r
8f420676
ED
1350 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1351 Status = EFI_SUCCESS;\r
7936fb6a 1352 goto Done;\r
1353 }\r
1354\r
901ba0e7
ED
1355 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
1356 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1357 if (String[Index] == NULL) {\r
1358 Status = EFI_NOT_FOUND;\r
1359 goto Done;\r
1360 }\r
7936fb6a 1361 }\r
1362 }\r
1363\r
901ba0e7
ED
1364 if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
1365 Size = StrSize (String[0]);\r
1366 StringPtr= AllocatePool (StrSize (String[1]) + Size);\r
1367 ASSERT (StringPtr != NULL);\r
1368 StrCpy (StringPtr, String[1]);\r
1369 StrCat (StringPtr, String[0]);\r
7936fb6a 1370\r
901ba0e7
ED
1371 Result->Type = EFI_IFR_TYPE_STRING;\r
1372 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
1373 } else {\r
1374 Result->Type = EFI_IFR_TYPE_BUFFER;\r
40578d09
ED
1375 Length0 = GetLengthForValue(&Value[0]);\r
1376 Length1 = GetLengthForValue(&Value[1]);\r
1377 Result->BufferLen = (UINT16) (Length0 + Length1);\r
901ba0e7
ED
1378\r
1379 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1380 ASSERT (Result->Buffer != NULL);\r
7936fb6a 1381\r
784952b1
ED
1382 TmpBuf = GetBufferForValue(&Value[0]);\r
1383 ASSERT (TmpBuf != NULL);\r
1384 CopyMem (Result->Buffer, TmpBuf, Length0);\r
1385 TmpBuf = GetBufferForValue(&Value[1]);\r
1386 ASSERT (TmpBuf != NULL);\r
1387 CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);\r
901ba0e7 1388 }\r
7936fb6a 1389Done:\r
901ba0e7
ED
1390 if (Value[0].Buffer != NULL) {\r
1391 FreePool (Value[0].Buffer);\r
1392 }\r
1393 if (Value[1].Buffer != NULL) {\r
1394 FreePool (Value[1].Buffer);\r
1395 }\r
676df92c 1396 if (String[0] != NULL) {\r
1397 FreePool (String[0]);\r
1398 }\r
1399 if (String[1] != NULL) {\r
1400 FreePool (String[1]);\r
8b0fc5c1 1401 }\r
676df92c 1402 if (StringPtr != NULL) {\r
1403 FreePool (StringPtr);\r
1404 }\r
7936fb6a 1405\r
1406 return Status;\r
1407}\r
1408\r
1409\r
1410/**\r
1411 Evaluate opcode EFI_IFR_MATCH.\r
1412\r
1413 @param FormSet Formset which contains this opcode.\r
1414 @param Result Evaluation result for this opcode.\r
1415\r
1416 @retval EFI_SUCCESS Opcode evaluation success.\r
1417 @retval Other Opcode evaluation failed.\r
1418\r
1419**/\r
1420EFI_STATUS\r
1421IfrMatch (\r
1422 IN FORM_BROWSER_FORMSET *FormSet,\r
1423 OUT EFI_HII_VALUE *Result\r
1424 )\r
1425{\r
1426 EFI_STATUS Status;\r
8f420676 1427 EFI_HII_VALUE Value[2];\r
7936fb6a 1428 CHAR16 *String[2];\r
1429 UINTN Index;\r
1430\r
1431 //\r
1432 // String[0] - The string to search\r
1433 // String[1] - pattern\r
1434 //\r
1435 String[0] = NULL;\r
1436 String[1] = NULL;\r
1437 Status = EFI_SUCCESS;\r
8f420676
ED
1438 ZeroMem (Value, sizeof (Value));\r
1439\r
1440 Status = PopExpression (&Value[0]);\r
1441 if (EFI_ERROR (Status)) {\r
1442 goto Done;\r
1443 }\r
1444\r
1445 Status = PopExpression (&Value[1]);\r
1446 if (EFI_ERROR (Status)) {\r
1447 goto Done;\r
1448 }\r
7936fb6a 1449\r
8f420676
ED
1450 for (Index = 0; Index < 2; Index++) {\r
1451 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
1452 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1453 Status = EFI_SUCCESS;\r
7936fb6a 1454 goto Done;\r
1455 }\r
1456\r
8f420676 1457 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
bc166db3 1458 if (String [Index] == NULL) {\r
7936fb6a 1459 Status = EFI_NOT_FOUND;\r
1460 goto Done;\r
1461 }\r
1462 }\r
1463\r
1464 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1465 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
1466\r
1467Done:\r
676df92c 1468 if (String[0] != NULL) {\r
1469 FreePool (String[0]);\r
1470 }\r
1471 if (String[1] != NULL) {\r
1472 FreePool (String[1]);\r
8b0fc5c1 1473 }\r
7936fb6a 1474\r
1475 return Status;\r
1476}\r
1477\r
1478\r
1479/**\r
1480 Evaluate opcode EFI_IFR_FIND.\r
1481\r
1482 @param FormSet Formset which contains this opcode.\r
1483 @param Format Case sensitive or insensitive.\r
1484 @param Result Evaluation result for this opcode.\r
1485\r
1486 @retval EFI_SUCCESS Opcode evaluation success.\r
1487 @retval Other Opcode evaluation failed.\r
1488\r
1489**/\r
1490EFI_STATUS\r
1491IfrFind (\r
1492 IN FORM_BROWSER_FORMSET *FormSet,\r
1493 IN UINT8 Format,\r
1494 OUT EFI_HII_VALUE *Result\r
1495 )\r
1496{\r
1497 EFI_STATUS Status;\r
8f420676 1498 EFI_HII_VALUE Value[3];\r
7936fb6a 1499 CHAR16 *String[2];\r
1500 UINTN Base;\r
1501 CHAR16 *StringPtr;\r
1502 UINTN Index;\r
1503\r
8f420676
ED
1504 ZeroMem (Value, sizeof (Value));\r
1505\r
7936fb6a 1506 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
8f420676 1507 return EFI_INVALID_PARAMETER;\r
7936fb6a 1508 }\r
1509\r
8f420676
ED
1510 Status = PopExpression (&Value[0]);\r
1511 if (EFI_ERROR (Status)) {\r
1512 return Status;\r
1513 }\r
1514\r
1515 Status = PopExpression (&Value[1]);\r
7936fb6a 1516 if (EFI_ERROR (Status)) {\r
1517 return Status;\r
1518 }\r
8f420676
ED
1519\r
1520 Status = PopExpression (&Value[2]);\r
1521 if (EFI_ERROR (Status)) {\r
1522 return Status;\r
1523 } \r
1524\r
1525 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1526 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1527 return EFI_SUCCESS;\r
7936fb6a 1528 }\r
8f420676 1529 Base = (UINTN) Value[0].Value.u64;\r
7936fb6a 1530\r
1531 //\r
1532 // String[0] - sub-string\r
1533 // String[1] - The string to search\r
1534 //\r
1535 String[0] = NULL;\r
1536 String[1] = NULL;\r
1537 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1538 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1539 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1540 Status = EFI_SUCCESS;\r
7936fb6a 1541 goto Done;\r
1542 }\r
1543\r
8f420676 1544 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
d0720b57 1545 if (String[Index] == NULL) {\r
7936fb6a 1546 Status = EFI_NOT_FOUND;\r
1547 goto Done;\r
1548 }\r
1549\r
1550 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
1551 //\r
1552 // Case insensitive, convert both string to upper case\r
1553 //\r
1554 IfrStrToUpper (String[Index]);\r
1555 }\r
1556 }\r
1557\r
1558 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1559 if (Base >= StrLen (String[1])) {\r
1560 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
1561 } else {\r
1562 StringPtr = StrStr (String[1] + Base, String[0]);\r
1563 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
1564 }\r
1565\r
1566Done:\r
676df92c 1567 if (String[0] != NULL) {\r
1568 FreePool (String[0]);\r
1569 }\r
1570 if (String[1] != NULL) {\r
1571 FreePool (String[1]);\r
8b0fc5c1 1572 }\r
7936fb6a 1573\r
1574 return Status;\r
1575}\r
1576\r
1577\r
1578/**\r
1579 Evaluate opcode EFI_IFR_MID.\r
1580\r
1581 @param FormSet Formset which contains this opcode.\r
1582 @param Result Evaluation result for this opcode.\r
1583\r
1584 @retval EFI_SUCCESS Opcode evaluation success.\r
1585 @retval Other Opcode evaluation failed.\r
1586\r
1587**/\r
1588EFI_STATUS\r
1589IfrMid (\r
1590 IN FORM_BROWSER_FORMSET *FormSet,\r
1591 OUT EFI_HII_VALUE *Result\r
1592 )\r
1593{\r
1594 EFI_STATUS Status;\r
8f420676 1595 EFI_HII_VALUE Value[3];\r
7936fb6a 1596 CHAR16 *String;\r
1597 UINTN Base;\r
1598 UINTN Length;\r
1599 CHAR16 *SubString;\r
901ba0e7 1600 UINT16 BufferLen;\r
40578d09 1601 UINT8 *Buffer;\r
7936fb6a 1602\r
8f420676
ED
1603 ZeroMem (Value, sizeof (Value));\r
1604\r
1605 Status = PopExpression (&Value[0]);\r
7936fb6a 1606 if (EFI_ERROR (Status)) {\r
1607 return Status;\r
1608 }\r
7936fb6a 1609\r
8f420676 1610 Status = PopExpression (&Value[1]);\r
7936fb6a 1611 if (EFI_ERROR (Status)) {\r
1612 return Status;\r
1613 }\r
7936fb6a 1614\r
8f420676 1615 Status = PopExpression (&Value[2]);\r
7936fb6a 1616 if (EFI_ERROR (Status)) {\r
1617 return Status;\r
8f420676
ED
1618 } \r
1619\r
1620 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1621 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1622 return EFI_SUCCESS;\r
7936fb6a 1623 }\r
8f420676
ED
1624 Length = (UINTN) Value[0].Value.u64;\r
1625\r
1626 if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1627 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1628 return EFI_SUCCESS;\r
7936fb6a 1629 }\r
8f420676
ED
1630 Base = (UINTN) Value[1].Value.u64;\r
1631\r
40578d09 1632 if (Value[2].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[2])) {\r
8f420676
ED
1633 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1634 return EFI_SUCCESS;\r
1635 }\r
1636 if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
1637 String = GetToken (Value[2].Value.string, FormSet->HiiHandle);\r
901ba0e7
ED
1638 if (String == NULL) {\r
1639 return EFI_NOT_FOUND;\r
1640 }\r
7936fb6a 1641\r
901ba0e7
ED
1642 if (Length == 0 || Base >= StrLen (String)) {\r
1643 SubString = gEmptyString;\r
1644 } else {\r
1645 SubString = String + Base;\r
1646 if ((Base + Length) < StrLen (String)) {\r
1647 SubString[Length] = L'\0';\r
1648 }\r
7936fb6a 1649 }\r
7936fb6a 1650\r
901ba0e7
ED
1651 Result->Type = EFI_IFR_TYPE_STRING;\r
1652 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
7936fb6a 1653\r
901ba0e7
ED
1654 FreePool (String);\r
1655 } else {\r
40578d09
ED
1656 BufferLen = GetLengthForValue (&Value[2]);\r
1657 Buffer = GetBufferForValue (&Value[2]);\r
1658\r
901ba0e7
ED
1659 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1660 if (Length == 0 || Base >= BufferLen) {\r
1661 Result->BufferLen = 0;\r
1662 Result->Buffer = NULL;\r
1663 } else {\r
1664 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length); \r
1665 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1666 ASSERT (Result->Buffer != NULL);\r
40578d09 1667 CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
901ba0e7 1668 }\r
7936fb6a 1669\r
40578d09
ED
1670 if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
1671 FreePool (Value[2].Buffer);\r
1672 }\r
901ba0e7
ED
1673 }\r
1674 \r
7936fb6a 1675 return Status;\r
1676}\r
1677\r
1678\r
1679/**\r
1680 Evaluate opcode EFI_IFR_TOKEN.\r
1681\r
1682 @param FormSet Formset which contains this opcode.\r
1683 @param Result Evaluation result for this opcode.\r
1684\r
1685 @retval EFI_SUCCESS Opcode evaluation success.\r
1686 @retval Other Opcode evaluation failed.\r
1687\r
1688**/\r
1689EFI_STATUS\r
1690IfrToken (\r
1691 IN FORM_BROWSER_FORMSET *FormSet,\r
1692 OUT EFI_HII_VALUE *Result\r
1693 )\r
1694{\r
1695 EFI_STATUS Status;\r
8f420676 1696 EFI_HII_VALUE Value[3];\r
7936fb6a 1697 CHAR16 *String[2];\r
1698 UINTN Count;\r
1699 CHAR16 *Delimiter;\r
1700 CHAR16 *SubString;\r
1701 CHAR16 *StringPtr;\r
1702 UINTN Index;\r
1703\r
8f420676
ED
1704 ZeroMem (Value, sizeof (Value));\r
1705\r
1706 Status = PopExpression (&Value[0]);\r
1707 if (EFI_ERROR (Status)) {\r
1708 return Status;\r
1709 }\r
1710\r
1711 Status = PopExpression (&Value[1]);\r
7936fb6a 1712 if (EFI_ERROR (Status)) {\r
1713 return Status;\r
1714 }\r
8f420676
ED
1715\r
1716 Status = PopExpression (&Value[2]);\r
1717 if (EFI_ERROR (Status)) {\r
1718 return Status;\r
1719 } \r
1720\r
1721 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) { \r
1722 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1723 return EFI_SUCCESS;\r
7936fb6a 1724 }\r
8f420676 1725 Count = (UINTN) Value[0].Value.u64;\r
7936fb6a 1726\r
1727 //\r
1728 // String[0] - Delimiter\r
1729 // String[1] - The string to search\r
1730 //\r
1731 String[0] = NULL;\r
1732 String[1] = NULL;\r
1733 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1734 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1735 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1736 Status = EFI_SUCCESS; \r
7936fb6a 1737 goto Done;\r
1738 }\r
1739\r
8f420676 1740 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
d0720b57 1741 if (String[Index] == NULL) {\r
7936fb6a 1742 Status = EFI_NOT_FOUND;\r
1743 goto Done;\r
1744 }\r
1745 }\r
1746\r
1747 Delimiter = String[0];\r
1748 SubString = String[1];\r
1749 while (Count > 0) {\r
1750 SubString = StrStr (SubString, Delimiter);\r
1751 if (SubString != NULL) {\r
1752 //\r
1753 // Skip over the delimiter\r
1754 //\r
1755 SubString = SubString + StrLen (Delimiter);\r
1756 } else {\r
1757 break;\r
1758 }\r
1759 Count--;\r
1760 }\r
1761\r
1762 if (SubString == NULL) {\r
1763 //\r
1764 // nth delimited sub-string not found, push an empty string\r
1765 //\r
1766 SubString = gEmptyString;\r
1767 } else {\r
1768 //\r
1769 // Put a NULL terminator for nth delimited sub-string\r
1770 //\r
1771 StringPtr = StrStr (SubString, Delimiter);\r
1772 if (StringPtr != NULL) {\r
1773 *StringPtr = L'\0';\r
1774 }\r
1775 }\r
1776\r
1777 Result->Type = EFI_IFR_TYPE_STRING;\r
1778 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1779\r
1780Done:\r
676df92c 1781 if (String[0] != NULL) {\r
1782 FreePool (String[0]);\r
1783 }\r
1784 if (String[1] != NULL) {\r
1785 FreePool (String[1]);\r
8b0fc5c1 1786 }\r
7936fb6a 1787\r
1788 return Status;\r
1789}\r
1790\r
1791\r
1792/**\r
1793 Evaluate opcode EFI_IFR_SPAN.\r
1794\r
1795 @param FormSet Formset which contains this opcode.\r
1796 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1797 @param Result Evaluation result for this opcode.\r
1798\r
1799 @retval EFI_SUCCESS Opcode evaluation success.\r
1800 @retval Other Opcode evaluation failed.\r
1801\r
1802**/\r
1803EFI_STATUS\r
1804IfrSpan (\r
1805 IN FORM_BROWSER_FORMSET *FormSet,\r
1806 IN UINT8 Flags,\r
1807 OUT EFI_HII_VALUE *Result\r
1808 )\r
1809{\r
1810 EFI_STATUS Status;\r
8f420676 1811 EFI_HII_VALUE Value[3];\r
7936fb6a 1812 CHAR16 *String[2];\r
1813 CHAR16 *Charset;\r
1814 UINTN Base;\r
1815 UINTN Index;\r
1816 CHAR16 *StringPtr;\r
1817 BOOLEAN Found;\r
1818\r
8f420676
ED
1819 ZeroMem (Value, sizeof (Value));\r
1820\r
1821 Status = PopExpression (&Value[0]);\r
1822 if (EFI_ERROR (Status)) {\r
1823 return Status;\r
1824 }\r
1825\r
1826 Status = PopExpression (&Value[1]);\r
7936fb6a 1827 if (EFI_ERROR (Status)) {\r
1828 return Status;\r
1829 }\r
8f420676
ED
1830\r
1831 Status = PopExpression (&Value[2]);\r
1832 if (EFI_ERROR (Status)) {\r
1833 return Status;\r
1834 } \r
1835\r
1836 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1837 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1838 return EFI_SUCCESS;\r
7936fb6a 1839 }\r
8f420676 1840 Base = (UINTN) Value[0].Value.u64;\r
7936fb6a 1841\r
1842 //\r
1843 // String[0] - Charset\r
1844 // String[1] - The string to search\r
1845 //\r
1846 String[0] = NULL;\r
1847 String[1] = NULL;\r
1848 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1849 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1850 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1851 Status = EFI_SUCCESS;\r
7936fb6a 1852 goto Done;\r
1853 }\r
1854\r
8f420676 1855 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
bc166db3 1856 if (String [Index] == NULL) {\r
7936fb6a 1857 Status = EFI_NOT_FOUND;\r
1858 goto Done;\r
1859 }\r
1860 }\r
1861\r
1862 if (Base >= StrLen (String[1])) {\r
8f420676
ED
1863 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1864 Status = EFI_SUCCESS;\r
7936fb6a 1865 goto Done;\r
1866 }\r
1867\r
1868 Found = FALSE;\r
1869 StringPtr = String[1] + Base;\r
1870 Charset = String[0];\r
1871 while (*StringPtr != 0 && !Found) {\r
1872 Index = 0;\r
1873 while (Charset[Index] != 0) {\r
1874 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
1875 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
1876 Found = TRUE;\r
1877 break;\r
1878 }\r
1879 } else {\r
1880 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
1881 Found = TRUE;\r
1882 break;\r
1883 }\r
1884 }\r
1885 //\r
1886 // Skip characters pair representing low-end of a range and high-end of a range\r
1887 //\r
1888 Index += 2;\r
1889 }\r
1890\r
1891 if (!Found) {\r
1892 StringPtr++;\r
1893 }\r
1894 }\r
1895\r
1896 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1897 Result->Value.u64 = StringPtr - String[1];\r
1898\r
1899Done:\r
676df92c 1900 if (String[0] != NULL) {\r
1901 FreePool (String[0]);\r
1902 }\r
1903 if (String[1] != NULL) {\r
1904 FreePool (String[1]);\r
8b0fc5c1 1905 }\r
7936fb6a 1906\r
1907 return Status;\r
1908}\r
1909\r
1910\r
1911/**\r
1912 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
1913\r
1914 @param Value HII Value to be converted.\r
1915\r
1916**/\r
1917VOID\r
1918ExtendValueToU64 (\r
1919 IN EFI_HII_VALUE *Value\r
1920 )\r
1921{\r
1922 UINT64 Temp;\r
1923\r
1924 Temp = 0;\r
1925 switch (Value->Type) {\r
1926 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1927 Temp = Value->Value.u8;\r
1928 break;\r
1929\r
1930 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1931 Temp = Value->Value.u16;\r
1932 break;\r
1933\r
1934 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1935 Temp = Value->Value.u32;\r
1936 break;\r
1937\r
1938 case EFI_IFR_TYPE_BOOLEAN:\r
1939 Temp = Value->Value.b;\r
1940 break;\r
1941\r
1942 case EFI_IFR_TYPE_TIME:\r
1943 Temp = Value->Value.u32 & 0xffffff;\r
1944 break;\r
1945\r
1946 case EFI_IFR_TYPE_DATE:\r
1947 Temp = Value->Value.u32;\r
1948 break;\r
1949\r
1950 default:\r
1951 return;\r
1952 }\r
1953\r
1954 Value->Value.u64 = Temp;\r
1955}\r
1956\r
d63a9eb4
ED
1957/**\r
1958 Get UINT64 type value.\r
1959\r
1960 @param Value Input Hii value.\r
1961\r
1962 @retval UINT64 Return the UINT64 type value.\r
1963\r
1964**/\r
1965UINT64\r
1966HiiValueToUINT64 (\r
1967 IN EFI_HII_VALUE *Value\r
1968 )\r
1969{\r
1970 UINT64 RetVal;\r
1971\r
1972 RetVal = 0;\r
1973\r
1974 switch (Value->Type) {\r
1975 case EFI_IFR_TYPE_NUM_SIZE_8:\r
1976 RetVal = Value->Value.u8;\r
1977 break;\r
1978\r
1979 case EFI_IFR_TYPE_NUM_SIZE_16:\r
1980 RetVal = Value->Value.u16;\r
1981 break;\r
1982\r
1983 case EFI_IFR_TYPE_NUM_SIZE_32:\r
1984 RetVal = Value->Value.u32;\r
1985 break;\r
1986\r
1987 case EFI_IFR_TYPE_BOOLEAN:\r
1988 RetVal = Value->Value.b;\r
1989 break;\r
1990\r
1991 case EFI_IFR_TYPE_DATE:\r
1992 RetVal = *(UINT64*) &Value->Value.date;\r
1993 break;\r
1994\r
1995 case EFI_IFR_TYPE_TIME:\r
1996 RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;\r
1997 break;\r
1998\r
1999 default:\r
2000 RetVal = Value->Value.u64;\r
2001 break;\r
2002 }\r
2003\r
2004 return RetVal;\r
2005}\r
7936fb6a 2006\r
2007/**\r
2008 Compare two Hii value.\r
2009\r
2010 @param Value1 Expression value to compare on left-hand.\r
2011 @param Value2 Expression value to compare on right-hand.\r
8f420676
ED
2012 @param Result Return value after compare.\r
2013 retval 0 Two operators equal.\r
2014 return Positive value if Value1 is greater than Value2.\r
2015 retval Negative value if Value1 is less than Value2.\r
7936fb6a 2016 @param HiiHandle Only required for string compare.\r
2017\r
8f420676
ED
2018 @retval other Could not perform compare on two values.\r
2019 @retval EFI_SUCCESS Compare the value success.\r
7936fb6a 2020\r
2021**/\r
8f420676 2022EFI_STATUS\r
7936fb6a 2023CompareHiiValue (\r
2024 IN EFI_HII_VALUE *Value1,\r
2025 IN EFI_HII_VALUE *Value2,\r
8f420676 2026 OUT INTN *Result,\r
7936fb6a 2027 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
2028 )\r
2029{\r
7936fb6a 2030 INT64 Temp64;\r
2031 CHAR16 *Str1;\r
2032 CHAR16 *Str2;\r
901ba0e7 2033 UINTN Len;\r
40578d09
ED
2034 UINT8 *Buf1;\r
2035 UINT16 Buf1Len;\r
2036 UINT8 *Buf2;\r
2037 UINT16 Buf2Len;\r
7936fb6a 2038\r
40578d09 2039 if (Value1->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {\r
7936fb6a 2040 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
2041 //\r
2042 // StringId 0 is reserved\r
2043 //\r
2044 return EFI_INVALID_PARAMETER;\r
2045 }\r
2046\r
2047 if (Value1->Value.string == Value2->Value.string) {\r
8f420676
ED
2048 *Result = 0;\r
2049 return EFI_SUCCESS;\r
7936fb6a 2050 }\r
2051\r
2052 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
2053 if (Str1 == NULL) {\r
2054 //\r
2055 // String not found\r
2056 //\r
8f420676 2057 return EFI_NOT_FOUND;\r
7936fb6a 2058 }\r
2059\r
2060 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
2061 if (Str2 == NULL) {\r
f4113e1f 2062 FreePool (Str1);\r
8f420676 2063 return EFI_NOT_FOUND;\r
7936fb6a 2064 }\r
2065\r
8f420676 2066 *Result = StrCmp (Str1, Str2);\r
7936fb6a 2067\r
f4113e1f 2068 FreePool (Str1);\r
2069 FreePool (Str2);\r
7936fb6a 2070\r
8f420676 2071 return EFI_SUCCESS;\r
7936fb6a 2072 }\r
2073\r
40578d09
ED
2074 //\r
2075 // Take types(date, time, ref, buffer) as buffer\r
2076 //\r
2077 if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {\r
2078 Buf1 = GetBufferForValue(Value1);\r
2079 Buf1Len = GetLengthForValue(Value1);\r
2080 Buf2 = GetBufferForValue(Value2);\r
2081 Buf2Len = GetLengthForValue(Value2);\r
2082 \r
2083 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
2084 *Result = CompareMem (Buf1, Buf2, Len);\r
2085 if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
901ba0e7
ED
2086 //\r
2087 // In this case, means base on samll number buffer, the data is same\r
2088 // So which value has more data, which value is bigger.\r
2089 //\r
40578d09 2090 *Result = Buf1Len > Buf2Len ? 1 : -1;\r
901ba0e7 2091 }\r
8f420676 2092 return EFI_SUCCESS;\r
901ba0e7
ED
2093 } \r
2094\r
7936fb6a 2095 //\r
40578d09 2096 // Take types(integer, boolean) as integer\r
7936fb6a 2097 //\r
40578d09
ED
2098 if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {\r
2099 Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);\r
2100 if (Temp64 > 0) {\r
2101 *Result = 1;\r
2102 } else if (Temp64 < 0) {\r
2103 *Result = -1;\r
2104 } else {\r
2105 *Result = 0;\r
2106 }\r
2107\r
2108 return EFI_SUCCESS;\r
7936fb6a 2109 }\r
2110\r
40578d09 2111 return EFI_UNSUPPORTED;\r
7936fb6a 2112}\r
2113\r
cbf73e50 2114/**\r
2115 Check if current user has the privilege specified by the permissions GUID.\r
2116\r
2117 @param[in] Guid A GUID specifying setup access permissions.\r
2118\r
2119 @retval TRUE Current user has the privilege.\r
2120 @retval FALSE Current user does not have the privilege.\r
2121**/\r
2122BOOLEAN\r
2123CheckUserPrivilege (\r
2124 IN EFI_GUID *Guid\r
2125 )\r
2126{\r
2127 EFI_STATUS Status;\r
2128 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
2129 EFI_USER_INFO_HANDLE UserInfoHandle;\r
2130 EFI_USER_INFO *UserInfo;\r
2131 EFI_GUID *UserPermissionsGuid;\r
2132 UINTN UserInfoSize;\r
2133 UINTN AccessControlDataSize;\r
2134 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
2135 UINTN RemainSize;\r
2136\r
2137 if (mUserManager == NULL) {\r
2138 Status = gBS->LocateProtocol (\r
2139 &gEfiUserManagerProtocolGuid,\r
2140 NULL,\r
2141 (VOID **) &mUserManager\r
2142 );\r
2143 if (EFI_ERROR (Status)) {\r
2144 ///\r
2145 /// If the system does not support user management, then it is assumed that\r
2146 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
2147 /// op-code is always TRUE.\r
2148 ///\r
2149 return TRUE;\r
2150 }\r
2151 }\r
2152\r
2153 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
2154 ASSERT_EFI_ERROR (Status);\r
2155\r
2156 ///\r
2157 /// Enumerate all user information of the current user profile\r
2158 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
2159 ///\r
2160 \r
2161 for (UserInfoHandle = NULL;;) {\r
2162 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
2163 if (EFI_ERROR (Status)) {\r
2164 break;\r
2165 }\r
2166\r
2167 UserInfoSize = 0;\r
2168 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
2169 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2170 continue;\r
2171 }\r
2172\r
2173 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
2174 if (UserInfo == NULL) {\r
2175 break;\r
2176 }\r
2177\r
2178 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
2179 if (EFI_ERROR (Status) ||\r
2180 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
2181 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
2182 FreePool (UserInfo);\r
2183 continue;\r
2184 }\r
2185\r
2186 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
2187 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
2188 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
3dd405be 2189 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
cbf73e50 2190 break;\r
2191 }\r
2192 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
2193 ///\r
2194 /// Check if current user has the privilege specified by the permissions GUID.\r
2195 ///\r
2196\r
2197 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
2198 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
2199 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
2200 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
2201 FreePool (UserInfo);\r
2202 return TRUE;\r
2203 }\r
2204 UserPermissionsGuid++;\r
2205 AccessControlDataSize -= sizeof (EFI_GUID);\r
2206 }\r
2207 }\r
2208 RemainSize -= AccessControl->Size;\r
2209 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
2210 }\r
2211\r
2212 FreePool (UserInfo);\r
2213 }\r
2214 return FALSE;\r
2215}\r
7936fb6a 2216\r
db40504e
ED
2217/**\r
2218 Get question value from the predefined formset.\r
2219\r
2220 @param DevicePath The driver's device path which produece the formset data.\r
2221 @param InputHiiHandle The hii handle associate with the formset data.\r
2222 @param FormSetGuid The formset guid which include the question.\r
2223 @param QuestionId The question id which need to get value from.\r
2224 @param Value The return data about question's value.\r
2225 \r
2226 @retval TRUE Get the question value success.\r
2227 @retval FALSE Get the question value failed.\r
2228**/\r
2229BOOLEAN \r
2230GetQuestionValueFromForm (\r
2231 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2232 IN EFI_HII_HANDLE InputHiiHandle,\r
2233 IN EFI_GUID *FormSetGuid,\r
2234 IN EFI_QUESTION_ID QuestionId,\r
2235 OUT EFI_HII_VALUE *Value\r
2236 )\r
2237{\r
2238 EFI_STATUS Status;\r
db40504e 2239 EFI_HII_HANDLE HiiHandle;\r
db40504e
ED
2240 FORM_BROWSER_STATEMENT *Question;\r
2241 FORM_BROWSER_FORMSET *FormSet;\r
2242 FORM_BROWSER_FORM *Form;\r
2243 BOOLEAN GetTheVal;\r
2244 LIST_ENTRY *Link;\r
2245\r
2246 // \r
2247 // The input parameter DevicePath or InputHiiHandle must have one valid input. \r
2248 //\r
2249 ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) || \r
2250 (DevicePath == NULL && InputHiiHandle != NULL) );\r
2251\r
2252 GetTheVal = TRUE;\r
db40504e
ED
2253 HiiHandle = NULL;\r
2254 Question = NULL;\r
2255 Form = NULL;\r
2256\r
2257 //\r
2258 // Get HiiHandle.\r
2259 //\r
2260 if (DevicePath != NULL) {\r
07d7dbae
ED
2261 HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
2262 if (HiiHandle == NULL) {\r
db40504e
ED
2263 return FALSE;\r
2264 }\r
db40504e
ED
2265 } else {\r
2266 HiiHandle = InputHiiHandle;\r
2267 } \r
2268 ASSERT (HiiHandle != NULL);\r
2269\r
2270 //\r
2271 // Get the formset data include this question.\r
2272 //\r
2273 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
2274 ASSERT (FormSet != NULL);\r
7c6c064c 2275 Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);\r
db40504e
ED
2276 if (EFI_ERROR (Status)) {\r
2277 GetTheVal = FALSE;\r
2278 goto Done;\r
2279 }\r
2280\r
2281 //\r
2282 // Base on the Question Id to get the question info.\r
2283 // \r
2284 Question = IdToQuestion(FormSet, NULL, QuestionId);\r
2285 if (Question == NULL) {\r
2286 GetTheVal = FALSE;\r
2287 goto Done;\r
2288 }\r
2289\r
2290 //\r
2291 // Search form in the formset scope\r
2292 //\r
2293 Link = GetFirstNode (&FormSet->FormListHead);\r
2294 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2295 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2296\r
2297 Question = IdToQuestion2 (Form, QuestionId);\r
2298 if (Question != NULL) {\r
2299 break;\r
2300 }\r
2301\r
2302 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2303 Form = NULL;\r
2304 }\r
2305 ASSERT (Form != NULL);\r
2306 \r
2307 //\r
2308 // Get the question value.\r
2309 //\r
816a7110 2310 Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithHiiDriver);\r
db40504e
ED
2311 if (EFI_ERROR (Status)) {\r
2312 GetTheVal = FALSE;\r
2313 goto Done;\r
2314 }\r
2315\r
2316 CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
2317 \r
2318Done:\r
2319 //\r
2320 // Clean the formset structure and restore the global parameter.\r
2321 //\r
2322 if (FormSet != NULL) {\r
2323 DestroyFormSet (FormSet);\r
2324 }\r
2325 \r
2326 return GetTheVal;\r
2327}\r
2328\r
7936fb6a 2329/**\r
bc166db3 2330 Evaluate the result of a HII expression.\r
2331\r
2332 If Expression is NULL, then ASSERT.\r
7936fb6a 2333\r
2334 @param FormSet FormSet associated with this expression.\r
2335 @param Form Form associated with this expression.\r
2336 @param Expression Expression to be evaluated.\r
2337\r
2338 @retval EFI_SUCCESS The expression evaluated successfuly\r
2339 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
2340 could not be found.\r
2341 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
2342 stack.\r
2343 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
2344 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
2345\r
2346**/\r
2347EFI_STATUS\r
2348EvaluateExpression (\r
2349 IN FORM_BROWSER_FORMSET *FormSet,\r
2350 IN FORM_BROWSER_FORM *Form,\r
2351 IN OUT FORM_EXPRESSION *Expression\r
2352 )\r
2353{\r
2354 EFI_STATUS Status;\r
2355 LIST_ENTRY *Link;\r
2356 EXPRESSION_OPCODE *OpCode;\r
2357 FORM_BROWSER_STATEMENT *Question;\r
2358 FORM_BROWSER_STATEMENT *Question2;\r
2359 UINT16 Index;\r
2360 EFI_HII_VALUE Data1;\r
2361 EFI_HII_VALUE Data2;\r
2362 EFI_HII_VALUE Data3;\r
2363 FORM_EXPRESSION *RuleExpression;\r
2364 EFI_HII_VALUE *Value;\r
2365 INTN Result;\r
2366 CHAR16 *StrPtr;\r
2573712e 2367 CHAR16 *NameValue;\r
7936fb6a 2368 UINT32 TempValue;\r
2573712e
LG
2369 LIST_ENTRY *SubExpressionLink;\r
2370 FORM_EXPRESSION *SubExpression;\r
2371 UINTN StackOffset;\r
2372 UINTN TempLength;\r
2373 CHAR16 TempStr[5];\r
2374 UINT8 DigitUint8;\r
2375 UINT8 *TempBuffer;\r
2376 EFI_TIME EfiTime;\r
db40504e 2377 EFI_HII_VALUE QuestionVal;\r
33efdf51 2378 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
7936fb6a 2379\r
4e1005ec
ED
2380 StrPtr = NULL;\r
2381\r
7936fb6a 2382 //\r
2573712e 2383 // Save current stack offset.\r
7936fb6a 2384 //\r
2573712e 2385 StackOffset = SaveExpressionEvaluationStackOffset ();\r
7936fb6a 2386\r
bc166db3 2387 ASSERT (Expression != NULL);\r
7936fb6a 2388 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
2389\r
2390 Link = GetFirstNode (&Expression->OpCodeListHead);\r
2391 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
2392 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
2393\r
2394 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
2395\r
2396 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
2397 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
2398 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
2399\r
2400 Value = &Data3;\r
2401 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2402 Status = EFI_SUCCESS;\r
2403\r
2404 switch (OpCode->Operand) {\r
2405 //\r
2406 // Built-in functions\r
2407 //\r
2408 case EFI_IFR_EQ_ID_VAL_OP:\r
2409 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2410 if (Question == NULL) {\r
8f420676
ED
2411 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2412 break;\r
7936fb6a 2413 }\r
2414\r
8f420676
ED
2415 Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);\r
2416 if (Status == EFI_UNSUPPORTED) {\r
2417 Status = EFI_SUCCESS;\r
2418 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2419 break;\r
2420 }\r
2421\r
2422 if (EFI_ERROR (Status)) {\r
2573712e 2423 goto Done;\r
7936fb6a 2424 }\r
2425 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2426 break;\r
2427\r
2428 case EFI_IFR_EQ_ID_ID_OP:\r
2429 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2430 if (Question == NULL) {\r
8f420676
ED
2431 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2432 break;\r
7936fb6a 2433 }\r
2434\r
2435 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
2436 if (Question2 == NULL) {\r
8f420676
ED
2437 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2438 break;\r
7936fb6a 2439 }\r
2440\r
8f420676
ED
2441 Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);\r
2442 if (Status == EFI_UNSUPPORTED) {\r
2443 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2444 Status = EFI_SUCCESS;\r
2445 break;\r
2446 }\r
2447 if (EFI_ERROR (Status)) {\r
2573712e 2448 goto Done;\r
7936fb6a 2449 }\r
2450 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2451 break;\r
2452\r
e8ef4283 2453 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
7936fb6a 2454 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2455 if (Question == NULL) {\r
8f420676
ED
2456 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2457 break;\r
7936fb6a 2458 }\r
2459\r
2460 Value->Value.b = FALSE;\r
2461 for (Index =0; Index < OpCode->ListLength; Index++) {\r
2462 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
2463 Value->Value.b = TRUE;\r
2464 break;\r
2465 }\r
2466 }\r
2467 break;\r
2468\r
2469 case EFI_IFR_DUP_OP:\r
2470 Status = PopExpression (Value);\r
2471 if (EFI_ERROR (Status)) {\r
2573712e 2472 goto Done;\r
7936fb6a 2473 }\r
2474\r
2475 Status = PushExpression (Value);\r
2476 break;\r
2477\r
2478 case EFI_IFR_QUESTION_REF1_OP:\r
2479 case EFI_IFR_THIS_OP:\r
2480 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2481 if (Question == NULL) {\r
2573712e
LG
2482 Status = EFI_NOT_FOUND;\r
2483 goto Done;\r
7936fb6a 2484 }\r
2485\r
2486 Value = &Question->HiiValue;\r
2487 break;\r
2488\r
cbf73e50 2489 case EFI_IFR_SECURITY_OP:\r
2490 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
2491 break;\r
2492\r
2573712e
LG
2493 case EFI_IFR_GET_OP:\r
2494 //\r
2495 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2496 //\r
2497 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2498 Value->Value.u8 = 0;\r
2499 if (OpCode->VarStorage != NULL) {\r
2500 switch (OpCode->VarStorage->Type) {\r
2501 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2502 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2503 //\r
2504 // Get value from Edit Buffer\r
2505 //\r
2506 Value->Type = OpCode->ValueType;\r
2507 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2508 break;\r
2509 case EFI_HII_VARSTORE_NAME_VALUE:\r
2510 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2511 //\r
2512 // Get value from string except for STRING value.\r
2513 //\r
816a7110 2514 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);\r
2573712e 2515 if (!EFI_ERROR (Status)) {\r
771ececd 2516 ASSERT (StrPtr != NULL);\r
2573712e
LG
2517 TempLength = StrLen (StrPtr);\r
2518 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
2519 Value->Type = OpCode->ValueType;\r
2520 TempBuffer = (UINT8 *) &Value->Value;\r
2521 ZeroMem (TempStr, sizeof (TempStr));\r
2522 for (Index = 0; Index < TempLength; Index ++) {\r
2523 TempStr[0] = StrPtr[TempLength - Index - 1];\r
2524 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
2525 if ((Index & 1) == 0) {\r
2526 TempBuffer [Index/2] = DigitUint8;\r
2527 } else {\r
771ececd 2528 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
2529 }\r
2530 }\r
2531 } \r
2532 }\r
2533 }\r
2534 break;\r
2535 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2536 //\r
2537 // Get value from variable.\r
2538 //\r
2539 TempLength = OpCode->ValueWidth;\r
2540 Value->Type = OpCode->ValueType;\r
2541 Status = gRT->GetVariable (\r
2542 OpCode->ValueName,\r
2543 &OpCode->VarStorage->Guid,\r
2544 NULL,\r
2545 &TempLength,\r
2546 &Value->Value\r
2547 );\r
2548 if (EFI_ERROR (Status)) {\r
2549 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2550 Value->Value.u8 = 0;\r
2551 }\r
cce6230f 2552 break;\r
2573712e
LG
2553 default:\r
2554 //\r
2555 // Not recognize storage.\r
2556 //\r
2557 Status = EFI_UNSUPPORTED;\r
2558 goto Done;\r
2559 }\r
2560 } else {\r
2561 //\r
2562 // For Time/Date Data\r
2563 //\r
2564 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2565 //\r
2566 // Only support Data/Time data when storage doesn't exist.\r
2567 //\r
2568 Status = EFI_UNSUPPORTED;\r
2569 goto Done;\r
2570 }\r
2571 Status = gRT->GetTime (&EfiTime, NULL);\r
2572 if (!EFI_ERROR (Status)) {\r
2573 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2574 switch (OpCode->VarStoreInfo.VarOffset) {\r
2575 case 0x00:\r
2576 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
2577 Value->Value.u16 = EfiTime.Year;\r
2578 break;\r
2579 case 0x02:\r
2580 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2581 Value->Value.u8 = EfiTime.Month;\r
2582 break;\r
2583 case 0x03:\r
2584 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2585 Value->Value.u8 = EfiTime.Day;\r
2586 break;\r
2587 default:\r
2588 //\r
2589 // Invalid Date field.\r
2590 //\r
2591 Status = EFI_INVALID_PARAMETER;\r
2592 goto Done;\r
2593 }\r
2594 } else {\r
2595 switch (OpCode->VarStoreInfo.VarOffset) {\r
2596 case 0x00:\r
2597 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2598 Value->Value.u8 = EfiTime.Hour;\r
2599 break;\r
2600 case 0x01:\r
2601 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2602 Value->Value.u8 = EfiTime.Minute;\r
2603 break;\r
2604 case 0x02:\r
2605 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2606 Value->Value.u8 = EfiTime.Second;\r
2607 break;\r
2608 default:\r
2609 //\r
2610 // Invalid Time field.\r
2611 //\r
2612 Status = EFI_INVALID_PARAMETER;\r
2613 goto Done;\r
2614 }\r
2615 }\r
2616 }\r
2617 }\r
2618\r
2619 break;\r
2620\r
7936fb6a 2621 case EFI_IFR_QUESTION_REF3_OP:\r
db40504e
ED
2622 //\r
2623 // EFI_IFR_QUESTION_REF3\r
2624 // Pop an expression from the expression stack\r
2625 //\r
2626 Status = PopExpression (Value);\r
2627 if (EFI_ERROR (Status)) {\r
2628 goto Done;\r
2629 }\r
2630 \r
2631 //\r
2632 // Validate the expression value\r
2633 //\r
2634 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2635 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2636 break;\r
db40504e
ED
2637 }\r
2638\r
2639 if (OpCode->DevicePath != 0) {\r
80a047f0 2640 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
33efdf51 2641\r
80a047f0
ED
2642 StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
2643 if (StrPtr != NULL && mPathFromText != NULL) {\r
2644 DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);\r
2645 if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {\r
2646 Value = &QuestionVal;\r
2647 }\r
2648 if (DevicePath != NULL) {\r
2649 FreePool (DevicePath);\r
2650 }\r
33efdf51
ED
2651 }\r
2652\r
80a047f0
ED
2653 if (StrPtr != NULL) {\r
2654 FreePool (StrPtr);\r
7936fb6a 2655 }\r
db40504e
ED
2656 } else if (CompareGuid (&OpCode->Guid, &gZeroGuid) != 0) {\r
2657 if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
8f420676
ED
2658 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2659 break;\r
db40504e 2660 }\r
8f420676 2661 Value = &QuestionVal;\r
db40504e 2662 } else {\r
7936fb6a 2663 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2664 if (Question == NULL) {\r
8f420676
ED
2665 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2666 break;\r
7936fb6a 2667 }\r
2668\r
2669 //\r
2670 // push the questions' value on to the expression stack\r
2671 //\r
2672 Value = &Question->HiiValue;\r
7936fb6a 2673 }\r
2674 break;\r
2675\r
2676 case EFI_IFR_RULE_REF_OP:\r
2677 //\r
2678 // Find expression for this rule\r
2679 //\r
2680 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
2681 if (RuleExpression == NULL) {\r
8f420676
ED
2682 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2683 break;\r
7936fb6a 2684 }\r
2685\r
2686 //\r
2687 // Evaluate this rule expression\r
2688 //\r
2689 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
8f420676
ED
2690 if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {\r
2691 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2692 break;\r
7936fb6a 2693 }\r
2694\r
2695 Value = &RuleExpression->Result;\r
2696 break;\r
2697\r
2698 case EFI_IFR_STRING_REF1_OP:\r
2699 Value->Type = EFI_IFR_TYPE_STRING;\r
2700 Value->Value.string = OpCode->Value.Value.string;\r
2701 break;\r
2702\r
2703 //\r
2704 // Constant\r
2705 //\r
2706 case EFI_IFR_TRUE_OP:\r
2707 case EFI_IFR_FALSE_OP:\r
2708 case EFI_IFR_ONE_OP:\r
2709 case EFI_IFR_ONES_OP:\r
2710 case EFI_IFR_UINT8_OP:\r
2711 case EFI_IFR_UINT16_OP:\r
2712 case EFI_IFR_UINT32_OP:\r
2713 case EFI_IFR_UINT64_OP:\r
2714 case EFI_IFR_UNDEFINED_OP:\r
2715 case EFI_IFR_VERSION_OP:\r
2716 case EFI_IFR_ZERO_OP:\r
2717 Value = &OpCode->Value;\r
2718 break;\r
2719\r
2720 //\r
2721 // unary-op\r
2722 //\r
2723 case EFI_IFR_LENGTH_OP:\r
2724 Status = PopExpression (Value);\r
2725 if (EFI_ERROR (Status)) {\r
2573712e 2726 goto Done;\r
7936fb6a 2727 }\r
40578d09 2728 if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) {\r
8f420676
ED
2729 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2730 break;\r
7936fb6a 2731 }\r
2732\r
901ba0e7
ED
2733 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2734 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2735 if (StrPtr == NULL) {\r
2736 Status = EFI_INVALID_PARAMETER;\r
2737 goto Done;\r
2738 }\r
7936fb6a 2739\r
901ba0e7
ED
2740 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2741 Value->Value.u64 = StrLen (StrPtr);\r
2742 FreePool (StrPtr);\r
2743 } else {\r
2744 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
40578d09 2745 Value->Value.u64 = GetLengthForValue(Value);\r
901ba0e7
ED
2746 FreePool (Value->Buffer);\r
2747 }\r
7936fb6a 2748 break;\r
2749\r
2750 case EFI_IFR_NOT_OP:\r
2751 Status = PopExpression (Value);\r
2752 if (EFI_ERROR (Status)) {\r
2573712e 2753 goto Done;\r
7936fb6a 2754 }\r
2755 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
2756 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2757 break;\r
7936fb6a 2758 }\r
2759 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2760 break;\r
2761\r
2762 case EFI_IFR_QUESTION_REF2_OP:\r
2763 //\r
2764 // Pop an expression from the expression stack\r
2765 //\r
2766 Status = PopExpression (Value);\r
2767 if (EFI_ERROR (Status)) {\r
2573712e 2768 goto Done;\r
7936fb6a 2769 }\r
2770\r
2771 //\r
2772 // Validate the expression value\r
2773 //\r
2774 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2775 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2776 break;\r
7936fb6a 2777 }\r
2778\r
2779 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2780 if (Question == NULL) {\r
8f420676
ED
2781 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2782 break;\r
7936fb6a 2783 }\r
2784\r
2785 Value = &Question->HiiValue;\r
2786 break;\r
2787\r
2788 case EFI_IFR_STRING_REF2_OP:\r
2789 //\r
2790 // Pop an expression from the expression stack\r
2791 //\r
2792 Status = PopExpression (Value);\r
2793 if (EFI_ERROR (Status)) {\r
2573712e 2794 goto Done;\r
7936fb6a 2795 }\r
2796\r
2797 //\r
2798 // Validate the expression value\r
2799 //\r
2800 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2801 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2802 break;\r
7936fb6a 2803 }\r
2804\r
2805 Value->Type = EFI_IFR_TYPE_STRING;\r
2806 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2807 if (StrPtr == NULL) {\r
2808 //\r
2809 // If String not exit, push an empty string\r
2810 //\r
2811 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2812 } else {\r
2813 Index = (UINT16) Value->Value.u64;\r
2814 Value->Value.string = Index;\r
f4113e1f 2815 FreePool (StrPtr);\r
7936fb6a 2816 }\r
2817 break;\r
2818\r
2819 case EFI_IFR_TO_BOOLEAN_OP:\r
2820 //\r
2821 // Pop an expression from the expression stack\r
2822 //\r
2823 Status = PopExpression (Value);\r
2824 if (EFI_ERROR (Status)) {\r
2573712e 2825 goto Done;\r
7936fb6a 2826 }\r
2827\r
2828 //\r
2829 // Convert an expression to a Boolean\r
2830 //\r
2831 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
2832 //\r
2833 // When converting from an unsigned integer, zero will be converted to\r
2834 // FALSE and any other value will be converted to TRUE.\r
2835 //\r
40578d09 2836 Value->Value.b = (BOOLEAN) (HiiValueToUINT64(Value) != 0);\r
7936fb6a 2837\r
2838 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2839 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2840 //\r
2841 // When converting from a string, if case-insensitive compare\r
2842 // with "true" is True, then push True. If a case-insensitive compare\r
39099cbd 2843 // with "false" is True, then push False. Otherwise, push Undefined. \r
7936fb6a 2844 //\r
2845 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2846 if (StrPtr == NULL) {\r
2573712e
LG
2847 Status = EFI_INVALID_PARAMETER;\r
2848 goto Done;\r
7936fb6a 2849 }\r
39099cbd
ED
2850 \r
2851 IfrStrToUpper (StrPtr);\r
2852 if (StrCmp (StrPtr, L"TRUE") == 0){\r
7936fb6a 2853 Value->Value.b = TRUE;\r
8f420676 2854 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 2855 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
7936fb6a 2856 Value->Value.b = FALSE;\r
8f420676 2857 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 2858 } else {\r
8f420676 2859 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
7936fb6a 2860 }\r
f4113e1f 2861 FreePool (StrPtr);\r
901ba0e7
ED
2862 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
2863 //\r
2864 // When converting from a buffer, if the buffer is all zeroes, \r
2865 // then push False. Otherwise push True. \r
2866 //\r
2867 for (Index =0; Index < Value->BufferLen; Index ++) {\r
2868 if (Value->Buffer[Index] != 0) { \r
2869 break;\r
2870 }\r
2871 }\r
2872\r
2873 if (Index >= Value->BufferLen) {\r
2874 Value->Value.b = FALSE;\r
2875 } else {\r
2876 Value->Value.b = TRUE;\r
2877 }\r
2878 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2879 FreePool (Value->Buffer);\r
7936fb6a 2880 }\r
2881 break;\r
2882\r
2883 case EFI_IFR_TO_STRING_OP:\r
2884 Status = IfrToString (FormSet, OpCode->Format, Value);\r
2885 break;\r
2886\r
2887 case EFI_IFR_TO_UINT_OP:\r
2888 Status = IfrToUint (FormSet, Value);\r
2889 break;\r
2890\r
2891 case EFI_IFR_TO_LOWER_OP:\r
2892 case EFI_IFR_TO_UPPER_OP:\r
2893 Status = InitializeUnicodeCollationProtocol ();\r
2894 if (EFI_ERROR (Status)) {\r
2573712e 2895 goto Done;\r
7936fb6a 2896 }\r
2897\r
2898 Status = PopExpression (Value);\r
2899 if (EFI_ERROR (Status)) {\r
2573712e 2900 goto Done;\r
7936fb6a 2901 }\r
2902\r
2903 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
8f420676
ED
2904 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2905 break;\r
7936fb6a 2906 }\r
2907\r
2908 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2909 if (StrPtr == NULL) {\r
2573712e
LG
2910 Status = EFI_NOT_FOUND;\r
2911 goto Done;\r
7936fb6a 2912 }\r
2913\r
2914 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
2915 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
2916 } else {\r
2917 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
2918 }\r
2919 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 2920 FreePool (StrPtr);\r
7936fb6a 2921 break;\r
2922\r
2923 case EFI_IFR_BITWISE_NOT_OP:\r
2924 //\r
2925 // Pop an expression from the expression stack\r
2926 //\r
2927 Status = PopExpression (Value);\r
2928 if (EFI_ERROR (Status)) {\r
2573712e 2929 goto Done;\r
7936fb6a 2930 }\r
2931 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
2932 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2933 break;\r
7936fb6a 2934 }\r
2935\r
2936 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
40578d09 2937 Value->Value.u64 = ~ HiiValueToUINT64(Value);\r
7936fb6a 2938 break;\r
2939\r
2573712e
LG
2940 case EFI_IFR_SET_OP:\r
2941 //\r
2942 // Pop an expression from the expression stack\r
2943 //\r
2944 Status = PopExpression (Value);\r
2945 if (EFI_ERROR (Status)) {\r
2946 goto Done;\r
2947 }\r
2948 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
2949 Data1.Value.b = FALSE;\r
2950 //\r
2951 // Set value to var storage buffer\r
2952 //\r
2953 if (OpCode->VarStorage != NULL) {\r
2954 switch (OpCode->VarStorage->Type) {\r
2955 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2956 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2957 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
2958 Data1.Value.b = TRUE;\r
2959 break;\r
2960 case EFI_HII_VARSTORE_NAME_VALUE:\r
2961 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2962 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
2963 ASSERT (Value != NULL);\r
2964 //\r
2965 // Convert Buffer to Hex String\r
2966 //\r
2967 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
2968 StrPtr = NameValue;\r
2969 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
2970 StrPtr += UnicodeValueToString (StrPtr, PREFIX_ZERO | RADIX_HEX, *TempBuffer, 2);\r
2971 }\r
7c6c064c 2972 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
2573712e
LG
2973 FreePool (NameValue);\r
2974 if (!EFI_ERROR (Status)) {\r
2975 Data1.Value.b = TRUE;\r
2976 }\r
2977 }\r
2978 break;\r
2979 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2980 Status = gRT->SetVariable (\r
2981 OpCode->ValueName,\r
2982 &OpCode->VarStorage->Guid,\r
2983 OpCode->VarStorage->Attributes,\r
2984 OpCode->ValueWidth,\r
2985 &Value->Value\r
2986 );\r
2987 if (!EFI_ERROR (Status)) {\r
2988 Data1.Value.b = TRUE;\r
2989 }\r
2990 break;\r
2991 default:\r
2992 //\r
2993 // Not recognize storage.\r
2994 //\r
2995 Status = EFI_UNSUPPORTED;\r
2996 goto Done;\r
2997 break;\r
2998 }\r
2999 } else {\r
3000 //\r
3001 // For Time/Date Data\r
3002 //\r
3003 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
3004 //\r
3005 // Only support Data/Time data when storage doesn't exist.\r
3006 //\r
3007 Status = EFI_UNSUPPORTED;\r
3008 goto Done;\r
3009 }\r
3010 Status = gRT->GetTime (&EfiTime, NULL);\r
3011 if (!EFI_ERROR (Status)) {\r
3012 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
3013 switch (OpCode->VarStoreInfo.VarOffset) {\r
3014 case 0x00:\r
3015 EfiTime.Year = Value->Value.u16;\r
3016 break;\r
3017 case 0x02:\r
3018 EfiTime.Month = Value->Value.u8;\r
3019 break;\r
3020 case 0x03:\r
3021 EfiTime.Day = Value->Value.u8;\r
3022 break;\r
3023 default:\r
3024 //\r
3025 // Invalid Date field.\r
3026 //\r
3027 Status = EFI_INVALID_PARAMETER;\r
3028 goto Done;\r
3029 }\r
3030 } else {\r
3031 switch (OpCode->VarStoreInfo.VarOffset) {\r
3032 case 0x00:\r
3033 EfiTime.Hour = Value->Value.u8;\r
3034 break;\r
3035 case 0x01:\r
3036 EfiTime.Minute = Value->Value.u8;\r
3037 break;\r
3038 case 0x02:\r
3039 EfiTime.Second = Value->Value.u8;\r
3040 break;\r
3041 default:\r
3042 //\r
3043 // Invalid Time field.\r
3044 //\r
3045 Status = EFI_INVALID_PARAMETER;\r
3046 goto Done;\r
3047 }\r
3048 }\r
3049 Status = gRT->SetTime (&EfiTime);\r
3050 if (!EFI_ERROR (Status)) {\r
3051 Data1.Value.b = TRUE;\r
3052 }\r
3053 }\r
3054 }\r
3055 Value = &Data1;\r
3056 break;\r
3057\r
7936fb6a 3058 //\r
3059 // binary-op\r
3060 //\r
3061 case EFI_IFR_ADD_OP:\r
3062 case EFI_IFR_SUBTRACT_OP:\r
3063 case EFI_IFR_MULTIPLY_OP:\r
3064 case EFI_IFR_DIVIDE_OP:\r
3065 case EFI_IFR_MODULO_OP:\r
3066 case EFI_IFR_BITWISE_AND_OP:\r
3067 case EFI_IFR_BITWISE_OR_OP:\r
3068 case EFI_IFR_SHIFT_LEFT_OP:\r
3069 case EFI_IFR_SHIFT_RIGHT_OP:\r
3070 //\r
3071 // Pop an expression from the expression stack\r
3072 //\r
3073 Status = PopExpression (&Data2);\r
3074 if (EFI_ERROR (Status)) {\r
2573712e 3075 goto Done;\r
7936fb6a 3076 }\r
7936fb6a 3077\r
3078 //\r
3079 // Pop another expression from the expression stack\r
3080 //\r
3081 Status = PopExpression (&Data1);\r
3082 if (EFI_ERROR (Status)) {\r
2573712e 3083 goto Done;\r
7936fb6a 3084 }\r
8f420676
ED
3085\r
3086 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
3087 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3088 break;\r
3089 }\r
3090\r
3091\r
7936fb6a 3092 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
3093 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3094 break;\r
7936fb6a 3095 }\r
3096\r
3097 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
3098\r
3099 switch (OpCode->Operand) {\r
3100 case EFI_IFR_ADD_OP:\r
40578d09 3101 Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2);\r
7936fb6a 3102 break;\r
3103\r
3104 case EFI_IFR_SUBTRACT_OP:\r
40578d09 3105 Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2);\r
7936fb6a 3106 break;\r
3107\r
3108 case EFI_IFR_MULTIPLY_OP:\r
40578d09 3109 Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
7936fb6a 3110 break;\r
3111\r
3112 case EFI_IFR_DIVIDE_OP:\r
40578d09 3113 Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
7936fb6a 3114 break;\r
3115\r
3116 case EFI_IFR_MODULO_OP:\r
40578d09 3117 DivU64x32Remainder (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &TempValue);\r
7936fb6a 3118 Value->Value.u64 = TempValue;\r
3119 break;\r
3120\r
3121 case EFI_IFR_BITWISE_AND_OP:\r
40578d09 3122 Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2);\r
7936fb6a 3123 break;\r
3124\r
3125 case EFI_IFR_BITWISE_OR_OP:\r
40578d09 3126 Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2);\r
7936fb6a 3127 break;\r
3128\r
3129 case EFI_IFR_SHIFT_LEFT_OP:\r
40578d09 3130 Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
7936fb6a 3131 break;\r
3132\r
3133 case EFI_IFR_SHIFT_RIGHT_OP:\r
40578d09 3134 Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
7936fb6a 3135 break;\r
3136\r
3137 default:\r
3138 break;\r
3139 }\r
3140 break;\r
3141\r
3142 case EFI_IFR_AND_OP:\r
3143 case EFI_IFR_OR_OP:\r
3144 //\r
3145 // Two Boolean operator\r
3146 //\r
3147 Status = PopExpression (&Data2);\r
3148 if (EFI_ERROR (Status)) {\r
2573712e 3149 goto Done;\r
7936fb6a 3150 }\r
7936fb6a 3151\r
3152 //\r
3153 // Pop another expression from the expression stack\r
3154 //\r
3155 Status = PopExpression (&Data1);\r
3156 if (EFI_ERROR (Status)) {\r
2573712e 3157 goto Done;\r
7936fb6a 3158 }\r
8f420676
ED
3159\r
3160 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3161 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3162 break;\r
3163 }\r
3164\r
7936fb6a 3165 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3166 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3167 break;\r
7936fb6a 3168 }\r
3169\r
3170 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
3171 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
3172 } else {\r
3173 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
3174 }\r
3175 break;\r
3176\r
3177 case EFI_IFR_EQUAL_OP:\r
3178 case EFI_IFR_NOT_EQUAL_OP:\r
3179 case EFI_IFR_GREATER_EQUAL_OP:\r
3180 case EFI_IFR_GREATER_THAN_OP:\r
3181 case EFI_IFR_LESS_EQUAL_OP:\r
3182 case EFI_IFR_LESS_THAN_OP:\r
3183 //\r
3184 // Compare two integer, string, boolean or date/time\r
3185 //\r
3186 Status = PopExpression (&Data2);\r
3187 if (EFI_ERROR (Status)) {\r
2573712e 3188 goto Done;\r
7936fb6a 3189 }\r
7936fb6a 3190\r
3191 //\r
3192 // Pop another expression from the expression stack\r
3193 //\r
3194 Status = PopExpression (&Data1);\r
3195 if (EFI_ERROR (Status)) {\r
2573712e 3196 goto Done;\r
7936fb6a 3197 }\r
3198\r
8f420676
ED
3199 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN && \r
3200 Data2.Type != EFI_IFR_TYPE_STRING && \r
40578d09 3201 !IsTypeInBuffer(&Data2)) {\r
8f420676
ED
3202 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3203 break;\r
3204 }\r
3205\r
3206 if (Data1.Type > EFI_IFR_TYPE_BOOLEAN && \r
3207 Data1.Type != EFI_IFR_TYPE_STRING && \r
40578d09 3208 !IsTypeInBuffer(&Data1)) {\r
8f420676
ED
3209 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3210 break;\r
3211 }\r
3212\r
3213 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
901ba0e7
ED
3214 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
3215 FreePool (Data1.Buffer);\r
40578d09
ED
3216 }\r
3217 if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
901ba0e7
ED
3218 FreePool (Data2.Buffer);\r
3219 }\r
3220 \r
8f420676
ED
3221 if (Status == EFI_UNSUPPORTED) {\r
3222 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3223 Status = EFI_SUCCESS;\r
3224 break;\r
3225 }\r
3226\r
3227 if (EFI_ERROR (Status)) {\r
2573712e 3228 goto Done;\r
7936fb6a 3229 }\r
3230\r
3231 switch (OpCode->Operand) {\r
3232 case EFI_IFR_EQUAL_OP:\r
3233 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
3234 break;\r
3235\r
3236 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 3237 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 3238 break;\r
3239\r
3240 case EFI_IFR_GREATER_EQUAL_OP:\r
3241 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
3242 break;\r
3243\r
3244 case EFI_IFR_GREATER_THAN_OP:\r
3245 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
3246 break;\r
3247\r
3248 case EFI_IFR_LESS_EQUAL_OP:\r
3249 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
3250 break;\r
3251\r
3252 case EFI_IFR_LESS_THAN_OP:\r
3253 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
3254 break;\r
3255\r
3256 default:\r
3257 break;\r
3258 }\r
3259 break;\r
3260\r
3261 case EFI_IFR_MATCH_OP:\r
20258293
ED
3262 Status = InitializeUnicodeCollationProtocol ();\r
3263 if (EFI_ERROR (Status)) {\r
3264 goto Done;\r
3265 }\r
3266 \r
7936fb6a 3267 Status = IfrMatch (FormSet, Value);\r
3268 break;\r
3269\r
3270 case EFI_IFR_CATENATE_OP:\r
3271 Status = IfrCatenate (FormSet, Value);\r
3272 break;\r
3273\r
3274 //\r
3275 // ternary-op\r
3276 //\r
3277 case EFI_IFR_CONDITIONAL_OP:\r
3278 //\r
3279 // Pop third expression from the expression stack\r
3280 //\r
3281 Status = PopExpression (&Data3);\r
3282 if (EFI_ERROR (Status)) {\r
2573712e 3283 goto Done;\r
7936fb6a 3284 }\r
3285\r
3286 //\r
3287 // Pop second expression from the expression stack\r
3288 //\r
3289 Status = PopExpression (&Data2);\r
3290 if (EFI_ERROR (Status)) {\r
2573712e 3291 goto Done;\r
7936fb6a 3292 }\r
3293\r
3294 //\r
3295 // Pop first expression from the expression stack\r
3296 //\r
3297 Status = PopExpression (&Data1);\r
3298 if (EFI_ERROR (Status)) {\r
2573712e 3299 goto Done;\r
7936fb6a 3300 }\r
3301 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3302 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3303 break;\r
7936fb6a 3304 }\r
3305\r
3306 if (Data1.Value.b) {\r
3307 Value = &Data3;\r
3308 } else {\r
3309 Value = &Data2;\r
3310 }\r
3311 break;\r
3312\r
3313 case EFI_IFR_FIND_OP:\r
3314 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3315 break;\r
3316\r
3317 case EFI_IFR_MID_OP:\r
3318 Status = IfrMid (FormSet, Value);\r
3319 break;\r
3320\r
3321 case EFI_IFR_TOKEN_OP:\r
3322 Status = IfrToken (FormSet, Value);\r
3323 break;\r
3324\r
3325 case EFI_IFR_SPAN_OP:\r
3326 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3327 break;\r
3328\r
2573712e
LG
3329 case EFI_IFR_MAP_OP:\r
3330 //\r
3331 // Pop the check value\r
3332 //\r
3333 Status = PopExpression (&Data1);\r
3334 if (EFI_ERROR (Status)) {\r
3335 goto Done;\r
3336 }\r
3337 //\r
3338 // Check MapExpression list is valid.\r
3339 //\r
3340 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
3341 Status = EFI_INVALID_PARAMETER;\r
3342 goto Done;\r
3343 }\r
3344 //\r
3345 // Go through map expression list.\r
3346 //\r
3347 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
3348 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3349 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3350 //\r
3351 // Evaluate the first expression in this pair.\r
3352 //\r
3353 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3354 if (EFI_ERROR (Status)) {\r
3355 goto Done;\r
3356 }\r
3357 //\r
3358 // Compare the expression value with current value\r
3359 //\r
8f420676 3360 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
2573712e
LG
3361 //\r
3362 // Try get the map value.\r
3363 //\r
3364 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3365 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3366 Status = EFI_INVALID_PARAMETER;\r
3367 goto Done;\r
3368 }\r
3369 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3370 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3371 if (EFI_ERROR (Status)) {\r
3372 goto Done;\r
3373 }\r
3374 Value = &SubExpression->Result;\r
3375 break;\r
3376 }\r
3377 //\r
3378 // Skip the second expression on this pair.\r
3379 //\r
3380 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3381 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3382 Status = EFI_INVALID_PARAMETER;\r
3383 goto Done;\r
3384 }\r
3385 //\r
3386 // Goto the first expression on next pair.\r
3387 //\r
3388 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3389 }\r
3390\r
3391 //\r
3392 // No map value is found.\r
3393 //\r
3394 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3395 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3396 Value->Value.u8 = 0;\r
3397 }\r
3398 break;\r
3399\r
7936fb6a 3400 default:\r
3401 break;\r
3402 }\r
8f420676 3403 if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
2573712e 3404 goto Done;\r
7936fb6a 3405 }\r
3406\r
3407 Status = PushExpression (Value);\r
3408 if (EFI_ERROR (Status)) {\r
2573712e 3409 goto Done;\r
7936fb6a 3410 }\r
3411 }\r
3412\r
3413 //\r
3414 // Pop the final result from expression stack\r
3415 //\r
3416 Value = &Data1;\r
3417 Status = PopExpression (Value);\r
3418 if (EFI_ERROR (Status)) {\r
2573712e 3419 goto Done;\r
7936fb6a 3420 }\r
3421\r
3422 //\r
3423 // After evaluating an expression, there should be only one value left on the expression stack\r
3424 //\r
3425 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 3426 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 3427 }\r
3428\r
2573712e
LG
3429Done:\r
3430 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3431 if (!EFI_ERROR (Status)) {\r
3432 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3433 }\r
7936fb6a 3434\r
2573712e 3435 return Status;\r
7936fb6a 3436}\r
31585af4 3437\r
e6106e89
ED
3438/**\r
3439 Check whether the result is TRUE or FALSE.\r
3440 \r
3441 For the EFI_HII_VALUE value type is numeric, return TRUE if the\r
3442 value is not 0.\r
3443\r
3444 @param Result Input the result data.\r
3445\r
3446 @retval TRUE The result is TRUE.\r
3447 @retval FALSE The result is FALSE.\r
3448\r
3449**/\r
3450BOOLEAN\r
3451IsTrue (\r
3452 IN EFI_HII_VALUE *Result\r
3453 )\r
3454{\r
3455 switch (Result->Type) {\r
3456 case EFI_IFR_TYPE_BOOLEAN:\r
3457 return Result->Value.b;\r
3458\r
3459 case EFI_IFR_TYPE_NUM_SIZE_8:\r
4f467fd3 3460 return (BOOLEAN)(Result->Value.u8 != 0);\r
e6106e89
ED
3461\r
3462 case EFI_IFR_TYPE_NUM_SIZE_16:\r
4f467fd3 3463 return (BOOLEAN)(Result->Value.u16 != 0);\r
e6106e89
ED
3464\r
3465 case EFI_IFR_TYPE_NUM_SIZE_32:\r
4f467fd3 3466 return (BOOLEAN)(Result->Value.u32 != 0);\r
e6106e89
ED
3467\r
3468 case EFI_IFR_TYPE_NUM_SIZE_64:\r
4f467fd3 3469 return (BOOLEAN)(Result->Value.u64 != 0);\r
e6106e89
ED
3470\r
3471 default:\r
3472 return FALSE;\r
3473 }\r
3474}\r
3475\r
31585af4
ED
3476/**\r
3477 Return the result of the expression list. Check the expression list and \r
3478 return the highest priority express result. \r
3479 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
3480\r
3481 @param ExpList The input expression list.\r
3482 @param Evaluate Whether need to evaluate the expression first.\r
3483 @param FormSet FormSet associated with this expression.\r
3484 @param Form Form associated with this expression. \r
3485\r
3486 @retval EXPRESS_RESULT Return the higher priority express result. \r
3487 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3488\r
3489**/\r
3490EXPRESS_RESULT \r
3491EvaluateExpressionList (\r
3492 IN FORM_EXPRESSION_LIST *ExpList,\r
3493 IN BOOLEAN Evaluate,\r
3494 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
3495 IN FORM_BROWSER_FORM *Form OPTIONAL\r
3496 )\r
3497{\r
3498 UINTN Index;\r
3499 EXPRESS_RESULT ReturnVal;\r
3500 EXPRESS_RESULT CompareOne;\r
3501 EFI_STATUS Status;\r
3502\r
3503 if (ExpList == NULL) {\r
3504 return ExpressFalse;\r
3505 }\r
3506\r
3507 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3508 Index = 0;\r
3509\r
3510 //\r
3511 // Check whether need to evaluate the expression first.\r
3512 //\r
3513 if (Evaluate) { \r
3514 while (ExpList->Count > Index) {\r
3515 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
3516 if (EFI_ERROR (Status)) {\r
3517 return ExpressFalse;\r
3518 }\r
3519 }\r
3520 }\r
3521\r
3522 //\r
3523 // Run the list of expressions.\r
3524 //\r
3525 ReturnVal = ExpressFalse;\r
3526 for (Index = 0; Index < ExpList->Count; Index++) {\r
e6106e89 3527 if (IsTrue (&ExpList->Expression[Index]->Result)) {\r
31585af4
ED
3528 switch (ExpList->Expression[Index]->Type) {\r
3529 case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
3530 CompareOne = ExpressSuppress;\r
3531 break;\r
3532\r
3533 case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
3534 CompareOne = ExpressGrayOut;\r
3535 break;\r
3536\r
3537 case EFI_HII_EXPRESSION_DISABLE_IF:\r
3538 CompareOne = ExpressDisable;\r
3539 break;\r
3540\r
3541 default:\r
3542 return ExpressFalse; \r
3543 }\r
3544\r
3545 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3546 }\r
3547 }\r
3548 \r
3549 return ReturnVal;\r
3550}\r