]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/SetupBrowserDxe/Expression.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / SetupBrowserDxe / Expression.c
... / ...
CommitLineData
1/** @file\r
2Utility functions for expression evaluation.\r
3\r
4Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "Setup.h"\r
10\r
11//\r
12// Global stack used to evaluate boolean expresions\r
13//\r
14EFI_HII_VALUE *mOpCodeScopeStack = NULL;\r
15EFI_HII_VALUE *mOpCodeScopeStackEnd = NULL;\r
16EFI_HII_VALUE *mOpCodeScopeStackPointer = NULL;\r
17\r
18EFI_HII_VALUE *mExpressionEvaluationStack = NULL;\r
19EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;\r
20EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;\r
21UINTN mExpressionEvaluationStackOffset = 0;\r
22\r
23EFI_HII_VALUE *mCurrentExpressionStack = NULL;\r
24EFI_HII_VALUE *mCurrentExpressionEnd = NULL;\r
25EFI_HII_VALUE *mCurrentExpressionPointer = NULL;\r
26\r
27EFI_HII_VALUE *mMapExpressionListStack = NULL;\r
28EFI_HII_VALUE *mMapExpressionListEnd = NULL;\r
29EFI_HII_VALUE *mMapExpressionListPointer = NULL;\r
30\r
31FORM_EXPRESSION **mFormExpressionStack = NULL;\r
32FORM_EXPRESSION **mFormExpressionEnd = NULL;\r
33FORM_EXPRESSION **mFormExpressionPointer = NULL;\r
34\r
35FORM_EXPRESSION **mStatementExpressionStack = NULL;\r
36FORM_EXPRESSION **mStatementExpressionEnd = NULL;\r
37FORM_EXPRESSION **mStatementExpressionPointer = NULL;\r
38\r
39FORM_EXPRESSION **mOptionExpressionStack = NULL;\r
40FORM_EXPRESSION **mOptionExpressionEnd = NULL;\r
41FORM_EXPRESSION **mOptionExpressionPointer = NULL;\r
42\r
43//\r
44// Unicode collation protocol interface\r
45//\r
46EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;\r
47EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;\r
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
70 UINTN Size;\r
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
96 FreePool (*Stack);\r
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
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
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
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
148 if (Data->Type == EFI_IFR_TYPE_BUFFER) {\r
149 (*StackPtr)->Buffer = AllocateCopyPool (Data->BufferLen, Data->Buffer);\r
150 ASSERT ((*StackPtr)->Buffer != NULL);\r
151 }\r
152\r
153 *StackPtr = *StackPtr + 1;\r
154\r
155 return EFI_SUCCESS;\r
156}\r
157\r
158/**\r
159 Pop an element from the stack.\r
160\r
161 @param Stack On input: old stack\r
162 @param StackPtr On input: old stack pointer; On output: new stack pointer\r
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
171 IN EFI_HII_VALUE *Stack,\r
172 IN OUT EFI_HII_VALUE **StackPtr,\r
173 OUT EFI_HII_VALUE *Data\r
174 )\r
175{\r
176 //\r
177 // Check for a stack underflow condition\r
178 //\r
179 if (*StackPtr == Stack) {\r
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
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
200 mCurrentExpressionPointer = mCurrentExpressionStack;\r
201 mFormExpressionPointer = mFormExpressionStack;\r
202 mStatementExpressionPointer = mStatementExpressionStack;\r
203 mOptionExpressionPointer = mOptionExpressionStack;\r
204}\r
205\r
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
222 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
223 Data.Value.u64 = (UINT64)(UINTN)Pointer;\r
224\r
225 return PushStack (\r
226 &mCurrentExpressionStack,\r
227 &mCurrentExpressionPointer,\r
228 &mCurrentExpressionEnd,\r
229 &Data\r
230 );\r
231}\r
232\r
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
244 OUT VOID **Pointer\r
245 )\r
246{\r
247 EFI_STATUS Status;\r
248 EFI_HII_VALUE Data;\r
249\r
250 Status = PopStack (\r
251 mCurrentExpressionStack,\r
252 &mCurrentExpressionPointer,\r
253 &Data\r
254 );\r
255\r
256 *Pointer = (VOID *)(UINTN)Data.Value.u64;\r
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
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
283\r
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
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
294 )\r
295{\r
296 UINTN Size;\r
297 FORM_EXPRESSION **NewStack;\r
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
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
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
373 CopyMem (*StackPtr, Data, sizeof (FORM_EXPRESSION *));\r
374 *StackPtr = *StackPtr + 1;\r
375\r
376 return EFI_SUCCESS;\r
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
392 IN FORM_EXPRESSION **Stack,\r
393 IN OUT FORM_EXPRESSION ***StackPtr,\r
394 OUT FORM_EXPRESSION **Data\r
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
410}\r
411\r
412/**\r
413 Get the expression list count.\r
414\r
415 @param Level Which type this expression belong to. Form,\r
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
422INTN\r
423GetConditionalExpressionCount (\r
424 IN EXPRESS_LEVEL Level\r
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
437 }\r
438}\r
439\r
440/**\r
441 Get the expression Buffer pointer.\r
442\r
443 @param Level Which type this expression belong to. Form,\r
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
451 IN EXPRESS_LEVEL Level\r
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
464 }\r
465}\r
466\r
467/**\r
468 Push the expression options onto the Stack.\r
469\r
470 @param Pointer Pointer to the current expression.\r
471 @param Level Which type this expression belong to. Form,\r
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
480 IN FORM_EXPRESSION *Pointer,\r
481 IN EXPRESS_LEVEL Level\r
482 )\r
483{\r
484 switch (Level) {\r
485 case ExpressForm:\r
486 return PushConditionalStack (\r
487 &mFormExpressionStack,\r
488 &mFormExpressionPointer,\r
489 &mFormExpressionEnd,\r
490 &Pointer\r
491 );\r
492 case ExpressStatement:\r
493 return PushConditionalStack (\r
494 &mStatementExpressionStack,\r
495 &mStatementExpressionPointer,\r
496 &mStatementExpressionEnd,\r
497 &Pointer\r
498 );\r
499 case ExpressOption:\r
500 return PushConditionalStack (\r
501 &mOptionExpressionStack,\r
502 &mOptionExpressionPointer,\r
503 &mOptionExpressionEnd,\r
504 &Pointer\r
505 );\r
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
515 @param Level Which type this expression belong to. Form,\r
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
524 IN EXPRESS_LEVEL Level\r
525 )\r
526{\r
527 FORM_EXPRESSION *Pointer;\r
528\r
529 switch (Level) {\r
530 case ExpressForm:\r
531 return PopConditionalStack (\r
532 mFormExpressionStack,\r
533 &mFormExpressionPointer,\r
534 &Pointer\r
535 );\r
536\r
537 case ExpressStatement:\r
538 return PopConditionalStack (\r
539 mStatementExpressionStack,\r
540 &mStatementExpressionPointer,\r
541 &Pointer\r
542 );\r
543\r
544 case ExpressOption:\r
545 return PopConditionalStack (\r
546 mOptionExpressionStack,\r
547 &mOptionExpressionPointer,\r
548 &Pointer\r
549 );\r
550\r
551 default:\r
552 ASSERT (FALSE);\r
553 return EFI_INVALID_PARAMETER;\r
554 }\r
555}\r
556\r
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
573 Data.Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
574 Data.Value.u64 = (UINT64)(UINTN)Pointer;\r
575\r
576 return PushStack (\r
577 &mMapExpressionListStack,\r
578 &mMapExpressionListPointer,\r
579 &mMapExpressionListEnd,\r
580 &Data\r
581 );\r
582}\r
583\r
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
595 OUT VOID **Pointer\r
596 )\r
597{\r
598 EFI_STATUS Status;\r
599 EFI_HII_VALUE Data;\r
600\r
601 Status = PopStack (\r
602 mMapExpressionListStack,\r
603 &mMapExpressionListPointer,\r
604 &Data\r
605 );\r
606\r
607 *Pointer = (VOID *)(UINTN)Data.Value.u64;\r
608\r
609 return Status;\r
610}\r
611\r
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
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
636 IN UINT8 Operand\r
637 )\r
638{\r
639 EFI_HII_VALUE Data;\r
640\r
641 Data.Type = EFI_IFR_TYPE_NUM_SIZE_8;\r
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
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
664 OUT UINT8 *Operand\r
665 )\r
666{\r
667 EFI_STATUS Status;\r
668 EFI_HII_VALUE Data;\r
669\r
670 Status = PopStack (\r
671 mOpCodeScopeStack,\r
672 &mOpCodeScopeStackPointer,\r
673 &Data\r
674 );\r
675\r
676 *Operand = Data.Value.u8;\r
677\r
678 return Status;\r
679}\r
680\r
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
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
719 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,\r
720 &mExpressionEvaluationStackPointer,\r
721 Value\r
722 );\r
723}\r
724\r
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
732 VOID\r
733 )\r
734{\r
735 UINTN TempStackOffset;\r
736\r
737 TempStackOffset = mExpressionEvaluationStackOffset;\r
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
750 UINTN StackOffset\r
751 )\r
752{\r
753 mExpressionEvaluationStackOffset = StackOffset;\r
754}\r
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
770 )\r
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
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
808 if ((QuestionId == 0) || (Form == NULL)) {\r
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
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
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
872 GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);\r
873 }\r
874\r
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
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
907 if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression->RuleId == RuleId)) {\r
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
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
943 (VOID **)&mUnicodeCollation\r
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
956 IN CHAR16 *String\r
957 )\r
958{\r
959 while (*String != 0) {\r
960 if ((*String >= 'a') && (*String <= 'z')) {\r
961 *String = (UINT16)((*String) & ((UINT16) ~0x20));\r
962 }\r
963\r
964 String++;\r
965 }\r
966}\r
967\r
968/**\r
969 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.\r
970\r
971 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
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
982 IN EFI_HII_VALUE *Value\r
983 )\r
984{\r
985 switch (Value->Type) {\r
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
991\r
992 default:\r
993 return FALSE;\r
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
1008 IN EFI_HII_VALUE *Value\r
1009 )\r
1010{\r
1011 switch (Value->Type) {\r
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
1018\r
1019 default:\r
1020 return FALSE;\r
1021 }\r
1022}\r
1023\r
1024/**\r
1025 Return the buffer length for this value.\r
1026\r
1027 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
1028 EFI_IFR_TYPE_BUFFER when do the value compare.\r
1029\r
1030 @param Value Expression value to compare on.\r
1031\r
1032 @retval BufLen Return the buffer length.\r
1033\r
1034**/\r
1035UINT16\r
1036GetLengthForValue (\r
1037 IN EFI_HII_VALUE *Value\r
1038 )\r
1039{\r
1040 switch (Value->Type) {\r
1041 case EFI_IFR_TYPE_BUFFER:\r
1042 return Value->BufferLen;\r
1043\r
1044 case EFI_IFR_TYPE_DATE:\r
1045 return (UINT16)sizeof (EFI_HII_DATE);\r
1046\r
1047 case EFI_IFR_TYPE_TIME:\r
1048 return (UINT16)sizeof (EFI_HII_TIME);\r
1049\r
1050 case EFI_IFR_TYPE_REF:\r
1051 return (UINT16)sizeof (EFI_HII_REF);\r
1052\r
1053 default:\r
1054 return 0;\r
1055 }\r
1056}\r
1057\r
1058/**\r
1059 Return the buffer pointer for this value.\r
1060\r
1061 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to\r
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
1071 IN EFI_HII_VALUE *Value\r
1072 )\r
1073{\r
1074 switch (Value->Type) {\r
1075 case EFI_IFR_TYPE_BUFFER:\r
1076 return Value->Buffer;\r
1077\r
1078 case EFI_IFR_TYPE_DATE:\r
1079 return (UINT8 *)(&Value->Value.date);\r
1080\r
1081 case EFI_IFR_TYPE_TIME:\r
1082 return (UINT8 *)(&Value->Value.time);\r
1083\r
1084 case EFI_IFR_TYPE_REF:\r
1085 return (UINT8 *)(&Value->Value.ref);\r
1086\r
1087 default:\r
1088 return NULL;\r
1089 }\r
1090}\r
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
1115 UINT8 *TmpBuf;\r
1116 UINT8 *SrcBuf;\r
1117 UINTN SrcLen;\r
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
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
1136\r
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
1149\r
1150 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);\r
1151 String = Buffer;\r
1152 break;\r
1153\r
1154 case EFI_IFR_TYPE_STRING:\r
1155 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));\r
1156 return EFI_SUCCESS;\r
1157\r
1158 case EFI_IFR_TYPE_BOOLEAN:\r
1159 String = (Value.Value.b) ? L"True" : L"False";\r
1160 break;\r
1161\r
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
1177\r
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
1188\r
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
1195\r
1196 break;\r
1197\r
1198 default:\r
1199 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1200 return EFI_SUCCESS;\r
1201 }\r
1202\r
1203 Result->Type = EFI_IFR_TYPE_STRING;\r
1204 Result->Value.string = NewString (String, FormSet->HiiHandle);\r
1205 return EFI_SUCCESS;\r
1206}\r
1207\r
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
1228\r
1229 Status = PopExpression (&Value);\r
1230 if (EFI_ERROR (Status)) {\r
1231 return Status;\r
1232 }\r
1233\r
1234 if ((Value.Type >= EFI_IFR_TYPE_OTHER) && !IsTypeInBuffer (&Value)) {\r
1235 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1236 return EFI_SUCCESS;\r
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
1245\r
1246 IfrStrToUpper (String);\r
1247 StringPtr = StrStr (String, L"0X");\r
1248 if (StringPtr != NULL) {\r
1249 //\r
1250 // Hex string\r
1251 //\r
1252 Result->Value.u64 = StrHexToUint64 (String);\r
1253 } else {\r
1254 //\r
1255 // decimal string\r
1256 //\r
1257 Result->Value.u64 = StrDecimalToUint64 (String);\r
1258 }\r
1259\r
1260 FreePool (String);\r
1261 } else if (IsTypeInBuffer (&Value)) {\r
1262 if (GetLengthForValue (&Value) > 8) {\r
1263 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1264 FreePool (Value.Buffer);\r
1265 }\r
1266\r
1267 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1268 return EFI_SUCCESS;\r
1269 }\r
1270\r
1271 ASSERT (GetBufferForValue (&Value) != NULL);\r
1272 Result->Value.u64 = *(UINT64 *)GetBufferForValue (&Value);\r
1273\r
1274 if (Value.Type == EFI_IFR_TYPE_BUFFER) {\r
1275 FreePool (Value.Buffer);\r
1276 }\r
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
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
1302 EFI_HII_VALUE Value[2];\r
1303 CHAR16 *String[2];\r
1304 UINTN Index;\r
1305 CHAR16 *StringPtr;\r
1306 UINTN Size;\r
1307 UINT16 Length0;\r
1308 UINT16 Length1;\r
1309 UINT8 *TmpBuf;\r
1310 UINTN MaxLen;\r
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
1319 Status = EFI_SUCCESS;\r
1320 ZeroMem (Value, sizeof (Value));\r
1321\r
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
1331\r
1332 for (Index = 0; Index < 2; Index++) {\r
1333 if ((Value[Index].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[Index])) {\r
1334 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1335 Status = EFI_SUCCESS;\r
1336 goto Done;\r
1337 }\r
1338\r
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
1345 }\r
1346 }\r
1347\r
1348 if (Value[0].Type == EFI_IFR_TYPE_STRING) {\r
1349 Size = StrSize (String[0]);\r
1350 MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);\r
1351 StringPtr = AllocatePool (MaxLen * sizeof (CHAR16));\r
1352 ASSERT (StringPtr != NULL);\r
1353 StrCpyS (StringPtr, MaxLen, String[1]);\r
1354 StrCatS (StringPtr, MaxLen, String[0]);\r
1355\r
1356 Result->Type = EFI_IFR_TYPE_STRING;\r
1357 Result->Value.string = NewString (StringPtr, FormSet->HiiHandle);\r
1358 } else {\r
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
1363\r
1364 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1365 ASSERT (Result->Buffer != NULL);\r
1366\r
1367 TmpBuf = GetBufferForValue (&Value[0]);\r
1368 ASSERT (TmpBuf != NULL);\r
1369 CopyMem (Result->Buffer, TmpBuf, Length0);\r
1370 TmpBuf = GetBufferForValue (&Value[1]);\r
1371 ASSERT (TmpBuf != NULL);\r
1372 CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);\r
1373 }\r
1374\r
1375Done:\r
1376 if (Value[0].Buffer != NULL) {\r
1377 FreePool (Value[0].Buffer);\r
1378 }\r
1379\r
1380 if (Value[1].Buffer != NULL) {\r
1381 FreePool (Value[1].Buffer);\r
1382 }\r
1383\r
1384 if (String[0] != NULL) {\r
1385 FreePool (String[0]);\r
1386 }\r
1387\r
1388 if (String[1] != NULL) {\r
1389 FreePool (String[1]);\r
1390 }\r
1391\r
1392 if (StringPtr != NULL) {\r
1393 FreePool (StringPtr);\r
1394 }\r
1395\r
1396 return Status;\r
1397}\r
1398\r
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
1416 EFI_HII_VALUE Value[2];\r
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
1426 Status = EFI_SUCCESS;\r
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
1438\r
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
1442 Status = EFI_SUCCESS;\r
1443 goto Done;\r
1444 }\r
1445\r
1446 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1447 if (String[Index] == NULL) {\r
1448 Status = EFI_NOT_FOUND;\r
1449 goto Done;\r
1450 }\r
1451 }\r
1452\r
1453 Result->Type = EFI_IFR_TYPE_BOOLEAN;\r
1454 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);\r
1455\r
1456Done:\r
1457 if (String[0] != NULL) {\r
1458 FreePool (String[0]);\r
1459 }\r
1460\r
1461 if (String[1] != NULL) {\r
1462 FreePool (String[1]);\r
1463 }\r
1464\r
1465 return Status;\r
1466}\r
1467\r
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
1502 String[0] = NULL;\r
1503 String[1] = NULL;\r
1504 HandleBuffer = NULL;\r
1505 RegExSyntaxTypeList = NULL;\r
1506 Status = EFI_SUCCESS;\r
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
1522 Status = EFI_SUCCESS;\r
1523 goto Done;\r
1524 }\r
1525\r
1526 String[Index] = GetToken (Value[Index].Value.string, FormSet->HiiHandle);\r
1527 if (String[Index] == NULL) {\r
1528 Status = EFI_NOT_FOUND;\r
1529 goto Done;\r
1530 }\r
1531 }\r
1532\r
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
1542 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1543 HandleBuffer = AllocateZeroPool (BufferSize);\r
1544 if (HandleBuffer == NULL) {\r
1545 Status = EFI_OUT_OF_RESOURCES;\r
1546 goto Done;\r
1547 }\r
1548\r
1549 Status = gBS->LocateHandle (\r
1550 ByProtocol,\r
1551 &gEfiRegularExpressionProtocolGuid,\r
1552 NULL,\r
1553 &BufferSize,\r
1554 HandleBuffer\r
1555 );\r
1556 }\r
1557\r
1558 if (EFI_ERROR (Status)) {\r
1559 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1560 Status = EFI_SUCCESS;\r
1561 goto Done;\r
1562 }\r
1563\r
1564 ASSERT (HandleBuffer != NULL);\r
1565 for ( Index = 0; Index < BufferSize / sizeof (EFI_HANDLE); Index++) {\r
1566 Status = gBS->HandleProtocol (\r
1567 HandleBuffer[Index],\r
1568 &gEfiRegularExpressionProtocolGuid,\r
1569 (VOID **)&RegularExpressionProtocol\r
1570 );\r
1571 if (EFI_ERROR (Status)) {\r
1572 goto Done;\r
1573 }\r
1574\r
1575 RegExSyntaxTypeListSize = 0;\r
1576 RegExSyntaxTypeList = NULL;\r
1577\r
1578 Status = RegularExpressionProtocol->GetInfo (\r
1579 RegularExpressionProtocol,\r
1580 &RegExSyntaxTypeListSize,\r
1581 RegExSyntaxTypeList\r
1582 );\r
1583 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1584 RegExSyntaxTypeList = AllocateZeroPool (RegExSyntaxTypeListSize);\r
1585 if (RegExSyntaxTypeList == NULL) {\r
1586 Status = EFI_OUT_OF_RESOURCES;\r
1587 goto Done;\r
1588 }\r
1589\r
1590 Status = RegularExpressionProtocol->GetInfo (\r
1591 RegularExpressionProtocol,\r
1592 &RegExSyntaxTypeListSize,\r
1593 RegExSyntaxTypeList\r
1594 );\r
1595 } else if (EFI_ERROR (Status)) {\r
1596 goto Done;\r
1597 }\r
1598\r
1599 for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof (EFI_GUID); GuidIndex++) {\r
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
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
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
1624 // Type specified by SyntaxType is not supported\r
1625 // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.\r
1626 //\r
1627 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1628 Status = EFI_SUCCESS;\r
1629\r
1630Done:\r
1631 if (String[0] != NULL) {\r
1632 FreePool (String[0]);\r
1633 }\r
1634\r
1635 if (String[1] != NULL) {\r
1636 FreePool (String[1]);\r
1637 }\r
1638\r
1639 if (RegExSyntaxTypeList != NULL) {\r
1640 FreePool (RegExSyntaxTypeList);\r
1641 }\r
1642\r
1643 if (HandleBuffer != NULL) {\r
1644 FreePool (HandleBuffer);\r
1645 }\r
1646\r
1647 return Status;\r
1648}\r
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
1669 EFI_HII_VALUE Value[3];\r
1670 CHAR16 *String[2];\r
1671 UINTN Base;\r
1672 CHAR16 *StringPtr;\r
1673 UINTN Index;\r
1674\r
1675 ZeroMem (Value, sizeof (Value));\r
1676\r
1677 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {\r
1678 return EFI_INVALID_PARAMETER;\r
1679 }\r
1680\r
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
1687 if (EFI_ERROR (Status)) {\r
1688 return Status;\r
1689 }\r
1690\r
1691 Status = PopExpression (&Value[2]);\r
1692 if (EFI_ERROR (Status)) {\r
1693 return Status;\r
1694 }\r
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
1699 }\r
1700\r
1701 Base = (UINTN)Value[0].Value.u64;\r
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
1710 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1711 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1712 Status = EFI_SUCCESS;\r
1713 goto Done;\r
1714 }\r
1715\r
1716 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
1717 if (String[Index] == NULL) {\r
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
1734 StringPtr = StrStr (String[1] + Base, String[0]);\r
1735 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);\r
1736 }\r
1737\r
1738Done:\r
1739 if (String[0] != NULL) {\r
1740 FreePool (String[0]);\r
1741 }\r
1742\r
1743 if (String[1] != NULL) {\r
1744 FreePool (String[1]);\r
1745 }\r
1746\r
1747 return Status;\r
1748}\r
1749\r
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
1767 EFI_HII_VALUE Value[3];\r
1768 CHAR16 *String;\r
1769 UINTN Base;\r
1770 UINTN Length;\r
1771 CHAR16 *SubString;\r
1772 UINT16 BufferLen;\r
1773 UINT8 *Buffer;\r
1774\r
1775 ZeroMem (Value, sizeof (Value));\r
1776\r
1777 Status = PopExpression (&Value[0]);\r
1778 if (EFI_ERROR (Status)) {\r
1779 return Status;\r
1780 }\r
1781\r
1782 Status = PopExpression (&Value[1]);\r
1783 if (EFI_ERROR (Status)) {\r
1784 return Status;\r
1785 }\r
1786\r
1787 Status = PopExpression (&Value[2]);\r
1788 if (EFI_ERROR (Status)) {\r
1789 return Status;\r
1790 }\r
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
1795 }\r
1796\r
1797 Length = (UINTN)Value[0].Value.u64;\r
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
1802 }\r
1803\r
1804 Base = (UINTN)Value[1].Value.u64;\r
1805\r
1806 if ((Value[2].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[2])) {\r
1807 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1808 return EFI_SUCCESS;\r
1809 }\r
1810\r
1811 if (Value[2].Type == EFI_IFR_TYPE_STRING) {\r
1812 String = GetToken (Value[2].Value.string, FormSet->HiiHandle);\r
1813 if (String == NULL) {\r
1814 return EFI_NOT_FOUND;\r
1815 }\r
1816\r
1817 if ((Length == 0) || (Base >= StrLen (String))) {\r
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
1824 }\r
1825\r
1826 Result->Type = EFI_IFR_TYPE_STRING;\r
1827 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1828\r
1829 FreePool (String);\r
1830 } else {\r
1831 BufferLen = GetLengthForValue (&Value[2]);\r
1832 Buffer = GetBufferForValue (&Value[2]);\r
1833\r
1834 Result->Type = EFI_IFR_TYPE_BUFFER;\r
1835 if ((Length == 0) || (Base >= BufferLen)) {\r
1836 Result->BufferLen = 0;\r
1837 Result->Buffer = NULL;\r
1838 } else {\r
1839 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);\r
1840 Result->Buffer = AllocateZeroPool (Result->BufferLen);\r
1841 ASSERT (Result->Buffer != NULL);\r
1842 CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);\r
1843 }\r
1844\r
1845 if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {\r
1846 FreePool (Value[2].Buffer);\r
1847 }\r
1848 }\r
1849\r
1850 return Status;\r
1851}\r
1852\r
1853/**\r
1854 Evaluate opcode EFI_IFR_TOKEN.\r
1855\r
1856 @param FormSet Formset which contains this opcode.\r
1857 @param Result Evaluation result for this opcode.\r
1858\r
1859 @retval EFI_SUCCESS Opcode evaluation success.\r
1860 @retval Other Opcode evaluation failed.\r
1861\r
1862**/\r
1863EFI_STATUS\r
1864IfrToken (\r
1865 IN FORM_BROWSER_FORMSET *FormSet,\r
1866 OUT EFI_HII_VALUE *Result\r
1867 )\r
1868{\r
1869 EFI_STATUS Status;\r
1870 EFI_HII_VALUE Value[3];\r
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
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
1886 if (EFI_ERROR (Status)) {\r
1887 return Status;\r
1888 }\r
1889\r
1890 Status = PopExpression (&Value[2]);\r
1891 if (EFI_ERROR (Status)) {\r
1892 return Status;\r
1893 }\r
1894\r
1895 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {\r
1896 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1897 return EFI_SUCCESS;\r
1898 }\r
1899\r
1900 Count = (UINTN)Value[0].Value.u64;\r
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
1909 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
1910 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
1911 Status = EFI_SUCCESS;\r
1912 goto Done;\r
1913 }\r
1914\r
1915 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
1916 if (String[Index] == NULL) {\r
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
1934\r
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
1953 Result->Type = EFI_IFR_TYPE_STRING;\r
1954 Result->Value.string = NewString (SubString, FormSet->HiiHandle);\r
1955\r
1956Done:\r
1957 if (String[0] != NULL) {\r
1958 FreePool (String[0]);\r
1959 }\r
1960\r
1961 if (String[1] != NULL) {\r
1962 FreePool (String[1]);\r
1963 }\r
1964\r
1965 return Status;\r
1966}\r
1967\r
1968/**\r
1969 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
1987 EFI_HII_VALUE Value[3];\r
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
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
2003 if (EFI_ERROR (Status)) {\r
2004 return Status;\r
2005 }\r
2006\r
2007 Status = PopExpression (&Value[2]);\r
2008 if (EFI_ERROR (Status)) {\r
2009 return Status;\r
2010 }\r
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
2015 }\r
2016\r
2017 Base = (UINTN)Value[0].Value.u64;\r
2018\r
2019 //\r
2020 // String[0] - Charset\r
2021 // String[1] - The string to search\r
2022 //\r
2023 String[0] = NULL;\r
2024 String[1] = NULL;\r
2025 for (Index = 0; Index < 2; Index++) {\r
2026 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {\r
2027 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2028 Status = EFI_SUCCESS;\r
2029 goto Done;\r
2030 }\r
2031\r
2032 String[Index] = GetToken (Value[Index + 1].Value.string, FormSet->HiiHandle);\r
2033 if (String[Index] == NULL) {\r
2034 Status = EFI_NOT_FOUND;\r
2035 goto Done;\r
2036 }\r
2037 }\r
2038\r
2039 if (Base >= StrLen (String[1])) {\r
2040 Result->Type = EFI_IFR_TYPE_UNDEFINED;\r
2041 Status = EFI_SUCCESS;\r
2042 goto Done;\r
2043 }\r
2044\r
2045 Found = FALSE;\r
2046 StringPtr = String[1] + Base;\r
2047 Charset = String[0];\r
2048 while (*StringPtr != 0 && !Found) {\r
2049 Index = 0;\r
2050 while (Charset[Index] != 0) {\r
2051 if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1])) {\r
2052 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {\r
2053 Found = TRUE;\r
2054 break;\r
2055 }\r
2056 } else {\r
2057 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {\r
2058 Found = TRUE;\r
2059 break;\r
2060 }\r
2061 }\r
2062\r
2063 //\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
2074 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;\r
2075 Result->Value.u64 = StringPtr - String[1];\r
2076\r
2077Done:\r
2078 if (String[0] != NULL) {\r
2079 FreePool (String[0]);\r
2080 }\r
2081\r
2082 if (String[1] != NULL) {\r
2083 FreePool (String[1]);\r
2084 }\r
2085\r
2086 return Status;\r
2087}\r
2088\r
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
2097 IN EFI_HII_VALUE *Value\r
2098 )\r
2099{\r
2100 UINT64 Temp;\r
2101\r
2102 Temp = 0;\r
2103 switch (Value->Type) {\r
2104 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2105 Temp = Value->Value.u8;\r
2106 break;\r
2107\r
2108 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2109 Temp = Value->Value.u16;\r
2110 break;\r
2111\r
2112 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2113 Temp = Value->Value.u32;\r
2114 break;\r
2115\r
2116 case EFI_IFR_TYPE_BOOLEAN:\r
2117 Temp = Value->Value.b;\r
2118 break;\r
2119\r
2120 case EFI_IFR_TYPE_TIME:\r
2121 Temp = Value->Value.u32 & 0xffffff;\r
2122 break;\r
2123\r
2124 case EFI_IFR_TYPE_DATE:\r
2125 Temp = Value->Value.u32;\r
2126 break;\r
2127\r
2128 default:\r
2129 return;\r
2130 }\r
2131\r
2132 Value->Value.u64 = Temp;\r
2133}\r
2134\r
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
2145 IN EFI_HII_VALUE *Value\r
2146 )\r
2147{\r
2148 UINT64 RetVal;\r
2149\r
2150 RetVal = 0;\r
2151\r
2152 switch (Value->Type) {\r
2153 case EFI_IFR_TYPE_NUM_SIZE_8:\r
2154 RetVal = Value->Value.u8;\r
2155 break;\r
2156\r
2157 case EFI_IFR_TYPE_NUM_SIZE_16:\r
2158 RetVal = Value->Value.u16;\r
2159 break;\r
2160\r
2161 case EFI_IFR_TYPE_NUM_SIZE_32:\r
2162 RetVal = Value->Value.u32;\r
2163 break;\r
2164\r
2165 case EFI_IFR_TYPE_BOOLEAN:\r
2166 RetVal = Value->Value.b;\r
2167 break;\r
2168\r
2169 case EFI_IFR_TYPE_DATE:\r
2170 RetVal = *(UINT64 *)&Value->Value.date;\r
2171 break;\r
2172\r
2173 case EFI_IFR_TYPE_TIME:\r
2174 RetVal = (*(UINT64 *)&Value->Value.time) & 0xffffff;\r
2175 break;\r
2176\r
2177 default:\r
2178 RetVal = Value->Value.u64;\r
2179 break;\r
2180 }\r
2181\r
2182 return RetVal;\r
2183}\r
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
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
2194 @param HiiHandle Only required for string compare.\r
2195\r
2196 @retval other Could not perform compare on two values.\r
2197 @retval EFI_SUCCESS Compare the value success.\r
2198\r
2199**/\r
2200EFI_STATUS\r
2201CompareHiiValue (\r
2202 IN EFI_HII_VALUE *Value1,\r
2203 IN EFI_HII_VALUE *Value2,\r
2204 OUT INTN *Result,\r
2205 IN EFI_HII_HANDLE HiiHandle OPTIONAL\r
2206 )\r
2207{\r
2208 INT64 Temp64;\r
2209 CHAR16 *Str1;\r
2210 CHAR16 *Str2;\r
2211 UINTN Len;\r
2212 UINT8 *Buf1;\r
2213 UINT16 Buf1Len;\r
2214 UINT8 *Buf2;\r
2215 UINT16 Buf2Len;\r
2216\r
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
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
2226 *Result = 0;\r
2227 return EFI_SUCCESS;\r
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
2235 return EFI_NOT_FOUND;\r
2236 }\r
2237\r
2238 Str2 = GetToken (Value2->Value.string, HiiHandle);\r
2239 if (Str2 == NULL) {\r
2240 FreePool (Str1);\r
2241 return EFI_NOT_FOUND;\r
2242 }\r
2243\r
2244 *Result = StrCmp (Str1, Str2);\r
2245\r
2246 FreePool (Str1);\r
2247 FreePool (Str2);\r
2248\r
2249 return EFI_SUCCESS;\r
2250 }\r
2251\r
2252 //\r
2253 // Take types(date, time, ref, buffer) as buffer\r
2254 //\r
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
2260\r
2261 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;\r
2262 *Result = CompareMem (Buf1, Buf2, Len);\r
2263 if ((*Result == 0) && (Buf1Len != Buf2Len)) {\r
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
2268 *Result = Buf1Len > Buf2Len ? 1 : -1;\r
2269 }\r
2270\r
2271 return EFI_SUCCESS;\r
2272 }\r
2273\r
2274 //\r
2275 // Take types(integer, boolean) as integer\r
2276 //\r
2277 if (IsTypeInUINT64 (Value1) && IsTypeInUINT64 (Value2)) {\r
2278 Temp64 = HiiValueToUINT64 (Value1) - HiiValueToUINT64 (Value2);\r
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
2288 }\r
2289\r
2290 return EFI_UNSUPPORTED;\r
2291}\r
2292\r
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
2303 IN EFI_GUID *Guid\r
2304 )\r
2305{\r
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
2315\r
2316 if (mUserManager == NULL) {\r
2317 Status = gBS->LocateProtocol (\r
2318 &gEfiUserManagerProtocolGuid,\r
2319 NULL,\r
2320 (VOID **)&mUserManager\r
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
2339\r
2340 for (UserInfoHandle = NULL; ;) {\r
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
2347 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);\r
2348 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2349 continue;\r
2350 }\r
2351\r
2352 UserInfo = (EFI_USER_INFO *)AllocatePool (UserInfoSize);\r
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
2359 (UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) ||\r
2360 (UserInfo->InfoSize <= sizeof (EFI_USER_INFO)))\r
2361 {\r
2362 FreePool (UserInfo);\r
2363 continue;\r
2364 }\r
2365\r
2366 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);\r
2367 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);\r
2368 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {\r
2369 if ((RemainSize < AccessControl->Size) || (AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL))) {\r
2370 break;\r
2371 }\r
2372\r
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
2378 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);\r
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
2385\r
2386 UserPermissionsGuid++;\r
2387 AccessControlDataSize -= sizeof (EFI_GUID);\r
2388 }\r
2389 }\r
2390\r
2391 RemainSize -= AccessControl->Size;\r
2392 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);\r
2393 }\r
2394\r
2395 FreePool (UserInfo);\r
2396 }\r
2397\r
2398 return FALSE;\r
2399}\r
2400\r
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
2409\r
2410 @retval TRUE Get the question value success.\r
2411 @retval FALSE Get the question value failed.\r
2412**/\r
2413BOOLEAN\r
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
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
2429\r
2430 //\r
2431 // The input parameter DevicePath or InputHiiHandle must have one valid input.\r
2432 //\r
2433 ASSERT (\r
2434 (DevicePath != NULL && InputHiiHandle == NULL) ||\r
2435 (DevicePath == NULL && InputHiiHandle != NULL)\r
2436 );\r
2437\r
2438 GetTheVal = TRUE;\r
2439 HiiHandle = NULL;\r
2440 Question = NULL;\r
2441 Form = NULL;\r
2442\r
2443 //\r
2444 // Get HiiHandle.\r
2445 //\r
2446 if (DevicePath != NULL) {\r
2447 HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);\r
2448 if (HiiHandle == NULL) {\r
2449 return FALSE;\r
2450 }\r
2451 } else {\r
2452 HiiHandle = InputHiiHandle;\r
2453 }\r
2454\r
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
2462 Status = InitializeFormSet (HiiHandle, FormSetGuid, FormSet);\r
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
2470 //\r
2471 Question = IdToQuestion (FormSet, NULL, QuestionId);\r
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
2492\r
2493 ASSERT (Form != NULL);\r
2494\r
2495 //\r
2496 // Get the question value.\r
2497 //\r
2498 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithEditBuffer);\r
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
2505\r
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
2513\r
2514 return GetTheVal;\r
2515}\r
2516\r
2517/**\r
2518 Evaluate the result of a HII expression.\r
2519\r
2520 If Expression is NULL, then ASSERT.\r
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
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
2567\r
2568 StrPtr = NULL;\r
2569\r
2570 //\r
2571 // Save current stack offset.\r
2572 //\r
2573 StackOffset = SaveExpressionEvaluationStackOffset ();\r
2574\r
2575 ASSERT (Expression != NULL);\r
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
2588 Value = &Data3;\r
2589 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
2590 Status = EFI_SUCCESS;\r
2591\r
2592 switch (OpCode->Operand) {\r
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
2602\r
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
2609\r
2610 if (EFI_ERROR (Status)) {\r
2611 goto Done;\r
2612 }\r
2613\r
2614 Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);\r
2615 break;\r
2616\r
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
2623\r
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
2640\r
2641 Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);\r
2642 break;\r
2643\r
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
2648 break;\r
2649 }\r
2650\r
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
2658\r
2659 break;\r
2660\r
2661 case EFI_IFR_DUP_OP:\r
2662 Status = PopExpression (Value);\r
2663 if (EFI_ERROR (Status)) {\r
2664 goto Done;\r
2665 }\r
2666\r
2667 Status = PushExpression (Value);\r
2668 break;\r
2669\r
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
2677\r
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
2686 //\r
2687 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.\r
2688 //\r
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
2695 //\r
2696 // Get value from Edit Buffer\r
2697 //\r
2698 Value->Type = OpCode->ValueType;\r
2699 CopyMem (&Value->Value, OpCode->VarStorage->EditBuffer + OpCode->VarStoreInfo.VarOffset, OpCode->ValueWidth);\r
2700 break;\r
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
2727 break;\r
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
2746 break;\r
2747 default:\r
2748 //\r
2749 // Not recognize storage.\r
2750 //\r
2751 Status = EFI_UNSUPPORTED;\r
2752 goto Done;\r
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
2810 }\r
2811 }\r
2812 }\r
2813\r
2814 break;\r
2815\r
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
2825\r
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
2836\r
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
2843\r
2844 if (DevicePath != NULL) {\r
2845 FreePool (DevicePath);\r
2846 }\r
2847 }\r
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
2856 }\r
2857\r
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
2870 }\r
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
2880 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2881 break;\r
2882 }\r
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
2889 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2890 break;\r
2891 }\r
2892\r
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
2900\r
2901 //\r
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
2916 break;\r
2917\r
2918 //\r
2919 // unary-op\r
2920 //\r
2921 case EFI_IFR_LENGTH_OP:\r
2922 Status = PopExpression (Value);\r
2923 if (EFI_ERROR (Status)) {\r
2924 goto Done;\r
2925 }\r
2926\r
2927 if ((Value->Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (Value)) {\r
2928 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2929 break;\r
2930 }\r
2931\r
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
2938\r
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
2947\r
2948 break;\r
2949\r
2950 case EFI_IFR_NOT_OP:\r
2951 Status = PopExpression (Value);\r
2952 if (EFI_ERROR (Status)) {\r
2953 goto Done;\r
2954 }\r
2955\r
2956 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {\r
2957 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
2958 break;\r
2959 }\r
2960\r
2961 Value->Value.b = (BOOLEAN)(!Value->Value.b);\r
2962 break;\r
2963\r
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
2972\r
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
2980\r
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
2986\r
2987 Value = &Question->HiiValue;\r
2988 break;\r
2989\r
2990 case EFI_IFR_STRING_REF2_OP:\r
2991 //\r
2992 // Pop an expression from the expression stack\r
2993 //\r
2994 Status = PopExpression (Value);\r
2995 if (EFI_ERROR (Status)) {\r
2996 goto Done;\r
2997 }\r
2998\r
2999 //\r
3000 // Validate the expression value\r
3001 //\r
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
3021\r
3022 case EFI_IFR_TO_BOOLEAN_OP:\r
3023 //\r
3024 // Pop an expression from the expression stack\r
3025 //\r
3026 Status = PopExpression (Value);\r
3027 if (EFI_ERROR (Status)) {\r
3028 goto Done;\r
3029 }\r
3030\r
3031 //\r
3032 // Convert an expression to a Boolean\r
3033 //\r
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
3052 }\r
3053\r
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
3064\r
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
3076\r
3077 if (Index >= Value->BufferLen) {\r
3078 Value->Value.b = FALSE;\r
3079 } else {\r
3080 Value->Value.b = TRUE;\r
3081 }\r
3082\r
3083 Value->Type = EFI_IFR_TYPE_BOOLEAN;\r
3084 FreePool (Value->Buffer);\r
3085 }\r
3086\r
3087 break;\r
3088\r
3089 case EFI_IFR_TO_STRING_OP:\r
3090 Status = IfrToString (FormSet, OpCode->Format, Value);\r
3091 break;\r
3092\r
3093 case EFI_IFR_TO_UINT_OP:\r
3094 Status = IfrToUint (FormSet, Value);\r
3095 break;\r
3096\r
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
3103\r
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
3128 break;\r
3129\r
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
3138\r
3139 if (Value->Type > EFI_IFR_TYPE_DATE) {\r
3140 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3141 break;\r
3142 }\r
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
3149 //\r
3150 // Pop an expression from the expression stack\r
3151 //\r
3152 Status = PopExpression (Value);\r
3153 if (EFI_ERROR (Status)) {\r
3154 goto Done;\r
3155 }\r
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
3168 break;\r
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
3196 break;\r
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
3209 break;\r
3210 default:\r
3211 //\r
3212 // Not recognize storage.\r
3213 //\r
3214 Status = EFI_UNSUPPORTED;\r
3215 goto Done;\r
3216 }\r
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
3230 if (!EFI_ERROR (Status)) {\r
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
3273 }\r
3274 }\r
3275\r
3276 Value = &Data1;\r
3277 break;\r
3278\r
3279 //\r
3280 // binary-op\r
3281 //\r
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
3327\r
3328 case EFI_IFR_MULTIPLY_OP:\r
3329 Value->Value.u64 = MultU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));\r
3330 break;\r
3331\r
3332 case EFI_IFR_DIVIDE_OP:\r
3333 Value->Value.u64 = DivU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));\r
3334 break;\r
3335\r
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
3340\r
3341 case EFI_IFR_BITWISE_AND_OP:\r
3342 Value->Value.u64 = HiiValueToUINT64 (&Data1) & HiiValueToUINT64 (&Data2);\r
3343 break;\r
3344\r
3345 case EFI_IFR_BITWISE_OR_OP:\r
3346 Value->Value.u64 = HiiValueToUINT64 (&Data1) | HiiValueToUINT64 (&Data2);\r
3347 break;\r
3348\r
3349 case EFI_IFR_SHIFT_LEFT_OP:\r
3350 Value->Value.u64 = LShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));\r
3351 break;\r
3352\r
3353 case EFI_IFR_SHIFT_RIGHT_OP:\r
3354 Value->Value.u64 = RShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));\r
3355 break;\r
3356\r
3357 default:\r
3358 break;\r
3359 }\r
3360\r
3361 break;\r
3362\r
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
3372\r
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
3380\r
3381 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3382 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3383 break;\r
3384 }\r
3385\r
3386 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3387 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3388 break;\r
3389 }\r
3390\r
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
3396\r
3397 break;\r
3398\r
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
3412\r
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
3420\r
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
3428\r
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
3436\r
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
3441\r
3442 if (Data2.Type == EFI_IFR_TYPE_BUFFER) {\r
3443 FreePool (Data2.Buffer);\r
3444 }\r
3445\r
3446 if (Status == EFI_UNSUPPORTED) {\r
3447 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3448 Status = EFI_SUCCESS;\r
3449 break;\r
3450 }\r
3451\r
3452 if (EFI_ERROR (Status)) {\r
3453 goto Done;\r
3454 }\r
3455\r
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
3460\r
3461 case EFI_IFR_NOT_EQUAL_OP:\r
3462 Value->Value.b = (BOOLEAN)((Result != 0) ? TRUE : FALSE);\r
3463 break;\r
3464\r
3465 case EFI_IFR_GREATER_EQUAL_OP:\r
3466 Value->Value.b = (BOOLEAN)((Result >= 0) ? TRUE : FALSE);\r
3467 break;\r
3468\r
3469 case EFI_IFR_GREATER_THAN_OP:\r
3470 Value->Value.b = (BOOLEAN)((Result > 0) ? TRUE : FALSE);\r
3471 break;\r
3472\r
3473 case EFI_IFR_LESS_EQUAL_OP:\r
3474 Value->Value.b = (BOOLEAN)((Result <= 0) ? TRUE : FALSE);\r
3475 break;\r
3476\r
3477 case EFI_IFR_LESS_THAN_OP:\r
3478 Value->Value.b = (BOOLEAN)((Result < 0) ? TRUE : FALSE);\r
3479 break;\r
3480\r
3481 default:\r
3482 break;\r
3483 }\r
3484\r
3485 break;\r
3486\r
3487 case EFI_IFR_MATCH_OP:\r
3488 Status = InitializeUnicodeCollationProtocol ();\r
3489 if (EFI_ERROR (Status)) {\r
3490 goto Done;\r
3491 }\r
3492\r
3493 Status = IfrMatch (FormSet, Value);\r
3494 break;\r
3495\r
3496 case EFI_IFR_MATCH2_OP:\r
3497 Status = IfrMatch2 (FormSet, &OpCode->Guid, Value);\r
3498 break;\r
3499\r
3500 case EFI_IFR_CATENATE_OP:\r
3501 Status = IfrCatenate (FormSet, Value);\r
3502 break;\r
3503\r
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
3515\r
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
3523\r
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
3531\r
3532 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {\r
3533 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3534 break;\r
3535 }\r
3536\r
3537 if (Data1.Value.b) {\r
3538 Value = &Data3;\r
3539 } else {\r
3540 Value = &Data2;\r
3541 }\r
3542\r
3543 break;\r
3544\r
3545 case EFI_IFR_FIND_OP:\r
3546 Status = IfrFind (FormSet, OpCode->Format, Value);\r
3547 break;\r
3548\r
3549 case EFI_IFR_MID_OP:\r
3550 Status = IfrMid (FormSet, Value);\r
3551 break;\r
3552\r
3553 case EFI_IFR_TOKEN_OP:\r
3554 Status = IfrToken (FormSet, Value);\r
3555 break;\r
3556\r
3557 case EFI_IFR_SPAN_OP:\r
3558 Status = IfrSpan (FormSet, OpCode->Flags, Value);\r
3559 break;\r
3560\r
3561 case EFI_IFR_MAP_OP:\r
3562 //\r
3563 // Pop the check value\r
3564 //\r
3565 Status = PopExpression (&Data1);\r
3566 if (EFI_ERROR (Status)) {\r
3567 goto Done;\r
3568 }\r
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
3578 //\r
3579 // Go through map expression list.\r
3580 //\r
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
3615 //\r
3616 // Skip the second expression on this pair.\r
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
3623\r
3624 //\r
3625 // Goto the first expression on next pair.\r
3626 //\r
3627 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);\r
3628 }\r
3629\r
3630 //\r
3631 // No map value is found.\r
3632 //\r
3633 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {\r
3634 Value->Type = EFI_IFR_TYPE_UNDEFINED;\r
3635 Value->Value.u8 = 0;\r
3636 }\r
3637\r
3638 break;\r
3639\r
3640 default:\r
3641 break;\r
3642 }\r
3643\r
3644 if (EFI_ERROR (Status) || (Value->Type == EFI_IFR_TYPE_UNDEFINED)) {\r
3645 goto Done;\r
3646 }\r
3647\r
3648 Status = PushExpression (Value);\r
3649 if (EFI_ERROR (Status)) {\r
3650 goto Done;\r
3651 }\r
3652 }\r
3653\r
3654 //\r
3655 // Pop the final result from expression stack\r
3656 //\r
3657 Value = &Data1;\r
3658 Status = PopExpression (Value);\r
3659 if (EFI_ERROR (Status)) {\r
3660 goto Done;\r
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
3667 Status = EFI_INVALID_PARAMETER;\r
3668 }\r
3669\r
3670Done:\r
3671 RestoreExpressionEvaluationStackOffset (StackOffset);\r
3672 if (!EFI_ERROR (Status)) {\r
3673 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));\r
3674 }\r
3675\r
3676 return Status;\r
3677}\r
3678\r
3679/**\r
3680 Check whether the result is TRUE or FALSE.\r
3681\r
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
3693 IN EFI_HII_VALUE *Result\r
3694 )\r
3695{\r
3696 switch (Result->Type) {\r
3697 case EFI_IFR_TYPE_BOOLEAN:\r
3698 return Result->Value.b;\r
3699\r
3700 case EFI_IFR_TYPE_NUM_SIZE_8:\r
3701 return (BOOLEAN)(Result->Value.u8 != 0);\r
3702\r
3703 case EFI_IFR_TYPE_NUM_SIZE_16:\r
3704 return (BOOLEAN)(Result->Value.u16 != 0);\r
3705\r
3706 case EFI_IFR_TYPE_NUM_SIZE_32:\r
3707 return (BOOLEAN)(Result->Value.u32 != 0);\r
3708\r
3709 case EFI_IFR_TYPE_NUM_SIZE_64:\r
3710 return (BOOLEAN)(Result->Value.u64 != 0);\r
3711\r
3712 default:\r
3713 return FALSE;\r
3714 }\r
3715}\r
3716\r
3717/**\r
3718 Return the result of the expression list. Check the expression list and\r
3719 return the highest priority express result.\r
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
3725 @param Form Form associated with this expression.\r
3726\r
3727 @retval EXPRESS_RESULT Return the higher priority express result.\r
3728 DisableIf > SuppressIf > GrayOutIf > FALSE\r
3729\r
3730**/\r
3731EXPRESS_RESULT\r
3732EvaluateExpressionList (\r
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
3737 )\r
3738{\r
3739 UINTN Index;\r
3740 EXPRESS_RESULT ReturnVal;\r
3741 EXPRESS_RESULT CompareOne;\r
3742 EFI_STATUS Status;\r
3743\r
3744 if (ExpList == NULL) {\r
3745 return ExpressFalse;\r
3746 }\r
3747\r
3748 ASSERT (ExpList->Signature == FORM_EXPRESSION_LIST_SIGNATURE);\r
3749 Index = 0;\r
3750\r
3751 //\r
3752 // Check whether need to evaluate the expression first.\r
3753 //\r
3754 if (Evaluate) {\r
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
3768 if (IsTrue (&ExpList->Expression[Index]->Result)) {\r
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
3783 return ExpressFalse;\r
3784 }\r
3785\r
3786 ReturnVal = ReturnVal < CompareOne ? CompareOne : ReturnVal;\r
3787 }\r
3788 }\r
3789\r
3790 return ReturnVal;\r
3791}\r