2 Common Library Routines to assist in IFR creation on-the-fly
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 // Include common header file for this module.
18 #include "IfrSupportLibInternal.h"
21 Determine what is the current language setting
22 The setting is stored in language variable in flash. This routine
23 will get setting by accesssing that variable. If failed to access
24 language variable, then use default setting that 'eng' as current
27 @param Lang Pointer of system language
29 @return whether sucess to get setting from variable
42 // Getting the system language and placing it into our Global Data
44 Size
= sizeof (Language
);
46 Status
= gRT
->GetVariable (
48 &gEfiGlobalVariableGuid
,
54 if (EFI_ERROR (Status
)) {
55 AsciiStrCpy (Language
, "eng");
58 for (Index
= 0; Index
< 3; Index
++) {
60 // Bitwise AND ascii value with 0xDF yields an uppercase value.
61 // Sign extend into a unicode value
63 Lang
[Index
] = (CHAR16
) (Language
[Index
] & 0xDF);
67 // Null-terminate the value
75 Add a string to the incoming buffer and return the token and offset data
77 @param StringBuffer The incoming buffer
78 @param Language Currrent language
79 @param String The string to be added
80 @param StringToken The index where the string placed
82 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
83 @retval EFI_SUCCESS String successfully added to the incoming buffer
87 IN VOID
*StringBuffer
,
90 IN OUT STRING_REF
*StringToken
93 EFI_HII_STRING_PACK
*StringPack
;
94 EFI_HII_STRING_PACK
*StringPackBuffer
;
97 RELOFST
*PackDestination
;
102 UINTN SizeofLanguage
;
105 StringPack
= (EFI_HII_STRING_PACK
*) StringBuffer
;
109 // Pre-allocate a buffer sufficient for us to work on.
110 // We will use it as a destination scratch pad to build data on
111 // and when complete shift the data back to the original buffer
113 NewBuffer
= AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE
);
114 if (NewBuffer
== NULL
) {
115 return EFI_OUT_OF_RESOURCES
;
118 StringPackBuffer
= (EFI_HII_STRING_PACK
*) NewBuffer
;
121 // StringPack is terminated with a length 0 entry
123 for (; StringPack
->Header
.Length
!= 0;) {
125 // If this stringpack's language is same as CurrentLanguage, use it
127 if (CompareMem ((VOID
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
, 3) == 0) {
129 // We have some data in this string pack, copy the string package up to the string data
131 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, sizeof (StringPack
));
134 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
136 StringPackBuffer
->LanguageNameString
= (UINT16
) (StringPackBuffer
->LanguageNameString
+ (UINT16
) sizeof (RELOFST
));
137 StringPackBuffer
->PrintableLanguageName
= (UINT16
) (StringPackBuffer
->PrintableLanguageName
+ (UINT16
) sizeof (RELOFST
));
139 PackSource
= (RELOFST
*) (StringPack
+ 1);
140 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
141 for (Index
= 0; PackSource
[Index
] != 0x0000; Index
++) {
143 // Copy the stringpointers from old to new buffer
144 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
146 PackDestination
[Index
] = (UINT16
) (PackDestination
[Index
] + sizeof (RELOFST
));
150 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
152 PackDestination
[Index
] = (UINT16
)(PackDestination
[Index
-1] +
153 StrSize((CHAR16
*)((CHAR8
*)(StringPack
) + PackSource
[Index
-1])));
154 PackDestination
[Index
+ 1] = (UINT16
) 0;
157 // Index is the token value for the new string
159 *StringToken
= (UINT16
) Index
;
162 // Source now points to the beginning of the old buffer strings
163 // Destination now points to the beginning of the new buffer strings
165 Source
= (UINT8
*) &PackSource
[Index
+ 1];
166 Destination
= (UINT8
*) &PackDestination
[Index
+ 2];
169 // This should copy all the strings from the old buffer to the new buffer
171 for (; Index
!= 0; Index
--) {
173 // Copy Source string to destination buffer
175 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) Source
);
178 // Adjust the source/destination to the next string location
180 Destination
= Destination
+ StrSize ((CHAR16
*) Source
);
181 Source
= Source
+ StrSize ((CHAR16
*) Source
);
185 // This copies the new string to the destination buffer
187 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) String
);
190 // Adjust the size of the changed string pack by adding the size of the new string
191 // along with the size of the additional offset entry for the new string
193 StringPackBuffer
->Header
.Length
= (UINT32
) ((UINTN
) StringPackBuffer
->Header
.Length
+ StrSize (String
) + sizeof (RELOFST
));
196 // Advance the buffers to point to the next spots.
198 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPackBuffer
->Header
.Length
);
199 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
204 // This isn't the language of the stringpack we were asked to add a string to
205 // so we need to copy it to the new buffer.
207 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, StringPack
->Header
.Length
);
210 // Advance the buffers to point to the next spots.
212 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPack
->Header
.Length
);
213 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
217 // If we didn't copy the new data to a stringpack yet
220 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
222 // Pointing to a new string pack location
224 SizeofLanguage
= StrSize (Language
);
225 SizeofString
= StrSize (String
);
226 StringPackBuffer
->Header
.Length
= (UINT32
)
228 sizeof (EFI_HII_STRING_PACK
) -
229 sizeof (EFI_STRING
) +
235 StringPackBuffer
->Header
.Type
= EFI_HII_STRING
;
236 StringPackBuffer
->LanguageNameString
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
237 StringPackBuffer
->PrintableLanguageName
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
238 StringPackBuffer
->Attributes
= 0;
239 PackDestination
[0] = (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
240 PackDestination
[1] = (UINT16
) (PackDestination
[0] + StrSize (Language
));
241 PackDestination
[2] = (UINT16
) 0;
244 // The first string location will be set to destination. The minimum number of strings
245 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
246 // and token 1 as the new string being added and and null entry for the stringpointers
248 Destination
= (UINT8
*) &PackDestination
[3];
251 // Copy the language name string to the new buffer
253 StrCpy ((CHAR16
*) Destination
, Language
);
256 // Advance the destination to the new empty spot
258 Destination
= Destination
+ StrSize (Language
);
261 // Copy the string to the new buffer
263 StrCpy ((CHAR16
*) Destination
, String
);
266 // Since we are starting with a new string pack - we know the new string is token 1
268 *StringToken
= (UINT16
) 1;
272 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
274 ZeroMem (StringBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
275 CopyMem (StringBuffer
, NewBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
278 // Free the newly created buffer since we don't need it anymore
280 gBS
->FreePool (NewBuffer
);
285 Add op-code data to the FormBuffer
287 @param FormBuffer Form buffer to be inserted to
288 @param OpCodeData Op-code data to be inserted
290 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
291 @retval EFI_SUCCESS Op-code data successfully inserted
296 IN OUT VOID
*OpCodeData
299 EFI_HII_PACK_HEADER
*NewBuffer
;
304 // Pre-allocate a buffer sufficient for us to work on.
305 // We will use it as a destination scratch pad to build data on
306 // and when complete shift the data back to the original buffer
308 NewBuffer
= AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE
);
309 if (NewBuffer
== NULL
) {
310 return EFI_OUT_OF_RESOURCES
;
313 Source
= (UINT8
*) FormBuffer
;
314 Destination
= (UINT8
*) NewBuffer
;
317 // Copy the IFR Package header to the new buffer
319 CopyMem (Destination
, Source
, sizeof (EFI_HII_PACK_HEADER
));
322 // Advance Source and Destination to next op-code
324 Source
= Source
+ sizeof (EFI_HII_PACK_HEADER
);
325 Destination
= Destination
+ sizeof (EFI_HII_PACK_HEADER
);
328 // Copy data to the new buffer until we run into the end_form
330 for (; ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->OpCode
!= FRAMEWORK_EFI_IFR_END_FORM_OP
;) {
332 // If the this opcode is an end_form_set we better be creating and endform
333 // Nonetheless, we will add data before the end_form_set. This also provides
334 // for interesting behavior in the code we will run, but has no bad side-effects
335 // since we will possibly do a 0 byte copy in this particular end-case.
337 if (((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->OpCode
== FRAMEWORK_EFI_IFR_END_FORM_SET_OP
) {
342 // Copy data to new buffer
344 CopyMem (Destination
, Source
, ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
);
347 // Adjust Source/Destination to next op-code location
349 Destination
= Destination
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
;
350 Source
= Source
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
;
354 // Prior to the end_form is where we insert the new op-code data
356 CopyMem (Destination
, OpCodeData
, ((FRAMEWORK_EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
357 Destination
= Destination
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
359 NewBuffer
->Length
= (UINT32
) (NewBuffer
->Length
+ (UINT32
) (((FRAMEWORK_EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
));
362 // Copy end-form data to new buffer
364 CopyMem (Destination
, Source
, ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
);
367 // Adjust Source/Destination to next op-code location
369 Destination
= Destination
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
;
370 Source
= Source
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
;
373 // Copy end-formset data to new buffer
375 CopyMem (Destination
, Source
, ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
);
378 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
380 ZeroMem (FormBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
381 CopyMem (FormBuffer
, NewBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
384 // Free the newly created buffer since we don't need it anymore
386 gBS
->FreePool (NewBuffer
);
391 Get the HII protocol interface
393 @param Hii HII protocol interface
395 @return the statue of locating HII protocol
400 OUT EFI_HII_PROTOCOL
**Hii
406 // There should only be one HII protocol
408 Status
= gBS
->LocateProtocol (
409 &gEfiHiiProtocolGuid
,
418 Extract information pertaining to the HiiHandle
420 @param HiiHandle Hii handle
421 @param ImageLength For input, length of DefaultImage;
422 For output, length of actually required
423 @param DefaultImage Image buffer prepared by caller
424 @param Guid Guid information about the form
426 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
427 @retval EFI_BUFFER_TOO_SMALL DefualtImage has no enough ImageLength
428 @retval EFI_SUCCESS Successfully extract data from Hii database.
431 ExtractDataFromHiiHandle (
432 IN FRAMEWORK_EFI_HII_HANDLE HiiHandle
,
433 IN OUT UINT16
*ImageLength
,
434 OUT UINT8
*DefaultImage
,
439 EFI_HII_PROTOCOL
*Hii
;
448 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
452 Status
= GetHiiInterface (&Hii
);
454 if (EFI_ERROR (Status
)) {
459 // Allocate space for retrieval of IFR data
461 RawData
= AllocateZeroPool (DataLength
);
462 if (RawData
== NULL
) {
463 return EFI_OUT_OF_RESOURCES
;
467 // Get all the forms associated with this HiiHandle
469 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
471 if (EFI_ERROR (Status
)) {
472 gBS
->FreePool (RawData
);
475 // Allocate space for retrieval of IFR data
477 RawData
= AllocateZeroPool (DataLength
);
478 if (RawData
== NULL
) {
479 return EFI_OUT_OF_RESOURCES
;
483 // Get all the forms associated with this HiiHandle
485 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
491 // Point RawData to the beginning of the form data
493 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
495 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
496 switch (RawData
[Index
]) {
497 case FRAMEWORK_EFI_IFR_FORM_SET_OP
:
499 // Copy the GUID information from this handle
501 CopyMem (Guid
, &((FRAMEWORK_EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
504 case FRAMEWORK_EFI_IFR_ONE_OF_OP
:
505 case FRAMEWORK_EFI_IFR_CHECKBOX_OP
:
506 case FRAMEWORK_EFI_IFR_NUMERIC_OP
:
507 case FRAMEWORK_EFI_IFR_DATE_OP
:
508 case FRAMEWORK_EFI_IFR_TIME_OP
:
509 case FRAMEWORK_EFI_IFR_PASSWORD_OP
:
510 case FRAMEWORK_EFI_IFR_STRING_OP
:
512 // Remember, multiple op-codes may reference the same item, so let's keep a running
513 // marker of what the highest QuestionId that wasn't zero length. This will accurately
514 // maintain the Size of the NvStore
516 if (((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
517 Temp
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
518 if (SizeOfNvStore
< Temp
) {
519 SizeOfNvStore
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
524 Index
= RawData
[Index
+ 1] + Index
;
528 // Return an error if buffer is too small
530 if (SizeOfNvStore
> *ImageLength
) {
531 gBS
->FreePool (OldData
);
532 *ImageLength
= (UINT16
) SizeOfNvStore
;
533 return EFI_BUFFER_TOO_SMALL
;
536 if (DefaultImage
!= NULL
) {
537 ZeroMem (DefaultImage
, SizeOfNvStore
);
541 // Copy the default image information to the user's buffer
543 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
544 switch (RawData
[Index
]) {
545 case FRAMEWORK_EFI_IFR_ONE_OF_OP
:
546 CachedStart
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
549 case FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP
:
550 if (((FRAMEWORK_EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& FRAMEWORK_EFI_IFR_FLAG_DEFAULT
) {
551 CopyMem (&DefaultImage
[CachedStart
], &((FRAMEWORK_EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
555 case FRAMEWORK_EFI_IFR_CHECKBOX_OP
:
556 DefaultImage
[((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((FRAMEWORK_EFI_IFR_CHECKBOX
*) &RawData
[Index
])->Flags
;
559 case FRAMEWORK_EFI_IFR_NUMERIC_OP
:
561 &DefaultImage
[((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
562 &((FRAMEWORK_EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
569 Index
= RawData
[Index
+ 1] + Index
;
572 *ImageLength
= (UINT16
) SizeOfNvStore
;
575 // Free our temporary repository of form data
577 gBS
->FreePool (OldData
);
583 Finds HII handle for given pack GUID previously registered with the HII.
585 @param HiiProtocol pointer to pointer to HII protocol interface.
586 If NULL, the interface will be found but not returned.
587 If it points to NULL, the interface will be found and
588 written back to the pointer that is pointed to.
589 @param Guid The GUID of the pack that registered with the HII.
591 @return Handle to the HII pack previously registered by the memory driver.
593 FRAMEWORK_EFI_HII_HANDLE
595 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
601 FRAMEWORK_EFI_HII_HANDLE
*HiiHandleBuffer
;
602 FRAMEWORK_EFI_HII_HANDLE HiiHandle
;
603 UINT16 HiiHandleBufferLength
;
604 UINT32 NumberOfHiiHandles
;
606 EFI_HII_PROTOCOL
*HiiProt
;
611 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
613 // The protocol has been passed in
615 HiiProt
= *HiiProtocol
;
617 gBS
->LocateProtocol (
618 &gEfiHiiProtocolGuid
,
622 if (HiiProt
== NULL
) {
626 if (HiiProtocol
!= NULL
) {
628 // Return back the HII protocol for the caller as promissed
630 *HiiProtocol
= HiiProt
;
636 HiiHandleBufferLength
= 10;
637 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
638 ASSERT (HiiHandleBuffer
!= NULL
);
641 // Get the Handles of the packages that were registered with Hii
643 Status
= HiiProt
->FindHandles (
645 &HiiHandleBufferLength
,
650 // Get a bigger bugffer if this one is to small, and try again
652 if (Status
== EFI_BUFFER_TOO_SMALL
) {
654 gBS
->FreePool (HiiHandleBuffer
);
656 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
657 ASSERT (HiiHandleBuffer
!= NULL
);
659 Status
= HiiProt
->FindHandles (
661 &HiiHandleBufferLength
,
666 if (EFI_ERROR (Status
)) {
670 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (FRAMEWORK_EFI_HII_HANDLE
);
673 // Iterate Hii handles and look for the one that matches our Guid
675 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
678 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
680 if (CompareGuid (&HiiGuid
, Guid
)) {
682 HiiHandle
= HiiHandleBuffer
[Index
];
688 gBS
->FreePool (HiiHandleBuffer
);
693 Validate that the data associated with the HiiHandle in NVRAM is within
694 the reasonable parameters for that FormSet. Values for strings and passwords
695 are not verified due to their not having the equivalent of valid range settings.
697 @param HiiHandle Handle of the HII database entry to query
699 @param Results If return Status is EFI_SUCCESS, Results provides valid data
700 TRUE = NVRAM Data is within parameters
701 FALSE = NVRAM Data is NOT within parameters
702 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
703 @retval EFI_SUCCESS Data successfully validated
706 ValidateDataFromHiiHandle (
707 IN FRAMEWORK_EFI_HII_HANDLE HiiHandle
,
712 EFI_HII_PROTOCOL
*Hii
;
724 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
730 Status
= GetHiiInterface (&Hii
);
732 if (EFI_ERROR (Status
)) {
737 // Allocate space for retrieval of IFR data
739 RawData
= AllocateZeroPool (RawDataLength
);
740 if (RawData
== NULL
) {
741 return EFI_OUT_OF_RESOURCES
;
745 // Get all the forms associated with this HiiHandle
747 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
749 if (EFI_ERROR (Status
)) {
750 gBS
->FreePool (RawData
);
753 // Allocate space for retrieval of IFR data
755 RawData
= AllocateZeroPool (RawDataLength
);
756 if (RawData
== NULL
) {
757 return EFI_OUT_OF_RESOURCES
;
761 // Get all the forms associated with this HiiHandle
763 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
769 // Point RawData to the beginning of the form data
771 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
773 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
774 if (RawData
[Index
] == FRAMEWORK_EFI_IFR_FORM_SET_OP
) {
775 CopyMem (&Guid
, &((FRAMEWORK_EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
779 Index
= RawData
[Index
+ 1] + Index
;
782 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
783 switch (RawData
[Index
]) {
784 case FRAMEWORK_EFI_IFR_FORM_SET_OP
:
787 case FRAMEWORK_EFI_IFR_ONE_OF_OP
:
788 case FRAMEWORK_EFI_IFR_CHECKBOX_OP
:
789 case FRAMEWORK_EFI_IFR_NUMERIC_OP
:
790 case FRAMEWORK_EFI_IFR_DATE_OP
:
791 case FRAMEWORK_EFI_IFR_TIME_OP
:
792 case FRAMEWORK_EFI_IFR_PASSWORD_OP
:
793 case FRAMEWORK_EFI_IFR_STRING_OP
:
795 // Remember, multiple op-codes may reference the same item, so let's keep a running
796 // marker of what the highest QuestionId that wasn't zero length. This will accurately
797 // maintain the Size of the NvStore
799 if (((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
800 Temp
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
801 if (SizeOfNvStore
< Temp
) {
802 SizeOfNvStore
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
807 Index
= RawData
[Index
+ 1] + Index
;
811 // Allocate memory for our File Form Tags
813 VariableData
= AllocateZeroPool (SizeOfNvStore
);
814 if (VariableData
== NULL
) {
815 return EFI_OUT_OF_RESOURCES
;
818 Status
= gRT
->GetVariable (
823 (VOID
*) VariableData
826 if (EFI_ERROR (Status
)) {
829 // If there is a variable that exists already and it is larger than what we calculated the
830 // storage needs to be, we must assume the variable size from GetVariable is correct and not
831 // allow the truncation of the variable. It is very possible that the user who created the IFR
832 // we are cracking is not referring to a variable that was in a previous map, however we cannot
833 // allow it's truncation.
835 if (Status
== EFI_BUFFER_TOO_SMALL
) {
837 // Free the buffer that was allocated that was too small
839 gBS
->FreePool (VariableData
);
841 VariableData
= AllocatePool (SizeOfNvStore
);
842 if (VariableData
== NULL
) {
843 return EFI_OUT_OF_RESOURCES
;
846 Status
= gRT
->GetVariable (
851 (VOID
*) VariableData
857 // Walk through the form and see that the variable data it refers to is ok.
858 // This allows for the possibility of stale (obsoleted) data in the variable
859 // can be overlooked without causing an error
861 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
862 switch (RawData
[Index
]) {
863 case FRAMEWORK_EFI_IFR_ONE_OF_OP
:
865 // A one_of has no data, its the option that does - cache the storage Id
867 CachedStart
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
870 case FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP
:
872 // A one_of_option can be any value
874 if (VariableData
[CachedStart
] == ((FRAMEWORK_EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
879 case FRAMEWORK_EFI_IFR_END_ONE_OF_OP
:
881 // At this point lets make sure that the data value in the NVRAM matches one of the options
889 case FRAMEWORK_EFI_IFR_CHECKBOX_OP
:
891 // A checkbox is a boolean, so 0 and 1 are valid
892 // Remember, QuestionId corresponds to the offset location of the data in the variable
894 if (VariableData
[((FRAMEWORK_EFI_IFR_CHECKBOX
*) &RawData
[Index
])->QuestionId
] > 1) {
900 case FRAMEWORK_EFI_IFR_NUMERIC_OP
:
901 if ((VariableData
[((FRAMEWORK_EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((FRAMEWORK_EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
902 (VariableData
[((FRAMEWORK_EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((FRAMEWORK_EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
910 Index
= RawData
[Index
+ 1] + Index
;
914 // Free our temporary repository of form data
916 gBS
->FreePool (OldData
);
917 gBS
->FreePool (VariableData
);