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
24 IN EFI_HANDLE ImageHandle
,
25 IN EFI_SYSTEM_TABLE
*SystemTable
39 Determine what is the current language setting
43 Lang - Pointer of system language
57 // Getting the system language and placing it into our Global Data
59 Size
= sizeof (Language
);
61 Status
= gRT
->GetVariable (
63 &gEfiGlobalVariableGuid
,
69 if (EFI_ERROR (Status
)) {
70 AsciiStrCpy (Language
, "eng");
73 for (Index
= 0; Language
[Index
] != 0; Index
++) {
75 // Bitwise AND ascii value with 0xDF yields an uppercase value.
76 // Sign extend into a unicode value
78 Lang
[Index
] = (CHAR16
) (Language
[Index
] & 0xDF);
82 // Null-terminate the value
92 IN VOID
*StringBuffer
,
95 IN OUT STRING_REF
*StringToken
101 Add a string to the incoming buffer and return the token and offset data
105 StringBuffer - The incoming buffer
107 Language - Currrent language
109 String - The string to be added
111 StringToken - The index where the string placed
115 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
117 EFI_SUCCESS - String successfully added to the incoming buffer
121 EFI_HII_STRING_PACK
*StringPack
;
122 EFI_HII_STRING_PACK
*StringPackBuffer
;
125 RELOFST
*PackDestination
;
131 StringPack
= (EFI_HII_STRING_PACK
*) StringBuffer
;
135 // Pre-allocate a buffer sufficient for us to work on.
136 // We will use it as a destination scratch pad to build data on
137 // and when complete shift the data back to the original buffer
139 NewBuffer
= AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE
);
140 if (NewBuffer
== NULL
) {
141 return EFI_OUT_OF_RESOURCES
;
144 StringPackBuffer
= (EFI_HII_STRING_PACK
*) NewBuffer
;
147 // StringPack is terminated with a length 0 entry
149 for (; StringPack
->Header
.Length
!= 0;) {
151 // If this stringpack's language is same as CurrentLanguage, use it
153 if (CompareMem ((VOID
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
, 3) == 0) {
155 // We have some data in this string pack, copy the string package up to the string data
157 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, sizeof (StringPack
));
160 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
162 StringPackBuffer
->LanguageNameString
= (UINT16
) (StringPackBuffer
->LanguageNameString
+ (UINT16
) sizeof (RELOFST
));
163 StringPackBuffer
->PrintableLanguageName
= (UINT16
) (StringPackBuffer
->PrintableLanguageName
+ (UINT16
) sizeof (RELOFST
));
165 PackSource
= (RELOFST
*) (StringPack
+ 1);
166 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
167 for (Index
= 0; PackSource
[Index
] != 0x0000; Index
++) {
169 // Copy the stringpointers from old to new buffer
170 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
172 PackDestination
[Index
] = (UINT16
) (PackDestination
[Index
] + sizeof (RELOFST
));
176 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
178 PackDestination
[Index
] = (UINT16
)(PackDestination
[Index
-1] +
179 StrSize((CHAR16
*)((CHAR8
*)(StringPack
) + PackSource
[Index
-1])));
180 PackDestination
[Index
+ 1] = (UINT16
) 0;
183 // Index is the token value for the new string
185 *StringToken
= (UINT16
) Index
;
188 // Source now points to the beginning of the old buffer strings
189 // Destination now points to the beginning of the new buffer strings
191 Source
= (UINT8
*) &PackSource
[Index
+ 1];
192 Destination
= (UINT8
*) &PackDestination
[Index
+ 2];
195 // This should copy all the strings from the old buffer to the new buffer
197 for (; Index
!= 0; Index
--) {
199 // Copy Source string to destination buffer
201 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) Source
);
204 // Adjust the source/destination to the next string location
206 Destination
= Destination
+ StrSize ((CHAR16
*) Source
);
207 Source
= Source
+ StrSize ((CHAR16
*) Source
);
211 // This copies the new string to the destination buffer
213 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) String
);
216 // Adjust the size of the changed string pack by adding the size of the new string
217 // along with the size of the additional offset entry for the new string
219 StringPackBuffer
->Header
.Length
= (UINT32
) ((UINTN
) StringPackBuffer
->Header
.Length
+ StrSize (String
) + sizeof (RELOFST
));
222 // Advance the buffers to point to the next spots.
224 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPackBuffer
->Header
.Length
);
225 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
230 // This isn't the language of the stringpack we were asked to add a string to
231 // so we need to copy it to the new buffer.
233 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, StringPack
->Header
.Length
);
236 // Advance the buffers to point to the next spots.
238 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPack
->Header
.Length
);
239 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
243 // If we didn't copy the new data to a stringpack yet
246 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
248 // Pointing to a new string pack location
250 StringPackBuffer
->Header
.Length
= (UINT32
)
252 sizeof (EFI_HII_STRING_PACK
) -
253 sizeof (EFI_STRING
) +
259 StringPackBuffer
->Header
.Type
= EFI_HII_STRING
;
260 StringPackBuffer
->LanguageNameString
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
261 StringPackBuffer
->PrintableLanguageName
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
262 StringPackBuffer
->Attributes
= 0;
263 PackDestination
[0] = (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
264 PackDestination
[1] = (UINT16
) (PackDestination
[0] + StrSize (Language
));
265 PackDestination
[2] = (UINT16
) 0;
268 // The first string location will be set to destination. The minimum number of strings
269 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
270 // and token 1 as the new string being added and and null entry for the stringpointers
272 Destination
= (UINT8
*) &PackDestination
[3];
275 // Copy the language name string to the new buffer
277 StrCpy ((CHAR16
*) Destination
, Language
);
280 // Advance the destination to the new empty spot
282 Destination
= Destination
+ StrSize (Language
);
285 // Copy the string to the new buffer
287 StrCpy ((CHAR16
*) Destination
, String
);
290 // Since we are starting with a new string pack - we know the new string is token 1
292 *StringToken
= (UINT16
) 1;
296 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
298 ZeroMem (StringBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
299 CopyMem (StringBuffer
, NewBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
302 // Free the newly created buffer since we don't need it anymore
304 gBS
->FreePool (NewBuffer
);
312 IN OUT VOID
*OpCodeData
318 Add op-code data to the FormBuffer
322 FormBuffer - Form buffer to be inserted to
324 OpCodeData - Op-code data to be inserted
328 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
330 EFI_SUCCESS - Op-code data successfully inserted
334 EFI_HII_PACK_HEADER
*NewBuffer
;
339 // Pre-allocate a buffer sufficient for us to work on.
340 // We will use it as a destination scratch pad to build data on
341 // and when complete shift the data back to the original buffer
343 NewBuffer
= AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE
);
344 if (NewBuffer
== NULL
) {
345 return EFI_OUT_OF_RESOURCES
;
348 Source
= (UINT8
*) FormBuffer
;
349 Destination
= (UINT8
*) NewBuffer
;
352 // Copy the IFR Package header to the new buffer
354 CopyMem (Destination
, Source
, sizeof (EFI_HII_PACK_HEADER
));
357 // Advance Source and Destination to next op-code
359 Source
= Source
+ sizeof (EFI_HII_PACK_HEADER
);
360 Destination
= Destination
+ sizeof (EFI_HII_PACK_HEADER
);
363 // Copy data to the new buffer until we run into the end_form
365 for (; ((EFI_IFR_OP_HEADER
*) Source
)->OpCode
!= EFI_IFR_END_FORM_OP
;) {
367 // If the this opcode is an end_form_set we better be creating and endform
368 // Nonetheless, we will add data before the end_form_set. This also provides
369 // for interesting behavior in the code we will run, but has no bad side-effects
370 // since we will possibly do a 0 byte copy in this particular end-case.
372 if (((EFI_IFR_OP_HEADER
*) Source
)->OpCode
== EFI_IFR_END_FORM_SET_OP
) {
377 // Copy data to new buffer
379 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
382 // Adjust Source/Destination to next op-code location
384 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
385 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
389 // Prior to the end_form is where we insert the new op-code data
391 CopyMem (Destination
, OpCodeData
, ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
392 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
394 NewBuffer
->Length
= (UINT32
) (NewBuffer
->Length
+ (UINT32
) (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
));
397 // Copy end-form data to new buffer
399 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
402 // Adjust Source/Destination to next op-code location
404 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
405 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
408 // Copy end-formset data to new buffer
410 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
413 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
415 ZeroMem (FormBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
416 CopyMem (FormBuffer
, NewBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
419 // Free the newly created buffer since we don't need it anymore
421 gBS
->FreePool (NewBuffer
);
428 OUT EFI_HII_PROTOCOL
**Hii
434 Get the HII protocol interface
438 Hii - HII protocol interface
449 // There should only be one HII protocol
451 Status
= gBS
->LocateProtocol (
452 &gEfiHiiProtocolGuid
,
462 ExtractDataFromHiiHandle (
463 IN EFI_HII_HANDLE HiiHandle
,
464 IN OUT UINT16
*ImageLength
,
465 OUT UINT8
*DefaultImage
,
472 Extract information pertaining to the HiiHandle
476 HiiHandle - Hii handle
478 ImageLength - For input, length of DefaultImage;
479 For output, length of actually required
481 DefaultImage - Image buffer prepared by caller
483 Guid - Guid information about the form
487 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
489 EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
491 EFI_SUCCESS - Successfully extract data from Hii database.
497 EFI_HII_PROTOCOL
*Hii
;
506 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
510 Status
= GetHiiInterface (&Hii
);
512 if (EFI_ERROR (Status
)) {
517 // Allocate space for retrieval of IFR data
519 RawData
= AllocateZeroPool (DataLength
);
520 if (RawData
== NULL
) {
521 return EFI_OUT_OF_RESOURCES
;
525 // Get all the forms associated with this HiiHandle
527 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
529 if (EFI_ERROR (Status
)) {
530 gBS
->FreePool (RawData
);
533 // Allocate space for retrieval of IFR data
535 RawData
= AllocateZeroPool (DataLength
);
536 if (RawData
== NULL
) {
537 return EFI_OUT_OF_RESOURCES
;
541 // Get all the forms associated with this HiiHandle
543 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
549 // Point RawData to the beginning of the form data
551 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
553 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
554 switch (RawData
[Index
]) {
555 case EFI_IFR_FORM_SET_OP
:
557 // Copy the GUID information from this handle
559 CopyMem (Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
562 case EFI_IFR_ONE_OF_OP
:
563 case EFI_IFR_CHECKBOX_OP
:
564 case EFI_IFR_NUMERIC_OP
:
565 case EFI_IFR_DATE_OP
:
566 case EFI_IFR_TIME_OP
:
567 case EFI_IFR_PASSWORD_OP
:
568 case EFI_IFR_STRING_OP
:
570 // Remember, multiple op-codes may reference the same item, so let's keep a running
571 // marker of what the highest QuestionId that wasn't zero length. This will accurately
572 // maintain the Size of the NvStore
574 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
575 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
576 if (SizeOfNvStore
< Temp
) {
577 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
582 Index
= RawData
[Index
+ 1] + Index
;
586 // Return an error if buffer is too small
588 if (SizeOfNvStore
> *ImageLength
) {
589 gBS
->FreePool (OldData
);
590 *ImageLength
= (UINT16
) SizeOfNvStore
;
591 return EFI_BUFFER_TOO_SMALL
;
594 if (DefaultImage
!= NULL
) {
595 ZeroMem (DefaultImage
, SizeOfNvStore
);
599 // Copy the default image information to the user's buffer
601 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
602 switch (RawData
[Index
]) {
603 case EFI_IFR_ONE_OF_OP
:
604 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
607 case EFI_IFR_ONE_OF_OPTION_OP
:
608 if (((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& EFI_IFR_FLAG_DEFAULT
) {
609 CopyMem (&DefaultImage
[CachedStart
], &((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
613 case EFI_IFR_CHECKBOX_OP
:
614 DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((EFI_IFR_CHECKBOX
*) &RawData
[Index
])->Flags
;
617 case EFI_IFR_NUMERIC_OP
:
619 &DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
620 &((EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
627 Index
= RawData
[Index
+ 1] + Index
;
630 *ImageLength
= (UINT16
) SizeOfNvStore
;
633 // Free our temporary repository of form data
635 gBS
->FreePool (OldData
);
643 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
649 Finds HII handle for given pack GUID previously registered with the HII.
652 HiiProtocol - pointer to pointer to HII protocol interface.
653 If NULL, the interface will be found but not returned.
654 If it points to NULL, the interface will be found and
655 written back to the pointer that is pointed to.
656 Guid - The GUID of the pack that registered with the HII.
659 Handle to the HII pack previously registered by the memory driver.
665 EFI_HII_HANDLE
*HiiHandleBuffer
;
666 EFI_HII_HANDLE HiiHandle
;
667 UINT16 HiiHandleBufferLength
;
668 UINT32 NumberOfHiiHandles
;
670 EFI_HII_PROTOCOL
*HiiProt
;
675 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
677 // The protocol has been passed in
679 HiiProt
= *HiiProtocol
;
681 gBS
->LocateProtocol (
682 &gEfiHiiProtocolGuid
,
686 if (HiiProt
== NULL
) {
690 if (HiiProtocol
!= NULL
) {
692 // Return back the HII protocol for the caller as promissed
694 *HiiProtocol
= HiiProt
;
700 HiiHandleBufferLength
= 10;
701 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
702 ASSERT (HiiHandleBuffer
!= NULL
);
705 // Get the Handles of the packages that were registered with Hii
707 Status
= HiiProt
->FindHandles (
709 &HiiHandleBufferLength
,
714 // Get a bigger bugffer if this one is to small, and try again
716 if (Status
== EFI_BUFFER_TOO_SMALL
) {
718 gBS
->FreePool (HiiHandleBuffer
);
720 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
721 ASSERT (HiiHandleBuffer
!= NULL
);
723 Status
= HiiProt
->FindHandles (
725 &HiiHandleBufferLength
,
730 if (EFI_ERROR (Status
)) {
734 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
737 // Iterate Hii handles and look for the one that matches our Guid
739 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
742 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
744 if (CompareGuid (&HiiGuid
, Guid
)) {
746 HiiHandle
= HiiHandleBuffer
[Index
];
752 gBS
->FreePool (HiiHandleBuffer
);
758 ValidateDataFromHiiHandle (
759 IN EFI_HII_HANDLE HiiHandle
,
766 Validate that the data associated with the HiiHandle in NVRAM is within
767 the reasonable parameters for that FormSet. Values for strings and passwords
768 are not verified due to their not having the equivalent of valid range settings.
772 HiiHandle - Handle of the HII database entry to query
774 Results - If return Status is EFI_SUCCESS, Results provides valid data
775 TRUE = NVRAM Data is within parameters
776 FALSE = NVRAM Data is NOT within parameters
780 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
782 EFI_SUCCESS - Data successfully validated
786 EFI_HII_PROTOCOL
*Hii
;
798 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
804 Status
= GetHiiInterface (&Hii
);
806 if (EFI_ERROR (Status
)) {
811 // Allocate space for retrieval of IFR data
813 RawData
= AllocateZeroPool (RawDataLength
);
814 if (RawData
== NULL
) {
815 return EFI_OUT_OF_RESOURCES
;
819 // Get all the forms associated with this HiiHandle
821 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
823 if (EFI_ERROR (Status
)) {
824 gBS
->FreePool (RawData
);
827 // Allocate space for retrieval of IFR data
829 RawData
= AllocateZeroPool (RawDataLength
);
830 if (RawData
== NULL
) {
831 return EFI_OUT_OF_RESOURCES
;
835 // Get all the forms associated with this HiiHandle
837 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
843 // Point RawData to the beginning of the form data
845 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
847 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
848 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
849 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
853 Index
= RawData
[Index
+ 1] + Index
;
856 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
857 switch (RawData
[Index
]) {
858 case EFI_IFR_FORM_SET_OP
:
861 case EFI_IFR_ONE_OF_OP
:
862 case EFI_IFR_CHECKBOX_OP
:
863 case EFI_IFR_NUMERIC_OP
:
864 case EFI_IFR_DATE_OP
:
865 case EFI_IFR_TIME_OP
:
866 case EFI_IFR_PASSWORD_OP
:
867 case EFI_IFR_STRING_OP
:
869 // Remember, multiple op-codes may reference the same item, so let's keep a running
870 // marker of what the highest QuestionId that wasn't zero length. This will accurately
871 // maintain the Size of the NvStore
873 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
874 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
875 if (SizeOfNvStore
< Temp
) {
876 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
881 Index
= RawData
[Index
+ 1] + Index
;
885 // Allocate memory for our File Form Tags
887 VariableData
= AllocateZeroPool (SizeOfNvStore
);
888 if (VariableData
== NULL
) {
889 return EFI_OUT_OF_RESOURCES
;
892 Status
= gRT
->GetVariable (
897 (VOID
*) VariableData
900 if (EFI_ERROR (Status
)) {
903 // If there is a variable that exists already and it is larger than what we calculated the
904 // storage needs to be, we must assume the variable size from GetVariable is correct and not
905 // allow the truncation of the variable. It is very possible that the user who created the IFR
906 // we are cracking is not referring to a variable that was in a previous map, however we cannot
907 // allow it's truncation.
909 if (Status
== EFI_BUFFER_TOO_SMALL
) {
911 // Free the buffer that was allocated that was too small
913 gBS
->FreePool (VariableData
);
915 VariableData
= AllocatePool (SizeOfNvStore
);
916 if (VariableData
== NULL
) {
917 return EFI_OUT_OF_RESOURCES
;
920 Status
= gRT
->GetVariable (
925 (VOID
*) VariableData
931 // Walk through the form and see that the variable data it refers to is ok.
932 // This allows for the possibility of stale (obsoleted) data in the variable
933 // can be overlooked without causing an error
935 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
936 switch (RawData
[Index
]) {
937 case EFI_IFR_ONE_OF_OP
:
939 // A one_of has no data, its the option that does - cache the storage Id
941 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
944 case EFI_IFR_ONE_OF_OPTION_OP
:
946 // A one_of_option can be any value
948 if (VariableData
[CachedStart
] == ((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
953 case EFI_IFR_END_ONE_OF_OP
:
955 // At this point lets make sure that the data value in the NVRAM matches one of the options
963 case EFI_IFR_CHECKBOX_OP
:
965 // A checkbox is a boolean, so 0 and 1 are valid
966 // Remember, QuestionId corresponds to the offset location of the data in the variable
968 if (VariableData
[((EFI_IFR_CHECKBOX
*) &RawData
[Index
])->QuestionId
] > 1) {
974 case EFI_IFR_NUMERIC_OP
:
975 if ((VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
976 (VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
984 Index
= RawData
[Index
+ 1] + Index
;
988 // Free our temporary repository of form data
990 gBS
->FreePool (OldData
);
991 gBS
->FreePool (VariableData
);