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
23 // Include common header file for this module.
25 #include "CommonHeader.h"
30 IN EFI_HANDLE ImageHandle
,
31 IN EFI_SYSTEM_TABLE
*SystemTable
45 Determine what is the current language setting
49 Lang - Pointer of system language
63 // Getting the system language and placing it into our Global Data
65 Size
= sizeof (Language
);
67 Status
= gRT
->GetVariable (
69 &gEfiGlobalVariableGuid
,
75 if (EFI_ERROR (Status
)) {
76 AsciiStrCpy (Language
, "eng");
79 for (Index
= 0; Index
< 3; Index
++) {
81 // Bitwise AND ascii value with 0xDF yields an uppercase value.
82 // Sign extend into a unicode value
84 Lang
[Index
] = (CHAR16
) (Language
[Index
] & 0xDF);
88 // Null-terminate the value
98 IN VOID
*StringBuffer
,
101 IN OUT STRING_REF
*StringToken
107 Add a string to the incoming buffer and return the token and offset data
111 StringBuffer - The incoming buffer
113 Language - Currrent language
115 String - The string to be added
117 StringToken - The index where the string placed
121 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
123 EFI_SUCCESS - String successfully added to the incoming buffer
127 EFI_HII_STRING_PACK
*StringPack
;
128 EFI_HII_STRING_PACK
*StringPackBuffer
;
131 RELOFST
*PackDestination
;
136 UINTN SizeofLanguage
;
139 StringPack
= (EFI_HII_STRING_PACK
*) StringBuffer
;
143 // Pre-allocate a buffer sufficient for us to work on.
144 // We will use it as a destination scratch pad to build data on
145 // and when complete shift the data back to the original buffer
147 NewBuffer
= AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE
);
148 if (NewBuffer
== NULL
) {
149 return EFI_OUT_OF_RESOURCES
;
152 StringPackBuffer
= (EFI_HII_STRING_PACK
*) NewBuffer
;
155 // StringPack is terminated with a length 0 entry
157 for (; StringPack
->Header
.Length
!= 0;) {
159 // If this stringpack's language is same as CurrentLanguage, use it
161 if (CompareMem ((VOID
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
, 3) == 0) {
163 // We have some data in this string pack, copy the string package up to the string data
165 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, sizeof (StringPack
));
168 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
170 StringPackBuffer
->LanguageNameString
= (UINT16
) (StringPackBuffer
->LanguageNameString
+ (UINT16
) sizeof (RELOFST
));
171 StringPackBuffer
->PrintableLanguageName
= (UINT16
) (StringPackBuffer
->PrintableLanguageName
+ (UINT16
) sizeof (RELOFST
));
173 PackSource
= (RELOFST
*) (StringPack
+ 1);
174 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
175 for (Index
= 0; PackSource
[Index
] != 0x0000; Index
++) {
177 // Copy the stringpointers from old to new buffer
178 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
180 PackDestination
[Index
] = (UINT16
) (PackDestination
[Index
] + sizeof (RELOFST
));
184 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
186 PackDestination
[Index
] = (UINT16
)(PackDestination
[Index
-1] +
187 StrSize((CHAR16
*)((CHAR8
*)(StringPack
) + PackSource
[Index
-1])));
188 PackDestination
[Index
+ 1] = (UINT16
) 0;
191 // Index is the token value for the new string
193 *StringToken
= (UINT16
) Index
;
196 // Source now points to the beginning of the old buffer strings
197 // Destination now points to the beginning of the new buffer strings
199 Source
= (UINT8
*) &PackSource
[Index
+ 1];
200 Destination
= (UINT8
*) &PackDestination
[Index
+ 2];
203 // This should copy all the strings from the old buffer to the new buffer
205 for (; Index
!= 0; Index
--) {
207 // Copy Source string to destination buffer
209 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) Source
);
212 // Adjust the source/destination to the next string location
214 Destination
= Destination
+ StrSize ((CHAR16
*) Source
);
215 Source
= Source
+ StrSize ((CHAR16
*) Source
);
219 // This copies the new string to the destination buffer
221 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) String
);
224 // Adjust the size of the changed string pack by adding the size of the new string
225 // along with the size of the additional offset entry for the new string
227 StringPackBuffer
->Header
.Length
= (UINT32
) ((UINTN
) StringPackBuffer
->Header
.Length
+ StrSize (String
) + sizeof (RELOFST
));
230 // Advance the buffers to point to the next spots.
232 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPackBuffer
->Header
.Length
);
233 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
238 // This isn't the language of the stringpack we were asked to add a string to
239 // so we need to copy it to the new buffer.
241 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, StringPack
->Header
.Length
);
244 // Advance the buffers to point to the next spots.
246 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPack
->Header
.Length
);
247 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
251 // If we didn't copy the new data to a stringpack yet
254 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
256 // Pointing to a new string pack location
258 SizeofLanguage
= StrSize (Language
);
259 SizeofString
= StrSize (String
);
260 StringPackBuffer
->Header
.Length
= (UINT32
)
262 sizeof (EFI_HII_STRING_PACK
) -
263 sizeof (EFI_STRING
) +
269 StringPackBuffer
->Header
.Type
= EFI_HII_STRING
;
270 StringPackBuffer
->LanguageNameString
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
271 StringPackBuffer
->PrintableLanguageName
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
272 StringPackBuffer
->Attributes
= 0;
273 PackDestination
[0] = (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
274 PackDestination
[1] = (UINT16
) (PackDestination
[0] + StrSize (Language
));
275 PackDestination
[2] = (UINT16
) 0;
278 // The first string location will be set to destination. The minimum number of strings
279 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
280 // and token 1 as the new string being added and and null entry for the stringpointers
282 Destination
= (UINT8
*) &PackDestination
[3];
285 // Copy the language name string to the new buffer
287 StrCpy ((CHAR16
*) Destination
, Language
);
290 // Advance the destination to the new empty spot
292 Destination
= Destination
+ StrSize (Language
);
295 // Copy the string to the new buffer
297 StrCpy ((CHAR16
*) Destination
, String
);
300 // Since we are starting with a new string pack - we know the new string is token 1
302 *StringToken
= (UINT16
) 1;
306 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
308 ZeroMem (StringBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
309 CopyMem (StringBuffer
, NewBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
312 // Free the newly created buffer since we don't need it anymore
314 gBS
->FreePool (NewBuffer
);
322 IN OUT VOID
*OpCodeData
328 Add op-code data to the FormBuffer
332 FormBuffer - Form buffer to be inserted to
334 OpCodeData - Op-code data to be inserted
338 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
340 EFI_SUCCESS - Op-code data successfully inserted
344 EFI_HII_PACK_HEADER
*NewBuffer
;
349 // Pre-allocate a buffer sufficient for us to work on.
350 // We will use it as a destination scratch pad to build data on
351 // and when complete shift the data back to the original buffer
353 NewBuffer
= AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE
);
354 if (NewBuffer
== NULL
) {
355 return EFI_OUT_OF_RESOURCES
;
358 Source
= (UINT8
*) FormBuffer
;
359 Destination
= (UINT8
*) NewBuffer
;
362 // Copy the IFR Package header to the new buffer
364 CopyMem (Destination
, Source
, sizeof (EFI_HII_PACK_HEADER
));
367 // Advance Source and Destination to next op-code
369 Source
= Source
+ sizeof (EFI_HII_PACK_HEADER
);
370 Destination
= Destination
+ sizeof (EFI_HII_PACK_HEADER
);
373 // Copy data to the new buffer until we run into the end_form
375 for (; ((EFI_IFR_OP_HEADER
*) Source
)->OpCode
!= EFI_IFR_END_FORM_OP
;) {
377 // If the this opcode is an end_form_set we better be creating and endform
378 // Nonetheless, we will add data before the end_form_set. This also provides
379 // for interesting behavior in the code we will run, but has no bad side-effects
380 // since we will possibly do a 0 byte copy in this particular end-case.
382 if (((EFI_IFR_OP_HEADER
*) Source
)->OpCode
== EFI_IFR_END_FORM_SET_OP
) {
387 // Copy data to new buffer
389 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
392 // Adjust Source/Destination to next op-code location
394 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
395 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
399 // Prior to the end_form is where we insert the new op-code data
401 CopyMem (Destination
, OpCodeData
, ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
402 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
404 NewBuffer
->Length
= (UINT32
) (NewBuffer
->Length
+ (UINT32
) (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
));
407 // Copy end-form data to new buffer
409 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
412 // Adjust Source/Destination to next op-code location
414 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
415 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
418 // Copy end-formset data to new buffer
420 CopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
423 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
425 ZeroMem (FormBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
426 CopyMem (FormBuffer
, NewBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
429 // Free the newly created buffer since we don't need it anymore
431 gBS
->FreePool (NewBuffer
);
438 OUT EFI_HII_PROTOCOL
**Hii
444 Get the HII protocol interface
448 Hii - HII protocol interface
459 // There should only be one HII protocol
461 Status
= gBS
->LocateProtocol (
462 &gEfiHiiProtocolGuid
,
472 ExtractDataFromHiiHandle (
473 IN EFI_HII_HANDLE HiiHandle
,
474 IN OUT UINT16
*ImageLength
,
475 OUT UINT8
*DefaultImage
,
482 Extract information pertaining to the HiiHandle
486 HiiHandle - Hii handle
488 ImageLength - For input, length of DefaultImage;
489 For output, length of actually required
491 DefaultImage - Image buffer prepared by caller
493 Guid - Guid information about the form
497 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
499 EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
501 EFI_SUCCESS - Successfully extract data from Hii database.
507 EFI_HII_PROTOCOL
*Hii
;
516 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
520 Status
= GetHiiInterface (&Hii
);
522 if (EFI_ERROR (Status
)) {
527 // Allocate space for retrieval of IFR data
529 RawData
= AllocateZeroPool (DataLength
);
530 if (RawData
== NULL
) {
531 return EFI_OUT_OF_RESOURCES
;
535 // Get all the forms associated with this HiiHandle
537 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
539 if (EFI_ERROR (Status
)) {
540 gBS
->FreePool (RawData
);
543 // Allocate space for retrieval of IFR data
545 RawData
= AllocateZeroPool (DataLength
);
546 if (RawData
== NULL
) {
547 return EFI_OUT_OF_RESOURCES
;
551 // Get all the forms associated with this HiiHandle
553 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
559 // Point RawData to the beginning of the form data
561 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
563 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
564 switch (RawData
[Index
]) {
565 case EFI_IFR_FORM_SET_OP
:
567 // Copy the GUID information from this handle
569 CopyMem (Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
572 case EFI_IFR_ONE_OF_OP
:
573 case EFI_IFR_CHECKBOX_OP
:
574 case EFI_IFR_NUMERIC_OP
:
575 case EFI_IFR_DATE_OP
:
576 case EFI_IFR_TIME_OP
:
577 case EFI_IFR_PASSWORD_OP
:
578 case EFI_IFR_STRING_OP
:
580 // Remember, multiple op-codes may reference the same item, so let's keep a running
581 // marker of what the highest QuestionId that wasn't zero length. This will accurately
582 // maintain the Size of the NvStore
584 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
585 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
586 if (SizeOfNvStore
< Temp
) {
587 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
592 Index
= RawData
[Index
+ 1] + Index
;
596 // Return an error if buffer is too small
598 if (SizeOfNvStore
> *ImageLength
) {
599 gBS
->FreePool (OldData
);
600 *ImageLength
= (UINT16
) SizeOfNvStore
;
601 return EFI_BUFFER_TOO_SMALL
;
604 if (DefaultImage
!= NULL
) {
605 ZeroMem (DefaultImage
, SizeOfNvStore
);
609 // Copy the default image information to the user's buffer
611 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
612 switch (RawData
[Index
]) {
613 case EFI_IFR_ONE_OF_OP
:
614 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
617 case EFI_IFR_ONE_OF_OPTION_OP
:
618 if (((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& EFI_IFR_FLAG_DEFAULT
) {
619 CopyMem (&DefaultImage
[CachedStart
], &((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
623 case EFI_IFR_CHECKBOX_OP
:
624 DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((EFI_IFR_CHECKBOX
*) &RawData
[Index
])->Flags
;
627 case EFI_IFR_NUMERIC_OP
:
629 &DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
630 &((EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
637 Index
= RawData
[Index
+ 1] + Index
;
640 *ImageLength
= (UINT16
) SizeOfNvStore
;
643 // Free our temporary repository of form data
645 gBS
->FreePool (OldData
);
653 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
659 Finds HII handle for given pack GUID previously registered with the HII.
662 HiiProtocol - pointer to pointer to HII protocol interface.
663 If NULL, the interface will be found but not returned.
664 If it points to NULL, the interface will be found and
665 written back to the pointer that is pointed to.
666 Guid - The GUID of the pack that registered with the HII.
669 Handle to the HII pack previously registered by the memory driver.
675 EFI_HII_HANDLE
*HiiHandleBuffer
;
676 EFI_HII_HANDLE HiiHandle
;
677 UINT16 HiiHandleBufferLength
;
678 UINT32 NumberOfHiiHandles
;
680 EFI_HII_PROTOCOL
*HiiProt
;
685 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
687 // The protocol has been passed in
689 HiiProt
= *HiiProtocol
;
691 gBS
->LocateProtocol (
692 &gEfiHiiProtocolGuid
,
696 if (HiiProt
== NULL
) {
700 if (HiiProtocol
!= NULL
) {
702 // Return back the HII protocol for the caller as promissed
704 *HiiProtocol
= HiiProt
;
710 HiiHandleBufferLength
= 10;
711 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
712 ASSERT (HiiHandleBuffer
!= NULL
);
715 // Get the Handles of the packages that were registered with Hii
717 Status
= HiiProt
->FindHandles (
719 &HiiHandleBufferLength
,
724 // Get a bigger bugffer if this one is to small, and try again
726 if (Status
== EFI_BUFFER_TOO_SMALL
) {
728 gBS
->FreePool (HiiHandleBuffer
);
730 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
731 ASSERT (HiiHandleBuffer
!= NULL
);
733 Status
= HiiProt
->FindHandles (
735 &HiiHandleBufferLength
,
740 if (EFI_ERROR (Status
)) {
744 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
747 // Iterate Hii handles and look for the one that matches our Guid
749 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
752 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
754 if (CompareGuid (&HiiGuid
, Guid
)) {
756 HiiHandle
= HiiHandleBuffer
[Index
];
762 gBS
->FreePool (HiiHandleBuffer
);
768 ValidateDataFromHiiHandle (
769 IN EFI_HII_HANDLE HiiHandle
,
776 Validate that the data associated with the HiiHandle in NVRAM is within
777 the reasonable parameters for that FormSet. Values for strings and passwords
778 are not verified due to their not having the equivalent of valid range settings.
782 HiiHandle - Handle of the HII database entry to query
784 Results - If return Status is EFI_SUCCESS, Results provides valid data
785 TRUE = NVRAM Data is within parameters
786 FALSE = NVRAM Data is NOT within parameters
790 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
792 EFI_SUCCESS - Data successfully validated
796 EFI_HII_PROTOCOL
*Hii
;
808 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
814 Status
= GetHiiInterface (&Hii
);
816 if (EFI_ERROR (Status
)) {
821 // Allocate space for retrieval of IFR data
823 RawData
= AllocateZeroPool (RawDataLength
);
824 if (RawData
== NULL
) {
825 return EFI_OUT_OF_RESOURCES
;
829 // Get all the forms associated with this HiiHandle
831 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
833 if (EFI_ERROR (Status
)) {
834 gBS
->FreePool (RawData
);
837 // Allocate space for retrieval of IFR data
839 RawData
= AllocateZeroPool (RawDataLength
);
840 if (RawData
== NULL
) {
841 return EFI_OUT_OF_RESOURCES
;
845 // Get all the forms associated with this HiiHandle
847 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
853 // Point RawData to the beginning of the form data
855 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
857 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
858 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
859 CopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
863 Index
= RawData
[Index
+ 1] + Index
;
866 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
867 switch (RawData
[Index
]) {
868 case EFI_IFR_FORM_SET_OP
:
871 case EFI_IFR_ONE_OF_OP
:
872 case EFI_IFR_CHECKBOX_OP
:
873 case EFI_IFR_NUMERIC_OP
:
874 case EFI_IFR_DATE_OP
:
875 case EFI_IFR_TIME_OP
:
876 case EFI_IFR_PASSWORD_OP
:
877 case EFI_IFR_STRING_OP
:
879 // Remember, multiple op-codes may reference the same item, so let's keep a running
880 // marker of what the highest QuestionId that wasn't zero length. This will accurately
881 // maintain the Size of the NvStore
883 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
884 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
885 if (SizeOfNvStore
< Temp
) {
886 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
891 Index
= RawData
[Index
+ 1] + Index
;
895 // Allocate memory for our File Form Tags
897 VariableData
= AllocateZeroPool (SizeOfNvStore
);
898 if (VariableData
== NULL
) {
899 return EFI_OUT_OF_RESOURCES
;
902 Status
= gRT
->GetVariable (
907 (VOID
*) VariableData
910 if (EFI_ERROR (Status
)) {
913 // If there is a variable that exists already and it is larger than what we calculated the
914 // storage needs to be, we must assume the variable size from GetVariable is correct and not
915 // allow the truncation of the variable. It is very possible that the user who created the IFR
916 // we are cracking is not referring to a variable that was in a previous map, however we cannot
917 // allow it's truncation.
919 if (Status
== EFI_BUFFER_TOO_SMALL
) {
921 // Free the buffer that was allocated that was too small
923 gBS
->FreePool (VariableData
);
925 VariableData
= AllocatePool (SizeOfNvStore
);
926 if (VariableData
== NULL
) {
927 return EFI_OUT_OF_RESOURCES
;
930 Status
= gRT
->GetVariable (
935 (VOID
*) VariableData
941 // Walk through the form and see that the variable data it refers to is ok.
942 // This allows for the possibility of stale (obsoleted) data in the variable
943 // can be overlooked without causing an error
945 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
946 switch (RawData
[Index
]) {
947 case EFI_IFR_ONE_OF_OP
:
949 // A one_of has no data, its the option that does - cache the storage Id
951 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
954 case EFI_IFR_ONE_OF_OPTION_OP
:
956 // A one_of_option can be any value
958 if (VariableData
[CachedStart
] == ((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
963 case EFI_IFR_END_ONE_OF_OP
:
965 // At this point lets make sure that the data value in the NVRAM matches one of the options
973 case EFI_IFR_CHECKBOX_OP
:
975 // A checkbox is a boolean, so 0 and 1 are valid
976 // Remember, QuestionId corresponds to the offset location of the data in the variable
978 if (VariableData
[((EFI_IFR_CHECKBOX
*) &RawData
[Index
])->QuestionId
] > 1) {
984 case EFI_IFR_NUMERIC_OP
:
985 if ((VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
986 (VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
994 Index
= RawData
[Index
+ 1] + Index
;
998 // Free our temporary repository of form data
1000 gBS
->FreePool (OldData
);
1001 gBS
->FreePool (VariableData
);