2 Copyright (c) 2004 - 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
20 #include "IfrLibrary.h"
30 Determine what is the current language setting
34 Lang - Pointer of system language
48 // Getting the system language and placing it into our Global Data
50 Size
= sizeof (Language
);
52 Status
= gRT
->GetVariable (
54 &gEfiGlobalVariableGuid
,
60 if (EFI_ERROR (Status
)) {
61 EfiAsciiStrCpy (Language
, "eng");
64 for (Index
= 0; Index
< 3; Index
++) {
66 // Bitwise AND ascii value with 0xDF yields an uppercase value.
67 // Sign extend into a unicode value
69 Lang
[Index
] = (CHAR16
) (Language
[Index
] & 0xDF);
73 // Null-terminate the value
83 IN VOID
*StringBuffer
,
86 IN OUT STRING_REF
*StringToken
92 Add a string to the incoming buffer and return the token and offset data
96 StringBuffer - The incoming buffer
98 Language - Currrent language
100 String - The string to be added
102 StringToken - The index where the string placed
106 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
108 EFI_SUCCESS - String successfully added to the incoming buffer
112 EFI_HII_STRING_PACK
*StringPack
;
113 EFI_HII_STRING_PACK
*StringPackBuffer
;
116 RELOFST
*PackDestination
;
122 StringPack
= (EFI_HII_STRING_PACK
*) StringBuffer
;
126 // Pre-allocate a buffer sufficient for us to work on.
127 // We will use it as a destination scratch pad to build data on
128 // and when complete shift the data back to the original buffer
130 NewBuffer
= EfiLibAllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE
);
131 if (NewBuffer
== NULL
) {
132 return EFI_OUT_OF_RESOURCES
;
135 StringPackBuffer
= (EFI_HII_STRING_PACK
*) NewBuffer
;
138 // StringPack is terminated with a length 0 entry
140 for (; StringPack
->Header
.Length
!= 0;) {
142 // If this stringpack's language is same as CurrentLanguage, use it
144 if (EfiCompareMem ((VOID
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
, 3) == 0) {
146 // We have some data in this string pack, copy the string package up to the string data
148 EfiCopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, sizeof (StringPack
));
151 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
153 StringPackBuffer
->LanguageNameString
= (UINT16
) (StringPackBuffer
->LanguageNameString
+ (UINT16
) sizeof (RELOFST
));
154 StringPackBuffer
->PrintableLanguageName
= (UINT16
) (StringPackBuffer
->PrintableLanguageName
+ (UINT16
) sizeof (RELOFST
));
156 PackSource
= (RELOFST
*) (StringPack
+ 1);
157 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
158 for (Index
= 0; PackSource
[Index
] != 0x0000; Index
++) {
160 // Copy the stringpointers from old to new buffer
161 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
163 PackDestination
[Index
] = (UINT16
) (PackDestination
[Index
] + sizeof (RELOFST
));
167 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
169 PackDestination
[Index
] = (UINT16
)(PackDestination
[Index
-1] +
170 EfiStrSize((CHAR16
*)((CHAR8
*)(StringPack
) + PackSource
[Index
-1])));
171 PackDestination
[Index
+ 1] = (UINT16
) 0;
174 // Index is the token value for the new string
176 *StringToken
= (UINT16
) Index
;
179 // Source now points to the beginning of the old buffer strings
180 // Destination now points to the beginning of the new buffer strings
182 Source
= (UINT8
*) &PackSource
[Index
+ 1];
183 Destination
= (UINT8
*) &PackDestination
[Index
+ 2];
186 // This should copy all the strings from the old buffer to the new buffer
188 for (; Index
!= 0; Index
--) {
190 // Copy Source string to destination buffer
192 EfiStrCpy ((CHAR16
*) Destination
, (CHAR16
*) Source
);
195 // Adjust the source/destination to the next string location
197 Destination
= Destination
+ EfiStrSize ((CHAR16
*) Source
);
198 Source
= Source
+ EfiStrSize ((CHAR16
*) Source
);
202 // This copies the new string to the destination buffer
204 EfiStrCpy ((CHAR16
*) Destination
, (CHAR16
*) String
);
207 // Adjust the size of the changed string pack by adding the size of the new string
208 // along with the size of the additional offset entry for the new string
210 StringPackBuffer
->Header
.Length
= (UINT32
) ((UINTN
) StringPackBuffer
->Header
.Length
+ EfiStrSize (String
) + sizeof (RELOFST
));
213 // Advance the buffers to point to the next spots.
215 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPackBuffer
->Header
.Length
);
216 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
221 // This isn't the language of the stringpack we were asked to add a string to
222 // so we need to copy it to the new buffer.
224 EfiCopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, StringPack
->Header
.Length
);
227 // Advance the buffers to point to the next spots.
229 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPack
->Header
.Length
);
230 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
234 // If we didn't copy the new data to a stringpack yet
237 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
239 // Pointing to a new string pack location
241 StringPackBuffer
->Header
.Length
= (UINT32
)
243 sizeof (EFI_HII_STRING_PACK
) -
244 sizeof (EFI_STRING
) +
247 EfiStrSize (Language
) +
250 StringPackBuffer
->Header
.Type
= EFI_HII_STRING
;
251 StringPackBuffer
->LanguageNameString
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
252 StringPackBuffer
->PrintableLanguageName
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
253 StringPackBuffer
->Attributes
= 0;
254 PackDestination
[0] = (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
255 PackDestination
[1] = (UINT16
) (PackDestination
[0] + EfiStrSize (Language
));
256 PackDestination
[2] = (UINT16
) 0;
259 // The first string location will be set to destination. The minimum number of strings
260 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
261 // and token 1 as the new string being added and and null entry for the stringpointers
263 Destination
= (CHAR8
*) &PackDestination
[3];
266 // Copy the language name string to the new buffer
268 EfiStrCpy ((CHAR16
*) Destination
, Language
);
271 // Advance the destination to the new empty spot
273 Destination
= Destination
+ EfiStrSize (Language
);
276 // Copy the string to the new buffer
278 EfiStrCpy ((CHAR16
*) Destination
, String
);
281 // Since we are starting with a new string pack - we know the new string is token 1
283 *StringToken
= (UINT16
) 1;
287 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
289 EfiZeroMem (StringBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
290 EfiCopyMem (StringBuffer
, NewBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
293 // Free the newly created buffer since we don't need it anymore
295 gBS
->FreePool (NewBuffer
);
303 IN OUT VOID
*OpCodeData
309 Add op-code data to the FormBuffer
313 FormBuffer - Form buffer to be inserted to
315 OpCodeData - Op-code data to be inserted
319 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
321 EFI_SUCCESS - Op-code data successfully inserted
325 EFI_HII_PACK_HEADER
*NewBuffer
;
330 // Pre-allocate a buffer sufficient for us to work on.
331 // We will use it as a destination scratch pad to build data on
332 // and when complete shift the data back to the original buffer
334 NewBuffer
= EfiLibAllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE
);
335 if (NewBuffer
== NULL
) {
336 return EFI_OUT_OF_RESOURCES
;
339 Source
= (UINT8
*) FormBuffer
;
340 Destination
= (UINT8
*) NewBuffer
;
343 // Copy the IFR Package header to the new buffer
345 EfiCopyMem (Destination
, Source
, sizeof (EFI_HII_PACK_HEADER
));
348 // Advance Source and Destination to next op-code
350 Source
= Source
+ sizeof (EFI_HII_PACK_HEADER
);
351 Destination
= Destination
+ sizeof (EFI_HII_PACK_HEADER
);
354 // Copy data to the new buffer until we run into the end_form
356 for (; ((EFI_IFR_OP_HEADER
*) Source
)->OpCode
!= EFI_IFR_END_FORM_OP
;) {
358 // If the this opcode is an end_form_set we better be creating and endform
359 // Nonetheless, we will add data before the end_form_set. This also provides
360 // for interesting behavior in the code we will run, but has no bad side-effects
361 // since we will possibly do a 0 byte copy in this particular end-case.
363 if (((EFI_IFR_OP_HEADER
*) Source
)->OpCode
== EFI_IFR_END_FORM_SET_OP
) {
368 // Copy data to new buffer
370 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
373 // Adjust Source/Destination to next op-code location
375 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
376 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
380 // Prior to the end_form is where we insert the new op-code data
382 EfiCopyMem (Destination
, OpCodeData
, ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
383 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
385 NewBuffer
->Length
= (UINT32
) (NewBuffer
->Length
+ (UINT32
) (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
));
388 // Copy end-form data to new buffer
390 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
393 // Adjust Source/Destination to next op-code location
395 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
396 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
399 // Copy end-formset data to new buffer
401 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
404 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
406 EfiZeroMem (FormBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
407 EfiCopyMem (FormBuffer
, NewBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
410 // Free the newly created buffer since we don't need it anymore
412 gBS
->FreePool (NewBuffer
);
419 OUT EFI_HII_PROTOCOL
**Hii
425 Get the HII protocol interface
429 Hii - HII protocol interface
440 // There should only be one HII protocol
442 Status
= gBS
->LocateProtocol (
443 &gEfiHiiProtocolGuid
,
453 ExtractDataFromHiiHandle (
454 IN EFI_HII_HANDLE HiiHandle
,
455 IN OUT UINT16
*ImageLength
,
456 OUT UINT8
*DefaultImage
,
463 Extract information pertaining to the HiiHandle
467 HiiHandle - Hii handle
469 ImageLength - For input, length of DefaultImage;
470 For output, length of actually required
472 DefaultImage - Image buffer prepared by caller
474 Guid - Guid information about the form
478 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
480 EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
482 EFI_SUCCESS - Successfully extract data from Hii database.
488 EFI_HII_PROTOCOL
*Hii
;
497 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
501 Status
= GetHiiInterface (&Hii
);
503 if (EFI_ERROR (Status
)) {
508 // Allocate space for retrieval of IFR data
510 RawData
= EfiLibAllocateZeroPool ((UINTN
) DataLength
);
511 if (RawData
== NULL
) {
512 return EFI_OUT_OF_RESOURCES
;
516 // Get all the forms associated with this HiiHandle
518 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
520 if (EFI_ERROR (Status
)) {
521 gBS
->FreePool (RawData
);
524 // Allocate space for retrieval of IFR data
526 RawData
= EfiLibAllocateZeroPool ((UINTN
) DataLength
);
527 if (RawData
== NULL
) {
528 return EFI_OUT_OF_RESOURCES
;
532 // Get all the forms associated with this HiiHandle
534 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
540 // Point RawData to the beginning of the form data
542 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
544 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
545 switch (RawData
[Index
]) {
546 case EFI_IFR_FORM_SET_OP
:
548 // Copy the GUID information from this handle
550 EfiCopyMem (Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
553 case EFI_IFR_ONE_OF_OP
:
554 case EFI_IFR_CHECKBOX_OP
:
555 case EFI_IFR_NUMERIC_OP
:
556 case EFI_IFR_DATE_OP
:
557 case EFI_IFR_TIME_OP
:
558 case EFI_IFR_PASSWORD_OP
:
559 case EFI_IFR_STRING_OP
:
561 // Remember, multiple op-codes may reference the same item, so let's keep a running
562 // marker of what the highest QuestionId that wasn't zero length. This will accurately
563 // maintain the Size of the NvStore
565 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
566 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
567 if (SizeOfNvStore
< Temp
) {
568 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
573 Index
= RawData
[Index
+ 1] + Index
;
577 // Return an error if buffer is too small
579 if (SizeOfNvStore
> *ImageLength
) {
580 gBS
->FreePool (OldData
);
581 *ImageLength
= (UINT16
) SizeOfNvStore
;
582 return EFI_BUFFER_TOO_SMALL
;
585 EfiZeroMem (DefaultImage
, SizeOfNvStore
);
588 // Copy the default image information to the user's buffer
590 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
591 switch (RawData
[Index
]) {
592 case EFI_IFR_ONE_OF_OP
:
593 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
596 case EFI_IFR_ONE_OF_OPTION_OP
:
597 if (((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& EFI_IFR_FLAG_DEFAULT
) {
598 EfiCopyMem (&DefaultImage
[CachedStart
], &((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
602 case EFI_IFR_CHECKBOX_OP
:
603 DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((EFI_IFR_CHECK_BOX
*) &RawData
[Index
])->Flags
;
606 case EFI_IFR_NUMERIC_OP
:
608 &DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
609 &((EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
616 Index
= RawData
[Index
+ 1] + Index
;
619 *ImageLength
= (UINT16
) SizeOfNvStore
;
622 // Free our temporary repository of form data
624 gBS
->FreePool (OldData
);
632 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
638 Finds HII handle for given pack GUID previously registered with the HII.
641 HiiProtocol - pointer to pointer to HII protocol interface.
642 If NULL, the interface will be found but not returned.
643 If it points to NULL, the interface will be found and
644 written back to the pointer that is pointed to.
645 Guid - The GUID of the pack that registered with the HII.
648 Handle to the HII pack previously registered by the memory driver.
654 EFI_HII_HANDLE
*HiiHandleBuffer
;
655 EFI_HII_HANDLE HiiHandle
;
656 UINT16 HiiHandleBufferLength
;
657 UINT32 NumberOfHiiHandles
;
659 EFI_HII_PROTOCOL
*HiiProt
;
664 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
666 // The protocol has been passed in
668 HiiProt
= *HiiProtocol
;
670 gBS
->LocateProtocol (
671 &gEfiHiiProtocolGuid
,
675 if (HiiProt
== NULL
) {
679 if (HiiProtocol
!= NULL
) {
681 // Return back the HII protocol for the caller as promissed
683 *HiiProtocol
= HiiProt
;
689 HiiHandleBufferLength
= 10;
690 HiiHandleBuffer
= EfiLibAllocatePool (HiiHandleBufferLength
);
691 ASSERT (HiiHandleBuffer
!= NULL
);
694 // Get the Handles of the packages that were registered with Hii
696 Status
= HiiProt
->FindHandles (
698 &HiiHandleBufferLength
,
703 // Get a bigger bugffer if this one is to small, and try again
705 if (Status
== EFI_BUFFER_TOO_SMALL
) {
707 gBS
->FreePool (HiiHandleBuffer
);
709 HiiHandleBuffer
= EfiLibAllocatePool (HiiHandleBufferLength
);
710 ASSERT (HiiHandleBuffer
!= NULL
);
712 Status
= HiiProt
->FindHandles (
714 &HiiHandleBufferLength
,
719 if (EFI_ERROR (Status
)) {
723 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
726 // Iterate Hii handles and look for the one that matches our Guid
728 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
731 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
733 if (EfiCompareGuid (&HiiGuid
, Guid
)) {
735 HiiHandle
= HiiHandleBuffer
[Index
];
741 gBS
->FreePool (HiiHandleBuffer
);
747 ValidateDataFromHiiHandle (
748 IN EFI_HII_HANDLE HiiHandle
,
755 Validate that the data associated with the HiiHandle in NVRAM is within
756 the reasonable parameters for that FormSet. Values for strings and passwords
757 are not verified due to their not having the equivalent of valid range settings.
761 HiiHandle - Handle of the HII database entry to query
763 Results - If return Status is EFI_SUCCESS, Results provides valid data
764 TRUE = NVRAM Data is within parameters
765 FALSE = NVRAM Data is NOT within parameters
769 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
771 EFI_SUCCESS - Data successfully validated
775 EFI_HII_PROTOCOL
*Hii
;
787 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
793 Status
= GetHiiInterface (&Hii
);
795 if (EFI_ERROR (Status
)) {
800 // Allocate space for retrieval of IFR data
802 RawData
= EfiLibAllocateZeroPool (RawDataLength
);
803 if (RawData
== NULL
) {
804 return EFI_OUT_OF_RESOURCES
;
808 // Get all the forms associated with this HiiHandle
810 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
812 if (EFI_ERROR (Status
)) {
813 gBS
->FreePool (RawData
);
816 // Allocate space for retrieval of IFR data
818 RawData
= EfiLibAllocateZeroPool (RawDataLength
);
819 if (RawData
== NULL
) {
820 return EFI_OUT_OF_RESOURCES
;
824 // Get all the forms associated with this HiiHandle
826 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
832 // Point RawData to the beginning of the form data
834 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
836 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
837 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
838 EfiCopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
842 Index
= RawData
[Index
+ 1] + Index
;
845 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
846 switch (RawData
[Index
]) {
847 case EFI_IFR_FORM_SET_OP
:
850 case EFI_IFR_ONE_OF_OP
:
851 case EFI_IFR_CHECKBOX_OP
:
852 case EFI_IFR_NUMERIC_OP
:
853 case EFI_IFR_DATE_OP
:
854 case EFI_IFR_TIME_OP
:
855 case EFI_IFR_PASSWORD_OP
:
856 case EFI_IFR_STRING_OP
:
858 // Remember, multiple op-codes may reference the same item, so let's keep a running
859 // marker of what the highest QuestionId that wasn't zero length. This will accurately
860 // maintain the Size of the NvStore
862 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
863 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
864 if (SizeOfNvStore
< Temp
) {
865 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
870 Index
= RawData
[Index
+ 1] + Index
;
874 // Allocate memory for our File Form Tags
876 VariableData
= EfiLibAllocateZeroPool (SizeOfNvStore
);
877 if (VariableData
== NULL
) {
878 return EFI_OUT_OF_RESOURCES
;
881 Status
= gRT
->GetVariable (
886 (VOID
*) VariableData
889 if (EFI_ERROR (Status
)) {
892 // If there is a variable that exists already and it is larger than what we calculated the
893 // storage needs to be, we must assume the variable size from GetVariable is correct and not
894 // allow the truncation of the variable. It is very possible that the user who created the IFR
895 // we are cracking is not referring to a variable that was in a previous map, however we cannot
896 // allow it's truncation.
898 if (Status
== EFI_BUFFER_TOO_SMALL
) {
900 // Free the buffer that was allocated that was too small
902 gBS
->FreePool (VariableData
);
904 VariableData
= EfiLibAllocatePool (SizeOfNvStore
);
905 if (VariableData
== NULL
) {
906 return EFI_OUT_OF_RESOURCES
;
909 Status
= gRT
->GetVariable (
914 (VOID
*) VariableData
920 // Walk through the form and see that the variable data it refers to is ok.
921 // This allows for the possibility of stale (obsoleted) data in the variable
922 // can be overlooked without causing an error
924 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
925 switch (RawData
[Index
]) {
926 case EFI_IFR_ONE_OF_OP
:
928 // A one_of has no data, its the option that does - cache the storage Id
930 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
933 case EFI_IFR_ONE_OF_OPTION_OP
:
935 // A one_of_option can be any value
937 if (VariableData
[CachedStart
] == ((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
942 case EFI_IFR_END_ONE_OF_OP
:
944 // At this point lets make sure that the data value in the NVRAM matches one of the options
952 case EFI_IFR_CHECKBOX_OP
:
954 // A checkbox is a boolean, so 0 and 1 are valid
955 // Remember, QuestionId corresponds to the offset location of the data in the variable
957 if (VariableData
[((EFI_IFR_CHECK_BOX
*) &RawData
[Index
])->QuestionId
] > 1) {
963 case EFI_IFR_NUMERIC_OP
:
964 if ((VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
965 (VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
973 Index
= RawData
[Index
+ 1] + Index
;
977 // Free our temporary repository of form data
979 gBS
->FreePool (OldData
);
980 gBS
->FreePool (VariableData
);
987 IN UINTN NumberOfPackages
,
995 Assemble EFI_HII_PACKAGES according to the passed in packages.
999 NumberOfPackages - Number of packages.
1000 GuidId - Package GUID.
1004 Pointer of EFI_HII_PACKAGES.
1009 EFI_HII_PACKAGES
*HiiPackages
;
1013 ASSERT (NumberOfPackages
> 0);
1015 HiiPackages
= EfiLibAllocateZeroPool (sizeof (EFI_HII_PACKAGES
) + NumberOfPackages
* sizeof (VOID
*));
1017 HiiPackages
->GuidId
= GuidId
;
1018 HiiPackages
->NumberOfPackages
= NumberOfPackages
;
1019 Package
= (VOID
**) (((UINT8
*) HiiPackages
) + sizeof (EFI_HII_PACKAGES
));
1021 VA_START (args
, GuidId
);
1023 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
1024 *Package
= VA_ARG (args
, VOID
*);