2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 Common Library Routines to assist in IFR creation on-the-fly
25 IN EFI_HANDLE ImageHandle
,
26 IN EFI_SYSTEM_TABLE
*SystemTable
40 Determine what is the current language setting
44 Lang - Pointer of system language
58 // Getting the system language and placing it into our Global Data
60 Size
= sizeof (Language
);
62 Status
= gRT
->GetVariable (
64 &gEfiGlobalVariableGuid
,
70 if (EFI_ERROR (Status
)) {
71 AsciiStrCpy (Language
, "eng");
74 for (Index
= 0; Language
[Index
] != 0; Index
++) {
76 // Bitwise AND ascii value with 0xDF yields an uppercase value.
77 // Sign extend into a unicode value
79 Lang
[Index
] = (CHAR16
) (Language
[Index
] & 0xDF);
83 // Null-terminate the value
93 IN VOID
*StringBuffer
,
96 IN OUT STRING_REF
*StringToken
102 Add a string to the incoming buffer and return the token and offset data
106 StringBuffer - The incoming buffer
108 Language - Currrent language
110 String - The string to be added
112 StringToken - The index where the string placed
116 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
118 EFI_SUCCESS - String successfully added to the incoming buffer
122 EFI_HII_STRING_PACK
*StringPack
;
123 EFI_HII_STRING_PACK
*StringPackBuffer
;
126 RELOFST
*PackDestination
;
132 StringPack
= (EFI_HII_STRING_PACK
*) StringBuffer
;
136 // Pre-allocate a buffer sufficient for us to work on.
137 // We will use it as a destination scratch pad to build data on
138 // and when complete shift the data back to the original buffer
140 NewBuffer
= AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE
);
141 if (NewBuffer
== NULL
) {
142 return EFI_OUT_OF_RESOURCES
;
145 StringPackBuffer
= (EFI_HII_STRING_PACK
*) NewBuffer
;
148 // StringPack is terminated with a length 0 entry
150 for (; StringPack
->Header
.Length
!= 0;) {
152 // If this stringpack's language is same as CurrentLanguage, use it
154 if (CompareMem ((VOID
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
, 3) == 0) {
156 // We have some data in this string pack, copy the string package up to the string data
158 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, sizeof (StringPack
));
161 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
163 StringPackBuffer
->LanguageNameString
= (UINT16
) (StringPackBuffer
->LanguageNameString
+ (UINT16
) sizeof (RELOFST
));
164 StringPackBuffer
->PrintableLanguageName
= (UINT16
) (StringPackBuffer
->PrintableLanguageName
+ (UINT16
) sizeof (RELOFST
));
166 PackSource
= (RELOFST
*) (StringPack
+ 1);
167 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
168 for (Index
= 0; PackSource
[Index
] != 0x0000; Index
++) {
170 // Copy the stringpointers from old to new buffer
171 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
173 PackDestination
[Index
] = (UINT16
) (PackDestination
[Index
] + sizeof (RELOFST
));
177 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
179 PackDestination
[Index
] = (UINT16
)(PackDestination
[Index
-1] +
180 StrSize((CHAR16
*)((CHAR8
*)(StringPack
) + PackSource
[Index
-1])));
181 PackDestination
[Index
+ 1] = (UINT16
) 0;
184 // Index is the token value for the new string
186 *StringToken
= (UINT16
) Index
;
189 // Source now points to the beginning of the old buffer strings
190 // Destination now points to the beginning of the new buffer strings
192 Source
= (UINT8
*) &PackSource
[Index
+ 1];
193 Destination
= (UINT8
*) &PackDestination
[Index
+ 2];
196 // This should copy all the strings from the old buffer to the new buffer
198 for (; Index
!= 0; Index
--) {
200 // Copy Source string to destination buffer
202 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) Source
);
205 // Adjust the source/destination to the next string location
207 Destination
= Destination
+ StrSize ((CHAR16
*) Source
);
208 Source
= Source
+ StrSize ((CHAR16
*) Source
);
212 // This copies the new string to the destination buffer
214 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) String
);
217 // Adjust the size of the changed string pack by adding the size of the new string
218 // along with the size of the additional offset entry for the new string
220 StringPackBuffer
->Header
.Length
= (UINT32
) ((UINTN
) StringPackBuffer
->Header
.Length
+ StrSize (String
) + sizeof (RELOFST
));
223 // Advance the buffers to point to the next spots.
225 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPackBuffer
->Header
.Length
);
226 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
231 // This isn't the language of the stringpack we were asked to add a string to
232 // so we need to copy it to the new buffer.
234 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, StringPack
->Header
.Length
);
237 // Advance the buffers to point to the next spots.
239 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPack
->Header
.Length
);
240 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
244 // If we didn't copy the new data to a stringpack yet
247 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
249 // Pointing to a new string pack location
251 StringPackBuffer
->Header
.Length
= (UINT32
)
253 sizeof (EFI_HII_STRING_PACK
) -
254 sizeof (EFI_STRING
) +
260 StringPackBuffer
->Header
.Type
= EFI_HII_STRING
;
261 StringPackBuffer
->LanguageNameString
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
262 StringPackBuffer
->PrintableLanguageName
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
263 StringPackBuffer
->Attributes
= 0;
264 PackDestination
[0] = (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
265 PackDestination
[1] = (UINT16
) (PackDestination
[0] + StrSize (Language
));
266 PackDestination
[2] = (UINT16
) 0;
269 // The first string location will be set to destination. The minimum number of strings
270 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
271 // and token 1 as the new string being added and and null entry for the stringpointers
273 Destination
= (UINT8
*) &PackDestination
[3];
276 // Copy the language name string to the new buffer
278 StrCpy ((CHAR16
*) Destination
, Language
);
281 // Advance the destination to the new empty spot
283 Destination
= Destination
+ StrSize (Language
);
286 // Copy the string to the new buffer
288 StrCpy ((CHAR16
*) Destination
, String
);
291 // Since we are starting with a new string pack - we know the new string is token 1
293 *StringToken
= (UINT16
) 1;
297 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
299 ZeroMem (StringBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
300 CopyMem (StringBuffer
, NewBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
303 // Free the newly created buffer since we don't need it anymore
305 gBS
->FreePool (NewBuffer
);
313 IN OUT VOID
*OpCodeData
319 Add op-code data to the FormBuffer
323 FormBuffer - Form buffer to be inserted to
325 OpCodeData - Op-code data to be inserted
329 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
331 EFI_SUCCESS - Op-code data successfully inserted
335 EFI_HII_PACK_HEADER
*NewBuffer
;
340 // Pre-allocate a buffer sufficient for us to work on.
341 // We will use it as a destination scratch pad to build data on
342 // and when complete shift the data back to the original buffer
344 NewBuffer
= AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE
);
345 if (NewBuffer
== NULL
) {
346 return EFI_OUT_OF_RESOURCES
;
349 Source
= (UINT8
*) FormBuffer
;
350 Destination
= (UINT8
*) NewBuffer
;
353 // Copy the IFR Package header to the new buffer
355 CopyMem (Destination
, Source
, sizeof (EFI_HII_PACK_HEADER
));
358 // Advance Source and Destination to next op-code
360 Source
= Source
+ sizeof (EFI_HII_PACK_HEADER
);
361 Destination
= Destination
+ sizeof (EFI_HII_PACK_HEADER
);
364 // Copy data to the new buffer until we run into the end_form
366 for (; ((EFI_IFR_OP_HEADER
*) Source
)->OpCode
!= EFI_IFR_END_FORM_OP
;) {
368 // If the this opcode is an end_form_set we better be creating and endform
369 // Nonetheless, we will add data before the end_form_set. This also provides
370 // for interesting behavior in the code we will run, but has no bad side-effects
371 // since we will possibly do a 0 byte copy in this particular end-case.
373 if (((EFI_IFR_OP_HEADER
*) Source
)->OpCode
== EFI_IFR_END_FORM_SET_OP
) {
378 // Copy data to new buffer
380 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
383 // Adjust Source/Destination to next op-code location
385 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
386 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
390 // Prior to the end_form is where we insert the new op-code data
392 CopyMem (Destination
, OpCodeData
, ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
393 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
395 NewBuffer
->Length
= (UINT32
) (NewBuffer
->Length
+ (UINT32
) (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
));
398 // Copy end-form data to new buffer
400 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
403 // Adjust Source/Destination to next op-code location
405 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
406 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
409 // Copy end-formset data to new buffer
411 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
414 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
416 ZeroMem (FormBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
417 CopyMem (FormBuffer
, NewBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
420 // Free the newly created buffer since we don't need it anymore
422 gBS
->FreePool (NewBuffer
);
429 OUT EFI_HII_PROTOCOL
**Hii
435 Get the HII protocol interface
439 Hii - HII protocol interface
450 // There should only be one HII protocol
452 Status
= gBS
->LocateProtocol (
453 &gEfiHiiProtocolGuid
,
463 ExtractDataFromHiiHandle (
464 IN EFI_HII_HANDLE HiiHandle
,
465 IN OUT UINT16
*ImageLength
,
466 OUT UINT8
*DefaultImage
,
473 Extract information pertaining to the HiiHandle
477 HiiHandle - Hii handle
479 ImageLength - For input, length of DefaultImage;
480 For output, length of actually required
482 DefaultImage - Image buffer prepared by caller
484 Guid - Guid information about the form
488 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
490 EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
492 EFI_SUCCESS - Successfully extract data from Hii database.
498 EFI_HII_PROTOCOL
*Hii
;
507 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
511 Status
= GetHiiInterface (&Hii
);
513 if (EFI_ERROR (Status
)) {
518 // Allocate space for retrieval of IFR data
520 RawData
= AllocateZeroPool (DataLength
);
521 if (RawData
== NULL
) {
522 return EFI_OUT_OF_RESOURCES
;
526 // Get all the forms associated with this HiiHandle
528 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
530 if (EFI_ERROR (Status
)) {
531 gBS
->FreePool (RawData
);
534 // Allocate space for retrieval of IFR data
536 RawData
= AllocateZeroPool (DataLength
);
537 if (RawData
== NULL
) {
538 return EFI_OUT_OF_RESOURCES
;
542 // Get all the forms associated with this HiiHandle
544 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
550 // Point RawData to the beginning of the form data
552 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
554 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
555 switch (RawData
[Index
]) {
556 case EFI_IFR_FORM_SET_OP
:
558 // Copy the GUID information from this handle
560 CopyMem (Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
563 case EFI_IFR_ONE_OF_OP
:
564 case EFI_IFR_CHECKBOX_OP
:
565 case EFI_IFR_NUMERIC_OP
:
566 case EFI_IFR_DATE_OP
:
567 case EFI_IFR_TIME_OP
:
568 case EFI_IFR_PASSWORD_OP
:
569 case EFI_IFR_STRING_OP
:
571 // Remember, multiple op-codes may reference the same item, so let's keep a running
572 // marker of what the highest QuestionId that wasn't zero length. This will accurately
573 // maintain the Size of the NvStore
575 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
576 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
577 if (SizeOfNvStore
< Temp
) {
578 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
583 Index
= RawData
[Index
+ 1] + Index
;
587 // Return an error if buffer is too small
589 if (SizeOfNvStore
> *ImageLength
) {
590 gBS
->FreePool (OldData
);
591 *ImageLength
= (UINT16
) SizeOfNvStore
;
592 return EFI_BUFFER_TOO_SMALL
;
595 if (DefaultImage
!= NULL
) {
596 ZeroMem (DefaultImage
, SizeOfNvStore
);
600 // Copy the default image information to the user's buffer
602 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
603 switch (RawData
[Index
]) {
604 case EFI_IFR_ONE_OF_OP
:
605 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
608 case EFI_IFR_ONE_OF_OPTION_OP
:
609 if (((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& EFI_IFR_FLAG_DEFAULT
) {
610 CopyMem (&DefaultImage
[CachedStart
], &((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
614 case EFI_IFR_CHECKBOX_OP
:
615 DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((EFI_IFR_CHECKBOX
*) &RawData
[Index
])->Flags
;
618 case EFI_IFR_NUMERIC_OP
:
620 &DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
621 &((EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
628 Index
= RawData
[Index
+ 1] + Index
;
631 *ImageLength
= (UINT16
) SizeOfNvStore
;
634 // Free our temporary repository of form data
636 gBS
->FreePool (OldData
);
644 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
650 Finds HII handle for given pack GUID previously registered with the HII.
653 HiiProtocol - pointer to pointer to HII protocol interface.
654 If NULL, the interface will be found but not returned.
655 If it points to NULL, the interface will be found and
656 written back to the pointer that is pointed to.
657 Guid - The GUID of the pack that registered with the HII.
660 Handle to the HII pack previously registered by the memory driver.
666 EFI_HII_HANDLE
*HiiHandleBuffer
;
667 EFI_HII_HANDLE HiiHandle
;
668 UINT16 HiiHandleBufferLength
;
669 UINT32 NumberOfHiiHandles
;
671 EFI_HII_PROTOCOL
*HiiProt
;
676 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
678 // The protocol has been passed in
680 HiiProt
= *HiiProtocol
;
682 gBS
->LocateProtocol (
683 &gEfiHiiProtocolGuid
,
687 if (HiiProt
== NULL
) {
691 if (HiiProtocol
!= NULL
) {
693 // Return back the HII protocol for the caller as promissed
695 *HiiProtocol
= HiiProt
;
701 HiiHandleBufferLength
= 10;
702 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
703 ASSERT (HiiHandleBuffer
!= NULL
);
706 // Get the Handles of the packages that were registered with Hii
708 Status
= HiiProt
->FindHandles (
710 &HiiHandleBufferLength
,
715 // Get a bigger bugffer if this one is to small, and try again
717 if (Status
== EFI_BUFFER_TOO_SMALL
) {
719 gBS
->FreePool (HiiHandleBuffer
);
721 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
722 ASSERT (HiiHandleBuffer
!= NULL
);
724 Status
= HiiProt
->FindHandles (
726 &HiiHandleBufferLength
,
731 if (EFI_ERROR (Status
)) {
735 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
738 // Iterate Hii handles and look for the one that matches our Guid
740 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
743 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
745 if (CompareGuid (&HiiGuid
, Guid
)) {
747 HiiHandle
= HiiHandleBuffer
[Index
];
753 gBS
->FreePool (HiiHandleBuffer
);
759 ValidateDataFromHiiHandle (
760 IN EFI_HII_HANDLE HiiHandle
,
767 Validate that the data associated with the HiiHandle in NVRAM is within
768 the reasonable parameters for that FormSet. Values for strings and passwords
769 are not verified due to their not having the equivalent of valid range settings.
773 HiiHandle - Handle of the HII database entry to query
775 Results - If return Status is EFI_SUCCESS, Results provides valid data
776 TRUE = NVRAM Data is within parameters
777 FALSE = NVRAM Data is NOT within parameters
781 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
783 EFI_SUCCESS - Data successfully validated
787 EFI_HII_PROTOCOL
*Hii
;
799 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
805 Status
= GetHiiInterface (&Hii
);
807 if (EFI_ERROR (Status
)) {
812 // Allocate space for retrieval of IFR data
814 RawData
= AllocateZeroPool (RawDataLength
);
815 if (RawData
== NULL
) {
816 return EFI_OUT_OF_RESOURCES
;
820 // Get all the forms associated with this HiiHandle
822 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
824 if (EFI_ERROR (Status
)) {
825 gBS
->FreePool (RawData
);
828 // Allocate space for retrieval of IFR data
830 RawData
= AllocateZeroPool (RawDataLength
);
831 if (RawData
== NULL
) {
832 return EFI_OUT_OF_RESOURCES
;
836 // Get all the forms associated with this HiiHandle
838 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
844 // Point RawData to the beginning of the form data
846 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
848 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
849 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
850 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
854 Index
= RawData
[Index
+ 1] + Index
;
857 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
858 switch (RawData
[Index
]) {
859 case EFI_IFR_FORM_SET_OP
:
862 case EFI_IFR_ONE_OF_OP
:
863 case EFI_IFR_CHECKBOX_OP
:
864 case EFI_IFR_NUMERIC_OP
:
865 case EFI_IFR_DATE_OP
:
866 case EFI_IFR_TIME_OP
:
867 case EFI_IFR_PASSWORD_OP
:
868 case EFI_IFR_STRING_OP
:
870 // Remember, multiple op-codes may reference the same item, so let's keep a running
871 // marker of what the highest QuestionId that wasn't zero length. This will accurately
872 // maintain the Size of the NvStore
874 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
875 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
876 if (SizeOfNvStore
< Temp
) {
877 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
882 Index
= RawData
[Index
+ 1] + Index
;
886 // Allocate memory for our File Form Tags
888 VariableData
= AllocateZeroPool (SizeOfNvStore
);
889 if (VariableData
== NULL
) {
890 return EFI_OUT_OF_RESOURCES
;
893 Status
= gRT
->GetVariable (
898 (VOID
*) VariableData
901 if (EFI_ERROR (Status
)) {
904 // If there is a variable that exists already and it is larger than what we calculated the
905 // storage needs to be, we must assume the variable size from GetVariable is correct and not
906 // allow the truncation of the variable. It is very possible that the user who created the IFR
907 // we are cracking is not referring to a variable that was in a previous map, however we cannot
908 // allow it's truncation.
910 if (Status
== EFI_BUFFER_TOO_SMALL
) {
912 // Free the buffer that was allocated that was too small
914 gBS
->FreePool (VariableData
);
916 VariableData
= AllocatePool (SizeOfNvStore
);
917 if (VariableData
== NULL
) {
918 return EFI_OUT_OF_RESOURCES
;
921 Status
= gRT
->GetVariable (
926 (VOID
*) VariableData
932 // Walk through the form and see that the variable data it refers to is ok.
933 // This allows for the possibility of stale (obsoleted) data in the variable
934 // can be overlooked without causing an error
936 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
937 switch (RawData
[Index
]) {
938 case EFI_IFR_ONE_OF_OP
:
940 // A one_of has no data, its the option that does - cache the storage Id
942 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
945 case EFI_IFR_ONE_OF_OPTION_OP
:
947 // A one_of_option can be any value
949 if (VariableData
[CachedStart
] == ((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
954 case EFI_IFR_END_ONE_OF_OP
:
956 // At this point lets make sure that the data value in the NVRAM matches one of the options
964 case EFI_IFR_CHECKBOX_OP
:
966 // A checkbox is a boolean, so 0 and 1 are valid
967 // Remember, QuestionId corresponds to the offset location of the data in the variable
969 if (VariableData
[((EFI_IFR_CHECKBOX
*) &RawData
[Index
])->QuestionId
] > 1) {
975 case EFI_IFR_NUMERIC_OP
:
976 if ((VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
977 (VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
985 Index
= RawData
[Index
+ 1] + Index
;
989 // Free our temporary repository of form data
991 gBS
->FreePool (OldData
);
992 gBS
->FreePool (VariableData
);