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
, (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.
493 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
496 EFI_HII_PROTOCOL
*Hii
;
505 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
509 Status
= GetHiiInterface (&Hii
);
511 if (EFI_ERROR (Status
)) {
516 // Allocate space for retrieval of IFR data
518 RawData
= EfiLibAllocateZeroPool ((UINTN
) DataLength
);
519 if (RawData
== NULL
) {
520 return EFI_OUT_OF_RESOURCES
;
524 // Get all the forms associated with this HiiHandle
526 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
528 if (EFI_ERROR (Status
)) {
529 gBS
->FreePool (RawData
);
532 // Allocate space for retrieval of IFR data
534 RawData
= EfiLibAllocateZeroPool ((UINTN
) DataLength
);
535 if (RawData
== NULL
) {
536 return EFI_OUT_OF_RESOURCES
;
540 // Get all the forms associated with this HiiHandle
542 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
548 // Point RawData to the beginning of the form data
550 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
552 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
553 switch (RawData
[Index
]) {
554 case EFI_IFR_FORM_SET_OP
:
556 // Copy the GUID information from this handle
558 EfiCopyMem (Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
561 case EFI_IFR_ONE_OF_OP
:
562 case EFI_IFR_CHECKBOX_OP
:
563 case EFI_IFR_NUMERIC_OP
:
564 case EFI_IFR_DATE_OP
:
565 case EFI_IFR_TIME_OP
:
566 case EFI_IFR_PASSWORD_OP
:
567 case EFI_IFR_STRING_OP
:
569 // Remember, multiple op-codes may reference the same item, so let's keep a running
570 // marker of what the highest QuestionId that wasn't zero length. This will accurately
571 // maintain the Size of the NvStore
573 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
574 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
575 if (SizeOfNvStore
< Temp
) {
576 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
581 Index
= RawData
[Index
+ 1] + Index
;
585 // Return an error if buffer is too small
587 if (SizeOfNvStore
> *ImageLength
) {
588 gBS
->FreePool (OldData
);
589 *ImageLength
= (UINT16
) SizeOfNvStore
;
590 return EFI_BUFFER_TOO_SMALL
;
593 EfiZeroMem (DefaultImage
, SizeOfNvStore
);
596 // Copy the default image information to the user's buffer
598 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
599 switch (RawData
[Index
]) {
600 case EFI_IFR_ONE_OF_OP
:
601 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
604 case EFI_IFR_ONE_OF_OPTION_OP
:
605 if (((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& EFI_IFR_FLAG_DEFAULT
) {
606 EfiCopyMem (&DefaultImage
[CachedStart
], &((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
610 case EFI_IFR_CHECKBOX_OP
:
611 DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((EFI_IFR_CHECK_BOX
*) &RawData
[Index
])->Flags
;
614 case EFI_IFR_NUMERIC_OP
:
616 &DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
617 &((EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
624 Index
= RawData
[Index
+ 1] + Index
;
627 *ImageLength
= (UINT16
) SizeOfNvStore
;
630 // Free our temporary repository of form data
632 gBS
->FreePool (OldData
);
637 // The implementation will be added later.
640 return EFI_UNSUPPORTED
;
647 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
653 Finds HII handle for given pack GUID previously registered with the HII.
656 HiiProtocol - pointer to pointer to HII protocol interface.
657 If NULL, the interface will be found but not returned.
658 If it points to NULL, the interface will be found and
659 written back to the pointer that is pointed to.
660 Guid - The GUID of the pack that registered with the HII.
663 Handle to the HII pack previously registered by the memory driver.
667 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
670 EFI_HII_HANDLE
*HiiHandleBuffer
;
671 EFI_HII_HANDLE HiiHandle
;
672 UINT16 HiiHandleBufferLength
;
673 UINT32 NumberOfHiiHandles
;
675 EFI_HII_PROTOCOL
*HiiProt
;
680 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
682 // The protocol has been passed in
684 HiiProt
= *HiiProtocol
;
686 gBS
->LocateProtocol (
687 &gEfiHiiProtocolGuid
,
691 if (HiiProt
== NULL
) {
695 if (HiiProtocol
!= NULL
) {
697 // Return back the HII protocol for the caller as promissed
699 *HiiProtocol
= HiiProt
;
705 HiiHandleBufferLength
= 10;
706 HiiHandleBuffer
= EfiLibAllocatePool (HiiHandleBufferLength
);
707 ASSERT (HiiHandleBuffer
!= NULL
);
710 // Get the Handles of the packages that were registered with Hii
712 Status
= HiiProt
->FindHandles (
714 &HiiHandleBufferLength
,
719 // Get a bigger bugffer if this one is to small, and try again
721 if (Status
== EFI_BUFFER_TOO_SMALL
) {
723 gBS
->FreePool (HiiHandleBuffer
);
725 HiiHandleBuffer
= EfiLibAllocatePool (HiiHandleBufferLength
);
726 ASSERT (HiiHandleBuffer
!= NULL
);
728 Status
= HiiProt
->FindHandles (
730 &HiiHandleBufferLength
,
735 if (EFI_ERROR (Status
)) {
739 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
742 // Iterate Hii handles and look for the one that matches our Guid
744 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
747 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
749 if (EfiCompareGuid (&HiiGuid
, Guid
)) {
751 HiiHandle
= HiiHandleBuffer
[Index
];
757 gBS
->FreePool (HiiHandleBuffer
);
761 // The implementation will be added later.
764 return (EFI_HII_HANDLE
) 0;
768 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
770 ValidateDataFromHiiHandle (
771 IN EFI_HII_HANDLE HiiHandle
,
778 Validate that the data associated with the HiiHandle in NVRAM is within
779 the reasonable parameters for that FormSet. Values for strings and passwords
780 are not verified due to their not having the equivalent of valid range settings.
784 HiiHandle - Handle of the HII database entry to query
786 Results - If return Status is EFI_SUCCESS, Results provides valid data
787 TRUE = NVRAM Data is within parameters
788 FALSE = NVRAM Data is NOT within parameters
792 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
794 EFI_SUCCESS - Data successfully validated
798 EFI_HII_PROTOCOL
*Hii
;
810 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
816 Status
= GetHiiInterface (&Hii
);
818 if (EFI_ERROR (Status
)) {
823 // Allocate space for retrieval of IFR data
825 RawData
= EfiLibAllocateZeroPool (RawDataLength
);
826 if (RawData
== NULL
) {
827 return EFI_OUT_OF_RESOURCES
;
831 // Get all the forms associated with this HiiHandle
833 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
835 if (EFI_ERROR (Status
)) {
836 gBS
->FreePool (RawData
);
839 // Allocate space for retrieval of IFR data
841 RawData
= EfiLibAllocateZeroPool (RawDataLength
);
842 if (RawData
== NULL
) {
843 return EFI_OUT_OF_RESOURCES
;
847 // Get all the forms associated with this HiiHandle
849 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
855 // Point RawData to the beginning of the form data
857 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
859 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
860 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
861 EfiCopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
865 Index
= RawData
[Index
+ 1] + Index
;
868 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
869 switch (RawData
[Index
]) {
870 case EFI_IFR_FORM_SET_OP
:
873 case EFI_IFR_ONE_OF_OP
:
874 case EFI_IFR_CHECKBOX_OP
:
875 case EFI_IFR_NUMERIC_OP
:
876 case EFI_IFR_DATE_OP
:
877 case EFI_IFR_TIME_OP
:
878 case EFI_IFR_PASSWORD_OP
:
879 case EFI_IFR_STRING_OP
:
881 // Remember, multiple op-codes may reference the same item, so let's keep a running
882 // marker of what the highest QuestionId that wasn't zero length. This will accurately
883 // maintain the Size of the NvStore
885 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
886 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
887 if (SizeOfNvStore
< Temp
) {
888 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
893 Index
= RawData
[Index
+ 1] + Index
;
897 // Allocate memory for our File Form Tags
899 VariableData
= EfiLibAllocateZeroPool (SizeOfNvStore
);
900 if (VariableData
== NULL
) {
901 return EFI_OUT_OF_RESOURCES
;
904 Status
= gRT
->GetVariable (
909 (VOID
*) VariableData
912 if (EFI_ERROR (Status
)) {
915 // If there is a variable that exists already and it is larger than what we calculated the
916 // storage needs to be, we must assume the variable size from GetVariable is correct and not
917 // allow the truncation of the variable. It is very possible that the user who created the IFR
918 // we are cracking is not referring to a variable that was in a previous map, however we cannot
919 // allow it's truncation.
921 if (Status
== EFI_BUFFER_TOO_SMALL
) {
923 // Free the buffer that was allocated that was too small
925 gBS
->FreePool (VariableData
);
927 VariableData
= EfiLibAllocatePool (SizeOfNvStore
);
928 if (VariableData
== NULL
) {
929 return EFI_OUT_OF_RESOURCES
;
932 Status
= gRT
->GetVariable (
937 (VOID
*) VariableData
943 // Walk through the form and see that the variable data it refers to is ok.
944 // This allows for the possibility of stale (obsoleted) data in the variable
945 // can be overlooked without causing an error
947 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
948 switch (RawData
[Index
]) {
949 case EFI_IFR_ONE_OF_OP
:
951 // A one_of has no data, its the option that does - cache the storage Id
953 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
956 case EFI_IFR_ONE_OF_OPTION_OP
:
958 // A one_of_option can be any value
960 if (VariableData
[CachedStart
] == ((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
965 case EFI_IFR_END_ONE_OF_OP
:
967 // At this point lets make sure that the data value in the NVRAM matches one of the options
975 case EFI_IFR_CHECKBOX_OP
:
977 // A checkbox is a boolean, so 0 and 1 are valid
978 // Remember, QuestionId corresponds to the offset location of the data in the variable
980 if (VariableData
[((EFI_IFR_CHECK_BOX
*) &RawData
[Index
])->QuestionId
] > 1) {
986 case EFI_IFR_NUMERIC_OP
:
987 if ((VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
988 (VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
996 Index
= RawData
[Index
+ 1] + Index
;
1000 // Free our temporary repository of form data
1002 gBS
->FreePool (OldData
);
1003 gBS
->FreePool (VariableData
);
1011 IN UINTN NumberOfPackages
,
1012 IN EFI_GUID
*GuidId
,
1017 Routine Description:
1019 Assemble EFI_HII_PACKAGES according to the passed in packages.
1023 NumberOfPackages - Number of packages.
1024 GuidId - Package GUID.
1028 Pointer of EFI_HII_PACKAGES.
1033 EFI_HII_PACKAGES
*HiiPackages
;
1037 ASSERT (NumberOfPackages
> 0);
1039 HiiPackages
= EfiLibAllocateZeroPool (sizeof (EFI_HII_PACKAGES
) + NumberOfPackages
* sizeof (VOID
*));
1041 HiiPackages
->GuidId
= GuidId
;
1042 HiiPackages
->NumberOfPackages
= NumberOfPackages
;
1043 Package
= (VOID
**) (((UINT8
*) HiiPackages
) + sizeof (EFI_HII_PACKAGES
));
1045 VA_START (args
, GuidId
);
1047 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
1048 *Package
= VA_ARG (args
, VOID
*);