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