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
;
123 StringPack
= (EFI_HII_STRING_PACK
*) StringBuffer
;
127 // Pre-allocate a buffer sufficient for us to work on.
128 // We will use it as a destination scratch pad to build data on
129 // and when complete shift the data back to the original buffer
131 NewBuffer
= EfiLibAllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE
);
132 if (NewBuffer
== NULL
) {
133 return EFI_OUT_OF_RESOURCES
;
136 StringPackBuffer
= (EFI_HII_STRING_PACK
*) NewBuffer
;
139 // StringPack is terminated with a length 0 entry
141 for (; StringPack
->Header
.Length
!= 0;) {
143 // If this stringpack's language is same as CurrentLanguage, use it
145 if (EfiCompareMem ((VOID
*) ((CHAR8
*) (StringPack
) + StringPack
->LanguageNameString
), Language
, 3) == 0) {
147 // We have some data in this string pack, copy the string package up to the string data
149 EfiCopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, sizeof (StringPack
));
152 // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
154 StringPackBuffer
->LanguageNameString
= (UINT16
) (StringPackBuffer
->LanguageNameString
+ (UINT16
) sizeof (RELOFST
));
155 StringPackBuffer
->PrintableLanguageName
= (UINT16
) (StringPackBuffer
->PrintableLanguageName
+ (UINT16
) sizeof (RELOFST
));
157 PackSource
= (RELOFST
*) (StringPack
+ 1);
158 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
159 for (Index
= 0; PackSource
[Index
] != 0x0000; Index
++) {
161 // Copy the stringpointers from old to new buffer
162 // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
164 PackDestination
[Index
] = (UINT16
) (PackDestination
[Index
] + sizeof (RELOFST
));
168 // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
170 PackDestination
[Index
] = (UINT16
)(PackDestination
[Index
-1] +
171 EfiStrSize((CHAR16
*)((CHAR8
*)(StringPack
) + PackSource
[Index
-1])));
172 PackDestination
[Index
+ 1] = (UINT16
) 0;
175 // Index is the token value for the new string
177 *StringToken
= (UINT16
) Index
;
180 // Source now points to the beginning of the old buffer strings
181 // Destination now points to the beginning of the new buffer strings
183 Source
= (UINT8
*) &PackSource
[Index
+ 1];
184 Destination
= (UINT8
*) &PackDestination
[Index
+ 2];
187 // This should copy all the strings from the old buffer to the new buffer
189 for (; Index
!= 0; Index
--) {
191 // Copy Source string to destination buffer
193 EfiStrCpy ((CHAR16
*) Destination
, (CHAR16
*) Source
);
196 // Adjust the source/destination to the next string location
198 Destination
= Destination
+ EfiStrSize ((CHAR16
*) Source
);
199 Source
= Source
+ EfiStrSize ((CHAR16
*) Source
);
203 // This copies the new string to the destination buffer
205 EfiStrCpy ((CHAR16
*) Destination
, (CHAR16
*) String
);
208 // Adjust the size of the changed string pack by adding the size of the new string
209 // along with the size of the additional offset entry for the new string
211 StringPackBuffer
->Header
.Length
= (UINT32
) ((UINTN
) StringPackBuffer
->Header
.Length
+ EfiStrSize (String
) + sizeof (RELOFST
));
214 // Advance the buffers to point to the next spots.
216 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPackBuffer
->Header
.Length
);
217 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
222 // This isn't the language of the stringpack we were asked to add a string to
223 // so we need to copy it to the new buffer.
225 EfiCopyMem (&StringPackBuffer
->Header
, &StringPack
->Header
, StringPack
->Header
.Length
);
228 // Advance the buffers to point to the next spots.
230 StringPackBuffer
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPackBuffer
) + StringPack
->Header
.Length
);
231 StringPack
= (EFI_HII_STRING_PACK
*) ((CHAR8
*) (StringPack
) + StringPack
->Header
.Length
);
235 // If we didn't copy the new data to a stringpack yet
238 PackDestination
= (RELOFST
*) (StringPackBuffer
+ 1);
240 // Pointing to a new string pack location
242 StringPackBuffer
->Header
.Length
= (UINT32
)
244 sizeof (EFI_HII_STRING_PACK
) -
245 sizeof (EFI_STRING
) +
248 EfiStrSize (Language
) +
251 StringPackBuffer
->Header
.Type
= EFI_HII_STRING
;
252 StringPackBuffer
->LanguageNameString
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
253 StringPackBuffer
->PrintableLanguageName
= (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
254 StringPackBuffer
->Attributes
= 0;
255 PackDestination
[0] = (UINT16
) ((UINTN
) &PackDestination
[3] - (UINTN
) StringPackBuffer
);
256 PackDestination
[1] = (UINT16
) (PackDestination
[0] + EfiStrSize (Language
));
257 PackDestination
[2] = (UINT16
) 0;
260 // The first string location will be set to destination. The minimum number of strings
261 // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
262 // and token 1 as the new string being added and and null entry for the stringpointers
264 Destination
= (CHAR8
*) &PackDestination
[3];
267 // Copy the language name string to the new buffer
269 EfiStrCpy ((CHAR16
*) Destination
, Language
);
272 // Advance the destination to the new empty spot
274 Destination
= Destination
+ EfiStrSize (Language
);
277 // Copy the string to the new buffer
279 EfiStrCpy ((CHAR16
*) Destination
, String
);
282 // Since we are starting with a new string pack - we know the new string is token 1
284 *StringToken
= (UINT16
) 1;
288 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
290 EfiZeroMem (StringBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
291 EfiCopyMem (StringBuffer
, NewBuffer
, DEFAULT_STRING_BUFFER_SIZE
);
294 // Free the newly created buffer since we don't need it anymore
296 gBS
->FreePool (NewBuffer
);
304 IN OUT VOID
*OpCodeData
310 Add op-code data to the FormBuffer
314 FormBuffer - Form buffer to be inserted to
316 OpCodeData - Op-code data to be inserted
320 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
322 EFI_SUCCESS - Op-code data successfully inserted
326 EFI_HII_PACK_HEADER
*NewBuffer
;
331 // Pre-allocate a buffer sufficient for us to work on.
332 // We will use it as a destination scratch pad to build data on
333 // and when complete shift the data back to the original buffer
335 NewBuffer
= EfiLibAllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE
);
336 if (NewBuffer
== NULL
) {
337 return EFI_OUT_OF_RESOURCES
;
340 Source
= (UINT8
*) FormBuffer
;
341 Destination
= (UINT8
*) NewBuffer
;
344 // Copy the IFR Package header to the new buffer
346 EfiCopyMem (Destination
, Source
, sizeof (EFI_HII_PACK_HEADER
));
349 // Advance Source and Destination to next op-code
351 Source
= Source
+ sizeof (EFI_HII_PACK_HEADER
);
352 Destination
= Destination
+ sizeof (EFI_HII_PACK_HEADER
);
355 // Copy data to the new buffer until we run into the end_form
357 for (; ((EFI_IFR_OP_HEADER
*) Source
)->OpCode
!= EFI_IFR_END_FORM_OP
;) {
359 // If the this opcode is an end_form_set we better be creating and endform
360 // Nonetheless, we will add data before the end_form_set. This also provides
361 // for interesting behavior in the code we will run, but has no bad side-effects
362 // since we will possibly do a 0 byte copy in this particular end-case.
364 if (((EFI_IFR_OP_HEADER
*) Source
)->OpCode
== EFI_IFR_END_FORM_SET_OP
) {
369 // Copy data to new buffer
371 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
374 // Adjust Source/Destination to next op-code location
376 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
377 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
381 // Prior to the end_form is where we insert the new op-code data
383 EfiCopyMem (Destination
, OpCodeData
, ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
);
384 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
;
386 NewBuffer
->Length
= (UINT32
) (NewBuffer
->Length
+ (UINT32
) (((EFI_IFR_OP_HEADER
*) OpCodeData
)->Length
));
389 // Copy end-form data to new buffer
391 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
394 // Adjust Source/Destination to next op-code location
396 Destination
= Destination
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
397 Source
= Source
+ (UINTN
) ((EFI_IFR_OP_HEADER
*) Source
)->Length
;
400 // Copy end-formset data to new buffer
402 EfiCopyMem (Destination
, Source
, ((EFI_IFR_OP_HEADER
*) Source
)->Length
);
405 // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
407 EfiZeroMem (FormBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
408 EfiCopyMem (FormBuffer
, NewBuffer
, DEFAULT_FORM_BUFFER_SIZE
);
411 // Free the newly created buffer since we don't need it anymore
413 gBS
->FreePool (NewBuffer
);
421 OUT EFI_HII_PROTOCOL
**Hii
427 Get the HII protocol interface
431 Hii - HII protocol interface
442 // There should only be one HII protocol
444 Status
= gBS
->LocateProtocol (
445 &gEfiHiiProtocolGuid
,
455 ExtractDataFromHiiHandle (
456 IN EFI_HII_HANDLE HiiHandle
,
457 IN OUT UINT16
*ImageLength
,
458 OUT UINT8
*DefaultImage
,
465 Extract information pertaining to the HiiHandle
469 HiiHandle - Hii handle
471 ImageLength - For input, length of DefaultImage;
472 For output, length of actually required
474 DefaultImage - Image buffer prepared by caller
476 Guid - Guid information about the form
480 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
482 EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
484 EFI_SUCCESS - Successfully extract data from Hii database.
489 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
492 EFI_HII_PROTOCOL
*Hii
;
501 DataLength
= DEFAULT_FORM_BUFFER_SIZE
;
505 Status
= GetHiiInterface (&Hii
);
507 if (EFI_ERROR (Status
)) {
512 // Allocate space for retrieval of IFR data
514 RawData
= EfiLibAllocateZeroPool ((UINTN
) DataLength
);
515 if (RawData
== NULL
) {
516 return EFI_OUT_OF_RESOURCES
;
520 // Get all the forms associated with this HiiHandle
522 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
524 if (EFI_ERROR (Status
)) {
525 gBS
->FreePool (RawData
);
528 // Allocate space for retrieval of IFR data
530 RawData
= EfiLibAllocateZeroPool ((UINTN
) DataLength
);
531 if (RawData
== NULL
) {
532 return EFI_OUT_OF_RESOURCES
;
536 // Get all the forms associated with this HiiHandle
538 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &DataLength
, RawData
);
544 // Point RawData to the beginning of the form data
546 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
548 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
549 switch (RawData
[Index
]) {
550 case EFI_IFR_FORM_SET_OP
:
552 // Copy the GUID information from this handle
554 EfiCopyMem (Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
557 case EFI_IFR_ONE_OF_OP
:
558 case EFI_IFR_CHECKBOX_OP
:
559 case EFI_IFR_NUMERIC_OP
:
560 case EFI_IFR_DATE_OP
:
561 case EFI_IFR_TIME_OP
:
562 case EFI_IFR_PASSWORD_OP
:
563 case EFI_IFR_STRING_OP
:
565 // Remember, multiple op-codes may reference the same item, so let's keep a running
566 // marker of what the highest QuestionId that wasn't zero length. This will accurately
567 // maintain the Size of the NvStore
569 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
570 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
571 if (SizeOfNvStore
< Temp
) {
572 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
577 Index
= RawData
[Index
+ 1] + Index
;
581 // Return an error if buffer is too small
583 if (SizeOfNvStore
> *ImageLength
) {
584 gBS
->FreePool (OldData
);
585 *ImageLength
= (UINT16
) SizeOfNvStore
;
586 return EFI_BUFFER_TOO_SMALL
;
589 EfiZeroMem (DefaultImage
, SizeOfNvStore
);
592 // Copy the default image information to the user's buffer
594 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
595 switch (RawData
[Index
]) {
596 case EFI_IFR_ONE_OF_OP
:
597 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
600 case EFI_IFR_ONE_OF_OPTION_OP
:
601 if (((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Flags
& EFI_IFR_FLAG_DEFAULT
) {
602 EfiCopyMem (&DefaultImage
[CachedStart
], &((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
, 2);
606 case EFI_IFR_CHECKBOX_OP
:
607 DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
] = ((EFI_IFR_CHECK_BOX
*) &RawData
[Index
])->Flags
;
610 case EFI_IFR_NUMERIC_OP
:
612 &DefaultImage
[((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
],
613 &((EFI_IFR_NUMERIC
*) &RawData
[Index
])->Default
,
620 Index
= RawData
[Index
+ 1] + Index
;
623 *ImageLength
= (UINT16
) SizeOfNvStore
;
626 // Free our temporary repository of form data
628 gBS
->FreePool (OldData
);
633 // The implementation will be added later.
636 return EFI_UNSUPPORTED
;
643 IN OUT EFI_HII_PROTOCOL
**HiiProtocol
, OPTIONAL
649 Finds HII handle for given pack GUID previously registered with the HII.
652 HiiProtocol - pointer to pointer to HII protocol interface.
653 If NULL, the interface will be found but not returned.
654 If it points to NULL, the interface will be found and
655 written back to the pointer that is pointed to.
656 Guid - The GUID of the pack that registered with the HII.
659 Handle to the HII pack previously registered by the memory driver.
663 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
666 EFI_HII_HANDLE
*HiiHandleBuffer
;
667 EFI_HII_HANDLE HiiHandle
;
668 UINT16 HiiHandleBufferLength
;
669 UINT32 NumberOfHiiHandles
;
671 EFI_HII_PROTOCOL
*HiiProt
;
676 if ((HiiProtocol
!= NULL
) && (*HiiProtocol
!= NULL
)) {
678 // The protocol has been passed in
680 HiiProt
= *HiiProtocol
;
682 gBS
->LocateProtocol (
683 &gEfiHiiProtocolGuid
,
687 if (HiiProt
== NULL
) {
691 if (HiiProtocol
!= NULL
) {
693 // Return back the HII protocol for the caller as promissed
695 *HiiProtocol
= HiiProt
;
701 HiiHandleBufferLength
= 10;
702 HiiHandleBuffer
= EfiLibAllocatePool (HiiHandleBufferLength
);
703 ASSERT (HiiHandleBuffer
!= NULL
);
706 // Get the Handles of the packages that were registered with Hii
708 Status
= HiiProt
->FindHandles (
710 &HiiHandleBufferLength
,
715 // Get a bigger bugffer if this one is to small, and try again
717 if (Status
== EFI_BUFFER_TOO_SMALL
) {
719 gBS
->FreePool (HiiHandleBuffer
);
721 HiiHandleBuffer
= EfiLibAllocatePool (HiiHandleBufferLength
);
722 ASSERT (HiiHandleBuffer
!= NULL
);
724 Status
= HiiProt
->FindHandles (
726 &HiiHandleBufferLength
,
731 if (EFI_ERROR (Status
)) {
735 NumberOfHiiHandles
= HiiHandleBufferLength
/ sizeof (EFI_HII_HANDLE
);
738 // Iterate Hii handles and look for the one that matches our Guid
740 for (Index
= 0; Index
< NumberOfHiiHandles
; Index
++) {
743 ExtractDataFromHiiHandle (HiiHandleBuffer
[Index
], &Length
, NULL
, &HiiGuid
);
745 if (EfiCompareGuid (&HiiGuid
, Guid
)) {
747 HiiHandle
= HiiHandleBuffer
[Index
];
753 gBS
->FreePool (HiiHandleBuffer
);
757 // The implementation will be added later.
760 return (EFI_HII_HANDLE
) 0;
764 #ifdef SUPPORT_DEPRECATED_IFRSUPPORTLIB_API
766 ValidateDataFromHiiHandle (
767 IN EFI_HII_HANDLE HiiHandle
,
774 Validate that the data associated with the HiiHandle in NVRAM is within
775 the reasonable parameters for that FormSet. Values for strings and passwords
776 are not verified due to their not having the equivalent of valid range settings.
780 HiiHandle - Handle of the HII database entry to query
782 Results - If return Status is EFI_SUCCESS, Results provides valid data
783 TRUE = NVRAM Data is within parameters
784 FALSE = NVRAM Data is NOT within parameters
788 EFI_OUT_OF_RESOURCES - No enough buffer to allocate
790 EFI_SUCCESS - Data successfully validated
794 EFI_HII_PROTOCOL
*Hii
;
806 RawDataLength
= DEFAULT_FORM_BUFFER_SIZE
;
812 Status
= GetHiiInterface (&Hii
);
814 if (EFI_ERROR (Status
)) {
819 // Allocate space for retrieval of IFR data
821 RawData
= EfiLibAllocateZeroPool (RawDataLength
);
822 if (RawData
== NULL
) {
823 return EFI_OUT_OF_RESOURCES
;
827 // Get all the forms associated with this HiiHandle
829 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
831 if (EFI_ERROR (Status
)) {
832 gBS
->FreePool (RawData
);
835 // Allocate space for retrieval of IFR data
837 RawData
= EfiLibAllocateZeroPool (RawDataLength
);
838 if (RawData
== NULL
) {
839 return EFI_OUT_OF_RESOURCES
;
843 // Get all the forms associated with this HiiHandle
845 Status
= Hii
->GetForms (Hii
, HiiHandle
, 0, &RawDataLength
, RawData
);
851 // Point RawData to the beginning of the form data
853 RawData
= (UINT8
*) ((UINTN
) RawData
+ sizeof (EFI_HII_PACK_HEADER
));
855 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
856 if (RawData
[Index
] == EFI_IFR_FORM_SET_OP
) {
857 EfiCopyMem (&Guid
, &((EFI_IFR_FORM_SET
*) &RawData
[Index
])->Guid
, sizeof (EFI_GUID
));
861 Index
= RawData
[Index
+ 1] + Index
;
864 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
865 switch (RawData
[Index
]) {
866 case EFI_IFR_FORM_SET_OP
:
869 case EFI_IFR_ONE_OF_OP
:
870 case EFI_IFR_CHECKBOX_OP
:
871 case EFI_IFR_NUMERIC_OP
:
872 case EFI_IFR_DATE_OP
:
873 case EFI_IFR_TIME_OP
:
874 case EFI_IFR_PASSWORD_OP
:
875 case EFI_IFR_STRING_OP
:
877 // Remember, multiple op-codes may reference the same item, so let's keep a running
878 // marker of what the highest QuestionId that wasn't zero length. This will accurately
879 // maintain the Size of the NvStore
881 if (((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
!= 0) {
882 Temp
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
883 if (SizeOfNvStore
< Temp
) {
884 SizeOfNvStore
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
+ ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->Width
;
889 Index
= RawData
[Index
+ 1] + Index
;
893 // Allocate memory for our File Form Tags
895 VariableData
= EfiLibAllocateZeroPool (SizeOfNvStore
);
896 if (VariableData
== NULL
) {
897 return EFI_OUT_OF_RESOURCES
;
900 Status
= gRT
->GetVariable (
905 (VOID
*) VariableData
908 if (EFI_ERROR (Status
)) {
911 // If there is a variable that exists already and it is larger than what we calculated the
912 // storage needs to be, we must assume the variable size from GetVariable is correct and not
913 // allow the truncation of the variable. It is very possible that the user who created the IFR
914 // we are cracking is not referring to a variable that was in a previous map, however we cannot
915 // allow it's truncation.
917 if (Status
== EFI_BUFFER_TOO_SMALL
) {
919 // Free the buffer that was allocated that was too small
921 gBS
->FreePool (VariableData
);
923 VariableData
= EfiLibAllocatePool (SizeOfNvStore
);
924 if (VariableData
== NULL
) {
925 return EFI_OUT_OF_RESOURCES
;
928 Status
= gRT
->GetVariable (
933 (VOID
*) VariableData
939 // Walk through the form and see that the variable data it refers to is ok.
940 // This allows for the possibility of stale (obsoleted) data in the variable
941 // can be overlooked without causing an error
943 for (Index
= 0; RawData
[Index
] != EFI_IFR_END_FORM_SET_OP
;) {
944 switch (RawData
[Index
]) {
945 case EFI_IFR_ONE_OF_OP
:
947 // A one_of has no data, its the option that does - cache the storage Id
949 CachedStart
= ((EFI_IFR_ONE_OF
*) &RawData
[Index
])->QuestionId
;
952 case EFI_IFR_ONE_OF_OPTION_OP
:
954 // A one_of_option can be any value
956 if (VariableData
[CachedStart
] == ((EFI_IFR_ONE_OF_OPTION
*) &RawData
[Index
])->Value
) {
961 case EFI_IFR_END_ONE_OF_OP
:
963 // At this point lets make sure that the data value in the NVRAM matches one of the options
971 case EFI_IFR_CHECKBOX_OP
:
973 // A checkbox is a boolean, so 0 and 1 are valid
974 // Remember, QuestionId corresponds to the offset location of the data in the variable
976 if (VariableData
[((EFI_IFR_CHECK_BOX
*) &RawData
[Index
])->QuestionId
] > 1) {
982 case EFI_IFR_NUMERIC_OP
:
983 if ((VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] < ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Minimum
) ||
984 (VariableData
[((EFI_IFR_NUMERIC
*)&RawData
[Index
])->QuestionId
] > ((EFI_IFR_NUMERIC
*)&RawData
[Index
])->Maximum
)) {
992 Index
= RawData
[Index
+ 1] + Index
;
996 // Free our temporary repository of form data
998 gBS
->FreePool (OldData
);
999 gBS
->FreePool (VariableData
);
1007 IN UINTN NumberOfPackages
,
1008 IN EFI_GUID
*GuidId
,
1013 Routine Description:
1015 Assemble EFI_HII_PACKAGES according to the passed in packages.
1019 NumberOfPackages - Number of packages.
1020 GuidId - Package GUID.
1024 Pointer of EFI_HII_PACKAGES.
1029 EFI_HII_PACKAGES
*HiiPackages
;
1033 ASSERT (NumberOfPackages
> 0);
1035 HiiPackages
= EfiLibAllocateZeroPool (sizeof (EFI_HII_PACKAGES
) + NumberOfPackages
* sizeof (VOID
*));
1037 HiiPackages
->GuidId
= GuidId
;
1038 HiiPackages
->NumberOfPackages
= NumberOfPackages
;
1039 Package
= (VOID
**) (((UINT8
*) HiiPackages
) + sizeof (EFI_HII_PACKAGES
));
1041 VA_START (args
, GuidId
);
1043 for (Index
= 0; Index
< NumberOfPackages
; Index
++) {
1044 *Package
= VA_ARG (args
, VOID
*);