summaryrefslogtreecommitdiff
path: root/EdkModulePkg/Library/EdkIfrSupportLib
diff options
context:
space:
mode:
authorbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
committerbbahnsen <bbahnsen@6f19259b-4bc3-4df7-8a09-765794883524>2006-04-21 22:54:32 +0000
commit878ddf1fc3540a715f63594ed22b6929e881afb4 (patch)
treec56c44dac138137b510e1fba7c3efe5e4d84bea2 /EdkModulePkg/Library/EdkIfrSupportLib
downloadedk2-platforms-878ddf1fc3540a715f63594ed22b6929e881afb4.tar.xz
Initial import.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkModulePkg/Library/EdkIfrSupportLib')
-rw-r--r--EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.mbd30
-rw-r--r--EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.msa75
-rw-r--r--EdkModulePkg/Library/EdkIfrSupportLib/IfrCommon.c995
-rw-r--r--EdkModulePkg/Library/EdkIfrSupportLib/IfrOnTheFly.c972
-rw-r--r--EdkModulePkg/Library/EdkIfrSupportLib/IfrOpCodeCreation.c613
-rw-r--r--EdkModulePkg/Library/EdkIfrSupportLib/IfrVariable.c484
-rw-r--r--EdkModulePkg/Library/EdkIfrSupportLib/build.xml47
7 files changed, 3216 insertions, 0 deletions
diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.mbd b/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.mbd
new file mode 100644
index 0000000000..3864ea2a5c
--- /dev/null
+++ b/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.mbd
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<LibraryModuleBuildDescription xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MbdLibHeader>
+ <BaseName>EdkIfrSupportLib</BaseName>
+ <Guid>ea55bada-d488-427b-9d2d-227e0aaa3707</Guid>
+ <Version>EDK_RELEASE_VERSION 0x00020000</Version>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Created>2006-03-12 17:09</Created>
+ <Modified>2006-03-31 13:14</Modified>
+ </MbdLibHeader>
+</LibraryModuleBuildDescription>
diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.msa b/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.msa
new file mode 100644
index 0000000000..fcf02afb02
--- /dev/null
+++ b/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.msa
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<LibraryModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.TianoCore.org/2006/Edk2.0 http://www.TianoCore.org/2006/Edk2.0/SurfaceArea.xsd">
+ <MsaLibHeader>
+ <BaseName>EdkIfrSupportLib</BaseName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <ComponentType>LIBRARY</ComponentType>
+ <Guid>ea55bada-d488-427b-9d2d-227e0aaa3707</Guid>
+ <Version>EDK_RELEASE_VERSION 0x00020000</Version>
+ <Abstract>Graphics Library for UEFI drivers</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2004-2006, Intel Corporation</Copyright>
+ <License>
+ All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ </License>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00000000</Specification>
+ <Created>2006-03-12 17:09</Created>
+ <Updated>2006-03-31 13:14</Updated>
+ </MsaLibHeader>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_PRODUCED">EdkIfrSupportLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">DebugLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">PrintLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">BaseMemoryLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">MemoryAllocationLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiBootServicesTableLib</LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">UefiRuntimeServicesTableLib</LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>IfrCommon.c</Filename>
+ <Filename>IfrOnTheFly.c</Filename>
+ <Filename>IfrOpCodeCreation.c</Filename>
+ <Filename>IfrLibrary.h</Filename>
+ <Filename>IfrVariable.c</Filename>
+ </SourceFiles>
+ <Includes>
+ <PackageName>MdePkg</PackageName>
+ <PackageName>EdkModulePkg</PackageName>
+ </Includes>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">Hii</Protocol>
+ </Protocols>
+ <Variables>
+ <Variable>
+ <String>L"Lang"</String>
+ <Guid>0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C}</Guid>
+ </Variable>
+ </Variables>
+ <Guids>
+ <GuidEntry Usage="ALWAYS_CONSUMED">
+ <C_Name>GlobalVariable</C_Name>
+ </GuidEntry>
+ </Guids>
+ <Externs>
+ <Extern>
+ <Constructor>IfrLibConstruct</Constructor>
+ </Extern>
+ </Externs>
+</LibraryModuleSurfaceArea>
diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/IfrCommon.c b/EdkModulePkg/Library/EdkIfrSupportLib/IfrCommon.c
new file mode 100644
index 0000000000..6d0a84de5e
--- /dev/null
+++ b/EdkModulePkg/Library/EdkIfrSupportLib/IfrCommon.c
@@ -0,0 +1,995 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ IfrCommon.c
+
+Abstract:
+
+ Common Library Routines to assist in IFR creation on-the-fly
+
+Revision History:
+
+--*/
+
+EFI_STATUS
+IfrLibConstruct (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetCurrentLanguage (
+ OUT CHAR16 *Lang
+ )
+/*++
+
+Routine Description:
+
+ Determine what is the current language setting
+
+Arguments:
+
+ Lang - Pointer of system language
+
+Returns:
+
+ Status code
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINTN Index;
+ CHAR8 Language[4];
+
+ //
+ // Getting the system language and placing it into our Global Data
+ //
+ Size = sizeof (Language);
+
+ Status = gRT->GetVariable (
+ (CHAR16 *) L"Lang",
+ &gEfiGlobalVariableGuid,
+ NULL,
+ &Size,
+ Language
+ );
+
+ if (EFI_ERROR (Status)) {
+ AsciiStrCpy (Language, "eng");
+ }
+
+ for (Index = 0; Language[Index] != 0; Index++) {
+ //
+ // Bitwise AND ascii value with 0xDF yields an uppercase value.
+ // Sign extend into a unicode value
+ //
+ Lang[Index] = (CHAR16) (Language[Index] & 0xDF);
+ }
+
+ //
+ // Null-terminate the value
+ //
+ Lang[3] = (CHAR16) 0;
+
+ return Status;
+}
+
+
+EFI_STATUS
+AddString (
+ IN VOID *StringBuffer,
+ IN CHAR16 *Language,
+ IN CHAR16 *String,
+ IN OUT STRING_REF *StringToken
+ )
+/*++
+
+Routine Description:
+
+ Add a string to the incoming buffer and return the token and offset data
+
+Arguments:
+
+ StringBuffer - The incoming buffer
+
+ Language - Currrent language
+
+ String - The string to be added
+
+ StringToken - The index where the string placed
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - String successfully added to the incoming buffer
+
+--*/
+{
+ EFI_HII_STRING_PACK *StringPack;
+ EFI_HII_STRING_PACK *StringPackBuffer;
+ VOID *NewBuffer;
+ RELOFST *PackSource;
+ RELOFST *PackDestination;
+ UINT8 *Source;
+ UINT8 *Destination;
+ UINTN Index;
+ BOOLEAN Finished;
+
+ StringPack = (EFI_HII_STRING_PACK *) StringBuffer;
+ Finished = FALSE;
+
+ //
+ // Pre-allocate a buffer sufficient for us to work on.
+ // We will use it as a destination scratch pad to build data on
+ // and when complete shift the data back to the original buffer
+ //
+ NewBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE);
+ if (NewBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StringPackBuffer = (EFI_HII_STRING_PACK *) NewBuffer;
+
+ //
+ // StringPack is terminated with a length 0 entry
+ //
+ for (; StringPack->Header.Length != 0;) {
+ //
+ // If this stringpack's language is same as CurrentLanguage, use it
+ //
+ if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language, 3) == 0) {
+ //
+ // We have some data in this string pack, copy the string package up to the string data
+ //
+ CopyMem (&StringPackBuffer->Header, &StringPack->Header, sizeof (StringPack));
+
+ //
+ // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
+ //
+ StringPackBuffer->LanguageNameString = (UINT16) (StringPackBuffer->LanguageNameString + (UINT16) sizeof (RELOFST));
+ StringPackBuffer->PrintableLanguageName = (UINT16) (StringPackBuffer->PrintableLanguageName + (UINT16) sizeof (RELOFST));
+
+ PackSource = (RELOFST *) (StringPack + 1);
+ PackDestination = (RELOFST *) (StringPackBuffer + 1);
+ for (Index = 0; PackSource[Index] != 0x0000; Index++) {
+ //
+ // Copy the stringpointers from old to new buffer
+ // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
+ //
+ PackDestination[Index] = (UINT16) (PackDestination[Index] + sizeof (RELOFST));
+ }
+
+ //
+ // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it
+ //
+ PackDestination[Index] = (UINT16)(PackDestination[Index-1] +
+ StrSize((CHAR16 *)((CHAR8 *)(StringPack) + PackSource[Index-1])));
+ PackDestination[Index + 1] = (UINT16) 0;
+
+ //
+ // Index is the token value for the new string
+ //
+ *StringToken = (UINT16) Index;
+
+ //
+ // Source now points to the beginning of the old buffer strings
+ // Destination now points to the beginning of the new buffer strings
+ //
+ Source = (UINT8 *) &PackSource[Index + 1];
+ Destination = (UINT8 *) &PackDestination[Index + 2];
+
+ //
+ // This should copy all the strings from the old buffer to the new buffer
+ //
+ for (; Index != 0; Index--) {
+ //
+ // Copy Source string to destination buffer
+ //
+ StrCpy ((CHAR16 *) Destination, (CHAR16 *) Source);
+
+ //
+ // Adjust the source/destination to the next string location
+ //
+ Destination = Destination + StrSize ((CHAR16 *) Source);
+ Source = Source + StrSize ((CHAR16 *) Source);
+ }
+
+ //
+ // This copies the new string to the destination buffer
+ //
+ StrCpy ((CHAR16 *) Destination, (CHAR16 *) String);
+
+ //
+ // Adjust the size of the changed string pack by adding the size of the new string
+ // along with the size of the additional offset entry for the new string
+ //
+ StringPackBuffer->Header.Length = (UINT32) ((UINTN) StringPackBuffer->Header.Length + StrSize (String) + sizeof (RELOFST));
+
+ //
+ // Advance the buffers to point to the next spots.
+ //
+ StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPackBuffer->Header.Length);
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);
+ Finished = TRUE;
+ continue;
+ }
+ //
+ // This isn't the language of the stringpack we were asked to add a string to
+ // so we need to copy it to the new buffer.
+ //
+ CopyMem (&StringPackBuffer->Header, &StringPack->Header, StringPack->Header.Length);
+
+ //
+ // Advance the buffers to point to the next spots.
+ //
+ StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPack->Header.Length);
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);
+ }
+
+ //
+ // If we didn't copy the new data to a stringpack yet
+ //
+ if (!Finished) {
+ PackDestination = (RELOFST *) (StringPackBuffer + 1);
+ //
+ // Pointing to a new string pack location
+ //
+ StringPackBuffer->Header.Length = (UINT32)
+ (
+ sizeof (EFI_HII_STRING_PACK) -
+ sizeof (EFI_STRING) +
+ sizeof (RELOFST) +
+ sizeof (RELOFST) +
+ StrSize (Language) +
+ StrSize (String)
+ );
+ StringPackBuffer->Header.Type = EFI_HII_STRING;
+ StringPackBuffer->LanguageNameString = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
+ StringPackBuffer->PrintableLanguageName = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
+ StringPackBuffer->Attributes = 0;
+ PackDestination[0] = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
+ PackDestination[1] = (UINT16) (PackDestination[0] + StrSize (Language));
+ PackDestination[2] = (UINT16) 0;
+
+ //
+ // The first string location will be set to destination. The minimum number of strings
+ // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
+ // and token 1 as the new string being added and and null entry for the stringpointers
+ //
+ Destination = (UINT8 *) &PackDestination[3];
+
+ //
+ // Copy the language name string to the new buffer
+ //
+ StrCpy ((CHAR16 *) Destination, Language);
+
+ //
+ // Advance the destination to the new empty spot
+ //
+ Destination = Destination + StrSize (Language);
+
+ //
+ // Copy the string to the new buffer
+ //
+ StrCpy ((CHAR16 *) Destination, String);
+
+ //
+ // Since we are starting with a new string pack - we know the new string is token 1
+ //
+ *StringToken = (UINT16) 1;
+ }
+
+ //
+ // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
+ //
+ ZeroMem (StringBuffer, DEFAULT_STRING_BUFFER_SIZE);
+ CopyMem (StringBuffer, NewBuffer, DEFAULT_STRING_BUFFER_SIZE);
+
+ //
+ // Free the newly created buffer since we don't need it anymore
+ //
+ gBS->FreePool (NewBuffer);
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+AddOpCode (
+ IN VOID *FormBuffer,
+ IN OUT VOID *OpCodeData
+ )
+/*++
+
+Routine Description:
+
+ Add op-code data to the FormBuffer
+
+Arguments:
+
+ FormBuffer - Form buffer to be inserted to
+
+ OpCodeData - Op-code data to be inserted
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Op-code data successfully inserted
+
+--*/
+{
+ EFI_HII_PACK_HEADER *NewBuffer;
+ UINT8 *Source;
+ UINT8 *Destination;
+
+ //
+ // Pre-allocate a buffer sufficient for us to work on.
+ // We will use it as a destination scratch pad to build data on
+ // and when complete shift the data back to the original buffer
+ //
+ NewBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE);
+ if (NewBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Source = (UINT8 *) FormBuffer;
+ Destination = (UINT8 *) NewBuffer;
+
+ //
+ // Copy the IFR Package header to the new buffer
+ //
+ CopyMem (Destination, Source, sizeof (EFI_HII_PACK_HEADER));
+
+ //
+ // Advance Source and Destination to next op-code
+ //
+ Source = Source + sizeof (EFI_HII_PACK_HEADER);
+ Destination = Destination + sizeof (EFI_HII_PACK_HEADER);
+
+ //
+ // Copy data to the new buffer until we run into the end_form
+ //
+ for (; ((EFI_IFR_OP_HEADER *) Source)->OpCode != EFI_IFR_END_FORM_OP;) {
+ //
+ // If the this opcode is an end_form_set we better be creating and endform
+ // Nonetheless, we will add data before the end_form_set. This also provides
+ // for interesting behavior in the code we will run, but has no bad side-effects
+ // since we will possibly do a 0 byte copy in this particular end-case.
+ //
+ if (((EFI_IFR_OP_HEADER *) Source)->OpCode == EFI_IFR_END_FORM_SET_OP) {
+ break;
+ }
+
+ //
+ // Copy data to new buffer
+ //
+ CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);
+
+ //
+ // Adjust Source/Destination to next op-code location
+ //
+ Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;
+ Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;
+ }
+
+ //
+ // Prior to the end_form is where we insert the new op-code data
+ //
+ CopyMem (Destination, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);
+ Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
+
+ NewBuffer->Length = (UINT32) (NewBuffer->Length + (UINT32) (((EFI_IFR_OP_HEADER *) OpCodeData)->Length));
+
+ //
+ // Copy end-form data to new buffer
+ //
+ CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);
+
+ //
+ // Adjust Source/Destination to next op-code location
+ //
+ Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;
+ Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;
+
+ //
+ // Copy end-formset data to new buffer
+ //
+ CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);
+
+ //
+ // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
+ //
+ ZeroMem (FormBuffer, DEFAULT_FORM_BUFFER_SIZE);
+ CopyMem (FormBuffer, NewBuffer, DEFAULT_FORM_BUFFER_SIZE);
+
+ //
+ // Free the newly created buffer since we don't need it anymore
+ //
+ gBS->FreePool (NewBuffer);
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+GetHiiInterface (
+ OUT EFI_HII_PROTOCOL **Hii
+ )
+/*++
+
+Routine Description:
+
+ Get the HII protocol interface
+
+Arguments:
+
+ Hii - HII protocol interface
+
+Returns:
+
+ Status code
+
+--*/
+{
+ EFI_STATUS Status;
+
+ //
+ // There should only be one HII protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiProtocolGuid,
+ NULL,
+ (VOID **) Hii
+ );
+
+ return Status;;
+}
+
+
+EFI_STATUS
+ExtractDataFromHiiHandle (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN OUT UINT16 *ImageLength,
+ OUT UINT8 *DefaultImage,
+ OUT EFI_GUID *Guid
+ )
+/*++
+
+Routine Description:
+
+ Extract information pertaining to the HiiHandle
+
+Arguments:
+
+ HiiHandle - Hii handle
+
+ ImageLength - For input, length of DefaultImage;
+ For output, length of actually required
+
+ DefaultImage - Image buffer prepared by caller
+
+ Guid - Guid information about the form
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength
+
+ EFI_SUCCESS - Successfully extract data from Hii database.
+
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_PROTOCOL *Hii;
+ UINTN DataLength;
+ UINT8 *RawData;
+ UINT8 *OldData;
+ UINTN Index;
+ UINTN Temp;
+ UINTN SizeOfNvStore;
+ UINTN CachedStart;
+
+ DataLength = DEFAULT_FORM_BUFFER_SIZE;
+ SizeOfNvStore = 0;
+ CachedStart = 0;
+
+ Status = GetHiiInterface (&Hii);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate space for retrieval of IFR data
+ //
+ RawData = AllocateZeroPool (DataLength);
+ if (RawData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get all the forms associated with this HiiHandle
+ //
+ Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (RawData);
+
+ //
+ // Allocate space for retrieval of IFR data
+ //
+ RawData = AllocateZeroPool (DataLength);
+ if (RawData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get all the forms associated with this HiiHandle
+ //
+ Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);
+ }
+
+ OldData = RawData;
+
+ //
+ // Point RawData to the beginning of the form data
+ //
+ RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));
+
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ switch (RawData[Index]) {
+ case EFI_IFR_FORM_SET_OP:
+ //
+ // Copy the GUID information from this handle
+ //
+ CopyMem (Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_CHECKBOX_OP:
+ case EFI_IFR_NUMERIC_OP:
+ case EFI_IFR_DATE_OP:
+ case EFI_IFR_TIME_OP:
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ //
+ // Remember, multiple op-codes may reference the same item, so let's keep a running
+ // marker of what the highest QuestionId that wasn't zero length. This will accurately
+ // maintain the Size of the NvStore
+ //
+ if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {
+ Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;
+ if (SizeOfNvStore < Temp) {
+ SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;
+ }
+ }
+ }
+
+ Index = RawData[Index + 1] + Index;
+ }
+
+ //
+ // Return an error if buffer is too small
+ //
+ if (SizeOfNvStore > *ImageLength) {
+ gBS->FreePool (OldData);
+ *ImageLength = (UINT16) SizeOfNvStore;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (DefaultImage != NULL) {
+ ZeroMem (DefaultImage, SizeOfNvStore);
+ }
+
+ //
+ // Copy the default image information to the user's buffer
+ //
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ switch (RawData[Index]) {
+ case EFI_IFR_ONE_OF_OP:
+ CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ if (((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Flags & EFI_IFR_FLAG_DEFAULT) {
+ CopyMem (&DefaultImage[CachedStart], &((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value, 2);
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId] = ((EFI_IFR_CHECKBOX *) &RawData[Index])->Flags;
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ CopyMem (
+ &DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId],
+ &((EFI_IFR_NUMERIC *) &RawData[Index])->Default,
+ 2
+ );
+ break;
+
+ }
+
+ Index = RawData[Index + 1] + Index;
+ }
+
+ *ImageLength = (UINT16) SizeOfNvStore;
+
+ //
+ // Free our temporary repository of form data
+ //
+ gBS->FreePool (OldData);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_HII_HANDLE
+FindHiiHandle (
+ IN OUT EFI_HII_PROTOCOL **HiiProtocol, OPTIONAL
+ IN EFI_GUID *Guid
+ )
+/*++
+
+Routine Description:
+ Finds HII handle for given pack GUID previously registered with the HII.
+
+Arguments:
+ HiiProtocol - pointer to pointer to HII protocol interface.
+ If NULL, the interface will be found but not returned.
+ If it points to NULL, the interface will be found and
+ written back to the pointer that is pointed to.
+ Guid - The GUID of the pack that registered with the HII.
+
+Returns:
+ Handle to the HII pack previously registered by the memory driver.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ EFI_HII_HANDLE *HiiHandleBuffer;
+ EFI_HII_HANDLE HiiHandle;
+ UINT16 HiiHandleBufferLength;
+ UINT32 NumberOfHiiHandles;
+ EFI_GUID HiiGuid;
+ EFI_HII_PROTOCOL *HiiProt;
+ UINT32 Index;
+ UINT16 Length;
+
+ HiiHandle = 0;
+ if ((HiiProtocol != NULL) && (*HiiProtocol != NULL)) {
+ //
+ // The protocol has been passed in
+ //
+ HiiProt = *HiiProtocol;
+ } else {
+ gBS->LocateProtocol (
+ &gEfiHiiProtocolGuid,
+ NULL,
+ (VOID **) &HiiProt
+ );
+ if (HiiProt == NULL) {
+ return HiiHandle;
+ }
+
+ if (HiiProtocol != NULL) {
+ //
+ // Return back the HII protocol for the caller as promissed
+ //
+ *HiiProtocol = HiiProt;
+ }
+ }
+ //
+ // Allocate buffer
+ //
+ HiiHandleBufferLength = 10;
+ HiiHandleBuffer = AllocatePool (HiiHandleBufferLength);
+ ASSERT (HiiHandleBuffer != NULL);
+
+ //
+ // Get the Handles of the packages that were registered with Hii
+ //
+ Status = HiiProt->FindHandles (
+ HiiProt,
+ &HiiHandleBufferLength,
+ HiiHandleBuffer
+ );
+
+ //
+ // Get a bigger bugffer if this one is to small, and try again
+ //
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+
+ gBS->FreePool (HiiHandleBuffer);
+
+ HiiHandleBuffer = AllocatePool (HiiHandleBufferLength);
+ ASSERT (HiiHandleBuffer != NULL);
+
+ Status = HiiProt->FindHandles (
+ HiiProt,
+ &HiiHandleBufferLength,
+ HiiHandleBuffer
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto lbl_exit;
+ }
+
+ NumberOfHiiHandles = HiiHandleBufferLength / sizeof (EFI_HII_HANDLE);
+
+ //
+ // Iterate Hii handles and look for the one that matches our Guid
+ //
+ for (Index = 0; Index < NumberOfHiiHandles; Index++) {
+
+ Length = 0;
+ ExtractDataFromHiiHandle (HiiHandleBuffer[Index], &Length, NULL, &HiiGuid);
+
+ if (CompareGuid (&HiiGuid, Guid)) {
+
+ HiiHandle = HiiHandleBuffer[Index];
+ break;
+ }
+ }
+
+lbl_exit:
+ gBS->FreePool (HiiHandleBuffer);
+ return HiiHandle;
+}
+
+
+EFI_STATUS
+ValidateDataFromHiiHandle (
+ IN EFI_HII_HANDLE HiiHandle,
+ OUT BOOLEAN *Results
+ )
+/*++
+
+Routine Description:
+
+ Validate that the data associated with the HiiHandle in NVRAM is within
+ the reasonable parameters for that FormSet. Values for strings and passwords
+ are not verified due to their not having the equivalent of valid range settings.
+
+Arguments:
+
+ HiiHandle - Handle of the HII database entry to query
+
+ Results - If return Status is EFI_SUCCESS, Results provides valid data
+ TRUE = NVRAM Data is within parameters
+ FALSE = NVRAM Data is NOT within parameters
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Data successfully validated
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_PROTOCOL *Hii;
+ EFI_GUID Guid;
+ UINT8 *RawData;
+ UINT8 *OldData;
+ UINTN RawDataLength;
+ UINT8 *VariableData;
+ UINTN Index;
+ UINTN Temp;
+ UINTN SizeOfNvStore;
+ UINTN CachedStart;
+ BOOLEAN GotMatch;
+
+ RawDataLength = DEFAULT_FORM_BUFFER_SIZE;
+ SizeOfNvStore = 0;
+ CachedStart = 0;
+ GotMatch = FALSE;
+ *Results = TRUE;
+
+ Status = GetHiiInterface (&Hii);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Allocate space for retrieval of IFR data
+ //
+ RawData = AllocateZeroPool (RawDataLength);
+ if (RawData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get all the forms associated with this HiiHandle
+ //
+ Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (RawData);
+
+ //
+ // Allocate space for retrieval of IFR data
+ //
+ RawData = AllocateZeroPool (RawDataLength);
+ if (RawData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get all the forms associated with this HiiHandle
+ //
+ Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);
+ }
+
+ OldData = RawData;
+
+ //
+ // Point RawData to the beginning of the form data
+ //
+ RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));
+
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ if (RawData[Index] == EFI_IFR_FORM_SET_OP) {
+ CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));
+ break;
+ }
+
+ Index = RawData[Index + 1] + Index;
+ }
+
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ switch (RawData[Index]) {
+ case EFI_IFR_FORM_SET_OP:
+ break;
+
+ case EFI_IFR_ONE_OF_OP:
+ case EFI_IFR_CHECKBOX_OP:
+ case EFI_IFR_NUMERIC_OP:
+ case EFI_IFR_DATE_OP:
+ case EFI_IFR_TIME_OP:
+ case EFI_IFR_PASSWORD_OP:
+ case EFI_IFR_STRING_OP:
+ //
+ // Remember, multiple op-codes may reference the same item, so let's keep a running
+ // marker of what the highest QuestionId that wasn't zero length. This will accurately
+ // maintain the Size of the NvStore
+ //
+ if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {
+ Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;
+ if (SizeOfNvStore < Temp) {
+ SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;
+ }
+ }
+ }
+
+ Index = RawData[Index + 1] + Index;
+ }
+
+ //
+ // Allocate memory for our File Form Tags
+ //
+ VariableData = AllocateZeroPool (SizeOfNvStore);
+ if (VariableData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gRT->GetVariable (
+ (CHAR16 *) L"Setup",
+ &Guid,
+ NULL,
+ &SizeOfNvStore,
+ (VOID *) VariableData
+ );
+
+ if (EFI_ERROR (Status)) {
+
+ //
+ // If there is a variable that exists already and it is larger than what we calculated the
+ // storage needs to be, we must assume the variable size from GetVariable is correct and not
+ // allow the truncation of the variable. It is very possible that the user who created the IFR
+ // we are cracking is not referring to a variable that was in a previous map, however we cannot
+ // allow it's truncation.
+ //
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Free the buffer that was allocated that was too small
+ //
+ gBS->FreePool (VariableData);
+
+ VariableData = AllocatePool (SizeOfNvStore);
+ if (VariableData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = gRT->GetVariable (
+ (CHAR16 *) L"Setup",
+ &Guid,
+ NULL,
+ &SizeOfNvStore,
+ (VOID *) VariableData
+ );
+ }
+ }
+
+ //
+ // Walk through the form and see that the variable data it refers to is ok.
+ // This allows for the possibility of stale (obsoleted) data in the variable
+ // can be overlooked without causing an error
+ //
+ for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
+ switch (RawData[Index]) {
+ case EFI_IFR_ONE_OF_OP:
+ //
+ // A one_of has no data, its the option that does - cache the storage Id
+ //
+ CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;
+ break;
+
+ case EFI_IFR_ONE_OF_OPTION_OP:
+ //
+ // A one_of_option can be any value
+ //
+ if (VariableData[CachedStart] == ((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value) {
+ GotMatch = TRUE;
+ }
+ break;
+
+ case EFI_IFR_END_ONE_OF_OP:
+ //
+ // At this point lets make sure that the data value in the NVRAM matches one of the options
+ //
+ if (!GotMatch) {
+ *Results = FALSE;
+ return EFI_SUCCESS;
+ }
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ //
+ // A checkbox is a boolean, so 0 and 1 are valid
+ // Remember, QuestionId corresponds to the offset location of the data in the variable
+ //
+ if (VariableData[((EFI_IFR_CHECKBOX *) &RawData[Index])->QuestionId] > 1) {
+ *Results = FALSE;
+ return EFI_SUCCESS;
+ }
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ if ((VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] < ((EFI_IFR_NUMERIC *)&RawData[Index])->Minimum) ||
+ (VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] > ((EFI_IFR_NUMERIC *)&RawData[Index])->Maximum)) {
+ *Results = FALSE;
+ return EFI_SUCCESS;
+ }
+ break;
+
+ }
+
+ Index = RawData[Index + 1] + Index;
+ }
+
+ //
+ // Free our temporary repository of form data
+ //
+ gBS->FreePool (OldData);
+ gBS->FreePool (VariableData);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/IfrOnTheFly.c b/EdkModulePkg/Library/EdkIfrSupportLib/IfrOnTheFly.c
new file mode 100644
index 0000000000..e3d1040896
--- /dev/null
+++ b/EdkModulePkg/Library/EdkIfrSupportLib/IfrOnTheFly.c
@@ -0,0 +1,972 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ IfrOnTheFly.c
+
+Abstract:
+
+ Library Routines to create IFR on-the-fly
+
+Revision History:
+
+--*/
+
+EFI_STATUS
+CreateFormSet (
+ IN CHAR16 *FormSetTitle,
+ IN EFI_GUID *Guid,
+ IN UINT8 Class,
+ IN UINT8 SubClass,
+ IN OUT VOID **FormBuffer,
+ IN OUT VOID **StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a formset
+
+Arguments:
+
+ FormSetTitle - Title of formset
+
+ Guid - Guid of formset
+
+ Class - Class of formset
+
+ SubClass - Sub class of formset
+
+ FormBuffer - Pointer of the formset created
+
+ StringBuffer - Pointer of FormSetTitile string created
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - No enough buffer to allocate
+
+ EFI_SUCCESS - Formset successfully created
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HII_IFR_PACK IfrPack;
+ EFI_IFR_FORM_SET FormSet;
+ EFI_IFR_END_FORM_SET EndFormSet;
+ UINT8 *Destination;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // Pre-allocate a buffer sufficient for us to work from.
+ //
+ FormBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE);
+ if (FormBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Pre-allocate a buffer sufficient for us to work from.
+ //
+ StringBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE);
+ if (StringBuffer == NULL) {
+ gBS->FreePool (FormBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ //
+ // Add the FormSetTitle to the string buffer and get the StringToken
+ //
+ Status = AddString (*StringBuffer, CurrentLanguage, FormSetTitle, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Initialize the Ifr Package header data
+ //
+ IfrPack.Header.Length = sizeof (EFI_HII_PACK_HEADER) + sizeof (EFI_IFR_FORM_SET) + sizeof (EFI_IFR_END_FORM_SET);
+ IfrPack.Header.Type = EFI_HII_IFR;
+
+ //
+ // Initialize FormSet with the appropriate information
+ //
+ FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP;
+ FormSet.Header.Length = sizeof (EFI_IFR_FORM_SET);
+ FormSet.FormSetTitle = StringToken;
+ FormSet.Class = Class;
+ FormSet.SubClass = SubClass;
+ CopyMem (&FormSet.Guid, Guid, sizeof (EFI_GUID));
+
+ //
+ // Initialize the end formset data
+ //
+ EndFormSet.Header.Length = sizeof (EFI_IFR_END_FORM_SET);
+ EndFormSet.Header.OpCode = EFI_IFR_END_FORM_SET_OP;
+
+ Destination = (UINT8 *) *FormBuffer;
+
+ //
+ // Copy the formset/endformset data to the form buffer
+ //
+ CopyMem (Destination, &IfrPack, sizeof (EFI_HII_PACK_HEADER));
+
+ Destination = Destination + sizeof (EFI_HII_PACK_HEADER);
+
+ CopyMem (Destination, &FormSet, sizeof (EFI_IFR_FORM_SET));
+
+ Destination = Destination + sizeof (EFI_IFR_FORM_SET);
+
+ CopyMem (Destination, &EndFormSet, sizeof (EFI_IFR_END_FORM_SET));
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateForm (
+ IN CHAR16 *FormTitle,
+ IN UINT16 FormId,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a form
+
+Arguments:
+
+ FormTitle - Title of the form
+
+ FormId - Id of the form
+
+ FormBuffer - Pointer of the form created
+
+ StringBuffer - Pointer of FormTitil string created
+
+Returns:
+
+ EFI_SUCCESS - Form successfully created
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IFR_FORM Form;
+ EFI_IFR_END_FORM EndForm;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ Status = AddString (StringBuffer, CurrentLanguage, FormTitle, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Form.Header.OpCode = EFI_IFR_FORM_OP;
+ Form.Header.Length = sizeof (EFI_IFR_FORM);
+ Form.FormId = FormId;
+ Form.FormTitle = StringToken;
+
+ Status = AddOpCode (FormBuffer, &Form);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ EndForm.Header.OpCode = EFI_IFR_END_FORM_OP;
+ EndForm.Header.Length = sizeof (EFI_IFR_END_FORM);
+
+ Status = AddOpCode (FormBuffer, &EndForm);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateSubTitle (
+ IN CHAR16 *SubTitle,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a SubTitle
+
+Arguments:
+
+ SubTitle - Sub title to be created
+
+ FormBuffer - Where this subtitle to add to
+
+ StringBuffer - String buffer created for subtitle
+
+Returns:
+
+ EFI_SUCCESS - Subtitle successfully created
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IFR_SUBTITLE Subtitle;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ Status = AddString (StringBuffer, CurrentLanguage, SubTitle, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP;
+ Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE);
+ Subtitle.SubTitle = StringToken;
+
+ Status = AddOpCode (FormBuffer, &Subtitle);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateText (
+ IN CHAR16 *String,
+ IN CHAR16 *String2,
+ IN CHAR16 *String3,
+ IN UINT8 Flags,
+ IN UINT16 Key,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a line of text
+
+Arguments:
+
+ String - First string of the text
+
+ String2 - Second string of the text
+
+ String3 - Help string of the text
+
+ Flags - Flag of the text
+
+ Key - Key of the text
+
+ FormBuffer - The form where this text adds to
+
+ StringBuffer - String buffer created for String, String2 and String3
+
+Returns:
+
+ EFI_SUCCESS - Text successfully created
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IFR_TEXT Text;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ //
+ // Add first string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, String, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Text.Header.OpCode = EFI_IFR_TEXT_OP;
+ Text.Header.Length = sizeof (EFI_IFR_TEXT);
+ Text.Text = StringToken;
+
+ //
+ // Add second string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, String2, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Text.TextTwo = StringToken;
+
+ Text.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED);
+ Text.Key = Key;
+
+ //
+ // Add second string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, String3, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Text.Help = StringToken;
+
+ Status = AddOpCode (FormBuffer, &Text);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateGoto (
+ IN UINT16 FormId,
+ IN CHAR16 *Prompt,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a hyperlink
+
+Arguments:
+
+ FormId - Form ID of the hyperlink
+
+ Prompt - Prompt of the hyperlink
+
+ FormBuffer - The form where this hyperlink adds to
+
+ StringBuffer - String buffer created for Prompt
+
+Returns:
+
+ EFI_SUCCESS - Hyperlink successfully created
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IFR_REF Hyperlink;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Hyperlink.Header.OpCode = EFI_IFR_REF_OP;
+ Hyperlink.Header.Length = sizeof (EFI_IFR_REF);
+ Hyperlink.FormId = FormId;
+ Hyperlink.Prompt = StringToken;
+
+ Status = AddOpCode (FormBuffer, &Hyperlink);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateOneOf (
+ IN UINT16 QuestionId,
+ IN UINT8 DataWidth,
+ IN CHAR16 *Prompt,
+ IN CHAR16 *Help,
+ IN IFR_OPTION *OptionsList,
+ IN UINTN OptionCount,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a one-of question with a set of options to choose from. The
+ OptionsList is a pointer to a null-terminated list of option descriptions.
+
+Arguments:
+
+ QuestionId - Question ID of the one-of box
+
+ DataWidth - DataWidth of the one-of box
+
+ Prompt - Prompt of the one-of box
+
+ Help - Help of the one-of box
+
+ OptionsList - Each string in it is an option of the one-of box
+
+ OptionCount - Option string count
+
+ FormBuffer - The form where this one-of box adds to
+
+ StringBuffer - String buffer created for Prompt, Help and Option strings
+
+Returns:
+
+ EFI_DEVICE_ERROR - DataWidth > 2
+
+ EFI_SUCCESS - One-Of box successfully created.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_IFR_ONE_OF OneOf;
+ EFI_IFR_ONE_OF_OPTION OneOfOption;
+ EFI_IFR_END_ONE_OF EndOneOf;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // We do not create op-code storage widths for one-of in excess of 16 bits for now
+ //
+ if (DataWidth > 2) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ //
+ // Add first string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP;
+ OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF);
+ OneOf.QuestionId = QuestionId;
+ OneOf.Width = DataWidth;
+ OneOf.Prompt = StringToken;
+
+ //
+ // Add second string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OneOf.Help = StringToken;
+
+ Status = AddOpCode (FormBuffer, &OneOf);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < OptionCount; Index++) {
+ OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
+ OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);
+
+ //
+ // Add string and get token back
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, OptionsList[Index].OptionString, &StringToken);
+
+ OneOfOption.Option = StringToken;
+ OneOfOption.Value = OptionsList[Index].Value;
+ OneOfOption.Flags = (UINT8) (OptionsList[Index].Flags | EFI_IFR_FLAG_CREATED);
+ OneOfOption.Key = OptionsList[Index].Key;
+
+ Status = AddOpCode (FormBuffer, &OneOfOption);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ EndOneOf.Header.Length = sizeof (EFI_IFR_END_ONE_OF);
+ EndOneOf.Header.OpCode = EFI_IFR_END_ONE_OF_OP;
+
+ Status = AddOpCode (FormBuffer, &EndOneOf);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateOrderedList (
+ IN UINT16 QuestionId,
+ IN UINT8 MaxEntries,
+ IN CHAR16 *Prompt,
+ IN CHAR16 *Help,
+ IN IFR_OPTION *OptionsList,
+ IN UINTN OptionCount,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a one-of question with a set of options to choose from. The
+ OptionsList is a pointer to a null-terminated list of option descriptions.
+
+Arguments:
+
+ QuestionId - Question ID of the ordered list
+
+ MaxEntries - MaxEntries of the ordered list
+
+ Prompt - Prompt of the ordered list
+
+ Help - Help of the ordered list
+
+ OptionsList - Each string in it is an option of the ordered list
+
+ OptionCount - Option string count
+
+ FormBuffer - The form where this ordered list adds to
+
+ StringBuffer - String buffer created for Prompt, Help and Option strings
+
+Returns:
+
+ EFI_SUCCESS - Ordered list successfully created.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_IFR_ORDERED_LIST OrderedList;
+ EFI_IFR_ONE_OF_OPTION OrderedListOption;
+ EFI_IFR_END_ONE_OF EndOrderedList;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ //
+ // Add first string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;
+ OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST);
+ OrderedList.QuestionId = QuestionId;
+ OrderedList.MaxEntries = MaxEntries;
+ OrderedList.Prompt = StringToken;
+
+ //
+ // Add second string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ OrderedList.Help = StringToken;
+
+ Status = AddOpCode (FormBuffer, &OrderedList);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < OptionCount; Index++) {
+ OrderedListOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
+ OrderedListOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);
+
+ //
+ // Add string and get token back
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, OptionsList[Index].OptionString, &StringToken);
+
+ OrderedListOption.Option = StringToken;
+ OrderedListOption.Value = OptionsList[Index].Value;
+ OrderedListOption.Flags = (UINT8) (OptionsList[Index].Flags | EFI_IFR_FLAG_CREATED);
+ OrderedListOption.Key = OptionsList[Index].Key;
+
+ Status = AddOpCode (FormBuffer, &OrderedListOption);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ EndOrderedList.Header.Length = sizeof (EFI_IFR_END_ONE_OF);
+ EndOrderedList.Header.OpCode = EFI_IFR_END_ONE_OF_OP;
+
+ Status = AddOpCode (FormBuffer, &EndOrderedList);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateCheckBox (
+ IN UINT16 QuestionId,
+ IN UINT8 DataWidth,
+ IN CHAR16 *Prompt,
+ IN CHAR16 *Help,
+ IN UINT8 Flags,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a checkbox
+
+Arguments:
+
+ QuestionId - Question ID of the check box
+
+ DataWidth - DataWidth of the check box
+
+ Prompt - Prompt of the check box
+
+ Help - Help of the check box
+
+ Flags - Flags of the check box
+
+ FormBuffer - The form where this check box adds to
+
+ StringBuffer - String buffer created for Prompt and Help.
+
+Returns:
+
+ EFI_DEVICE_ERROR - DataWidth > 1
+
+ EFI_SUCCESS - Check box successfully created
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IFR_CHECKBOX CheckBox;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // We do not create op-code storage widths for checkbox in excess of 8 bits for now
+ //
+ if (DataWidth > 1) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ //
+ // Add first string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP;
+ CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX);
+ CheckBox.QuestionId = QuestionId;
+ CheckBox.Width = DataWidth;
+ CheckBox.Prompt = StringToken;
+
+ //
+ // Add second string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CheckBox.Help = StringToken;
+ CheckBox.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED);
+
+ Status = AddOpCode (FormBuffer, &CheckBox);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateNumeric (
+ IN UINT16 QuestionId,
+ IN UINT8 DataWidth,
+ IN CHAR16 *Prompt,
+ IN CHAR16 *Help,
+ IN UINT16 Minimum,
+ IN UINT16 Maximum,
+ IN UINT16 Step,
+ IN UINT16 Default,
+ IN UINT8 Flags,
+ IN UINT16 Key,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a numeric
+
+Arguments:
+
+ QuestionId - Question ID of the numeric
+
+ DataWidth - DataWidth of the numeric
+
+ Prompt - Prompt of the numeric
+
+ Help - Help of the numeric
+
+ Minimum - Minumun boundary of the numeric
+
+ Maximum - Maximum boundary of the numeric
+
+ Step - Step of the numeric
+
+ Default - Default value
+
+ Flags - Flags of the numeric
+
+ Key - Key of the numeric
+
+ FormBuffer - The form where this numeric adds to
+
+ StringBuffer - String buffer created for Prompt and Help.
+
+Returns:
+
+ EFI_DEVICE_ERROR - DataWidth > 2
+
+ EFI_SUCCESS - Numeric is successfully created
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IFR_NUMERIC Numeric;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // We do not create op-code storage widths for numerics in excess of 16 bits for now
+ //
+ if (DataWidth > 2) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ //
+ // Add first string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP;
+ Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC);
+ Numeric.QuestionId = QuestionId;
+ Numeric.Width = DataWidth;
+ Numeric.Prompt = StringToken;
+
+ //
+ // Add second string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Numeric.Help = StringToken;
+ Numeric.Minimum = Minimum;
+ Numeric.Maximum = Maximum;
+ Numeric.Step = Step;
+ Numeric.Default = Default;
+ Numeric.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED);
+ Numeric.Key = Key;
+
+ Status = AddOpCode (FormBuffer, &Numeric);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateString (
+ IN UINT16 QuestionId,
+ IN UINT8 DataWidth,
+ IN CHAR16 *Prompt,
+ IN CHAR16 *Help,
+ IN UINT8 MinSize,
+ IN UINT8 MaxSize,
+ IN UINT8 Flags,
+ IN UINT16 Key,
+ IN OUT VOID *FormBuffer,
+ IN OUT VOID *StringBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a string
+
+Arguments:
+
+ QuestionId - Question ID of the string
+
+ DataWidth - DataWidth of the string
+
+ Prompt - Prompt of the string
+
+ Help - Help of the string
+
+ MinSize - Min size boundary of the string
+
+ MaxSize - Max size boundary of the string
+
+ Flags - Flags of the string
+
+ Key - Key of the string
+
+ FormBuffer - The form where this string adds to
+
+ StringBuffer - String buffer created for Prompt and Help.
+
+Returns:
+
+ EFI_SUCCESS - String successfully created.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_IFR_STRING String;
+ CHAR16 CurrentLanguage[4];
+ STRING_REF StringToken;
+
+ //
+ // Obtain current language value
+ //
+ GetCurrentLanguage (CurrentLanguage);
+
+ //
+ // Add first string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ String.Header.OpCode = EFI_IFR_STRING_OP;
+ String.Header.Length = sizeof (EFI_IFR_STRING);
+ String.QuestionId = QuestionId;
+ String.Width = DataWidth;
+ String.Prompt = StringToken;
+
+ //
+ // Add second string, get first string's token
+ //
+ Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ String.Help = StringToken;
+ String.MinSize = MinSize;
+ String.MaxSize = MaxSize;
+ String.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED);
+ String.Key = Key;
+
+ Status = AddOpCode (FormBuffer, &String);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/IfrOpCodeCreation.c b/EdkModulePkg/Library/EdkIfrSupportLib/IfrOpCodeCreation.c
new file mode 100644
index 0000000000..6fb2be791e
--- /dev/null
+++ b/EdkModulePkg/Library/EdkIfrSupportLib/IfrOpCodeCreation.c
@@ -0,0 +1,613 @@
+/*++
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ IfrOpCodeCreation.c
+
+Abstract:
+
+ Library Routines to create IFR independent of string data - assume tokens already exist
+ Primarily to be used for exporting op-codes at a label in pre-defined forms.
+
+Revision History:
+
+--*/
+
+EFI_STATUS
+CreateSubTitleOpCode (
+ IN STRING_REF StringToken,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a SubTitle opcode independent of string creation
+ This is used primarily by users who need to create just one particular valid op-code and the string
+ data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label
+ location to pre-defined forms in HII)
+
+Arguments:
+
+ StringToken - StringToken of the subtitle
+
+ FormBuffer - Output of subtitle as a form
+
+Returns:
+
+ EFI_SUCCESS - Subtitle created to be a form
+
+--*/
+{
+ EFI_IFR_SUBTITLE Subtitle;
+
+ Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP;
+ Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE);
+ Subtitle.SubTitle = StringToken;
+
+ CopyMem (FormBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE));
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateTextOpCode (
+ IN STRING_REF StringToken,
+ IN STRING_REF StringTokenTwo,
+ IN STRING_REF StringTokenThree,
+ IN UINT8 Flags,
+ IN UINT16 Key,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a Text opcode independent of string creation
+ This is used primarily by users who need to create just one particular valid op-code and the string
+ data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label
+ location to pre-defined forms in HII)
+
+Arguments:
+
+ StringToken - First string token of the text
+
+ StringTokenTwo - Second string token of the text
+
+ StringTokenThree - Help string token of the text
+
+ Flags - Flag of the text
+
+ Key - Key of the text
+
+ FormBuffer - Output of text as a form
+
+Returns:
+
+ EFI_SUCCESS - Text created to be a form
+
+--*/
+{
+ EFI_IFR_TEXT Text;
+
+ Text.Header.OpCode = EFI_IFR_TEXT_OP;
+ Text.Header.Length = sizeof (EFI_IFR_TEXT);
+ Text.Text = StringToken;
+
+ Text.TextTwo = StringTokenTwo;
+ Text.Help = StringTokenThree;
+ Text.Flags = Flags;
+ Text.Key = Key;
+
+ CopyMem (FormBuffer, &Text, sizeof (EFI_IFR_TEXT));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateGotoOpCode (
+ IN UINT16 FormId,
+ IN STRING_REF StringToken,
+ IN STRING_REF StringTokenTwo,
+ IN UINT8 Flags,
+ IN UINT16 Key,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a hyperlink opcode independent of string creation
+ This is used primarily by users who need to create just one particular valid op-code and the string
+ data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label
+ location to pre-defined forms in HII)
+
+Arguments:
+
+ FormId - Form ID of the hyperlink
+
+ StringToken - Prompt string token of the hyperlink
+
+ StringTokenTwo - Help string token of the hyperlink
+
+ Flags - Flags of the hyperlink
+
+ Key - Key of the hyperlink
+
+ FormBuffer - Output of hyperlink as a form
+
+Returns:
+
+ EFI_SUCCESS - Hyperlink created to be a form
+
+--*/
+{
+ EFI_IFR_REF Hyperlink;
+
+ Hyperlink.Header.OpCode = EFI_IFR_REF_OP;
+ Hyperlink.Header.Length = sizeof (EFI_IFR_REF);
+ Hyperlink.FormId = FormId;
+ Hyperlink.Prompt = StringToken;
+ Hyperlink.Help = StringTokenTwo;
+ Hyperlink.Key = Key;
+ Hyperlink.Flags = Flags;
+
+ CopyMem (FormBuffer, &Hyperlink, sizeof (EFI_IFR_REF));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateOneOfOpCode (
+ IN UINT16 QuestionId,
+ IN UINT8 DataWidth,
+ IN STRING_REF PromptToken,
+ IN STRING_REF HelpToken,
+ IN IFR_OPTION *OptionsList,
+ IN UINTN OptionCount,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a one-of opcode with a set of option op-codes to choose from independent of string creation.
+ This is used primarily by users who need to create just one particular valid op-code and the string
+ data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label
+ location to pre-defined forms in HII)
+
+ OptionsList is a pointer to a null-terminated list of option descriptions. Ensure that OptionsList[x].StringToken
+ has been filled in since this routine will not generate StringToken values.
+
+Arguments:
+
+ QuestionId - Question ID of the one-of box
+
+ DataWidth - DataWidth of the one-of box
+
+ PromptToken - Prompt string token of the one-of box
+
+ HelpToken - Help string token of the one-of box
+
+ OptionsList - Each string in it is an option of the one-of box
+
+ OptionCount - Option string count
+
+ FormBuffer - Output of One-Of box as a form
+
+Returns:
+
+ EFI_SUCCESS - One-Of box created to be a form
+
+ EFI_DEVICE_ERROR - DataWidth > 2
+
+--*/
+{
+ UINTN Index;
+ EFI_IFR_ONE_OF OneOf;
+ EFI_IFR_ONE_OF_OPTION OneOfOption;
+ EFI_IFR_END_ONE_OF EndOneOf;
+ UINT8 *LocalBuffer;
+
+ //
+ // We do not create op-code storage widths for one-of in excess of 16 bits for now
+ //
+ if (DataWidth > 2) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP;
+ OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF);
+ OneOf.QuestionId = QuestionId;
+ OneOf.Width = DataWidth;
+ OneOf.Prompt = PromptToken;
+
+ OneOf.Help = HelpToken;
+
+ LocalBuffer = (UINT8 *) FormBuffer;
+
+ CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF));
+
+ LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF));
+
+ for (Index = 0; Index < OptionCount; Index++) {
+ OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
+ OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);
+
+ OneOfOption.Option = OptionsList[Index].StringToken;
+ OneOfOption.Value = OptionsList[Index].Value;
+ OneOfOption.Flags = OptionsList[Index].Flags;
+ OneOfOption.Key = OptionsList[Index].Key;
+
+ CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION));
+
+ LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF_OPTION));
+ }
+
+ EndOneOf.Header.Length = sizeof (EFI_IFR_END_ONE_OF);
+ EndOneOf.Header.OpCode = EFI_IFR_END_ONE_OF_OP;
+
+ CopyMem (LocalBuffer, &EndOneOf, sizeof (EFI_IFR_END_ONE_OF));
+
+ LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_END_ONE_OF));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateOrderedListOpCode (
+ IN UINT16 QuestionId,
+ IN UINT8 MaxEntries,
+ IN STRING_REF PromptToken,
+ IN STRING_REF HelpToken,
+ IN IFR_OPTION *OptionsList,
+ IN UINTN OptionCount,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a ordered list opcode with a set of option op-codes to choose from independent of string creation.
+ This is used primarily by users who need to create just one particular valid op-code and the string
+ data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label
+ location to pre-defined forms in HII)
+
+ OptionsList is a pointer to a null-terminated list of option descriptions. Ensure that OptionsList[x].StringToken
+ has been filled in since this routine will not generate StringToken values.
+
+Arguments:
+
+ QuestionId - Question ID of the ordered list
+
+ MaxEntries - MaxEntries of the ordered list
+
+ PromptToken - Prompt string token of the ordered list
+
+ HelpToken - Help string token of the ordered list
+
+ OptionsList - Each string in it is an option of the ordered list
+
+ OptionCount - Option string count
+
+ FormBuffer - Output of ordered list as a form
+
+Returns:
+
+ EFI_SUCCESS - Ordered list created to be a form
+
+--*/
+{
+ UINTN Index;
+ EFI_IFR_ORDERED_LIST OrderedList;
+ EFI_IFR_ONE_OF_OPTION OrderedListOption;
+ EFI_IFR_END_ONE_OF EndOrderedList;
+ UINT8 *LocalBuffer;
+
+ OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;
+ OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST);
+ OrderedList.QuestionId = QuestionId;
+ OrderedList.MaxEntries = MaxEntries;
+ OrderedList.Prompt = PromptToken;
+
+ OrderedList.Help = HelpToken;
+
+ LocalBuffer = (UINT8 *) FormBuffer;
+
+ CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST));
+
+ LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ORDERED_LIST));
+
+ for (Index = 0; Index < OptionCount; Index++) {
+ OrderedListOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;
+ OrderedListOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);
+
+ OrderedListOption.Option = OptionsList[Index].StringToken;
+ OrderedListOption.Value = OptionsList[Index].Value;
+ OrderedListOption.Flags = OptionsList[Index].Flags;
+ OrderedListOption.Key = OptionsList[Index].Key;
+
+ CopyMem (LocalBuffer, &OrderedListOption, sizeof (EFI_IFR_ONE_OF_OPTION));
+
+ LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF_OPTION));
+ }
+
+ EndOrderedList.Header.Length = sizeof (EFI_IFR_END_ONE_OF);
+ EndOrderedList.Header.OpCode = EFI_IFR_END_ONE_OF_OP;
+
+ CopyMem (LocalBuffer, &EndOrderedList, sizeof (EFI_IFR_END_ONE_OF));
+
+ LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_END_ONE_OF));
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateCheckBoxOpCode (
+ IN UINT16 QuestionId,
+ IN UINT8 DataWidth,
+ IN STRING_REF PromptToken,
+ IN STRING_REF HelpToken,
+ IN UINT8 Flags,
+ IN UINT16 Key,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a checkbox opcode independent of string creation
+ This is used primarily by users who need to create just one particular valid op-code and the string
+ data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label
+ location to pre-defined forms in HII)
+
+Arguments:
+
+ QuestionId - Question ID of the check box
+
+ DataWidth - DataWidth of the check box
+
+ PromptToken - Prompt string token of the check box
+
+ HelpToken - Help string token of the check box
+
+ Flags - Flags of the check box
+
+ Key - Key of the check box
+
+ FormBuffer - Output of the check box as a form
+
+Returns:
+
+ EFI_SUCCESS - Checkbox created to be a form
+
+ EFI_DEVICE_ERROR - DataWidth > 1
+
+--*/
+{
+ EFI_IFR_CHECKBOX CheckBox;
+
+ //
+ // We do not create op-code storage widths for checkbox in excess of 8 bits for now
+ //
+ if (DataWidth > 1) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP;
+ CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX);
+ CheckBox.QuestionId = QuestionId;
+ CheckBox.Width = DataWidth;
+ CheckBox.Prompt = PromptToken;
+
+ CheckBox.Help = HelpToken;
+ CheckBox.Flags = Flags;
+ CheckBox.Key = Key;
+
+ CopyMem (FormBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateNumericOpCode (
+ IN UINT16 QuestionId,
+ IN UINT8 DataWidth,
+ IN STRING_REF PromptToken,
+ IN STRING_REF HelpToken,
+ IN UINT16 Minimum,
+ IN UINT16 Maximum,
+ IN UINT16 Step,
+ IN UINT16 Default,
+ IN UINT8 Flags,
+ IN UINT16 Key,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a numeric opcode independent of string creation
+ This is used primarily by users who need to create just one particular valid op-code and the string
+ data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label
+ location to pre-defined forms in HII)
+
+Arguments:
+
+ QuestionId - Question ID of the numeric
+
+ DataWidth - DataWidth of the numeric
+
+ PromptToken - Prompt string token of the numeric
+
+ HelpToken - Help string token of the numeric
+
+ Minimum - Minumun boundary of the numeric
+
+ Maximum - Maximum boundary of the numeric
+
+ Step - Step of the numeric
+
+ Default - Default value of the numeric
+
+ Flags - Flags of the numeric
+
+ Key - Key of the numeric
+
+ FormBuffer - Output of the numeric as a form
+
+Returns:
+
+ EFI_SUCCESS - The numeric created to be a form.
+
+ EFI_DEVICE_ERROR - DataWidth > 2
+
+--*/
+{
+ EFI_IFR_NUMERIC Numeric;
+
+ //
+ // We do not create op-code storage widths for numerics in excess of 16 bits for now
+ //
+ if (DataWidth > 2) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP;
+ Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC);
+ Numeric.QuestionId = QuestionId;
+ Numeric.Width = DataWidth;
+ Numeric.Prompt = PromptToken;
+
+ Numeric.Help = HelpToken;
+ Numeric.Minimum = Minimum;
+ Numeric.Maximum = Maximum;
+ Numeric.Step = Step;
+ Numeric.Default = Default;
+ Numeric.Flags = Flags;
+ Numeric.Key = Key;
+
+ CopyMem (FormBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateStringOpCode (
+ IN UINT16 QuestionId,
+ IN UINT8 DataWidth,
+ IN STRING_REF PromptToken,
+ IN STRING_REF HelpToken,
+ IN UINT8 MinSize,
+ IN UINT8 MaxSize,
+ IN UINT8 Flags,
+ IN UINT16 Key,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a numeric opcode independent of string creation
+ This is used primarily by users who need to create just one particular valid op-code and the string
+ data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label
+ location to pre-defined forms in HII)
+
+Arguments:
+
+ QuestionId - Question ID of the string
+
+ DataWidth - DataWidth of the string
+
+ PromptToken - Prompt token of the string
+
+ HelpToken - Help token of the string
+
+ MinSize - Min size boundary of the string
+
+ MaxSize - Max size boundary of the string
+
+ Flags - Flags of the string
+
+ Key - Key of the string
+
+ FormBuffer - Output of the string as a form
+
+Returns:
+
+ EFI_SUCCESS - String created to be a form.
+
+--*/
+{
+ EFI_IFR_STRING String;
+
+ String.Header.OpCode = EFI_IFR_STRING_OP;
+ String.Header.Length = sizeof (EFI_IFR_STRING);
+ String.QuestionId = QuestionId;
+ String.Width = DataWidth;
+ String.Prompt = PromptToken;
+
+ String.Help = HelpToken;
+ String.MinSize = MinSize;
+ String.MaxSize = MaxSize;
+ String.Flags = Flags;
+ String.Key = Key;
+
+ CopyMem (FormBuffer, &String, sizeof (EFI_IFR_STRING));
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+CreateBannerOpCode (
+ IN UINT16 Title,
+ IN UINT16 LineNumber,
+ IN UINT8 Alignment,
+ IN OUT VOID *FormBuffer
+ )
+/*++
+
+Routine Description:
+
+ Create a banner opcode. This is primarily used by the FrontPage implementation from BDS.
+
+Arguments:
+
+ Title - Title of the banner
+
+ LineNumber - LineNumber of the banner
+
+ Alignment - Alignment of the banner
+
+ FormBuffer - Output of banner as a form
+
+Returns:
+
+ EFI_SUCCESS - Banner created to be a form.
+
+--*/
+{
+ EFI_IFR_BANNER Banner;
+
+ Banner.Header.OpCode = EFI_IFR_BANNER_OP;
+ Banner.Header.Length = sizeof (EFI_IFR_BANNER);
+ CopyMem (&Banner.Title, &Title, sizeof (UINT16));
+ CopyMem (&Banner.LineNumber, &LineNumber, sizeof (UINT16));
+ Banner.Alignment = Alignment;
+
+ CopyMem (FormBuffer, &Banner, sizeof (EFI_IFR_BANNER));
+
+ return EFI_SUCCESS;
+}
diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/IfrVariable.c b/EdkModulePkg/Library/EdkIfrSupportLib/IfrVariable.c
new file mode 100644
index 0000000000..3e37553668
--- /dev/null
+++ b/EdkModulePkg/Library/EdkIfrSupportLib/IfrVariable.c
@@ -0,0 +1,484 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+ IfrVariable.c
+
+Abstract:
+ Variable/Map manipulations routines
+
+--*/
+
+VOID
+EfiLibHiiVariablePackGetMap (
+ IN EFI_HII_VARIABLE_PACK *Pack,
+ OUT CHAR16 **Name, OPTIONAL
+ OUT EFI_GUID **Guid, OPTIONAL
+ OUT UINT16 *Id, OPTIONAL
+ OUT VOID **Var, OPTIONAL
+ OUT UINTN *Size OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Extracts a variable form a Pack.
+
+Arguments:
+
+ Pack - List of variables
+ Name - Name of the variable/map
+ Guid - GUID of the variable/map
+ Var - Pointer to the variable/map
+ Size - Size of the variable/map in bytes
+
+Returns:
+
+ VOID
+
+--*/
+{
+ if (NULL != Name) {
+ *Name = (VOID *) (Pack + 1);
+ }
+
+ if (NULL != Guid) {
+ *Guid = (EFI_GUID *)(UINTN)&Pack->VariableGuid;
+ }
+
+
+ if (NULL != Id) {
+ *Id = Pack->VariableId;
+ }
+
+ if (NULL != Var) {
+ *Var = (VOID *) ((CHAR8 *) (Pack + 1) + Pack->VariableNameLength);
+ }
+
+ if (NULL != Size) {
+ *Size = Pack->Header.Length - sizeof (*Pack) - Pack->VariableNameLength;
+ }
+}
+
+
+UINTN
+EfiLibHiiVariablePackListGetMapCnt (
+ IN EFI_HII_VARIABLE_PACK_LIST *List
+ )
+
+/*++
+
+Routine Description:
+
+ Finds a count of the variables/maps in the List.
+
+Arguments:
+
+ List - List of variables
+
+Returns:
+
+ UINTN - The number of map count.
+
+--*/
+
+{
+ UINTN Cnt = 0;
+ while (NULL != List) {
+ Cnt++;
+ List = List->NextVariablePack;
+ }
+ return Cnt;
+}
+
+
+VOID
+EfiLibHiiVariablePackListForEachVar (
+ IN EFI_HII_VARIABLE_PACK_LIST *List,
+ IN EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK *Callback
+ )
+/*++
+
+Routine Description:
+
+ Will iterate all variable/maps as appearing
+ in List and for each, it will call the Callback.
+
+Arguments:
+
+ List - List of variables
+ Callback - Routine to be called for each iterated variable.
+
+Returns:
+
+ VOID
+
+--*/
+
+{
+ CHAR16 *MapName;
+ EFI_GUID *MapGuid;
+ UINT16 MapId;
+ VOID *Map;
+ UINTN MapSize;
+
+ while (NULL != List) {
+ EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
+ //
+ // call the callback
+ //
+ Callback (MapName, MapGuid, MapId, Map, MapSize);
+ List = List->NextVariablePack;
+ }
+}
+
+
+EFI_STATUS
+EfiLibHiiVariablePackListGetMapByIdx (
+ IN UINTN Idx,
+ IN EFI_HII_VARIABLE_PACK_LIST *List,
+ OUT CHAR16 **Name, OPTIONAL
+ OUT EFI_GUID **Guid, OPTIONAL
+ OUT UINT16 *Id, OPTIONAL
+ OUT VOID **Var,
+ OUT UINTN *Size
+ )
+
+/*++
+
+Routine Description:
+
+ Finds a variable form List given
+ the order number as appears in the List.
+
+Arguments:
+
+ Idx - The index of the variable/map to retrieve
+ List - List of variables
+ Name - Name of the variable/map
+ Guid - GUID of the variable/map
+ Var - Pointer to the variable/map
+ Size - Size of the variable/map in bytes
+
+Returns:
+
+ EFI_SUCCESS - Variable is found, OUT parameters are valid
+ EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid
+
+--*/
+{
+ CHAR16 *MapName;
+ EFI_GUID *MapGuid;
+ UINT16 MapId;
+ VOID *Map;
+ UINTN MapSize;
+
+ while (NULL != List) {
+ EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
+ if (0 == Idx--) {
+ *Var = Map;
+ *Size = MapSize;
+
+ if (NULL != Name) {
+ *Name = MapName;
+ }
+
+ if (NULL != Guid) {
+ *Guid = MapGuid;
+ }
+
+ if (NULL != Id) {
+ *Id = MapId;
+ }
+
+ return EFI_SUCCESS; // Map found
+ }
+ List = List->NextVariablePack;
+ }
+ //
+ // If here, the map is not found
+ //
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+EfiLibHiiVariablePackListGetMapById (
+ IN UINT16 Id,
+ IN EFI_HII_VARIABLE_PACK_LIST *List,
+ OUT CHAR16 **Name, OPTIONAL
+ OUT EFI_GUID **Guid, OPTIONAL
+ OUT VOID **Var,
+ OUT UINTN *Size
+ )
+
+/*++
+
+Routine Description:
+
+ Finds a variable form List given the
+ order number as appears in the List.
+
+Arguments:
+
+ Id - The ID of the variable/map to retrieve
+ List - List of variables
+ Name - Name of the variable/map
+ Guid - GUID of the variable/map
+ Var - Pointer to the variable/map
+ Size - Size of the variable/map in bytes
+
+Returns:
+
+ EFI_SUCCESS - Variable is found, OUT parameters are valid
+ EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid
+
+--*/
+
+{
+ CHAR16 *MapName;
+ EFI_GUID *MapGuid;
+ UINT16 MapId;
+ VOID *Map;
+ UINTN MapSize;
+
+ while (NULL != List) {
+ EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
+ if (MapId == Id) {
+ *Var = Map;
+ *Size = MapSize;
+ if (NULL != Name) {
+ *Name = MapName;
+ }
+ if (NULL != Guid) {
+ *Guid = MapGuid;
+ }
+ //
+ // Map found
+ //
+ return EFI_SUCCESS;
+ }
+ List = List->NextVariablePack;
+ }
+ //
+ // If here, the map is not found
+ //
+ return EFI_NOT_FOUND;
+}
+
+
+EFI_STATUS
+EfiLibHiiVariablePackListGetMap (
+ IN EFI_HII_VARIABLE_PACK_LIST *List,
+ IN CHAR16 *Name,
+ IN EFI_GUID *Guid,
+ OUT UINT16 *Id,
+ OUT VOID **Var,
+ OUT UINTN *Size
+ )
+
+/*++
+
+Routine Description:
+
+ Finds a variable form EFI_HII_VARIABLE_PACK_LIST given name and GUID.
+
+Arguments:
+
+ List - List of variables
+ Name - Name of the variable/map to be found
+ Guid - GUID of the variable/map to be found
+ Var - Pointer to the variable/map found
+ Size - Size of the variable/map in bytes found
+
+Returns:
+
+ EFI_SUCCESS - variable is found, OUT parameters are valid
+ EFI_NOT_FOUND - variable is not found, OUT parameters are not valid
+
+--*/
+
+{
+ VOID *Map;
+ UINTN MapSize;
+ UINT16 MapId;
+ CHAR16 *MapName;
+ EFI_GUID *MapGuid;
+
+ while (NULL != List) {
+ EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);
+ if ((0 == StrCmp (Name, MapName)) && CompareGuid (Guid, MapGuid)) {
+ *Id = MapId;
+ *Var = Map;
+ *Size = MapSize;
+ return EFI_SUCCESS;
+ }
+ List = List->NextVariablePack;
+ }
+ //
+ // If here, the map is not found
+ //
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EfiLibHiiVariableRetrieveFromNv (
+ IN CHAR16 *Name,
+ IN EFI_GUID *Guid,
+ IN UINTN Size,
+ OUT VOID **Var
+ )
+/*++
+
+Routine Description:
+ Finds out if a variable of specific Name/Guid/Size exists in NV.
+ If it does, it will retrieve it into the Var.
+
+Arguments:
+ Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
+ Var - Variable will be retrieved into buffer pointed by this pointer.
+ If pointing to NULL, the buffer will be allocated. Caller is responsible for releasing the buffer.
+Returns:
+ EFI_SUCCESS - The variable of exact Name/Guid/Size parameters was retrieved and written to Var.
+ EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV.
+ EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN SizeNv;
+
+ //
+ // Test for existence of the variable.
+ //
+ SizeNv = 0;
+ Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, NULL);
+ if (EFI_BUFFER_TOO_SMALL != Status) {
+ ASSERT (EFI_SUCCESS != Status);
+ return EFI_NOT_FOUND;
+ }
+ if (SizeNv != Size) {
+ //
+ // The variable is considered corrupt, as it has different size from expected.
+ //
+ return EFI_LOAD_ERROR;
+ }
+
+ if (NULL == *Var) {
+ *Var = AllocatePool (Size);
+ ASSERT (NULL != *Var);
+ }
+ SizeNv = Size;
+ //
+ // Final read into the Var
+ //
+ Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, *Var);
+ //
+ // No tolerance for random failures. Such behavior is undetermined and not validated.
+ //
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (SizeNv == Size);
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EfiLibHiiVariableOverrideIfSuffix (
+ IN CHAR16 *Suffix,
+ IN CHAR16 *Name,
+ IN EFI_GUID *Guid,
+ IN UINTN Size,
+ OUT VOID *Var
+ )
+/*++
+
+Routine Description:
+ Overrrides the variable with NV data if found.
+ But it only does it if the Name ends with specified Suffix.
+ For example, if Suffix="MyOverride" and the Name="XyzSetupMyOverride",
+ the Suffix matches the end of Name, so the variable will be loaded from NV
+ provided the variable exists and the GUID and Size matches.
+
+Arguments:
+ Suffix - Suffix the Name should end with.
+ Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
+ Var - Variable will be retrieved into this buffer.
+ Caller is responsible for providing storage of exactly Size size in bytes.
+Returns:
+ EFI_SUCCESS - The variable was overriden with NV variable of same Name/Guid/Size.
+ EFI_INVALID_PARAMETER - The name of the variable does not end with <Suffix>.
+ EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV.
+ EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.
+
+--*/
+{
+ UINTN StrLength;
+ UINTN StrLenSuffix;
+
+ StrLength = StrLen (Name);
+ StrLenSuffix = StrLen (Suffix);
+ if ((StrLength <= StrLenSuffix) || (0 != StrCmp (Suffix, &Name[StrLength - StrLenSuffix]))) {
+ //
+ // Not ending with <Suffix>.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ return EfiLibHiiVariableRetrieveFromNv (Name, Guid, Size, &Var);
+}
+
+EFI_STATUS
+EfiLibHiiVariableOverrideBySuffix (
+ IN CHAR16 *Suffix,
+ IN CHAR16 *Name,
+ IN EFI_GUID *Guid,
+ IN UINTN Size,
+ OUT VOID *Var
+ )
+/*++
+
+Routine Description:
+ Overrrides the variable with NV data if found.
+ But it only does it if the NV contains the same variable with Name is appended with Suffix.
+ For example, if Suffix="MyOverride" and the Name="XyzSetup",
+ the Suffix will be appended to the end of Name, and the variable with Name="XyzSetupMyOverride"
+ will be loaded from NV provided the variable exists and the GUID and Size matches.
+
+Arguments:
+ Suffix - Suffix the variable will be appended with.
+ Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.
+ Var - Variable will be retrieved into this buffer.
+ Caller is responsible for providing storage of exactly Size size in bytes.
+
+Returns:
+ EFI_SUCCESS - The variable was overriden with NV variable of same Name/Guid/Size.
+ EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV.
+ EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.
+
+--*/
+{
+ EFI_STATUS Status;
+ CHAR16 *NameSuffixed;
+
+ //
+ // enough to concatenate both strings.
+ //
+ NameSuffixed = AllocateZeroPool ((StrLen (Name) + StrLen (Suffix) + 1) * sizeof (CHAR16));
+
+ StrCpy (NameSuffixed, Name);
+ StrCat (NameSuffixed, Suffix);
+
+ Status = EfiLibHiiVariableRetrieveFromNv (NameSuffixed, Guid, Size, &Var);
+ gBS->FreePool (NameSuffixed);
+
+ return Status;
+}
+
diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/build.xml b/EdkModulePkg/Library/EdkIfrSupportLib/build.xml
new file mode 100644
index 0000000000..54b607a71f
--- /dev/null
+++ b/EdkModulePkg/Library/EdkIfrSupportLib/build.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!-- Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.-->
+<project basedir="." default="EdkIfrSupportLib"><!--Apply external ANT tasks-->
+ <taskdef resource="GenBuild.tasks"/>
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+ <property environment="env"/>
+ <property name="WORKSPACE_DIR" value="${env.WORKSPACE}"/>
+ <import file="${WORKSPACE_DIR}\Tools\Conf\BuildMacro.xml"/><!--MODULE_RELATIVE PATH is relative to PACKAGE_DIR-->
+ <property name="MODULE_RELATIVE_PATH" value="Library\EdkIfrSupportLib"/>
+ <property name="MODULE_DIR" value="${PACKAGE_DIR}\${MODULE_RELATIVE_PATH}"/>
+ <property name="COMMON_FILE" value="${WORKSPACE_DIR}\Tools\Conf\Common.xml"/>
+ <target name="EdkIfrSupportLib">
+ <GenBuild baseName="EdkIfrSupportLib" mbdFilename="${MODULE_DIR}\EdkIfrSupportLib.mbd" msaFilename="${MODULE_DIR}\EdkIfrSupportLib.msa"/>
+ </target>
+ <target depends="EdkIfrSupportLib_clean" name="clean"/>
+ <target depends="EdkIfrSupportLib_cleanall" name="cleanall"/>
+ <target name="EdkIfrSupportLib_clean">
+ <OutputDirSetup baseName="EdkIfrSupportLib" mbdFilename="${MODULE_DIR}\EdkIfrSupportLib.mbd" msaFilename="${MODULE_DIR}\EdkIfrSupportLib.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\EdkIfrSupportLib_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\EdkIfrSupportLib_build.xml" target="clean"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}" excludes="*.xml"/>
+ </target>
+ <target name="EdkIfrSupportLib_cleanall">
+ <OutputDirSetup baseName="EdkIfrSupportLib" mbdFilename="${MODULE_DIR}\EdkIfrSupportLib.mbd" msaFilename="${MODULE_DIR}\EdkIfrSupportLib.msa"/>
+ <if>
+ <available file="${DEST_DIR_OUTPUT}\EdkIfrSupportLib_build.xml"/>
+ <then>
+ <ant antfile="${DEST_DIR_OUTPUT}\EdkIfrSupportLib_build.xml" target="cleanall"/>
+ </then>
+ </if>
+ <delete dir="${DEST_DIR_OUTPUT}"/>
+ <delete dir="${DEST_DIR_DEBUG}"/>
+ <delete>
+ <fileset dir="${BIN_DIR}" includes="**EdkIfrSupportLib*"/>
+ </delete>
+ </target>
+</project> \ No newline at end of file