]> git.proxmox.com Git - mirror_edk2.git/commitdiff
add in FrameworkIfrSupportLib
authorqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 29 Jun 2007 03:49:52 +0000 (03:49 +0000)
committerqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 29 Jun 2007 03:49:52 +0000 (03:49 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2881 6f19259b-4bc3-4df7-8a09-765794883524

IntelFrameworkPkg/Library/FrameworkIfrSupportLib/CommonHeader.h [new file with mode: 0644]
IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrCommon.c [new file with mode: 0644]
IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOnTheFly.c [new file with mode: 0644]
IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOpCodeCreation.c [new file with mode: 0644]
IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf [new file with mode: 0644]
IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.msa [new file with mode: 0644]
IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrVariable.c [new file with mode: 0644]

diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/CommonHeader.h b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/CommonHeader.h
new file mode 100644 (file)
index 0000000..552000f
--- /dev/null
@@ -0,0 +1,39 @@
+/**@file\r
+  Common header file shared by all source files.\r
+\r
+  This file includes package header files, library classes and protocol, PPI & GUID definitions.\r
+\r
+  Copyright (c) 2006 - 2007, Intel Corporation.\r
+  All rights reserved. This program and the accompanying materials\r
+   are licensed and made available under the terms and conditions of the BSD License\r
+   which accompanies this distribution. The full text of the license may be found at\r
+   http://opensource.org/licenses/bsd-license.php\r
+   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\r
+#ifndef __COMMON_HEADER_H_\r
+#define __COMMON_HEADER_H_\r
+\r
+\r
+//\r
+// The package level header files this module uses\r
+//\r
+#include <PiDxe.h>\r
+//\r
+// The protocols, PPI and GUID defintions for this module\r
+//\r
+#include <Guid/GlobalVariable.h>\r
+#include <Protocol/FrameworkHii.h>\r
+//\r
+// The Library classes this module consumes\r
+//\r
+#include <Library/FrameworkIfrSupportLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+\r
+#endif\r
diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrCommon.c b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrCommon.c
new file mode 100644 (file)
index 0000000..69764f7
--- /dev/null
@@ -0,0 +1,1005 @@
+/*++\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php                                            \r
+        \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+  IfrCommon.c\r
+\r
+Abstract:\r
+\r
+  Common Library Routines to assist in IFR creation on-the-fly\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+IfrLibConstruct (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetCurrentLanguage (\r
+  OUT     CHAR16              *Lang\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Determine what is the current language setting\r
+\r
+Arguments:\r
+\r
+  Lang      - Pointer of system language\r
+\r
+Returns:\r
+\r
+  Status code\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Size;\r
+  UINTN       Index;\r
+  CHAR8       Language[4];\r
+\r
+  //\r
+  // Getting the system language and placing it into our Global Data\r
+  //\r
+  Size = sizeof (Language);\r
+\r
+  Status = gRT->GetVariable (\r
+                  (CHAR16 *) L"Lang",\r
+                  &gEfiGlobalVariableGuid,\r
+                  NULL,\r
+                  &Size,\r
+                  Language\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    AsciiStrCpy (Language, "eng");\r
+  }\r
+\r
+  for (Index = 0; Index < 3; Index++) {\r
+    //\r
+    // Bitwise AND ascii value with 0xDF yields an uppercase value.\r
+    // Sign extend into a unicode value\r
+    //\r
+    Lang[Index] = (CHAR16) (Language[Index] & 0xDF);\r
+  }\r
+\r
+  //\r
+  // Null-terminate the value\r
+  //\r
+  Lang[3] = (CHAR16) 0;\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+AddString (\r
+  IN      VOID                *StringBuffer,\r
+  IN      CHAR16              *Language,\r
+  IN      CHAR16              *String,\r
+  IN OUT  STRING_REF          *StringToken\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add a string to the incoming buffer and return the token and offset data\r
+\r
+Arguments:\r
+\r
+  StringBuffer      - The incoming buffer\r
+\r
+  Language          - Currrent language\r
+\r
+  String            - The string to be added\r
+\r
+  StringToken       - The index where the string placed\r
+\r
+Returns:\r
+\r
+  EFI_OUT_OF_RESOURCES    - No enough buffer to allocate\r
+\r
+  EFI_SUCCESS             - String successfully added to the incoming buffer\r
+\r
+--*/\r
+{\r
+  EFI_HII_STRING_PACK *StringPack;\r
+  EFI_HII_STRING_PACK *StringPackBuffer;\r
+  VOID                *NewBuffer;\r
+  RELOFST             *PackSource;\r
+  RELOFST             *PackDestination;\r
+  UINT8               *Source;\r
+  UINT8               *Destination;\r
+  UINTN               Index;\r
+  BOOLEAN             Finished;\r
+  UINTN               SizeofLanguage;\r
+  UINTN               SizeofString;\r
+\r
+  StringPack  = (EFI_HII_STRING_PACK *) StringBuffer;\r
+  Finished    = FALSE;\r
+\r
+  //\r
+  // Pre-allocate a buffer sufficient for us to work on.\r
+  // We will use it as a destination scratch pad to build data on\r
+  // and when complete shift the data back to the original buffer\r
+  //\r
+  NewBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE);\r
+  if (NewBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  StringPackBuffer = (EFI_HII_STRING_PACK *) NewBuffer;\r
+\r
+  //\r
+  // StringPack is terminated with a length 0 entry\r
+  //\r
+  for (; StringPack->Header.Length != 0;) {\r
+    //\r
+    // If this stringpack's language is same as CurrentLanguage, use it\r
+    //\r
+    if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language, 3) == 0) {\r
+      //\r
+      // We have some data in this string pack, copy the string package up to the string data\r
+      //\r
+      CopyMem (&StringPackBuffer->Header, &StringPack->Header, sizeof (StringPack));\r
+\r
+      //\r
+      // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer\r
+      //\r
+      StringPackBuffer->LanguageNameString = (UINT16) (StringPackBuffer->LanguageNameString + (UINT16) sizeof (RELOFST));\r
+      StringPackBuffer->PrintableLanguageName = (UINT16) (StringPackBuffer->PrintableLanguageName + (UINT16) sizeof (RELOFST));\r
+\r
+      PackSource      = (RELOFST *) (StringPack + 1);\r
+      PackDestination = (RELOFST *) (StringPackBuffer + 1);\r
+      for (Index = 0; PackSource[Index] != 0x0000; Index++) {\r
+        //\r
+        // Copy the stringpointers from old to new buffer\r
+        // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)\r
+        //\r
+        PackDestination[Index] = (UINT16) (PackDestination[Index] + sizeof (RELOFST));\r
+      }\r
+\r
+      //\r
+      // Add a new stringpointer in the new buffer since we are adding a string.  Null terminate it\r
+      //\r
+      PackDestination[Index] = (UINT16)(PackDestination[Index-1] +\r
+                                        StrSize((CHAR16 *)((CHAR8 *)(StringPack) + PackSource[Index-1])));\r
+      PackDestination[Index + 1] = (UINT16) 0;\r
+\r
+      //\r
+      // Index is the token value for the new string\r
+      //\r
+      *StringToken = (UINT16) Index;\r
+\r
+      //\r
+      // Source now points to the beginning of the old buffer strings\r
+      // Destination now points to the beginning of the new buffer strings\r
+      //\r
+      Source      = (UINT8 *) &PackSource[Index + 1];\r
+      Destination = (UINT8 *) &PackDestination[Index + 2];\r
+\r
+      //\r
+      // This should copy all the strings from the old buffer to the new buffer\r
+      //\r
+      for (; Index != 0; Index--) {\r
+        //\r
+        // Copy Source string to destination buffer\r
+        //\r
+        StrCpy ((CHAR16 *) Destination, (CHAR16 *) Source);\r
+\r
+        //\r
+        // Adjust the source/destination to the next string location\r
+        //\r
+        Destination = Destination + StrSize ((CHAR16 *) Source);\r
+        Source      = Source + StrSize ((CHAR16 *) Source);\r
+      }\r
+\r
+      //\r
+      // This copies the new string to the destination buffer\r
+      //\r
+      StrCpy ((CHAR16 *) Destination, (CHAR16 *) String);\r
+\r
+      //\r
+      // Adjust the size of the changed string pack by adding the size of the new string\r
+      // along with the size of the additional offset entry for the new string\r
+      //\r
+      StringPackBuffer->Header.Length = (UINT32) ((UINTN) StringPackBuffer->Header.Length + StrSize (String) + sizeof (RELOFST));\r
+\r
+      //\r
+      // Advance the buffers to point to the next spots.\r
+      //\r
+      StringPackBuffer  = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPackBuffer->Header.Length);\r
+      StringPack        = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);\r
+      Finished          = TRUE;\r
+      continue;\r
+    }\r
+    //\r
+    // This isn't the language of the stringpack we were asked to add a string to\r
+    // so we need to copy it to the new buffer.\r
+    //\r
+    CopyMem (&StringPackBuffer->Header, &StringPack->Header, StringPack->Header.Length);\r
+\r
+    //\r
+    // Advance the buffers to point to the next spots.\r
+    //\r
+    StringPackBuffer  = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPack->Header.Length);\r
+    StringPack        = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);\r
+  }\r
+\r
+  //\r
+  // If we didn't copy the new data to a stringpack yet\r
+  //\r
+  if (!Finished) {\r
+    PackDestination = (RELOFST *) (StringPackBuffer + 1);\r
+    //\r
+    // Pointing to a new string pack location\r
+    //\r
+    SizeofLanguage = StrSize (Language);\r
+    SizeofString   = StrSize (String);\r
+    StringPackBuffer->Header.Length = (UINT32)\r
+      (\r
+        sizeof (EFI_HII_STRING_PACK) -\r
+        sizeof (EFI_STRING) +\r
+        sizeof (RELOFST) +\r
+        sizeof (RELOFST) +\r
+        SizeofLanguage +\r
+        SizeofString\r
+      );\r
+    StringPackBuffer->Header.Type           = EFI_HII_STRING;\r
+    StringPackBuffer->LanguageNameString    = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
+    StringPackBuffer->PrintableLanguageName = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
+    StringPackBuffer->Attributes            = 0;\r
+    PackDestination[0]                      = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);\r
+    PackDestination[1]                      = (UINT16) (PackDestination[0] + StrSize (Language));\r
+    PackDestination[2]                      = (UINT16) 0;\r
+\r
+    //\r
+    // The first string location will be set to destination.  The minimum number of strings\r
+    // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)\r
+    // and token 1 as the new string being added and and null entry for the stringpointers\r
+    //\r
+    Destination = (UINT8 *) &PackDestination[3];\r
+\r
+    //\r
+    // Copy the language name string to the new buffer\r
+    //\r
+    StrCpy ((CHAR16 *) Destination, Language);\r
+\r
+    //\r
+    // Advance the destination to the new empty spot\r
+    //\r
+    Destination = Destination + StrSize (Language);\r
+\r
+    //\r
+    // Copy the string to the new buffer\r
+    //\r
+    StrCpy ((CHAR16 *) Destination, String);\r
+\r
+    //\r
+    // Since we are starting with a new string pack - we know the new string is token 1\r
+    //\r
+    *StringToken = (UINT16) 1;\r
+  }\r
+\r
+  //\r
+  // Zero out the original buffer and copy the updated data in the new buffer to the old buffer\r
+  //\r
+  ZeroMem (StringBuffer, DEFAULT_STRING_BUFFER_SIZE);\r
+  CopyMem (StringBuffer, NewBuffer, DEFAULT_STRING_BUFFER_SIZE);\r
+\r
+  //\r
+  // Free the newly created buffer since we don't need it anymore\r
+  //\r
+  gBS->FreePool (NewBuffer);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+AddOpCode (\r
+  IN      VOID                *FormBuffer,\r
+  IN OUT  VOID                *OpCodeData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add op-code data to the FormBuffer\r
+\r
+Arguments:\r
+\r
+  FormBuffer      - Form buffer to be inserted to\r
+\r
+  OpCodeData      - Op-code data to be inserted\r
+\r
+Returns:\r
+\r
+  EFI_OUT_OF_RESOURCES    - No enough buffer to allocate\r
+\r
+  EFI_SUCCESS             - Op-code data successfully inserted\r
+\r
+--*/\r
+{\r
+  EFI_HII_PACK_HEADER *NewBuffer;\r
+  UINT8               *Source;\r
+  UINT8               *Destination;\r
+\r
+  //\r
+  // Pre-allocate a buffer sufficient for us to work on.\r
+  // We will use it as a destination scratch pad to build data on\r
+  // and when complete shift the data back to the original buffer\r
+  //\r
+  NewBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE);\r
+  if (NewBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Source      = (UINT8 *) FormBuffer;\r
+  Destination = (UINT8 *) NewBuffer;\r
+\r
+  //\r
+  // Copy the IFR Package header to the new buffer\r
+  //\r
+  CopyMem (Destination, Source, sizeof (EFI_HII_PACK_HEADER));\r
+\r
+  //\r
+  // Advance Source and Destination to next op-code\r
+  //\r
+  Source      = Source + sizeof (EFI_HII_PACK_HEADER);\r
+  Destination = Destination + sizeof (EFI_HII_PACK_HEADER);\r
+\r
+  //\r
+  // Copy data to the new buffer until we run into the end_form\r
+  //\r
+  for (; ((EFI_IFR_OP_HEADER *) Source)->OpCode != EFI_IFR_END_FORM_OP;) {\r
+    //\r
+    // If the this opcode is an end_form_set we better be creating and endform\r
+    // Nonetheless, we will add data before the end_form_set.  This also provides\r
+    // for interesting behavior in the code we will run, but has no bad side-effects\r
+    // since we will possibly do a 0 byte copy in this particular end-case.\r
+    //\r
+    if (((EFI_IFR_OP_HEADER *) Source)->OpCode == EFI_IFR_END_FORM_SET_OP) {\r
+      break;\r
+    }\r
+\r
+    //\r
+    // Copy data to new buffer\r
+    //\r
+    CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
+\r
+    //\r
+    // Adjust Source/Destination to next op-code location\r
+    //\r
+    Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
+    Source      = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
+  }\r
+\r
+  //\r
+  // Prior to the end_form is where we insert the new op-code data\r
+  //\r
+  CopyMem (Destination, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length);\r
+  Destination       = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;\r
+\r
+  NewBuffer->Length = (UINT32) (NewBuffer->Length + (UINT32) (((EFI_IFR_OP_HEADER *) OpCodeData)->Length));\r
+\r
+  //\r
+  // Copy end-form data to new buffer\r
+  //\r
+  CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
+\r
+  //\r
+  // Adjust Source/Destination to next op-code location\r
+  //\r
+  Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
+  Source      = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length;\r
+\r
+  //\r
+  // Copy end-formset data to new buffer\r
+  //\r
+  CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length);\r
+\r
+  //\r
+  // Zero out the original buffer and copy the updated data in the new buffer to the old buffer\r
+  //\r
+  ZeroMem (FormBuffer, DEFAULT_FORM_BUFFER_SIZE);\r
+  CopyMem (FormBuffer, NewBuffer, DEFAULT_FORM_BUFFER_SIZE);\r
+\r
+  //\r
+  // Free the newly created buffer since we don't need it anymore\r
+  //\r
+  gBS->FreePool (NewBuffer);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+GetHiiInterface (\r
+  OUT     EFI_HII_PROTOCOL    **Hii\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get the HII protocol interface\r
+\r
+Arguments:\r
+\r
+  Hii     - HII protocol interface\r
+\r
+Returns:\r
+\r
+  Status code\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // There should only be one HII protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiHiiProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) Hii\r
+                  );\r
+\r
+  return Status;;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+ExtractDataFromHiiHandle (\r
+  IN      EFI_HII_HANDLE      HiiHandle,\r
+  IN OUT  UINT16              *ImageLength,\r
+  OUT     UINT8               *DefaultImage,\r
+  OUT     EFI_GUID            *Guid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Extract information pertaining to the HiiHandle\r
+\r
+Arguments:\r
+\r
+  HiiHandle       - Hii handle\r
+\r
+  ImageLength     - For input, length of DefaultImage;\r
+                    For output, length of actually required\r
+\r
+  DefaultImage    - Image buffer prepared by caller\r
+\r
+  Guid            - Guid information about the form\r
+\r
+Returns:\r
+\r
+  EFI_OUT_OF_RESOURCES    - No enough buffer to allocate\r
+\r
+  EFI_BUFFER_TOO_SMALL    - DefualtImage has no enough ImageLength\r
+\r
+  EFI_SUCCESS             - Successfully extract data from Hii database.\r
+\r
+\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_HII_PROTOCOL  *Hii;\r
+  UINTN             DataLength;\r
+  UINT8             *RawData;\r
+  UINT8             *OldData;\r
+  UINTN             Index;\r
+  UINTN             Temp;\r
+  UINTN             SizeOfNvStore;\r
+  UINTN             CachedStart;\r
+\r
+  DataLength    = DEFAULT_FORM_BUFFER_SIZE;\r
+  SizeOfNvStore = 0;\r
+  CachedStart   = 0;\r
+\r
+  Status        = GetHiiInterface (&Hii);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Allocate space for retrieval of IFR data\r
+  //\r
+  RawData = AllocateZeroPool (DataLength);\r
+  if (RawData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Get all the forms associated with this HiiHandle\r
+  //\r
+  Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (RawData);\r
+\r
+    //\r
+    // Allocate space for retrieval of IFR data\r
+    //\r
+    RawData = AllocateZeroPool (DataLength);\r
+    if (RawData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Get all the forms associated with this HiiHandle\r
+    //\r
+    Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);\r
+  }\r
+\r
+  OldData = RawData;\r
+\r
+  //\r
+  // Point RawData to the beginning of the form data\r
+  //\r
+  RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));\r
+\r
+  for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
+    switch (RawData[Index]) {\r
+    case EFI_IFR_FORM_SET_OP:\r
+      //\r
+      // Copy the GUID information from this handle\r
+      //\r
+      CopyMem (Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));\r
+      break;\r
+\r
+    case EFI_IFR_ONE_OF_OP:\r
+    case EFI_IFR_CHECKBOX_OP:\r
+    case EFI_IFR_NUMERIC_OP:\r
+    case EFI_IFR_DATE_OP:\r
+    case EFI_IFR_TIME_OP:\r
+    case EFI_IFR_PASSWORD_OP:\r
+    case EFI_IFR_STRING_OP:\r
+      //\r
+      // Remember, multiple op-codes may reference the same item, so let's keep a running\r
+      // marker of what the highest QuestionId that wasn't zero length.  This will accurately\r
+      // maintain the Size of the NvStore\r
+      //\r
+      if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {\r
+        Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
+        if (SizeOfNvStore < Temp) {\r
+          SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
+        }\r
+      }\r
+    }\r
+\r
+    Index = RawData[Index + 1] + Index;\r
+  }\r
+\r
+  //\r
+  // Return an error if buffer is too small\r
+  //\r
+  if (SizeOfNvStore > *ImageLength) {\r
+    gBS->FreePool (OldData);\r
+    *ImageLength = (UINT16) SizeOfNvStore;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  if (DefaultImage != NULL) {\r
+    ZeroMem (DefaultImage, SizeOfNvStore);\r
+  }\r
+\r
+  //\r
+  // Copy the default image information to the user's buffer\r
+  //\r
+  for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
+    switch (RawData[Index]) {\r
+    case EFI_IFR_ONE_OF_OP:\r
+      CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;\r
+      break;\r
+\r
+    case EFI_IFR_ONE_OF_OPTION_OP:\r
+      if (((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Flags & EFI_IFR_FLAG_DEFAULT) {\r
+        CopyMem (&DefaultImage[CachedStart], &((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value, 2);\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_CHECKBOX_OP:\r
+      DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId] = ((EFI_IFR_CHECKBOX *) &RawData[Index])->Flags;\r
+      break;\r
+\r
+    case EFI_IFR_NUMERIC_OP:\r
+      CopyMem (\r
+        &DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId],\r
+        &((EFI_IFR_NUMERIC *) &RawData[Index])->Default,\r
+        2\r
+        );\r
+      break;\r
+\r
+    }\r
+\r
+    Index = RawData[Index + 1] + Index;\r
+  }\r
+\r
+  *ImageLength = (UINT16) SizeOfNvStore;\r
+\r
+  //\r
+  // Free our temporary repository of form data\r
+  //\r
+  gBS->FreePool (OldData);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_HII_HANDLE\r
+FindHiiHandle (\r
+  IN OUT EFI_HII_PROTOCOL    **HiiProtocol, OPTIONAL\r
+  IN     EFI_GUID            *Guid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Finds HII handle for given pack GUID previously registered with the HII.\r
+\r
+Arguments:\r
+  HiiProtocol - pointer to pointer to HII protocol interface.\r
+                If NULL, the interface will be found but not returned.\r
+                If it points to NULL, the interface will be found and\r
+                written back to the pointer that is pointed to.\r
+  Guid        - The GUID of the pack that registered with the HII.\r
+\r
+Returns:\r
+  Handle to the HII pack previously registered by the memory driver.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+\r
+  EFI_HII_HANDLE    *HiiHandleBuffer;\r
+  EFI_HII_HANDLE    HiiHandle;\r
+  UINT16            HiiHandleBufferLength;\r
+  UINT32            NumberOfHiiHandles;\r
+  EFI_GUID          HiiGuid;\r
+  EFI_HII_PROTOCOL  *HiiProt;\r
+  UINT32            Index;\r
+  UINT16            Length;\r
+\r
+  HiiHandle = 0;\r
+  if ((HiiProtocol != NULL) && (*HiiProtocol != NULL)) {\r
+    //\r
+    // The protocol has been passed in\r
+    //\r
+    HiiProt = *HiiProtocol;\r
+  } else {\r
+    gBS->LocateProtocol (\r
+          &gEfiHiiProtocolGuid,\r
+          NULL,\r
+          (VOID **) &HiiProt\r
+          );\r
+    if (HiiProt == NULL) {\r
+      return HiiHandle;\r
+    }\r
+\r
+    if (HiiProtocol != NULL) {\r
+      //\r
+      // Return back the HII protocol for the caller as promissed\r
+      //\r
+      *HiiProtocol = HiiProt;\r
+    }\r
+  }\r
+  //\r
+  // Allocate buffer\r
+  //\r
+  HiiHandleBufferLength = 10;\r
+  HiiHandleBuffer       = AllocatePool (HiiHandleBufferLength);\r
+  ASSERT (HiiHandleBuffer != NULL);\r
+\r
+  //\r
+  // Get the Handles of the packages that were registered with Hii\r
+  //\r
+  Status = HiiProt->FindHandles (\r
+                      HiiProt,\r
+                      &HiiHandleBufferLength,\r
+                      HiiHandleBuffer\r
+                      );\r
+\r
+  //\r
+  // Get a bigger bugffer if this one is to small, and try again\r
+  //\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+\r
+    gBS->FreePool (HiiHandleBuffer);\r
+\r
+    HiiHandleBuffer = AllocatePool (HiiHandleBufferLength);\r
+    ASSERT (HiiHandleBuffer != NULL);\r
+\r
+    Status = HiiProt->FindHandles (\r
+                        HiiProt,\r
+                        &HiiHandleBufferLength,\r
+                        HiiHandleBuffer\r
+                        );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto lbl_exit;\r
+  }\r
+\r
+  NumberOfHiiHandles = HiiHandleBufferLength / sizeof (EFI_HII_HANDLE);\r
+\r
+  //\r
+  // Iterate Hii handles and look for the one that matches our Guid\r
+  //\r
+  for (Index = 0; Index < NumberOfHiiHandles; Index++) {\r
+\r
+    Length = 0;\r
+    ExtractDataFromHiiHandle (HiiHandleBuffer[Index], &Length, NULL, &HiiGuid);\r
+\r
+    if (CompareGuid (&HiiGuid, Guid)) {\r
+\r
+      HiiHandle = HiiHandleBuffer[Index];\r
+      break;\r
+    }\r
+  }\r
+\r
+lbl_exit:\r
+  gBS->FreePool (HiiHandleBuffer);\r
+  return HiiHandle;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+ValidateDataFromHiiHandle (\r
+  IN      EFI_HII_HANDLE      HiiHandle,\r
+  OUT     BOOLEAN             *Results\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Validate that the data associated with the HiiHandle in NVRAM is within\r
+  the reasonable parameters for that FormSet.  Values for strings and passwords\r
+  are not verified due to their not having the equivalent of valid range settings.\r
+\r
+Arguments:\r
+\r
+  HiiHandle -   Handle of the HII database entry to query\r
+\r
+  Results -     If return Status is EFI_SUCCESS, Results provides valid data\r
+                TRUE  = NVRAM Data is within parameters\r
+                FALSE = NVRAM Data is NOT within parameters\r
+\r
+Returns:\r
+\r
+  EFI_OUT_OF_RESOURCES      - No enough buffer to allocate\r
+\r
+  EFI_SUCCESS               - Data successfully validated\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_HII_PROTOCOL  *Hii;\r
+  EFI_GUID          Guid;\r
+  UINT8             *RawData;\r
+  UINT8             *OldData;\r
+  UINTN             RawDataLength;\r
+  UINT8             *VariableData;\r
+  UINTN             Index;\r
+  UINTN             Temp;\r
+  UINTN             SizeOfNvStore;\r
+  UINTN             CachedStart;\r
+  BOOLEAN           GotMatch;\r
+\r
+  RawDataLength = DEFAULT_FORM_BUFFER_SIZE;\r
+  SizeOfNvStore = 0;\r
+  CachedStart   = 0;\r
+  GotMatch      = FALSE;\r
+  *Results      = TRUE;\r
+\r
+  Status        = GetHiiInterface (&Hii);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Allocate space for retrieval of IFR data\r
+  //\r
+  RawData = AllocateZeroPool (RawDataLength);\r
+  if (RawData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Get all the forms associated with this HiiHandle\r
+  //\r
+  Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (RawData);\r
+\r
+    //\r
+    // Allocate space for retrieval of IFR data\r
+    //\r
+    RawData = AllocateZeroPool (RawDataLength);\r
+    if (RawData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Get all the forms associated with this HiiHandle\r
+    //\r
+    Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);\r
+  }\r
+\r
+  OldData = RawData;\r
+\r
+  //\r
+  // Point RawData to the beginning of the form data\r
+  //\r
+  RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));\r
+\r
+  for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
+    if (RawData[Index] == EFI_IFR_FORM_SET_OP) {\r
+      CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));\r
+      break;\r
+    }\r
+\r
+    Index = RawData[Index + 1] + Index;\r
+  }\r
+\r
+  for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
+    switch (RawData[Index]) {\r
+    case EFI_IFR_FORM_SET_OP:\r
+      break;\r
+\r
+    case EFI_IFR_ONE_OF_OP:\r
+    case EFI_IFR_CHECKBOX_OP:\r
+    case EFI_IFR_NUMERIC_OP:\r
+    case EFI_IFR_DATE_OP:\r
+    case EFI_IFR_TIME_OP:\r
+    case EFI_IFR_PASSWORD_OP:\r
+    case EFI_IFR_STRING_OP:\r
+      //\r
+      // Remember, multiple op-codes may reference the same item, so let's keep a running\r
+      // marker of what the highest QuestionId that wasn't zero length.  This will accurately\r
+      // maintain the Size of the NvStore\r
+      //\r
+      if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {\r
+        Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
+        if (SizeOfNvStore < Temp) {\r
+          SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width;\r
+        }\r
+      }\r
+    }\r
+\r
+    Index = RawData[Index + 1] + Index;\r
+  }\r
+\r
+  //\r
+  // Allocate memory for our File Form Tags\r
+  //\r
+  VariableData = AllocateZeroPool (SizeOfNvStore);\r
+  if (VariableData == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Status = gRT->GetVariable (\r
+                  (CHAR16 *) L"Setup",\r
+                  &Guid,\r
+                  NULL,\r
+                  &SizeOfNvStore,\r
+                  (VOID *) VariableData\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+\r
+    //\r
+    // If there is a variable that exists already and it is larger than what we calculated the\r
+    // storage needs to be, we must assume the variable size from GetVariable is correct and not\r
+    // allow the truncation of the variable.  It is very possible that the user who created the IFR\r
+    // we are cracking is not referring to a variable that was in a previous map, however we cannot\r
+    // allow it's truncation.\r
+    //\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      //\r
+      // Free the buffer that was allocated that was too small\r
+      //\r
+      gBS->FreePool (VariableData);\r
+\r
+      VariableData = AllocatePool (SizeOfNvStore);\r
+      if (VariableData == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      Status = gRT->GetVariable (\r
+                      (CHAR16 *) L"Setup",\r
+                      &Guid,\r
+                      NULL,\r
+                      &SizeOfNvStore,\r
+                      (VOID *) VariableData\r
+                      );\r
+    }\r
+  }\r
+\r
+  //\r
+  // Walk through the form and see that the variable data it refers to is ok.\r
+  // This allows for the possibility of stale (obsoleted) data in the variable\r
+  // can be overlooked without causing an error\r
+  //\r
+  for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {\r
+    switch (RawData[Index]) {\r
+    case EFI_IFR_ONE_OF_OP:\r
+      //\r
+      // A one_of has no data, its the option that does - cache the storage Id\r
+      //\r
+      CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;\r
+      break;\r
+\r
+    case EFI_IFR_ONE_OF_OPTION_OP:\r
+      //\r
+      // A one_of_option can be any value\r
+      //\r
+      if (VariableData[CachedStart] == ((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value) {\r
+        GotMatch = TRUE;\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_END_ONE_OF_OP:\r
+      //\r
+      // At this point lets make sure that the data value in the NVRAM matches one of the options\r
+      //\r
+      if (!GotMatch) {\r
+        *Results = FALSE;\r
+        return EFI_SUCCESS;\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_CHECKBOX_OP:\r
+      //\r
+      // A checkbox is a boolean, so 0 and 1 are valid\r
+      // Remember, QuestionId corresponds to the offset location of the data in the variable\r
+      //\r
+      if (VariableData[((EFI_IFR_CHECKBOX *) &RawData[Index])->QuestionId] > 1) {\r
+        *Results = FALSE;\r
+        return EFI_SUCCESS;\r
+      }\r
+      break;\r
+\r
+    case EFI_IFR_NUMERIC_OP:\r
+        if ((VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] < ((EFI_IFR_NUMERIC *)&RawData[Index])->Minimum) ||\r
+            (VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] > ((EFI_IFR_NUMERIC *)&RawData[Index])->Maximum)) {\r
+        *Results = FALSE;\r
+        return EFI_SUCCESS;\r
+      }\r
+      break;\r
+\r
+    }\r
+\r
+    Index = RawData[Index + 1] + Index;\r
+  }\r
+\r
+  //\r
+  // Free our temporary repository of form data\r
+  //\r
+  gBS->FreePool (OldData);\r
+  gBS->FreePool (VariableData);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOnTheFly.c b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOnTheFly.c
new file mode 100644 (file)
index 0000000..ee99bfa
--- /dev/null
@@ -0,0 +1,977 @@
+/*++\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  IfrOnTheFly.c\r
+\r
+Abstract:\r
+\r
+  Library Routines to create IFR on-the-fly\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+EFI_STATUS\r
+CreateFormSet (\r
+  IN      CHAR16              *FormSetTitle,\r
+  IN      EFI_GUID            *Guid,\r
+  IN      UINT8               Class,\r
+  IN      UINT8               SubClass,\r
+  IN OUT  VOID                **FormBuffer,\r
+  IN OUT  VOID                **StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a formset\r
+  \r
+Arguments:\r
+  \r
+  FormSetTitle        - Title of formset\r
+  \r
+  Guid                - Guid of formset\r
+  \r
+  Class               - Class of formset\r
+  \r
+  SubClass            - Sub class of formset\r
+  \r
+  FormBuffer          - Pointer of the formset created\r
+  \r
+  StringBuffer        - Pointer of FormSetTitile string created\r
+  \r
+Returns: \r
+\r
+  EFI_OUT_OF_RESOURCES    - No enough buffer to allocate\r
+  \r
+  EFI_SUCCESS             - Formset successfully created\r
+\r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  EFI_HII_IFR_PACK      IfrPack;\r
+  EFI_IFR_FORM_SET      FormSet;\r
+  EFI_IFR_END_FORM_SET  EndFormSet;\r
+  UINT8                 *Destination;\r
+  CHAR16                CurrentLanguage[4];\r
+  STRING_REF            StringToken;\r
+\r
+  //\r
+  // Pre-allocate a buffer sufficient for us to work from.\r
+  //\r
+  FormBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE);\r
+  if (FormBuffer == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Pre-allocate a buffer sufficient for us to work from.\r
+  //\r
+  StringBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE);\r
+  if (StringBuffer == NULL) {\r
+    gBS->FreePool (FormBuffer);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  //\r
+  // Add the FormSetTitle to the string buffer and get the StringToken\r
+  //\r
+  Status = AddString (*StringBuffer, CurrentLanguage, FormSetTitle, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Initialize the Ifr Package header data\r
+  //\r
+  IfrPack.Header.Length = sizeof (EFI_HII_PACK_HEADER) + sizeof (EFI_IFR_FORM_SET) + sizeof (EFI_IFR_END_FORM_SET);\r
+  IfrPack.Header.Type   = EFI_HII_IFR;\r
+\r
+  //\r
+  // Initialize FormSet with the appropriate information\r
+  //\r
+  FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP;\r
+  FormSet.Header.Length = sizeof (EFI_IFR_FORM_SET);\r
+  FormSet.FormSetTitle  = StringToken;\r
+  FormSet.Class         = Class;\r
+  FormSet.SubClass      = SubClass;\r
+  CopyMem (&FormSet.Guid, Guid, sizeof (EFI_GUID));\r
+\r
+  //\r
+  // Initialize the end formset data\r
+  //\r
+  EndFormSet.Header.Length  = sizeof (EFI_IFR_END_FORM_SET);\r
+  EndFormSet.Header.OpCode  = EFI_IFR_END_FORM_SET_OP;\r
+\r
+  Destination               = (UINT8 *) *FormBuffer;\r
+\r
+  //\r
+  // Copy the formset/endformset data to the form buffer\r
+  //\r
+  CopyMem (Destination, &IfrPack, sizeof (EFI_HII_PACK_HEADER));\r
+\r
+  Destination = Destination + sizeof (EFI_HII_PACK_HEADER);\r
+\r
+  CopyMem (Destination, &FormSet, sizeof (EFI_IFR_FORM_SET));\r
+\r
+  Destination = Destination + sizeof (EFI_IFR_FORM_SET);\r
+\r
+  CopyMem (Destination, &EndFormSet, sizeof (EFI_IFR_END_FORM_SET));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateForm (\r
+  IN      CHAR16              *FormTitle,\r
+  IN      UINT16              FormId,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a form\r
+  \r
+Arguments:\r
+  \r
+  FormTitle       - Title of the form\r
+  \r
+  FormId          - Id of the form\r
+  \r
+  FormBuffer          - Pointer of the form created\r
+  \r
+  StringBuffer        - Pointer of FormTitil string created\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - Form successfully created\r
+\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_IFR_FORM      Form;\r
+  EFI_IFR_END_FORM  EndForm;\r
+  CHAR16            CurrentLanguage[4];\r
+  STRING_REF        StringToken;\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  Status = AddString (StringBuffer, CurrentLanguage, FormTitle, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Form.Header.OpCode  = EFI_IFR_FORM_OP;\r
+  Form.Header.Length  = sizeof (EFI_IFR_FORM);\r
+  Form.FormId         = FormId;\r
+  Form.FormTitle      = StringToken;\r
+\r
+  Status              = AddOpCode (FormBuffer, &Form);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  EndForm.Header.OpCode = EFI_IFR_END_FORM_OP;\r
+  EndForm.Header.Length = sizeof (EFI_IFR_END_FORM);\r
+\r
+  Status                = AddOpCode (FormBuffer, &EndForm);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateSubTitle (\r
+  IN      CHAR16              *SubTitle,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a SubTitle\r
+  \r
+Arguments:\r
+  \r
+  SubTitle        - Sub title to be created\r
+  \r
+  FormBuffer      - Where this subtitle to add to\r
+  \r
+  StringBuffer    - String buffer created for subtitle\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - Subtitle successfully created\r
+\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_IFR_SUBTITLE  Subtitle;\r
+  CHAR16            CurrentLanguage[4];\r
+  STRING_REF        StringToken;\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  Status = AddString (StringBuffer, CurrentLanguage, SubTitle, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Subtitle.Header.OpCode  = EFI_IFR_SUBTITLE_OP;\r
+  Subtitle.Header.Length  = sizeof (EFI_IFR_SUBTITLE);\r
+  Subtitle.SubTitle       = StringToken;\r
+\r
+  Status                  = AddOpCode (FormBuffer, &Subtitle);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateText (\r
+  IN      CHAR16              *String,\r
+  IN      CHAR16              *String2,\r
+  IN      CHAR16              *String3,\r
+  IN      UINT8               Flags,\r
+  IN      UINT16              Key,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a line of text\r
+  \r
+Arguments:\r
+  \r
+  String          - First string of the text\r
+  \r
+  String2         - Second string of the text\r
+  \r
+  String3         - Help string of the text\r
+  \r
+  Flags           - Flag of the text\r
+  \r
+  Key             - Key of the text\r
+  \r
+  FormBuffer      - The form where this text adds to\r
+  \r
+  StringBuffer    - String buffer created for String, String2 and String3\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - Text successfully created\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  EFI_IFR_TEXT  Text;\r
+  CHAR16        CurrentLanguage[4];\r
+  STRING_REF    StringToken;\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  //\r
+  // Add first string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, String, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Text.Header.OpCode  = EFI_IFR_TEXT_OP;\r
+  Text.Header.Length  = sizeof (EFI_IFR_TEXT);\r
+  Text.Text           = StringToken;\r
+\r
+  //\r
+  // Add second string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, String2, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Text.TextTwo  = StringToken;\r
+\r
+  Text.Flags    = (UINT8) (Flags | EFI_IFR_FLAG_CREATED);\r
+  Text.Key      = Key;\r
+\r
+  //\r
+  // Add second string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, String3, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Text.Help = StringToken;\r
+\r
+  Status    = AddOpCode (FormBuffer, &Text);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateGoto (\r
+  IN      UINT16              FormId,\r
+  IN      CHAR16              *Prompt,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a hyperlink\r
+  \r
+Arguments:\r
+  \r
+  FormId        - Form ID of the hyperlink\r
+  \r
+  Prompt        - Prompt of the hyperlink\r
+  \r
+  FormBuffer    - The form where this hyperlink adds to\r
+  \r
+  StringBuffer  - String buffer created for Prompt\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - Hyperlink successfully created\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  EFI_IFR_REF Hyperlink;\r
+  CHAR16      CurrentLanguage[4];\r
+  STRING_REF  StringToken;\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Hyperlink.Header.OpCode = EFI_IFR_REF_OP;\r
+  Hyperlink.Header.Length = sizeof (EFI_IFR_REF);\r
+  Hyperlink.FormId        = FormId;\r
+  Hyperlink.Prompt        = StringToken;\r
+\r
+  Status                  = AddOpCode (FormBuffer, &Hyperlink);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateOneOf (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               DataWidth,\r
+  IN      CHAR16              *Prompt,\r
+  IN      CHAR16              *Help,\r
+  IN      IFR_OPTION          *OptionsList,\r
+  IN      UINTN               OptionCount,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a one-of question with a set of options to choose from.  The\r
+  OptionsList is a pointer to a null-terminated list of option descriptions.\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the one-of box\r
+  \r
+  DataWidth       - DataWidth of the one-of box\r
+  \r
+  Prompt          - Prompt of the one-of box\r
+  \r
+  Help            - Help of the one-of box\r
+  \r
+  OptionsList     - Each string in it is an option of the one-of box\r
+  \r
+  OptionCount     - Option string count\r
+  \r
+  FormBuffer      - The form where this one-of box adds to\r
+  \r
+  StringBuffer    - String buffer created for Prompt, Help and Option strings\r
+  \r
+Returns: \r
+\r
+  EFI_DEVICE_ERROR    - DataWidth > 2\r
+\r
+  EFI_SUCCESS         - One-Of box successfully created.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  UINTN                 Index;\r
+  EFI_IFR_ONE_OF        OneOf;\r
+  EFI_IFR_ONE_OF_OPTION OneOfOption;\r
+  EFI_IFR_END_ONE_OF    EndOneOf;\r
+  CHAR16                CurrentLanguage[4];\r
+  STRING_REF            StringToken;\r
+\r
+  //\r
+  // We do not create op-code storage widths for one-of in excess of 16 bits for now\r
+  //\r
+  if (DataWidth > 2) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  //\r
+  // Add first string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP;\r
+  OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF);\r
+  OneOf.QuestionId    = QuestionId;\r
+  OneOf.Width         = DataWidth;\r
+  OneOf.Prompt        = StringToken;\r
+\r
+  //\r
+  // Add second string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OneOf.Help  = StringToken;\r
+\r
+  Status      = AddOpCode (FormBuffer, &OneOf);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;\r
+    OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);\r
+\r
+    //\r
+    // Add string and get token back\r
+    //\r
+    Status              = AddString (StringBuffer, CurrentLanguage, OptionsList[Index].OptionString, &StringToken);\r
+\r
+    OneOfOption.Option  = StringToken;\r
+    OneOfOption.Value   = OptionsList[Index].Value;\r
+    OneOfOption.Flags   = (UINT8) (OptionsList[Index].Flags | EFI_IFR_FLAG_CREATED);\r
+    OneOfOption.Key     = OptionsList[Index].Key;\r
+\r
+    Status              = AddOpCode (FormBuffer, &OneOfOption);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  EndOneOf.Header.Length  = sizeof (EFI_IFR_END_ONE_OF);\r
+  EndOneOf.Header.OpCode  = EFI_IFR_END_ONE_OF_OP;\r
+\r
+  Status                  = AddOpCode (FormBuffer, &EndOneOf);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+CreateOrderedList (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               MaxEntries,\r
+  IN      CHAR16              *Prompt,\r
+  IN      CHAR16              *Help,\r
+  IN      IFR_OPTION          *OptionsList,\r
+  IN      UINTN               OptionCount,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a one-of question with a set of options to choose from.  The\r
+  OptionsList is a pointer to a null-terminated list of option descriptions.\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the ordered list\r
+  \r
+  MaxEntries      - MaxEntries of the ordered list\r
+  \r
+  Prompt          - Prompt of the ordered list\r
+  \r
+  Help            - Help of the ordered list\r
+  \r
+  OptionsList     - Each string in it is an option of the ordered list\r
+  \r
+  OptionCount     - Option string count\r
+  \r
+  FormBuffer      - The form where this ordered list adds to\r
+  \r
+  StringBuffer    - String buffer created for Prompt, Help and Option strings\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - Ordered list successfully created.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS            Status;\r
+  UINTN                 Index;\r
+  EFI_IFR_ORDERED_LIST  OrderedList;\r
+  EFI_IFR_ONE_OF_OPTION OrderedListOption;\r
+  EFI_IFR_END_ONE_OF    EndOrderedList;\r
+  CHAR16                CurrentLanguage[4];\r
+  STRING_REF            StringToken;\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  //\r
+  // Add first string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;\r
+  OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST);\r
+  OrderedList.QuestionId    = QuestionId;\r
+  OrderedList.MaxEntries    = MaxEntries;\r
+  OrderedList.Prompt        = StringToken;\r
+\r
+  //\r
+  // Add second string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  OrderedList.Help  = StringToken;\r
+\r
+  Status            = AddOpCode (FormBuffer, &OrderedList);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    OrderedListOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;\r
+    OrderedListOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);\r
+\r
+    //\r
+    // Add string and get token back\r
+    //\r
+    Status                    = AddString (StringBuffer, CurrentLanguage, OptionsList[Index].OptionString, &StringToken);\r
+\r
+    OrderedListOption.Option  = StringToken;\r
+    OrderedListOption.Value   = OptionsList[Index].Value;\r
+    OrderedListOption.Flags   = (UINT8) (OptionsList[Index].Flags | EFI_IFR_FLAG_CREATED);\r
+    OrderedListOption.Key     = OptionsList[Index].Key;\r
+\r
+    Status                    = AddOpCode (FormBuffer, &OrderedListOption);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  EndOrderedList.Header.Length  = sizeof (EFI_IFR_END_ONE_OF);\r
+  EndOrderedList.Header.OpCode  = EFI_IFR_END_ONE_OF_OP;\r
+\r
+  Status                        = AddOpCode (FormBuffer, &EndOrderedList);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateCheckBox (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               DataWidth,\r
+  IN      CHAR16              *Prompt,\r
+  IN      CHAR16              *Help,\r
+  IN      UINT8               Flags,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a checkbox\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the check box\r
+  \r
+  DataWidth       - DataWidth of the check box\r
+  \r
+  Prompt          - Prompt of the check box\r
+  \r
+  Help            - Help of the check box\r
+  \r
+  Flags           - Flags of the check box\r
+  \r
+  FormBuffer      - The form where this check box adds to\r
+  \r
+  StringBuffer    - String buffer created for Prompt and Help.\r
+  \r
+Returns: \r
+\r
+  EFI_DEVICE_ERROR    - DataWidth > 1\r
+\r
+  EFI_SUCCESS         - Check box successfully created\r
+\r
+--*/\r
+{\r
+  EFI_STATUS        Status;\r
+  EFI_IFR_CHECKBOX  CheckBox;\r
+  CHAR16            CurrentLanguage[4];\r
+  STRING_REF        StringToken;\r
+\r
+  //\r
+  // We do not create op-code storage widths for checkbox in excess of 8 bits for now\r
+  //\r
+  if (DataWidth > 1) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  //\r
+  // Add first string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  CheckBox.Header.OpCode  = EFI_IFR_CHECKBOX_OP;\r
+  CheckBox.Header.Length  = sizeof (EFI_IFR_CHECKBOX);\r
+  CheckBox.QuestionId     = QuestionId;\r
+  CheckBox.Width          = DataWidth;\r
+  CheckBox.Prompt         = StringToken;\r
+\r
+  //\r
+  // Add second string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  CheckBox.Help   = StringToken;\r
+  CheckBox.Flags  = (UINT8) (Flags | EFI_IFR_FLAG_CREATED);\r
+\r
+  Status          = AddOpCode (FormBuffer, &CheckBox);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateNumeric (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               DataWidth,\r
+  IN      CHAR16              *Prompt,\r
+  IN      CHAR16              *Help,\r
+  IN      UINT16              Minimum,\r
+  IN      UINT16              Maximum,\r
+  IN      UINT16              Step,\r
+  IN      UINT16              Default,\r
+  IN      UINT8               Flags,\r
+  IN      UINT16              Key,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a numeric\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the numeric\r
+  \r
+  DataWidth       - DataWidth of the numeric\r
+  \r
+  Prompt          - Prompt of the numeric\r
+  \r
+  Help            - Help of the numeric\r
+  \r
+  Minimum         - Minumun boundary of the numeric\r
+  \r
+  Maximum         - Maximum boundary of the numeric\r
+  \r
+  Step            - Step of the numeric\r
+  \r
+  Default         - Default value\r
+  \r
+  Flags           - Flags of the numeric\r
+  \r
+  Key             - Key of the numeric\r
+  \r
+  FormBuffer      - The form where this numeric adds to\r
+  \r
+  StringBuffer    - String buffer created for Prompt and Help.\r
+  \r
+Returns: \r
+\r
+  EFI_DEVICE_ERROR      - DataWidth > 2\r
+  \r
+  EFI_SUCCESS           - Numeric is successfully created\r
+\r
+--*/\r
+{\r
+  EFI_STATUS      Status;\r
+  EFI_IFR_NUMERIC Numeric;\r
+  CHAR16          CurrentLanguage[4];\r
+  STRING_REF      StringToken;\r
+\r
+  //\r
+  // We do not create op-code storage widths for numerics in excess of 16 bits for now\r
+  //\r
+  if (DataWidth > 2) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  //\r
+  // Add first string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP;\r
+  Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC);\r
+  Numeric.QuestionId    = QuestionId;\r
+  Numeric.Width         = DataWidth;\r
+  Numeric.Prompt        = StringToken;\r
+\r
+  //\r
+  // Add second string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Numeric.Help    = StringToken;\r
+  Numeric.Minimum = Minimum;\r
+  Numeric.Maximum = Maximum;\r
+  Numeric.Step    = Step;\r
+  Numeric.Default = Default;\r
+  Numeric.Flags   = (UINT8) (Flags | EFI_IFR_FLAG_CREATED);\r
+  Numeric.Key     = Key;\r
+\r
+  Status          = AddOpCode (FormBuffer, &Numeric);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateString (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               DataWidth,\r
+  IN      CHAR16              *Prompt,\r
+  IN      CHAR16              *Help,\r
+  IN      UINT8               MinSize,\r
+  IN      UINT8               MaxSize,\r
+  IN      UINT8               Flags,\r
+  IN      UINT16              Key,\r
+  IN OUT  VOID                *FormBuffer,\r
+  IN OUT  VOID                *StringBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a string\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the string\r
+  \r
+  DataWidth       - DataWidth of the string\r
+  \r
+  Prompt          - Prompt of the string\r
+  \r
+  Help            - Help of the string\r
+  \r
+  MinSize         - Min size boundary of the string\r
+  \r
+  MaxSize         - Max size boundary of the string\r
+    \r
+  Flags           - Flags of the string\r
+  \r
+  Key             - Key of the string\r
+  \r
+  FormBuffer      - The form where this string adds to\r
+  \r
+  StringBuffer    - String buffer created for Prompt and Help.\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - String successfully created.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS      Status;\r
+  EFI_IFR_STRING  String;\r
+  CHAR16          CurrentLanguage[4];\r
+  STRING_REF      StringToken;\r
+\r
+  //\r
+  // Obtain current language value\r
+  //\r
+  GetCurrentLanguage (CurrentLanguage);\r
+\r
+  //\r
+  // Add first string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  String.Header.OpCode  = EFI_IFR_STRING_OP;\r
+  String.Header.Length  = sizeof (EFI_IFR_STRING);\r
+  String.QuestionId     = QuestionId;\r
+  String.Width          = DataWidth;\r
+  String.Prompt         = StringToken;\r
+\r
+  //\r
+  // Add second string, get first string's token\r
+  //\r
+  Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  String.Help     = StringToken;\r
+  String.MinSize  = MinSize;\r
+  String.MaxSize  = MaxSize;\r
+  String.Flags    = (UINT8) (Flags | EFI_IFR_FLAG_CREATED);\r
+  String.Key      = Key;\r
+\r
+  Status          = AddOpCode (FormBuffer, &String);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOpCodeCreation.c b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrOpCodeCreation.c
new file mode 100644 (file)
index 0000000..7bcb453
--- /dev/null
@@ -0,0 +1,618 @@
+/*++\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  IfrOpCodeCreation.c\r
+\r
+Abstract:\r
+\r
+  Library Routines to create IFR independent of string data - assume tokens already exist\r
+  Primarily to be used for exporting op-codes at a label in pre-defined forms.\r
+\r
+Revision History:\r
+\r
+--*/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+EFI_STATUS\r
+CreateSubTitleOpCode (\r
+  IN      STRING_REF          StringToken,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a SubTitle opcode independent of string creation\r
+  This is used primarily by users who need to create just one particular valid op-code and the string\r
+  data will be assumed to exist in the HiiDatabase already.  (Useful when exporting op-codes at a label\r
+  location to pre-defined forms in HII)\r
+  \r
+Arguments:\r
+  \r
+  StringToken     - StringToken of the subtitle\r
+  \r
+  FormBuffer      - Output of subtitle as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - Subtitle created to be a form\r
+\r
+--*/\r
+{\r
+  EFI_IFR_SUBTITLE  Subtitle;\r
+\r
+  Subtitle.Header.OpCode  = EFI_IFR_SUBTITLE_OP;\r
+  Subtitle.Header.Length  = sizeof (EFI_IFR_SUBTITLE);\r
+  Subtitle.SubTitle       = StringToken;\r
+\r
+  CopyMem (FormBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateTextOpCode (\r
+  IN      STRING_REF          StringToken,\r
+  IN      STRING_REF          StringTokenTwo,\r
+  IN      STRING_REF          StringTokenThree,\r
+  IN      UINT8               Flags,\r
+  IN      UINT16              Key,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a Text opcode independent of string creation\r
+  This is used primarily by users who need to create just one particular valid op-code and the string\r
+  data will be assumed to exist in the HiiDatabase already.  (Useful when exporting op-codes at a label\r
+  location to pre-defined forms in HII)\r
+  \r
+Arguments:\r
+  \r
+  StringToken               - First string token of the text\r
+  \r
+  StringTokenTwo            - Second string token of the text\r
+  \r
+  StringTokenThree          - Help string token of the text\r
+  \r
+  Flags                     - Flag of the text\r
+  \r
+  Key                       - Key of the text\r
+  \r
+  FormBuffer                - Output of text as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS       - Text created to be a form\r
+\r
+--*/\r
+{\r
+  EFI_IFR_TEXT  Text;\r
+\r
+  Text.Header.OpCode  = EFI_IFR_TEXT_OP;\r
+  Text.Header.Length  = sizeof (EFI_IFR_TEXT);\r
+  Text.Text           = StringToken;\r
+\r
+  Text.TextTwo        = StringTokenTwo;\r
+  Text.Help           = StringTokenThree;\r
+  Text.Flags          = Flags;\r
+  Text.Key            = Key;\r
+\r
+  CopyMem (FormBuffer, &Text, sizeof (EFI_IFR_TEXT));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateGotoOpCode (\r
+  IN      UINT16              FormId,\r
+  IN      STRING_REF          StringToken,\r
+  IN      STRING_REF          StringTokenTwo,\r
+  IN      UINT8               Flags,\r
+  IN      UINT16              Key,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a hyperlink opcode independent of string creation\r
+  This is used primarily by users who need to create just one particular valid op-code and the string\r
+  data will be assumed to exist in the HiiDatabase already.  (Useful when exporting op-codes at a label\r
+  location to pre-defined forms in HII)\r
+  \r
+Arguments:\r
+  \r
+  FormId          - Form ID of the hyperlink\r
+  \r
+  StringToken     - Prompt string token of the hyperlink\r
+  \r
+  StringTokenTwo  - Help string token of the hyperlink\r
+  \r
+  Flags           - Flags of the hyperlink\r
+  \r
+  Key             - Key of the hyperlink\r
+  \r
+  FormBuffer      - Output of hyperlink as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS   - Hyperlink created to be a form\r
+\r
+--*/\r
+{\r
+  EFI_IFR_REF Hyperlink;\r
+\r
+  Hyperlink.Header.OpCode = EFI_IFR_REF_OP;\r
+  Hyperlink.Header.Length = sizeof (EFI_IFR_REF);\r
+  Hyperlink.FormId        = FormId;\r
+  Hyperlink.Prompt        = StringToken;\r
+  Hyperlink.Help          = StringTokenTwo;\r
+  Hyperlink.Key           = Key;\r
+  Hyperlink.Flags         = Flags;\r
+\r
+  CopyMem (FormBuffer, &Hyperlink, sizeof (EFI_IFR_REF));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateOneOfOpCode (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               DataWidth,\r
+  IN      STRING_REF          PromptToken,\r
+  IN      STRING_REF          HelpToken,\r
+  IN      IFR_OPTION          *OptionsList,\r
+  IN      UINTN               OptionCount,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a one-of opcode with a set of option op-codes to choose from independent of string creation.\r
+  This is used primarily by users who need to create just one particular valid op-code and the string\r
+  data will be assumed to exist in the HiiDatabase already.  (Useful when exporting op-codes at a label\r
+  location to pre-defined forms in HII)\r
+\r
+  OptionsList is a pointer to a null-terminated list of option descriptions.  Ensure that OptionsList[x].StringToken\r
+  has been filled in since this routine will not generate StringToken values.\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the one-of box\r
+  \r
+  DataWidth       - DataWidth of the one-of box\r
+  \r
+  PromptToken     - Prompt string token of the one-of box\r
+  \r
+  HelpToken       - Help string token of the one-of box\r
+  \r
+  OptionsList     - Each string in it is an option of the one-of box\r
+  \r
+  OptionCount     - Option string count\r
+  \r
+  FormBuffer      - Output of One-Of box as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS         - One-Of box created to be a form\r
+  \r
+  EFI_DEVICE_ERROR    - DataWidth > 2\r
+\r
+--*/\r
+{\r
+  UINTN                 Index;\r
+  EFI_IFR_ONE_OF        OneOf;\r
+  EFI_IFR_ONE_OF_OPTION OneOfOption;\r
+  EFI_IFR_END_ONE_OF    EndOneOf;\r
+  UINT8                 *LocalBuffer;\r
+\r
+  //\r
+  // We do not create op-code storage widths for one-of in excess of 16 bits for now\r
+  //\r
+  if (DataWidth > 2) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP;\r
+  OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF);\r
+  OneOf.QuestionId    = QuestionId;\r
+  OneOf.Width         = DataWidth;\r
+  OneOf.Prompt        = PromptToken;\r
+\r
+  OneOf.Help          = HelpToken;\r
+\r
+  LocalBuffer         = (UINT8 *) FormBuffer;\r
+\r
+  CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF));\r
+\r
+  LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF));\r
+\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;\r
+    OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);\r
+\r
+    OneOfOption.Option        = OptionsList[Index].StringToken;\r
+    OneOfOption.Value         = OptionsList[Index].Value;\r
+    OneOfOption.Flags         = OptionsList[Index].Flags;\r
+    OneOfOption.Key           = OptionsList[Index].Key;\r
+\r
+    CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION));\r
+\r
+    LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF_OPTION));\r
+  }\r
+\r
+  EndOneOf.Header.Length  = sizeof (EFI_IFR_END_ONE_OF);\r
+  EndOneOf.Header.OpCode  = EFI_IFR_END_ONE_OF_OP;\r
+\r
+  CopyMem (LocalBuffer, &EndOneOf, sizeof (EFI_IFR_END_ONE_OF));\r
+\r
+  LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_END_ONE_OF));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+CreateOrderedListOpCode (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               MaxEntries,\r
+  IN      STRING_REF          PromptToken,\r
+  IN      STRING_REF          HelpToken,\r
+  IN      IFR_OPTION          *OptionsList,\r
+  IN      UINTN               OptionCount,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a ordered list opcode with a set of option op-codes to choose from independent of string creation.\r
+  This is used primarily by users who need to create just one particular valid op-code and the string\r
+  data will be assumed to exist in the HiiDatabase already.  (Useful when exporting op-codes at a label\r
+  location to pre-defined forms in HII)\r
+\r
+  OptionsList is a pointer to a null-terminated list of option descriptions.  Ensure that OptionsList[x].StringToken\r
+  has been filled in since this routine will not generate StringToken values.\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the ordered list\r
+  \r
+  MaxEntries      - MaxEntries of the ordered list\r
+  \r
+  PromptToken     - Prompt string token of the ordered list\r
+  \r
+  HelpToken       - Help string token of the ordered list\r
+  \r
+  OptionsList     - Each string in it is an option of the ordered list\r
+  \r
+  OptionCount     - Option string count\r
+  \r
+  FormBuffer      - Output of ordered list as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - Ordered list created to be a form\r
+\r
+--*/\r
+{\r
+  UINTN                 Index;\r
+  EFI_IFR_ORDERED_LIST  OrderedList;\r
+  EFI_IFR_ONE_OF_OPTION OrderedListOption;\r
+  EFI_IFR_END_ONE_OF    EndOrderedList;\r
+  UINT8                 *LocalBuffer;\r
+\r
+  OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP;\r
+  OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST);\r
+  OrderedList.QuestionId    = QuestionId;\r
+  OrderedList.MaxEntries    = MaxEntries;\r
+  OrderedList.Prompt        = PromptToken;\r
+\r
+  OrderedList.Help          = HelpToken;\r
+\r
+  LocalBuffer               = (UINT8 *) FormBuffer;\r
+\r
+  CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST));\r
+\r
+  LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ORDERED_LIST));\r
+\r
+  for (Index = 0; Index < OptionCount; Index++) {\r
+    OrderedListOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP;\r
+    OrderedListOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION);\r
+\r
+    OrderedListOption.Option        = OptionsList[Index].StringToken;\r
+    OrderedListOption.Value         = OptionsList[Index].Value;\r
+    OrderedListOption.Flags         = OptionsList[Index].Flags;\r
+    OrderedListOption.Key           = OptionsList[Index].Key;\r
+\r
+    CopyMem (LocalBuffer, &OrderedListOption, sizeof (EFI_IFR_ONE_OF_OPTION));\r
+\r
+    LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF_OPTION));\r
+  }\r
+\r
+  EndOrderedList.Header.Length  = sizeof (EFI_IFR_END_ONE_OF);\r
+  EndOrderedList.Header.OpCode  = EFI_IFR_END_ONE_OF_OP;\r
+\r
+  CopyMem (LocalBuffer, &EndOrderedList, sizeof (EFI_IFR_END_ONE_OF));\r
+\r
+  LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_END_ONE_OF));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+CreateCheckBoxOpCode (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               DataWidth,\r
+  IN      STRING_REF          PromptToken,\r
+  IN      STRING_REF          HelpToken,\r
+  IN      UINT8               Flags,\r
+  IN      UINT16              Key,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a checkbox opcode independent of string creation\r
+  This is used primarily by users who need to create just one particular valid op-code and the string\r
+  data will be assumed to exist in the HiiDatabase already.  (Useful when exporting op-codes at a label\r
+  location to pre-defined forms in HII)\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the check box\r
+  \r
+  DataWidth       - DataWidth of the check box\r
+  \r
+  PromptToken     - Prompt string token of the check box\r
+  \r
+  HelpToken       - Help string token of the check box\r
+  \r
+  Flags           - Flags of the check box\r
+  \r
+  Key             - Key of the check box\r
+  \r
+  FormBuffer      - Output of the check box as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS       - Checkbox created to be a form\r
+  \r
+  EFI_DEVICE_ERROR  - DataWidth > 1\r
+\r
+--*/\r
+{\r
+  EFI_IFR_CHECKBOX  CheckBox;\r
+\r
+  //\r
+  // We do not create op-code storage widths for checkbox in excess of 8 bits for now\r
+  //\r
+  if (DataWidth > 1) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  CheckBox.Header.OpCode  = EFI_IFR_CHECKBOX_OP;\r
+  CheckBox.Header.Length  = sizeof (EFI_IFR_CHECKBOX);\r
+  CheckBox.QuestionId     = QuestionId;\r
+  CheckBox.Width          = DataWidth;\r
+  CheckBox.Prompt         = PromptToken;\r
+\r
+  CheckBox.Help           = HelpToken;\r
+  CheckBox.Flags          = Flags;\r
+  CheckBox.Key            = Key;\r
+\r
+  CopyMem (FormBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateNumericOpCode (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               DataWidth,\r
+  IN      STRING_REF          PromptToken,\r
+  IN      STRING_REF          HelpToken,\r
+  IN      UINT16              Minimum,\r
+  IN      UINT16              Maximum,\r
+  IN      UINT16              Step,\r
+  IN      UINT16              Default,\r
+  IN      UINT8               Flags,\r
+  IN      UINT16              Key,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a numeric opcode independent of string creation\r
+  This is used primarily by users who need to create just one particular valid op-code and the string\r
+  data will be assumed to exist in the HiiDatabase already.  (Useful when exporting op-codes at a label\r
+  location to pre-defined forms in HII)\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the numeric\r
+  \r
+  DataWidth       - DataWidth of the numeric\r
+  \r
+  PromptToken     - Prompt string token of the numeric\r
+  \r
+  HelpToken       - Help string token of the numeric\r
+  \r
+  Minimum         - Minumun boundary of the numeric\r
+  \r
+  Maximum         - Maximum boundary of the numeric\r
+  \r
+  Step            - Step of the numeric\r
+  \r
+  Default         - Default value of the numeric\r
+  \r
+  Flags           - Flags of the numeric\r
+  \r
+  Key             - Key of the numeric\r
+  \r
+  FormBuffer      - Output of the numeric as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS       - The numeric created to be a form.\r
+  \r
+  EFI_DEVICE_ERROR  - DataWidth > 2\r
+\r
+--*/\r
+{\r
+  EFI_IFR_NUMERIC Numeric;\r
+\r
+  //\r
+  // We do not create op-code storage widths for numerics in excess of 16 bits for now\r
+  //\r
+  if (DataWidth > 2) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP;\r
+  Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC);\r
+  Numeric.QuestionId    = QuestionId;\r
+  Numeric.Width         = DataWidth;\r
+  Numeric.Prompt        = PromptToken;\r
+\r
+  Numeric.Help          = HelpToken;\r
+  Numeric.Minimum       = Minimum;\r
+  Numeric.Maximum       = Maximum;\r
+  Numeric.Step          = Step;\r
+  Numeric.Default       = Default;\r
+  Numeric.Flags         = Flags;\r
+  Numeric.Key           = Key;\r
+\r
+  CopyMem (FormBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateStringOpCode (\r
+  IN      UINT16              QuestionId,\r
+  IN      UINT8               DataWidth,\r
+  IN      STRING_REF          PromptToken,\r
+  IN      STRING_REF          HelpToken,\r
+  IN      UINT8               MinSize,\r
+  IN      UINT8               MaxSize,\r
+  IN      UINT8               Flags,\r
+  IN      UINT16              Key,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a numeric opcode independent of string creation\r
+  This is used primarily by users who need to create just one particular valid op-code and the string\r
+  data will be assumed to exist in the HiiDatabase already.  (Useful when exporting op-codes at a label\r
+  location to pre-defined forms in HII)\r
+  \r
+Arguments:\r
+  \r
+  QuestionId      - Question ID of the string\r
+  \r
+  DataWidth       - DataWidth of the string\r
+  \r
+  PromptToken     - Prompt token of the string\r
+  \r
+  HelpToken       - Help token of the string\r
+  \r
+  MinSize         - Min size boundary of the string\r
+  \r
+  MaxSize         - Max size boundary of the string\r
+    \r
+  Flags           - Flags of the string\r
+  \r
+  Key             - Key of the string\r
+  \r
+  FormBuffer      - Output of the string as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS       - String created to be a form.\r
+\r
+--*/\r
+{\r
+  EFI_IFR_STRING  String;\r
+\r
+  String.Header.OpCode  = EFI_IFR_STRING_OP;\r
+  String.Header.Length  = sizeof (EFI_IFR_STRING);\r
+  String.QuestionId     = QuestionId;\r
+  String.Width          = DataWidth;\r
+  String.Prompt         = PromptToken;\r
+\r
+  String.Help           = HelpToken;\r
+  String.MinSize        = MinSize;\r
+  String.MaxSize        = MaxSize;\r
+  String.Flags          = Flags;\r
+  String.Key            = Key;\r
+\r
+  CopyMem (FormBuffer, &String, sizeof (EFI_IFR_STRING));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+CreateBannerOpCode (\r
+  IN      UINT16              Title,\r
+  IN      UINT16              LineNumber,\r
+  IN      UINT8               Alignment,\r
+  IN OUT  VOID                *FormBuffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a banner opcode.  This is primarily used by the FrontPage implementation from BDS.\r
+  \r
+Arguments:\r
+  \r
+  Title       - Title of the banner\r
+  \r
+  LineNumber  - LineNumber of the banner\r
+  \r
+  Alignment   - Alignment of the banner\r
+  \r
+  FormBuffer  - Output of banner as a form\r
+  \r
+Returns: \r
+\r
+  EFI_SUCCESS     - Banner created to be a form.\r
+\r
+--*/\r
+{\r
+  EFI_IFR_BANNER  Banner;\r
+\r
+  Banner.Header.OpCode  = EFI_IFR_BANNER_OP;\r
+  Banner.Header.Length  = sizeof (EFI_IFR_BANNER);\r
+  CopyMem (&Banner.Title, &Title, sizeof (UINT16));\r
+  CopyMem (&Banner.LineNumber, &LineNumber, sizeof (UINT16));\r
+  Banner.Alignment = Alignment;\r
+\r
+  CopyMem (FormBuffer, &Banner, sizeof (EFI_IFR_BANNER));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf
new file mode 100644 (file)
index 0000000..3fa870c
--- /dev/null
@@ -0,0 +1,104 @@
+#/** @file\r
+# EDK Internal Form Refresentation Support Library Instance.\r
+#\r
+# The library instance provides common library routines help in \r
+#  IFR creation on-the-fly, HII variable access, HII database access, multi language supports.\r
+# Copyright (c) 2006 - 2007, Intel Corporation.\r
+#\r
+#  All rights reserved. This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\r
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+################################################################################\r
+#\r
+# Defines Section - statements that will be processed to create a Makefile.\r
+#\r
+################################################################################\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = FrameworkIfrSupportLib\r
+  FILE_GUID                      = ea55bada-d488-427b-9d2d-227e0aaa3707\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = FrameworkIfrSupportLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER \r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+\r
+  CONSTRUCTOR                    = IfrLibConstruct\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+#  Variable Guid C Name: gLanGuid Variable Name: L"Lan"\r
+#\r
+\r
+################################################################################\r
+#\r
+# Sources Section - list of files that are required for the build to succeed.\r
+#\r
+################################################################################\r
+\r
+[Sources.common]\r
+  IfrVariable.c\r
+  IfrOpCodeCreation.c\r
+  IfrOnTheFly.c\r
+  IfrCommon.c\r
+  CommonHeader.h\r
+\r
+\r
+################################################################################\r
+#\r
+# Package Dependency Section - list of Package files that are required for\r
+#                              this module.\r
+#\r
+################################################################################\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  IntelFrameworkPkg/IntelFrameworkPkg.dec\r
+\r
+\r
+################################################################################\r
+#\r
+# Library Class Section - list of Library Classes that are required for\r
+#                         this module.\r
+#\r
+################################################################################\r
+\r
+[LibraryClasses]\r
+  UefiRuntimeServicesTableLib\r
+  UefiBootServicesTableLib\r
+  MemoryAllocationLib\r
+  BaseMemoryLib\r
+  BaseLib\r
+  DebugLib\r
+\r
+\r
+################################################################################\r
+#\r
+# Guid C Name Section - list of Guids that this module uses or produces.\r
+#\r
+################################################################################\r
+\r
+[Guids]\r
+  gEfiGlobalVariableGuid                        # ALWAYS_CONSUMED\r
+\r
+\r
+################################################################################\r
+#\r
+# Protocol C Name Section - list of Protocol and Protocol Notify C Names\r
+#                           that this module uses or produces.\r
+#\r
+################################################################################\r
+\r
+[Protocols]\r
+  gEfiHiiProtocolGuid                           # PROTOCOL ALWAYS_CONSUMED\r
+\r
diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.msa b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.msa
new file mode 100644 (file)
index 0000000..87f4f74
--- /dev/null
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>EdkIfrSupportLib</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>ea55bada-d488-427b-9d2d-227e0aaa3707</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>EDK Internal Form Refresentation Support Library Instance.</Abstract>\r
+    <Description>The library instance provides common library routines help in 
+    IFR creation on-the-fly, HII variable access, HII database access, multi language supports.</Description>\r
+    <Copyright>Copyright (c) 2006 - 2007, Intel Corporation.</Copyright>\r
+    <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>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>EdkIfrSupportLib</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_PRODUCED" SupModuleList="DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER">\r
+      <Keyword>EdkIfrSupportLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>BaseMemoryLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>MemoryAllocationLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>IfrCommon.c</Filename>\r
+    <Filename>IfrOnTheFly.c</Filename>\r
+    <Filename>IfrOpCodeCreation.c</Filename>\r
+    <Filename>IfrVariable.c</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiHiiProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Variables>\r
+    <Variable Usage="ALWAYS_CONSUMED">\r
+      <VariableName>0x004C 0x0061 0x006E</VariableName>\r
+      <GuidC_Name>gLanGuid</GuidC_Name>\r
+    </Variable>\r
+  </Variables>\r
+  <Guids>\r
+    <GuidCNames Usage="ALWAYS_CONSUMED">\r
+      <GuidCName>gEfiGlobalVariableGuid</GuidCName>\r
+    </GuidCNames>\r
+  </Guids>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+    <Extern>\r
+      <Constructor>IfrLibConstruct</Constructor>\r
+    </Extern>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrVariable.c b/IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrVariable.c
new file mode 100644 (file)
index 0000000..e48adbd
--- /dev/null
@@ -0,0 +1,493 @@
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+  IfrVariable.c\r
+\r
+Abstract:\r
+  Variable/Map manipulations routines\r
+\r
+--*/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+VOID\r
+EfiLibHiiVariablePackGetMap (\r
+  IN    EFI_HII_VARIABLE_PACK       *Pack,  \r
+  OUT   CHAR16                      **Name,  OPTIONAL\r
+  OUT   EFI_GUID                    **Guid,  OPTIONAL\r
+  OUT   UINT16                      *Id,     OPTIONAL\r
+  OUT   VOID                        **Var,   OPTIONAL\r
+  OUT   UINTN                       *Size    OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Extracts a variable form a Pack.\r
+\r
+Arguments:\r
+\r
+  Pack - List of variables\r
+  Name - Name of the variable/map\r
+  Guid - GUID of the variable/map\r
+  Var  - Pointer to the variable/map\r
+  Size - Size of the variable/map in bytes\r
+\r
+Returns: \r
+\r
+  VOID\r
+  \r
+--*/\r
+{\r
+  if (NULL != Name) {\r
+    *Name = (VOID *) (Pack + 1);\r
+  }\r
+    \r
+  if (NULL != Guid) { \r
+    *Guid = (EFI_GUID *)(UINTN)&Pack->VariableGuid;\r
+  }\r
+    \r
+    \r
+  if (NULL != Id) {\r
+    *Id   = Pack->VariableId;\r
+  }\r
+    \r
+  if (NULL != Var) {\r
+    *Var  = (VOID *) ((CHAR8 *) (Pack + 1) + Pack->VariableNameLength);\r
+  }\r
+    \r
+  if (NULL != Size) {\r
+    *Size = Pack->Header.Length - sizeof (*Pack) - Pack->VariableNameLength;\r
+  }\r
+}\r
+\r
+\r
+UINTN\r
+EfiLibHiiVariablePackListGetMapCnt (\r
+  IN    EFI_HII_VARIABLE_PACK_LIST   *List\r
+  )\r
+  \r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Finds a count of the variables/maps in the List.\r
+\r
+Arguments:\r
+\r
+  List - List of variables\r
+\r
+Returns: \r
+\r
+  UINTN - The number of map count.\r
+\r
+--*/\r
+\r
+{\r
+  UINTN   Cnt = 0;\r
+  while (NULL != List) {\r
+    Cnt++;\r
+    List = List->NextVariablePack;\r
+  }\r
+  return Cnt;\r
+}\r
+\r
+\r
+VOID\r
+EfiLibHiiVariablePackListForEachVar (\r
+  IN    EFI_HII_VARIABLE_PACK_LIST               *List,\r
+  IN    EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK  *Callback\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Will iterate all variable/maps as appearing \r
+  in List and for each, it will call the Callback.\r
+\r
+Arguments:\r
+\r
+  List     - List of variables\r
+  Callback - Routine to be called for each iterated variable.\r
+\r
+Returns: \r
+\r
+  VOID\r
+  \r
+--*/\r
+\r
+{\r
+  CHAR16    *MapName;\r
+  EFI_GUID  *MapGuid;\r
+  UINT16    MapId;\r
+  VOID      *Map;\r
+  UINTN     MapSize;\r
+\r
+  while (NULL != List) {\r
+    EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);\r
+    //\r
+    // call the callback\r
+    //\r
+    Callback (MapName, MapGuid, MapId, Map, MapSize); \r
+    List = List->NextVariablePack;\r
+  }\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EfiLibHiiVariablePackListGetMapByIdx (\r
+  IN    UINTN                       Idx,  \r
+  IN    EFI_HII_VARIABLE_PACK_LIST  *List,  \r
+  OUT   CHAR16                      **Name,  OPTIONAL\r
+  OUT   EFI_GUID                    **Guid,  OPTIONAL\r
+  OUT   UINT16                      *Id,     OPTIONAL\r
+  OUT   VOID                        **Var,\r
+  OUT   UINTN                       *Size\r
+  )\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Finds a variable form List given \r
+  the order number as appears in the List.\r
+\r
+Arguments:\r
+\r
+  Idx  - The index of the variable/map to retrieve\r
+  List - List of variables\r
+  Name - Name of the variable/map\r
+  Guid - GUID of the variable/map\r
+  Var  - Pointer to the variable/map\r
+  Size - Size of the variable/map in bytes\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS   - Variable is found, OUT parameters are valid\r
+  EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid\r
+\r
+--*/\r
+{\r
+  CHAR16     *MapName;\r
+  EFI_GUID   *MapGuid;\r
+  UINT16     MapId;\r
+  VOID       *Map;\r
+  UINTN      MapSize;\r
+\r
+  while (NULL != List) {\r
+    EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);\r
+    if (0 == Idx--) {\r
+      *Var  = Map;\r
+      *Size = MapSize;\r
+\r
+      if (NULL != Name) {\r
+        *Name = MapName;\r
+      }\r
+\r
+      if (NULL != Guid) {\r
+        *Guid = MapGuid;\r
+      }\r
+        \r
+      if (NULL != Id) {\r
+        *Id   = MapId;\r
+      }\r
+        \r
+      return EFI_SUCCESS; // Map found\r
+    }\r
+    List = List->NextVariablePack;\r
+  }\r
+  //\r
+  // If here, the map is not found\r
+  //\r
+  return EFI_NOT_FOUND; \r
+}\r
+\r
+\r
+EFI_STATUS\r
+EfiLibHiiVariablePackListGetMapById (\r
+  IN    UINT16                        Id,  \r
+  IN    EFI_HII_VARIABLE_PACK_LIST    *List,\r
+  OUT   CHAR16                        **Name,  OPTIONAL\r
+  OUT   EFI_GUID                      **Guid,  OPTIONAL\r
+  OUT   VOID                          **Var,\r
+  OUT   UINTN                         *Size\r
+  )\r
+  \r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Finds a variable form List given the \r
+  order number as appears in the List.\r
+\r
+Arguments:\r
+\r
+  Id   - The ID of the variable/map to retrieve\r
+  List - List of variables\r
+  Name - Name of the variable/map\r
+  Guid - GUID of the variable/map\r
+  Var  - Pointer to the variable/map\r
+  Size - Size of the variable/map in bytes\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS   - Variable is found, OUT parameters are valid\r
+  EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid\r
+\r
+--*/\r
+\r
+{ \r
+  CHAR16    *MapName;\r
+  EFI_GUID  *MapGuid;\r
+  UINT16    MapId;\r
+  VOID      *Map;\r
+  UINTN     MapSize;\r
+\r
+  while (NULL != List) {\r
+    EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);\r
+    if (MapId == Id) {\r
+      *Var  = Map;\r
+      *Size = MapSize;\r
+      if (NULL != Name) {\r
+         *Name = MapName;\r
+      }\r
+      if (NULL != Guid) {\r
+        *Guid = MapGuid;\r
+      }\r
+      //\r
+      // Map found\r
+      //\r
+      return EFI_SUCCESS; \r
+    }\r
+    List = List->NextVariablePack;\r
+  }\r
+  //\r
+  // If here, the map is not found\r
+  //\r
+  return EFI_NOT_FOUND; \r
+}\r
+\r
+\r
+EFI_STATUS\r
+EfiLibHiiVariablePackListGetMap (\r
+  IN    EFI_HII_VARIABLE_PACK_LIST   *List,\r
+  IN    CHAR16                       *Name,\r
+  IN    EFI_GUID                     *Guid,\r
+  OUT   UINT16                       *Id,\r
+  OUT   VOID                         **Var, \r
+  OUT   UINTN                        *Size\r
+  )\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Finds a variable form EFI_HII_VARIABLE_PACK_LIST given name and GUID.\r
+\r
+Arguments:\r
+\r
+  List - List of variables\r
+  Name - Name of the variable/map to be found\r
+  Guid - GUID of the variable/map to be found\r
+  Var  - Pointer to the variable/map found\r
+  Size - Size of the variable/map in bytes found\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS   - variable is found, OUT parameters are valid\r
+  EFI_NOT_FOUND - variable is not found, OUT parameters are not valid\r
+\r
+--*/\r
+\r
+{ \r
+  VOID      *Map;\r
+  UINTN     MapSize;\r
+  UINT16    MapId;\r
+  CHAR16    *MapName;\r
+  EFI_GUID  *MapGuid;\r
+\r
+  while (NULL != List) {\r
+    EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize);\r
+    if ((0 == StrCmp (Name, MapName)) && CompareGuid (Guid, MapGuid)) {\r
+      *Id   = MapId;\r
+      *Var  = Map;\r
+      *Size = MapSize;\r
+      return EFI_SUCCESS;\r
+    }\r
+    List = List->NextVariablePack;\r
+  }\r
+  //\r
+  // If here, the map is not found\r
+  //\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+EfiLibHiiVariableRetrieveFromNv (\r
+  IN  CHAR16                 *Name,\r
+  IN  EFI_GUID               *Guid,\r
+  IN  UINTN                   Size,\r
+  OUT VOID                  **Var\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Finds out if a variable of specific Name/Guid/Size exists in NV. \r
+  If it does, it will retrieve it into the Var. \r
+\r
+Arguments:\r
+  Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.\r
+  Var              - Variable will be retrieved into buffer pointed by this pointer.\r
+                     If pointing to NULL, the buffer will be allocated. Caller is responsible for releasing the buffer.\r
+Returns:\r
+  EFI_SUCCESS    - The variable of exact Name/Guid/Size parameters was retrieved and written to Var.\r
+  EFI_NOT_FOUND  - The variable of this Name/Guid was not found in the NV.\r
+  EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINTN                       SizeNv;\r
+\r
+  //\r
+  // Test for existence of the variable.\r
+  //\r
+  SizeNv = 0;\r
+  Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, NULL);\r
+  if (EFI_BUFFER_TOO_SMALL != Status) {\r
+    ASSERT (EFI_SUCCESS != Status);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+  if (SizeNv != Size) {\r
+    //\r
+    // The variable is considered corrupt, as it has different size from expected.\r
+    //\r
+    return EFI_LOAD_ERROR; \r
+  }\r
+\r
+  if (NULL == *Var) {\r
+    *Var = AllocatePool (Size);\r
+    ASSERT (NULL != *Var);\r
+  }\r
+  SizeNv = Size;\r
+  //\r
+  // Final read into the Var\r
+  //\r
+  Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, *Var); \r
+  //\r
+  // No tolerance for random failures. Such behavior is undetermined and not validated.\r
+  //\r
+  ASSERT_EFI_ERROR (Status); \r
+  ASSERT (SizeNv == Size);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+EfiLibHiiVariableOverrideIfSuffix (\r
+  IN  CHAR16                 *Suffix,\r
+  IN  CHAR16                 *Name,\r
+  IN  EFI_GUID               *Guid,\r
+  IN  UINTN                   Size,\r
+  OUT VOID                   *Var\r
+  )  \r
+/*++\r
+\r
+Routine Description:\r
+  Overrrides the variable with NV data if found.\r
+  But it only does it if the Name ends with specified Suffix.\r
+  For example, if Suffix="MyOverride" and the Name="XyzSetupMyOverride",\r
+  the Suffix matches the end of Name, so the variable will be loaded from NV\r
+  provided the variable exists and the GUID and Size matches.\r
+\r
+Arguments:\r
+  Suffix           - Suffix the Name should end with.\r
+  Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.\r
+  Var              - Variable will be retrieved into this buffer.\r
+                     Caller is responsible for providing storage of exactly Size size in bytes.\r
+Returns:\r
+  EFI_SUCCESS           - The variable was overriden with NV variable of same Name/Guid/Size.\r
+  EFI_INVALID_PARAMETER - The name of the variable does not end with <Suffix>.\r
+  EFI_NOT_FOUND         - The variable of this Name/Guid was not found in the NV.\r
+  EFI_LOAD_ERROR        - The variable in the NV was of different size, or NV API returned error.\r
+\r
+--*/\r
+{\r
+  UINTN         StrLength;\r
+  UINTN         StrLenSuffix;\r
+\r
+  StrLength       = StrLen (Name);\r
+  StrLenSuffix    = StrLen (Suffix);\r
+  if ((StrLength <= StrLenSuffix) || (0 != StrCmp (Suffix, &Name[StrLength - StrLenSuffix]))) {\r
+    //\r
+    // Not ending with <Suffix>.\r
+    //\r
+    return EFI_INVALID_PARAMETER; \r
+  }\r
+  return EfiLibHiiVariableRetrieveFromNv (Name, Guid, Size, &Var);\r
+}\r
+\r
+EFI_STATUS\r
+EfiLibHiiVariableOverrideBySuffix (\r
+  IN  CHAR16                 *Suffix,\r
+  IN  CHAR16                 *Name,\r
+  IN  EFI_GUID               *Guid,\r
+  IN  UINTN                   Size,\r
+  OUT VOID                   *Var\r
+  ) \r
+/*++\r
+\r
+Routine Description:\r
+  Overrrides the variable with NV data if found.\r
+  But it only does it if the NV contains the same variable with Name is appended with Suffix.  \r
+  For example, if Suffix="MyOverride" and the Name="XyzSetup",\r
+  the Suffix will be appended to the end of Name, and the variable with Name="XyzSetupMyOverride"\r
+  will be loaded from NV provided the variable exists and the GUID and Size matches.\r
+\r
+Arguments:\r
+  Suffix           - Suffix the variable will be appended with.\r
+  Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly.\r
+  Var              - Variable will be retrieved into this buffer.\r
+                     Caller is responsible for providing storage of exactly Size size in bytes.\r
+\r
+Returns:\r
+  EFI_SUCCESS    - The variable was overriden with NV variable of same Name/Guid/Size.\r
+  EFI_NOT_FOUND  - The variable of this Name/Guid was not found in the NV.\r
+  EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  CHAR16       *NameSuffixed;\r
+  UINTN         NameLength;\r
+  UINTN         SuffixLength;\r
+\r
+  //\r
+  // enough to concatenate both strings.\r
+  //\r
+  NameLength   = StrLen (Name);\r
+  SuffixLength = StrLen (Suffix);\r
+  NameSuffixed = AllocateZeroPool ((NameLength + SuffixLength + 1) * sizeof (CHAR16)); \r
+  \r
+  StrCpy (NameSuffixed, Name);\r
+  StrCat (NameSuffixed, Suffix);\r
+  \r
+  Status = EfiLibHiiVariableRetrieveFromNv (NameSuffixed, Guid, Size, &Var);\r
+  gBS->FreePool (NameSuffixed);\r
+  \r
+  return Status;\r
+}\r
+\r