]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
MdeModulePkg/SetupBrowserDxe: ASSERT GetBufferForValue(&Value)
[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
0c1541d4
SZ
1284\r
1285 ASSERT (GetBufferForValue (&Value) != NULL);\r
40578d09 1286 Result->Value.u64 = *(UINT64*) GetBufferForValue (&Value);\r
0c1541d4 1287\r
40578d09
ED
1288 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1289 FreePool (Value.Buffer);\r
1290 }\r
7936fb6a 1291 } else {\r
1292 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1293 }\r
1294\r
1295 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1296 return Status;\r
1297}\r
1298\r
1299\r
1300/**\r
1301 Evaluate opcode EFI_IFR_CATENATE.\r
1302\r
1303 @param FormSet Formset which contains this opcode.\r
1304 @param Result Evaluation result for this opcode.\r
1305\r
1306 @retval EFI_SUCCESS Opcode evaluation success.\r
1307 @retval Other Opcode evaluation failed.\r
1308\r
1309**/\r
1310EFI_STATUS\r
1311IfrCatenate (\r
1312 IN FORM_BROWSER_FORMSET *FormSet,\r
1313 OUT EFI_HII_VALUE *Result\r
1314 )\r
1315{\r
1316 EFI_STATUS Status;\r
901ba0e7 1317 EFI_HII_VALUE Value[2];\r
7936fb6a 1318 CHAR16 *String[2];\r
1319 UINTN Index;\r
1320 CHAR16 *StringPtr;\r
1321 UINTN Size;\r
40578d09
ED
1322 UINT16 Length0;\r
1323 UINT16 Length1;\r
784952b1 1324 UINT8 *TmpBuf;\r
5ad66ec6 1325 UINTN MaxLen;\r
7936fb6a 1326\r
1327 //\r
1328 // String[0] - The second string\r
1329 // String[1] - The first string\r
1330 //\r
1331 String[0] = NULL;\r
1332 String[1] = NULL;\r
1333 StringPtr = NULL;\r
1334 Status = EFI_SUCCESS;\r
901ba0e7 1335 ZeroMem (Value, sizeof (Value));\r
7936fb6a 1336\r
8f420676
ED
1337 Status = PopExpression (&Value[0]);\r
1338 if (EFI_ERROR (Status)) {\r
1339 goto Done;\r
1340 }\r
1341\r
1342 Status = PopExpression (&Value[1]);\r
1343 if (EFI_ERROR (Status)) {\r
1344 goto Done;\r
1345 }\r
7936fb6a 1346\r
8f420676 1347 for (Index = 0; Index < 2; Index++) {\r
40578d09 1348 if (Value[Index].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[Index])) {\r
8f420676
ED
1349 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1350 Status = EFI_SUCCESS;\r
7936fb6a 1351 goto Done;\r
1352 }\r
1353\r
901ba0e7
ED
1354 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {\r
1355 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1356 if (String[Index] == NULL) {\r
1357 Status = EFI_NOT_FOUND;\r
1358 goto Done;\r
1359 }\r
7936fb6a 1360 }\r
1361 }\r
1362\r
901ba0e7
ED
1363 if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
1364 Size = StrSize (String[0]);\r
5ad66ec6
DB
1365 MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);\r
1366 StringPtr= AllocatePool (MaxLen * sizeof (CHAR16));\r
901ba0e7 1367 ASSERT (StringPtr != NULL);\r
5ad66ec6
DB
1368 StrCpyS (StringPtr, MaxLen, String[1]);\r
1369 StrCatS (StringPtr, MaxLen, String[0]);\r
7936fb6a 1370\r
901ba0e7
ED
1371 Result->Type = EFI_IFR_TYPE_STRING;\r
1372 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
1373 } else {\r
1374 Result->Type = EFI_IFR_TYPE_BUFFER;\r
40578d09
ED
1375 Length0 = GetLengthForValue(&Value[0]);\r
1376 Length1 = GetLengthForValue(&Value[1]);\r
1377 Result->BufferLen = (UINT16) (Length0 + Length1);\r
901ba0e7
ED
1378\r
1379 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1380 ASSERT (Result->Buffer != NULL);\r
7936fb6a 1381\r
784952b1
ED
1382 TmpBuf = GetBufferForValue(&Value[0]);\r
1383 ASSERT (TmpBuf != NULL);\r
1384 CopyMem (Result->Buffer, TmpBuf, Length0);\r
1385 TmpBuf = GetBufferForValue(&Value[1]);\r
1386 ASSERT (TmpBuf != NULL);\r
1387 CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);\r
901ba0e7 1388 }\r
7936fb6a 1389Done:\r
901ba0e7
ED
1390 if (Value[0].Buffer != NULL) {\r
1391 FreePool (Value[0].Buffer);\r
1392 }\r
1393 if (Value[1].Buffer != NULL) {\r
1394 FreePool (Value[1].Buffer);\r
1395 }\r
676df92c 1396 if (String[0] != NULL) {\r
1397 FreePool (String[0]);\r
1398 }\r
1399 if (String[1] != NULL) {\r
1400 FreePool (String[1]);\r
8b0fc5c1 1401 }\r
676df92c 1402 if (StringPtr != NULL) {\r
1403 FreePool (StringPtr);\r
1404 }\r
7936fb6a 1405\r
1406 return Status;\r
1407}\r
1408\r
1409\r
1410/**\r
1411 Evaluate opcode EFI_IFR_MATCH.\r
1412\r
1413 @param FormSet Formset which contains this opcode.\r
1414 @param Result Evaluation result for this opcode.\r
1415\r
1416 @retval EFI_SUCCESS Opcode evaluation success.\r
1417 @retval Other Opcode evaluation failed.\r
1418\r
1419**/\r
1420EFI_STATUS\r
1421IfrMatch (\r
1422 IN FORM_BROWSER_FORMSET *FormSet,\r
1423 OUT EFI_HII_VALUE *Result\r
1424 )\r
1425{\r
1426 EFI_STATUS Status;\r
8f420676 1427 EFI_HII_VALUE Value[2];\r
7936fb6a 1428 CHAR16 *String[2];\r
1429 UINTN Index;\r
1430\r
1431 //\r
1432 // String[0] - The string to search\r
1433 // String[1] - pattern\r
1434 //\r
1435 String[0] = NULL;\r
1436 String[1] = NULL;\r
1437 Status = EFI_SUCCESS;\r
8f420676
ED
1438 ZeroMem (Value, sizeof (Value));\r
1439\r
1440 Status = PopExpression (&Value[0]);\r
1441 if (EFI_ERROR (Status)) {\r
1442 goto Done;\r
1443 }\r
1444\r
1445 Status = PopExpression (&Value[1]);\r
1446 if (EFI_ERROR (Status)) {\r
1447 goto Done;\r
1448 }\r
7936fb6a 1449\r
8f420676
ED
1450 for (Index = 0; Index < 2; Index++) {\r
1451 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
1452 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1453 Status = EFI_SUCCESS;\r
7936fb6a 1454 goto Done;\r
1455 }\r
1456\r
8f420676 1457 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
bc166db3 1458 if (String [Index] == NULL) {\r
7936fb6a 1459 Status = EFI_NOT_FOUND;\r
1460 goto Done;\r
1461 }\r
1462 }\r
1463\r
1464 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1465 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
1466\r
1467Done:\r
676df92c 1468 if (String[0] != NULL) {\r
1469 FreePool (String[0]);\r
1470 }\r
1471 if (String[1] != NULL) {\r
1472 FreePool (String[1]);\r
8b0fc5c1 1473 }\r
7936fb6a 1474\r
1475 return Status;\r
1476}\r
1477\r
9bd22b08
ED
1478/**\r
1479 Evaluate opcode EFI_IFR_MATCH2.\r
1480\r
1481 @param FormSet Formset which contains this opcode.\r
1482 @param SyntaxType Syntax type for match2.\r
1483 @param Result Evaluation result for this opcode.\r
1484\r
1485 @retval EFI_SUCCESS Opcode evaluation success.\r
1486 @retval Other Opcode evaluation failed.\r
1487\r
1488**/\r
1489EFI_STATUS\r
1490IfrMatch2 (\r
1491 IN FORM_BROWSER_FORMSET *FormSet,\r
1492 IN EFI_GUID *SyntaxType,\r
1493 OUT EFI_HII_VALUE *Result\r
1494 )\r
1495{\r
1496 EFI_STATUS Status;\r
1497 EFI_HII_VALUE Value[2];\r
1498 CHAR16 *String[2];\r
1499 UINTN Index;\r
1500 UINTN GuidIndex;\r
1501 EFI_HANDLE *HandleBuffer;\r
1502 UINTN BufferSize;\r
1503 EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol;\r
1504 UINTN RegExSyntaxTypeListSize;\r
1505 EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList;\r
1506 UINTN CapturesCount;\r
1507\r
1508 //\r
1509 // String[0] - The string to search\r
1510 // String[1] - pattern\r
1511 //\r
1512 String[0] = NULL;\r
1513 String[1] = NULL;\r
1514 HandleBuffer = NULL;\r
1515 RegExSyntaxTypeList = NULL;\r
1516 Status = EFI_SUCCESS;\r
1517 ZeroMem (Value, sizeof (Value));\r
1518\r
1519 Status = PopExpression (&Value[0]);\r
1520 if (EFI_ERROR (Status)) {\r
1521 goto Done;\r
1522 }\r
1523\r
1524 Status = PopExpression (&Value[1]);\r
1525 if (EFI_ERROR (Status)) {\r
1526 goto Done;\r
1527 }\r
1528\r
1529 for (Index = 0; Index < 2; Index++) {\r
1530 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {\r
1531 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1532 Status = EFI_SUCCESS;\r
1533 goto Done;\r
1534 }\r
1535\r
1536 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1537 if (String [Index] == NULL) {\r
1538 Status = EFI_NOT_FOUND;\r
1539 goto Done;\r
1540 }\r
1541 }\r
1542\r
1543 BufferSize = 0;\r
1544 HandleBuffer = NULL;\r
1545 Status = gBS->LocateHandle(\r
1546 ByProtocol,\r
1547 &gEfiRegularExpressionProtocolGuid,\r
1548 NULL,\r
1549 &BufferSize,\r
1550 HandleBuffer);\r
1551 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1552 HandleBuffer = AllocateZeroPool(BufferSize);\r
1553 if (HandleBuffer == NULL) {\r
1554 Status = EFI_OUT_OF_RESOURCES;\r
1555 goto Done;\r
1556 }\r
1557 Status = gBS->LocateHandle(\r
1558 ByProtocol,\r
1559 &gEfiRegularExpressionProtocolGuid,\r
1560 NULL,\r
1561 &BufferSize,\r
1562 HandleBuffer);\r
1563\r
aee257db
ED
1564 }\r
1565\r
1566 if (EFI_ERROR (Status)) {\r
1a03ab8a 1567 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
9bd22b08
ED
1568 Status = EFI_SUCCESS;\r
1569 goto Done;\r
1570 }\r
1571\r
aee257db 1572 ASSERT (HandleBuffer != NULL);\r
9bd22b08
ED
1573 for ( Index = 0; Index < BufferSize / sizeof(EFI_HANDLE); Index ++) {\r
1574 Status = gBS->HandleProtocol (\r
1575 HandleBuffer[Index],\r
1576 &gEfiRegularExpressionProtocolGuid,\r
1577 (VOID**)&RegularExpressionProtocol\r
1578 );\r
1579 if (EFI_ERROR (Status)) {\r
1580 goto Done;\r
1581 }\r
1582\r
1583 RegExSyntaxTypeListSize = 0;\r
1584 RegExSyntaxTypeList = NULL;\r
1585\r
1586 Status = RegularExpressionProtocol->GetInfo (\r
d1102dba
LG
1587 RegularExpressionProtocol,\r
1588 &RegExSyntaxTypeListSize,\r
9bd22b08
ED
1589 RegExSyntaxTypeList\r
1590 );\r
1591 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1592 RegExSyntaxTypeList = AllocateZeroPool(RegExSyntaxTypeListSize);\r
1593 if (RegExSyntaxTypeList == NULL) {\r
1594 Status = EFI_OUT_OF_RESOURCES;\r
1595 goto Done;\r
1596 }\r
1597 Status = RegularExpressionProtocol->GetInfo (\r
d1102dba
LG
1598 RegularExpressionProtocol,\r
1599 &RegExSyntaxTypeListSize,\r
9bd22b08
ED
1600 RegExSyntaxTypeList\r
1601 );\r
1602 } else if (EFI_ERROR (Status)) {\r
1603 goto Done;\r
1604 }\r
1605\r
1606 for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof(EFI_GUID); GuidIndex++) {\r
1607 if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {\r
1608 //\r
1609 // Find the match type, return the value.\r
1610 //\r
1611 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1612 Status = RegularExpressionProtocol->MatchString (\r
d1102dba 1613 RegularExpressionProtocol,\r
9bd22b08
ED
1614 String[0],\r
1615 String[1],\r
1616 SyntaxType,\r
1617 &Result->Value.b,\r
1618 NULL,\r
1619 &CapturesCount\r
1620 );\r
1621 goto Done;\r
1622 }\r
1623 }\r
1624\r
1625 if (RegExSyntaxTypeList != NULL) {\r
1626 FreePool (RegExSyntaxTypeList);\r
1627 }\r
1628 }\r
1629\r
1630 //\r
d1102dba 1631 // Type specified by SyntaxType is not supported\r
9bd22b08
ED
1632 // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.\r
1633 //\r
1a03ab8a 1634 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
9bd22b08
ED
1635 Status = EFI_SUCCESS;\r
1636\r
1637Done:\r
1638 if (String[0] != NULL) {\r
1639 FreePool (String[0]);\r
1640 }\r
1641 if (String[1] != NULL) {\r
1642 FreePool (String[1]);\r
1643 }\r
1644 if (RegExSyntaxTypeList != NULL) {\r
1645 FreePool (RegExSyntaxTypeList);\r
1646 }\r
1647 if (HandleBuffer != NULL) {\r
1648 FreePool (HandleBuffer);\r
1649 }\r
1650 return Status;\r
1651}\r
7936fb6a 1652\r
1653/**\r
1654 Evaluate opcode EFI_IFR_FIND.\r
1655\r
1656 @param FormSet Formset which contains this opcode.\r
1657 @param Format Case sensitive or insensitive.\r
1658 @param Result Evaluation result for this opcode.\r
1659\r
1660 @retval EFI_SUCCESS Opcode evaluation success.\r
1661 @retval Other Opcode evaluation failed.\r
1662\r
1663**/\r
1664EFI_STATUS\r
1665IfrFind (\r
1666 IN FORM_BROWSER_FORMSET *FormSet,\r
1667 IN UINT8 Format,\r
1668 OUT EFI_HII_VALUE *Result\r
1669 )\r
1670{\r
1671 EFI_STATUS Status;\r
8f420676 1672 EFI_HII_VALUE Value[3];\r
7936fb6a 1673 CHAR16 *String[2];\r
1674 UINTN Base;\r
1675 CHAR16 *StringPtr;\r
1676 UINTN Index;\r
1677\r
8f420676
ED
1678 ZeroMem (Value, sizeof (Value));\r
1679\r
7936fb6a 1680 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
8f420676 1681 return EFI_INVALID_PARAMETER;\r
7936fb6a 1682 }\r
1683\r
8f420676
ED
1684 Status = PopExpression (&Value[0]);\r
1685 if (EFI_ERROR (Status)) {\r
1686 return Status;\r
1687 }\r
1688\r
1689 Status = PopExpression (&Value[1]);\r
7936fb6a 1690 if (EFI_ERROR (Status)) {\r
1691 return Status;\r
1692 }\r
8f420676
ED
1693\r
1694 Status = PopExpression (&Value[2]);\r
1695 if (EFI_ERROR (Status)) {\r
1696 return Status;\r
d1102dba 1697 }\r
8f420676
ED
1698\r
1699 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1700 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1701 return EFI_SUCCESS;\r
7936fb6a 1702 }\r
8f420676 1703 Base = (UINTN) Value[0].Value.u64;\r
7936fb6a 1704\r
1705 //\r
1706 // String[0] - sub-string\r
1707 // String[1] - The string to search\r
1708 //\r
1709 String[0] = NULL;\r
1710 String[1] = NULL;\r
1711 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1712 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1713 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1714 Status = EFI_SUCCESS;\r
7936fb6a 1715 goto Done;\r
1716 }\r
1717\r
8f420676 1718 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
d0720b57 1719 if (String[Index] == NULL) {\r
7936fb6a 1720 Status = EFI_NOT_FOUND;\r
1721 goto Done;\r
1722 }\r
1723\r
1724 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {\r
1725 //\r
1726 // Case insensitive, convert both string to upper case\r
1727 //\r
1728 IfrStrToUpper (String[Index]);\r
1729 }\r
1730 }\r
1731\r
1732 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
1733 if (Base >= StrLen (String[1])) {\r
1734 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;\r
1735 } else {\r
1736 StringPtr = StrStr (String[1] + Base, String[0]);\r
1737 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
1738 }\r
1739\r
1740Done:\r
676df92c 1741 if (String[0] != NULL) {\r
1742 FreePool (String[0]);\r
1743 }\r
1744 if (String[1] != NULL) {\r
1745 FreePool (String[1]);\r
8b0fc5c1 1746 }\r
7936fb6a 1747\r
1748 return Status;\r
1749}\r
1750\r
1751\r
1752/**\r
1753 Evaluate opcode EFI_IFR_MID.\r
1754\r
1755 @param FormSet Formset which contains this opcode.\r
1756 @param Result Evaluation result for this opcode.\r
1757\r
1758 @retval EFI_SUCCESS Opcode evaluation success.\r
1759 @retval Other Opcode evaluation failed.\r
1760\r
1761**/\r
1762EFI_STATUS\r
1763IfrMid (\r
1764 IN FORM_BROWSER_FORMSET *FormSet,\r
1765 OUT EFI_HII_VALUE *Result\r
1766 )\r
1767{\r
1768 EFI_STATUS Status;\r
8f420676 1769 EFI_HII_VALUE Value[3];\r
7936fb6a 1770 CHAR16 *String;\r
1771 UINTN Base;\r
1772 UINTN Length;\r
1773 CHAR16 *SubString;\r
901ba0e7 1774 UINT16 BufferLen;\r
40578d09 1775 UINT8 *Buffer;\r
7936fb6a 1776\r
8f420676
ED
1777 ZeroMem (Value, sizeof (Value));\r
1778\r
1779 Status = PopExpression (&Value[0]);\r
7936fb6a 1780 if (EFI_ERROR (Status)) {\r
1781 return Status;\r
1782 }\r
7936fb6a 1783\r
8f420676 1784 Status = PopExpression (&Value[1]);\r
7936fb6a 1785 if (EFI_ERROR (Status)) {\r
1786 return Status;\r
1787 }\r
7936fb6a 1788\r
8f420676 1789 Status = PopExpression (&Value[2]);\r
7936fb6a 1790 if (EFI_ERROR (Status)) {\r
1791 return Status;\r
d1102dba 1792 }\r
8f420676
ED
1793\r
1794 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1795 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1796 return EFI_SUCCESS;\r
7936fb6a 1797 }\r
8f420676
ED
1798 Length = (UINTN) Value[0].Value.u64;\r
1799\r
1800 if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1801 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1802 return EFI_SUCCESS;\r
7936fb6a 1803 }\r
8f420676
ED
1804 Base = (UINTN) Value[1].Value.u64;\r
1805\r
40578d09 1806 if (Value[2].Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer(&Value[2])) {\r
8f420676
ED
1807 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1808 return EFI_SUCCESS;\r
1809 }\r
1810 if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
1811 String = GetToken (Value[2].Value.string, FormSet->HiiHandle);\r
901ba0e7
ED
1812 if (String == NULL) {\r
1813 return EFI_NOT_FOUND;\r
1814 }\r
7936fb6a 1815\r
901ba0e7
ED
1816 if (Length == 0 || Base >= StrLen (String)) {\r
1817 SubString = gEmptyString;\r
1818 } else {\r
1819 SubString = String + Base;\r
1820 if ((Base + Length) < StrLen (String)) {\r
1821 SubString[Length] = L'\0';\r
1822 }\r
7936fb6a 1823 }\r
7936fb6a 1824\r
901ba0e7
ED
1825 Result->Type = EFI_IFR_TYPE_STRING;\r
1826 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
7936fb6a 1827\r
901ba0e7
ED
1828 FreePool (String);\r
1829 } else {\r
40578d09
ED
1830 BufferLen = GetLengthForValue (&Value[2]);\r
1831 Buffer = GetBufferForValue (&Value[2]);\r
1832\r
901ba0e7
ED
1833 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1834 if (Length == 0 || Base >= BufferLen) {\r
1835 Result->BufferLen = 0;\r
1836 Result->Buffer = NULL;\r
1837 } else {\r
d1102dba 1838 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);\r
901ba0e7
ED
1839 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1840 ASSERT (Result->Buffer != NULL);\r
40578d09 1841 CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
901ba0e7 1842 }\r
7936fb6a 1843\r
40578d09
ED
1844 if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
1845 FreePool (Value[2].Buffer);\r
1846 }\r
901ba0e7 1847 }\r
d1102dba 1848\r
7936fb6a 1849 return Status;\r
1850}\r
1851\r
1852\r
1853/**\r
1854 Evaluate opcode EFI_IFR_TOKEN.\r
1855\r
1856 @param FormSet Formset which contains this opcode.\r
1857 @param Result Evaluation result for this opcode.\r
1858\r
1859 @retval EFI_SUCCESS Opcode evaluation success.\r
1860 @retval Other Opcode evaluation failed.\r
1861\r
1862**/\r
1863EFI_STATUS\r
1864IfrToken (\r
1865 IN FORM_BROWSER_FORMSET *FormSet,\r
1866 OUT EFI_HII_VALUE *Result\r
1867 )\r
1868{\r
1869 EFI_STATUS Status;\r
8f420676 1870 EFI_HII_VALUE Value[3];\r
7936fb6a 1871 CHAR16 *String[2];\r
1872 UINTN Count;\r
1873 CHAR16 *Delimiter;\r
1874 CHAR16 *SubString;\r
1875 CHAR16 *StringPtr;\r
1876 UINTN Index;\r
1877\r
8f420676
ED
1878 ZeroMem (Value, sizeof (Value));\r
1879\r
1880 Status = PopExpression (&Value[0]);\r
1881 if (EFI_ERROR (Status)) {\r
1882 return Status;\r
1883 }\r
1884\r
1885 Status = PopExpression (&Value[1]);\r
7936fb6a 1886 if (EFI_ERROR (Status)) {\r
1887 return Status;\r
1888 }\r
8f420676
ED
1889\r
1890 Status = PopExpression (&Value[2]);\r
1891 if (EFI_ERROR (Status)) {\r
1892 return Status;\r
d1102dba 1893 }\r
8f420676 1894\r
d1102dba 1895 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
8f420676
ED
1896 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1897 return EFI_SUCCESS;\r
7936fb6a 1898 }\r
8f420676 1899 Count = (UINTN) Value[0].Value.u64;\r
7936fb6a 1900\r
1901 //\r
1902 // String[0] - Delimiter\r
1903 // String[1] - The string to search\r
1904 //\r
1905 String[0] = NULL;\r
1906 String[1] = NULL;\r
1907 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
1908 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1909 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
d1102dba 1910 Status = EFI_SUCCESS;\r
7936fb6a 1911 goto Done;\r
1912 }\r
1913\r
8f420676 1914 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
d0720b57 1915 if (String[Index] == NULL) {\r
7936fb6a 1916 Status = EFI_NOT_FOUND;\r
1917 goto Done;\r
1918 }\r
1919 }\r
1920\r
1921 Delimiter = String[0];\r
1922 SubString = String[1];\r
1923 while (Count > 0) {\r
1924 SubString = StrStr (SubString, Delimiter);\r
1925 if (SubString != NULL) {\r
1926 //\r
1927 // Skip over the delimiter\r
1928 //\r
1929 SubString = SubString + StrLen (Delimiter);\r
1930 } else {\r
1931 break;\r
1932 }\r
1933 Count--;\r
1934 }\r
1935\r
1936 if (SubString == NULL) {\r
1937 //\r
1938 // nth delimited sub-string not found, push an empty string\r
1939 //\r
1940 SubString = gEmptyString;\r
1941 } else {\r
1942 //\r
1943 // Put a NULL terminator for nth delimited sub-string\r
1944 //\r
1945 StringPtr = StrStr (SubString, Delimiter);\r
1946 if (StringPtr != NULL) {\r
1947 *StringPtr = L'\0';\r
1948 }\r
1949 }\r
1950\r
1951 Result->Type = EFI_IFR_TYPE_STRING;\r
1952 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1953\r
1954Done:\r
676df92c 1955 if (String[0] != NULL) {\r
1956 FreePool (String[0]);\r
1957 }\r
1958 if (String[1] != NULL) {\r
1959 FreePool (String[1]);\r
8b0fc5c1 1960 }\r
7936fb6a 1961\r
1962 return Status;\r
1963}\r
1964\r
1965\r
1966/**\r
1967 Evaluate opcode EFI_IFR_SPAN.\r
1968\r
1969 @param FormSet Formset which contains this opcode.\r
1970 @param Flags FIRST_MATCHING or FIRST_NON_MATCHING.\r
1971 @param Result Evaluation result for this opcode.\r
1972\r
1973 @retval EFI_SUCCESS Opcode evaluation success.\r
1974 @retval Other Opcode evaluation failed.\r
1975\r
1976**/\r
1977EFI_STATUS\r
1978IfrSpan (\r
1979 IN FORM_BROWSER_FORMSET *FormSet,\r
1980 IN UINT8 Flags,\r
1981 OUT EFI_HII_VALUE *Result\r
1982 )\r
1983{\r
1984 EFI_STATUS Status;\r
8f420676 1985 EFI_HII_VALUE Value[3];\r
7936fb6a 1986 CHAR16 *String[2];\r
1987 CHAR16 *Charset;\r
1988 UINTN Base;\r
1989 UINTN Index;\r
1990 CHAR16 *StringPtr;\r
1991 BOOLEAN Found;\r
1992\r
8f420676
ED
1993 ZeroMem (Value, sizeof (Value));\r
1994\r
1995 Status = PopExpression (&Value[0]);\r
1996 if (EFI_ERROR (Status)) {\r
1997 return Status;\r
1998 }\r
1999\r
2000 Status = PopExpression (&Value[1]);\r
7936fb6a 2001 if (EFI_ERROR (Status)) {\r
2002 return Status;\r
2003 }\r
8f420676
ED
2004\r
2005 Status = PopExpression (&Value[2]);\r
2006 if (EFI_ERROR (Status)) {\r
2007 return Status;\r
d1102dba 2008 }\r
8f420676
ED
2009\r
2010 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
2011 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2012 return EFI_SUCCESS;\r
7936fb6a 2013 }\r
8f420676 2014 Base = (UINTN) Value[0].Value.u64;\r
7936fb6a 2015\r
2016 //\r
2017 // String[0] - Charset\r
2018 // String[1] - The string to search\r
2019 //\r
2020 String[0] = NULL;\r
2021 String[1] = NULL;\r
2022 for (Index = 0; Index < 2; Index++) {\r
8f420676
ED
2023 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
2024 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2025 Status = EFI_SUCCESS;\r
7936fb6a 2026 goto Done;\r
2027 }\r
2028\r
8f420676 2029 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
bc166db3 2030 if (String [Index] == NULL) {\r
7936fb6a 2031 Status = EFI_NOT_FOUND;\r
2032 goto Done;\r
2033 }\r
2034 }\r
2035\r
2036 if (Base >= StrLen (String[1])) {\r
8f420676
ED
2037 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2038 Status = EFI_SUCCESS;\r
7936fb6a 2039 goto Done;\r
2040 }\r
2041\r
2042 Found = FALSE;\r
2043 StringPtr = String[1] + Base;\r
2044 Charset = String[0];\r
2045 while (*StringPtr != 0 && !Found) {\r
2046 Index = 0;\r
2047 while (Charset[Index] != 0) {\r
2048 if (*StringPtr >= Charset[Index] && *StringPtr <= Charset[Index + 1]) {\r
2049 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
2050 Found = TRUE;\r
2051 break;\r
2052 }\r
2053 } else {\r
2054 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
2055 Found = TRUE;\r
2056 break;\r
2057 }\r
2058 }\r
2059 //\r
2060 // Skip characters pair representing low-end of a range and high-end of a range\r
2061 //\r
2062 Index += 2;\r
2063 }\r
2064\r
2065 if (!Found) {\r
2066 StringPtr++;\r
2067 }\r
2068 }\r
2069\r
2070 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2071 Result->Value.u64 = StringPtr - String[1];\r
2072\r
2073Done:\r
676df92c 2074 if (String[0] != NULL) {\r
2075 FreePool (String[0]);\r
2076 }\r
2077 if (String[1] != NULL) {\r
2078 FreePool (String[1]);\r
8b0fc5c1 2079 }\r
7936fb6a 2080\r
2081 return Status;\r
2082}\r
2083\r
2084\r
2085/**\r
2086 Zero extend integer/boolean/date/time to UINT64 for comparing.\r
2087\r
2088 @param Value HII Value to be converted.\r
2089\r
2090**/\r
2091VOID\r
2092ExtendValueToU64 (\r
2093 IN EFI_HII_VALUE *Value\r
2094 )\r
2095{\r
2096 UINT64 Temp;\r
2097\r
2098 Temp = 0;\r
2099 switch (Value->Type) {\r
2100 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2101 Temp = Value->Value.u8;\r
2102 break;\r
2103\r
2104 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2105 Temp = Value->Value.u16;\r
2106 break;\r
2107\r
2108 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2109 Temp = Value->Value.u32;\r
2110 break;\r
2111\r
2112 case EFI_IFR_TYPE_BOOLEAN:\r
2113 Temp = Value->Value.b;\r
2114 break;\r
2115\r
2116 case EFI_IFR_TYPE_TIME:\r
2117 Temp = Value->Value.u32 & 0xffffff;\r
2118 break;\r
2119\r
2120 case EFI_IFR_TYPE_DATE:\r
2121 Temp = Value->Value.u32;\r
2122 break;\r
2123\r
2124 default:\r
2125 return;\r
2126 }\r
2127\r
2128 Value->Value.u64 = Temp;\r
2129}\r
2130\r
d63a9eb4
ED
2131/**\r
2132 Get UINT64 type value.\r
2133\r
2134 @param Value Input Hii value.\r
2135\r
2136 @retval UINT64 Return the UINT64 type value.\r
2137\r
2138**/\r
2139UINT64\r
2140HiiValueToUINT64 (\r
2141 IN EFI_HII_VALUE *Value\r
2142 )\r
2143{\r
2144 UINT64 RetVal;\r
2145\r
2146 RetVal = 0;\r
2147\r
2148 switch (Value->Type) {\r
2149 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2150 RetVal = Value->Value.u8;\r
2151 break;\r
2152\r
2153 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2154 RetVal = Value->Value.u16;\r
2155 break;\r
2156\r
2157 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2158 RetVal = Value->Value.u32;\r
2159 break;\r
2160\r
2161 case EFI_IFR_TYPE_BOOLEAN:\r
2162 RetVal = Value->Value.b;\r
2163 break;\r
2164\r
2165 case EFI_IFR_TYPE_DATE:\r
2166 RetVal = *(UINT64*) &Value->Value.date;\r
2167 break;\r
2168\r
2169 case EFI_IFR_TYPE_TIME:\r
2170 RetVal = (*(UINT64*) &Value->Value.time) & 0xffffff;\r
2171 break;\r
2172\r
2173 default:\r
2174 RetVal = Value->Value.u64;\r
2175 break;\r
2176 }\r
2177\r
2178 return RetVal;\r
2179}\r
7936fb6a 2180\r
2181/**\r
2182 Compare two Hii value.\r
2183\r
2184 @param Value1 Expression value to compare on left-hand.\r
2185 @param Value2 Expression value to compare on right-hand.\r
8f420676
ED
2186 @param Result Return value after compare.\r
2187 retval 0 Two operators equal.\r
2188 return Positive value if Value1 is greater than Value2.\r
2189 retval Negative value if Value1 is less than Value2.\r
7936fb6a 2190 @param HiiHandle Only required for string compare.\r
2191\r
8f420676
ED
2192 @retval other Could not perform compare on two values.\r
2193 @retval EFI_SUCCESS Compare the value success.\r
7936fb6a 2194\r
2195**/\r
8f420676 2196EFI_STATUS\r
7936fb6a 2197CompareHiiValue (\r
2198 IN EFI_HII_VALUE *Value1,\r
2199 IN EFI_HII_VALUE *Value2,\r
8f420676 2200 OUT INTN *Result,\r
7936fb6a 2201 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
2202 )\r
2203{\r
7936fb6a 2204 INT64 Temp64;\r
2205 CHAR16 *Str1;\r
2206 CHAR16 *Str2;\r
901ba0e7 2207 UINTN Len;\r
40578d09
ED
2208 UINT8 *Buf1;\r
2209 UINT16 Buf1Len;\r
2210 UINT8 *Buf2;\r
2211 UINT16 Buf2Len;\r
7936fb6a 2212\r
40578d09 2213 if (Value1->Type == EFI_IFR_TYPE_STRING && Value2->Type == EFI_IFR_TYPE_STRING) {\r
7936fb6a 2214 if (Value1->Value.string == 0 || Value2->Value.string == 0) {\r
2215 //\r
2216 // StringId 0 is reserved\r
2217 //\r
2218 return EFI_INVALID_PARAMETER;\r
2219 }\r
2220\r
2221 if (Value1->Value.string == Value2->Value.string) {\r
8f420676
ED
2222 *Result = 0;\r
2223 return EFI_SUCCESS;\r
7936fb6a 2224 }\r
2225\r
2226 Str1 = GetToken (Value1->Value.string, HiiHandle);\r
2227 if (Str1 == NULL) {\r
2228 //\r
2229 // String not found\r
2230 //\r
8f420676 2231 return EFI_NOT_FOUND;\r
7936fb6a 2232 }\r
2233\r
2234 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
2235 if (Str2 == NULL) {\r
f4113e1f 2236 FreePool (Str1);\r
8f420676 2237 return EFI_NOT_FOUND;\r
7936fb6a 2238 }\r
2239\r
8f420676 2240 *Result = StrCmp (Str1, Str2);\r
7936fb6a 2241\r
f4113e1f 2242 FreePool (Str1);\r
2243 FreePool (Str2);\r
7936fb6a 2244\r
8f420676 2245 return EFI_SUCCESS;\r
7936fb6a 2246 }\r
2247\r
40578d09
ED
2248 //\r
2249 // Take types(date, time, ref, buffer) as buffer\r
2250 //\r
2251 if (IsTypeInBuffer(Value1) && IsTypeInBuffer(Value2)) {\r
2252 Buf1 = GetBufferForValue(Value1);\r
2253 Buf1Len = GetLengthForValue(Value1);\r
2254 Buf2 = GetBufferForValue(Value2);\r
2255 Buf2Len = GetLengthForValue(Value2);\r
d1102dba 2256\r
40578d09
ED
2257 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
2258 *Result = CompareMem (Buf1, Buf2, Len);\r
2259 if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
901ba0e7
ED
2260 //\r
2261 // In this case, means base on samll number buffer, the data is same\r
2262 // So which value has more data, which value is bigger.\r
2263 //\r
40578d09 2264 *Result = Buf1Len > Buf2Len ? 1 : -1;\r
901ba0e7 2265 }\r
8f420676 2266 return EFI_SUCCESS;\r
d1102dba 2267 }\r
901ba0e7 2268\r
7936fb6a 2269 //\r
40578d09 2270 // Take types(integer, boolean) as integer\r
7936fb6a 2271 //\r
40578d09
ED
2272 if (IsTypeInUINT64(Value1) && IsTypeInUINT64(Value2)) {\r
2273 Temp64 = HiiValueToUINT64(Value1) - HiiValueToUINT64(Value2);\r
2274 if (Temp64 > 0) {\r
2275 *Result = 1;\r
2276 } else if (Temp64 < 0) {\r
2277 *Result = -1;\r
2278 } else {\r
2279 *Result = 0;\r
2280 }\r
2281\r
2282 return EFI_SUCCESS;\r
7936fb6a 2283 }\r
2284\r
40578d09 2285 return EFI_UNSUPPORTED;\r
7936fb6a 2286}\r
2287\r
cbf73e50 2288/**\r
2289 Check if current user has the privilege specified by the permissions GUID.\r
2290\r
2291 @param[in] Guid A GUID specifying setup access permissions.\r
2292\r
2293 @retval TRUE Current user has the privilege.\r
2294 @retval FALSE Current user does not have the privilege.\r
2295**/\r
2296BOOLEAN\r
2297CheckUserPrivilege (\r
2298 IN EFI_GUID *Guid\r
2299 )\r
2300{\r
2301 EFI_STATUS Status;\r
2302 EFI_USER_PROFILE_HANDLE UserProfileHandle;\r
2303 EFI_USER_INFO_HANDLE UserInfoHandle;\r
2304 EFI_USER_INFO *UserInfo;\r
2305 EFI_GUID *UserPermissionsGuid;\r
2306 UINTN UserInfoSize;\r
2307 UINTN AccessControlDataSize;\r
2308 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;\r
2309 UINTN RemainSize;\r
2310\r
2311 if (mUserManager == NULL) {\r
2312 Status = gBS->LocateProtocol (\r
2313 &gEfiUserManagerProtocolGuid,\r
2314 NULL,\r
2315 (VOID **) &mUserManager\r
2316 );\r
2317 if (EFI_ERROR (Status)) {\r
2318 ///\r
2319 /// If the system does not support user management, then it is assumed that\r
2320 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY\r
2321 /// op-code is always TRUE.\r
2322 ///\r
2323 return TRUE;\r
2324 }\r
2325 }\r
2326\r
2327 Status = mUserManager->Current (mUserManager, &UserProfileHandle);\r
2328 ASSERT_EFI_ERROR (Status);\r
2329\r
2330 ///\r
2331 /// Enumerate all user information of the current user profile\r
2332 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.\r
2333 ///\r
d1102dba 2334\r
cbf73e50 2335 for (UserInfoHandle = NULL;;) {\r
2336 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);\r
2337 if (EFI_ERROR (Status)) {\r
2338 break;\r
2339 }\r
2340\r
2341 UserInfoSize = 0;\r
2342 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
2343 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2344 continue;\r
2345 }\r
2346\r
2347 UserInfo = (EFI_USER_INFO *) AllocatePool (UserInfoSize);\r
2348 if (UserInfo == NULL) {\r
2349 break;\r
2350 }\r
2351\r
2352 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);\r
2353 if (EFI_ERROR (Status) ||\r
2354 UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD ||\r
2355 UserInfo->InfoSize <= sizeof (EFI_USER_INFO)) {\r
2356 FreePool (UserInfo);\r
2357 continue;\r
2358 }\r
2359\r
2360 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
2361 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
2362 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
3dd405be 2363 if (RemainSize < AccessControl->Size || AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
cbf73e50 2364 break;\r
2365 }\r
2366 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {\r
2367 ///\r
2368 /// Check if current user has the privilege specified by the permissions GUID.\r
2369 ///\r
2370\r
2371 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
2372 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);\r
2373 while (AccessControlDataSize >= sizeof (EFI_GUID)) {\r
2374 if (CompareGuid (Guid, UserPermissionsGuid)) {\r
2375 FreePool (UserInfo);\r
2376 return TRUE;\r
2377 }\r
2378 UserPermissionsGuid++;\r
2379 AccessControlDataSize -= sizeof (EFI_GUID);\r
2380 }\r
2381 }\r
2382 RemainSize -= AccessControl->Size;\r
2383 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
2384 }\r
2385\r
2386 FreePool (UserInfo);\r
2387 }\r
2388 return FALSE;\r
2389}\r
7936fb6a 2390\r
db40504e
ED
2391/**\r
2392 Get question value from the predefined formset.\r
2393\r
2394 @param DevicePath The driver's device path which produece the formset data.\r
2395 @param InputHiiHandle The hii handle associate with the formset data.\r
2396 @param FormSetGuid The formset guid which include the question.\r
2397 @param QuestionId The question id which need to get value from.\r
2398 @param Value The return data about question's value.\r
d1102dba 2399\r
db40504e
ED
2400 @retval TRUE Get the question value success.\r
2401 @retval FALSE Get the question value failed.\r
2402**/\r
d1102dba 2403BOOLEAN\r
db40504e
ED
2404GetQuestionValueFromForm (\r
2405 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
2406 IN EFI_HII_HANDLE InputHiiHandle,\r
2407 IN EFI_GUID *FormSetGuid,\r
2408 IN EFI_QUESTION_ID QuestionId,\r
2409 OUT EFI_HII_VALUE *Value\r
2410 )\r
2411{\r
2412 EFI_STATUS Status;\r
db40504e 2413 EFI_HII_HANDLE HiiHandle;\r
db40504e
ED
2414 FORM_BROWSER_STATEMENT *Question;\r
2415 FORM_BROWSER_FORMSET *FormSet;\r
2416 FORM_BROWSER_FORM *Form;\r
2417 BOOLEAN GetTheVal;\r
2418 LIST_ENTRY *Link;\r
2419\r
db40504e 2420 //\r
d1102dba
LG
2421 // The input parameter DevicePath or InputHiiHandle must have one valid input.\r
2422 //\r
2423 ASSERT ((DevicePath != NULL && InputHiiHandle == NULL) ||\r
db40504e
ED
2424 (DevicePath == NULL && InputHiiHandle != NULL) );\r
2425\r
2426 GetTheVal = TRUE;\r
db40504e
ED
2427 HiiHandle = NULL;\r
2428 Question = NULL;\r
2429 Form = NULL;\r
2430\r
2431 //\r
2432 // Get HiiHandle.\r
2433 //\r
2434 if (DevicePath != NULL) {\r
07d7dbae
ED
2435 HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
2436 if (HiiHandle == NULL) {\r
db40504e
ED
2437 return FALSE;\r
2438 }\r
db40504e
ED
2439 } else {\r
2440 HiiHandle = InputHiiHandle;\r
d1102dba 2441 }\r
db40504e
ED
2442 ASSERT (HiiHandle != NULL);\r
2443\r
2444 //\r
2445 // Get the formset data include this question.\r
2446 //\r
2447 FormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));\r
2448 ASSERT (FormSet != NULL);\r
7c6c064c 2449 Status = InitializeFormSet(HiiHandle, FormSetGuid, FormSet);\r
db40504e
ED
2450 if (EFI_ERROR (Status)) {\r
2451 GetTheVal = FALSE;\r
2452 goto Done;\r
2453 }\r
2454\r
2455 //\r
2456 // Base on the Question Id to get the question info.\r
d1102dba 2457 //\r
db40504e
ED
2458 Question = IdToQuestion(FormSet, NULL, QuestionId);\r
2459 if (Question == NULL) {\r
2460 GetTheVal = FALSE;\r
2461 goto Done;\r
2462 }\r
2463\r
2464 //\r
2465 // Search form in the formset scope\r
2466 //\r
2467 Link = GetFirstNode (&FormSet->FormListHead);\r
2468 while (!IsNull (&FormSet->FormListHead, Link)) {\r
2469 Form = FORM_BROWSER_FORM_FROM_LINK (Link);\r
2470\r
2471 Question = IdToQuestion2 (Form, QuestionId);\r
2472 if (Question != NULL) {\r
2473 break;\r
2474 }\r
2475\r
2476 Link = GetNextNode (&FormSet->FormListHead, Link);\r
2477 Form = NULL;\r
2478 }\r
2479 ASSERT (Form != NULL);\r
d1102dba 2480\r
db40504e
ED
2481 //\r
2482 // Get the question value.\r
2483 //\r
e6557276 2484 Status = GetQuestionValue(FormSet, Form, Question, GetSetValueWithEditBuffer);\r
db40504e
ED
2485 if (EFI_ERROR (Status)) {\r
2486 GetTheVal = FALSE;\r
2487 goto Done;\r
2488 }\r
2489\r
2490 CopyMem (Value, &Question->HiiValue, sizeof (EFI_HII_VALUE));\r
d1102dba 2491\r
db40504e
ED
2492Done:\r
2493 //\r
2494 // Clean the formset structure and restore the global parameter.\r
2495 //\r
2496 if (FormSet != NULL) {\r
2497 DestroyFormSet (FormSet);\r
2498 }\r
d1102dba 2499\r
db40504e
ED
2500 return GetTheVal;\r
2501}\r
2502\r
7936fb6a 2503/**\r
bc166db3 2504 Evaluate the result of a HII expression.\r
2505\r
2506 If Expression is NULL, then ASSERT.\r
7936fb6a 2507\r
2508 @param FormSet FormSet associated with this expression.\r
2509 @param Form Form associated with this expression.\r
2510 @param Expression Expression to be evaluated.\r
2511\r
2512 @retval EFI_SUCCESS The expression evaluated successfuly\r
2513 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId\r
2514 could not be found.\r
2515 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the\r
2516 stack.\r
2517 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack\r
2518 @retval EFI_INVALID_PARAMETER Syntax error with the Expression\r
2519\r
2520**/\r
2521EFI_STATUS\r
2522EvaluateExpression (\r
2523 IN FORM_BROWSER_FORMSET *FormSet,\r
2524 IN FORM_BROWSER_FORM *Form,\r
2525 IN OUT FORM_EXPRESSION *Expression\r
2526 )\r
2527{\r
2528 EFI_STATUS Status;\r
2529 LIST_ENTRY *Link;\r
2530 EXPRESSION_OPCODE *OpCode;\r
2531 FORM_BROWSER_STATEMENT *Question;\r
2532 FORM_BROWSER_STATEMENT *Question2;\r
2533 UINT16 Index;\r
2534 EFI_HII_VALUE Data1;\r
2535 EFI_HII_VALUE Data2;\r
2536 EFI_HII_VALUE Data3;\r
2537 FORM_EXPRESSION *RuleExpression;\r
2538 EFI_HII_VALUE *Value;\r
2539 INTN Result;\r
2540 CHAR16 *StrPtr;\r
2573712e 2541 CHAR16 *NameValue;\r
7936fb6a 2542 UINT32 TempValue;\r
2573712e
LG
2543 LIST_ENTRY *SubExpressionLink;\r
2544 FORM_EXPRESSION *SubExpression;\r
2545 UINTN StackOffset;\r
2546 UINTN TempLength;\r
2547 CHAR16 TempStr[5];\r
2548 UINT8 DigitUint8;\r
2549 UINT8 *TempBuffer;\r
2550 EFI_TIME EfiTime;\r
db40504e 2551 EFI_HII_VALUE QuestionVal;\r
33efdf51 2552 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
7936fb6a 2553\r
4e1005ec
ED
2554 StrPtr = NULL;\r
2555\r
7936fb6a 2556 //\r
2573712e 2557 // Save current stack offset.\r
7936fb6a 2558 //\r
2573712e 2559 StackOffset = SaveExpressionEvaluationStackOffset ();\r
7936fb6a 2560\r
bc166db3 2561 ASSERT (Expression != NULL);\r
7936fb6a 2562 Expression->Result.Type = EFI_IFR_TYPE_OTHER;\r
2563\r
2564 Link = GetFirstNode (&Expression->OpCodeListHead);\r
2565 while (!IsNull (&Expression->OpCodeListHead, Link)) {\r
2566 OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);\r
2567\r
2568 Link = GetNextNode (&Expression->OpCodeListHead, Link);\r
2569\r
2570 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));\r
2571 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));\r
2572 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));\r
2573\r
2574 Value = &Data3;\r
2575 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2576 Status = EFI_SUCCESS;\r
2577\r
2578 switch (OpCode->Operand) {\r
2579 //\r
2580 // Built-in functions\r
2581 //\r
2582 case EFI_IFR_EQ_ID_VAL_OP:\r
2583 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2584 if (Question == NULL) {\r
8f420676
ED
2585 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2586 break;\r
7936fb6a 2587 }\r
2588\r
8f420676
ED
2589 Status = CompareHiiValue (&Question->HiiValue, &OpCode->Value, &Result, NULL);\r
2590 if (Status == EFI_UNSUPPORTED) {\r
2591 Status = EFI_SUCCESS;\r
2592 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2593 break;\r
2594 }\r
2595\r
2596 if (EFI_ERROR (Status)) {\r
2573712e 2597 goto Done;\r
7936fb6a 2598 }\r
2599 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2600 break;\r
2601\r
2602 case EFI_IFR_EQ_ID_ID_OP:\r
2603 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2604 if (Question == NULL) {\r
8f420676
ED
2605 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2606 break;\r
7936fb6a 2607 }\r
2608\r
2609 Question2 = IdToQuestion (FormSet, Form, OpCode->QuestionId2);\r
2610 if (Question2 == NULL) {\r
8f420676
ED
2611 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2612 break;\r
7936fb6a 2613 }\r
2614\r
8f420676
ED
2615 Status = CompareHiiValue (&Question->HiiValue, &Question2->HiiValue, &Result, FormSet->HiiHandle);\r
2616 if (Status == EFI_UNSUPPORTED) {\r
2617 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2618 Status = EFI_SUCCESS;\r
2619 break;\r
2620 }\r
2621 if (EFI_ERROR (Status)) {\r
2573712e 2622 goto Done;\r
7936fb6a 2623 }\r
2624 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
2625 break;\r
2626\r
e8ef4283 2627 case EFI_IFR_EQ_ID_VAL_LIST_OP:\r
7936fb6a 2628 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2629 if (Question == NULL) {\r
8f420676
ED
2630 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2631 break;\r
7936fb6a 2632 }\r
2633\r
2634 Value->Value.b = FALSE;\r
2635 for (Index =0; Index < OpCode->ListLength; Index++) {\r
2636 if (Question->HiiValue.Value.u16 == OpCode->ValueList[Index]) {\r
2637 Value->Value.b = TRUE;\r
2638 break;\r
2639 }\r
2640 }\r
2641 break;\r
2642\r
2643 case EFI_IFR_DUP_OP:\r
2644 Status = PopExpression (Value);\r
2645 if (EFI_ERROR (Status)) {\r
2573712e 2646 goto Done;\r
7936fb6a 2647 }\r
2648\r
2649 Status = PushExpression (Value);\r
2650 break;\r
2651\r
2652 case EFI_IFR_QUESTION_REF1_OP:\r
2653 case EFI_IFR_THIS_OP:\r
2654 Question = IdToQuestion (FormSet, Form, OpCode->QuestionId);\r
2655 if (Question == NULL) {\r
2573712e
LG
2656 Status = EFI_NOT_FOUND;\r
2657 goto Done;\r
7936fb6a 2658 }\r
2659\r
2660 Value = &Question->HiiValue;\r
2661 break;\r
2662\r
cbf73e50 2663 case EFI_IFR_SECURITY_OP:\r
2664 Value->Value.b = CheckUserPrivilege (&OpCode->Guid);\r
2665 break;\r
2666\r
2573712e
LG
2667 case EFI_IFR_GET_OP:\r
2668 //\r
2669 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2670 //\r
2671 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2672 Value->Value.u8 = 0;\r
2673 if (OpCode->VarStorage != NULL) {\r
2674 switch (OpCode->VarStorage->Type) {\r
2675 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 2676 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
2677 //\r
2678 // Get value from Edit Buffer\r
2679 //\r
2680 Value->Type = OpCode->ValueType;\r
2681 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2682 break;\r
2683 case EFI_HII_VARSTORE_NAME_VALUE:\r
2684 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
2685 //\r
2686 // Get value from string except for STRING value.\r
2687 //\r
816a7110 2688 Status = GetValueByName (OpCode->VarStorage, OpCode->ValueName, &StrPtr, GetSetValueWithEditBuffer);\r
2573712e 2689 if (!EFI_ERROR (Status)) {\r
771ececd 2690 ASSERT (StrPtr != NULL);\r
2573712e
LG
2691 TempLength = StrLen (StrPtr);\r
2692 if (OpCode->ValueWidth >= ((TempLength + 1) / 2)) {\r
2693 Value->Type = OpCode->ValueType;\r
2694 TempBuffer = (UINT8 *) &Value->Value;\r
2695 ZeroMem (TempStr, sizeof (TempStr));\r
2696 for (Index = 0; Index < TempLength; Index ++) {\r
2697 TempStr[0] = StrPtr[TempLength - Index - 1];\r
2698 DigitUint8 = (UINT8) StrHexToUint64 (TempStr);\r
2699 if ((Index & 1) == 0) {\r
2700 TempBuffer [Index/2] = DigitUint8;\r
2701 } else {\r
771ececd 2702 TempBuffer [Index/2] = (UINT8) ((DigitUint8 << 4) + TempBuffer [Index/2]);\r
2573712e
LG
2703 }\r
2704 }\r
d1102dba 2705 }\r
2573712e
LG
2706 }\r
2707 }\r
2708 break;\r
2709 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
2710 //\r
2711 // Get value from variable.\r
2712 //\r
2713 TempLength = OpCode->ValueWidth;\r
2714 Value->Type = OpCode->ValueType;\r
2715 Status = gRT->GetVariable (\r
2716 OpCode->ValueName,\r
2717 &OpCode->VarStorage->Guid,\r
2718 NULL,\r
2719 &TempLength,\r
2720 &Value->Value\r
2721 );\r
2722 if (EFI_ERROR (Status)) {\r
2723 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2724 Value->Value.u8 = 0;\r
2725 }\r
cce6230f 2726 break;\r
2573712e
LG
2727 default:\r
2728 //\r
2729 // Not recognize storage.\r
2730 //\r
2731 Status = EFI_UNSUPPORTED;\r
2732 goto Done;\r
2733 }\r
2734 } else {\r
2735 //\r
2736 // For Time/Date Data\r
2737 //\r
2738 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
2739 //\r
2740 // Only support Data/Time data when storage doesn't exist.\r
2741 //\r
2742 Status = EFI_UNSUPPORTED;\r
2743 goto Done;\r
2744 }\r
2745 Status = gRT->GetTime (&EfiTime, NULL);\r
2746 if (!EFI_ERROR (Status)) {\r
2747 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
2748 switch (OpCode->VarStoreInfo.VarOffset) {\r
2749 case 0x00:\r
2750 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;\r
2751 Value->Value.u16 = EfiTime.Year;\r
2752 break;\r
2753 case 0x02:\r
2754 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2755 Value->Value.u8 = EfiTime.Month;\r
2756 break;\r
2757 case 0x03:\r
2758 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2759 Value->Value.u8 = EfiTime.Day;\r
2760 break;\r
2761 default:\r
2762 //\r
2763 // Invalid Date field.\r
2764 //\r
2765 Status = EFI_INVALID_PARAMETER;\r
2766 goto Done;\r
2767 }\r
2768 } else {\r
2769 switch (OpCode->VarStoreInfo.VarOffset) {\r
2770 case 0x00:\r
2771 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2772 Value->Value.u8 = EfiTime.Hour;\r
2773 break;\r
2774 case 0x01:\r
2775 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2776 Value->Value.u8 = EfiTime.Minute;\r
2777 break;\r
2778 case 0x02:\r
2779 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
2780 Value->Value.u8 = EfiTime.Second;\r
2781 break;\r
2782 default:\r
2783 //\r
2784 // Invalid Time field.\r
2785 //\r
2786 Status = EFI_INVALID_PARAMETER;\r
2787 goto Done;\r
2788 }\r
2789 }\r
2790 }\r
2791 }\r
2792\r
2793 break;\r
2794\r
7936fb6a 2795 case EFI_IFR_QUESTION_REF3_OP:\r
db40504e
ED
2796 //\r
2797 // EFI_IFR_QUESTION_REF3\r
2798 // Pop an expression from the expression stack\r
2799 //\r
2800 Status = PopExpression (Value);\r
2801 if (EFI_ERROR (Status)) {\r
2802 goto Done;\r
2803 }\r
d1102dba 2804\r
db40504e
ED
2805 //\r
2806 // Validate the expression value\r
2807 //\r
2808 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2809 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2810 break;\r
db40504e
ED
2811 }\r
2812\r
2813 if (OpCode->DevicePath != 0) {\r
80a047f0 2814 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
33efdf51 2815\r
80a047f0
ED
2816 StrPtr = GetToken (OpCode->DevicePath, FormSet->HiiHandle);\r
2817 if (StrPtr != NULL && mPathFromText != NULL) {\r
2818 DevicePath = mPathFromText->ConvertTextToDevicePath(StrPtr);\r
2819 if (DevicePath != NULL && GetQuestionValueFromForm(DevicePath, NULL, &OpCode->Guid, Value->Value.u16, &QuestionVal)) {\r
2820 Value = &QuestionVal;\r
2821 }\r
2822 if (DevicePath != NULL) {\r
2823 FreePool (DevicePath);\r
2824 }\r
33efdf51
ED
2825 }\r
2826\r
80a047f0
ED
2827 if (StrPtr != NULL) {\r
2828 FreePool (StrPtr);\r
7936fb6a 2829 }\r
39cde03c 2830 } else if (IsZeroGuid (&OpCode->Guid)) {\r
db40504e 2831 if (!GetQuestionValueFromForm(NULL, FormSet->HiiHandle, &OpCode->Guid, Value->Value.u16, &QuestionVal)){\r
8f420676
ED
2832 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2833 break;\r
db40504e 2834 }\r
8f420676 2835 Value = &QuestionVal;\r
db40504e 2836 } else {\r
7936fb6a 2837 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2838 if (Question == NULL) {\r
8f420676
ED
2839 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2840 break;\r
7936fb6a 2841 }\r
2842\r
2843 //\r
2844 // push the questions' value on to the expression stack\r
2845 //\r
2846 Value = &Question->HiiValue;\r
7936fb6a 2847 }\r
2848 break;\r
2849\r
2850 case EFI_IFR_RULE_REF_OP:\r
2851 //\r
2852 // Find expression for this rule\r
2853 //\r
2854 RuleExpression = RuleIdToExpression (Form, OpCode->RuleId);\r
2855 if (RuleExpression == NULL) {\r
8f420676
ED
2856 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2857 break;\r
7936fb6a 2858 }\r
2859\r
2860 //\r
2861 // Evaluate this rule expression\r
2862 //\r
2863 Status = EvaluateExpression (FormSet, Form, RuleExpression);\r
8f420676
ED
2864 if (EFI_ERROR (Status) || RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED) {\r
2865 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2866 break;\r
7936fb6a 2867 }\r
2868\r
2869 Value = &RuleExpression->Result;\r
2870 break;\r
2871\r
2872 case EFI_IFR_STRING_REF1_OP:\r
2873 Value->Type = EFI_IFR_TYPE_STRING;\r
2874 Value->Value.string = OpCode->Value.Value.string;\r
2875 break;\r
2876\r
2877 //\r
2878 // Constant\r
2879 //\r
2880 case EFI_IFR_TRUE_OP:\r
2881 case EFI_IFR_FALSE_OP:\r
2882 case EFI_IFR_ONE_OP:\r
2883 case EFI_IFR_ONES_OP:\r
2884 case EFI_IFR_UINT8_OP:\r
2885 case EFI_IFR_UINT16_OP:\r
2886 case EFI_IFR_UINT32_OP:\r
2887 case EFI_IFR_UINT64_OP:\r
2888 case EFI_IFR_UNDEFINED_OP:\r
2889 case EFI_IFR_VERSION_OP:\r
2890 case EFI_IFR_ZERO_OP:\r
2891 Value = &OpCode->Value;\r
2892 break;\r
2893\r
2894 //\r
2895 // unary-op\r
2896 //\r
2897 case EFI_IFR_LENGTH_OP:\r
2898 Status = PopExpression (Value);\r
2899 if (EFI_ERROR (Status)) {\r
2573712e 2900 goto Done;\r
7936fb6a 2901 }\r
40578d09 2902 if (Value->Type != EFI_IFR_TYPE_STRING && !IsTypeInBuffer (Value)) {\r
8f420676
ED
2903 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2904 break;\r
7936fb6a 2905 }\r
2906\r
901ba0e7
ED
2907 if (Value->Type == EFI_IFR_TYPE_STRING) {\r
2908 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
2909 if (StrPtr == NULL) {\r
2910 Status = EFI_INVALID_PARAMETER;\r
2911 goto Done;\r
2912 }\r
7936fb6a 2913\r
901ba0e7
ED
2914 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2915 Value->Value.u64 = StrLen (StrPtr);\r
2916 FreePool (StrPtr);\r
2917 } else {\r
2918 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
40578d09 2919 Value->Value.u64 = GetLengthForValue(Value);\r
901ba0e7
ED
2920 FreePool (Value->Buffer);\r
2921 }\r
7936fb6a 2922 break;\r
2923\r
2924 case EFI_IFR_NOT_OP:\r
2925 Status = PopExpression (Value);\r
2926 if (EFI_ERROR (Status)) {\r
2573712e 2927 goto Done;\r
7936fb6a 2928 }\r
2929 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
2930 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2931 break;\r
7936fb6a 2932 }\r
2933 Value->Value.b = (BOOLEAN) (!Value->Value.b);\r
2934 break;\r
2935\r
2936 case EFI_IFR_QUESTION_REF2_OP:\r
2937 //\r
2938 // Pop an expression from the expression stack\r
2939 //\r
2940 Status = PopExpression (Value);\r
2941 if (EFI_ERROR (Status)) {\r
2573712e 2942 goto Done;\r
7936fb6a 2943 }\r
2944\r
2945 //\r
2946 // Validate the expression value\r
2947 //\r
2948 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2949 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2950 break;\r
7936fb6a 2951 }\r
2952\r
2953 Question = IdToQuestion (FormSet, Form, Value->Value.u16);\r
2954 if (Question == NULL) {\r
8f420676
ED
2955 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2956 break;\r
7936fb6a 2957 }\r
2958\r
2959 Value = &Question->HiiValue;\r
2960 break;\r
2961\r
2962 case EFI_IFR_STRING_REF2_OP:\r
2963 //\r
2964 // Pop an expression from the expression stack\r
2965 //\r
2966 Status = PopExpression (Value);\r
2967 if (EFI_ERROR (Status)) {\r
2573712e 2968 goto Done;\r
7936fb6a 2969 }\r
2970\r
2971 //\r
2972 // Validate the expression value\r
2973 //\r
2974 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {\r
8f420676
ED
2975 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2976 break;\r
7936fb6a 2977 }\r
2978\r
2979 Value->Type = EFI_IFR_TYPE_STRING;\r
2980 StrPtr = GetToken (Value->Value.u16, FormSet->HiiHandle);\r
2981 if (StrPtr == NULL) {\r
2982 //\r
2983 // If String not exit, push an empty string\r
2984 //\r
2985 Value->Value.string = NewString (gEmptyString, FormSet->HiiHandle);\r
2986 } else {\r
2987 Index = (UINT16) Value->Value.u64;\r
2988 Value->Value.string = Index;\r
f4113e1f 2989 FreePool (StrPtr);\r
7936fb6a 2990 }\r
2991 break;\r
2992\r
2993 case EFI_IFR_TO_BOOLEAN_OP:\r
2994 //\r
2995 // Pop an expression from the expression stack\r
2996 //\r
2997 Status = PopExpression (Value);\r
2998 if (EFI_ERROR (Status)) {\r
2573712e 2999 goto Done;\r
7936fb6a 3000 }\r
3001\r
3002 //\r
3003 // Convert an expression to a Boolean\r
3004 //\r
3005 if (Value->Type <= EFI_IFR_TYPE_DATE) {\r
3006 //\r
3007 // When converting from an unsigned integer, zero will be converted to\r
3008 // FALSE and any other value will be converted to TRUE.\r
3009 //\r
40578d09 3010 Value->Value.b = (BOOLEAN) (HiiValueToUINT64(Value) != 0);\r
7936fb6a 3011\r
3012 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3013 } else if (Value->Type == EFI_IFR_TYPE_STRING) {\r
3014 //\r
3015 // When converting from a string, if case-insensitive compare\r
3016 // with "true" is True, then push True. If a case-insensitive compare\r
d1102dba 3017 // with "false" is True, then push False. Otherwise, push Undefined.\r
7936fb6a 3018 //\r
3019 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
3020 if (StrPtr == NULL) {\r
2573712e
LG
3021 Status = EFI_INVALID_PARAMETER;\r
3022 goto Done;\r
7936fb6a 3023 }\r
d1102dba 3024\r
39099cbd
ED
3025 IfrStrToUpper (StrPtr);\r
3026 if (StrCmp (StrPtr, L"TRUE") == 0){\r
7936fb6a 3027 Value->Value.b = TRUE;\r
8f420676 3028 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 3029 } else if (StrCmp (StrPtr, L"FALSE") == 0) {\r
7936fb6a 3030 Value->Value.b = FALSE;\r
8f420676 3031 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
39099cbd 3032 } else {\r
8f420676 3033 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
7936fb6a 3034 }\r
f4113e1f 3035 FreePool (StrPtr);\r
901ba0e7
ED
3036 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {\r
3037 //\r
d1102dba
LG
3038 // When converting from a buffer, if the buffer is all zeroes,\r
3039 // then push False. Otherwise push True.\r
901ba0e7
ED
3040 //\r
3041 for (Index =0; Index < Value->BufferLen; Index ++) {\r
d1102dba 3042 if (Value->Buffer[Index] != 0) {\r
901ba0e7
ED
3043 break;\r
3044 }\r
3045 }\r
3046\r
3047 if (Index >= Value->BufferLen) {\r
3048 Value->Value.b = FALSE;\r
3049 } else {\r
3050 Value->Value.b = TRUE;\r
3051 }\r
3052 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3053 FreePool (Value->Buffer);\r
7936fb6a 3054 }\r
3055 break;\r
3056\r
3057 case EFI_IFR_TO_STRING_OP:\r
3058 Status = IfrToString (FormSet, OpCode->Format, Value);\r
3059 break;\r
3060\r
3061 case EFI_IFR_TO_UINT_OP:\r
3062 Status = IfrToUint (FormSet, Value);\r
3063 break;\r
3064\r
3065 case EFI_IFR_TO_LOWER_OP:\r
3066 case EFI_IFR_TO_UPPER_OP:\r
3067 Status = InitializeUnicodeCollationProtocol ();\r
3068 if (EFI_ERROR (Status)) {\r
2573712e 3069 goto Done;\r
7936fb6a 3070 }\r
3071\r
3072 Status = PopExpression (Value);\r
3073 if (EFI_ERROR (Status)) {\r
2573712e 3074 goto Done;\r
7936fb6a 3075 }\r
3076\r
3077 if (Value->Type != EFI_IFR_TYPE_STRING) {\r
8f420676
ED
3078 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3079 break;\r
7936fb6a 3080 }\r
3081\r
3082 StrPtr = GetToken (Value->Value.string, FormSet->HiiHandle);\r
3083 if (StrPtr == NULL) {\r
2573712e
LG
3084 Status = EFI_NOT_FOUND;\r
3085 goto Done;\r
7936fb6a 3086 }\r
3087\r
3088 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {\r
3089 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);\r
3090 } else {\r
3091 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);\r
3092 }\r
3093 Value->Value.string = NewString (StrPtr, FormSet->HiiHandle);\r
f4113e1f 3094 FreePool (StrPtr);\r
7936fb6a 3095 break;\r
3096\r
3097 case EFI_IFR_BITWISE_NOT_OP:\r
3098 //\r
3099 // Pop an expression from the expression stack\r
3100 //\r
3101 Status = PopExpression (Value);\r
3102 if (EFI_ERROR (Status)) {\r
2573712e 3103 goto Done;\r
7936fb6a 3104 }\r
3105 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
3106 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3107 break;\r
7936fb6a 3108 }\r
3109\r
3110 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
40578d09 3111 Value->Value.u64 = ~ HiiValueToUINT64(Value);\r
7936fb6a 3112 break;\r
3113\r
2573712e
LG
3114 case EFI_IFR_SET_OP:\r
3115 //\r
3116 // Pop an expression from the expression stack\r
3117 //\r
3118 Status = PopExpression (Value);\r
3119 if (EFI_ERROR (Status)) {\r
3120 goto Done;\r
3121 }\r
3122 Data1.Type = EFI_IFR_TYPE_BOOLEAN;\r
3123 Data1.Value.b = FALSE;\r
3124 //\r
3125 // Set value to var storage buffer\r
3126 //\r
3127 if (OpCode->VarStorage != NULL) {\r
3128 switch (OpCode->VarStorage->Type) {\r
3129 case EFI_HII_VARSTORE_BUFFER:\r
cce6230f 3130 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:\r
2573712e
LG
3131 CopyMem (OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, &Value->Value, OpCode->ValueWidth);\r
3132 Data1.Value.b = TRUE;\r
3133 break;\r
3134 case EFI_HII_VARSTORE_NAME_VALUE:\r
3135 if (OpCode->ValueType != EFI_IFR_TYPE_STRING) {\r
3136 NameValue = AllocateZeroPool ((OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16));\r
bef778c1 3137 ASSERT (NameValue != NULL);\r
2573712e
LG
3138 //\r
3139 // Convert Buffer to Hex String\r
3140 //\r
3141 TempBuffer = (UINT8 *) &Value->Value + OpCode->ValueWidth - 1;\r
3142 StrPtr = NameValue;\r
3143 for (Index = 0; Index < OpCode->ValueWidth; Index ++, TempBuffer --) {\r
9f4048f7
HW
3144 UnicodeValueToStringS (\r
3145 StrPtr,\r
3146 (OpCode->ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),\r
3147 PREFIX_ZERO | RADIX_HEX,\r
3148 *TempBuffer,\r
3149 2\r
3150 );\r
3151 StrPtr += StrnLenS (StrPtr, OpCode->ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));\r
2573712e 3152 }\r
7c6c064c 3153 Status = SetValueByName (OpCode->VarStorage, OpCode->ValueName, NameValue, GetSetValueWithEditBuffer, NULL);\r
2573712e
LG
3154 FreePool (NameValue);\r
3155 if (!EFI_ERROR (Status)) {\r
3156 Data1.Value.b = TRUE;\r
3157 }\r
3158 }\r
3159 break;\r
3160 case EFI_HII_VARSTORE_EFI_VARIABLE:\r
3161 Status = gRT->SetVariable (\r
3162 OpCode->ValueName,\r
3163 &OpCode->VarStorage->Guid,\r
3164 OpCode->VarStorage->Attributes,\r
3165 OpCode->ValueWidth,\r
3166 &Value->Value\r
3167 );\r
3168 if (!EFI_ERROR (Status)) {\r
3169 Data1.Value.b = TRUE;\r
3170 }\r
3171 break;\r
3172 default:\r
3173 //\r
3174 // Not recognize storage.\r
3175 //\r
3176 Status = EFI_UNSUPPORTED;\r
3177 goto Done;\r
2573712e
LG
3178 }\r
3179 } else {\r
3180 //\r
3181 // For Time/Date Data\r
3182 //\r
3183 if (OpCode->ValueType != EFI_IFR_TYPE_DATE && OpCode->ValueType != EFI_IFR_TYPE_TIME) {\r
3184 //\r
3185 // Only support Data/Time data when storage doesn't exist.\r
3186 //\r
3187 Status = EFI_UNSUPPORTED;\r
3188 goto Done;\r
3189 }\r
3190 Status = gRT->GetTime (&EfiTime, NULL);\r
3191 if (!EFI_ERROR (Status)) {\r
3192 if (OpCode->ValueType == EFI_IFR_TYPE_DATE) {\r
3193 switch (OpCode->VarStoreInfo.VarOffset) {\r
3194 case 0x00:\r
3195 EfiTime.Year = Value->Value.u16;\r
3196 break;\r
3197 case 0x02:\r
3198 EfiTime.Month = Value->Value.u8;\r
3199 break;\r
3200 case 0x03:\r
3201 EfiTime.Day = Value->Value.u8;\r
3202 break;\r
3203 default:\r
3204 //\r
3205 // Invalid Date field.\r
3206 //\r
3207 Status = EFI_INVALID_PARAMETER;\r
3208 goto Done;\r
3209 }\r
3210 } else {\r
3211 switch (OpCode->VarStoreInfo.VarOffset) {\r
3212 case 0x00:\r
3213 EfiTime.Hour = Value->Value.u8;\r
3214 break;\r
3215 case 0x01:\r
3216 EfiTime.Minute = Value->Value.u8;\r
3217 break;\r
3218 case 0x02:\r
3219 EfiTime.Second = Value->Value.u8;\r
3220 break;\r
3221 default:\r
3222 //\r
3223 // Invalid Time field.\r
3224 //\r
3225 Status = EFI_INVALID_PARAMETER;\r
3226 goto Done;\r
3227 }\r
3228 }\r
3229 Status = gRT->SetTime (&EfiTime);\r
3230 if (!EFI_ERROR (Status)) {\r
3231 Data1.Value.b = TRUE;\r
3232 }\r
3233 }\r
3234 }\r
3235 Value = &Data1;\r
3236 break;\r
3237\r
7936fb6a 3238 //\r
3239 // binary-op\r
3240 //\r
3241 case EFI_IFR_ADD_OP:\r
3242 case EFI_IFR_SUBTRACT_OP:\r
3243 case EFI_IFR_MULTIPLY_OP:\r
3244 case EFI_IFR_DIVIDE_OP:\r
3245 case EFI_IFR_MODULO_OP:\r
3246 case EFI_IFR_BITWISE_AND_OP:\r
3247 case EFI_IFR_BITWISE_OR_OP:\r
3248 case EFI_IFR_SHIFT_LEFT_OP:\r
3249 case EFI_IFR_SHIFT_RIGHT_OP:\r
3250 //\r
3251 // Pop an expression from the expression stack\r
3252 //\r
3253 Status = PopExpression (&Data2);\r
3254 if (EFI_ERROR (Status)) {\r
2573712e 3255 goto Done;\r
7936fb6a 3256 }\r
7936fb6a 3257\r
3258 //\r
3259 // Pop another expression from the expression stack\r
3260 //\r
3261 Status = PopExpression (&Data1);\r
3262 if (EFI_ERROR (Status)) {\r
2573712e 3263 goto Done;\r
7936fb6a 3264 }\r
8f420676
ED
3265\r
3266 if (Data2.Type > EFI_IFR_TYPE_DATE) {\r
3267 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3268 break;\r
3269 }\r
3270\r
3271\r
7936fb6a 3272 if (Data1.Type > EFI_IFR_TYPE_DATE) {\r
8f420676
ED
3273 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3274 break;\r
7936fb6a 3275 }\r
3276\r
3277 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
3278\r
3279 switch (OpCode->Operand) {\r
3280 case EFI_IFR_ADD_OP:\r
40578d09 3281 Value->Value.u64 = HiiValueToUINT64(&Data1) + HiiValueToUINT64(&Data2);\r
7936fb6a 3282 break;\r
3283\r
3284 case EFI_IFR_SUBTRACT_OP:\r
40578d09 3285 Value->Value.u64 = HiiValueToUINT64(&Data1) - HiiValueToUINT64(&Data2);\r
7936fb6a 3286 break;\r
3287\r
3288 case EFI_IFR_MULTIPLY_OP:\r
40578d09 3289 Value->Value.u64 = MultU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
7936fb6a 3290 break;\r
3291\r
3292 case EFI_IFR_DIVIDE_OP:\r
40578d09 3293 Value->Value.u64 = DivU64x32 (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2));\r
7936fb6a 3294 break;\r
3295\r
3296 case EFI_IFR_MODULO_OP:\r
40578d09 3297 DivU64x32Remainder (HiiValueToUINT64(&Data1), (UINT32) HiiValueToUINT64(&Data2), &TempValue);\r
7936fb6a 3298 Value->Value.u64 = TempValue;\r
3299 break;\r
3300\r
3301 case EFI_IFR_BITWISE_AND_OP:\r
40578d09 3302 Value->Value.u64 = HiiValueToUINT64(&Data1) & HiiValueToUINT64(&Data2);\r
7936fb6a 3303 break;\r
3304\r
3305 case EFI_IFR_BITWISE_OR_OP:\r
40578d09 3306 Value->Value.u64 = HiiValueToUINT64(&Data1) | HiiValueToUINT64(&Data2);\r
7936fb6a 3307 break;\r
3308\r
3309 case EFI_IFR_SHIFT_LEFT_OP:\r
40578d09 3310 Value->Value.u64 = LShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
7936fb6a 3311 break;\r
3312\r
3313 case EFI_IFR_SHIFT_RIGHT_OP:\r
40578d09 3314 Value->Value.u64 = RShiftU64 (HiiValueToUINT64(&Data1), (UINTN) HiiValueToUINT64(&Data2));\r
7936fb6a 3315 break;\r
3316\r
3317 default:\r
3318 break;\r
3319 }\r
3320 break;\r
3321\r
3322 case EFI_IFR_AND_OP:\r
3323 case EFI_IFR_OR_OP:\r
3324 //\r
3325 // Two Boolean operator\r
3326 //\r
3327 Status = PopExpression (&Data2);\r
3328 if (EFI_ERROR (Status)) {\r
2573712e 3329 goto Done;\r
7936fb6a 3330 }\r
7936fb6a 3331\r
3332 //\r
3333 // Pop another expression from the expression stack\r
3334 //\r
3335 Status = PopExpression (&Data1);\r
3336 if (EFI_ERROR (Status)) {\r
2573712e 3337 goto Done;\r
7936fb6a 3338 }\r
8f420676
ED
3339\r
3340 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3341 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3342 break;\r
3343 }\r
3344\r
7936fb6a 3345 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3346 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3347 break;\r
7936fb6a 3348 }\r
3349\r
3350 if (OpCode->Operand == EFI_IFR_AND_OP) {\r
3351 Value->Value.b = (BOOLEAN) (Data1.Value.b && Data2.Value.b);\r
3352 } else {\r
3353 Value->Value.b = (BOOLEAN) (Data1.Value.b || Data2.Value.b);\r
3354 }\r
3355 break;\r
3356\r
3357 case EFI_IFR_EQUAL_OP:\r
3358 case EFI_IFR_NOT_EQUAL_OP:\r
3359 case EFI_IFR_GREATER_EQUAL_OP:\r
3360 case EFI_IFR_GREATER_THAN_OP:\r
3361 case EFI_IFR_LESS_EQUAL_OP:\r
3362 case EFI_IFR_LESS_THAN_OP:\r
3363 //\r
3364 // Compare two integer, string, boolean or date/time\r
3365 //\r
3366 Status = PopExpression (&Data2);\r
3367 if (EFI_ERROR (Status)) {\r
2573712e 3368 goto Done;\r
7936fb6a 3369 }\r
7936fb6a 3370\r
3371 //\r
3372 // Pop another expression from the expression stack\r
3373 //\r
3374 Status = PopExpression (&Data1);\r
3375 if (EFI_ERROR (Status)) {\r
2573712e 3376 goto Done;\r
7936fb6a 3377 }\r
3378\r
d1102dba
LG
3379 if (Data2.Type > EFI_IFR_TYPE_BOOLEAN &&\r
3380 Data2.Type != EFI_IFR_TYPE_STRING &&\r
40578d09 3381 !IsTypeInBuffer(&Data2)) {\r
8f420676
ED
3382 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3383 break;\r
3384 }\r
3385\r
d1102dba
LG
3386 if (Data1.Type > EFI_IFR_TYPE_BOOLEAN &&\r
3387 Data1.Type != EFI_IFR_TYPE_STRING &&\r
40578d09 3388 !IsTypeInBuffer(&Data1)) {\r
8f420676
ED
3389 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3390 break;\r
3391 }\r
3392\r
3393 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);\r
901ba0e7
ED
3394 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {\r
3395 FreePool (Data1.Buffer);\r
40578d09
ED
3396 }\r
3397 if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
901ba0e7
ED
3398 FreePool (Data2.Buffer);\r
3399 }\r
d1102dba 3400\r
8f420676
ED
3401 if (Status == EFI_UNSUPPORTED) {\r
3402 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3403 Status = EFI_SUCCESS;\r
3404 break;\r
3405 }\r
3406\r
3407 if (EFI_ERROR (Status)) {\r
2573712e 3408 goto Done;\r
7936fb6a 3409 }\r
3410\r
3411 switch (OpCode->Operand) {\r
3412 case EFI_IFR_EQUAL_OP:\r
3413 Value->Value.b = (BOOLEAN) ((Result == 0) ? TRUE : FALSE);\r
3414 break;\r
3415\r
3416 case EFI_IFR_NOT_EQUAL_OP:\r
7b9b2b92 3417 Value->Value.b = (BOOLEAN) ((Result != 0) ? TRUE : FALSE);\r
7936fb6a 3418 break;\r
3419\r
3420 case EFI_IFR_GREATER_EQUAL_OP:\r
3421 Value->Value.b = (BOOLEAN) ((Result >= 0) ? TRUE : FALSE);\r
3422 break;\r
3423\r
3424 case EFI_IFR_GREATER_THAN_OP:\r
3425 Value->Value.b = (BOOLEAN) ((Result > 0) ? TRUE : FALSE);\r
3426 break;\r
3427\r
3428 case EFI_IFR_LESS_EQUAL_OP:\r
3429 Value->Value.b = (BOOLEAN) ((Result <= 0) ? TRUE : FALSE);\r
3430 break;\r
3431\r
3432 case EFI_IFR_LESS_THAN_OP:\r
3433 Value->Value.b = (BOOLEAN) ((Result < 0) ? TRUE : FALSE);\r
3434 break;\r
3435\r
3436 default:\r
3437 break;\r
3438 }\r
3439 break;\r
3440\r
3441 case EFI_IFR_MATCH_OP:\r
20258293
ED
3442 Status = InitializeUnicodeCollationProtocol ();\r
3443 if (EFI_ERROR (Status)) {\r
3444 goto Done;\r
3445 }\r
d1102dba 3446\r
7936fb6a 3447 Status = IfrMatch (FormSet, Value);\r
3448 break;\r
3449\r
9bd22b08
ED
3450 case EFI_IFR_MATCH2_OP:\r
3451 Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);\r
3452 break;\r
3453\r
7936fb6a 3454 case EFI_IFR_CATENATE_OP:\r
3455 Status = IfrCatenate (FormSet, Value);\r
3456 break;\r
3457\r
3458 //\r
3459 // ternary-op\r
3460 //\r
3461 case EFI_IFR_CONDITIONAL_OP:\r
3462 //\r
3463 // Pop third expression from the expression stack\r
3464 //\r
3465 Status = PopExpression (&Data3);\r
3466 if (EFI_ERROR (Status)) {\r
2573712e 3467 goto Done;\r
7936fb6a 3468 }\r
3469\r
3470 //\r
3471 // Pop second expression from the expression stack\r
3472 //\r
3473 Status = PopExpression (&Data2);\r
3474 if (EFI_ERROR (Status)) {\r
2573712e 3475 goto Done;\r
7936fb6a 3476 }\r
3477\r
3478 //\r
3479 // Pop first expression from the expression stack\r
3480 //\r
3481 Status = PopExpression (&Data1);\r
3482 if (EFI_ERROR (Status)) {\r
2573712e 3483 goto Done;\r
7936fb6a 3484 }\r
3485 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
8f420676
ED
3486 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3487 break;\r
7936fb6a 3488 }\r
3489\r
3490 if (Data1.Value.b) {\r
3491 Value = &Data3;\r
3492 } else {\r
3493 Value = &Data2;\r
3494 }\r
3495 break;\r
3496\r
3497 case EFI_IFR_FIND_OP:\r
3498 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3499 break;\r
3500\r
3501 case EFI_IFR_MID_OP:\r
3502 Status = IfrMid (FormSet, Value);\r
3503 break;\r
3504\r
3505 case EFI_IFR_TOKEN_OP:\r
3506 Status = IfrToken (FormSet, Value);\r
3507 break;\r
3508\r
3509 case EFI_IFR_SPAN_OP:\r
3510 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3511 break;\r
3512\r
2573712e
LG
3513 case EFI_IFR_MAP_OP:\r
3514 //\r
3515 // Pop the check value\r
3516 //\r
3517 Status = PopExpression (&Data1);\r
3518 if (EFI_ERROR (Status)) {\r
3519 goto Done;\r
3520 }\r
3521 //\r
3522 // Check MapExpression list is valid.\r
3523 //\r
3524 if (OpCode->MapExpressionList.ForwardLink == NULL) {\r
3525 Status = EFI_INVALID_PARAMETER;\r
3526 goto Done;\r
3527 }\r
3528 //\r
3529 // Go through map expression list.\r
3530 //\r
3531 SubExpressionLink = GetFirstNode(&OpCode->MapExpressionList);\r
3532 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3533 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3534 //\r
3535 // Evaluate the first expression in this pair.\r
3536 //\r
3537 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3538 if (EFI_ERROR (Status)) {\r
3539 goto Done;\r
3540 }\r
3541 //\r
3542 // Compare the expression value with current value\r
3543 //\r
8f420676 3544 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {\r
2573712e
LG
3545 //\r
3546 // Try get the map value.\r
3547 //\r
3548 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3549 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3550 Status = EFI_INVALID_PARAMETER;\r
3551 goto Done;\r
3552 }\r
3553 SubExpression = FORM_EXPRESSION_FROM_LINK (SubExpressionLink);\r
3554 Status = EvaluateExpression (FormSet, Form, SubExpression);\r
3555 if (EFI_ERROR (Status)) {\r
3556 goto Done;\r
3557 }\r
3558 Value = &SubExpression->Result;\r
3559 break;\r
3560 }\r
3561 //\r
3562 // Skip the second expression on this pair.\r
3563 //\r
3564 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3565 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3566 Status = EFI_INVALID_PARAMETER;\r
3567 goto Done;\r
3568 }\r
3569 //\r
3570 // Goto the first expression on next pair.\r
3571 //\r
3572 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3573 }\r
3574\r
3575 //\r
3576 // No map value is found.\r
3577 //\r
3578 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3579 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3580 Value->Value.u8 = 0;\r
3581 }\r
3582 break;\r
3583\r
7936fb6a 3584 default:\r
3585 break;\r
3586 }\r
8f420676 3587 if (EFI_ERROR (Status) || Value->Type == EFI_IFR_TYPE_UNDEFINED) {\r
2573712e 3588 goto Done;\r
7936fb6a 3589 }\r
3590\r
3591 Status = PushExpression (Value);\r
3592 if (EFI_ERROR (Status)) {\r
2573712e 3593 goto Done;\r
7936fb6a 3594 }\r
3595 }\r
3596\r
3597 //\r
3598 // Pop the final result from expression stack\r
3599 //\r
3600 Value = &Data1;\r
3601 Status = PopExpression (Value);\r
3602 if (EFI_ERROR (Status)) {\r
2573712e 3603 goto Done;\r
7936fb6a 3604 }\r
3605\r
3606 //\r
3607 // After evaluating an expression, there should be only one value left on the expression stack\r
3608 //\r
3609 if (PopExpression (Value) != EFI_ACCESS_DENIED) {\r
2573712e 3610 Status = EFI_INVALID_PARAMETER;\r
7936fb6a 3611 }\r
3612\r
2573712e
LG
3613Done:\r
3614 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3615 if (!EFI_ERROR (Status)) {\r
3616 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3617 }\r
7936fb6a 3618\r
2573712e 3619 return Status;\r
7936fb6a 3620}\r
31585af4 3621\r
e6106e89
ED
3622/**\r
3623 Check whether the result is TRUE or FALSE.\r
d1102dba 3624\r
e6106e89
ED
3625 For the EFI_HII_VALUE value type is numeric, return TRUE if the\r
3626 value is not 0.\r
3627\r
3628 @param Result Input the result data.\r
3629\r
3630 @retval TRUE The result is TRUE.\r
3631 @retval FALSE The result is FALSE.\r
3632\r
3633**/\r
3634BOOLEAN\r
3635IsTrue (\r
3636 IN EFI_HII_VALUE *Result\r
3637 )\r
3638{\r
3639 switch (Result->Type) {\r
3640 case EFI_IFR_TYPE_BOOLEAN:\r
3641 return Result->Value.b;\r
3642\r
3643 case EFI_IFR_TYPE_NUM_SIZE_8:\r
4f467fd3 3644 return (BOOLEAN)(Result->Value.u8 != 0);\r
e6106e89
ED
3645\r
3646 case EFI_IFR_TYPE_NUM_SIZE_16:\r
4f467fd3 3647 return (BOOLEAN)(Result->Value.u16 != 0);\r
e6106e89
ED
3648\r
3649 case EFI_IFR_TYPE_NUM_SIZE_32:\r
4f467fd3 3650 return (BOOLEAN)(Result->Value.u32 != 0);\r
e6106e89
ED
3651\r
3652 case EFI_IFR_TYPE_NUM_SIZE_64:\r
4f467fd3 3653 return (BOOLEAN)(Result->Value.u64 != 0);\r
e6106e89
ED
3654\r
3655 default:\r
3656 return FALSE;\r
3657 }\r
3658}\r
3659\r
31585af4 3660/**\r
d1102dba
LG
3661 Return the result of the expression list. Check the expression list and\r
3662 return the highest priority express result.\r
31585af4
ED
3663 Priority: DisableIf > SuppressIf > GrayOutIf > FALSE\r
3664\r
3665 @param ExpList The input expression list.\r
3666 @param Evaluate Whether need to evaluate the expression first.\r
3667 @param FormSet FormSet associated with this expression.\r
d1102dba 3668 @param Form Form associated with this expression.\r
31585af4 3669\r
d1102dba 3670 @retval EXPRESS_RESULT Return the higher priority express result.\r
31585af4
ED
3671 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3672\r
3673**/\r
d1102dba 3674EXPRESS_RESULT\r
31585af4
ED
3675EvaluateExpressionList (\r
3676 IN FORM_EXPRESSION_LIST *ExpList,\r
3677 IN BOOLEAN Evaluate,\r
3678 IN FORM_BROWSER_FORMSET *FormSet, OPTIONAL\r
3679 IN FORM_BROWSER_FORM *Form OPTIONAL\r
3680 )\r
3681{\r
3682 UINTN Index;\r
3683 EXPRESS_RESULT ReturnVal;\r
3684 EXPRESS_RESULT CompareOne;\r
3685 EFI_STATUS Status;\r
3686\r
3687 if (ExpList == NULL) {\r
3688 return ExpressFalse;\r
3689 }\r
3690\r
3691 ASSERT(ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3692 Index = 0;\r
3693\r
3694 //\r
3695 // Check whether need to evaluate the expression first.\r
3696 //\r
d1102dba 3697 if (Evaluate) {\r
31585af4
ED
3698 while (ExpList->Count > Index) {\r
3699 Status = EvaluateExpression (FormSet, Form, ExpList->Expression[Index++]);\r
3700 if (EFI_ERROR (Status)) {\r
3701 return ExpressFalse;\r
3702 }\r
3703 }\r
3704 }\r
3705\r
3706 //\r
3707 // Run the list of expressions.\r
3708 //\r
3709 ReturnVal = ExpressFalse;\r
3710 for (Index = 0; Index < ExpList->Count; Index++) {\r
e6106e89 3711 if (IsTrue (&ExpList->Expression[Index]->Result)) {\r
31585af4
ED
3712 switch (ExpList->Expression[Index]->Type) {\r
3713 case EFI_HII_EXPRESSION_SUPPRESS_IF:\r
3714 CompareOne = ExpressSuppress;\r
3715 break;\r
3716\r
3717 case EFI_HII_EXPRESSION_GRAY_OUT_IF:\r
3718 CompareOne = ExpressGrayOut;\r
3719 break;\r
3720\r
3721 case EFI_HII_EXPRESSION_DISABLE_IF:\r
3722 CompareOne = ExpressDisable;\r
3723 break;\r
3724\r
3725 default:\r
d1102dba 3726 return ExpressFalse;\r
31585af4
ED
3727 }\r
3728\r
3729 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3730 }\r
3731 }\r
d1102dba 3732\r
31585af4
ED
3733 return ReturnVal;\r
3734}\r