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.
15 #include "IfrSupportLibInternal.h"
18 Determine what is the current language setting
19 The setting is stored in language variable in flash. This routine
20 will get setting by accesssing that variable. If failed to access
21 language variable, then use default setting that 'eng' as current
24 @param Lang Pointer of system language
26 @return whether sucess to get setting from variable
40 // Getting the system language and placing it into our Global Data
42 Size
= sizeof (Language
);
43 Status
= gRT
->GetVariable (
45 &gEfiGlobalVariableGuid
,
50 if (EFI_ERROR (Status
)) {
51 AsciiStrCpy (Language
, "eng");
54 for (Index
= 0; Index
< 3; Index
++) {
56 // Bitwise AND ascii value with 0xDF yields an uppercase value.
57 // Sign extend into a unicode value
59 Lang
[Index
] = (CHAR16
) (Language
[Index
] & 0xDF);
63 // Null-terminate the value
71 Add a string to the incoming buffer and return the token and offset data.
73 @param StringBuffer The incoming buffer
74 @param Language Currrent language
75 @param String The string to be added
76 @param StringToken The index where the string placed
78 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
79 @retval EFI_SUCCESS String successfully added to the incoming buffer
84 IN VOID
*StringBuffer
,
87 IN OUT STRING_REF
*StringToken
90 EFI_HII_STRING_PACK
*StringPack
;
91 EFI_HII_STRING_PACK
*StringPackBuffer
;
94 RELOFST
*PackDestination
;
102 StringPack
= (EFI_HII_STRING_PACK
*) StringBuffer
;
106 // Pre-allocate a buffer sufficient for us to work on.
107 // We will use it as a destination scratch pad to build data on
108 // and when complete shift the data back to the original buffer
110 NewBuffer
= AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE
);
111 if (NewBuffer
== NULL
) {
112 return EFI_OUT_OF_RESOURCES
;
115 StringPackBuffer
= (EFI_HII_STRING_PACK
*) NewBuffer
;
118 // StringPack is terminated with a length 0 entry
120 for (; StringPack
->Header
.Length
!= 0;) {
122 // If this stringpack's language is same as CurrentLanguage, use it
124 if (CompareMem ((VOID
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
, 3) == 0) {
126 // We have some data in this string pack, copy the string package up to the string data
128 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, sizeof (StringPack
));
131 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
133 StringPackBuffer
->LanguageNameString
= (UINT16
) (StringPackBuffer
->LanguageNameString
+ (UINT16
) sizeof (RELOFST
));
134 StringPackBuffer
->PrintableLanguageName
= (UINT16
) (StringPackBuffer
->PrintableLanguageName
+ (UINT16
) sizeof (RELOFST
));
136 PackSource
= (RELOFST
*) (StringPack
+ 1);
137 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
138 for (Index
= 0; PackSource
[Index
] != 0x0000; Index
++) {
140 // Copy the stringpointers from old to new buffer
141 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
143 PackDestination
[Index
] = (UINT16
) (PackDestination
[Index
] + sizeof (RELOFST
));
147 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
149 PackDestination
[Index
] = (UINT16
)(PackDestination
[Index
- 1] +
150 StrSize((CHAR16
*)((CHAR8
*)(StringPack
) + PackSource
[Index
- 1])));
151 PackDestination
[Index
+ 1] = (UINT16
) 0;
154 // Index is the token value for the new string
156 *StringToken
= (UINT16
) Index
;
159 // Source now points to the beginning of the old buffer strings
160 // Destination now points to the beginning of the new buffer strings
162 Source
= (UINT8
*) &PackSource
[Index
+ 1];
163 Destination
= (UINT8
*) &PackDestination
[Index
+ 2];
166 // This should copy all the strings from the old buffer to the new buffer
168 for (; Index
!= 0; Index
--) {
170 // Copy Source string to destination buffer
172 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) Source
);
175 // Adjust the source/destination to the next string location
177 Destination
= Destination
+ StrSize ((CHAR16
*) Source
);
178 Source
= Source
+ StrSize ((CHAR16
*) Source
);
182 // This copies the new string to the destination buffer
184 StrCpy ((CHAR16
*) Destination
, (CHAR16
*) String
);
187 // Adjust the size of the changed string pack by adding the size of the new string
188 // along with the size of the additional offset entry for the new string
190 StringPackBuffer
->Header
.Length
= (UINT32
) ((UINTN
) StringPackBuffer
->Header
.Length
+ StrSize (String
) + sizeof (RELOFST
));
193 // Advance the buffers to point to the next spots.
195 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPackBuffer
->Header
.Length
);
196 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
201 // This isn't the language of the stringpack we were asked to add a string to
202 // so we need to copy it to the new buffer.
204 CopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, StringPack
->Header
.Length
);
207 // Advance the buffers to point to the next spots.
209 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPack
->Header
.Length
);
210 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
214 // If we didn't copy the new data to a stringpack yet
217 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
219 // Pointing to a new string pack location
221 SizeofLanguage
= StrSize (Language
);
222 SizeofString
= StrSize (String
);
223 StringPackBuffer
->Header
.Length
= (UINT32
)
225 sizeof (EFI_HII_STRING_PACK
) -
226 sizeof (EFI_STRING
) +
232 StringPackBuffer
->Header
.Type
= EFI_HII_STRING
;
233 StringPackBuffer
->LanguageNameString
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
234 StringPackBuffer
->PrintableLanguageName
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
235 StringPackBuffer
->Attributes
= 0;
236 PackDestination
[0] = (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
237 PackDestination
[1] = (UINT16
) (PackDestination
[0] + StrSize (Language
));
238 PackDestination
[2] = (UINT16
) 0;
241 // The first string location will be set to destination. The minimum number of strings
242 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
243 // and token 1 as the new string being added and and null entry for the stringpointers
245 Destination
= (UINT8
*) &PackDestination
[3];
248 // Copy the language name string to the new buffer
250 StrCpy ((CHAR16
*) Destination
, Language
);
253 // Advance the destination to the new empty spot
255 Destination
= Destination
+ StrSize (Language
);
258 // Copy the string to the new buffer
260 StrCpy ((CHAR16
*) Destination
, String
);
263 // Since we are starting with a new string pack - we know the new string is token 1
265 *StringToken
= (UINT16
) 1;
269 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
271 ZeroMem (StringBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
272 CopyMem (StringBuffer
, NewBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
275 // Free the newly created buffer since we don't need it anymore
277 FreePool (NewBuffer
);
282 Add op-code data to the FormBuffer.
284 @param FormBuffer Form buffer to be inserted to
285 @param OpCodeData Op-code data to be inserted
287 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
288 @retval EFI_SUCCESS Op-code data successfully inserted
294 IN OUT VOID
*OpCodeData
297 EFI_HII_PACK_HEADER
*NewBuffer
;
302 // Pre-allocate a buffer sufficient for us to work on.
303 // We will use it as a destination scratch pad to build data on
304 // and when complete shift the data back to the original buffer
306 NewBuffer
= AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE
);
307 if (NewBuffer
== NULL
) {
308 return EFI_OUT_OF_RESOURCES
;
312 // Copy the IFR Package header to the new buffer
314 Source
= (UINT8
*) FormBuffer
;
315 Destination
= (UINT8
*) NewBuffer
;
316 CopyMem (Destination
, Source
, sizeof (EFI_HII_PACK_HEADER
));
319 // Advance Source and Destination to next op-code
321 Source
= Source
+ sizeof (EFI_HII_PACK_HEADER
);
322 Destination
= Destination
+ sizeof (EFI_HII_PACK_HEADER
);
325 // Copy data to the new buffer until we run into the end_form
327 for (; ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->OpCode
!= FRAMEWORK_EFI_IFR_END_FORM_OP
;) {
329 // If the opcode is an end_form_set we better be creating and endform
330 // Nonetheless, we will add data before the end_form_set. This also provides
331 // for interesting behavior in the code we will run, but has no bad side-effects
332 // since we will possibly do a 0 byte copy in this particular end-case.
334 if (((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->OpCode
== FRAMEWORK_EFI_IFR_END_FORM_SET_OP
) {
339 // Copy data to new buffer
341 CopyMem (Destination
, Source
, ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
);
344 // Adjust Source/Destination to next op-code location
346 Destination
= Destination
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
;
347 Source
= Source
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
;
351 // Prior to the end_form is where we insert the new op-code data
353 CopyMem (Destination
, OpCodeData
, ((FRAMEWORK_EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
355 Destination
= Destination
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
356 NewBuffer
->Length
= (UINT32
) (NewBuffer
->Length
+ (UINT32
) (((FRAMEWORK_EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
));
359 // Copy end-form data to new buffer
361 CopyMem (Destination
, Source
, ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
);
364 // Copy end-formset data to new buffer
366 Destination
= Destination
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
;
367 Source
= Source
+ (UINTN
) ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
;
368 CopyMem (Destination
, Source
, ((FRAMEWORK_EFI_IFR_OP_HEADER
*) Source
)->Length
);
371 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
373 ZeroMem (FormBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
374 CopyMem (FormBuffer
, NewBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
377 // Free the newly created buffer since we don't need it anymore
379 FreePool (NewBuffer
);
384 Get the HII protocol interface.
386 @param Hii HII protocol interface
388 @return the statue of locating HII protocol
393 OUT EFI_HII_PROTOCOL
**Hii
399 // There should only be one HII protocol
401 Status
= gBS
->LocateProtocol (
402 &gEfiHiiProtocolGuid
,
411 Extract information pertaining to the HiiHandle.
413 @param HiiHandle Hii handle
414 @param ImageLength For input, length of DefaultImage;
415 For output, length of actually required
416 @param DefaultImage Image buffer prepared by caller
417 @param Guid Guid information about the form
419 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
420 @retval EFI_BUFFER_TOO_SMALL DefualtImage has no enough ImageLength
421 @retval EFI_SUCCESS Successfully extract data from Hii database.
425 ExtractDataFromHiiHandle (
426 IN FRAMEWORK_EFI_HII_HANDLE HiiHandle
,
427 IN OUT UINT16
*ImageLength
,
428 OUT UINT8
*DefaultImage
,
433 EFI_HII_PROTOCOL
*Hii
;
442 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
446 if (DefaultImage
== NULL
|| Guid
== NULL
) {
447 return EFI_INVALID_PARAMETER
;
450 Status
= GetHiiInterface (&Hii
);
451 if (EFI_ERROR (Status
)) {
456 // Allocate space for retrieval of IFR data
458 RawData
= AllocateZeroPool (DataLength
);
459 if (RawData
== NULL
) {
460 return EFI_OUT_OF_RESOURCES
;
464 // Get all the forms associated with this HiiHandle
466 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
467 if (EFI_ERROR (Status
)) {
471 // Allocate space for retrieval of IFR data
473 RawData
= AllocateZeroPool (DataLength
);
474 if (RawData
== NULL
) {
475 return EFI_OUT_OF_RESOURCES
;
479 // Get all the forms associated with this HiiHandle
481 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
487 // Point RawData to the beginning of the form data
489 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
491 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
492 switch (RawData
[Index
]) {
494 case FRAMEWORK_EFI_IFR_FORM_SET_OP
:
496 // Copy the GUID information from this handle
498 CopyGuid (Guid
, (GUID
*)(VOID
*)&((FRAMEWORK_EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
);
501 case FRAMEWORK_EFI_IFR_ONE_OF_OP
:
502 case FRAMEWORK_EFI_IFR_CHECKBOX_OP
:
503 case FRAMEWORK_EFI_IFR_NUMERIC_OP
:
504 case FRAMEWORK_EFI_IFR_DATE_OP
:
505 case FRAMEWORK_EFI_IFR_TIME_OP
:
506 case FRAMEWORK_EFI_IFR_PASSWORD_OP
:
507 case FRAMEWORK_EFI_IFR_STRING_OP
:
509 // Remember, multiple op-codes may reference the same item, so let's keep a running
510 // marker of what the highest QuestionId that wasn't zero length. This will accurately
511 // maintain the Size of the NvStore
513 if (((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
514 Temp
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
515 if (SizeOfNvStore
< Temp
) {
516 SizeOfNvStore
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
521 Index
= RawData
[Index
+ 1] + Index
;
525 // Return an error if buffer is too small
527 if (SizeOfNvStore
> *ImageLength
) {
529 *ImageLength
= (UINT16
) SizeOfNvStore
;
530 return EFI_BUFFER_TOO_SMALL
;
533 if (DefaultImage
!= NULL
) {
534 ZeroMem (DefaultImage
, SizeOfNvStore
);
538 // Copy the default image information to the user's buffer
540 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
541 switch (RawData
[Index
]) {
543 case FRAMEWORK_EFI_IFR_ONE_OF_OP
:
544 CachedStart
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
547 case FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP
:
548 if (((FRAMEWORK_EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& FRAMEWORK_EFI_IFR_FLAG_DEFAULT
) {
549 CopyMem (&DefaultImage
[CachedStart
], &((FRAMEWORK_EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
553 case FRAMEWORK_EFI_IFR_CHECKBOX_OP
:
554 DefaultImage
[((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((FRAMEWORK_EFI_IFR_CHECKBOX
*) &RawData
[Index
])->Flags
;
557 case FRAMEWORK_EFI_IFR_NUMERIC_OP
:
559 &DefaultImage
[((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
560 &((FRAMEWORK_EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
567 Index
= RawData
[Index
+ 1] + Index
;
570 *ImageLength
= (UINT16
) SizeOfNvStore
;
573 // Free our temporary repository of form data
581 Finds HII handle for given pack GUID previously registered with the HII.
583 @param HiiProtocol pointer to pointer to HII protocol interface.
584 If NULL, the interface will be found but not returned.
585 If it points to NULL, the interface will be found and
586 written back to the pointer that is pointed to.
587 @param Guid The GUID of the pack that registered with the HII.
589 @return Handle to the HII pack previously registered by the memory driver.
591 FRAMEWORK_EFI_HII_HANDLE
594 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
599 FRAMEWORK_EFI_HII_HANDLE
*HiiHandleBuffer
;
600 FRAMEWORK_EFI_HII_HANDLE HiiHandle
;
601 UINT16 HiiHandleBufferLength
;
602 UINT32 NumberOfHiiHandles
;
604 EFI_HII_PROTOCOL
*HiiProt
;
609 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
611 // The protocol has been passed in
613 HiiProt
= *HiiProtocol
;
615 gBS
->LocateProtocol (
616 &gEfiHiiProtocolGuid
,
620 if (HiiProt
== NULL
) {
624 if (HiiProtocol
!= NULL
) {
626 // Return back the HII protocol for the caller as promissed
628 *HiiProtocol
= HiiProt
;
634 HiiHandleBufferLength
= 10;
635 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
636 ASSERT (HiiHandleBuffer
!= NULL
);
639 // Get the Handles of the packages that were registered with Hii
641 Status
= HiiProt
->FindHandles (
643 &HiiHandleBufferLength
,
648 // Get a bigger bugffer if this one is to small, and try again
650 if (Status
== EFI_BUFFER_TOO_SMALL
) {
652 FreePool (HiiHandleBuffer
);
654 HiiHandleBuffer
= AllocatePool (HiiHandleBufferLength
);
655 ASSERT (HiiHandleBuffer
!= NULL
);
657 Status
= HiiProt
->FindHandles (
659 &HiiHandleBufferLength
,
664 if (EFI_ERROR (Status
)) {
668 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (FRAMEWORK_EFI_HII_HANDLE
);
671 // Iterate Hii handles and look for the one that matches our Guid
673 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
676 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
678 if (CompareGuid (&HiiGuid
, Guid
)) {
679 HiiHandle
= HiiHandleBuffer
[Index
];
685 FreePool (HiiHandleBuffer
);
690 Validate that the data associated with the HiiHandle in NVRAM is within
691 the reasonable parameters for that FormSet. Values for strings and passwords
692 are not verified due to their not having the equivalent of valid range settings.
694 @param HiiHandle Handle of the HII database entry to query
695 @param Results If return Status is EFI_SUCCESS, Results provides valid data
696 TRUE = NVRAM Data is within parameters
697 FALSE = NVRAM Data is NOT within parameters
699 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
700 @retval EFI_SUCCESS Data successfully validated
704 ValidateDataFromHiiHandle (
705 IN FRAMEWORK_EFI_HII_HANDLE HiiHandle
,
710 EFI_HII_PROTOCOL
*Hii
;
722 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
728 Status
= GetHiiInterface (&Hii
);
729 if (EFI_ERROR (Status
)) {
734 // Allocate space for retrieval of IFR data
736 RawData
= AllocateZeroPool (RawDataLength
);
737 if (RawData
== NULL
) {
738 return EFI_OUT_OF_RESOURCES
;
742 // Get all the forms associated with this HiiHandle
744 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
745 if (EFI_ERROR (Status
)) {
749 // Allocate space for retrieval of IFR data
751 RawData
= AllocateZeroPool (RawDataLength
);
752 if (RawData
== NULL
) {
753 return EFI_OUT_OF_RESOURCES
;
757 // Get all the forms associated with this HiiHandle
759 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
765 // Point RawData to the beginning of the form data
767 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
769 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
770 if (RawData
[Index
] == FRAMEWORK_EFI_IFR_FORM_SET_OP
) {
771 CopyGuid (&Guid
, (GUID
*)(VOID
*)&((FRAMEWORK_EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
);
774 Index
= RawData
[Index
+ 1] + Index
;
777 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
778 switch (RawData
[Index
]) {
780 case FRAMEWORK_EFI_IFR_FORM_SET_OP
:
783 case FRAMEWORK_EFI_IFR_ONE_OF_OP
:
784 case FRAMEWORK_EFI_IFR_CHECKBOX_OP
:
785 case FRAMEWORK_EFI_IFR_NUMERIC_OP
:
786 case FRAMEWORK_EFI_IFR_DATE_OP
:
787 case FRAMEWORK_EFI_IFR_TIME_OP
:
788 case FRAMEWORK_EFI_IFR_PASSWORD_OP
:
789 case FRAMEWORK_EFI_IFR_STRING_OP
:
791 // Remember, multiple op-codes may reference the same item, so let's keep a running
792 // marker of what the highest QuestionId that wasn't zero length. This will accurately
793 // maintain the Size of the NvStore
795 if (((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
796 Temp
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
797 if (SizeOfNvStore
< Temp
) {
798 SizeOfNvStore
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
803 Index
= RawData
[Index
+ 1] + Index
;
807 // Allocate memory for our File Form Tags
809 VariableData
= AllocateZeroPool (SizeOfNvStore
);
810 if (VariableData
== NULL
) {
812 return EFI_OUT_OF_RESOURCES
;
815 Status
= gRT
->GetVariable (
820 (VOID
*) VariableData
823 if (EFI_ERROR (Status
)) {
826 // If there is a variable that exists already and it is larger than what we calculated the
827 // storage needs to be, we must assume the variable size from GetVariable is correct and not
828 // allow the truncation of the variable. It is very possible that the user who created the IFR
829 // we are cracking is not referring to a variable that was in a previous map, however we cannot
830 // allow it's truncation.
832 if (Status
== EFI_BUFFER_TOO_SMALL
) {
834 // Free the buffer that was allocated that was too small
836 FreePool (VariableData
);
838 VariableData
= AllocatePool (SizeOfNvStore
);
839 if (VariableData
== NULL
) {
841 return EFI_OUT_OF_RESOURCES
;
844 Status
= gRT
->GetVariable (
849 (VOID
*) VariableData
855 // Walk through the form and see that the variable data it refers to is ok.
856 // This allows for the possibility of stale (obsoleted) data in the variable
857 // can be overlooked without causing an error
859 for (Index
= 0; RawData
[Index
] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP
;) {
860 switch (RawData
[Index
]) {
862 case FRAMEWORK_EFI_IFR_ONE_OF_OP
:
864 // A one_of has no data, its the option that does - cache the storage Id
866 CachedStart
= ((FRAMEWORK_EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
869 case FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP
:
871 // A one_of_option can be any value
873 if (VariableData
[CachedStart
] == ((FRAMEWORK_EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
878 case FRAMEWORK_EFI_IFR_END_ONE_OF_OP
:
880 // At this point lets make sure that the data value in the NVRAM matches one of the options
888 case FRAMEWORK_EFI_IFR_CHECKBOX_OP
:
890 // A checkbox is a boolean, so 0 and 1 are valid
891 // Remember, QuestionId corresponds to the offset location of the data in the variable
893 if (VariableData
[((FRAMEWORK_EFI_IFR_CHECKBOX
*) &RawData
[Index
])->QuestionId
] > 1) {
899 case FRAMEWORK_EFI_IFR_NUMERIC_OP
:
900 if ((VariableData
[((FRAMEWORK_EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((FRAMEWORK_EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
901 (VariableData
[((FRAMEWORK_EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((FRAMEWORK_EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
909 Index
= RawData
[Index
+ 1] + Index
;
914 // Free our temporary repository of form data
917 FreePool (VariableData
);