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