2 Copyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>
3 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
, (CHAR8
*) "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
81 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
84 IN VOID
*StringBuffer
,
87 IN OUT STRING_REF
*StringToken
93 Add a string to the incoming buffer and return the token and offset data
97 StringBuffer - The incoming buffer
99 Language - Currrent language
101 String - The string to be added
103 StringToken - The index where the string placed
107 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
109 EFI_SUCCESS - String successfully added to the incoming buffer
113 EFI_HII_STRING_PACK
*StringPack
;
114 EFI_HII_STRING_PACK
*StringPackBuffer
;
117 RELOFST
*PackDestination
;
122 UINTN SizeofLanguage
;
125 StringPack
= (EFI_HII_STRING_PACK
*) StringBuffer
;
129 // Pre-allocate a buffer sufficient for us to work on.
130 // We will use it as a destination scratch pad to build data on
131 // and when complete shift the data back to the original buffer
133 NewBuffer
= EfiLibAllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE
);
134 if (NewBuffer
== NULL
) {
135 return EFI_OUT_OF_RESOURCES
;
138 StringPackBuffer
= (EFI_HII_STRING_PACK
*) NewBuffer
;
141 // StringPack is terminated with a length 0 entry
143 for (; StringPack
->Header
.Length
!= 0;) {
145 // If this stringpack's language is same as CurrentLanguage, use it
147 if (EfiCompareMem ((VOID
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
, 3) == 0) {
149 // We have some data in this string pack, copy the string package up to the string data
151 EfiCopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, sizeof (StringPack
));
154 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
156 StringPackBuffer
->LanguageNameString
= (UINT16
) (StringPackBuffer
->LanguageNameString
+ (UINT16
) sizeof (RELOFST
));
157 StringPackBuffer
->PrintableLanguageName
= (UINT16
) (StringPackBuffer
->PrintableLanguageName
+ (UINT16
) sizeof (RELOFST
));
159 PackSource
= (RELOFST
*) (StringPack
+ 1);
160 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
161 for (Index
= 0; PackSource
[Index
] != 0x0000; Index
++) {
163 // Copy the stringpointers from old to new buffer
164 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
166 PackDestination
[Index
] = (UINT16
) (PackDestination
[Index
] + sizeof (RELOFST
));
170 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
172 PackDestination
[Index
] = (UINT16
)(PackDestination
[Index
-1] +
173 EfiStrSize((CHAR16
*)((CHAR8
*)(StringPack
) + PackSource
[Index
-1])));
174 PackDestination
[Index
+ 1] = (UINT16
) 0;
177 // Index is the token value for the new string
179 *StringToken
= (UINT16
) Index
;
182 // Source now points to the beginning of the old buffer strings
183 // Destination now points to the beginning of the new buffer strings
185 Source
= (UINT8
*) &PackSource
[Index
+ 1];
186 Destination
= (UINT8
*) &PackDestination
[Index
+ 2];
189 // This should copy all the strings from the old buffer to the new buffer
191 for (; Index
!= 0; Index
--) {
193 // Copy Source string to destination buffer
195 EfiStrCpy ((CHAR16
*) Destination
, (CHAR16
*) Source
);
198 // Adjust the source/destination to the next string location
200 Destination
= Destination
+ EfiStrSize ((CHAR16
*) Source
);
201 Source
= Source
+ EfiStrSize ((CHAR16
*) Source
);
205 // This copies the new string to the destination buffer
207 EfiStrCpy ((CHAR16
*) Destination
, (CHAR16
*) String
);
210 // Adjust the size of the changed string pack by adding the size of the new string
211 // along with the size of the additional offset entry for the new string
213 StringPackBuffer
->Header
.Length
= (UINT32
) ((UINTN
) StringPackBuffer
->Header
.Length
+ EfiStrSize (String
) + sizeof (RELOFST
));
216 // Advance the buffers to point to the next spots.
218 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPackBuffer
->Header
.Length
);
219 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
224 // This isn't the language of the stringpack we were asked to add a string to
225 // so we need to copy it to the new buffer.
227 EfiCopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, StringPack
->Header
.Length
);
230 // Advance the buffers to point to the next spots.
232 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPack
->Header
.Length
);
233 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
237 // If we didn't copy the new data to a stringpack yet
240 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
242 // Pointing to a new string pack location
244 SizeofLanguage
= EfiStrSize (Language
);
245 SizeofString
= EfiStrSize (String
);
246 StringPackBuffer
->Header
.Length
= (UINT32
)
248 sizeof (EFI_HII_STRING_PACK
) -
249 sizeof (EFI_STRING
) +
255 StringPackBuffer
->Header
.Type
= EFI_HII_STRING
;
256 StringPackBuffer
->LanguageNameString
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
257 StringPackBuffer
->PrintableLanguageName
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
258 StringPackBuffer
->Attributes
= 0;
259 PackDestination
[0] = (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
260 PackDestination
[1] = (UINT16
) (PackDestination
[0] + EfiStrSize (Language
));
261 PackDestination
[2] = (UINT16
) 0;
264 // The first string location will be set to destination. The minimum number of strings
265 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
266 // and token 1 as the new string being added and and null entry for the stringpointers
268 Destination
= (CHAR8
*) &PackDestination
[3];
271 // Copy the language name string to the new buffer
273 EfiStrCpy ((CHAR16
*) Destination
, Language
);
276 // Advance the destination to the new empty spot
278 Destination
= Destination
+ EfiStrSize (Language
);
281 // Copy the string to the new buffer
283 EfiStrCpy ((CHAR16
*) Destination
, String
);
286 // Since we are starting with a new string pack - we know the new string is token 1
288 *StringToken
= (UINT16
) 1;
292 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
294 EfiZeroMem (StringBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
295 EfiCopyMem (StringBuffer
, NewBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
298 // Free the newly created buffer since we don't need it anymore
300 gBS
->FreePool (NewBuffer
);
308 IN OUT VOID
*OpCodeData
314 Add op-code data to the FormBuffer
318 FormBuffer - Form buffer to be inserted to
320 OpCodeData - Op-code data to be inserted
324 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
326 EFI_SUCCESS - Op-code data successfully inserted
330 EFI_HII_PACK_HEADER
*NewBuffer
;
335 // Pre-allocate a buffer sufficient for us to work on.
336 // We will use it as a destination scratch pad to build data on
337 // and when complete shift the data back to the original buffer
339 NewBuffer
= EfiLibAllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE
);
340 if (NewBuffer
== NULL
) {
341 return EFI_OUT_OF_RESOURCES
;
344 Source
= (UINT8
*) FormBuffer
;
345 Destination
= (UINT8
*) NewBuffer
;
348 // Copy the IFR Package header to the new buffer
350 EfiCopyMem (Destination
, Source
, sizeof (EFI_HII_PACK_HEADER
));
353 // Advance Source and Destination to next op-code
355 Source
= Source
+ sizeof (EFI_HII_PACK_HEADER
);
356 Destination
= Destination
+ sizeof (EFI_HII_PACK_HEADER
);
359 // Copy data to the new buffer until we run into the end_form
361 for (; ((EFI_IFR_OP_HEADER
*) Source
)->OpCode
!= EFI_IFR_END_FORM_OP
;) {
363 // If the this opcode is an end_form_set we better be creating and endform
364 // Nonetheless, we will add data before the end_form_set. This also provides
365 // for interesting behavior in the code we will run, but has no bad side-effects
366 // since we will possibly do a 0 byte copy in this particular end-case.
368 if (((EFI_IFR_OP_HEADER
*) Source
)->OpCode
== EFI_IFR_END_FORM_SET_OP
) {
373 // Copy data to new buffer
375 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
378 // Adjust Source/Destination to next op-code location
380 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
381 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
385 // Prior to the end_form is where we insert the new op-code data
387 EfiCopyMem (Destination
, OpCodeData
, ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
388 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
390 NewBuffer
->Length
= (UINT32
) (NewBuffer
->Length
+ (UINT32
) (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
));
393 // Copy end-form data to new buffer
395 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
398 // Adjust Source/Destination to next op-code location
400 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
401 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
404 // Copy end-formset data to new buffer
406 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
409 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
411 EfiZeroMem (FormBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
412 EfiCopyMem (FormBuffer
, NewBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
415 // Free the newly created buffer since we don't need it anymore
417 gBS
->FreePool (NewBuffer
);
425 OUT EFI_HII_PROTOCOL
**Hii
431 Get the HII protocol interface
435 Hii - HII protocol interface
446 // There should only be one HII protocol
448 Status
= gBS
->LocateProtocol (
449 &gEfiHiiProtocolGuid
,
459 ExtractDataFromHiiHandle (
460 IN EFI_HII_HANDLE HiiHandle
,
461 IN OUT UINT16
*ImageLength
,
462 OUT UINT8
*DefaultImage
,
469 Extract information pertaining to the HiiHandle
473 HiiHandle - Hii handle
475 ImageLength - For input, length of DefaultImage;
476 For output, length of actually required
478 DefaultImage - Image buffer prepared by caller
480 Guid - Guid information about the form
484 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
486 EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
488 EFI_SUCCESS - Successfully extract data from Hii database.
494 EFI_HII_PROTOCOL
*Hii
;
503 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
507 Status
= GetHiiInterface (&Hii
);
509 if (EFI_ERROR (Status
)) {
514 // Allocate space for retrieval of IFR data
516 RawData
= EfiLibAllocateZeroPool ((UINTN
) DataLength
);
517 if (RawData
== NULL
) {
518 return EFI_OUT_OF_RESOURCES
;
522 // Get all the forms associated with this HiiHandle
524 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
526 if (EFI_ERROR (Status
)) {
527 gBS
->FreePool (RawData
);
530 // Allocate space for retrieval of IFR data
532 RawData
= EfiLibAllocateZeroPool ((UINTN
) DataLength
);
533 if (RawData
== NULL
) {
534 return EFI_OUT_OF_RESOURCES
;
538 // Get all the forms associated with this HiiHandle
540 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
546 // Point RawData to the beginning of the form data
548 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
550 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
551 switch (RawData
[Index
]) {
552 case EFI_IFR_FORM_SET_OP
:
554 // Copy the GUID information from this handle
556 EfiCopyMem (Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
559 case EFI_IFR_ONE_OF_OP
:
560 case EFI_IFR_CHECKBOX_OP
:
561 case EFI_IFR_NUMERIC_OP
:
562 case EFI_IFR_DATE_OP
:
563 case EFI_IFR_TIME_OP
:
564 case EFI_IFR_PASSWORD_OP
:
565 case EFI_IFR_STRING_OP
:
567 // Remember, multiple op-codes may reference the same item, so let's keep a running
568 // marker of what the highest QuestionId that wasn't zero length. This will accurately
569 // maintain the Size of the NvStore
571 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
572 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
573 if (SizeOfNvStore
< Temp
) {
574 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
579 Index
= RawData
[Index
+ 1] + Index
;
583 // Return an error if buffer is too small
585 if (SizeOfNvStore
> *ImageLength
) {
586 gBS
->FreePool (OldData
);
587 *ImageLength
= (UINT16
) SizeOfNvStore
;
588 return EFI_BUFFER_TOO_SMALL
;
591 EfiZeroMem (DefaultImage
, SizeOfNvStore
);
594 // Copy the default image information to the user's buffer
596 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
597 switch (RawData
[Index
]) {
598 case EFI_IFR_ONE_OF_OP
:
599 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
602 case EFI_IFR_ONE_OF_OPTION_OP
:
603 if (((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& EFI_IFR_FLAG_DEFAULT
) {
604 EfiCopyMem (&DefaultImage
[CachedStart
], &((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
608 case EFI_IFR_CHECKBOX_OP
:
609 DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((EFI_IFR_CHECK_BOX
*) &RawData
[Index
])->Flags
;
612 case EFI_IFR_NUMERIC_OP
:
614 &DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
615 &((EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
622 Index
= RawData
[Index
+ 1] + Index
;
625 *ImageLength
= (UINT16
) SizeOfNvStore
;
628 // Free our temporary repository of form data
630 gBS
->FreePool (OldData
);
638 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
644 Finds HII handle for given pack GUID previously registered with the HII.
647 HiiProtocol - pointer to pointer to HII protocol interface.
648 If NULL, the interface will be found but not returned.
649 If it points to NULL, the interface will be found and
650 written back to the pointer that is pointed to.
651 Guid - The GUID of the pack that registered with the HII.
654 Handle to the HII pack previously registered by the memory driver.
660 EFI_HII_HANDLE
*HiiHandleBuffer
;
661 EFI_HII_HANDLE HiiHandle
;
662 UINT16 HiiHandleBufferLength
;
663 UINT32 NumberOfHiiHandles
;
665 EFI_HII_PROTOCOL
*HiiProt
;
670 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
672 // The protocol has been passed in
674 HiiProt
= *HiiProtocol
;
676 gBS
->LocateProtocol (
677 &gEfiHiiProtocolGuid
,
681 if (HiiProt
== NULL
) {
685 if (HiiProtocol
!= NULL
) {
687 // Return back the HII protocol for the caller as promissed
689 *HiiProtocol
= HiiProt
;
695 HiiHandleBufferLength
= 10;
696 HiiHandleBuffer
= EfiLibAllocatePool (HiiHandleBufferLength
);
697 ASSERT (HiiHandleBuffer
!= NULL
);
700 // Get the Handles of the packages that were registered with Hii
702 Status
= HiiProt
->FindHandles (
704 &HiiHandleBufferLength
,
709 // Get a bigger bugffer if this one is to small, and try again
711 if (Status
== EFI_BUFFER_TOO_SMALL
) {
713 gBS
->FreePool (HiiHandleBuffer
);
715 HiiHandleBuffer
= EfiLibAllocatePool (HiiHandleBufferLength
);
716 ASSERT (HiiHandleBuffer
!= NULL
);
718 Status
= HiiProt
->FindHandles (
720 &HiiHandleBufferLength
,
725 if (EFI_ERROR (Status
)) {
729 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
732 // Iterate Hii handles and look for the one that matches our Guid
734 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
737 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
739 if (EfiCompareGuid (&HiiGuid
, Guid
)) {
741 HiiHandle
= HiiHandleBuffer
[Index
];
747 gBS
->FreePool (HiiHandleBuffer
);
751 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
753 ValidateDataFromHiiHandle (
754 IN EFI_HII_HANDLE HiiHandle
,
761 Validate that the data associated with the HiiHandle in NVRAM is within
762 the reasonable parameters for that FormSet. Values for strings and passwords
763 are not verified due to their not having the equivalent of valid range settings.
767 HiiHandle - Handle of the HII database entry to query
769 Results - If return Status is EFI_SUCCESS, Results provides valid data
770 TRUE = NVRAM Data is within parameters
771 FALSE = NVRAM Data is NOT within parameters
775 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
777 EFI_SUCCESS - Data successfully validated
781 EFI_HII_PROTOCOL
*Hii
;
793 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
799 Status
= GetHiiInterface (&Hii
);
801 if (EFI_ERROR (Status
)) {
806 // Allocate space for retrieval of IFR data
808 RawData
= EfiLibAllocateZeroPool (RawDataLength
);
809 if (RawData
== NULL
) {
810 return EFI_OUT_OF_RESOURCES
;
814 // Get all the forms associated with this HiiHandle
816 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
818 if (EFI_ERROR (Status
)) {
819 gBS
->FreePool (RawData
);
822 // Allocate space for retrieval of IFR data
824 RawData
= EfiLibAllocateZeroPool (RawDataLength
);
825 if (RawData
== NULL
) {
826 return EFI_OUT_OF_RESOURCES
;
830 // Get all the forms associated with this HiiHandle
832 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
838 // Point RawData to the beginning of the form data
840 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
842 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
843 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
844 EfiCopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
848 Index
= RawData
[Index
+ 1] + Index
;
851 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
852 switch (RawData
[Index
]) {
853 case EFI_IFR_FORM_SET_OP
:
856 case EFI_IFR_ONE_OF_OP
:
857 case EFI_IFR_CHECKBOX_OP
:
858 case EFI_IFR_NUMERIC_OP
:
859 case EFI_IFR_DATE_OP
:
860 case EFI_IFR_TIME_OP
:
861 case EFI_IFR_PASSWORD_OP
:
862 case EFI_IFR_STRING_OP
:
864 // Remember, multiple op-codes may reference the same item, so let's keep a running
865 // marker of what the highest QuestionId that wasn't zero length. This will accurately
866 // maintain the Size of the NvStore
868 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
869 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
870 if (SizeOfNvStore
< Temp
) {
871 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
876 Index
= RawData
[Index
+ 1] + Index
;
880 // Allocate memory for our File Form Tags
882 VariableData
= EfiLibAllocateZeroPool (SizeOfNvStore
);
883 if (VariableData
== NULL
) {
884 return EFI_OUT_OF_RESOURCES
;
887 Status
= gRT
->GetVariable (
892 (VOID
*) VariableData
895 if (EFI_ERROR (Status
)) {
898 // If there is a variable that exists already and it is larger than what we calculated the
899 // storage needs to be, we must assume the variable size from GetVariable is correct and not
900 // allow the truncation of the variable. It is very possible that the user who created the IFR
901 // we are cracking is not referring to a variable that was in a previous map, however we cannot
902 // allow it's truncation.
904 if (Status
== EFI_BUFFER_TOO_SMALL
) {
906 // Free the buffer that was allocated that was too small
908 gBS
->FreePool (VariableData
);
910 VariableData
= EfiLibAllocatePool (SizeOfNvStore
);
911 if (VariableData
== NULL
) {
912 return EFI_OUT_OF_RESOURCES
;
915 Status
= gRT
->GetVariable (
920 (VOID
*) VariableData
926 // Walk through the form and see that the variable data it refers to is ok.
927 // This allows for the possibility of stale (obsoleted) data in the variable
928 // can be overlooked without causing an error
930 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
931 switch (RawData
[Index
]) {
932 case EFI_IFR_ONE_OF_OP
:
934 // A one_of has no data, its the option that does - cache the storage Id
936 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
939 case EFI_IFR_ONE_OF_OPTION_OP
:
941 // A one_of_option can be any value
943 if (VariableData
[CachedStart
] == ((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
948 case EFI_IFR_END_ONE_OF_OP
:
950 // At this point lets make sure that the data value in the NVRAM matches one of the options
958 case EFI_IFR_CHECKBOX_OP
:
960 // A checkbox is a boolean, so 0 and 1 are valid
961 // Remember, QuestionId corresponds to the offset location of the data in the variable
963 if (VariableData
[((EFI_IFR_CHECK_BOX
*) &RawData
[Index
])->QuestionId
] > 1) {
969 case EFI_IFR_NUMERIC_OP
:
970 if ((VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
971 (VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
979 Index
= RawData
[Index
+ 1] + Index
;
983 // Free our temporary repository of form data
985 gBS
->FreePool (OldData
);
986 gBS
->FreePool (VariableData
);
994 IN UINTN NumberOfPackages
,
1000 Routine Description:
1002 Assemble EFI_HII_PACKAGES according to the passed in packages.
1006 NumberOfPackages - Number of packages.
1007 GuidId - Package GUID.
1011 Pointer of EFI_HII_PACKAGES.
1016 EFI_HII_PACKAGES
*HiiPackages
;
1020 ASSERT (NumberOfPackages
> 0);
1022 HiiPackages
= EfiLibAllocateZeroPool (sizeof (EFI_HII_PACKAGES
) + NumberOfPackages
* sizeof (VOID
*));
1024 HiiPackages
->GuidId
= GuidId
;
1025 HiiPackages
->NumberOfPackages
= NumberOfPackages
;
1026 Package
= (VOID
**) (((UINT8
*) HiiPackages
) + sizeof (EFI_HII_PACKAGES
));
1028 VA_START (args
, GuidId
);
1030 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
1031 *Package
= VA_ARG (args
, VOID
*);