VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/RedfishPkg/Library/HiiUtilityLib/HiiUtilityInternal.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 157.0 KB
Line 
1/** @file
2 HII utility internal functions.
3
4 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
6 Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include "HiiInternal.h"
13
14CHAR16 *mUnknownString = L"!";
15CHAR16 *gEmptyString = L"";
16
17EFI_HII_VALUE *mExpressionEvaluationStack = NULL;
18EFI_HII_VALUE *mExpressionEvaluationStackEnd = NULL;
19EFI_HII_VALUE *mExpressionEvaluationStackPointer = NULL;
20UINTN mExpressionEvaluationStackOffset = 0;
21
22//
23// Unicode collation protocol interface
24//
25EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL;
26EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL;
27
28/**
29 Allocate new memory and then copy the Unicode string Source to Destination.
30
31 @param[in,out] Dest Location to copy string
32 @param[in] Src String to copy
33
34**/
35VOID
36NewStringCopy (
37 IN OUT CHAR16 **Dest,
38 IN CHAR16 *Src
39 )
40{
41 if (*Dest != NULL) {
42 FreePool (*Dest);
43 }
44
45 *Dest = AllocateCopyPool (StrSize (Src), Src);
46}
47
48/**
49 Set Value of given Name in a NameValue Storage.
50
51 @param[in] Storage The NameValue Storage.
52 @param[in] Name The Name.
53 @param[in] Value The Value to set.
54 @param[out] ReturnNode The node use the input name.
55
56 @retval EFI_SUCCESS Value found for given Name.
57 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
58
59**/
60EFI_STATUS
61SetValueByName (
62 IN HII_FORMSET_STORAGE *Storage,
63 IN CHAR16 *Name,
64 IN CHAR16 *Value,
65 OUT HII_NAME_VALUE_NODE **ReturnNode
66 )
67{
68 LIST_ENTRY *Link;
69 HII_NAME_VALUE_NODE *Node;
70 CHAR16 *Buffer;
71
72 Link = GetFirstNode (&Storage->NameValueList);
73 while (!IsNull (&Storage->NameValueList, Link)) {
74 Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
75
76 if (StrCmp (Name, Node->Name) == 0) {
77 Buffer = Node->Value;
78 if (Buffer != NULL) {
79 FreePool (Buffer);
80 }
81
82 Buffer = AllocateCopyPool (StrSize (Value), Value);
83 if (Buffer == NULL) {
84 return EFI_OUT_OF_RESOURCES;
85 }
86
87 Node->Value = Buffer;
88
89 if (ReturnNode != NULL) {
90 *ReturnNode = Node;
91 }
92
93 return EFI_SUCCESS;
94 }
95
96 Link = GetNextNode (&Storage->NameValueList, Link);
97 }
98
99 return EFI_NOT_FOUND;
100}
101
102/**
103 Get bit field value from the buffer and then set the value for the question.
104 Note: Data type UINT32 can cover all the bit field value.
105
106 @param[in] Question The question refer to bit field.
107 @param[in] Buffer Point to the buffer which the question value get from.
108 @param[out] QuestionValue The Question Value retrieved from Bits.
109
110**/
111VOID
112GetBitsQuestionValue (
113 IN HII_STATEMENT *Question,
114 IN UINT8 *Buffer,
115 OUT HII_STATEMENT_VALUE *QuestionValue
116 )
117{
118 UINTN StartBit;
119 UINTN EndBit;
120 UINT32 RetVal;
121 UINT32 BufferValue;
122
123 StartBit = Question->BitVarOffset % 8;
124 EndBit = StartBit + Question->BitStorageWidth - 1;
125
126 CopyMem ((UINT8 *)&BufferValue, Buffer, Question->StorageWidth);
127
128 RetVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
129
130 //
131 // Set question value.
132 // Note: Since Question with BufferValue (orderedlist, password, string)are not supported to refer bit field.
133 // Only oneof/checkbox/oneof can support bit field.So we can copy the value to the HiiValue of Question directly.
134 //
135 CopyMem ((UINT8 *)&QuestionValue->Value, (UINT8 *)&RetVal, Question->StorageWidth);
136}
137
138/**
139 Set bit field value to the buffer.
140 Note: Data type UINT32 can cover all the bit field value.
141
142 @param[in] Question The question refer to bit field.
143 @param[in,out] Buffer Point to the buffer which the question value set to.
144 @param[in] Value The bit field value need to set.
145
146**/
147VOID
148SetBitsQuestionValue (
149 IN HII_STATEMENT *Question,
150 IN OUT UINT8 *Buffer,
151 IN UINT32 Value
152 )
153{
154 UINT32 Operand;
155 UINTN StartBit;
156 UINTN EndBit;
157 UINT32 RetVal;
158
159 StartBit = Question->BitVarOffset % 8;
160 EndBit = StartBit + Question->BitStorageWidth - 1;
161
162 CopyMem ((UINT8 *)&Operand, Buffer, Question->StorageWidth);
163 RetVal = BitFieldWrite32 (Operand, StartBit, EndBit, Value);
164 CopyMem (Buffer, (UINT8 *)&RetVal, Question->StorageWidth);
165}
166
167/**
168 Convert the buffer value to HiiValue.
169
170 @param[in] Question The question.
171 @param[in] Value Unicode buffer save the question value.
172 @param[out] QuestionValue The Question Value retrieved from Buffer.
173
174 @retval Status whether convert the value success.
175
176**/
177EFI_STATUS
178BufferToQuestionValue (
179 IN HII_STATEMENT *Question,
180 IN CHAR16 *Value,
181 OUT HII_STATEMENT_VALUE *QuestionValue
182 )
183{
184 CHAR16 *StringPtr;
185 BOOLEAN IsBufferStorage;
186 CHAR16 *DstBuf;
187 CHAR16 TempChar;
188 UINTN LengthStr;
189 UINT8 *Dst;
190 CHAR16 TemStr[5];
191 UINTN Index;
192 UINT8 DigitUint8;
193 BOOLEAN IsString;
194 UINTN Length;
195 EFI_STATUS Status;
196 UINT8 *Buffer;
197
198 Buffer = NULL;
199
200 IsString = (BOOLEAN)((QuestionValue->Type == EFI_IFR_TYPE_STRING) ? TRUE : FALSE);
201 if ((Question->Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
202 (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
203 {
204 IsBufferStorage = TRUE;
205 } else {
206 IsBufferStorage = FALSE;
207 }
208
209 //
210 // Question Value is provided by Buffer Storage or NameValue Storage
211 //
212 if ((QuestionValue->Type == EFI_IFR_TYPE_STRING) || (QuestionValue->Type == EFI_IFR_TYPE_BUFFER)) {
213 //
214 // This Question is password or orderedlist
215 //
216 if (QuestionValue->Buffer == NULL) {
217 return EFI_OUT_OF_RESOURCES;
218 }
219
220 Dst = QuestionValue->Buffer;
221 } else {
222 //
223 // Other type of Questions
224 //
225 if (Question->QuestionReferToBitField) {
226 Buffer = (UINT8 *)AllocateZeroPool (Question->StorageWidth);
227 if (Buffer == NULL) {
228 return EFI_OUT_OF_RESOURCES;
229 }
230
231 Dst = Buffer;
232 } else {
233 Dst = (UINT8 *)&QuestionValue->Value;
234 }
235 }
236
237 //
238 // Temp cut at the end of this section, end with '\0' or '&'.
239 //
240 StringPtr = Value;
241 while (*StringPtr != L'\0' && *StringPtr != L'&') {
242 StringPtr++;
243 }
244
245 TempChar = *StringPtr;
246 *StringPtr = L'\0';
247
248 LengthStr = StrLen (Value);
249
250 //
251 // Value points to a Unicode hexadecimal string, we need to convert the string to the value with CHAR16/UINT8...type.
252 // When generating the Value string, we follow this rule: 1 byte -> 2 Unicode characters (for string: 2 byte(CHAR16) ->4 Unicode characters).
253 // So the maximum value string length of a question is : Question->StorageWidth * 2.
254 // If the value string length > Question->StorageWidth * 2, only set the string length as Question->StorageWidth * 2, then convert.
255 //
256 if (LengthStr > (UINTN)Question->StorageWidth * 2) {
257 Length = (UINTN)Question->StorageWidth * 2;
258 } else {
259 Length = LengthStr;
260 }
261
262 Status = EFI_SUCCESS;
263 if (!IsBufferStorage && IsString) {
264 //
265 // Convert Config String to Unicode String, e.g "0041004200430044" => "ABCD"
266 // Add string tail char L'\0' into Length
267 //
268 DstBuf = (CHAR16 *)Dst;
269 ZeroMem (TemStr, sizeof (TemStr));
270 for (Index = 0; Index < Length; Index += 4) {
271 StrnCpyS (TemStr, sizeof (TemStr) / sizeof (CHAR16), Value + Index, 4);
272 DstBuf[Index/4] = (CHAR16)StrHexToUint64 (TemStr);
273 }
274
275 //
276 // Add tailing L'\0' character
277 //
278 DstBuf[Index/4] = L'\0';
279 } else {
280 ZeroMem (TemStr, sizeof (TemStr));
281 for (Index = 0; Index < Length; Index++) {
282 TemStr[0] = Value[LengthStr - Index - 1];
283 DigitUint8 = (UINT8)StrHexToUint64 (TemStr);
284 if ((Index & 1) == 0) {
285 Dst[Index/2] = DigitUint8;
286 } else {
287 Dst[Index/2] = (UINT8)((DigitUint8 << 4) + Dst[Index/2]);
288 }
289 }
290 }
291
292 *StringPtr = TempChar;
293
294 if ((Buffer != NULL) && Question->QuestionReferToBitField) {
295 GetBitsQuestionValue (Question, Buffer, QuestionValue);
296 FreePool (Buffer);
297 }
298
299 return Status;
300}
301
302/**
303 Get the string based on the StringId and HII Package List Handle.
304
305 @param[in] Token The String's ID.
306 @param[in] HiiHandle The package list in the HII database to search for
307 the specified string.
308
309 @return The output string.
310
311**/
312CHAR16 *
313GetTokenString (
314 IN EFI_STRING_ID Token,
315 IN EFI_HII_HANDLE HiiHandle
316 )
317{
318 EFI_STRING String;
319
320 if (HiiHandle == NULL) {
321 return NULL;
322 }
323
324 String = HiiGetString (HiiHandle, Token, NULL);
325 if (String == NULL) {
326 String = AllocateCopyPool (StrSize (mUnknownString), mUnknownString);
327 if (String == NULL) {
328 return NULL;
329 }
330 }
331
332 return (CHAR16 *)String;
333}
334
335/**
336 Converts the unicode character of the string from uppercase to lowercase.
337 This is a internal function.
338
339 @param[in] ConfigString String to be converted
340
341**/
342VOID
343EFIAPI
344HiiStringToLowercase (
345 IN EFI_STRING ConfigString
346 )
347{
348 EFI_STRING String;
349 BOOLEAN Lower;
350
351 //
352 // Convert all hex digits in range [A-F] in the configuration header to [a-f]
353 //
354 for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
355 if (*String == L'=') {
356 Lower = TRUE;
357 } else if (*String == L'&') {
358 Lower = FALSE;
359 } else if (Lower && (*String >= L'A') && (*String <= L'F')) {
360 *String = (CHAR16)(*String - L'A' + L'a');
361 }
362 }
363}
364
365/**
366 Evaluate if the result is a non-zero value.
367
368 @param[in] Result The result to be evaluated.
369
370 @retval TRUE It is a non-zero value.
371 @retval FALSE It is a zero value.
372
373**/
374BOOLEAN
375IsHiiValueTrue (
376 IN EFI_HII_VALUE *Result
377 )
378{
379 switch (Result->Type) {
380 case EFI_IFR_TYPE_BOOLEAN:
381 return Result->Value.b;
382
383 case EFI_IFR_TYPE_NUM_SIZE_8:
384 return (BOOLEAN)(Result->Value.u8 != 0);
385
386 case EFI_IFR_TYPE_NUM_SIZE_16:
387 return (BOOLEAN)(Result->Value.u16 != 0);
388
389 case EFI_IFR_TYPE_NUM_SIZE_32:
390 return (BOOLEAN)(Result->Value.u32 != 0);
391
392 case EFI_IFR_TYPE_NUM_SIZE_64:
393 return (BOOLEAN)(Result->Value.u64 != 0);
394
395 default:
396 return FALSE;
397 }
398}
399
400/**
401 Set a new string to string package.
402
403 @param[in] String A pointer to the Null-terminated Unicode string
404 to add or update in the String Package associated
405 with HiiHandle.
406 @param[in] HiiHandle A handle that was previously registered in the
407 HII Database.
408
409 @return the Id for this new string.
410
411**/
412EFI_STRING_ID
413NewHiiString (
414 IN CHAR16 *String,
415 IN EFI_HII_HANDLE HiiHandle
416 )
417{
418 EFI_STRING_ID StringId;
419
420 StringId = HiiSetString (HiiHandle, 0, String, NULL);
421 return StringId;
422}
423
424/**
425 Perform nosubmitif check for a Form.
426
427 @param[in] FormSet FormSet data structure.
428 @param[in] Form Form data structure.
429 @param[in] Question The Question to be validated.
430
431 @retval EFI_SUCCESS Form validation pass.
432 @retval other Form validation failed.
433
434**/
435EFI_STATUS
436ValidateNoSubmit (
437 IN HII_FORMSET *FormSet,
438 IN HII_FORM *Form,
439 IN HII_STATEMENT *Question
440 )
441{
442 EFI_STATUS Status;
443 LIST_ENTRY *Link;
444 LIST_ENTRY *ListHead;
445 HII_EXPRESSION *Expression;
446
447 ListHead = &Question->NoSubmitListHead;
448 Link = GetFirstNode (ListHead);
449 while (!IsNull (ListHead, Link)) {
450 Expression = HII_EXPRESSION_FROM_LINK (Link);
451
452 //
453 // Evaluate the expression
454 //
455 Status = EvaluateHiiExpression (FormSet, Form, Expression);
456 if (EFI_ERROR (Status)) {
457 return Status;
458 }
459
460 if (IsHiiValueTrue (&Expression->Result)) {
461 return EFI_NOT_READY;
462 }
463
464 Link = GetNextNode (ListHead, Link);
465 }
466
467 return EFI_SUCCESS;
468}
469
470/**
471 Perform NoSubmit check for each Form in FormSet.
472
473 @param[in] FormSet FormSet data structure.
474 @param[in,out] CurrentForm Current input form data structure.
475 @param[out] Statement The statement for this check.
476
477 @retval EFI_SUCCESS Form validation pass.
478 @retval other Form validation failed.
479
480**/
481EFI_STATUS
482NoSubmitCheck (
483 IN HII_FORMSET *FormSet,
484 IN OUT HII_FORM **CurrentForm,
485 OUT HII_STATEMENT **Statement
486 )
487{
488 EFI_STATUS Status;
489 LIST_ENTRY *Link;
490 HII_STATEMENT *Question;
491 HII_FORM *Form;
492 LIST_ENTRY *LinkForm;
493
494 LinkForm = GetFirstNode (&FormSet->FormListHead);
495 while (!IsNull (&FormSet->FormListHead, LinkForm)) {
496 Form = HII_FORM_FROM_LINK (LinkForm);
497 LinkForm = GetNextNode (&FormSet->FormListHead, LinkForm);
498
499 if ((*CurrentForm != NULL) && (*CurrentForm != Form)) {
500 continue;
501 }
502
503 Link = GetFirstNode (&Form->StatementListHead);
504 while (!IsNull (&Form->StatementListHead, Link)) {
505 Question = HII_STATEMENT_FROM_LINK (Link);
506 Status = ValidateNoSubmit (FormSet, Form, Question);
507 if (EFI_ERROR (Status)) {
508 if (*CurrentForm == NULL) {
509 *CurrentForm = Form;
510 }
511
512 if (Statement != NULL) {
513 *Statement = Question;
514 }
515
516 return Status;
517 }
518
519 Link = GetNextNode (&Form->StatementListHead, Link);
520 }
521 }
522
523 return EFI_SUCCESS;
524}
525
526/**
527 Allocate new memory and concatenate Source on the end of Destination.
528
529 @param Dest String to added to the end of.
530 @param Src String to concatenate.
531
532**/
533VOID
534NewStringCat (
535 IN OUT CHAR16 **Dest,
536 IN CHAR16 *Src
537 )
538{
539 CHAR16 *NewHiiString;
540 UINTN MaxLen;
541
542 if (*Dest == NULL) {
543 NewStringCopy (Dest, Src);
544 return;
545 }
546
547 MaxLen = (StrSize (*Dest) + StrSize (Src) - 2) / sizeof (CHAR16);
548 NewHiiString = AllocatePool (MaxLen * sizeof (CHAR16));
549 if (NewHiiString == NULL) {
550 return;
551 }
552
553 StrCpyS (NewHiiString, MaxLen, *Dest);
554 StrCatS (NewHiiString, MaxLen, Src);
555
556 FreePool (*Dest);
557 *Dest = NewHiiString;
558}
559
560/**
561 Convert setting of Buffer Storage or NameValue Storage to <ConfigResp>.
562
563 @param[in] Storage The Storage to be converted.
564 @param[in] ConfigResp The returned <ConfigResp>.
565 @param[in] ConfigRequest The ConfigRequest string.
566
567 @retval EFI_SUCCESS Convert success.
568 @retval EFI_INVALID_PARAMETER Incorrect storage type.
569
570**/
571EFI_STATUS
572StorageToConfigResp (
573 IN HII_FORMSET_STORAGE *Storage,
574 IN CHAR16 **ConfigResp,
575 IN CHAR16 *ConfigRequest
576 )
577{
578 EFI_STATUS Status;
579 EFI_STRING Progress;
580 LIST_ENTRY *Link;
581 HII_NAME_VALUE_NODE *Node;
582 UINT8 *SourceBuf;
583 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
584 EFI_STRING TempConfigRequest;
585 UINTN RequestStrSize;
586
587 Status = EFI_SUCCESS;
588
589 if (Storage->ConfigHdr == NULL) {
590 return EFI_INVALID_PARAMETER;
591 }
592
593 if (ConfigRequest != NULL) {
594 TempConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
595 if (TempConfigRequest == NULL) {
596 return EFI_OUT_OF_RESOURCES;
597 }
598 } else {
599 RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage->ConfigRequest) + 1) * sizeof (CHAR16);
600 TempConfigRequest = AllocatePool (RequestStrSize);
601 if (TempConfigRequest == NULL) {
602 return EFI_OUT_OF_RESOURCES;
603 }
604
605 UnicodeSPrint (
606 TempConfigRequest,
607 RequestStrSize,
608 L"%s%s",
609 Storage->ConfigHdr,
610 Storage->ConfigRequest
611 );
612 }
613
614 switch (Storage->Type) {
615 case EFI_HII_VARSTORE_BUFFER:
616 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
617
618 Status = gBS->LocateProtocol (
619 &gEfiHiiConfigRoutingProtocolGuid,
620 NULL,
621 (VOID **)&HiiConfigRouting
622 );
623 if (EFI_ERROR (Status)) {
624 return Status;
625 }
626
627 SourceBuf = Storage->Buffer;
628 Status = HiiConfigRouting->BlockToConfig (
629 HiiConfigRouting,
630 TempConfigRequest,
631 SourceBuf,
632 Storage->Size,
633 ConfigResp,
634 &Progress
635 );
636 break;
637
638 case EFI_HII_VARSTORE_NAME_VALUE:
639
640 *ConfigResp = NULL;
641 NewStringCat (ConfigResp, Storage->ConfigHdr);
642
643 Link = GetFirstNode (&Storage->NameValueList);
644 while (!IsNull (&Storage->NameValueList, Link)) {
645 Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
646
647 if (StrStr (TempConfigRequest, Node->Name) != NULL) {
648 NewStringCat (ConfigResp, L"&");
649 NewStringCat (ConfigResp, Node->Name);
650 NewStringCat (ConfigResp, L"=");
651 NewStringCat (ConfigResp, Node->Value);
652 }
653
654 Link = GetNextNode (&Storage->NameValueList, Link);
655 }
656
657 break;
658
659 case EFI_HII_VARSTORE_EFI_VARIABLE:
660 default:
661 Status = EFI_INVALID_PARAMETER;
662 break;
663 }
664
665 return Status;
666}
667
668/**
669 Convert <ConfigResp> to settings in Buffer Storage or NameValue Storage.
670
671 @param[in] Storage The Storage to receive the settings.
672 @param[in] ConfigResp The <ConfigResp> to be converted.
673
674 @retval EFI_SUCCESS Convert success.
675 @retval EFI_INVALID_PARAMETER Incorrect storage type.
676
677**/
678EFI_STATUS
679ConfigRespToStorage (
680 IN HII_FORMSET_STORAGE *Storage,
681 IN CHAR16 *ConfigResp
682 )
683{
684 EFI_STATUS Status;
685 EFI_STRING Progress;
686 UINTN BufferSize;
687 CHAR16 *StrPtr;
688 CHAR16 *Name;
689 CHAR16 *Value;
690 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
691
692 Status = EFI_SUCCESS;
693
694 switch (Storage->Type) {
695 case EFI_HII_VARSTORE_BUFFER:
696 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
697
698 Status = gBS->LocateProtocol (
699 &gEfiHiiConfigRoutingProtocolGuid,
700 NULL,
701 (VOID **)&HiiConfigRouting
702 );
703 if (EFI_ERROR (Status)) {
704 return Status;
705 }
706
707 BufferSize = Storage->Size;
708 Status = HiiConfigRouting->ConfigToBlock (
709 HiiConfigRouting,
710 ConfigResp,
711 Storage->Buffer,
712 &BufferSize,
713 &Progress
714 );
715 break;
716
717 case EFI_HII_VARSTORE_NAME_VALUE:
718 StrPtr = StrStr (ConfigResp, L"PATH");
719 if (StrPtr == NULL) {
720 break;
721 }
722
723 StrPtr = StrStr (ConfigResp, L"&");
724 while (StrPtr != NULL) {
725 //
726 // Skip '&'
727 //
728 StrPtr = StrPtr + 1;
729 Name = StrPtr;
730 StrPtr = StrStr (StrPtr, L"=");
731 if (StrPtr == NULL) {
732 break;
733 }
734
735 *StrPtr = 0;
736
737 //
738 // Skip '='
739 //
740 StrPtr = StrPtr + 1;
741 Value = StrPtr;
742 StrPtr = StrStr (StrPtr, L"&");
743 if (StrPtr != NULL) {
744 *StrPtr = 0;
745 }
746
747 SetValueByName (Storage, Name, Value, NULL);
748 }
749
750 break;
751
752 case EFI_HII_VARSTORE_EFI_VARIABLE:
753 default:
754 Status = EFI_INVALID_PARAMETER;
755 break;
756 }
757
758 return Status;
759}
760
761/**
762 Fetch the Ifr binary data of a FormSet.
763
764 @param[in] Handle PackageList Handle
765 @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not
766 specified (NULL or zero GUID), take the first
767 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
768 found in package list.
769 On output, GUID of the formset found(if not NULL).
770 @param[out] BinaryLength The length of the FormSet IFR binary.
771 @param[out] BinaryData The buffer designed to receive the FormSet.
772
773 @retval EFI_SUCCESS Buffer filled with the requested FormSet.
774 BufferLength was updated.
775 @retval EFI_INVALID_PARAMETER The handle is unknown.
776 @retval EFI_NOT_FOUND A form or FormSet on the requested handle cannot
777 be found with the requested FormId.
778
779**/
780EFI_STATUS
781GetIfrBinaryData (
782 IN EFI_HII_HANDLE Handle,
783 IN OUT EFI_GUID *FormSetGuid,
784 OUT UINTN *BinaryLength,
785 OUT UINT8 **BinaryData
786 )
787{
788 EFI_STATUS Status;
789 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
790 UINTN BufferSize;
791 UINT8 *Package;
792 UINT8 *OpCodeData;
793 UINT32 Offset;
794 UINT32 Offset2;
795 UINT32 PackageListLength;
796 EFI_HII_PACKAGE_HEADER PackageHeader;
797 UINT8 Index;
798 UINT8 NumberOfClassGuid;
799 BOOLEAN ClassGuidMatch;
800 EFI_GUID *ClassGuid;
801 EFI_GUID *ComparingGuid;
802 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
803
804 OpCodeData = NULL;
805 Package = NULL;
806 ZeroMem (&PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
807
808 //
809 // if FormSetGuid is NULL or zero GUID, return first Setup FormSet in the package list
810 //
811 if (FormSetGuid == NULL) {
812 ComparingGuid = &gZeroGuid;
813 } else {
814 ComparingGuid = FormSetGuid;
815 }
816
817 //
818 // Get HII PackageList
819 //
820 Status = gBS->LocateProtocol (
821 &gEfiHiiDatabaseProtocolGuid,
822 NULL,
823 (VOID **)&HiiDatabase
824 );
825 if (EFI_ERROR (Status)) {
826 *BinaryData = NULL;
827 return Status;
828 }
829
830 BufferSize = 0;
831 HiiPackageList = NULL;
832 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
833 if (Status == EFI_BUFFER_TOO_SMALL) {
834 HiiPackageList = AllocatePool (BufferSize);
835 if (HiiPackageList == NULL) {
836 return EFI_OUT_OF_RESOURCES;
837 }
838
839 Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
840 }
841
842 if (EFI_ERROR (Status)) {
843 if (HiiPackageList != NULL) {
844 FreePool (HiiPackageList);
845 }
846
847 *BinaryData = NULL;
848 return Status;
849 }
850
851 //
852 // Get Form package from this HII package List
853 //
854 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
855 Offset2 = 0;
856 CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
857
858 ClassGuidMatch = FALSE;
859 while (Offset < PackageListLength) {
860 Package = ((UINT8 *)HiiPackageList) + Offset;
861 CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
862
863 if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
864 //
865 // Search FormSet in this Form Package
866 //
867
868 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
869 while (Offset2 < PackageHeader.Length) {
870 OpCodeData = Package + Offset2;
871
872 if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
873 //
874 // Try to compare against formset GUID
875 //
876
877 if (IsZeroGuid (FormSetGuid) ||
878 CompareGuid (ComparingGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER))))
879 {
880 break;
881 }
882
883 if (((EFI_IFR_OP_HEADER *)OpCodeData)->Length > OFFSET_OF (EFI_IFR_FORM_SET, Flags)) {
884 //
885 // Try to compare against formset class GUID
886 //
887 NumberOfClassGuid = (UINT8)(((EFI_IFR_FORM_SET *)OpCodeData)->Flags & 0x3);
888 ClassGuid = (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_FORM_SET));
889 for (Index = 0; Index < NumberOfClassGuid; Index++) {
890 if (CompareGuid (ComparingGuid, ClassGuid + Index)) {
891 ClassGuidMatch = TRUE;
892 break;
893 }
894 }
895
896 if (ClassGuidMatch) {
897 break;
898 }
899 } else if (ComparingGuid == &gEfiHiiPlatformSetupFormsetGuid) {
900 ClassGuidMatch = TRUE;
901 break;
902 }
903 }
904
905 Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
906 }
907
908 if (Offset2 < PackageHeader.Length) {
909 //
910 // Target formset found
911 //
912 break;
913 }
914 }
915
916 Offset += PackageHeader.Length;
917 }
918
919 if (Offset >= PackageListLength) {
920 //
921 // Form package not found in this Package List
922 //
923 FreePool (HiiPackageList);
924 *BinaryData = NULL;
925 return EFI_NOT_FOUND;
926 }
927
928 if (FormSetGuid != NULL) {
929 //
930 // Return the FormSet GUID
931 //
932 CopyMem (FormSetGuid, &((EFI_IFR_FORM_SET *)OpCodeData)->Guid, sizeof (EFI_GUID));
933 }
934
935 //
936 // To determine the length of a whole FormSet IFR binary, one have to parse all the Opcodes
937 // in this FormSet; So, here just simply copy the data from start of a FormSet to the end
938 // of the Form Package.
939 //
940
941 *BinaryLength = PackageHeader.Length - Offset2;
942 *BinaryData = AllocateCopyPool (*BinaryLength, OpCodeData);
943 FreePool (HiiPackageList);
944 if (*BinaryData == NULL) {
945 return EFI_OUT_OF_RESOURCES;
946 }
947
948 return EFI_SUCCESS;
949}
950
951/**
952 Check if the requested element is in storage.
953
954 @param Storage The storage contains elements.
955 @param RequestElement The element to be searched.
956
957**/
958BOOLEAN
959ElementValidation (
960 IN HII_FORMSET_STORAGE *Storage,
961 IN CHAR16 *RequestElement
962 )
963{
964 return StrStr (Storage->ConfigRequest, RequestElement) != NULL ? TRUE : FALSE;
965}
966
967/**
968 Append the Request element to the Config Request.
969
970 @param ConfigRequest Current ConfigRequest info.
971 @param SpareStrLen Current remain free buffer for config request.
972 @param RequestElement New Request element.
973
974**/
975VOID
976AppendConfigRequest (
977 IN OUT CHAR16 **ConfigRequest,
978 IN OUT UINTN *SpareStrLen,
979 IN CHAR16 *RequestElement
980 )
981{
982 CHAR16 *NewStr;
983 UINTN StringSize;
984 UINTN StrLength;
985 UINTN MaxLen;
986
987 StrLength = StrLen (RequestElement);
988 StringSize = (*ConfigRequest != NULL) ? StrSize (*ConfigRequest) : sizeof (CHAR16);
989 MaxLen = StringSize / sizeof (CHAR16) + *SpareStrLen;
990
991 //
992 // Append <RequestElement> to <ConfigRequest>
993 //
994 if (StrLength > *SpareStrLen) {
995 //
996 // Old String buffer is not sufficient for RequestElement, allocate a new one
997 //
998 MaxLen = StringSize / sizeof (CHAR16) + CONFIG_REQUEST_STRING_INCREMENTAL;
999 NewStr = AllocatePool (MaxLen * sizeof (CHAR16));
1000 if (NewStr == NULL) {
1001 return;
1002 }
1003
1004 if (*ConfigRequest != NULL) {
1005 CopyMem (NewStr, *ConfigRequest, StringSize);
1006 FreePool (*ConfigRequest);
1007 } else {
1008 NewStr[0] = L'\0';
1009 }
1010
1011 *ConfigRequest = NewStr;
1012 *SpareStrLen = CONFIG_REQUEST_STRING_INCREMENTAL;
1013 }
1014
1015 StrCatS (*ConfigRequest, MaxLen, RequestElement);
1016 *SpareStrLen -= StrLength;
1017}
1018
1019/**
1020 Adjust the config request info, remove the request elements which already in AllConfigRequest string.
1021
1022 @param Storage Form set Storage.
1023 @param Request The input request string.
1024 @param RespString Whether the input is ConfigRequest or ConfigResp format.
1025
1026 @retval TRUE Has element not covered by current used elements, need to continue to call ExtractConfig
1027 @retval FALSE All elements covered by current used elements.
1028
1029**/
1030BOOLEAN
1031ConfigRequestAdjust (
1032 IN HII_FORMSET_STORAGE *Storage,
1033 IN CHAR16 *Request,
1034 IN BOOLEAN RespString
1035 )
1036{
1037 CHAR16 *RequestElement;
1038 CHAR16 *NextRequestElement;
1039 CHAR16 *NextElementBackup;
1040 CHAR16 *SearchKey;
1041 CHAR16 *ValueKey;
1042 BOOLEAN RetVal;
1043 CHAR16 *ConfigRequest;
1044
1045 RetVal = FALSE;
1046 NextElementBackup = NULL;
1047 ValueKey = NULL;
1048
1049 if (Request != NULL) {
1050 ConfigRequest = Request;
1051 } else {
1052 ConfigRequest = Storage->ConfigRequest;
1053 }
1054
1055 if (Storage->ConfigRequest == NULL) {
1056 Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
1057 if (Storage->ConfigRequest == NULL) {
1058 return FALSE;
1059 }
1060
1061 return TRUE;
1062 }
1063
1064 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1065 //
1066 // "&Name1&Name2" section for EFI_HII_VARSTORE_NAME_VALUE storage
1067 //
1068 SearchKey = L"&";
1069 } else {
1070 //
1071 // "&OFFSET=####&WIDTH=####" section for EFI_HII_VARSTORE_BUFFER storage
1072 //
1073 SearchKey = L"&OFFSET";
1074 ValueKey = L"&VALUE";
1075 }
1076
1077 //
1078 // Find SearchKey storage
1079 //
1080 if (Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
1081 RequestElement = StrStr (ConfigRequest, L"PATH");
1082 if (RequestElement == NULL) {
1083 return FALSE;
1084 }
1085
1086 RequestElement = StrStr (RequestElement, SearchKey);
1087 } else {
1088 RequestElement = StrStr (ConfigRequest, SearchKey);
1089 }
1090
1091 while (RequestElement != NULL) {
1092 //
1093 // +1 to avoid find header itself.
1094 //
1095 NextRequestElement = StrStr (RequestElement + 1, SearchKey);
1096
1097 //
1098 // The last Request element in configRequest string.
1099 //
1100 if (NextRequestElement != NULL) {
1101 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
1102 NextElementBackup = NextRequestElement;
1103 NextRequestElement = StrStr (RequestElement, ValueKey);
1104 if (NextRequestElement == NULL) {
1105 return FALSE;
1106 }
1107 }
1108
1109 //
1110 // Replace "&" with '\0'.
1111 //
1112 *NextRequestElement = L'\0';
1113 } else {
1114 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
1115 NextElementBackup = NextRequestElement;
1116 NextRequestElement = StrStr (RequestElement, ValueKey);
1117 if (NextRequestElement == NULL) {
1118 return FALSE;
1119 }
1120
1121 //
1122 // Replace "&" with '\0'.
1123 //
1124 *NextRequestElement = L'\0';
1125 }
1126 }
1127
1128 if (!ElementValidation (Storage, RequestElement)) {
1129 //
1130 // Add this element to the Storage->BrowserStorage->AllRequestElement.
1131 //
1132 AppendConfigRequest (&Storage->ConfigRequest, &Storage->SpareStrLen, RequestElement);
1133 RetVal = TRUE;
1134 }
1135
1136 if (NextRequestElement != NULL) {
1137 //
1138 // Restore '&' with '\0' for later used.
1139 //
1140 *NextRequestElement = L'&';
1141 }
1142
1143 if (RespString && (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER)) {
1144 RequestElement = NextElementBackup;
1145 } else {
1146 RequestElement = NextRequestElement;
1147 }
1148 }
1149
1150 return RetVal;
1151}
1152
1153/**
1154 Fill storage with settings requested from Configuration Driver.
1155
1156 @param[in] FormSet FormSet data structure.
1157 @param[in] Storage Buffer Storage.
1158
1159**/
1160VOID
1161LoadFormSetStorage (
1162 IN HII_FORMSET *FormSet,
1163 IN HII_FORMSET_STORAGE *Storage
1164 )
1165{
1166 EFI_STATUS Status;
1167 EFI_STRING Progress;
1168 EFI_STRING Result;
1169 CHAR16 *StrPtr;
1170 EFI_STRING ConfigRequest;
1171 UINTN RequestStrSize;
1172 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1173
1174 ConfigRequest = NULL;
1175
1176 switch (Storage->Type) {
1177 case EFI_HII_VARSTORE_EFI_VARIABLE:
1178 return;
1179
1180 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
1181 #if 0 // bug fix for efivarstore
1182 if (Storage->ConfigRequest != NULL) {
1183 ConfigRequestAdjust (Storage, Storage->ConfigRequest, FALSE);
1184 return;
1185 }
1186
1187 #endif
1188 break;
1189
1190 case EFI_HII_VARSTORE_BUFFER:
1191 case EFI_HII_VARSTORE_NAME_VALUE:
1192 //
1193 // Skip if there is no RequestElement.
1194 //
1195 if (Storage->ElementCount == 0) {
1196 return;
1197 }
1198
1199 break;
1200
1201 default:
1202 return;
1203 }
1204
1205 if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
1206 //
1207 // Create the config request string to get all fields for this storage.
1208 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1209 // followed by "&OFFSET=0&WIDTH=WWWW"followed by a Null-terminator
1210 //
1211 RequestStrSize = StrSize (Storage->ConfigHdr) + 20 * sizeof (CHAR16);
1212 ConfigRequest = AllocatePool (RequestStrSize);
1213 if (ConfigRequest == NULL) {
1214 return;
1215 }
1216
1217 UnicodeSPrint (
1218 ConfigRequest,
1219 RequestStrSize,
1220 L"%s&OFFSET=0&WIDTH=%04x",
1221 Storage->ConfigHdr,
1222 Storage->Size
1223 );
1224 } else {
1225 RequestStrSize = (StrLen (Storage->ConfigHdr) + StrLen (Storage->ConfigRequest) + 1) * sizeof (CHAR16);
1226 ConfigRequest = AllocatePool (RequestStrSize);
1227 if (ConfigRequest == NULL) {
1228 return;
1229 }
1230
1231 UnicodeSPrint (
1232 ConfigRequest,
1233 RequestStrSize,
1234 L"%s%s",
1235 Storage->ConfigHdr,
1236 Storage->ConfigRequest
1237 );
1238 }
1239
1240 //
1241 // Request current settings from Configuration Driver
1242 //
1243 Status = gBS->LocateProtocol (
1244 &gEfiHiiConfigRoutingProtocolGuid,
1245 NULL,
1246 (VOID **)&HiiConfigRouting
1247 );
1248 if (EFI_ERROR (Status)) {
1249 return;
1250 }
1251
1252 Status = HiiConfigRouting->ExtractConfig (
1253 HiiConfigRouting,
1254 ConfigRequest,
1255 &Progress,
1256 &Result
1257 );
1258 if (!EFI_ERROR (Status)) {
1259 //
1260 // Convert Result from <ConfigAltResp> to <ConfigResp>
1261 //
1262 StrPtr = StrStr (Result, L"&GUID=");
1263 if (StrPtr != NULL) {
1264 *StrPtr = L'\0';
1265 }
1266
1267 Status = ConfigRespToStorage (Storage, Result);
1268 FreePool (Result);
1269 }
1270
1271 Storage->ConfigRequest = AllocateCopyPool (StrSize (ConfigRequest), ConfigRequest);
1272 if (Storage->ConfigRequest == NULL) {
1273 if (ConfigRequest != NULL) {
1274 FreePool (ConfigRequest);
1275 }
1276
1277 return;
1278 }
1279
1280 if (Storage->Type != EFI_HII_VARSTORE_NAME_VALUE) {
1281 if (ConfigRequest != NULL) {
1282 FreePool (ConfigRequest);
1283 }
1284 }
1285}
1286
1287/**
1288 Zero extend integer/boolean/date/time to UINT64 for comparing.
1289
1290 @param[in] Value HII Value to be converted.
1291
1292**/
1293VOID
1294ExtendValueToU64 (
1295 IN HII_STATEMENT_VALUE *Value
1296 )
1297{
1298 UINT64 Temp;
1299
1300 Temp = 0;
1301 switch (Value->Type) {
1302 case EFI_IFR_TYPE_NUM_SIZE_8:
1303 Temp = Value->Value.u8;
1304 break;
1305
1306 case EFI_IFR_TYPE_NUM_SIZE_16:
1307 Temp = Value->Value.u16;
1308 break;
1309
1310 case EFI_IFR_TYPE_NUM_SIZE_32:
1311 Temp = Value->Value.u32;
1312 break;
1313
1314 case EFI_IFR_TYPE_BOOLEAN:
1315 Temp = Value->Value.b;
1316 break;
1317
1318 case EFI_IFR_TYPE_TIME:
1319 Temp = Value->Value.u32 & 0xffffff;
1320 break;
1321
1322 case EFI_IFR_TYPE_DATE:
1323 Temp = Value->Value.u32;
1324 break;
1325
1326 default:
1327 return;
1328 }
1329
1330 Value->Value.u64 = Temp;
1331}
1332
1333/**
1334 Pop an element from the stack.
1335
1336 @param Stack On input: old stack
1337 @param StackPtr On input: old stack pointer; On output: new stack pointer
1338 @param Data Data to pop.
1339
1340 @retval EFI_SUCCESS The value was popped onto the stack.
1341 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
1342
1343**/
1344EFI_STATUS
1345PopStack (
1346 IN EFI_HII_VALUE *Stack,
1347 IN OUT EFI_HII_VALUE **StackPtr,
1348 OUT EFI_HII_VALUE *Data
1349 );
1350
1351/**
1352 Push an element onto the Boolean Stack.
1353
1354 @param Stack On input: old stack; On output: new stack
1355 @param StackPtr On input: old stack pointer; On output: new stack
1356 pointer
1357 @param StackEnd On input: old stack end; On output: new stack end
1358 @param Data Data to push.
1359
1360 @retval EFI_SUCCESS Push stack success.
1361
1362**/
1363EFI_STATUS
1364PushStack (
1365 IN OUT EFI_HII_VALUE **Stack,
1366 IN OUT EFI_HII_VALUE **StackPtr,
1367 IN OUT EFI_HII_VALUE **StackEnd,
1368 IN EFI_HII_VALUE *Data
1369 );
1370
1371/**
1372 Initialize the internal data structure of a FormSet.
1373
1374 @param[in] Handle PackageList Handle
1375 @param[in,out] FormSetGuid On input, GUID or class GUID of a formset. If not
1376 specified (NULL or zero GUID), take the first
1377 FormSet with class GUID EFI_HII_PLATFORM_SETUP_FORMSET_GUID
1378 found in package list.
1379 On output, GUID of the formset found(if not NULL).
1380 @param[out] FormSet FormSet data structure.
1381
1382 @retval EFI_SUCCESS The function completed successfully.
1383 @retval EFI_NOT_FOUND The specified FormSet could not be found.
1384
1385**/
1386EFI_STATUS
1387CreateFormSetFromHiiHandle (
1388 IN EFI_HII_HANDLE Handle,
1389 IN OUT EFI_GUID *FormSetGuid,
1390 OUT HII_FORMSET *FormSet
1391 );
1392
1393/**
1394 Initialize a Formset and get current setting for Questions.
1395
1396 @param[in,out] FormSet FormSet data structure.
1397
1398**/
1399VOID
1400InitializeFormSet (
1401 IN OUT HII_FORMSET *FormSet
1402 );
1403
1404/**
1405 Get Value for given Name from a NameValue Storage.
1406
1407 @param[in] Storage The NameValue Storage.
1408 @param[in] Name The Name.
1409 @param[in,out] Value The returned Value.
1410
1411 @retval EFI_SUCCESS Value found for given Name.
1412 @retval EFI_NOT_FOUND No such Name found in NameValue storage.
1413 @retval EFI_INVALID_PARAMETER Storage or Value is NULL.
1414
1415**/
1416EFI_STATUS
1417GetValueByName (
1418 IN HII_FORMSET_STORAGE *Storage,
1419 IN CHAR16 *Name,
1420 IN OUT CHAR16 **Value
1421 )
1422{
1423 LIST_ENTRY *Link;
1424 HII_NAME_VALUE_NODE *Node;
1425
1426 if ((Storage == NULL) || (Value == NULL)) {
1427 return EFI_INVALID_PARAMETER;
1428 }
1429
1430 *Value = NULL;
1431
1432 Link = GetFirstNode (&Storage->NameValueList);
1433 while (!IsNull (&Storage->NameValueList, Link)) {
1434 Node = HII_NAME_VALUE_NODE_FROM_LINK (Link);
1435
1436 if (StrCmp (Name, Node->Name) == 0) {
1437 NewStringCopy (Value, Node->Value);
1438 return EFI_SUCCESS;
1439 }
1440
1441 Link = GetNextNode (&Storage->NameValueList, Link);
1442 }
1443
1444 return EFI_NOT_FOUND;
1445}
1446
1447/**
1448 Get Question's current Value.
1449
1450 @param[in] FormSet FormSet data structure.
1451 @param[in] Form Form data structure.
1452 @param[in,out] Question Question to be initialized.
1453 @param[in] GetValueFrom Where to get value, may from editbuffer, buffer or hii driver.
1454
1455 @retval EFI_SUCCESS The function completed successfully.
1456 @retval EFI_INVALID_PARAMETER Formset, Form or Question is NULL.
1457
1458**/
1459EFI_STATUS
1460GetQuestionValue (
1461 IN HII_FORMSET *FormSet,
1462 IN HII_FORM *Form,
1463 IN OUT HII_STATEMENT *Question,
1464 IN GET_SET_QUESTION_VALUE_WITH GetValueFrom
1465 )
1466{
1467 EFI_STATUS Status;
1468 BOOLEAN Enabled;
1469 BOOLEAN Pending;
1470 UINT8 *Dst;
1471 UINTN StorageWidth;
1472 EFI_TIME EfiTime;
1473 HII_FORMSET_STORAGE *Storage;
1474 HII_FORMSET_STORAGE *FormsetStorage;
1475 EFI_IFR_TYPE_VALUE *QuestionValue;
1476 CHAR16 *ConfigRequest;
1477 CHAR16 *Progress;
1478 CHAR16 *Result;
1479 CHAR16 *Value;
1480 UINTN Length;
1481 BOOLEAN IsBufferStorage;
1482 UINTN MaxLen;
1483 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
1484
1485 if ((FormSet == NULL) || (Form == NULL) || (Question == NULL)) {
1486 return EFI_INVALID_PARAMETER;
1487 }
1488
1489 Status = EFI_SUCCESS;
1490 Value = NULL;
1491 Result = NULL;
1492
1493 if (GetValueFrom >= GetSetValueWithMax) {
1494 return EFI_INVALID_PARAMETER;
1495 }
1496
1497 //
1498 // Question value is provided by an Expression, evaluate it
1499 //
1500 if (Question->ValueExpression != NULL) {
1501 Status = EvaluateHiiExpression (FormSet, Form, Question->ValueExpression);
1502 if (!EFI_ERROR (Status)) {
1503 if (Question->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
1504 ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question->Value.Buffer != NULL);
1505 if (Question->StorageWidth > Question->ValueExpression->Result.BufferLen) {
1506 CopyMem (Question->Value.Buffer, Question->ValueExpression->Result.Buffer, Question->ValueExpression->Result.BufferLen);
1507 Question->Value.BufferLen = Question->ValueExpression->Result.BufferLen;
1508 } else {
1509 CopyMem (Question->Value.Buffer, Question->ValueExpression->Result.Buffer, Question->StorageWidth);
1510 Question->Value.BufferLen = Question->StorageWidth;
1511 }
1512
1513 FreePool (Question->ValueExpression->Result.Buffer);
1514 }
1515
1516 Question->Value.Type = Question->ValueExpression->Result.Type;
1517 CopyMem (&Question->Value.Value, &Question->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
1518 }
1519
1520 return Status;
1521 }
1522
1523 //
1524 // Get question value by read expression.
1525 //
1526 if ((Question->ReadExpression != NULL) && (Form->FormType == STANDARD_MAP_FORM_TYPE)) {
1527 Status = EvaluateHiiExpression (FormSet, Form, Question->ReadExpression);
1528 if (!EFI_ERROR (Status) &&
1529 ((Question->ReadExpression->Result.Type < EFI_IFR_TYPE_OTHER) || (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER)))
1530 {
1531 //
1532 // Only update question value to the valid result.
1533 //
1534 if (Question->ReadExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
1535 ASSERT (Question->Value.Type == EFI_IFR_TYPE_BUFFER && Question->Value.Buffer != NULL);
1536 if (Question->StorageWidth > Question->ReadExpression->Result.BufferLen) {
1537 CopyMem (Question->Value.Buffer, Question->ReadExpression->Result.Buffer, Question->ReadExpression->Result.BufferLen);
1538 Question->Value.BufferLen = Question->ReadExpression->Result.BufferLen;
1539 } else {
1540 CopyMem (Question->Value.Buffer, Question->ReadExpression->Result.Buffer, Question->StorageWidth);
1541 Question->Value.BufferLen = Question->StorageWidth;
1542 }
1543
1544 FreePool (Question->ReadExpression->Result.Buffer);
1545 }
1546
1547 Question->Value.Type = Question->ReadExpression->Result.Type;
1548 CopyMem (&Question->Value.Value, &Question->ReadExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
1549 return EFI_SUCCESS;
1550 }
1551 }
1552
1553 //
1554 // Question value is provided by RTC
1555 //
1556 Storage = Question->Storage;
1557 QuestionValue = &Question->Value.Value;
1558 if (Storage == NULL) {
1559 //
1560 // It's a Question without storage, or RTC date/time
1561 //
1562 if ((Question->Operand == EFI_IFR_DATE_OP) || (Question->Operand == EFI_IFR_TIME_OP)) {
1563 //
1564 // Date and time define the same Flags bit
1565 //
1566 switch (Question->ExtraData.Flags & EFI_QF_DATE_STORAGE) {
1567 case QF_DATE_STORAGE_TIME:
1568 Status = gRT->GetTime (&EfiTime, NULL);
1569 break;
1570
1571 case QF_DATE_STORAGE_WAKEUP:
1572 Status = gRT->GetWakeupTime (&Enabled, &Pending, &EfiTime);
1573 break;
1574
1575 case QF_DATE_STORAGE_NORMAL:
1576 default:
1577 //
1578 // For date/time without storage
1579 //
1580 return EFI_SUCCESS;
1581 }
1582
1583 if (EFI_ERROR (Status)) {
1584 if (Question->Operand == EFI_IFR_DATE_OP) {
1585 QuestionValue->date.Year = 0xff;
1586 QuestionValue->date.Month = 0xff;
1587 QuestionValue->date.Day = 0xff;
1588 } else {
1589 QuestionValue->time.Hour = 0xff;
1590 QuestionValue->time.Minute = 0xff;
1591 QuestionValue->time.Second = 0xff;
1592 }
1593
1594 return EFI_SUCCESS;
1595 }
1596
1597 if (Question->Operand == EFI_IFR_DATE_OP) {
1598 QuestionValue->date.Year = EfiTime.Year;
1599 QuestionValue->date.Month = EfiTime.Month;
1600 QuestionValue->date.Day = EfiTime.Day;
1601 } else {
1602 QuestionValue->time.Hour = EfiTime.Hour;
1603 QuestionValue->time.Minute = EfiTime.Minute;
1604 QuestionValue->time.Second = EfiTime.Second;
1605 }
1606 }
1607
1608 return EFI_SUCCESS;
1609 }
1610
1611 //
1612 // Question value is provided by EFI variable
1613 //
1614 StorageWidth = Question->StorageWidth;
1615 if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
1616 if (Question->Value.Buffer != NULL) {
1617 Dst = Question->Value.Buffer;
1618 } else {
1619 Dst = (UINT8 *)QuestionValue;
1620 }
1621
1622 Status = gRT->GetVariable (
1623 Question->VariableName,
1624 &Storage->Guid,
1625 NULL,
1626 &StorageWidth,
1627 Dst
1628 );
1629 //
1630 // Always return success, even this EFI variable doesn't exist
1631 //
1632 return EFI_SUCCESS;
1633 }
1634
1635 //
1636 // Question Value is provided by Buffer Storage or NameValue Storage
1637 //
1638 if (Question->Value.Buffer != NULL) {
1639 //
1640 // This Question is password or orderedlist
1641 //
1642 Dst = Question->Value.Buffer;
1643 } else {
1644 //
1645 // Other type of Questions
1646 //
1647 Dst = (UINT8 *)&Question->Value.Value;
1648 }
1649
1650 if ((Storage->Type == EFI_HII_VARSTORE_BUFFER) ||
1651 (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER))
1652 {
1653 IsBufferStorage = TRUE;
1654 } else {
1655 IsBufferStorage = FALSE;
1656 }
1657
1658 if (GetValueFrom == GetSetValueWithBuffer ) {
1659 if (IsBufferStorage) {
1660 //
1661 // Copy from storage Edit buffer
1662 // If the Question refer to bit filed, get the value in the related bit filed.
1663 //
1664 if (Question->QuestionReferToBitField) {
1665 GetBitsQuestionValue (Question, Storage->Buffer + Question->VarStoreInfo.VarOffset, &Question->Value);
1666 } else {
1667 CopyMem (Dst, Storage->Buffer + Question->VarStoreInfo.VarOffset, StorageWidth);
1668 }
1669 } else {
1670 Value = NULL;
1671 Status = GetValueByName (Storage, Question->VariableName, &Value);
1672 if (EFI_ERROR (Status)) {
1673 return Status;
1674 }
1675
1676 ASSERT (Value != NULL);
1677 Status = BufferToQuestionValue (Question, Value, &Question->Value);
1678 FreePool (Value);
1679 }
1680 } else {
1681 FormsetStorage = GetFstStgFromVarId (FormSet, Question->VarStoreId);
1682 ASSERT (FormsetStorage != NULL);
1683 //
1684 // <ConfigRequest> ::= <ConfigHdr> + <BlockName> ||
1685 // <ConfigHdr> + "&" + <VariableName>
1686 //
1687 if (IsBufferStorage) {
1688 Length = StrLen (FormsetStorage->ConfigHdr);
1689 Length += StrLen (Question->BlockName);
1690 } else {
1691 Length = StrLen (FormsetStorage->ConfigHdr);
1692 Length += StrLen (Question->VariableName) + 1;
1693 }
1694
1695 // Allocate buffer include '\0'
1696 MaxLen = Length + 1;
1697 ConfigRequest = AllocatePool (MaxLen * sizeof (CHAR16));
1698 ASSERT (ConfigRequest != NULL);
1699
1700 StrCpyS (ConfigRequest, MaxLen, FormsetStorage->ConfigHdr);
1701 if (IsBufferStorage) {
1702 StrCatS (ConfigRequest, MaxLen, Question->BlockName);
1703 } else {
1704 StrCatS (ConfigRequest, MaxLen, L"&");
1705 StrCatS (ConfigRequest, MaxLen, Question->VariableName);
1706 }
1707
1708 Status = gBS->LocateProtocol (
1709 &gEfiHiiConfigRoutingProtocolGuid,
1710 NULL,
1711 (VOID **)&HiiConfigRouting
1712 );
1713 if (EFI_ERROR (Status)) {
1714 return Status;
1715 }
1716
1717 //
1718 // Request current settings from Configuration Driver
1719 //
1720 Status = HiiConfigRouting->ExtractConfig (
1721 HiiConfigRouting,
1722 ConfigRequest,
1723 &Progress,
1724 &Result
1725 );
1726 FreePool (ConfigRequest);
1727 if (EFI_ERROR (Status)) {
1728 return Status;
1729 }
1730
1731 //
1732 // Skip <ConfigRequest>
1733 //
1734 if (IsBufferStorage) {
1735 Value = StrStr (Result, L"&VALUE");
1736 if (Value == NULL) {
1737 FreePool (Result);
1738 return EFI_NOT_FOUND;
1739 }
1740
1741 //
1742 // Skip "&VALUE"
1743 //
1744 Value = Value + 6;
1745 } else {
1746 Value = Result + Length;
1747 }
1748
1749 if (*Value != '=') {
1750 FreePool (Result);
1751 return EFI_NOT_FOUND;
1752 }
1753
1754 //
1755 // Skip '=', point to value
1756 //
1757 Value = Value + 1;
1758
1759 Status = BufferToQuestionValue (Question, Value, &Question->Value);
1760 if (EFI_ERROR (Status)) {
1761 FreePool (Result);
1762 return Status;
1763 }
1764
1765 //
1766 // Synchronize Buffer
1767 //
1768 if (IsBufferStorage) {
1769 CopyMem (Storage->Buffer + Question->VarStoreInfo.VarOffset, Dst, StorageWidth);
1770 } else {
1771 SetValueByName (Storage, Question->VariableName, Value, NULL);
1772 }
1773
1774 if (Result != NULL) {
1775 FreePool (Result);
1776 }
1777 }
1778
1779 return Status;
1780}
1781
1782/**
1783 Convert the input Unicode character to upper.
1784
1785 @param[in] String Th Unicode character to be converted.
1786
1787**/
1788VOID
1789IfrStrToUpper (
1790 IN CHAR16 *String
1791 )
1792{
1793 if (String == NULL) {
1794 return;
1795 }
1796
1797 while (*String != 0) {
1798 if ((*String >= 'a') && (*String <= 'z')) {
1799 *String = (UINT16)((*String) & ((UINT16) ~0x20));
1800 }
1801
1802 String++;
1803 }
1804}
1805
1806/**
1807 Check whether this value type can be transfer to EFI_IFR_TYPE_BUFFER type.
1808
1809 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1810 EFI_IFR_TYPE_BUFFER when do the value compare.
1811
1812 @param[in] Value Expression value to compare on.
1813
1814 @retval TRUE This value type can be transferred to EFI_IFR_TYPE_BUFFER type.
1815 @retval FALSE This value type can't be transferred to EFI_IFR_TYPE_BUFFER type.
1816
1817**/
1818BOOLEAN
1819IsTypeInBuffer (
1820 IN EFI_HII_VALUE *Value
1821 )
1822{
1823 if (Value == NULL) {
1824 return FALSE;
1825 }
1826
1827 switch (Value->Type) {
1828 case EFI_IFR_TYPE_BUFFER:
1829 case EFI_IFR_TYPE_DATE:
1830 case EFI_IFR_TYPE_TIME:
1831 case EFI_IFR_TYPE_REF:
1832 return TRUE;
1833
1834 default:
1835 return FALSE;
1836 }
1837}
1838
1839/**
1840 Check whether this value type can be transfer to EFI_IFR_TYPE_UINT64
1841
1842 @param[in] Value Expression value to compare on.
1843
1844 @retval TRUE This value type can be transferred to EFI_IFR_TYPE_BUFFER type.
1845 @retval FALSE This value type can't be transferred to EFI_IFR_TYPE_BUFFER type.
1846
1847**/
1848BOOLEAN
1849IsTypeInUINT64 (
1850 IN EFI_HII_VALUE *Value
1851 )
1852{
1853 if (Value == NULL) {
1854 return FALSE;
1855 }
1856
1857 switch (Value->Type) {
1858 case EFI_IFR_TYPE_NUM_SIZE_8:
1859 case EFI_IFR_TYPE_NUM_SIZE_16:
1860 case EFI_IFR_TYPE_NUM_SIZE_32:
1861 case EFI_IFR_TYPE_NUM_SIZE_64:
1862 case EFI_IFR_TYPE_BOOLEAN:
1863 return TRUE;
1864
1865 default:
1866 return FALSE;
1867 }
1868}
1869
1870/**
1871 Return the buffer pointer for this value.
1872
1873 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1874 EFI_IFR_TYPE_BUFFER when do the value compare.
1875
1876 @param[in] Value Expression value to compare on.
1877
1878 @retval Buf Return the buffer pointer.
1879
1880**/
1881UINT8 *
1882GetBufferForValue (
1883 IN EFI_HII_VALUE *Value
1884 )
1885{
1886 if (Value == NULL) {
1887 return NULL;
1888 }
1889
1890 switch (Value->Type) {
1891 case EFI_IFR_TYPE_BUFFER:
1892 return Value->Buffer;
1893
1894 case EFI_IFR_TYPE_DATE:
1895 return (UINT8 *)(&Value->Value.date);
1896
1897 case EFI_IFR_TYPE_TIME:
1898 return (UINT8 *)(&Value->Value.time);
1899
1900 case EFI_IFR_TYPE_REF:
1901 return (UINT8 *)(&Value->Value.ref);
1902
1903 default:
1904 return NULL;
1905 }
1906}
1907
1908/**
1909 Return the buffer length for this value.
1910
1911 EFI_IFR_TYPE_REF, EFI_IFR_TYPE_DATE and EFI_IFR_TYPE_TIME are converted to
1912 EFI_IFR_TYPE_BUFFER when do the value compare.
1913
1914 @param[in] Value Expression value to compare on.
1915
1916 @retval BufLen Return the buffer length.
1917
1918**/
1919UINT16
1920GetLengthForValue (
1921 IN EFI_HII_VALUE *Value
1922 )
1923{
1924 if (Value == NULL) {
1925 return 0;
1926 }
1927
1928 switch (Value->Type) {
1929 case EFI_IFR_TYPE_BUFFER:
1930 return Value->BufferLen;
1931
1932 case EFI_IFR_TYPE_DATE:
1933 return (UINT16)sizeof (EFI_HII_DATE);
1934
1935 case EFI_IFR_TYPE_TIME:
1936 return (UINT16)sizeof (EFI_HII_TIME);
1937
1938 case EFI_IFR_TYPE_REF:
1939 return (UINT16)sizeof (EFI_HII_REF);
1940
1941 default:
1942 return 0;
1943 }
1944}
1945
1946/**
1947 Get UINT64 type value.
1948
1949 @param[in] Value Input Hii value.
1950
1951 @retval UINT64 Return the UINT64 type value.
1952
1953**/
1954UINT64
1955HiiValueToUINT64 (
1956 IN EFI_HII_VALUE *Value
1957 )
1958{
1959 UINT64 RetVal;
1960
1961 if (Value == NULL) {
1962 return 0;
1963 }
1964
1965 RetVal = 0;
1966
1967 switch (Value->Type) {
1968 case EFI_IFR_TYPE_NUM_SIZE_8:
1969 RetVal = Value->Value.u8;
1970 break;
1971
1972 case EFI_IFR_TYPE_NUM_SIZE_16:
1973 RetVal = Value->Value.u16;
1974 break;
1975
1976 case EFI_IFR_TYPE_NUM_SIZE_32:
1977 RetVal = Value->Value.u32;
1978 break;
1979
1980 case EFI_IFR_TYPE_BOOLEAN:
1981 RetVal = Value->Value.b;
1982 break;
1983
1984 case EFI_IFR_TYPE_DATE:
1985 RetVal = *(UINT64 *)&Value->Value.date;
1986 break;
1987
1988 case EFI_IFR_TYPE_TIME:
1989 RetVal = (*(UINT64 *)&Value->Value.time) & 0xffffff;
1990 break;
1991
1992 default:
1993 RetVal = Value->Value.u64;
1994 break;
1995 }
1996
1997 return RetVal;
1998}
1999
2000/**
2001 Compare two Hii value.
2002
2003 @param[in] Value1 Expression value to compare on left-hand.
2004 @param[in] Value2 Expression value to compare on right-hand.
2005 @param[out] Result Return value after compare.
2006 retval 0 Two operators equal.
2007 return Positive value if Value1 is greater than Value2.
2008 retval Negative value if Value1 is less than Value2.
2009 @param[in] HiiHandle Only required for string compare.
2010
2011 @retval other Could not perform compare on two values.
2012 @retval EFI_SUCCESS Compare the value success.
2013 @retval EFI_INVALID_PARAMETER Value1, Value2 or Result is NULL.
2014
2015**/
2016EFI_STATUS
2017CompareHiiValue (
2018 IN EFI_HII_VALUE *Value1,
2019 IN EFI_HII_VALUE *Value2,
2020 OUT INTN *Result,
2021 IN EFI_HII_HANDLE HiiHandle OPTIONAL
2022 )
2023{
2024 INT64 Temp64;
2025 CHAR16 *Str1;
2026 CHAR16 *Str2;
2027 UINTN Len;
2028 UINT8 *Buf1;
2029 UINT16 Buf1Len;
2030 UINT8 *Buf2;
2031 UINT16 Buf2Len;
2032
2033 if ((Value1 == NULL) || (Value2 == NULL) || (Result == NULL)) {
2034 return EFI_INVALID_PARAMETER;
2035 }
2036
2037 if ((Value1->Type == EFI_IFR_TYPE_STRING) && (Value2->Type == EFI_IFR_TYPE_STRING)) {
2038 if ((Value1->Value.string == 0) || (Value2->Value.string == 0)) {
2039 //
2040 // StringId 0 is reserved
2041 //
2042 return EFI_INVALID_PARAMETER;
2043 }
2044
2045 if (Value1->Value.string == Value2->Value.string) {
2046 *Result = 0;
2047 return EFI_SUCCESS;
2048 }
2049
2050 Str1 = GetTokenString (Value1->Value.string, HiiHandle);
2051 if (Str1 == NULL) {
2052 //
2053 // String not found
2054 //
2055 return EFI_NOT_FOUND;
2056 }
2057
2058 Str2 = GetTokenString (Value2->Value.string, HiiHandle);
2059 if (Str2 == NULL) {
2060 FreePool (Str1);
2061 return EFI_NOT_FOUND;
2062 }
2063
2064 *Result = StrCmp (Str1, Str2);
2065
2066 FreePool (Str1);
2067 FreePool (Str2);
2068
2069 return EFI_SUCCESS;
2070 }
2071
2072 //
2073 // Take types(date, time, ref, buffer) as buffer
2074 //
2075 if (IsTypeInBuffer (Value1) && IsTypeInBuffer (Value2)) {
2076 Buf1 = GetBufferForValue (Value1);
2077 Buf1Len = GetLengthForValue (Value1);
2078 Buf2 = GetBufferForValue (Value2);
2079 Buf2Len = GetLengthForValue (Value2);
2080
2081 Len = Buf1Len > Buf2Len ? Buf2Len : Buf1Len;
2082 *Result = CompareMem (Buf1, Buf2, Len);
2083 if ((*Result == 0) && (Buf1Len != Buf2Len)) {
2084 //
2085 // In this case, means base on small number buffer, the data is same
2086 // So which value has more data, which value is bigger.
2087 //
2088 *Result = Buf1Len > Buf2Len ? 1 : -1;
2089 }
2090
2091 return EFI_SUCCESS;
2092 }
2093
2094 //
2095 // Take types(integer, boolean) as integer
2096 //
2097 if (IsTypeInUINT64 (Value1) && IsTypeInUINT64 (Value2)) {
2098 Temp64 = HiiValueToUINT64 (Value1) - HiiValueToUINT64 (Value2);
2099 if (Temp64 > 0) {
2100 *Result = 1;
2101 } else if (Temp64 < 0) {
2102 *Result = -1;
2103 } else {
2104 *Result = 0;
2105 }
2106
2107 return EFI_SUCCESS;
2108 }
2109
2110 return EFI_UNSUPPORTED;
2111}
2112
2113/**
2114 Check if current user has the privilege specified by the permissions GUID.
2115
2116 @param[in] Guid A GUID specifying setup access permissions.
2117
2118 @retval TRUE Current user has the privilege.
2119 @retval FALSE Current user does not have the privilege.
2120**/
2121BOOLEAN
2122CheckUserPrivilege (
2123 IN EFI_GUID *Guid
2124 )
2125{
2126 EFI_STATUS Status;
2127 EFI_USER_PROFILE_HANDLE UserProfileHandle;
2128 EFI_USER_INFO_HANDLE UserInfoHandle;
2129 EFI_USER_INFO *UserInfo;
2130 EFI_GUID *UserPermissionsGuid;
2131 UINTN UserInfoSize;
2132 UINTN AccessControlDataSize;
2133 EFI_USER_INFO_ACCESS_CONTROL *AccessControl;
2134 UINTN RemainSize;
2135
2136 if (mUserManager == NULL) {
2137 Status = gBS->LocateProtocol (
2138 &gEfiUserManagerProtocolGuid,
2139 NULL,
2140 (VOID **)&mUserManager
2141 );
2142 if (EFI_ERROR (Status)) {
2143 ///
2144 /// If the system does not support user management, then it is assumed that
2145 /// all users have admin privilege and evaluation of each EFI_IFR_SECURITY
2146 /// op-code is always TRUE.
2147 ///
2148 return TRUE;
2149 }
2150 }
2151
2152 Status = mUserManager->Current (mUserManager, &UserProfileHandle);
2153 ASSERT_EFI_ERROR (Status);
2154
2155 ///
2156 /// Enumerate all user information of the current user profile
2157 /// to look for any EFI_USER_INFO_ACCESS_SETUP record.
2158 ///
2159
2160 for (UserInfoHandle = NULL; ;) {
2161 Status = mUserManager->GetNextInfo (mUserManager, UserProfileHandle, &UserInfoHandle);
2162 if (EFI_ERROR (Status)) {
2163 break;
2164 }
2165
2166 UserInfoSize = 0;
2167 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, NULL, &UserInfoSize);
2168 if (Status != EFI_BUFFER_TOO_SMALL) {
2169 continue;
2170 }
2171
2172 UserInfo = (EFI_USER_INFO *)AllocatePool (UserInfoSize);
2173 if (UserInfo == NULL) {
2174 break;
2175 }
2176
2177 Status = mUserManager->GetInfo (mUserManager, UserProfileHandle, UserInfoHandle, UserInfo, &UserInfoSize);
2178 if (EFI_ERROR (Status) ||
2179 (UserInfo->InfoType != EFI_USER_INFO_ACCESS_POLICY_RECORD) ||
2180 (UserInfo->InfoSize <= sizeof (EFI_USER_INFO)))
2181 {
2182 FreePool (UserInfo);
2183 continue;
2184 }
2185
2186 RemainSize = UserInfo->InfoSize - sizeof (EFI_USER_INFO);
2187 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)(UserInfo + 1);
2188 while (RemainSize >= sizeof (EFI_USER_INFO_ACCESS_CONTROL)) {
2189 if ((RemainSize < AccessControl->Size) || (AccessControl->Size < sizeof (EFI_USER_INFO_ACCESS_CONTROL))) {
2190 break;
2191 }
2192
2193 if (AccessControl->Type == EFI_USER_INFO_ACCESS_SETUP) {
2194 ///
2195 /// Check if current user has the privilege specified by the permissions GUID.
2196 ///
2197
2198 UserPermissionsGuid = (EFI_GUID *)(AccessControl + 1);
2199 AccessControlDataSize = AccessControl->Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);
2200 while (AccessControlDataSize >= sizeof (EFI_GUID)) {
2201 if (CompareGuid (Guid, UserPermissionsGuid)) {
2202 FreePool (UserInfo);
2203 return TRUE;
2204 }
2205
2206 UserPermissionsGuid++;
2207 AccessControlDataSize -= sizeof (EFI_GUID);
2208 }
2209 }
2210
2211 RemainSize -= AccessControl->Size;
2212 AccessControl = (EFI_USER_INFO_ACCESS_CONTROL *)((UINT8 *)AccessControl + AccessControl->Size);
2213 }
2214
2215 FreePool (UserInfo);
2216 }
2217
2218 return FALSE;
2219}
2220
2221/**
2222 Search a Question in Form scope using its QuestionId.
2223
2224 @param[in] Form The form which contains this Question.
2225 @param[in] QuestionId Id of this Question.
2226
2227 @retval Pointer The Question.
2228 @retval NULL Specified Question not found in the form.
2229
2230**/
2231HII_STATEMENT *
2232QuestionIdInForm (
2233 IN HII_FORM *Form,
2234 IN UINT16 QuestionId
2235 )
2236{
2237 LIST_ENTRY *Link;
2238 HII_STATEMENT *Question;
2239
2240 if ((QuestionId == 0) || (Form == NULL)) {
2241 //
2242 // The value of zero is reserved
2243 //
2244 return NULL;
2245 }
2246
2247 Link = GetFirstNode (&Form->StatementListHead);
2248 while (!IsNull (&Form->StatementListHead, Link)) {
2249 Question = HII_STATEMENT_FROM_LINK (Link);
2250
2251 if (Question->QuestionId == QuestionId) {
2252 return Question;
2253 }
2254
2255 Link = GetNextNode (&Form->StatementListHead, Link);
2256 }
2257
2258 return NULL;
2259}
2260
2261/**
2262 Search a Question in Formset scope using its QuestionId.
2263
2264 @param[in] FormSet The formset which contains this form.
2265 @param[in] Form The form which contains this Question.
2266 @param[in] QuestionId Id of this Question.
2267
2268 @retval Pointer The Question.
2269 @retval NULL Specified Question not found in the form.
2270
2271**/
2272HII_STATEMENT *
2273QuestionIdInFormset (
2274 IN HII_FORMSET *FormSet,
2275 IN HII_FORM *Form,
2276 IN UINT16 QuestionId
2277 )
2278{
2279 LIST_ENTRY *Link;
2280 HII_STATEMENT *Question;
2281
2282 if ((FormSet == NULL) || (Form == NULL)) {
2283 return NULL;
2284 }
2285
2286 //
2287 // Search in the form scope first
2288 //
2289 Question = QuestionIdInForm (Form, QuestionId);
2290 if (Question != NULL) {
2291 return Question;
2292 }
2293
2294 //
2295 // Search in the formset scope
2296 //
2297 Link = GetFirstNode (&FormSet->FormListHead);
2298 while (!IsNull (&FormSet->FormListHead, Link)) {
2299 Form = HII_FORM_FROM_LINK (Link);
2300
2301 Question = QuestionIdInForm (Form, QuestionId);
2302 if (Question != NULL) {
2303 //
2304 // EFI variable storage may be updated by Callback() asynchronous,
2305 // to keep synchronous, always reload the Question Value.
2306 //
2307 if (Question->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
2308 GetQuestionValue (FormSet, Form, Question, GetSetValueWithHiiDriver);
2309 }
2310
2311 return Question;
2312 }
2313
2314 Link = GetNextNode (&FormSet->FormListHead, Link);
2315 }
2316
2317 return NULL;
2318}
2319
2320/**
2321 Push an Expression value onto the Stack
2322
2323 @param[in] Value Expression value to push.
2324
2325 @retval EFI_SUCCESS The value was pushed onto the stack.
2326 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
2327 stack.
2328 @retval EFI_INVALID_PARAMETER Value is NULL.
2329
2330**/
2331EFI_STATUS
2332PushExpression (
2333 IN EFI_HII_VALUE *Value
2334 )
2335{
2336 if (Value == NULL) {
2337 return EFI_INVALID_PARAMETER;
2338 }
2339
2340 return PushStack (
2341 &mExpressionEvaluationStack,
2342 &mExpressionEvaluationStackPointer,
2343 &mExpressionEvaluationStackEnd,
2344 Value
2345 );
2346}
2347
2348/**
2349 Pop an Expression value from the stack.
2350
2351 @param[out] Value Expression value to pop.
2352
2353 @retval EFI_SUCCESS The value was popped onto the stack.
2354 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack
2355 @retval EFI_INVALID_PARAMETER Value is NULL.
2356
2357**/
2358EFI_STATUS
2359PopExpression (
2360 OUT EFI_HII_VALUE *Value
2361 )
2362{
2363 if (Value == NULL) {
2364 return EFI_INVALID_PARAMETER;
2365 }
2366
2367 return PopStack (
2368 mExpressionEvaluationStack + mExpressionEvaluationStackOffset,
2369 &mExpressionEvaluationStackPointer,
2370 Value
2371 );
2372}
2373
2374/**
2375 Get current stack offset from stack start.
2376
2377 @return Stack offset to stack start.
2378**/
2379UINTN
2380SaveExpressionEvaluationStackOffset (
2381 VOID
2382 )
2383{
2384 UINTN TempStackOffset;
2385
2386 TempStackOffset = mExpressionEvaluationStackOffset;
2387 mExpressionEvaluationStackOffset = mExpressionEvaluationStackPointer - mExpressionEvaluationStack;
2388 return TempStackOffset;
2389}
2390
2391/**
2392 Restore stack offset based on input stack offset
2393
2394 @param[in] StackOffset Offset to stack start.
2395
2396**/
2397VOID
2398RestoreExpressionEvaluationStackOffset (
2399 UINTN StackOffset
2400 )
2401{
2402 mExpressionEvaluationStackOffset = StackOffset;
2403}
2404
2405/**
2406 Evaluate opcode EFI_IFR_TO_STRING.
2407
2408 @param[in] FormSet Formset which contains this opcode.
2409 @param[in] Format String format in EFI_IFR_TO_STRING.
2410 @param[out] Result Evaluation result for this opcode.
2411
2412 @retval EFI_SUCCESS Opcode evaluation success.
2413 @retval Other Opcode evaluation failed.
2414
2415**/
2416EFI_STATUS
2417IfrToString (
2418 IN HII_FORMSET *FormSet,
2419 IN UINT8 Format,
2420 OUT EFI_HII_VALUE *Result
2421 )
2422{
2423 EFI_STATUS Status;
2424 EFI_HII_VALUE Value;
2425 CHAR16 *String;
2426 CHAR16 *PrintFormat;
2427 CHAR16 Buffer[MAXIMUM_VALUE_CHARACTERS];
2428 UINT8 *SrcBuf;
2429 UINTN BufferSize;
2430
2431 if ((FormSet == NULL) || (Result == NULL)) {
2432 return EFI_INVALID_PARAMETER;
2433 }
2434
2435 Status = PopExpression (&Value);
2436 if (EFI_ERROR (Status)) {
2437 return Status;
2438 }
2439
2440 switch (Value.Type) {
2441 case EFI_IFR_TYPE_NUM_SIZE_8:
2442 case EFI_IFR_TYPE_NUM_SIZE_16:
2443 case EFI_IFR_TYPE_NUM_SIZE_32:
2444 case EFI_IFR_TYPE_NUM_SIZE_64:
2445 BufferSize = MAXIMUM_VALUE_CHARACTERS * sizeof (CHAR16);
2446 switch (Format) {
2447 case EFI_IFR_STRING_UNSIGNED_DEC:
2448 case EFI_IFR_STRING_SIGNED_DEC:
2449 PrintFormat = L"%ld";
2450 break;
2451
2452 case EFI_IFR_STRING_LOWERCASE_HEX:
2453 PrintFormat = L"%lx";
2454 break;
2455
2456 case EFI_IFR_STRING_UPPERCASE_HEX:
2457 PrintFormat = L"%lX";
2458 break;
2459
2460 default:
2461 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2462 return EFI_SUCCESS;
2463 }
2464
2465 UnicodeSPrint (Buffer, BufferSize, PrintFormat, Value.Value.u64);
2466 String = Buffer;
2467 break;
2468
2469 case EFI_IFR_TYPE_STRING:
2470 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
2471 return EFI_SUCCESS;
2472
2473 case EFI_IFR_TYPE_BOOLEAN:
2474 String = (Value.Value.b) ? L"True" : L"False";
2475 break;
2476
2477 case EFI_IFR_TYPE_BUFFER:
2478 case EFI_IFR_TYPE_DATE:
2479 case EFI_IFR_TYPE_TIME:
2480 case EFI_IFR_TYPE_REF:
2481 //
2482 // + 3 is base on the unicode format, the length may be odd number,
2483 // so need 1 byte to align, also need 2 bytes for L'\0'.
2484 //
2485 if (Value.Type == EFI_IFR_TYPE_BUFFER) {
2486 SrcBuf = Value.Buffer;
2487 } else {
2488 SrcBuf = GetBufferForValue (&Value);
2489 }
2490
2491 if (Format == EFI_IFR_STRING_ASCII) {
2492 PrintFormat = L"%a";
2493 } else {
2494 // Format == EFI_IFR_STRING_UNICODE
2495 PrintFormat = L"%s";
2496 }
2497
2498 UnicodeSPrint (Buffer, sizeof (Buffer), PrintFormat, SrcBuf);
2499 String = Buffer;
2500 if (Value.Type == EFI_IFR_TYPE_BUFFER) {
2501 FreePool (Value.Buffer);
2502 }
2503
2504 break;
2505
2506 default:
2507 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2508 return EFI_SUCCESS;
2509 }
2510
2511 Result->Type = EFI_IFR_TYPE_STRING;
2512 Result->Value.string = NewHiiString (String, FormSet->HiiHandle);
2513 return EFI_SUCCESS;
2514}
2515
2516/**
2517 Evaluate opcode EFI_IFR_TO_UINT.
2518
2519 @param[in] FormSet Formset which contains this opcode.
2520 @param[out] Result Evaluation result for this opcode.
2521
2522 @retval EFI_SUCCESS Opcode evaluation success.
2523 @retval Other Opcode evaluation failed.
2524
2525**/
2526EFI_STATUS
2527IfrToUint (
2528 IN HII_FORMSET *FormSet,
2529 OUT EFI_HII_VALUE *Result
2530 )
2531{
2532 EFI_STATUS Status;
2533 EFI_HII_VALUE Value;
2534 CHAR16 *String;
2535 CHAR16 *StringPtr;
2536
2537 if ((FormSet == NULL) || (Result == NULL)) {
2538 return EFI_INVALID_PARAMETER;
2539 }
2540
2541 Status = PopExpression (&Value);
2542 if (EFI_ERROR (Status)) {
2543 return Status;
2544 }
2545
2546 if ((Value.Type >= EFI_IFR_TYPE_OTHER) && !IsTypeInBuffer (&Value)) {
2547 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2548 return EFI_SUCCESS;
2549 }
2550
2551 Status = EFI_SUCCESS;
2552 if (Value.Type == EFI_IFR_TYPE_STRING) {
2553 String = GetTokenString (Value.Value.string, FormSet->HiiHandle);
2554 if (String == NULL) {
2555 return EFI_NOT_FOUND;
2556 }
2557
2558 IfrStrToUpper (String);
2559 StringPtr = StrStr (String, L"0X");
2560 if (StringPtr != NULL) {
2561 //
2562 // Hex string
2563 //
2564 Result->Value.u64 = StrHexToUint64 (String);
2565 } else {
2566 //
2567 // decimal string
2568 //
2569 Result->Value.u64 = StrDecimalToUint64 (String);
2570 }
2571
2572 FreePool (String);
2573 } else if (IsTypeInBuffer (&Value)) {
2574 if (GetLengthForValue (&Value) > 8) {
2575 if (Value.Type == EFI_IFR_TYPE_BUFFER) {
2576 FreePool (Value.Buffer);
2577 }
2578
2579 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2580 return EFI_SUCCESS;
2581 }
2582
2583 Result->Value.u64 = *(UINT64 *)GetBufferForValue (&Value);
2584 if (Value.Type == EFI_IFR_TYPE_BUFFER) {
2585 FreePool (Value.Buffer);
2586 }
2587 } else {
2588 CopyMem (Result, &Value, sizeof (EFI_HII_VALUE));
2589 }
2590
2591 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
2592 return Status;
2593}
2594
2595/**
2596 Evaluate opcode EFI_IFR_CATENATE.
2597
2598 @param[in] FormSet Formset which contains this opcode.
2599 @param[out] Result Evaluation result for this opcode.
2600
2601 @retval EFI_SUCCESS Opcode evaluation success.
2602 @retval Other Opcode evaluation failed.
2603
2604**/
2605EFI_STATUS
2606IfrCatenate (
2607 IN HII_FORMSET *FormSet,
2608 OUT EFI_HII_VALUE *Result
2609 )
2610{
2611 EFI_STATUS Status;
2612 EFI_HII_VALUE Value[2];
2613 CHAR16 *String[2];
2614 UINTN Index;
2615 CHAR16 *StringPtr;
2616 UINTN Size;
2617 UINT16 Length0;
2618 UINT16 Length1;
2619 UINT8 *TmpBuf;
2620 UINTN MaxLen;
2621
2622 if ((FormSet == NULL) || (Result == NULL)) {
2623 return EFI_INVALID_PARAMETER;
2624 }
2625
2626 //
2627 // String[0] - The second string
2628 // String[1] - The first string
2629 //
2630 String[0] = NULL;
2631 String[1] = NULL;
2632 StringPtr = NULL;
2633 Status = EFI_SUCCESS;
2634 ZeroMem (Value, sizeof (Value));
2635
2636 Status = PopExpression (&Value[0]);
2637 if (EFI_ERROR (Status)) {
2638 goto Done;
2639 }
2640
2641 Status = PopExpression (&Value[1]);
2642 if (EFI_ERROR (Status)) {
2643 goto Done;
2644 }
2645
2646 for (Index = 0; Index < 2; Index++) {
2647 if ((Value[Index].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[Index])) {
2648 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2649 Status = EFI_SUCCESS;
2650 goto Done;
2651 }
2652
2653 if (Value[Index].Type == EFI_IFR_TYPE_STRING) {
2654 String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);
2655 if (String[Index] == NULL) {
2656 Status = EFI_NOT_FOUND;
2657 goto Done;
2658 }
2659 }
2660 }
2661
2662 if (Value[0].Type == EFI_IFR_TYPE_STRING) {
2663 Size = StrSize (String[0]);
2664 MaxLen = (StrSize (String[1]) + Size) / sizeof (CHAR16);
2665 StringPtr = AllocatePool (MaxLen * sizeof (CHAR16));
2666 ASSERT (StringPtr != NULL);
2667 StrCpyS (StringPtr, MaxLen, String[1]);
2668 StrCatS (StringPtr, MaxLen, String[0]);
2669
2670 Result->Type = EFI_IFR_TYPE_STRING;
2671 Result->Value.string = NewHiiString (StringPtr, FormSet->HiiHandle);
2672 } else {
2673 Result->Type = EFI_IFR_TYPE_BUFFER;
2674 Length0 = GetLengthForValue (&Value[0]);
2675 Length1 = GetLengthForValue (&Value[1]);
2676 Result->BufferLen = (UINT16)(Length0 + Length1);
2677
2678 Result->Buffer = AllocatePool (Result->BufferLen);
2679 ASSERT (Result->Buffer != NULL);
2680
2681 TmpBuf = GetBufferForValue (&Value[0]);
2682 ASSERT (TmpBuf != NULL);
2683 CopyMem (Result->Buffer, TmpBuf, Length0);
2684 TmpBuf = GetBufferForValue (&Value[1]);
2685 ASSERT (TmpBuf != NULL);
2686 CopyMem (&Result->Buffer[Length0], TmpBuf, Length1);
2687 }
2688
2689Done:
2690 if (Value[0].Buffer != NULL) {
2691 FreePool (Value[0].Buffer);
2692 }
2693
2694 if (Value[1].Buffer != NULL) {
2695 FreePool (Value[1].Buffer);
2696 }
2697
2698 if (String[0] != NULL) {
2699 FreePool (String[0]);
2700 }
2701
2702 if (String[1] != NULL) {
2703 FreePool (String[1]);
2704 }
2705
2706 if (StringPtr != NULL) {
2707 FreePool (StringPtr);
2708 }
2709
2710 return Status;
2711}
2712
2713/**
2714 Evaluate opcode EFI_IFR_MATCH.
2715
2716 @param[in] FormSet Formset which contains this opcode.
2717 @param[out] Result Evaluation result for this opcode.
2718
2719 @retval EFI_SUCCESS Opcode evaluation success.
2720 @retval Other Opcode evaluation failed.
2721
2722**/
2723EFI_STATUS
2724IfrMatch (
2725 IN HII_FORMSET *FormSet,
2726 OUT EFI_HII_VALUE *Result
2727 )
2728{
2729 EFI_STATUS Status;
2730 EFI_HII_VALUE Value[2];
2731 CHAR16 *String[2];
2732 UINTN Index;
2733
2734 if ((FormSet == NULL) || (Result == NULL)) {
2735 return EFI_INVALID_PARAMETER;
2736 }
2737
2738 //
2739 // String[0] - The string to search
2740 // String[1] - pattern
2741 //
2742 String[0] = NULL;
2743 String[1] = NULL;
2744 Status = EFI_SUCCESS;
2745 ZeroMem (Value, sizeof (Value));
2746
2747 Status = PopExpression (&Value[0]);
2748 if (EFI_ERROR (Status)) {
2749 goto Done;
2750 }
2751
2752 Status = PopExpression (&Value[1]);
2753 if (EFI_ERROR (Status)) {
2754 goto Done;
2755 }
2756
2757 for (Index = 0; Index < 2; Index++) {
2758 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
2759 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2760 Status = EFI_SUCCESS;
2761 goto Done;
2762 }
2763
2764 String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);
2765 if (String[Index] == NULL) {
2766 Status = EFI_NOT_FOUND;
2767 goto Done;
2768 }
2769 }
2770
2771 Result->Type = EFI_IFR_TYPE_BOOLEAN;
2772 Result->Value.b = mUnicodeCollation->MetaiMatch (mUnicodeCollation, String[0], String[1]);
2773
2774Done:
2775 if (String[0] != NULL) {
2776 FreePool (String[0]);
2777 }
2778
2779 if (String[1] != NULL) {
2780 FreePool (String[1]);
2781 }
2782
2783 return Status;
2784}
2785
2786/**
2787 Evaluate opcode EFI_IFR_MATCH2.
2788
2789 @param[in] FormSet Formset which contains this opcode.
2790 @param[in] SyntaxType Syntax type for match2.
2791 @param[out] Result Evaluation result for this opcode.
2792
2793 @retval EFI_SUCCESS Opcode evaluation success.
2794 @retval Other Opcode evaluation failed.
2795
2796**/
2797EFI_STATUS
2798IfrMatch2 (
2799 IN HII_FORMSET *FormSet,
2800 IN EFI_GUID *SyntaxType,
2801 OUT EFI_HII_VALUE *Result
2802 )
2803{
2804 EFI_STATUS Status;
2805 EFI_HII_VALUE Value[2];
2806 CHAR16 *String[2];
2807 UINTN Index;
2808 UINTN GuidIndex;
2809 EFI_HANDLE *HandleBuffer;
2810 UINTN BufferSize;
2811 EFI_REGULAR_EXPRESSION_PROTOCOL *RegularExpressionProtocol;
2812 UINTN RegExSyntaxTypeListSize;
2813 EFI_REGEX_SYNTAX_TYPE *RegExSyntaxTypeList;
2814 UINTN CapturesCount;
2815
2816 if ((FormSet == NULL) || (SyntaxType == NULL) || (Result == NULL)) {
2817 return EFI_INVALID_PARAMETER;
2818 }
2819
2820 //
2821 // String[0] - The string to search
2822 // String[1] - pattern
2823 //
2824 String[0] = NULL;
2825 String[1] = NULL;
2826 HandleBuffer = NULL;
2827 RegExSyntaxTypeList = NULL;
2828 Status = EFI_SUCCESS;
2829 ZeroMem (Value, sizeof (Value));
2830
2831 Status = PopExpression (&Value[0]);
2832 if (EFI_ERROR (Status)) {
2833 goto Done;
2834 }
2835
2836 Status = PopExpression (&Value[1]);
2837 if (EFI_ERROR (Status)) {
2838 goto Done;
2839 }
2840
2841 for (Index = 0; Index < 2; Index++) {
2842 if (Value[Index].Type != EFI_IFR_TYPE_STRING) {
2843 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2844 Status = EFI_SUCCESS;
2845 goto Done;
2846 }
2847
2848 String[Index] = GetTokenString (Value[Index].Value.string, FormSet->HiiHandle);
2849 if (String[Index] == NULL) {
2850 Status = EFI_NOT_FOUND;
2851 goto Done;
2852 }
2853 }
2854
2855 BufferSize = 0;
2856 HandleBuffer = NULL;
2857 Status = gBS->LocateHandle (
2858 ByProtocol,
2859 &gEfiRegularExpressionProtocolGuid,
2860 NULL,
2861 &BufferSize,
2862 HandleBuffer
2863 );
2864 if (Status == EFI_BUFFER_TOO_SMALL) {
2865 HandleBuffer = AllocatePool (BufferSize);
2866 if (HandleBuffer == NULL) {
2867 Status = EFI_OUT_OF_RESOURCES;
2868 goto Done;
2869 }
2870
2871 Status = gBS->LocateHandle (
2872 ByProtocol,
2873 &gEfiRegularExpressionProtocolGuid,
2874 NULL,
2875 &BufferSize,
2876 HandleBuffer
2877 );
2878 }
2879
2880 if (EFI_ERROR (Status)) {
2881 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2882 Status = EFI_SUCCESS;
2883 goto Done;
2884 }
2885
2886 ASSERT (HandleBuffer != NULL);
2887 for ( Index = 0; Index < BufferSize / sizeof (EFI_HANDLE); Index++) {
2888 Status = gBS->HandleProtocol (
2889 HandleBuffer[Index],
2890 &gEfiRegularExpressionProtocolGuid,
2891 (VOID **)&RegularExpressionProtocol
2892 );
2893 if (EFI_ERROR (Status)) {
2894 goto Done;
2895 }
2896
2897 RegExSyntaxTypeListSize = 0;
2898 RegExSyntaxTypeList = NULL;
2899
2900 Status = RegularExpressionProtocol->GetInfo (
2901 RegularExpressionProtocol,
2902 &RegExSyntaxTypeListSize,
2903 RegExSyntaxTypeList
2904 );
2905 if (Status == EFI_BUFFER_TOO_SMALL) {
2906 RegExSyntaxTypeList = AllocatePool (RegExSyntaxTypeListSize);
2907 if (RegExSyntaxTypeList == NULL) {
2908 Status = EFI_OUT_OF_RESOURCES;
2909 goto Done;
2910 }
2911
2912 Status = RegularExpressionProtocol->GetInfo (
2913 RegularExpressionProtocol,
2914 &RegExSyntaxTypeListSize,
2915 RegExSyntaxTypeList
2916 );
2917 } else if (EFI_ERROR (Status)) {
2918 goto Done;
2919 }
2920
2921 for (GuidIndex = 0; GuidIndex < RegExSyntaxTypeListSize / sizeof (EFI_GUID); GuidIndex++) {
2922 if (CompareGuid (&RegExSyntaxTypeList[GuidIndex], SyntaxType)) {
2923 //
2924 // Find the match type, return the value.
2925 //
2926 Result->Type = EFI_IFR_TYPE_BOOLEAN;
2927 Status = RegularExpressionProtocol->MatchString (
2928 RegularExpressionProtocol,
2929 String[0],
2930 String[1],
2931 SyntaxType,
2932 &Result->Value.b,
2933 NULL,
2934 &CapturesCount
2935 );
2936 goto Done;
2937 }
2938 }
2939
2940 if (RegExSyntaxTypeList != NULL) {
2941 FreePool (RegExSyntaxTypeList);
2942 }
2943 }
2944
2945 //
2946 // Type specified by SyntaxType is not supported
2947 // in any of the EFI_REGULAR_EXPRESSION_PROTOCOL instances.
2948 //
2949 Result->Type = EFI_IFR_TYPE_UNDEFINED;
2950 Status = EFI_SUCCESS;
2951
2952Done:
2953 if (String[0] != NULL) {
2954 FreePool (String[0]);
2955 }
2956
2957 if (String[1] != NULL) {
2958 FreePool (String[1]);
2959 }
2960
2961 if (RegExSyntaxTypeList != NULL) {
2962 FreePool (RegExSyntaxTypeList);
2963 }
2964
2965 if (HandleBuffer != NULL) {
2966 FreePool (HandleBuffer);
2967 }
2968
2969 return Status;
2970}
2971
2972/**
2973 Evaluate opcode EFI_IFR_FIND.
2974
2975 @param[in] FormSet Formset which contains this opcode.
2976 @param[in] Format Case sensitive or insensitive.
2977 @param[out] Result Evaluation result for this opcode.
2978
2979 @retval EFI_SUCCESS Opcode evaluation success.
2980 @retval Other Opcode evaluation failed.
2981
2982**/
2983EFI_STATUS
2984IfrFind (
2985 IN HII_FORMSET *FormSet,
2986 IN UINT8 Format,
2987 OUT EFI_HII_VALUE *Result
2988 )
2989{
2990 EFI_STATUS Status;
2991 EFI_HII_VALUE Value[3];
2992 CHAR16 *String[2];
2993 UINTN Base;
2994 CHAR16 *StringPtr;
2995 UINTN Index;
2996
2997 if ((FormSet == NULL) || (Result == NULL)) {
2998 return EFI_INVALID_PARAMETER;
2999 }
3000
3001 ZeroMem (Value, sizeof (Value));
3002
3003 if (Format > EFI_IFR_FF_CASE_INSENSITIVE) {
3004 return EFI_INVALID_PARAMETER;
3005 }
3006
3007 Status = PopExpression (&Value[0]);
3008 if (EFI_ERROR (Status)) {
3009 return Status;
3010 }
3011
3012 Status = PopExpression (&Value[1]);
3013 if (EFI_ERROR (Status)) {
3014 return Status;
3015 }
3016
3017 Status = PopExpression (&Value[2]);
3018 if (EFI_ERROR (Status)) {
3019 return Status;
3020 }
3021
3022 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
3023 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3024 return EFI_SUCCESS;
3025 }
3026
3027 Base = (UINTN)Value[0].Value.u64;
3028
3029 //
3030 // String[0] - sub-string
3031 // String[1] - The string to search
3032 //
3033 String[0] = NULL;
3034 String[1] = NULL;
3035 for (Index = 0; Index < 2; Index++) {
3036 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
3037 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3038 Status = EFI_SUCCESS;
3039 goto Done;
3040 }
3041
3042 String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);
3043 if (String[Index] == NULL) {
3044 Status = EFI_NOT_FOUND;
3045 goto Done;
3046 }
3047
3048 if (Format == EFI_IFR_FF_CASE_INSENSITIVE) {
3049 //
3050 // Case insensitive, convert both string to upper case
3051 //
3052 IfrStrToUpper (String[Index]);
3053 }
3054 }
3055
3056 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
3057 if (Base >= StrLen (String[1])) {
3058 Result->Value.u64 = 0xFFFFFFFFFFFFFFFFULL;
3059 } else {
3060 StringPtr = StrStr (String[1] + Base, String[0]);
3061 Result->Value.u64 = (StringPtr == NULL) ? 0xFFFFFFFFFFFFFFFFULL : (StringPtr - String[1]);
3062 }
3063
3064Done:
3065 if (String[0] != NULL) {
3066 FreePool (String[0]);
3067 }
3068
3069 if (String[1] != NULL) {
3070 FreePool (String[1]);
3071 }
3072
3073 return Status;
3074}
3075
3076/**
3077 Evaluate opcode EFI_IFR_MID.
3078
3079 @param[in] FormSet Formset which contains this opcode.
3080 @param[out] Result Evaluation result for this opcode.
3081
3082 @retval EFI_SUCCESS Opcode evaluation success.
3083 @retval Other Opcode evaluation failed.
3084
3085**/
3086EFI_STATUS
3087IfrMid (
3088 IN HII_FORMSET *FormSet,
3089 OUT EFI_HII_VALUE *Result
3090 )
3091{
3092 EFI_STATUS Status;
3093 EFI_HII_VALUE Value[3];
3094 CHAR16 *String;
3095 UINTN Base;
3096 UINTN Length;
3097 CHAR16 *SubString;
3098 UINT16 BufferLen;
3099 UINT8 *Buffer;
3100
3101 if ((FormSet == NULL) || (Result == NULL)) {
3102 return EFI_INVALID_PARAMETER;
3103 }
3104
3105 ZeroMem (Value, sizeof (Value));
3106
3107 Status = PopExpression (&Value[0]);
3108 if (EFI_ERROR (Status)) {
3109 return Status;
3110 }
3111
3112 Status = PopExpression (&Value[1]);
3113 if (EFI_ERROR (Status)) {
3114 return Status;
3115 }
3116
3117 Status = PopExpression (&Value[2]);
3118 if (EFI_ERROR (Status)) {
3119 return Status;
3120 }
3121
3122 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
3123 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3124 return EFI_SUCCESS;
3125 }
3126
3127 Length = (UINTN)Value[0].Value.u64;
3128
3129 if (Value[1].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
3130 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3131 return EFI_SUCCESS;
3132 }
3133
3134 Base = (UINTN)Value[1].Value.u64;
3135
3136 if ((Value[2].Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (&Value[2])) {
3137 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3138 return EFI_SUCCESS;
3139 }
3140
3141 if (Value[2].Type == EFI_IFR_TYPE_STRING) {
3142 String = GetTokenString (Value[2].Value.string, FormSet->HiiHandle);
3143 if (String == NULL) {
3144 return EFI_NOT_FOUND;
3145 }
3146
3147 if ((Length == 0) || (Base >= StrLen (String))) {
3148 SubString = gEmptyString;
3149 } else {
3150 SubString = String + Base;
3151 if ((Base + Length) < StrLen (String)) {
3152 SubString[Length] = L'\0';
3153 }
3154 }
3155
3156 Result->Type = EFI_IFR_TYPE_STRING;
3157 Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);
3158
3159 FreePool (String);
3160 } else {
3161 BufferLen = GetLengthForValue (&Value[2]);
3162 Buffer = GetBufferForValue (&Value[2]);
3163
3164 Result->Type = EFI_IFR_TYPE_BUFFER;
3165 if ((Length == 0) || (Base >= BufferLen)) {
3166 Result->BufferLen = 0;
3167 Result->Buffer = NULL;
3168 } else {
3169 Result->BufferLen = (UINT16)((BufferLen - Base) < Length ? (BufferLen - Base) : Length);
3170 Result->Buffer = AllocatePool (Result->BufferLen);
3171 ASSERT (Result->Buffer != NULL);
3172 CopyMem (Result->Buffer, &Buffer[Base], Result->BufferLen);
3173 }
3174
3175 if (Value[2].Type == EFI_IFR_TYPE_BUFFER) {
3176 FreePool (Value[2].Buffer);
3177 }
3178 }
3179
3180 return Status;
3181}
3182
3183/**
3184 Evaluate opcode EFI_IFR_TOKEN.
3185
3186 @param[in] FormSet Formset which contains this opcode.
3187 @param[out] Result Evaluation result for this opcode.
3188
3189 @retval EFI_SUCCESS Opcode evaluation success.
3190 @retval Other Opcode evaluation failed.
3191
3192**/
3193EFI_STATUS
3194IfrToken (
3195 IN HII_FORMSET *FormSet,
3196 OUT EFI_HII_VALUE *Result
3197 )
3198{
3199 EFI_STATUS Status;
3200 EFI_HII_VALUE Value[3];
3201 CHAR16 *String[2];
3202 UINTN Count;
3203 CHAR16 *Delimiter;
3204 CHAR16 *SubString;
3205 CHAR16 *StringPtr;
3206 UINTN Index;
3207
3208 if ((FormSet == NULL) || (Result == NULL)) {
3209 return EFI_INVALID_PARAMETER;
3210 }
3211
3212 ZeroMem (Value, sizeof (Value));
3213
3214 Status = PopExpression (&Value[0]);
3215 if (EFI_ERROR (Status)) {
3216 return Status;
3217 }
3218
3219 Status = PopExpression (&Value[1]);
3220 if (EFI_ERROR (Status)) {
3221 return Status;
3222 }
3223
3224 Status = PopExpression (&Value[2]);
3225 if (EFI_ERROR (Status)) {
3226 return Status;
3227 }
3228
3229 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
3230 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3231 return EFI_SUCCESS;
3232 }
3233
3234 Count = (UINTN)Value[0].Value.u64;
3235
3236 //
3237 // String[0] - Delimiter
3238 // String[1] - The string to search
3239 //
3240 String[0] = NULL;
3241 String[1] = NULL;
3242 for (Index = 0; Index < 2; Index++) {
3243 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
3244 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3245 Status = EFI_SUCCESS;
3246 goto Done;
3247 }
3248
3249 String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);
3250 if (String[Index] == NULL) {
3251 Status = EFI_NOT_FOUND;
3252 goto Done;
3253 }
3254 }
3255
3256 Delimiter = String[0];
3257 SubString = String[1];
3258 while (Count > 0) {
3259 SubString = StrStr (SubString, Delimiter);
3260 if (SubString != NULL) {
3261 //
3262 // Skip over the delimiter
3263 //
3264 SubString = SubString + StrLen (Delimiter);
3265 } else {
3266 break;
3267 }
3268
3269 Count--;
3270 }
3271
3272 if (SubString == NULL) {
3273 //
3274 // nth delimited sub-string not found, push an empty string
3275 //
3276 SubString = gEmptyString;
3277 } else {
3278 //
3279 // Put a NULL terminator for nth delimited sub-string
3280 //
3281 StringPtr = StrStr (SubString, Delimiter);
3282 if (StringPtr != NULL) {
3283 *StringPtr = L'\0';
3284 }
3285 }
3286
3287 Result->Type = EFI_IFR_TYPE_STRING;
3288 Result->Value.string = NewHiiString (SubString, FormSet->HiiHandle);
3289
3290Done:
3291 if (String[0] != NULL) {
3292 FreePool (String[0]);
3293 }
3294
3295 if (String[1] != NULL) {
3296 FreePool (String[1]);
3297 }
3298
3299 return Status;
3300}
3301
3302/**
3303 Evaluate opcode EFI_IFR_SPAN.
3304
3305 @param[in] FormSet Formset which contains this opcode.
3306 @param[in] Flags FIRST_MATCHING or FIRST_NON_MATCHING.
3307 @param[out] Result Evaluation result for this opcode.
3308
3309 @retval EFI_SUCCESS Opcode evaluation success.
3310 @retval Other Opcode evaluation failed.
3311
3312**/
3313EFI_STATUS
3314IfrSpan (
3315 IN HII_FORMSET *FormSet,
3316 IN UINT8 Flags,
3317 OUT EFI_HII_VALUE *Result
3318 )
3319{
3320 EFI_STATUS Status;
3321 EFI_HII_VALUE Value[3];
3322 CHAR16 *String[2];
3323 CHAR16 *Charset;
3324 UINTN Base;
3325 UINTN Index;
3326 CHAR16 *StringPtr;
3327 BOOLEAN Found;
3328
3329 if ((FormSet == NULL) || (Result == NULL)) {
3330 return EFI_INVALID_PARAMETER;
3331 }
3332
3333 ZeroMem (Value, sizeof (Value));
3334
3335 Status = PopExpression (&Value[0]);
3336 if (EFI_ERROR (Status)) {
3337 return Status;
3338 }
3339
3340 Status = PopExpression (&Value[1]);
3341 if (EFI_ERROR (Status)) {
3342 return Status;
3343 }
3344
3345 Status = PopExpression (&Value[2]);
3346 if (EFI_ERROR (Status)) {
3347 return Status;
3348 }
3349
3350 if (Value[0].Type > EFI_IFR_TYPE_NUM_SIZE_64) {
3351 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3352 return EFI_SUCCESS;
3353 }
3354
3355 Base = (UINTN)Value[0].Value.u64;
3356
3357 //
3358 // String[0] - Charset
3359 // String[1] - The string to search
3360 //
3361 String[0] = NULL;
3362 String[1] = NULL;
3363 for (Index = 0; Index < 2; Index++) {
3364 if (Value[Index + 1].Type != EFI_IFR_TYPE_STRING) {
3365 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3366 Status = EFI_SUCCESS;
3367 goto Done;
3368 }
3369
3370 String[Index] = GetTokenString (Value[Index + 1].Value.string, FormSet->HiiHandle);
3371 if (String[Index] == NULL) {
3372 Status = EFI_NOT_FOUND;
3373 goto Done;
3374 }
3375 }
3376
3377 if (Base >= StrLen (String[1])) {
3378 Result->Type = EFI_IFR_TYPE_UNDEFINED;
3379 Status = EFI_SUCCESS;
3380 goto Done;
3381 }
3382
3383 Found = FALSE;
3384 StringPtr = String[1] + Base;
3385 Charset = String[0];
3386 while (*StringPtr != 0 && !Found) {
3387 Index = 0;
3388 while (Charset[Index] != 0) {
3389 if ((*StringPtr >= Charset[Index]) && (*StringPtr <= Charset[Index + 1])) {
3390 if (Flags == EFI_IFR_FLAGS_FIRST_MATCHING) {
3391 Found = TRUE;
3392 break;
3393 }
3394 } else {
3395 if (Flags == EFI_IFR_FLAGS_FIRST_NON_MATCHING) {
3396 Found = TRUE;
3397 break;
3398 }
3399 }
3400
3401 //
3402 // Skip characters pair representing low-end of a range and high-end of a range
3403 //
3404 Index += 2;
3405 }
3406
3407 if (!Found) {
3408 StringPtr++;
3409 }
3410 }
3411
3412 Result->Type = EFI_IFR_TYPE_NUM_SIZE_64;
3413 Result->Value.u64 = StringPtr - String[1];
3414
3415Done:
3416 if (String[0] != NULL) {
3417 FreePool (String[0]);
3418 }
3419
3420 if (String[1] != NULL) {
3421 FreePool (String[1]);
3422 }
3423
3424 return Status;
3425}
3426
3427/**
3428 Get Expression given its RuleId.
3429
3430 @param[in] Form The form which contains this Expression.
3431 @param[in] RuleId Id of this Expression.
3432
3433 @retval Pointer The Expression.
3434 @retval NULL Specified Expression not found in the form.
3435
3436**/
3437HII_EXPRESSION *
3438RuleIdToExpression (
3439 IN HII_FORM *Form,
3440 IN UINT8 RuleId
3441 )
3442{
3443 LIST_ENTRY *Link;
3444 HII_EXPRESSION *Expression;
3445
3446 if (Form == NULL) {
3447 return NULL;
3448 }
3449
3450 Link = GetFirstNode (&Form->RuleListHead);
3451 while (!IsNull (&Form->RuleListHead, Link)) {
3452 Expression = HII_EXPRESSION_FROM_LINK (Link);
3453
3454 if ((Expression->Type == EFI_HII_EXPRESSION_RULE) && (Expression->ExtraData.RuleId == RuleId)) {
3455 return Expression;
3456 }
3457
3458 Link = GetNextNode (&Form->RuleListHead, Link);
3459 }
3460
3461 return NULL;
3462}
3463
3464/**
3465 Locate the Unicode Collation Protocol interface for later use.
3466
3467 @retval EFI_SUCCESS Protocol interface initialize success.
3468 @retval Other Protocol interface initialize failed.
3469
3470**/
3471EFI_STATUS
3472InitializeUnicodeCollationProtocol (
3473 VOID
3474 )
3475{
3476 EFI_STATUS Status;
3477
3478 if (mUnicodeCollation != NULL) {
3479 return EFI_SUCCESS;
3480 }
3481
3482 //
3483 // BUGBUG: Proper implementation is to locate all Unicode Collation Protocol
3484 // instances first and then select one which support English language.
3485 // Current implementation just pick the first instance.
3486 //
3487 Status = gBS->LocateProtocol (
3488 &gEfiUnicodeCollation2ProtocolGuid,
3489 NULL,
3490 (VOID **)&mUnicodeCollation
3491 );
3492 return Status;
3493}
3494
3495/**
3496 Check whether the formset guid is in this Hii package list.
3497
3498 @param[in] HiiHandle The HiiHandle for this HII package list.
3499 @param[in] FormSetGuid The formset guid for the request formset.
3500
3501 @retval TRUE Find the formset guid.
3502 @retval FALSE Not found the formset guid.
3503
3504**/
3505BOOLEAN
3506IsFormsetGuidInHiiHandle (
3507 IN EFI_HII_HANDLE HiiHandle,
3508 IN EFI_GUID *FormSetGuid
3509 )
3510{
3511 EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
3512 UINTN BufferSize;
3513 UINT32 Offset;
3514 UINT32 Offset2;
3515 UINT32 PackageListLength;
3516 EFI_HII_PACKAGE_HEADER *PackageHeader;
3517 UINT8 *Package;
3518 UINT8 *OpCodeData;
3519 EFI_STATUS Status;
3520 BOOLEAN FindGuid;
3521 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
3522
3523 if (FormSetGuid == NULL) {
3524 return FALSE;
3525 }
3526
3527 BufferSize = 0;
3528 HiiPackageList = NULL;
3529 FindGuid = FALSE;
3530
3531 //
3532 // Locate required Hii Database protocol
3533 //
3534 Status = gBS->LocateProtocol (
3535 &gEfiHiiDatabaseProtocolGuid,
3536 NULL,
3537 (VOID **)&HiiDatabase
3538 );
3539 if (EFI_ERROR (Status)) {
3540 return FALSE;
3541 }
3542
3543 Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
3544 if (Status == EFI_BUFFER_TOO_SMALL) {
3545 HiiPackageList = AllocatePool (BufferSize);
3546 if (HiiPackageList == NULL) {
3547 ASSERT (HiiPackageList != NULL);
3548 return FALSE;
3549 }
3550
3551 Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
3552 } else {
3553 //
3554 // Fix coverity: 14253 Explicit null dereferenced.
3555 // When calling ExportPackageLists with BufferSize = 0, only EFI_BUFFER_TOO_SMALL is expected.
3556 // Otherwise, return FALSE immediately.
3557 //
3558 return FALSE;
3559 }
3560
3561 if (EFI_ERROR (Status)) {
3562 if (HiiPackageList != NULL) {
3563 FreePool (HiiPackageList);
3564 }
3565
3566 return FALSE;
3567 }
3568
3569 //
3570 // Get Form package from this HII package List
3571 //
3572 Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
3573 Offset2 = 0;
3574 PackageListLength = HiiPackageList->PackageLength;
3575
3576 while (Offset < PackageListLength) {
3577 Package = ((UINT8 *)HiiPackageList) + Offset;
3578 PackageHeader = (EFI_HII_PACKAGE_HEADER *)Package;
3579 Offset += PackageHeader->Length;
3580
3581 if (PackageHeader->Type == EFI_HII_PACKAGE_FORMS) {
3582 //
3583 // Search FormSet in this Form Package
3584 //
3585 Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
3586 while (Offset2 < PackageHeader->Length) {
3587 OpCodeData = Package + Offset2;
3588
3589 if (((EFI_IFR_OP_HEADER *)OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
3590 if (CompareGuid (FormSetGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
3591 FindGuid = TRUE;
3592 break;
3593 }
3594 }
3595
3596 Offset2 += ((EFI_IFR_OP_HEADER *)OpCodeData)->Length;
3597 }
3598 }
3599
3600 if (FindGuid) {
3601 break;
3602 }
3603 }
3604
3605 FreePool (HiiPackageList);
3606
3607 return FindGuid;
3608}
3609
3610/**
3611 Find HII Handle in the HII database associated with given Device Path.
3612
3613 If DevicePath is NULL, then ASSERT.
3614
3615 @param[in] DevicePath Device Path associated with the HII package list
3616 handle.
3617 @param[in] FormsetGuid The formset guid for this formset.
3618
3619 @retval Handle HII package list Handle associated with the Device
3620 Path.
3621 @retval NULL Hii Package list handle is not found.
3622
3623**/
3624EFI_HII_HANDLE
3625DevicePathToHiiHandle (
3626 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3627 IN EFI_GUID *FormsetGuid
3628 )
3629{
3630 EFI_STATUS Status;
3631 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;
3632 UINTN Index;
3633 EFI_HANDLE Handle;
3634 EFI_HANDLE DriverHandle;
3635 EFI_HII_HANDLE *HiiHandles;
3636 EFI_HII_HANDLE HiiHandle;
3637 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
3638
3639 if ((DevicePath == NULL) || (FormsetGuid == NULL)) {
3640 return NULL;
3641 }
3642
3643 TmpDevicePath = DevicePath;
3644 //
3645 // Locate Device Path Protocol handle buffer
3646 //
3647 Status = gBS->LocateDevicePath (
3648 &gEfiDevicePathProtocolGuid,
3649 &TmpDevicePath,
3650 &DriverHandle
3651 );
3652 if (EFI_ERROR (Status) || !IsDevicePathEnd (TmpDevicePath)) {
3653 return NULL;
3654 }
3655
3656 //
3657 // Locate required Hii Database protocol
3658 //
3659 Status = gBS->LocateProtocol (
3660 &gEfiHiiDatabaseProtocolGuid,
3661 NULL,
3662 (VOID **)&HiiDatabase
3663 );
3664 if (EFI_ERROR (Status)) {
3665 return NULL;
3666 }
3667
3668 //
3669 // Retrieve all HII Handles from HII database
3670 //
3671 HiiHandles = HiiGetHiiHandles (NULL);
3672 if (HiiHandles == NULL) {
3673 return NULL;
3674 }
3675
3676 //
3677 // Search Hii Handle by Driver Handle
3678 //
3679 HiiHandle = NULL;
3680 for (Index = 0; HiiHandles[Index] != NULL; Index++) {
3681 Status = HiiDatabase->GetPackageListHandle (
3682 HiiDatabase,
3683 HiiHandles[Index],
3684 &Handle
3685 );
3686 if (!EFI_ERROR (Status) && (Handle == DriverHandle)) {
3687 if (IsFormsetGuidInHiiHandle (HiiHandles[Index], FormsetGuid)) {
3688 HiiHandle = HiiHandles[Index];
3689 break;
3690 }
3691
3692 if (HiiHandle != NULL) {
3693 break;
3694 }
3695 }
3696 }
3697
3698 FreePool (HiiHandles);
3699 return HiiHandle;
3700}
3701
3702/**
3703 Get question value from the predefined formset.
3704
3705 @param[in] DevicePath The driver's device path which produce the formset data.
3706 @param[in] InputHiiHandle The hii handle associate with the formset data.
3707 @param[in] FormSetGuid The formset guid which include the question.
3708 @param[in] QuestionId The question id which need to get value from.
3709 @param[out] Value The return data about question's value.
3710
3711 @retval TRUE Get the question value success.
3712 @retval FALSE Get the question value failed.
3713**/
3714BOOLEAN
3715GetQuestionValueFromForm (
3716 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
3717 IN EFI_HII_HANDLE InputHiiHandle,
3718 IN EFI_GUID *FormSetGuid,
3719 IN EFI_QUESTION_ID QuestionId,
3720 OUT EFI_HII_VALUE *Value
3721 )
3722{
3723 EFI_STATUS Status;
3724 EFI_HII_HANDLE HiiHandle;
3725 HII_STATEMENT *Question;
3726 HII_FORMSET *FormSet;
3727 HII_FORM *Form;
3728 BOOLEAN GetTheVal;
3729 LIST_ENTRY *Link;
3730
3731 //
3732 // The input parameter DevicePath or InputHiiHandle must have one valid input.
3733 //
3734 if ((DevicePath == NULL) && (InputHiiHandle == NULL)) {
3735 ASSERT (
3736 (DevicePath != NULL && InputHiiHandle == NULL) ||
3737 (DevicePath == NULL && InputHiiHandle != NULL)
3738 );
3739 return FALSE;
3740 }
3741
3742 if ((FormSetGuid == NULL) || (Value == NULL)) {
3743 return FALSE;
3744 }
3745
3746 GetTheVal = TRUE;
3747 HiiHandle = NULL;
3748 Question = NULL;
3749 Form = NULL;
3750
3751 //
3752 // Get HiiHandle.
3753 //
3754 if (DevicePath != NULL) {
3755 HiiHandle = DevicePathToHiiHandle (DevicePath, FormSetGuid);
3756 if (HiiHandle == NULL) {
3757 return FALSE;
3758 }
3759 } else {
3760 HiiHandle = InputHiiHandle;
3761 }
3762
3763 ASSERT (HiiHandle != NULL);
3764
3765 //
3766 // Get the formset data include this question.
3767 //
3768 FormSet = AllocateZeroPool (sizeof (HII_FORMSET));
3769 ASSERT (FormSet != NULL);
3770
3771 Status = CreateFormSetFromHiiHandle (HiiHandle, FormSetGuid, FormSet);
3772 if (EFI_ERROR (Status)) {
3773 GetTheVal = FALSE;
3774 goto Done;
3775 }
3776
3777 InitializeFormSet (FormSet);
3778
3779 //
3780 // Base on the Question Id to get the question info.
3781 //
3782 Question = QuestionIdInFormset (FormSet, NULL, QuestionId);
3783 if (Question == NULL) {
3784 GetTheVal = FALSE;
3785 goto Done;
3786 }
3787
3788 //
3789 // Search form in the formset scope
3790 //
3791 Link = GetFirstNode (&FormSet->FormListHead);
3792 while (!IsNull (&FormSet->FormListHead, Link)) {
3793 Form = HII_FORM_FROM_LINK (Link);
3794
3795 Question = QuestionIdInForm (Form, QuestionId);
3796 if (Question != NULL) {
3797 break;
3798 }
3799
3800 Link = GetNextNode (&FormSet->FormListHead, Link);
3801 Form = NULL;
3802 }
3803
3804 ASSERT (Form != NULL);
3805
3806 //
3807 // Get the question value.
3808 //
3809 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
3810 if (EFI_ERROR (Status)) {
3811 GetTheVal = FALSE;
3812 goto Done;
3813 }
3814
3815 CopyMem (Value, &Question->Value, sizeof (EFI_HII_VALUE));
3816
3817Done:
3818 //
3819 // Clean the formset structure and restore the global parameter.
3820 //
3821 if (FormSet != NULL) {
3822 DestroyFormSet (FormSet);
3823 }
3824
3825 return GetTheVal;
3826}
3827
3828/**
3829 Covert HII_STATEMENT_VALUE to EFI_HII_VALUE.
3830
3831 The HiiValue->Buffer is allocated from EFI boot services memory. It is the
3832 responsibility of the caller to free the memory allocated.
3833
3834 @param[in] StatementValue Source to be converted.
3835 @param[out] HiiValue The buffer that is converted from StatementValue
3836
3837 @retval EFI_SUCCESS Convert successfully.
3838 @retval EFI_INVALID_PARAMETER StatementValue is NULL or HiiValue is NULL.
3839
3840**/
3841EFI_STATUS
3842HiiStatementValueToHiiValue (
3843 IN HII_STATEMENT_VALUE *StatementValue,
3844 OUT EFI_HII_VALUE *HiiValue
3845 )
3846{
3847 if ((StatementValue == NULL) || (HiiValue == NULL)) {
3848 return EFI_INVALID_PARAMETER;
3849 }
3850
3851 ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));
3852
3853 HiiValue->Type = StatementValue->Type;
3854 HiiValue->BufferLen = StatementValue->BufferLen;
3855 if ((StatementValue->Buffer != NULL) && (StatementValue->BufferLen > 0)) {
3856 HiiValue->Buffer = AllocateCopyPool (HiiValue->BufferLen, StatementValue->Buffer);
3857 }
3858
3859 CopyMem (&HiiValue->Value, &StatementValue->Value, sizeof (EFI_IFR_TYPE_VALUE));
3860
3861 return EFI_SUCCESS;
3862}
3863
3864/**
3865 Release the buffer in EFI_HII_VALUE if the buffer is not NULL.
3866
3867 @param[in] HiiValue The buffer to be released.
3868
3869 @retval EFI_SUCCESS release HiiValue successfully.
3870 @retval EFI_INVALID_PARAMETER HiiValue is NULL.
3871
3872**/
3873EFI_STATUS
3874ReleaseHiiValue (
3875 IN EFI_HII_VALUE *HiiValue
3876 )
3877{
3878 if (HiiValue == NULL) {
3879 return EFI_INVALID_PARAMETER;
3880 }
3881
3882 if (HiiValue->Buffer == NULL) {
3883 return EFI_SUCCESS;
3884 }
3885
3886 FreePool (HiiValue->Buffer);
3887 ZeroMem (HiiValue, sizeof (EFI_HII_VALUE));
3888
3889 return EFI_SUCCESS;
3890}
3891
3892/**
3893 Evaluate the result of a HII expression.
3894
3895 If Expression is NULL, then ASSERT.
3896
3897 @param[in] FormSet FormSet associated with this expression.
3898 @param[in] Form Form associated with this expression.
3899 @param[in,out] Expression Expression to be evaluated.
3900
3901 @retval EFI_SUCCESS The expression evaluated successfully.
3902 @retval EFI_NOT_FOUND The Question which referenced by a QuestionId
3903 could not be found.
3904 @retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the
3905 stack.
3906 @retval EFI_ACCESS_DENIED The pop operation underflowed the stack.
3907 @retval EFI_INVALID_PARAMETER Syntax error with the Expression.
3908 @retval EFI_INVALID_PARAMETER Formset, Form or Expression is NULL.
3909
3910**/
3911EFI_STATUS
3912EvaluateHiiExpression (
3913 IN HII_FORMSET *FormSet,
3914 IN HII_FORM *Form,
3915 IN OUT HII_EXPRESSION *Expression
3916 )
3917{
3918 EFI_STATUS Status;
3919 LIST_ENTRY *Link;
3920 HII_EXPRESSION_OPCODE *OpCode;
3921 HII_STATEMENT *Question;
3922 HII_STATEMENT *Question2;
3923 UINT16 Index;
3924 EFI_HII_VALUE Data1;
3925 EFI_HII_VALUE Data2;
3926 EFI_HII_VALUE Data3;
3927 HII_EXPRESSION *RuleExpression;
3928 EFI_HII_VALUE *Value;
3929 INTN Result;
3930 CHAR16 *StrPtr;
3931 CHAR16 *NameValue;
3932 UINT32 TempValue;
3933 LIST_ENTRY *SubExpressionLink;
3934 HII_EXPRESSION *SubExpression;
3935 UINTN StackOffset;
3936 UINTN TempLength;
3937 CHAR16 TempStr[5];
3938 UINT8 DigitUint8;
3939 UINT8 *TempBuffer;
3940 EFI_TIME EfiTime;
3941 EFI_HII_VALUE QuestionVal;
3942 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
3943 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *PathFromText;
3944
3945 if ((FormSet == NULL) || (Form == NULL) || (Expression == NULL)) {
3946 return EFI_INVALID_PARAMETER;
3947 }
3948
3949 StrPtr = NULL;
3950 DevicePath = NULL;
3951 PathFromText = NULL;
3952
3953 //
3954 // Save current stack offset.
3955 //
3956 StackOffset = SaveExpressionEvaluationStackOffset ();
3957
3958 ASSERT (Expression != NULL);
3959 Expression->Result.Type = EFI_IFR_TYPE_OTHER;
3960
3961 Link = GetFirstNode (&Expression->OpCodeListHead);
3962 while (!IsNull (&Expression->OpCodeListHead, Link)) {
3963 OpCode = HII_EXPRESSION_OPCODE_FROM_LINK (Link);
3964
3965 Link = GetNextNode (&Expression->OpCodeListHead, Link);
3966
3967 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
3968 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
3969 ZeroMem (&Data3, sizeof (EFI_HII_VALUE));
3970
3971 Value = &Data3;
3972 Value->Type = EFI_IFR_TYPE_BOOLEAN;
3973 Status = EFI_SUCCESS;
3974
3975 switch (OpCode->Operand) {
3976 //
3977 // Built-in functions
3978 //
3979 case EFI_IFR_EQ_ID_VAL_OP:
3980 Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdValData.QuestionId);
3981 if (Question == NULL) {
3982 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3983 break;
3984 }
3985
3986 //
3987 // Load value from storage.
3988 //
3989 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
3990 if (EFI_ERROR (Status)) {
3991 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3992 break;
3993 }
3994
3995 Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);
3996 if (EFI_ERROR (Status)) {
3997 Value->Type = EFI_IFR_TYPE_UNDEFINED;
3998 break;
3999 }
4000
4001 Status = CompareHiiValue (&Data1, &OpCode->ExtraData.EqIdValData.Value, &Result, NULL);
4002 ReleaseHiiValue (&Data1);
4003 if (Status == EFI_UNSUPPORTED) {
4004 Status = EFI_SUCCESS;
4005 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4006 break;
4007 }
4008
4009 if (EFI_ERROR (Status)) {
4010 goto Done;
4011 }
4012
4013 Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
4014 break;
4015
4016 case EFI_IFR_EQ_ID_ID_OP:
4017 Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdIdData.QuestionId1);
4018 if (Question == NULL) {
4019 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4020 break;
4021 }
4022
4023 //
4024 // Load value from storage.
4025 //
4026 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
4027 if (EFI_ERROR (Status)) {
4028 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4029 break;
4030 }
4031
4032 Status = HiiStatementValueToHiiValue (&Question->Value, &Data1);
4033 if (EFI_ERROR (Status)) {
4034 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4035 break;
4036 }
4037
4038 Question2 = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdIdData.QuestionId2);
4039 if (Question2 == NULL) {
4040 ReleaseHiiValue (&Data1);
4041 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4042 break;
4043 }
4044
4045 //
4046 // Load value from storage.
4047 //
4048 Status = GetQuestionValue (FormSet, Form, Question2, GetSetValueWithBuffer);
4049 if (EFI_ERROR (Status)) {
4050 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4051 break;
4052 }
4053
4054 Status = HiiStatementValueToHiiValue (&Question2->Value, &Data2);
4055 if (EFI_ERROR (Status)) {
4056 ReleaseHiiValue (&Data1);
4057 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4058 break;
4059 }
4060
4061 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);
4062 ReleaseHiiValue (&Data1);
4063 ReleaseHiiValue (&Data2);
4064 if (Status == EFI_UNSUPPORTED) {
4065 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4066 Status = EFI_SUCCESS;
4067 break;
4068 }
4069
4070 if (EFI_ERROR (Status)) {
4071 goto Done;
4072 }
4073
4074 Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
4075 break;
4076
4077 case EFI_IFR_EQ_ID_VAL_LIST_OP:
4078 Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.EqIdListData.QuestionId);
4079 if (Question == NULL) {
4080 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4081 break;
4082 }
4083
4084 //
4085 // Load value from storage.
4086 //
4087 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
4088 if (EFI_ERROR (Status)) {
4089 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4090 break;
4091 }
4092
4093 Value->Value.b = FALSE;
4094 for (Index = 0; Index < OpCode->ExtraData.EqIdListData.ListLength; Index++) {
4095 if (Question->Value.Value.u16 == OpCode->ExtraData.EqIdListData.ValueList[Index]) {
4096 Value->Value.b = TRUE;
4097 break;
4098 }
4099 }
4100
4101 break;
4102
4103 case EFI_IFR_DUP_OP:
4104 Status = PopExpression (Value);
4105 if (EFI_ERROR (Status)) {
4106 goto Done;
4107 }
4108
4109 Status = PushExpression (Value);
4110 break;
4111
4112 case EFI_IFR_QUESTION_REF1_OP:
4113 case EFI_IFR_THIS_OP:
4114 Question = QuestionIdInFormset (FormSet, Form, OpCode->ExtraData.QuestionRef1Data.QuestionId);
4115 if (Question == NULL) {
4116 Status = EFI_NOT_FOUND;
4117 goto Done;
4118 }
4119
4120 //
4121 // Load value from storage.
4122 //
4123 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
4124 if (EFI_ERROR (Status)) {
4125 goto Done;
4126 }
4127
4128 Status = HiiStatementValueToHiiValue (&Question->Value, Value);
4129 if (EFI_ERROR (Status)) {
4130 ReleaseHiiValue (Value);
4131 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4132 }
4133
4134 break;
4135
4136 case EFI_IFR_SECURITY_OP:
4137 Value->Value.b = CheckUserPrivilege (&OpCode->ExtraData.Guid);
4138 break;
4139
4140 case EFI_IFR_GET_OP:
4141 //
4142 // Get Value from VarStore buffer, EFI VarStore, Name/Value VarStore.
4143 //
4144 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4145 Value->Value.u8 = 0;
4146 if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {
4147 switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {
4148 case EFI_HII_VARSTORE_BUFFER:
4149 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
4150 //
4151 // Get value from Edit Buffer
4152 //
4153 Value->Type = OpCode->ExtraData.GetSetData.ValueType;
4154 CopyMem (&Value->Value, OpCode->ExtraData.GetSetData.VarStorage->EditBuffer + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, OpCode->ExtraData.GetSetData.ValueWidth);
4155 break;
4156 case EFI_HII_VARSTORE_NAME_VALUE:
4157 if (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_STRING) {
4158 //
4159 // Get value from string except for STRING value.
4160 //
4161 Status = GetValueByName (OpCode->ExtraData.GetSetData.VarStorage, OpCode->ExtraData.GetSetData.ValueName, &StrPtr);
4162 if (!EFI_ERROR (Status)) {
4163 ASSERT (StrPtr != NULL);
4164 TempLength = StrLen (StrPtr);
4165 if (OpCode->ExtraData.GetSetData.ValueWidth >= ((TempLength + 1) / 2)) {
4166 Value->Type = OpCode->ExtraData.GetSetData.ValueType;
4167 TempBuffer = (UINT8 *)&Value->Value;
4168 ZeroMem (TempStr, sizeof (TempStr));
4169 for (Index = 0; Index < TempLength; Index++) {
4170 TempStr[0] = StrPtr[TempLength - Index - 1];
4171 DigitUint8 = (UINT8)StrHexToUint64 (TempStr);
4172 if ((Index & 1) == 0) {
4173 TempBuffer[Index/2] = DigitUint8;
4174 } else {
4175 TempBuffer[Index/2] = (UINT8)((DigitUint8 << 4) + TempBuffer[Index/2]);
4176 }
4177 }
4178 }
4179 }
4180 }
4181
4182 break;
4183 case EFI_HII_VARSTORE_EFI_VARIABLE:
4184 //
4185 // Get value from variable.
4186 //
4187 TempLength = OpCode->ExtraData.GetSetData.ValueWidth;
4188 Value->Type = OpCode->ExtraData.GetSetData.ValueType;
4189 Status = gRT->GetVariable (
4190 OpCode->ExtraData.GetSetData.ValueName,
4191 &OpCode->ExtraData.GetSetData.VarStorage->Guid,
4192 NULL,
4193 &TempLength,
4194 &Value->Value
4195 );
4196 if (EFI_ERROR (Status)) {
4197 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4198 Value->Value.u8 = 0;
4199 }
4200
4201 break;
4202 default:
4203 //
4204 // Not recognize storage.
4205 //
4206 Status = EFI_UNSUPPORTED;
4207 goto Done;
4208 }
4209 } else {
4210 //
4211 // For Time/Date Data
4212 //
4213 if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {
4214 //
4215 // Only support Data/Time data when storage doesn't exist.
4216 //
4217 Status = EFI_UNSUPPORTED;
4218 goto Done;
4219 }
4220
4221 Status = gRT->GetTime (&EfiTime, NULL);
4222 if (!EFI_ERROR (Status)) {
4223 if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE) {
4224 switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
4225 case 0x00:
4226 Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
4227 Value->Value.u16 = EfiTime.Year;
4228 break;
4229 case 0x02:
4230 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
4231 Value->Value.u8 = EfiTime.Month;
4232 break;
4233 case 0x03:
4234 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
4235 Value->Value.u8 = EfiTime.Day;
4236 break;
4237 default:
4238 //
4239 // Invalid Date field.
4240 //
4241 Status = EFI_INVALID_PARAMETER;
4242 goto Done;
4243 }
4244 } else {
4245 switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
4246 case 0x00:
4247 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
4248 Value->Value.u8 = EfiTime.Hour;
4249 break;
4250 case 0x01:
4251 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
4252 Value->Value.u8 = EfiTime.Minute;
4253 break;
4254 case 0x02:
4255 Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
4256 Value->Value.u8 = EfiTime.Second;
4257 break;
4258 default:
4259 //
4260 // Invalid Time field.
4261 //
4262 Status = EFI_INVALID_PARAMETER;
4263 goto Done;
4264 }
4265 }
4266 }
4267 }
4268
4269 break;
4270
4271 case EFI_IFR_QUESTION_REF3_OP:
4272 //
4273 // EFI_IFR_QUESTION_REF3
4274 // Pop an expression from the expression stack
4275 //
4276 Status = PopExpression (Value);
4277 if (EFI_ERROR (Status)) {
4278 goto Done;
4279 }
4280
4281 //
4282 // Validate the expression value
4283 //
4284 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
4285 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4286 break;
4287 }
4288
4289 if (OpCode->ExtraData.QuestionRef3Data.DevicePath != 0) {
4290 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4291
4292 Status = gBS->LocateProtocol (
4293 &gEfiDevicePathFromTextProtocolGuid,
4294 NULL,
4295 (VOID **)&PathFromText
4296 );
4297 if (EFI_ERROR (Status)) {
4298 goto Done;
4299 }
4300
4301 StrPtr = GetTokenString (OpCode->ExtraData.QuestionRef3Data.DevicePath, FormSet->HiiHandle);
4302 if ((StrPtr != NULL) && (PathFromText != NULL)) {
4303 DevicePath = PathFromText->ConvertTextToDevicePath (StrPtr);
4304 if ((DevicePath != NULL) && GetQuestionValueFromForm (DevicePath, NULL, &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {
4305 Value = &QuestionVal;
4306 }
4307
4308 if (DevicePath != NULL) {
4309 FreePool (DevicePath);
4310 }
4311 }
4312
4313 if (StrPtr != NULL) {
4314 FreePool (StrPtr);
4315 }
4316 } else if (IsZeroGuid (&OpCode->ExtraData.Guid)) {
4317 if (!GetQuestionValueFromForm (NULL, FormSet->HiiHandle, &OpCode->ExtraData.Guid, Value->Value.u16, &QuestionVal)) {
4318 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4319 break;
4320 }
4321
4322 Value = &QuestionVal;
4323 } else {
4324 Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);
4325 if (Question == NULL) {
4326 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4327 break;
4328 }
4329
4330 //
4331 // Load value from storage.
4332 //
4333 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
4334 if (EFI_ERROR (Status)) {
4335 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4336 break;
4337 }
4338
4339 //
4340 // push the questions' value on to the expression stack
4341 //
4342 Status = HiiStatementValueToHiiValue (&Question->Value, Value);
4343 if (EFI_ERROR (Status)) {
4344 ReleaseHiiValue (Value);
4345 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4346 }
4347 }
4348
4349 break;
4350
4351 case EFI_IFR_RULE_REF_OP:
4352 //
4353 // Find expression for this rule
4354 //
4355 RuleExpression = RuleIdToExpression (Form, OpCode->ExtraData.RuleId);
4356 if (RuleExpression == NULL) {
4357 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4358 break;
4359 }
4360
4361 //
4362 // Evaluate this rule expression
4363 //
4364 Status = EvaluateHiiExpression (FormSet, Form, RuleExpression);
4365 if (EFI_ERROR (Status) || (RuleExpression->Result.Type == EFI_IFR_TYPE_UNDEFINED)) {
4366 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4367 break;
4368 }
4369
4370 Value = &RuleExpression->Result;
4371 break;
4372
4373 case EFI_IFR_STRING_REF1_OP:
4374 Value->Type = EFI_IFR_TYPE_STRING;
4375 Value->Value.string = OpCode->ExtraData.Value.Value.string;
4376 break;
4377
4378 //
4379 // Constant
4380 //
4381 case EFI_IFR_TRUE_OP:
4382 case EFI_IFR_FALSE_OP:
4383 case EFI_IFR_ONE_OP:
4384 case EFI_IFR_ONES_OP:
4385 case EFI_IFR_UINT8_OP:
4386 case EFI_IFR_UINT16_OP:
4387 case EFI_IFR_UINT32_OP:
4388 case EFI_IFR_UINT64_OP:
4389 case EFI_IFR_UNDEFINED_OP:
4390 case EFI_IFR_VERSION_OP:
4391 case EFI_IFR_ZERO_OP:
4392 Value = &OpCode->ExtraData.Value;
4393 break;
4394
4395 //
4396 // unary-op
4397 //
4398 case EFI_IFR_LENGTH_OP:
4399 Status = PopExpression (Value);
4400 if (EFI_ERROR (Status)) {
4401 goto Done;
4402 }
4403
4404 if ((Value->Type != EFI_IFR_TYPE_STRING) && !IsTypeInBuffer (Value)) {
4405 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4406 break;
4407 }
4408
4409 if (Value->Type == EFI_IFR_TYPE_STRING) {
4410 StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
4411 if (StrPtr == NULL) {
4412 Status = EFI_INVALID_PARAMETER;
4413 goto Done;
4414 }
4415
4416 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
4417 Value->Value.u64 = StrLen (StrPtr);
4418 FreePool (StrPtr);
4419 } else {
4420 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
4421 Value->Value.u64 = GetLengthForValue (Value);
4422 FreePool (Value->Buffer);
4423 }
4424
4425 break;
4426
4427 case EFI_IFR_NOT_OP:
4428 Status = PopExpression (Value);
4429 if (EFI_ERROR (Status)) {
4430 goto Done;
4431 }
4432
4433 if (Value->Type != EFI_IFR_TYPE_BOOLEAN) {
4434 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4435 break;
4436 }
4437
4438 Value->Value.b = (BOOLEAN)(!Value->Value.b);
4439 break;
4440
4441 case EFI_IFR_QUESTION_REF2_OP:
4442 //
4443 // Pop an expression from the expression stack
4444 //
4445 Status = PopExpression (Value);
4446 if (EFI_ERROR (Status)) {
4447 goto Done;
4448 }
4449
4450 //
4451 // Validate the expression value
4452 //
4453 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
4454 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4455 break;
4456 }
4457
4458 Question = QuestionIdInFormset (FormSet, Form, Value->Value.u16);
4459 if (Question == NULL) {
4460 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4461 break;
4462 }
4463
4464 //
4465 // Load value from storage.
4466 //
4467 Status = GetQuestionValue (FormSet, Form, Question, GetSetValueWithBuffer);
4468 if (EFI_ERROR (Status)) {
4469 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4470 break;
4471 }
4472
4473 Status = HiiStatementValueToHiiValue (&Question->Value, Value);
4474 if (EFI_ERROR (Status)) {
4475 ReleaseHiiValue (Value);
4476 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4477 }
4478
4479 break;
4480
4481 case EFI_IFR_STRING_REF2_OP:
4482 //
4483 // Pop an expression from the expression stack
4484 //
4485 Status = PopExpression (Value);
4486 if (EFI_ERROR (Status)) {
4487 goto Done;
4488 }
4489
4490 //
4491 // Validate the expression value
4492 //
4493 if ((Value->Type > EFI_IFR_TYPE_NUM_SIZE_64) || (Value->Value.u64 > 0xffff)) {
4494 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4495 break;
4496 }
4497
4498 Value->Type = EFI_IFR_TYPE_STRING;
4499 StrPtr = GetTokenString (Value->Value.u16, FormSet->HiiHandle);
4500 if (StrPtr == NULL) {
4501 //
4502 // If String not exit, push an empty string
4503 //
4504 Value->Value.string = NewHiiString (gEmptyString, FormSet->HiiHandle);
4505 } else {
4506 Index = (UINT16)Value->Value.u64;
4507 Value->Value.string = Index;
4508 FreePool (StrPtr);
4509 }
4510
4511 break;
4512
4513 case EFI_IFR_TO_BOOLEAN_OP:
4514 //
4515 // Pop an expression from the expression stack
4516 //
4517 Status = PopExpression (Value);
4518 if (EFI_ERROR (Status)) {
4519 goto Done;
4520 }
4521
4522 //
4523 // Convert an expression to a Boolean
4524 //
4525 if (Value->Type <= EFI_IFR_TYPE_DATE) {
4526 //
4527 // When converting from an unsigned integer, zero will be converted to
4528 // FALSE and any other value will be converted to TRUE.
4529 //
4530 Value->Value.b = (BOOLEAN)(HiiValueToUINT64 (Value) != 0);
4531
4532 Value->Type = EFI_IFR_TYPE_BOOLEAN;
4533 } else if (Value->Type == EFI_IFR_TYPE_STRING) {
4534 //
4535 // When converting from a string, if case-insensitive compare
4536 // with "true" is True, then push True. If a case-insensitive compare
4537 // with "false" is True, then push False. Otherwise, push Undefined.
4538 //
4539 StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
4540 if (StrPtr == NULL) {
4541 Status = EFI_INVALID_PARAMETER;
4542 goto Done;
4543 }
4544
4545 IfrStrToUpper (StrPtr);
4546 if (StrCmp (StrPtr, L"TRUE") == 0) {
4547 Value->Value.b = TRUE;
4548 Value->Type = EFI_IFR_TYPE_BOOLEAN;
4549 } else if (StrCmp (StrPtr, L"FALSE") == 0) {
4550 Value->Value.b = FALSE;
4551 Value->Type = EFI_IFR_TYPE_BOOLEAN;
4552 } else {
4553 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4554 }
4555
4556 FreePool (StrPtr);
4557 } else if (Value->Type == EFI_IFR_TYPE_BUFFER) {
4558 //
4559 // When converting from a buffer, if the buffer is all zeroes,
4560 // then push False. Otherwise push True.
4561 //
4562 for (Index = 0; Index < Value->BufferLen; Index++) {
4563 if (Value->Buffer[Index] != 0) {
4564 break;
4565 }
4566 }
4567
4568 if (Index >= Value->BufferLen) {
4569 Value->Value.b = FALSE;
4570 } else {
4571 Value->Value.b = TRUE;
4572 }
4573
4574 Value->Type = EFI_IFR_TYPE_BOOLEAN;
4575 FreePool (Value->Buffer);
4576 }
4577
4578 break;
4579
4580 case EFI_IFR_TO_STRING_OP:
4581 Status = IfrToString (FormSet, OpCode->ExtraData.Format, Value);
4582 break;
4583
4584 case EFI_IFR_TO_UINT_OP:
4585 Status = IfrToUint (FormSet, Value);
4586 break;
4587
4588 case EFI_IFR_TO_LOWER_OP:
4589 case EFI_IFR_TO_UPPER_OP:
4590 Status = InitializeUnicodeCollationProtocol ();
4591 if (EFI_ERROR (Status)) {
4592 goto Done;
4593 }
4594
4595 Status = PopExpression (Value);
4596 if (EFI_ERROR (Status)) {
4597 goto Done;
4598 }
4599
4600 if (Value->Type != EFI_IFR_TYPE_STRING) {
4601 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4602 break;
4603 }
4604
4605 StrPtr = GetTokenString (Value->Value.string, FormSet->HiiHandle);
4606 if (StrPtr == NULL) {
4607 Status = EFI_NOT_FOUND;
4608 goto Done;
4609 }
4610
4611 if (OpCode->Operand == EFI_IFR_TO_LOWER_OP) {
4612 mUnicodeCollation->StrLwr (mUnicodeCollation, StrPtr);
4613 } else {
4614 mUnicodeCollation->StrUpr (mUnicodeCollation, StrPtr);
4615 }
4616
4617 Value->Value.string = NewHiiString (StrPtr, FormSet->HiiHandle);
4618 FreePool (StrPtr);
4619 break;
4620
4621 case EFI_IFR_BITWISE_NOT_OP:
4622 //
4623 // Pop an expression from the expression stack
4624 //
4625 Status = PopExpression (Value);
4626 if (EFI_ERROR (Status)) {
4627 goto Done;
4628 }
4629
4630 if (Value->Type > EFI_IFR_TYPE_DATE) {
4631 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4632 break;
4633 }
4634
4635 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
4636 Value->Value.u64 = ~HiiValueToUINT64(Value);
4637 break;
4638
4639 case EFI_IFR_SET_OP:
4640 //
4641 // Pop an expression from the expression stack
4642 //
4643 Status = PopExpression (Value);
4644 if (EFI_ERROR (Status)) {
4645 goto Done;
4646 }
4647
4648 Data1.Type = EFI_IFR_TYPE_BOOLEAN;
4649 Data1.Value.b = FALSE;
4650 //
4651 // Set value to var storage buffer
4652 //
4653 if (OpCode->ExtraData.GetSetData.VarStorage != NULL) {
4654 switch (OpCode->ExtraData.GetSetData.VarStorage->Type) {
4655 case EFI_HII_VARSTORE_BUFFER:
4656 case EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER:
4657 CopyMem (OpCode->ExtraData.GetSetData.VarStorage->EditBuffer + OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset, &Value->Value, OpCode->ExtraData.GetSetData.ValueWidth);
4658 Data1.Value.b = TRUE;
4659 break;
4660 case EFI_HII_VARSTORE_NAME_VALUE:
4661 if (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_STRING) {
4662 NameValue = AllocatePool ((OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16));
4663 ASSERT (NameValue != NULL);
4664 //
4665 // Convert Buffer to Hex String
4666 //
4667 TempBuffer = (UINT8 *)&Value->Value + OpCode->ExtraData.GetSetData.ValueWidth - 1;
4668 StrPtr = NameValue;
4669 for (Index = 0; Index < OpCode->ExtraData.GetSetData.ValueWidth; Index++, TempBuffer--) {
4670 UnicodeValueToStringS (
4671 StrPtr,
4672 (OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1) * sizeof (CHAR16) - ((UINTN)StrPtr - (UINTN)NameValue),
4673 PREFIX_ZERO | RADIX_HEX,
4674 *TempBuffer,
4675 2
4676 );
4677 StrPtr += StrnLenS (StrPtr, OpCode->ExtraData.GetSetData.ValueWidth * 2 + 1 - ((UINTN)StrPtr - (UINTN)NameValue) / sizeof (CHAR16));
4678 }
4679
4680 Status = SetValueByName (OpCode->ExtraData.GetSetData.VarStorage, OpCode->ExtraData.GetSetData.ValueName, NameValue, NULL);
4681 FreePool (NameValue);
4682 if (!EFI_ERROR (Status)) {
4683 Data1.Value.b = TRUE;
4684 }
4685 }
4686
4687 break;
4688 case EFI_HII_VARSTORE_EFI_VARIABLE:
4689 Status = gRT->SetVariable (
4690 OpCode->ExtraData.GetSetData.ValueName,
4691 &OpCode->ExtraData.GetSetData.VarStorage->Guid,
4692 OpCode->ExtraData.GetSetData.VarStorage->Attributes,
4693 OpCode->ExtraData.GetSetData.ValueWidth,
4694 &Value->Value
4695 );
4696 if (!EFI_ERROR (Status)) {
4697 Data1.Value.b = TRUE;
4698 }
4699
4700 break;
4701 default:
4702 //
4703 // Not recognize storage.
4704 //
4705 Status = EFI_UNSUPPORTED;
4706 goto Done;
4707 }
4708 } else {
4709 //
4710 // For Time/Date Data
4711 //
4712 if ((OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_DATE) && (OpCode->ExtraData.GetSetData.ValueType != EFI_IFR_TYPE_TIME)) {
4713 //
4714 // Only support Data/Time data when storage doesn't exist.
4715 //
4716 Status = EFI_UNSUPPORTED;
4717 goto Done;
4718 }
4719
4720 Status = gRT->GetTime (&EfiTime, NULL);
4721 if (!EFI_ERROR (Status)) {
4722 if (OpCode->ExtraData.GetSetData.ValueType == EFI_IFR_TYPE_DATE) {
4723 switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
4724 case 0x00:
4725 EfiTime.Year = Value->Value.u16;
4726 break;
4727 case 0x02:
4728 EfiTime.Month = Value->Value.u8;
4729 break;
4730 case 0x03:
4731 EfiTime.Day = Value->Value.u8;
4732 break;
4733 default:
4734 //
4735 // Invalid Date field.
4736 //
4737 Status = EFI_INVALID_PARAMETER;
4738 goto Done;
4739 }
4740 } else {
4741 switch (OpCode->ExtraData.GetSetData.VarStoreInfo.VarOffset) {
4742 case 0x00:
4743 EfiTime.Hour = Value->Value.u8;
4744 break;
4745 case 0x01:
4746 EfiTime.Minute = Value->Value.u8;
4747 break;
4748 case 0x02:
4749 EfiTime.Second = Value->Value.u8;
4750 break;
4751 default:
4752 //
4753 // Invalid Time field.
4754 //
4755 Status = EFI_INVALID_PARAMETER;
4756 goto Done;
4757 }
4758 }
4759
4760 Status = gRT->SetTime (&EfiTime);
4761 if (!EFI_ERROR (Status)) {
4762 Data1.Value.b = TRUE;
4763 }
4764 }
4765 }
4766
4767 Value = &Data1;
4768 break;
4769
4770 //
4771 // binary-op
4772 //
4773 case EFI_IFR_ADD_OP:
4774 case EFI_IFR_SUBTRACT_OP:
4775 case EFI_IFR_MULTIPLY_OP:
4776 case EFI_IFR_DIVIDE_OP:
4777 case EFI_IFR_MODULO_OP:
4778 case EFI_IFR_BITWISE_AND_OP:
4779 case EFI_IFR_BITWISE_OR_OP:
4780 case EFI_IFR_SHIFT_LEFT_OP:
4781 case EFI_IFR_SHIFT_RIGHT_OP:
4782 //
4783 // Pop an expression from the expression stack
4784 //
4785 Status = PopExpression (&Data2);
4786 if (EFI_ERROR (Status)) {
4787 goto Done;
4788 }
4789
4790 //
4791 // Pop another expression from the expression stack
4792 //
4793 Status = PopExpression (&Data1);
4794 if (EFI_ERROR (Status)) {
4795 goto Done;
4796 }
4797
4798 if (Data2.Type > EFI_IFR_TYPE_DATE) {
4799 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4800 break;
4801 }
4802
4803 if (Data1.Type > EFI_IFR_TYPE_DATE) {
4804 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4805 break;
4806 }
4807
4808 Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
4809
4810 switch (OpCode->Operand) {
4811 case EFI_IFR_ADD_OP:
4812 Value->Value.u64 = HiiValueToUINT64 (&Data1) + HiiValueToUINT64 (&Data2);
4813 break;
4814
4815 case EFI_IFR_SUBTRACT_OP:
4816 Value->Value.u64 = HiiValueToUINT64 (&Data1) - HiiValueToUINT64 (&Data2);
4817 break;
4818
4819 case EFI_IFR_MULTIPLY_OP:
4820 Value->Value.u64 = MultU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));
4821 break;
4822
4823 case EFI_IFR_DIVIDE_OP:
4824 Value->Value.u64 = DivU64x32 (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2));
4825 break;
4826
4827 case EFI_IFR_MODULO_OP:
4828 DivU64x32Remainder (HiiValueToUINT64 (&Data1), (UINT32)HiiValueToUINT64 (&Data2), &TempValue);
4829 Value->Value.u64 = TempValue;
4830 break;
4831
4832 case EFI_IFR_BITWISE_AND_OP:
4833 Value->Value.u64 = HiiValueToUINT64 (&Data1) & HiiValueToUINT64 (&Data2);
4834 break;
4835
4836 case EFI_IFR_BITWISE_OR_OP:
4837 Value->Value.u64 = HiiValueToUINT64 (&Data1) | HiiValueToUINT64 (&Data2);
4838 break;
4839
4840 case EFI_IFR_SHIFT_LEFT_OP:
4841 Value->Value.u64 = LShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));
4842 break;
4843
4844 case EFI_IFR_SHIFT_RIGHT_OP:
4845 Value->Value.u64 = RShiftU64 (HiiValueToUINT64 (&Data1), (UINTN)HiiValueToUINT64 (&Data2));
4846 break;
4847
4848 default:
4849 break;
4850 }
4851
4852 break;
4853
4854 case EFI_IFR_AND_OP:
4855 case EFI_IFR_OR_OP:
4856 //
4857 // Two Boolean operator
4858 //
4859 Status = PopExpression (&Data2);
4860 if (EFI_ERROR (Status)) {
4861 goto Done;
4862 }
4863
4864 //
4865 // Pop another expression from the expression stack
4866 //
4867 Status = PopExpression (&Data1);
4868 if (EFI_ERROR (Status)) {
4869 goto Done;
4870 }
4871
4872 if (Data2.Type != EFI_IFR_TYPE_BOOLEAN) {
4873 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4874 break;
4875 }
4876
4877 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
4878 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4879 break;
4880 }
4881
4882 if (OpCode->Operand == EFI_IFR_AND_OP) {
4883 Value->Value.b = (BOOLEAN)(Data1.Value.b && Data2.Value.b);
4884 } else {
4885 Value->Value.b = (BOOLEAN)(Data1.Value.b || Data2.Value.b);
4886 }
4887
4888 break;
4889
4890 case EFI_IFR_EQUAL_OP:
4891 case EFI_IFR_NOT_EQUAL_OP:
4892 case EFI_IFR_GREATER_EQUAL_OP:
4893 case EFI_IFR_GREATER_THAN_OP:
4894 case EFI_IFR_LESS_EQUAL_OP:
4895 case EFI_IFR_LESS_THAN_OP:
4896 //
4897 // Compare two integer, string, boolean or date/time
4898 //
4899 Status = PopExpression (&Data2);
4900 if (EFI_ERROR (Status)) {
4901 goto Done;
4902 }
4903
4904 //
4905 // Pop another expression from the expression stack
4906 //
4907 Status = PopExpression (&Data1);
4908 if (EFI_ERROR (Status)) {
4909 goto Done;
4910 }
4911
4912 if ((Data2.Type > EFI_IFR_TYPE_BOOLEAN) &&
4913 (Data2.Type != EFI_IFR_TYPE_STRING) &&
4914 !IsTypeInBuffer (&Data2))
4915 {
4916 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4917 break;
4918 }
4919
4920 if ((Data1.Type > EFI_IFR_TYPE_BOOLEAN) &&
4921 (Data1.Type != EFI_IFR_TYPE_STRING) &&
4922 !IsTypeInBuffer (&Data1))
4923 {
4924 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4925 break;
4926 }
4927
4928 Status = CompareHiiValue (&Data1, &Data2, &Result, FormSet->HiiHandle);
4929 if (Data1.Type == EFI_IFR_TYPE_BUFFER) {
4930 FreePool (Data1.Buffer);
4931 }
4932
4933 if (Data2.Type == EFI_IFR_TYPE_BUFFER) {
4934 FreePool (Data2.Buffer);
4935 }
4936
4937 if (Status == EFI_UNSUPPORTED) {
4938 Value->Type = EFI_IFR_TYPE_UNDEFINED;
4939 Status = EFI_SUCCESS;
4940 break;
4941 }
4942
4943 if (EFI_ERROR (Status)) {
4944 goto Done;
4945 }
4946
4947 switch (OpCode->Operand) {
4948 case EFI_IFR_EQUAL_OP:
4949 Value->Value.b = (BOOLEAN)((Result == 0) ? TRUE : FALSE);
4950 break;
4951
4952 case EFI_IFR_NOT_EQUAL_OP:
4953 Value->Value.b = (BOOLEAN)((Result != 0) ? TRUE : FALSE);
4954 break;
4955
4956 case EFI_IFR_GREATER_EQUAL_OP:
4957 Value->Value.b = (BOOLEAN)((Result >= 0) ? TRUE : FALSE);
4958 break;
4959
4960 case EFI_IFR_GREATER_THAN_OP:
4961 Value->Value.b = (BOOLEAN)((Result > 0) ? TRUE : FALSE);
4962 break;
4963
4964 case EFI_IFR_LESS_EQUAL_OP:
4965 Value->Value.b = (BOOLEAN)((Result <= 0) ? TRUE : FALSE);
4966 break;
4967
4968 case EFI_IFR_LESS_THAN_OP:
4969 Value->Value.b = (BOOLEAN)((Result < 0) ? TRUE : FALSE);
4970 break;
4971
4972 default:
4973 break;
4974 }
4975
4976 break;
4977
4978 case EFI_IFR_MATCH_OP:
4979 Status = InitializeUnicodeCollationProtocol ();
4980 if (EFI_ERROR (Status)) {
4981 goto Done;
4982 }
4983
4984 Status = IfrMatch (FormSet, Value);
4985 break;
4986
4987 case EFI_IFR_MATCH2_OP:
4988 Status = IfrMatch2 (FormSet, &OpCode->ExtraData.Guid, Value);
4989 break;
4990
4991 case EFI_IFR_CATENATE_OP:
4992 Status = IfrCatenate (FormSet, Value);
4993 break;
4994
4995 //
4996 // ternary-op
4997 //
4998 case EFI_IFR_CONDITIONAL_OP:
4999 //
5000 // Pop third expression from the expression stack
5001 //
5002 Status = PopExpression (&Data3);
5003 if (EFI_ERROR (Status)) {
5004 goto Done;
5005 }
5006
5007 //
5008 // Pop second expression from the expression stack
5009 //
5010 Status = PopExpression (&Data2);
5011 if (EFI_ERROR (Status)) {
5012 goto Done;
5013 }
5014
5015 //
5016 // Pop first expression from the expression stack
5017 //
5018 Status = PopExpression (&Data1);
5019 if (EFI_ERROR (Status)) {
5020 goto Done;
5021 }
5022
5023 if (Data1.Type != EFI_IFR_TYPE_BOOLEAN) {
5024 Value->Type = EFI_IFR_TYPE_UNDEFINED;
5025 break;
5026 }
5027
5028 if (Data1.Value.b) {
5029 Value = &Data3;
5030 } else {
5031 Value = &Data2;
5032 }
5033
5034 break;
5035
5036 case EFI_IFR_FIND_OP:
5037 Status = IfrFind (FormSet, OpCode->ExtraData.Format, Value);
5038 break;
5039
5040 case EFI_IFR_MID_OP:
5041 Status = IfrMid (FormSet, Value);
5042 break;
5043
5044 case EFI_IFR_TOKEN_OP:
5045 Status = IfrToken (FormSet, Value);
5046 break;
5047
5048 case EFI_IFR_SPAN_OP:
5049 Status = IfrSpan (FormSet, OpCode->ExtraData.Flags, Value);
5050 break;
5051
5052 case EFI_IFR_MAP_OP:
5053 //
5054 // Pop the check value
5055 //
5056 Status = PopExpression (&Data1);
5057 if (EFI_ERROR (Status)) {
5058 goto Done;
5059 }
5060
5061 //
5062 // Check MapExpression list is valid.
5063 //
5064 if (OpCode->MapExpressionList.ForwardLink == NULL) {
5065 Status = EFI_INVALID_PARAMETER;
5066 goto Done;
5067 }
5068
5069 //
5070 // Go through map expression list.
5071 //
5072 SubExpressionLink = GetFirstNode (&OpCode->MapExpressionList);
5073 while (!IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
5074 SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
5075 //
5076 // Evaluate the first expression in this pair.
5077 //
5078 Status = EvaluateHiiExpression (FormSet, Form, SubExpression);
5079 if (EFI_ERROR (Status)) {
5080 goto Done;
5081 }
5082
5083 //
5084 // Compare the expression value with current value
5085 //
5086 if ((CompareHiiValue (&Data1, &SubExpression->Result, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
5087 //
5088 // Try get the map value.
5089 //
5090 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
5091 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
5092 Status = EFI_INVALID_PARAMETER;
5093 goto Done;
5094 }
5095
5096 SubExpression = HII_EXPRESSION_FROM_LINK (SubExpressionLink);
5097 Status = EvaluateHiiExpression (FormSet, Form, SubExpression);
5098 if (EFI_ERROR (Status)) {
5099 goto Done;
5100 }
5101
5102 Value = &SubExpression->Result;
5103 break;
5104 }
5105
5106 //
5107 // Skip the second expression on this pair.
5108 //
5109 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
5110 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
5111 Status = EFI_INVALID_PARAMETER;
5112 goto Done;
5113 }
5114
5115 //
5116 // Goto the first expression on next pair.
5117 //
5118 SubExpressionLink = GetNextNode (&OpCode->MapExpressionList, SubExpressionLink);
5119 }
5120
5121 //
5122 // No map value is found.
5123 //
5124 if (IsNull (&OpCode->MapExpressionList, SubExpressionLink)) {
5125 Value->Type = EFI_IFR_TYPE_UNDEFINED;
5126 Value->Value.u8 = 0;
5127 }
5128
5129 break;
5130
5131 default:
5132 break;
5133 }
5134
5135 if (EFI_ERROR (Status) || (Value->Type == EFI_IFR_TYPE_UNDEFINED)) {
5136 goto Done;
5137 }
5138
5139 Status = PushExpression (Value);
5140 if (EFI_ERROR (Status)) {
5141 goto Done;
5142 }
5143 }
5144
5145 //
5146 // Pop the final result from expression stack
5147 //
5148 Value = &Data1;
5149 Status = PopExpression (Value);
5150 if (EFI_ERROR (Status)) {
5151 goto Done;
5152 }
5153
5154 //
5155 // After evaluating an expression, there should be only one value left on the expression stack
5156 //
5157 if (PopExpression (Value) != EFI_ACCESS_DENIED) {
5158 Status = EFI_INVALID_PARAMETER;
5159 }
5160
5161Done:
5162 RestoreExpressionEvaluationStackOffset (StackOffset);
5163 if (!EFI_ERROR (Status)) {
5164 CopyMem (&Expression->Result, Value, sizeof (EFI_HII_VALUE));
5165 }
5166
5167 return Status;
5168}
5169
5170/**
5171 Set value of a data element in an Array by its Index.
5172
5173 @param[in] Array The data array.
5174 @param[in] Type Type of the data in this array.
5175 @param[in] Index Zero based index for data in this array.
5176 @param[in] Value The value to be set.
5177
5178**/
5179VOID
5180SetArrayData (
5181 IN VOID *Array,
5182 IN UINT8 Type,
5183 IN UINTN Index,
5184 IN UINT64 Value
5185 )
5186{
5187 ASSERT (Array != NULL);
5188
5189 switch (Type) {
5190 case EFI_IFR_TYPE_NUM_SIZE_8:
5191 *(((UINT8 *)Array) + Index) = (UINT8)Value;
5192 break;
5193
5194 case EFI_IFR_TYPE_NUM_SIZE_16:
5195 *(((UINT16 *)Array) + Index) = (UINT16)Value;
5196 break;
5197
5198 case EFI_IFR_TYPE_NUM_SIZE_32:
5199 *(((UINT32 *)Array) + Index) = (UINT32)Value;
5200 break;
5201
5202 case EFI_IFR_TYPE_NUM_SIZE_64:
5203 *(((UINT64 *)Array) + Index) = (UINT64)Value;
5204 break;
5205
5206 default:
5207 break;
5208 }
5209}
5210
5211/**
5212 Search an Option of a Question by its value.
5213
5214 @param[in] Question The Question
5215 @param[in] OptionValue Value for Option to be searched.
5216
5217 @retval Pointer Pointer to the found Option.
5218 @retval NULL Option not found.
5219
5220**/
5221HII_QUESTION_OPTION *
5222ValueToOption (
5223 IN HII_STATEMENT *Question,
5224 IN HII_STATEMENT_VALUE *OptionValue
5225 )
5226{
5227 LIST_ENTRY *Link;
5228 HII_QUESTION_OPTION *Option;
5229 EFI_HII_VALUE Data1;
5230 EFI_HII_VALUE Data2;
5231 INTN Result;
5232 EFI_STATUS Status;
5233
5234 Result = 0;
5235 ZeroMem (&Data1, sizeof (EFI_HII_VALUE));
5236 ZeroMem (&Data2, sizeof (EFI_HII_VALUE));
5237
5238 Status = HiiStatementValueToHiiValue (OptionValue, &Data1);
5239 ASSERT_EFI_ERROR (Status);
5240
5241 Link = GetFirstNode (&Question->OptionListHead);
5242 while (!IsNull (&Question->OptionListHead, Link)) {
5243 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
5244
5245 Status = HiiStatementValueToHiiValue (&Option->Value, &Data2);
5246 ASSERT_EFI_ERROR (Status);
5247
5248 if ((CompareHiiValue (&Data1, &Data2, &Result, NULL) == EFI_SUCCESS) && (Result == 0)) {
5249 //
5250 // Check the suppressif condition, only a valid option can be return.
5251 //
5252 if ((Option->SuppressExpression == NULL) ||
5253 ((EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) == ExpressFalse)))
5254 {
5255 return Option;
5256 }
5257 }
5258
5259 Link = GetNextNode (&Question->OptionListHead, Link);
5260 }
5261
5262 return NULL;
5263}
5264
5265/**
5266 Find the point in the ConfigResp string for this question.
5267
5268 @param[in] Question The question.
5269 @param[in] ConfigResp Get ConfigResp string.
5270
5271 @retval point to the offset where is for this question.
5272
5273**/
5274CHAR16 *
5275GetOffsetFromConfigResp (
5276 IN HII_STATEMENT *Question,
5277 IN CHAR16 *ConfigResp
5278 )
5279{
5280 CHAR16 *RequestElement;
5281 CHAR16 *BlockData;
5282
5283 //
5284 // Type is EFI_HII_VARSTORE_NAME_VALUE.
5285 //
5286 if (Question->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
5287 RequestElement = StrStr (ConfigResp, Question->VariableName);
5288 if (RequestElement != NULL) {
5289 //
5290 // Skip the "VariableName=" field.
5291 //
5292 RequestElement += StrLen (Question->VariableName) + 1;
5293 }
5294
5295 return RequestElement;
5296 }
5297
5298 //
5299 // Type is EFI_HII_VARSTORE_EFI_VARIABLE or EFI_HII_VARSTORE_EFI_VARIABLE_BUFFER
5300 //
5301
5302 //
5303 // Convert all hex digits in ConfigResp to lower case before searching.
5304 //
5305 HiiStringToLowercase (ConfigResp);
5306
5307 //
5308 // 1. Directly use Question->BlockName to find.
5309 //
5310 RequestElement = StrStr (ConfigResp, Question->BlockName);
5311 if (RequestElement != NULL) {
5312 //
5313 // Skip the "Question->BlockName&VALUE=" field.
5314 //
5315 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");
5316 return RequestElement;
5317 }
5318
5319 //
5320 // 2. Change all hex digits in Question->BlockName to lower and compare again.
5321 //
5322 BlockData = AllocateCopyPool (StrSize (Question->BlockName), Question->BlockName);
5323 ASSERT (BlockData != NULL);
5324 HiiStringToLowercase (BlockData);
5325 RequestElement = StrStr (ConfigResp, BlockData);
5326 FreePool (BlockData);
5327
5328 if (RequestElement != NULL) {
5329 //
5330 // Skip the "Question->BlockName&VALUE=" field.
5331 //
5332 RequestElement += StrLen (Question->BlockName) + StrLen (L"&VALUE=");
5333 }
5334
5335 return RequestElement;
5336}
5337
5338/**
5339 Get Question default value from AltCfg string.
5340
5341 @param[in] FormSet The form set.
5342 @param[in] Form The form
5343 @param[in] Question The question.
5344 @param[out] DefaultValue Default value.
5345
5346 @retval EFI_SUCCESS Question is reset to default value.
5347
5348**/
5349EFI_STATUS
5350GetDefaultValueFromAltCfg (
5351 IN HII_FORMSET *FormSet,
5352 IN HII_FORM *Form,
5353 IN HII_STATEMENT *Question,
5354 OUT HII_STATEMENT_VALUE *DefaultValue
5355 )
5356{
5357 HII_FORMSET_STORAGE *Storage;
5358 CHAR16 *ConfigResp;
5359 CHAR16 *Value;
5360 LIST_ENTRY *Link;
5361 HII_FORM_CONFIG_REQUEST *ConfigInfo;
5362
5363 Storage = Question->Storage;
5364 if ((Storage == NULL) || (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
5365 return EFI_NOT_FOUND;
5366 }
5367
5368 //
5369 // Try to get AltCfg string from form. If not found it, then
5370 // try to get it from formset.
5371 //
5372 ConfigResp = NULL;
5373 Link = GetFirstNode (&Form->ConfigRequestHead);
5374 while (!IsNull (&Form->ConfigRequestHead, Link)) {
5375 ConfigInfo = HII_FORM_CONFIG_REQUEST_FROM_LINK (Link);
5376 Link = GetNextNode (&Form->ConfigRequestHead, Link);
5377
5378 if (Storage == ConfigInfo->Storage) {
5379 ConfigResp = ConfigInfo->ConfigAltResp;
5380 break;
5381 }
5382 }
5383
5384 if (ConfigResp == NULL) {
5385 return EFI_NOT_FOUND;
5386 }
5387
5388 Value = GetOffsetFromConfigResp (Question, ConfigResp);
5389 if (Value == NULL) {
5390 return EFI_NOT_FOUND;
5391 }
5392
5393 return BufferToQuestionValue (Question, Value, DefaultValue);
5394}
5395
5396/**
5397 Get default Id value used for browser.
5398
5399 @param[in] DefaultId The default id value used by hii.
5400
5401 @retval Browser used default value.
5402
5403**/
5404INTN
5405GetDefaultIdForCallBack (
5406 IN UINTN DefaultId
5407 )
5408{
5409 if (DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) {
5410 return EFI_BROWSER_ACTION_DEFAULT_STANDARD;
5411 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
5412 return EFI_BROWSER_ACTION_DEFAULT_MANUFACTURING;
5413 } else if (DefaultId == EFI_HII_DEFAULT_CLASS_SAFE) {
5414 return EFI_BROWSER_ACTION_DEFAULT_SAFE;
5415 } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN + 0x1000)) {
5416 return EFI_BROWSER_ACTION_DEFAULT_PLATFORM + DefaultId - EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN;
5417 } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN + 0x1000)) {
5418 return EFI_BROWSER_ACTION_DEFAULT_HARDWARE + DefaultId - EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN;
5419 } else if ((DefaultId >= EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN) && (DefaultId < EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN + 0x1000)) {
5420 return EFI_BROWSER_ACTION_DEFAULT_FIRMWARE + DefaultId - EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN;
5421 } else {
5422 return -1;
5423 }
5424}
5425
5426/**
5427 Get default value of question.
5428
5429 @param[in] FormSet The form set.
5430 @param[in] Form The form.
5431 @param[in] Question The question.
5432 @param[in] DefaultId The Class of the default.
5433 @param[out] DefaultValue The default value of given question.
5434
5435 @retval EFI_SUCCESS Question is reset to default value.
5436
5437**/
5438EFI_STATUS
5439GetQuestionDefault (
5440 IN HII_FORMSET *FormSet,
5441 IN HII_FORM *Form,
5442 IN HII_STATEMENT *Question,
5443 IN UINT16 DefaultId,
5444 OUT HII_STATEMENT_VALUE *DefaultValue
5445 )
5446{
5447 EFI_STATUS Status;
5448 LIST_ENTRY *Link;
5449 HII_QUESTION_DEFAULT *Default;
5450 HII_QUESTION_OPTION *Option;
5451 HII_STATEMENT_VALUE *HiiValue;
5452 UINT8 Index;
5453 EFI_STRING StrValue;
5454 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
5455 EFI_BROWSER_ACTION_REQUEST ActionRequest;
5456 INTN Action;
5457 EFI_IFR_TYPE_VALUE *TypeValue;
5458 UINT16 OriginalDefaultId;
5459 HII_FORMSET_DEFAULTSTORE *DefaultStore;
5460 LIST_ENTRY *DefaultLink;
5461
5462 if ((FormSet == NULL) || (Form == NULL) || (Question == NULL) || (DefaultValue == NULL)) {
5463 return EFI_INVALID_PARAMETER;
5464 }
5465
5466 Status = EFI_NOT_FOUND;
5467 StrValue = NULL;
5468 ConfigAccess = NULL;
5469 OriginalDefaultId = DefaultId;
5470 DefaultLink = GetFirstNode (&FormSet->DefaultStoreListHead);
5471
5472 //
5473 // Statement don't have storage, skip them
5474 //
5475 if (Question->QuestionId == 0) {
5476 DEBUG ((DEBUG_ERROR, "%a: Question has no storage, skip it\n", __func__));
5477 return Status;
5478 }
5479
5480 //
5481 // There are Five ways to specify default value for a Question:
5482 // 1, use call back function (highest priority)
5483 // 2, use ExtractConfig function
5484 // 3, use nested EFI_IFR_DEFAULT
5485 // 4, set flags of EFI_ONE_OF_OPTION (provide Standard and Manufacturing default)
5486 // 5, set flags of EFI_IFR_CHECKBOX (provide Standard and Manufacturing default) (lowest priority)
5487 //
5488 CopyMem (DefaultValue, &Question->Value, sizeof (HII_STATEMENT_VALUE));
5489ReGetDefault:
5490 HiiValue = DefaultValue;
5491 TypeValue = &HiiValue->Value;
5492 if (HiiValue->Type == EFI_IFR_TYPE_BUFFER) {
5493 //
5494 // For orderedlist, need to pass the BufferValue to Callback function.
5495 //
5496 DefaultValue->BufferLen = Question->Value.BufferLen;
5497 DefaultValue->Buffer = AllocateZeroPool (DefaultValue->BufferLen);
5498 ASSERT (DefaultValue->Buffer != NULL);
5499 if (DefaultValue->Buffer == NULL) {
5500 return EFI_OUT_OF_RESOURCES;
5501 }
5502
5503 TypeValue = (EFI_IFR_TYPE_VALUE *)DefaultValue->Buffer;
5504 }
5505
5506 //
5507 // Get Question default value from call back function.
5508 // The string type of question cause HII driver to set string to its default value.
5509 // So, we don't do this otherwise it will actually set question to default value.
5510 // We only want to get default value of question.
5511 //
5512 if (HiiValue->Type != EFI_IFR_TYPE_STRING) {
5513 ConfigAccess = FormSet->ConfigAccess;
5514 Action = GetDefaultIdForCallBack (DefaultId);
5515 if ((Action > 0) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) != 0) && (ConfigAccess != NULL)) {
5516 ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE;
5517 Status = ConfigAccess->Callback (
5518 ConfigAccess,
5519 Action,
5520 Question->QuestionId,
5521 HiiValue->Type,
5522 TypeValue,
5523 &ActionRequest
5524 );
5525 if (!EFI_ERROR (Status)) {
5526 return Status;
5527 }
5528 }
5529 }
5530
5531 //
5532 // Get default value from altcfg string.
5533 //
5534 if (ConfigAccess != NULL) {
5535 Status = GetDefaultValueFromAltCfg (FormSet, Form, Question, DefaultValue);
5536 if (!EFI_ERROR (Status)) {
5537 return Status;
5538 }
5539 }
5540
5541 //
5542 // EFI_IFR_DEFAULT has highest priority
5543 //
5544 if (!IsListEmpty (&Question->DefaultListHead)) {
5545 Link = GetFirstNode (&Question->DefaultListHead);
5546 while (!IsNull (&Question->DefaultListHead, Link)) {
5547 Default = HII_QUESTION_DEFAULT_FROM_LINK (Link);
5548
5549 if (Default->DefaultId == DefaultId) {
5550 if (Default->ValueExpression != NULL) {
5551 //
5552 // Default is provided by an Expression, evaluate it
5553 //
5554 Status = EvaluateHiiExpression (FormSet, Form, Default->ValueExpression);
5555 if (EFI_ERROR (Status)) {
5556 return Status;
5557 }
5558
5559 if (Default->ValueExpression->Result.Type == EFI_IFR_TYPE_BUFFER) {
5560 ASSERT (HiiValue->Type == EFI_IFR_TYPE_BUFFER && DefaultValue->Buffer != NULL);
5561 if (DefaultValue->BufferLen > Default->ValueExpression->Result.BufferLen) {
5562 CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, Default->ValueExpression->Result.BufferLen);
5563 DefaultValue->BufferLen = Default->ValueExpression->Result.BufferLen;
5564 } else {
5565 CopyMem (DefaultValue->Buffer, Default->ValueExpression->Result.Buffer, DefaultValue->BufferLen);
5566 }
5567
5568 FreePool (Default->ValueExpression->Result.Buffer);
5569 }
5570
5571 HiiValue->Type = Default->ValueExpression->Result.Type;
5572 CopyMem (&HiiValue->Value, &Default->ValueExpression->Result.Value, sizeof (EFI_IFR_TYPE_VALUE));
5573 } else {
5574 //
5575 // Default value is embedded in EFI_IFR_DEFAULT
5576 //
5577 if (Default->Value.Type == EFI_IFR_TYPE_BUFFER) {
5578 ASSERT (HiiValue->Buffer != NULL);
5579 CopyMem (HiiValue->Buffer, Default->Value.Buffer, Default->Value.BufferLen);
5580 } else {
5581 CopyMem (HiiValue, &Default->Value, sizeof (EFI_HII_VALUE));
5582 }
5583 }
5584
5585 if (HiiValue->Type == EFI_IFR_TYPE_STRING) {
5586 StrValue = HiiGetString (FormSet->HiiHandle, HiiValue->Value.string, NULL);
5587 if (StrValue == NULL) {
5588 return EFI_NOT_FOUND;
5589 }
5590
5591 if (DefaultValue->BufferLen > StrSize (StrValue)) {
5592 ZeroMem (DefaultValue->Buffer, DefaultValue->BufferLen);
5593 CopyMem (DefaultValue->Buffer, StrValue, StrSize (StrValue));
5594 } else {
5595 CopyMem (DefaultValue->Buffer, StrValue, DefaultValue->BufferLen);
5596 }
5597 }
5598
5599 return EFI_SUCCESS;
5600 }
5601
5602 Link = GetNextNode (&Question->DefaultListHead, Link);
5603 }
5604 }
5605
5606 //
5607 // EFI_ONE_OF_OPTION
5608 //
5609 if ((Question->Operand == EFI_IFR_ONE_OF_OP) && !IsListEmpty (&Question->OptionListHead)) {
5610 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
5611 //
5612 // OneOfOption could only provide Standard and Manufacturing default
5613 //
5614 Link = GetFirstNode (&Question->OptionListHead);
5615 while (!IsNull (&Question->OptionListHead, Link)) {
5616 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
5617 Link = GetNextNode (&Question->OptionListHead, Link);
5618
5619 if ((Option->SuppressExpression != NULL) &&
5620 (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
5621 {
5622 continue;
5623 }
5624
5625 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT) != 0)) ||
5626 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Option->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0))
5627 )
5628 {
5629 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
5630
5631 return EFI_SUCCESS;
5632 }
5633 }
5634 }
5635 }
5636
5637 //
5638 // EFI_IFR_CHECKBOX - lowest priority
5639 //
5640 if (Question->Operand == EFI_IFR_CHECKBOX_OP) {
5641 if (DefaultId <= EFI_HII_DEFAULT_CLASS_MANUFACTURING) {
5642 //
5643 // Checkbox could only provide Standard and Manufacturing default
5644 //
5645 if (((DefaultId == EFI_HII_DEFAULT_CLASS_STANDARD) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0)) ||
5646 ((DefaultId == EFI_HII_DEFAULT_CLASS_MANUFACTURING) && ((Question->ExtraData.Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0))
5647 )
5648 {
5649 HiiValue->Value.b = TRUE;
5650 }
5651
5652 return EFI_SUCCESS;
5653 }
5654 }
5655
5656 //
5657 // For question without default value for current default Id, we try to re-get the default value form other default id in the DefaultStoreList.
5658 // If get, will exit the function, if not, will choose next default id in the DefaultStoreList.
5659 // The default id in DefaultStoreList are in ascending order to make sure choose the smallest default id every time.
5660 //
5661 while (!IsNull (&FormSet->DefaultStoreListHead, DefaultLink)) {
5662 DefaultStore = HII_FORMSET_DEFAULTSTORE_FROM_LINK (DefaultLink);
5663 DefaultLink = GetNextNode (&FormSet->DefaultStoreListHead, DefaultLink);
5664 DefaultId = DefaultStore->DefaultId;
5665 if (DefaultId == OriginalDefaultId) {
5666 continue;
5667 }
5668
5669 goto ReGetDefault;
5670 }
5671
5672 //
5673 // For Questions without default value for all the default id in the DefaultStoreList.
5674 //
5675 Status = EFI_NOT_FOUND;
5676 switch (Question->Operand) {
5677 case EFI_IFR_CHECKBOX_OP:
5678 HiiValue->Value.b = FALSE;
5679 Status = EFI_SUCCESS;
5680 break;
5681
5682 case EFI_IFR_NUMERIC_OP:
5683 //
5684 // Take minimum value as numeric default value
5685 //
5686 if ((Question->ExtraData.NumData.Flags & EFI_IFR_DISPLAY) == 0) {
5687 //
5688 // In EFI_IFR_DISPLAY_INT_DEC type, should check value with int* type.
5689 //
5690 switch (Question->ExtraData.NumData.Flags & EFI_IFR_NUMERIC_SIZE) {
5691 case EFI_IFR_NUMERIC_SIZE_1:
5692 if (((INT8)HiiValue->Value.u8 < (INT8)Question->ExtraData.NumData.Minimum) || ((INT8)HiiValue->Value.u8 > (INT8)Question->ExtraData.NumData.Maximum)) {
5693 HiiValue->Value.u8 = (UINT8)Question->ExtraData.NumData.Minimum;
5694 Status = EFI_SUCCESS;
5695 }
5696
5697 break;
5698 case EFI_IFR_NUMERIC_SIZE_2:
5699 if (((INT16)HiiValue->Value.u16 < (INT16)Question->ExtraData.NumData.Minimum) || ((INT16)HiiValue->Value.u16 > (INT16)Question->ExtraData.NumData.Maximum)) {
5700 HiiValue->Value.u16 = (UINT16)Question->ExtraData.NumData.Minimum;
5701 Status = EFI_SUCCESS;
5702 }
5703
5704 break;
5705 case EFI_IFR_NUMERIC_SIZE_4:
5706 if (((INT32)HiiValue->Value.u32 < (INT32)Question->ExtraData.NumData.Minimum) || ((INT32)HiiValue->Value.u32 > (INT32)Question->ExtraData.NumData.Maximum)) {
5707 HiiValue->Value.u32 = (UINT32)Question->ExtraData.NumData.Minimum;
5708 Status = EFI_SUCCESS;
5709 }
5710
5711 break;
5712 case EFI_IFR_NUMERIC_SIZE_8:
5713 if (((INT64)HiiValue->Value.u64 < (INT64)Question->ExtraData.NumData.Minimum) || ((INT64)HiiValue->Value.u64 > (INT64)Question->ExtraData.NumData.Maximum)) {
5714 HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;
5715 Status = EFI_SUCCESS;
5716 }
5717
5718 break;
5719 default:
5720 break;
5721 }
5722 } else {
5723 if ((HiiValue->Value.u64 < Question->ExtraData.NumData.Minimum) || (HiiValue->Value.u64 > Question->ExtraData.NumData.Maximum)) {
5724 HiiValue->Value.u64 = Question->ExtraData.NumData.Minimum;
5725 Status = EFI_SUCCESS;
5726 }
5727 }
5728
5729 break;
5730
5731 case EFI_IFR_ONE_OF_OP:
5732 //
5733 // Take first oneof option as oneof's default value
5734 //
5735 Link = GetFirstNode (&Question->OptionListHead);
5736 while (!IsNull (&Question->OptionListHead, Link)) {
5737 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
5738 Link = GetNextNode (&Question->OptionListHead, Link);
5739
5740 if ((Option->SuppressExpression != NULL) &&
5741 (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
5742 {
5743 continue;
5744 }
5745
5746 CopyMem (HiiValue, &Option->Value, sizeof (EFI_HII_VALUE));
5747 Status = EFI_SUCCESS;
5748 break;
5749 }
5750
5751 break;
5752
5753 case EFI_IFR_ORDERED_LIST_OP:
5754 //
5755 // Take option sequence in IFR as ordered list's default value
5756 //
5757 Index = 0;
5758 Link = GetFirstNode (&Question->OptionListHead);
5759 while (!IsNull (&Question->OptionListHead, Link)) {
5760 Status = EFI_SUCCESS;
5761 Option = HII_QUESTION_OPTION_FROM_LINK (Link);
5762 Link = GetNextNode (&Question->OptionListHead, Link);
5763
5764 if ((Option->SuppressExpression != NULL) &&
5765 (EvaluateExpressionList (Option->SuppressExpression, FALSE, NULL, NULL) != ExpressFalse))
5766 {
5767 continue;
5768 }
5769
5770 SetArrayData (DefaultValue->Buffer, Question->Value.Type, Index, Option->Value.Value.u64);
5771
5772 Index++;
5773 if (Index >= Question->ExtraData.OrderListData.MaxContainers) {
5774 break;
5775 }
5776 }
5777
5778 break;
5779
5780 default:
5781 break;
5782 }
5783
5784 return Status;
5785}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette