Removed the dependency to MdeModulePkg in the HiiLibFramework Removed EDK_RELEASE_VERSION and EFI_SPECIFICATION_VERSION in the Framework inf file. other coding style changes git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@7218 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			919 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			919 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Common Library Routines to assist in IFR creation on-the-fly
 | 
						|
  
 | 
						|
Copyright (c) 2006, Intel Corporation
 | 
						|
All rights reserved. This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
        
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "IfrSupportLibInternal.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Determine what is the current language setting
 | 
						|
  The setting is stored in language variable in flash. This routine
 | 
						|
  will get setting by accesssing that variable. If failed to access
 | 
						|
  language variable, then use default setting that 'eng' as current
 | 
						|
  language setting.
 | 
						|
  
 | 
						|
  @param    Lang       Pointer of system language
 | 
						|
  
 | 
						|
  @return              whether sucess to get setting from variable
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetCurrentLanguage (
 | 
						|
  OUT  CHAR16                       *Lang
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  UINTN                             Size;
 | 
						|
  UINTN                             Index;
 | 
						|
  CHAR8                             Language[4];
 | 
						|
 | 
						|
  //
 | 
						|
  // Getting the system language and placing it into our Global Data
 | 
						|
  //
 | 
						|
  Size = sizeof (Language);
 | 
						|
  Status = gRT->GetVariable (
 | 
						|
                  (CHAR16 *) L"Lang",
 | 
						|
                  &gEfiGlobalVariableGuid,
 | 
						|
                  NULL,
 | 
						|
                  &Size,
 | 
						|
                  Language
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    AsciiStrCpy (Language, "eng");
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < 3; Index++) {
 | 
						|
    //
 | 
						|
    // Bitwise AND ascii value with 0xDF yields an uppercase value.
 | 
						|
    // Sign extend into a unicode value
 | 
						|
    //
 | 
						|
    Lang[Index] = (CHAR16) (Language[Index] & 0xDF);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Null-terminate the value
 | 
						|
  //
 | 
						|
  Lang[3] = (CHAR16) 0;
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add a string to the incoming buffer and return the token and offset data.
 | 
						|
  
 | 
						|
  @param  StringBuffer         The incoming buffer
 | 
						|
  @param  Language             Currrent language
 | 
						|
  @param  String               The string to be added
 | 
						|
  @param  StringToken          The index where the string placed  
 | 
						|
  
 | 
						|
  @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
 | 
						|
  @retval EFI_SUCCESS          String successfully added to the incoming buffer
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AddString (
 | 
						|
  IN      VOID                      *StringBuffer,
 | 
						|
  IN      CHAR16                    *Language,
 | 
						|
  IN      CHAR16                    *String,
 | 
						|
  IN OUT  STRING_REF                *StringToken
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HII_STRING_PACK               *StringPack;
 | 
						|
  EFI_HII_STRING_PACK               *StringPackBuffer;
 | 
						|
  VOID                              *NewBuffer;
 | 
						|
  RELOFST                           *PackSource;
 | 
						|
  RELOFST                           *PackDestination;
 | 
						|
  UINT8                             *Source;
 | 
						|
  UINT8                             *Destination;
 | 
						|
  UINTN                             Index;
 | 
						|
  BOOLEAN                           Finished;
 | 
						|
  UINTN                             SizeofLanguage;
 | 
						|
  UINTN                             SizeofString;
 | 
						|
 | 
						|
  StringPack  = (EFI_HII_STRING_PACK *) StringBuffer;
 | 
						|
  Finished    = FALSE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Pre-allocate a buffer sufficient for us to work on.
 | 
						|
  // We will use it as a destination scratch pad to build data on
 | 
						|
  // and when complete shift the data back to the original buffer
 | 
						|
  //
 | 
						|
  NewBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE);
 | 
						|
  if (NewBuffer == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  StringPackBuffer = (EFI_HII_STRING_PACK *) NewBuffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // StringPack is terminated with a length 0 entry
 | 
						|
  //
 | 
						|
  for (; StringPack->Header.Length != 0;) {
 | 
						|
    //
 | 
						|
    // If this stringpack's language is same as CurrentLanguage, use it
 | 
						|
    //
 | 
						|
    if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language, 3) == 0) {
 | 
						|
      //
 | 
						|
      // We have some data in this string pack, copy the string package up to the string data
 | 
						|
      //
 | 
						|
      CopyMem (&StringPackBuffer->Header, &StringPack->Header, sizeof (StringPack));
 | 
						|
 | 
						|
      //
 | 
						|
      // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer
 | 
						|
      //
 | 
						|
      StringPackBuffer->LanguageNameString = (UINT16) (StringPackBuffer->LanguageNameString + (UINT16) sizeof (RELOFST));
 | 
						|
      StringPackBuffer->PrintableLanguageName = (UINT16) (StringPackBuffer->PrintableLanguageName + (UINT16) sizeof (RELOFST));
 | 
						|
 | 
						|
      PackSource      = (RELOFST *) (StringPack + 1);
 | 
						|
      PackDestination = (RELOFST *) (StringPackBuffer + 1);
 | 
						|
      for (Index = 0; PackSource[Index] != 0x0000; Index++) {
 | 
						|
        //
 | 
						|
        // Copy the stringpointers from old to new buffer
 | 
						|
        // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST)
 | 
						|
        //
 | 
						|
        PackDestination[Index] = (UINT16) (PackDestination[Index] + sizeof (RELOFST));
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Add a new stringpointer in the new buffer since we are adding a string.  Null terminate it
 | 
						|
      //
 | 
						|
      PackDestination[Index] = (UINT16)(PackDestination[Index - 1] +
 | 
						|
                                        StrSize((CHAR16 *)((CHAR8 *)(StringPack) + PackSource[Index - 1])));
 | 
						|
      PackDestination[Index + 1] = (UINT16) 0;
 | 
						|
 | 
						|
      //
 | 
						|
      // Index is the token value for the new string
 | 
						|
      //
 | 
						|
      *StringToken = (UINT16) Index;
 | 
						|
 | 
						|
      //
 | 
						|
      // Source now points to the beginning of the old buffer strings
 | 
						|
      // Destination now points to the beginning of the new buffer strings
 | 
						|
      //
 | 
						|
      Source      = (UINT8 *) &PackSource[Index + 1];
 | 
						|
      Destination = (UINT8 *) &PackDestination[Index + 2];
 | 
						|
 | 
						|
      //
 | 
						|
      // This should copy all the strings from the old buffer to the new buffer
 | 
						|
      //
 | 
						|
      for (; Index != 0; Index--) {
 | 
						|
        //
 | 
						|
        // Copy Source string to destination buffer
 | 
						|
        //
 | 
						|
        StrCpy ((CHAR16 *) Destination, (CHAR16 *) Source);
 | 
						|
 | 
						|
        //
 | 
						|
        // Adjust the source/destination to the next string location
 | 
						|
        //
 | 
						|
        Destination = Destination + StrSize ((CHAR16 *) Source);
 | 
						|
        Source      = Source + StrSize ((CHAR16 *) Source);
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // This copies the new string to the destination buffer
 | 
						|
      //
 | 
						|
      StrCpy ((CHAR16 *) Destination, (CHAR16 *) String);
 | 
						|
 | 
						|
      //
 | 
						|
      // Adjust the size of the changed string pack by adding the size of the new string
 | 
						|
      // along with the size of the additional offset entry for the new string
 | 
						|
      //
 | 
						|
      StringPackBuffer->Header.Length = (UINT32) ((UINTN) StringPackBuffer->Header.Length + StrSize (String) + sizeof (RELOFST));
 | 
						|
 | 
						|
      //
 | 
						|
      // Advance the buffers to point to the next spots.
 | 
						|
      //
 | 
						|
      StringPackBuffer  = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPackBuffer->Header.Length);
 | 
						|
      StringPack        = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);
 | 
						|
      Finished          = TRUE;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // This isn't the language of the stringpack we were asked to add a string to
 | 
						|
    // so we need to copy it to the new buffer.
 | 
						|
    //
 | 
						|
    CopyMem (&StringPackBuffer->Header, &StringPack->Header, StringPack->Header.Length);
 | 
						|
 | 
						|
    //
 | 
						|
    // Advance the buffers to point to the next spots.
 | 
						|
    //
 | 
						|
    StringPackBuffer  = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPack->Header.Length);
 | 
						|
    StringPack        = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If we didn't copy the new data to a stringpack yet
 | 
						|
  //
 | 
						|
  if (!Finished) {
 | 
						|
    PackDestination = (RELOFST *) (StringPackBuffer + 1);
 | 
						|
    //
 | 
						|
    // Pointing to a new string pack location
 | 
						|
    //
 | 
						|
    SizeofLanguage = StrSize (Language);
 | 
						|
    SizeofString   = StrSize (String);
 | 
						|
    StringPackBuffer->Header.Length = (UINT32)
 | 
						|
      (
 | 
						|
        sizeof (EFI_HII_STRING_PACK) -
 | 
						|
        sizeof (EFI_STRING) +
 | 
						|
        sizeof (RELOFST) +
 | 
						|
        sizeof (RELOFST) +
 | 
						|
        SizeofLanguage +
 | 
						|
        SizeofString
 | 
						|
      );
 | 
						|
    StringPackBuffer->Header.Type           = EFI_HII_STRING;
 | 
						|
    StringPackBuffer->LanguageNameString    = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
 | 
						|
    StringPackBuffer->PrintableLanguageName = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
 | 
						|
    StringPackBuffer->Attributes            = 0;
 | 
						|
    PackDestination[0]                      = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer);
 | 
						|
    PackDestination[1]                      = (UINT16) (PackDestination[0] + StrSize (Language));
 | 
						|
    PackDestination[2]                      = (UINT16) 0;
 | 
						|
 | 
						|
    //
 | 
						|
    // The first string location will be set to destination.  The minimum number of strings
 | 
						|
    // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc)
 | 
						|
    // and token 1 as the new string being added and and null entry for the stringpointers
 | 
						|
    //
 | 
						|
    Destination = (UINT8 *) &PackDestination[3];
 | 
						|
 | 
						|
    //
 | 
						|
    // Copy the language name string to the new buffer
 | 
						|
    //
 | 
						|
    StrCpy ((CHAR16 *) Destination, Language);
 | 
						|
 | 
						|
    //
 | 
						|
    // Advance the destination to the new empty spot
 | 
						|
    //
 | 
						|
    Destination = Destination + StrSize (Language);
 | 
						|
 | 
						|
    //
 | 
						|
    // Copy the string to the new buffer
 | 
						|
    //
 | 
						|
    StrCpy ((CHAR16 *) Destination, String);
 | 
						|
 | 
						|
    //
 | 
						|
    // Since we are starting with a new string pack - we know the new string is token 1
 | 
						|
    //
 | 
						|
    *StringToken = (UINT16) 1;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
 | 
						|
  //
 | 
						|
  ZeroMem (StringBuffer, DEFAULT_STRING_BUFFER_SIZE);
 | 
						|
  CopyMem (StringBuffer, NewBuffer, DEFAULT_STRING_BUFFER_SIZE);
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the newly created buffer since we don't need it anymore
 | 
						|
  //
 | 
						|
  FreePool (NewBuffer);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add op-code data to the FormBuffer.
 | 
						|
  
 | 
						|
  @param  FormBuffer            Form buffer to be inserted to
 | 
						|
  @param  OpCodeData            Op-code data to be inserted  
 | 
						|
  
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough buffer to allocate
 | 
						|
  @retval EFI_SUCCESS           Op-code data successfully inserted  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AddOpCode (
 | 
						|
  IN      VOID                      *FormBuffer,
 | 
						|
  IN OUT  VOID                      *OpCodeData
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HII_PACK_HEADER               *NewBuffer;
 | 
						|
  UINT8                             *Source;
 | 
						|
  UINT8                             *Destination;
 | 
						|
 | 
						|
  //
 | 
						|
  // Pre-allocate a buffer sufficient for us to work on.
 | 
						|
  // We will use it as a destination scratch pad to build data on
 | 
						|
  // and when complete shift the data back to the original buffer
 | 
						|
  //
 | 
						|
  NewBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE);
 | 
						|
  if (NewBuffer == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy the IFR Package header to the new buffer
 | 
						|
  //
 | 
						|
  Source      = (UINT8 *) FormBuffer;
 | 
						|
  Destination = (UINT8 *) NewBuffer;
 | 
						|
  CopyMem (Destination, Source, sizeof (EFI_HII_PACK_HEADER));
 | 
						|
 | 
						|
  //
 | 
						|
  // Advance Source and Destination to next op-code
 | 
						|
  //
 | 
						|
  Source      = Source + sizeof (EFI_HII_PACK_HEADER);
 | 
						|
  Destination = Destination + sizeof (EFI_HII_PACK_HEADER);
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy data to the new buffer until we run into the end_form
 | 
						|
  //
 | 
						|
  for (; ((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->OpCode != FRAMEWORK_EFI_IFR_END_FORM_OP;) {
 | 
						|
    //
 | 
						|
    // If the opcode is an end_form_set we better be creating and endform
 | 
						|
    // Nonetheless, we will add data before the end_form_set.  This also provides
 | 
						|
    // for interesting behavior in the code we will run, but has no bad side-effects
 | 
						|
    // since we will possibly do a 0 byte copy in this particular end-case.
 | 
						|
    //
 | 
						|
    if (((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->OpCode == FRAMEWORK_EFI_IFR_END_FORM_SET_OP) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Copy data to new buffer
 | 
						|
    //
 | 
						|
    CopyMem (Destination, Source, ((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->Length);
 | 
						|
 | 
						|
    //
 | 
						|
    // Adjust Source/Destination to next op-code location
 | 
						|
    //
 | 
						|
    Destination = Destination + (UINTN) ((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->Length;
 | 
						|
    Source      = Source + (UINTN) ((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->Length;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Prior to the end_form is where we insert the new op-code data
 | 
						|
  //
 | 
						|
  CopyMem (Destination, OpCodeData, ((FRAMEWORK_EFI_IFR_OP_HEADER *) OpCodeData)->Length);
 | 
						|
  
 | 
						|
  Destination = Destination + (UINTN) ((FRAMEWORK_EFI_IFR_OP_HEADER *) OpCodeData)->Length;
 | 
						|
  NewBuffer->Length = (UINT32) (NewBuffer->Length + (UINT32) (((FRAMEWORK_EFI_IFR_OP_HEADER *) OpCodeData)->Length));
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy end-form data to new buffer
 | 
						|
  //
 | 
						|
  CopyMem (Destination, Source, ((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->Length);
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy end-formset data to new buffer
 | 
						|
  //
 | 
						|
  Destination = Destination + (UINTN) ((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->Length;
 | 
						|
  Source      = Source + (UINTN) ((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->Length;
 | 
						|
  CopyMem (Destination, Source, ((FRAMEWORK_EFI_IFR_OP_HEADER *) Source)->Length);
 | 
						|
 | 
						|
  //
 | 
						|
  // Zero out the original buffer and copy the updated data in the new buffer to the old buffer
 | 
						|
  //
 | 
						|
  ZeroMem (FormBuffer, DEFAULT_FORM_BUFFER_SIZE);
 | 
						|
  CopyMem (FormBuffer, NewBuffer, DEFAULT_FORM_BUFFER_SIZE);
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the newly created buffer since we don't need it anymore
 | 
						|
  //
 | 
						|
  FreePool (NewBuffer);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the HII protocol interface.
 | 
						|
  
 | 
						|
  @param  Hii    HII protocol interface
 | 
						|
  
 | 
						|
  @return        the statue of locating HII protocol
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
GetHiiInterface (
 | 
						|
  OUT  EFI_HII_PROTOCOL             **Hii
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // There should only be one HII protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiHiiProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) Hii
 | 
						|
                  );
 | 
						|
 | 
						|
  return Status;;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Extract information pertaining to the HiiHandle.
 | 
						|
  
 | 
						|
  @param  HiiHandle             Hii handle
 | 
						|
  @param  ImageLength           For input, length of DefaultImage;
 | 
						|
                                For output, length of actually required
 | 
						|
  @param  DefaultImage          Image buffer prepared by caller
 | 
						|
  @param  Guid                  Guid information about the form 
 | 
						|
  
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  No enough buffer to allocate
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL  DefualtImage has no enough ImageLength
 | 
						|
  @retval EFI_SUCCESS           Successfully extract data from Hii database.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ExtractDataFromHiiHandle (
 | 
						|
  IN      FRAMEWORK_EFI_HII_HANDLE  HiiHandle,
 | 
						|
  IN OUT  UINT16                    *ImageLength,
 | 
						|
     OUT  UINT8                     *DefaultImage,
 | 
						|
     OUT  EFI_GUID                  *Guid
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_HII_PROTOCOL                  *Hii;
 | 
						|
  UINTN                             DataLength;
 | 
						|
  UINT8                             *RawData;
 | 
						|
  UINT8                             *OldData;
 | 
						|
  UINTN                             Index;
 | 
						|
  UINTN                             Temp;
 | 
						|
  UINTN                             SizeOfNvStore;
 | 
						|
  UINTN                             CachedStart;
 | 
						|
 | 
						|
  DataLength    = DEFAULT_FORM_BUFFER_SIZE;
 | 
						|
  SizeOfNvStore = 0;
 | 
						|
  CachedStart   = 0;
 | 
						|
 | 
						|
  Status        = GetHiiInterface (&Hii);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate space for retrieval of IFR data
 | 
						|
  //
 | 
						|
  RawData = AllocateZeroPool (DataLength);
 | 
						|
  if (RawData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get all the forms associated with this HiiHandle
 | 
						|
  //
 | 
						|
  Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (RawData);
 | 
						|
 | 
						|
    //
 | 
						|
    // Allocate space for retrieval of IFR data
 | 
						|
    //
 | 
						|
    RawData = AllocateZeroPool (DataLength);
 | 
						|
    if (RawData == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get all the forms associated with this HiiHandle
 | 
						|
    //
 | 
						|
    Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData);
 | 
						|
  }
 | 
						|
 | 
						|
  OldData = RawData;
 | 
						|
 | 
						|
  //
 | 
						|
  // Point RawData to the beginning of the form data
 | 
						|
  //
 | 
						|
  RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
 | 
						|
  for (Index = 0; RawData[Index] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
    switch (RawData[Index]) {
 | 
						|
      
 | 
						|
    case FRAMEWORK_EFI_IFR_FORM_SET_OP:
 | 
						|
      //
 | 
						|
      // Copy the GUID information from this handle
 | 
						|
      //
 | 
						|
      CopyGuid (Guid, (GUID *)(VOID *)&((FRAMEWORK_EFI_IFR_FORM_SET *) &RawData[Index])->Guid);
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_ONE_OF_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_NUMERIC_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_DATE_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_TIME_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_PASSWORD_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_STRING_OP:
 | 
						|
      //
 | 
						|
      // Remember, multiple op-codes may reference the same item, so let's keep a running
 | 
						|
      // marker of what the highest QuestionId that wasn't zero length.  This will accurately
 | 
						|
      // maintain the Size of the NvStore
 | 
						|
      //
 | 
						|
      if (((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {
 | 
						|
        Temp = ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->Width;
 | 
						|
        if (SizeOfNvStore < Temp) {
 | 
						|
          SizeOfNvStore = ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->Width;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Index = RawData[Index + 1] + Index;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Return an error if buffer is too small
 | 
						|
  //
 | 
						|
  if (SizeOfNvStore > *ImageLength) {
 | 
						|
    FreePool (OldData);
 | 
						|
    *ImageLength = (UINT16) SizeOfNvStore;
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DefaultImage != NULL) {
 | 
						|
    ZeroMem (DefaultImage, SizeOfNvStore);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy the default image information to the user's buffer
 | 
						|
  //
 | 
						|
  for (Index = 0; RawData[Index] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
    switch (RawData[Index]) {
 | 
						|
      
 | 
						|
    case FRAMEWORK_EFI_IFR_ONE_OF_OP:
 | 
						|
      CachedStart = ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP:
 | 
						|
      if (((FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Flags & FRAMEWORK_EFI_IFR_FLAG_DEFAULT) {
 | 
						|
        CopyMem (&DefaultImage[CachedStart], &((FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value, 2);
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
 | 
						|
      DefaultImage[((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId] = ((FRAMEWORK_EFI_IFR_CHECKBOX *) &RawData[Index])->Flags;
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_NUMERIC_OP:
 | 
						|
      CopyMem (
 | 
						|
        &DefaultImage[((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId],
 | 
						|
        &((FRAMEWORK_EFI_IFR_NUMERIC *) &RawData[Index])->Default,
 | 
						|
        2
 | 
						|
        );
 | 
						|
      break;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    Index = RawData[Index + 1] + Index;
 | 
						|
  }
 | 
						|
 | 
						|
  *ImageLength = (UINT16) SizeOfNvStore;
 | 
						|
 | 
						|
  //
 | 
						|
  // Free our temporary repository of form data
 | 
						|
  //
 | 
						|
  FreePool (OldData);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Finds HII handle for given pack GUID previously registered with the HII.
 | 
						|
  
 | 
						|
  @param  HiiProtocol pointer to pointer to HII protocol interface.
 | 
						|
                      If NULL, the interface will be found but not returned.
 | 
						|
                      If it points to NULL, the interface will be found and
 | 
						|
                      written back to the pointer that is pointed to.
 | 
						|
  @param  Guid        The GUID of the pack that registered with the HII.
 | 
						|
 | 
						|
  @return             Handle to the HII pack previously registered by the memory driver.
 | 
						|
**/
 | 
						|
FRAMEWORK_EFI_HII_HANDLE
 | 
						|
EFIAPI
 | 
						|
FindHiiHandle (
 | 
						|
  IN OUT  EFI_HII_PROTOCOL          **HiiProtocol, OPTIONAL
 | 
						|
  IN      EFI_GUID                  *Guid
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  FRAMEWORK_EFI_HII_HANDLE          *HiiHandleBuffer;
 | 
						|
  FRAMEWORK_EFI_HII_HANDLE          HiiHandle;
 | 
						|
  UINT16                            HiiHandleBufferLength;
 | 
						|
  UINT32                            NumberOfHiiHandles;
 | 
						|
  EFI_GUID                          HiiGuid;
 | 
						|
  EFI_HII_PROTOCOL                  *HiiProt;
 | 
						|
  UINT32                            Index;
 | 
						|
  UINT16                            Length;
 | 
						|
 | 
						|
  HiiHandle = 0;
 | 
						|
  if ((HiiProtocol != NULL) && (*HiiProtocol != NULL)) {
 | 
						|
    //
 | 
						|
    // The protocol has been passed in
 | 
						|
    //
 | 
						|
    HiiProt = *HiiProtocol;
 | 
						|
  } else {
 | 
						|
    gBS->LocateProtocol (
 | 
						|
          &gEfiHiiProtocolGuid,
 | 
						|
          NULL,
 | 
						|
          (VOID **) &HiiProt
 | 
						|
          );
 | 
						|
    if (HiiProt == NULL) {
 | 
						|
      return HiiHandle;
 | 
						|
    }
 | 
						|
 | 
						|
    if (HiiProtocol != NULL) {
 | 
						|
      //
 | 
						|
      // Return back the HII protocol for the caller as promissed
 | 
						|
      //
 | 
						|
      *HiiProtocol = HiiProt;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Allocate buffer
 | 
						|
  //
 | 
						|
  HiiHandleBufferLength = 10;
 | 
						|
  HiiHandleBuffer       = AllocatePool (HiiHandleBufferLength);
 | 
						|
  ASSERT (HiiHandleBuffer != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the Handles of the packages that were registered with Hii
 | 
						|
  //
 | 
						|
  Status = HiiProt->FindHandles (
 | 
						|
                      HiiProt,
 | 
						|
                      &HiiHandleBufferLength,
 | 
						|
                      HiiHandleBuffer
 | 
						|
                      );
 | 
						|
 | 
						|
  //
 | 
						|
  // Get a bigger bugffer if this one is to small, and try again
 | 
						|
  //
 | 
						|
  if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
 | 
						|
    FreePool (HiiHandleBuffer);
 | 
						|
 | 
						|
    HiiHandleBuffer = AllocatePool (HiiHandleBufferLength);
 | 
						|
    ASSERT (HiiHandleBuffer != NULL);
 | 
						|
 | 
						|
    Status = HiiProt->FindHandles (
 | 
						|
                        HiiProt,
 | 
						|
                        &HiiHandleBufferLength,
 | 
						|
                        HiiHandleBuffer
 | 
						|
                        );
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto lbl_exit;
 | 
						|
  }
 | 
						|
 | 
						|
  NumberOfHiiHandles = HiiHandleBufferLength / sizeof (FRAMEWORK_EFI_HII_HANDLE );
 | 
						|
 | 
						|
  //
 | 
						|
  // Iterate Hii handles and look for the one that matches our Guid
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < NumberOfHiiHandles; Index++) {
 | 
						|
 | 
						|
    Length = 0;
 | 
						|
    ExtractDataFromHiiHandle (HiiHandleBuffer[Index], &Length, NULL, &HiiGuid);
 | 
						|
 | 
						|
    if (CompareGuid (&HiiGuid, Guid)) {
 | 
						|
      HiiHandle = HiiHandleBuffer[Index];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
lbl_exit:
 | 
						|
  FreePool (HiiHandleBuffer);
 | 
						|
  return HiiHandle;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Validate that the data associated with the HiiHandle in NVRAM is within
 | 
						|
  the reasonable parameters for that FormSet.  Values for strings and passwords
 | 
						|
  are not verified due to their not having the equivalent of valid range settings.
 | 
						|
 | 
						|
  @param  HiiHandle   Handle of the HII database entry to query
 | 
						|
  @param  Results     If return Status is EFI_SUCCESS, Results provides valid data
 | 
						|
                      TRUE  = NVRAM Data is within parameters
 | 
						|
                      FALSE = NVRAM Data is NOT within parameters
 | 
						|
                      
 | 
						|
  @retval EFI_OUT_OF_RESOURCES   No enough buffer to allocate
 | 
						|
  @retval EFI_SUCCESS            Data successfully validated
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ValidateDataFromHiiHandle (
 | 
						|
  IN      FRAMEWORK_EFI_HII_HANDLE  HiiHandle,
 | 
						|
     OUT  BOOLEAN                   *Results
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_HII_PROTOCOL                  *Hii;
 | 
						|
  EFI_GUID                          Guid;
 | 
						|
  UINT8                             *RawData;
 | 
						|
  UINT8                             *OldData;
 | 
						|
  UINTN                             RawDataLength;
 | 
						|
  UINT8                             *VariableData;
 | 
						|
  UINTN                             Index;
 | 
						|
  UINTN                             Temp;
 | 
						|
  UINTN                             SizeOfNvStore;
 | 
						|
  UINTN                             CachedStart;
 | 
						|
  BOOLEAN                           GotMatch;
 | 
						|
 | 
						|
  RawDataLength = DEFAULT_FORM_BUFFER_SIZE;
 | 
						|
  SizeOfNvStore = 0;
 | 
						|
  CachedStart   = 0;
 | 
						|
  GotMatch      = FALSE;
 | 
						|
  *Results      = TRUE;
 | 
						|
 | 
						|
  Status        = GetHiiInterface (&Hii);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate space for retrieval of IFR data
 | 
						|
  //
 | 
						|
  RawData = AllocateZeroPool (RawDataLength);
 | 
						|
  if (RawData == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get all the forms associated with this HiiHandle
 | 
						|
  //
 | 
						|
  Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    FreePool (RawData);
 | 
						|
 | 
						|
    //
 | 
						|
    // Allocate space for retrieval of IFR data
 | 
						|
    //
 | 
						|
    RawData = AllocateZeroPool (RawDataLength);
 | 
						|
    if (RawData == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get all the forms associated with this HiiHandle
 | 
						|
    //
 | 
						|
    Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData);
 | 
						|
  }
 | 
						|
 | 
						|
  OldData = RawData;
 | 
						|
 | 
						|
  //
 | 
						|
  // Point RawData to the beginning of the form data
 | 
						|
  //
 | 
						|
  RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
 | 
						|
  for (Index = 0; RawData[Index] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
    if (RawData[Index] == FRAMEWORK_EFI_IFR_FORM_SET_OP) {
 | 
						|
      CopyGuid (&Guid, (GUID *)(VOID *)&((FRAMEWORK_EFI_IFR_FORM_SET *) &RawData[Index])->Guid);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    Index = RawData[Index + 1] + Index;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; RawData[Index] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
    switch (RawData[Index]) {
 | 
						|
      
 | 
						|
    case FRAMEWORK_EFI_IFR_FORM_SET_OP:
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_ONE_OF_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_NUMERIC_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_DATE_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_TIME_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_PASSWORD_OP:
 | 
						|
    case FRAMEWORK_EFI_IFR_STRING_OP:
 | 
						|
      //
 | 
						|
      // Remember, multiple op-codes may reference the same item, so let's keep a running
 | 
						|
      // marker of what the highest QuestionId that wasn't zero length.  This will accurately
 | 
						|
      // maintain the Size of the NvStore
 | 
						|
      //
 | 
						|
      if (((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) {
 | 
						|
        Temp = ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->Width;
 | 
						|
        if (SizeOfNvStore < Temp) {
 | 
						|
          SizeOfNvStore = ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->Width;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Index = RawData[Index + 1] + Index;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate memory for our File Form Tags
 | 
						|
  //
 | 
						|
  VariableData = AllocateZeroPool (SizeOfNvStore);
 | 
						|
  if (VariableData == NULL) {
 | 
						|
    FreePool (OldData);
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gRT->GetVariable (
 | 
						|
                  (CHAR16 *) L"Setup",
 | 
						|
                  &Guid,
 | 
						|
                  NULL,
 | 
						|
                  &SizeOfNvStore,
 | 
						|
                  (VOID *) VariableData
 | 
						|
                  );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
 | 
						|
    //
 | 
						|
    // If there is a variable that exists already and it is larger than what we calculated the
 | 
						|
    // storage needs to be, we must assume the variable size from GetVariable is correct and not
 | 
						|
    // allow the truncation of the variable.  It is very possible that the user who created the IFR
 | 
						|
    // we are cracking is not referring to a variable that was in a previous map, however we cannot
 | 
						|
    // allow it's truncation.
 | 
						|
    //
 | 
						|
    if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
      //
 | 
						|
      // Free the buffer that was allocated that was too small
 | 
						|
      //
 | 
						|
      FreePool (VariableData);
 | 
						|
 | 
						|
      VariableData = AllocatePool (SizeOfNvStore);
 | 
						|
      if (VariableData == NULL) {
 | 
						|
        FreePool (OldData);
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = gRT->GetVariable (
 | 
						|
                      (CHAR16 *) L"Setup",
 | 
						|
                      &Guid,
 | 
						|
                      NULL,
 | 
						|
                      &SizeOfNvStore,
 | 
						|
                      (VOID *) VariableData
 | 
						|
                      );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Walk through the form and see that the variable data it refers to is ok.
 | 
						|
  // This allows for the possibility of stale (obsoleted) data in the variable
 | 
						|
  // can be overlooked without causing an error
 | 
						|
  //
 | 
						|
  for (Index = 0; RawData[Index] != FRAMEWORK_EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
    switch (RawData[Index]) {
 | 
						|
      
 | 
						|
    case FRAMEWORK_EFI_IFR_ONE_OF_OP:
 | 
						|
      //
 | 
						|
      // A one_of has no data, its the option that does - cache the storage Id
 | 
						|
      //
 | 
						|
      CachedStart = ((FRAMEWORK_EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId;
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_ONE_OF_OPTION_OP:
 | 
						|
      //
 | 
						|
      // A one_of_option can be any value
 | 
						|
      //
 | 
						|
      if (VariableData[CachedStart] == ((FRAMEWORK_EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value) {
 | 
						|
        GotMatch = TRUE;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_END_ONE_OF_OP:
 | 
						|
      //
 | 
						|
      // At this point lets make sure that the data value in the NVRAM matches one of the options
 | 
						|
      //
 | 
						|
      if (!GotMatch) {
 | 
						|
        *Results = FALSE;
 | 
						|
        goto EXIT;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_CHECKBOX_OP:
 | 
						|
      //
 | 
						|
      // A checkbox is a boolean, so 0 and 1 are valid
 | 
						|
      // Remember, QuestionId corresponds to the offset location of the data in the variable
 | 
						|
      //
 | 
						|
      if (VariableData[((FRAMEWORK_EFI_IFR_CHECKBOX *) &RawData[Index])->QuestionId] > 1) {
 | 
						|
        *Results = FALSE;
 | 
						|
        goto EXIT;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case FRAMEWORK_EFI_IFR_NUMERIC_OP:
 | 
						|
        if ((VariableData[((FRAMEWORK_EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] < ((FRAMEWORK_EFI_IFR_NUMERIC *)&RawData[Index])->Minimum) ||
 | 
						|
            (VariableData[((FRAMEWORK_EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] > ((FRAMEWORK_EFI_IFR_NUMERIC *)&RawData[Index])->Maximum)) {
 | 
						|
        *Results = FALSE;
 | 
						|
        goto EXIT;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    Index = RawData[Index + 1] + Index;
 | 
						|
  }
 | 
						|
 | 
						|
EXIT: 
 | 
						|
  //
 | 
						|
  // Free our temporary repository of form data
 | 
						|
  //
 | 
						|
  FreePool (OldData);
 | 
						|
  FreePool (VariableData);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 |