git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3242 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1578 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1578 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**@file
 | 
						|
  This file contains the form processing code to the HII database.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2007 Intel Corporation. <BR>
 | 
						|
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 "HiiDatabase.h"
 | 
						|
 | 
						|
STATIC
 | 
						|
CHAR16*
 | 
						|
Ascii2Unicode (
 | 
						|
  OUT CHAR16         *UnicodeStr,
 | 
						|
  IN  CHAR8          *AsciiStr
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
 | 
						|
    This function converts ASCII string to Unicode string.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
 | 
						|
    UnicodeStr     - NULL terminated Unicode output string.
 | 
						|
    AsciieStr      - NULL terminated ASCII input string.
 | 
						|
 | 
						|
  Returns:
 | 
						|
 | 
						|
    Start of the Unicode ouput string.
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
{
 | 
						|
  CHAR16      *Str = UnicodeStr;
 | 
						|
  while (TRUE) {
 | 
						|
    *(UnicodeStr++) = (CHAR16) *AsciiStr;
 | 
						|
    if (*(AsciiStr++) == '\0') {
 | 
						|
      return Str;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
CHAR8*
 | 
						|
Unicode2Ascii (
 | 
						|
  OUT CHAR8          *AsciiStr,
 | 
						|
  IN  CHAR16         *UnicodeStr
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
 | 
						|
    This function converts Unicode string to ASCII string.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
 | 
						|
    AsciieStr      - NULL terminated ASCII output string.
 | 
						|
    UnicodeStr     - NULL terminated Unicode input string.
 | 
						|
 | 
						|
  Returns:
 | 
						|
 | 
						|
    Start of the ASCII ouput string.
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
{
 | 
						|
  CHAR8      *Str = AsciiStr;
 | 
						|
  while (TRUE) {
 | 
						|
    *(AsciiStr++) = (CHAR8) *UnicodeStr;
 | 
						|
    if (*(UnicodeStr++) == '\0') {
 | 
						|
      return Str;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
ExtractDevicePathData (
 | 
						|
  IN     EFI_HII_DATA_TABLE   *DataTable,
 | 
						|
  IN     UINT8                *IfrData,
 | 
						|
  IN OUT UINT8                **ExportBufferPtr
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINT8 *ExportBuffer;
 | 
						|
 | 
						|
  ExportBuffer = *ExportBufferPtr;
 | 
						|
 | 
						|
  //
 | 
						|
  // BUGBUG - don't have devicepath data yet, setting dummy value
 | 
						|
  //
 | 
						|
  DataTable++;
 | 
						|
  ExportBuffer  = (UINT8 *) DataTable;
 | 
						|
  ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Type = EFI_HII_DEVICE_PATH;
 | 
						|
  ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Length = (UINT32) (sizeof (EFI_HII_DEVICE_PATH_PACK) + sizeof (EFI_DEVICE_PATH_PROTOCOL));
 | 
						|
 | 
						|
  //
 | 
						|
  // BUGBUG - part of hack - skip the Device Path Pack.....place some data
 | 
						|
  //
 | 
						|
  ExportBuffer  = ExportBuffer + sizeof (EFI_HII_DEVICE_PATH_PACK);
 | 
						|
 | 
						|
  ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->Type     = EFI_END_ENTIRE_DEVICE_PATH;
 | 
						|
  ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->SubType  = EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
 | 
						|
 | 
						|
  //
 | 
						|
  // BUGBUG - still part of hack....
 | 
						|
  //
 | 
						|
  ExportBuffer      = ExportBuffer + sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
  *ExportBufferPtr  = ExportBuffer;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
ExtractVariableData (
 | 
						|
  IN OUT EFI_HII_DATA_TABLE   *DataTable,
 | 
						|
  IN     UINT8                *IfrData,
 | 
						|
  IN OUT UINT8                **ExportBufferPtr
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function extract the EFI_HII_VARIABLE_PACK portion from the
 | 
						|
  each of the EFI_HII_PACKAGE_INSTANCE in HII handle database.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  DataTable       - On input, this parameter point to the EFI_HII_DATA_TABLE structure
 | 
						|
                    of the final data buffer for the EFI_HII_EXPORT interface. This function
 | 
						|
                    update the NumberOfVariableData attribute.
 | 
						|
  IfrData         - It points to a staring address of a EFI_HII_IFR_PACK structure.
 | 
						|
  ExportBufferPtr - On input, it points the starting address of the data buffer to
 | 
						|
                    host the variable pack. On output, it is the starting address
 | 
						|
                    of data buffer for the next extraction operation.
 | 
						|
Returns:
 | 
						|
 | 
						|
  VOID
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_VARIABLE_PACK       *VariableContents;
 | 
						|
  UINT8                       *ExportBuffer;
 | 
						|
  UINTN                       Index;
 | 
						|
  UINTN                       Index2;
 | 
						|
  UINTN                       TempValue;
 | 
						|
  UINTN                       TempValue2;
 | 
						|
  EFI_FORM_CALLBACK_PROTOCOL  *FormCallback;
 | 
						|
  EFI_PHYSICAL_ADDRESS        CallbackHandle;
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  CHAR16                      *String;
 | 
						|
 | 
						|
  FormCallback    = NULL;
 | 
						|
  CallbackHandle  = 0;
 | 
						|
  ExportBuffer    = *ExportBufferPtr;
 | 
						|
 | 
						|
  for (Index = 0; IfrData[Index] != EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
    VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer;
 | 
						|
 | 
						|
    switch (IfrData[Index]) {
 | 
						|
    case EFI_IFR_FORM_SET_OP:
 | 
						|
      TempValue = EFI_HII_VARIABLE;
 | 
						|
      CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));
 | 
						|
      CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));
 | 
						|
 | 
						|
      //
 | 
						|
      // If the variable has 0 size, do not process it
 | 
						|
      //
 | 
						|
      if (TempValue == 0) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Add the size of the variable pack overhead.  Later, will also add the size of the
 | 
						|
      // name of the variable.
 | 
						|
      //
 | 
						|
      TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
 | 
						|
      CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));
 | 
						|
      CopyMem (
 | 
						|
        &CallbackHandle,
 | 
						|
        &((EFI_IFR_FORM_SET *) &IfrData[Index])->CallbackHandle,
 | 
						|
        sizeof (EFI_PHYSICAL_ADDRESS)
 | 
						|
        );
 | 
						|
      if (CallbackHandle != 0) {
 | 
						|
        Status = gBS->HandleProtocol (
 | 
						|
                        (EFI_HANDLE) (UINTN) CallbackHandle,
 | 
						|
                        &gEfiFormCallbackProtocolGuid,
 | 
						|
                        (VOID *) &FormCallback
 | 
						|
                        );
 | 
						|
        ASSERT_EFI_ERROR (Status);
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Since we have a "Setup" variable that wasn't specified by a variable op-code
 | 
						|
      // it will have a VariableId of 0.  All other variable op-codes will have a designation
 | 
						|
      // of VariableId 1+
 | 
						|
      //
 | 
						|
      TempValue = 0;
 | 
						|
      CopyMem (&VariableContents->VariableId, &TempValue, sizeof (UINT16));
 | 
						|
      CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_FORM_SET *) &IfrData[Index])->Guid, sizeof (EFI_GUID));
 | 
						|
      TempValue = sizeof (SETUP_MAP_NAME);
 | 
						|
      CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));
 | 
						|
 | 
						|
      //
 | 
						|
      // Add the size of the name to the Header Length
 | 
						|
      //
 | 
						|
      TempValue2 = 0;
 | 
						|
      CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));
 | 
						|
      TempValue2 = TempValue + TempValue2;
 | 
						|
      CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));
 | 
						|
 | 
						|
      ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
      CopyMem (ExportBuffer, SETUP_MAP_NAME, sizeof (SETUP_MAP_NAME));
 | 
						|
      ExportBuffer = ExportBuffer + sizeof (SETUP_MAP_NAME);
 | 
						|
 | 
						|
      CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16));
 | 
						|
 | 
						|
      if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
 | 
						|
        Status = FormCallback->NvRead (
 | 
						|
                                 FormCallback,
 | 
						|
                                 (CHAR16 *) SETUP_MAP_NAME,
 | 
						|
                                 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,
 | 
						|
                                 NULL,
 | 
						|
                                 &TempValue,
 | 
						|
                                 ExportBuffer
 | 
						|
                                 );
 | 
						|
        ASSERT_EFI_ERROR (Status);
 | 
						|
      } else {
 | 
						|
        Status = gRT->GetVariable (
 | 
						|
                        (CHAR16 *) SETUP_MAP_NAME,
 | 
						|
                        (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,
 | 
						|
                        NULL,
 | 
						|
                        &TempValue,
 | 
						|
                        ExportBuffer
 | 
						|
                        );
 | 
						|
        ASSERT_EFI_ERROR (Status);
 | 
						|
      }
 | 
						|
 | 
						|
      ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);
 | 
						|
      DataTable->NumberOfVariableData++;
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_IFR_VARSTORE_OP:
 | 
						|
      TempValue = EFI_HII_VARIABLE;
 | 
						|
      CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));
 | 
						|
      CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16));
 | 
						|
 | 
						|
      //
 | 
						|
      // If the variable has 0 size, do not process it
 | 
						|
      //
 | 
						|
      if (TempValue == 0) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Add the size of the variable pack overhead.  Later, will also add the size of the
 | 
						|
      // name of the variable.
 | 
						|
      //
 | 
						|
      TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
 | 
						|
      CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));
 | 
						|
      CopyMem (&VariableContents->VariableId, &((EFI_IFR_VARSTORE *) &IfrData[Index])->VarId, sizeof (UINT16));
 | 
						|
      CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Guid, sizeof (EFI_GUID));
 | 
						|
      TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &IfrData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);
 | 
						|
      TempValue = TempValue * 2;
 | 
						|
      CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32));
 | 
						|
 | 
						|
      //
 | 
						|
      // Add the size of the name to the Header Length
 | 
						|
      //
 | 
						|
      TempValue2 = 0;
 | 
						|
      CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32));
 | 
						|
      TempValue2 = TempValue + TempValue2;
 | 
						|
      CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32));
 | 
						|
 | 
						|
      ExportBuffer  = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
      String        = (CHAR16 *) ExportBuffer;
 | 
						|
      for (Index2 = 0; Index2 < TempValue / 2; Index2++) {
 | 
						|
        ExportBuffer[Index2 * 2]      = IfrData[Index + sizeof (EFI_IFR_VARSTORE) + Index2];
 | 
						|
        ExportBuffer[Index2 * 2 + 1]  = 0;
 | 
						|
      }
 | 
						|
 | 
						|
      ExportBuffer = ExportBuffer + TempValue;
 | 
						|
 | 
						|
      CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16));
 | 
						|
 | 
						|
      if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
 | 
						|
        Status = FormCallback->NvRead (
 | 
						|
                                 FormCallback,
 | 
						|
                                 String,
 | 
						|
                                 (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,
 | 
						|
                                 NULL,
 | 
						|
                                 &TempValue,
 | 
						|
                                 ExportBuffer
 | 
						|
                                 );
 | 
						|
        ASSERT_EFI_ERROR (Status);
 | 
						|
      } else {
 | 
						|
        Status = gRT->GetVariable (
 | 
						|
                        String,
 | 
						|
                        (EFI_GUID *)(UINTN)&VariableContents->VariableGuid,
 | 
						|
                        NULL,
 | 
						|
                        &TempValue,
 | 
						|
                        ExportBuffer
 | 
						|
                        );
 | 
						|
        ASSERT_EFI_ERROR (Status);
 | 
						|
      }
 | 
						|
 | 
						|
      ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue);
 | 
						|
      DataTable->NumberOfVariableData++;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Index = IfrData[Index + 1] + Index;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If we have added a variable pack, add a dummy empty one to signify the end
 | 
						|
  //
 | 
						|
  if (ExportBuffer != *ExportBufferPtr) {
 | 
						|
    VariableContents  = (EFI_HII_VARIABLE_PACK *) ExportBuffer;
 | 
						|
    TempValue         = EFI_HII_VARIABLE;
 | 
						|
    CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16));
 | 
						|
    TempValue = sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
    CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32));
 | 
						|
    ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
  }
 | 
						|
 | 
						|
  *ExportBufferPtr = ExportBuffer;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HiiExportDatabase (
 | 
						|
  IN     EFI_HII_PROTOCOL *This,
 | 
						|
  IN     EFI_HII_HANDLE   Handle,
 | 
						|
  IN OUT UINTN            *BufferSize,
 | 
						|
  OUT    VOID             *Buffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function allows a program to extract a form or form package that has
 | 
						|
  previously been registered with the EFI HII database.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_PACKAGE_INSTANCE  *PackageInstance;
 | 
						|
  EFI_HII_DATA              *HiiData;
 | 
						|
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
 | 
						|
  EFI_HII_IFR_PACK          *FormPack;
 | 
						|
  UINT8                     *RawData;
 | 
						|
  UINT8                     *ExportBuffer;
 | 
						|
  EFI_HII_EXPORT_TABLE      *ExportTable;
 | 
						|
  EFI_HII_DATA_TABLE        *DataTable;
 | 
						|
  BOOLEAN                   VariableExist;
 | 
						|
  UINT16                    NumberOfHiiDataTables;
 | 
						|
  UINTN                     SizeNeeded;
 | 
						|
  UINTN                     Index;
 | 
						|
  UINTN                     VariableSize;
 | 
						|
  UINTN                     TempValue;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  HiiData               = EFI_HII_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  HandleDatabase        = HiiData->DatabaseHead;
 | 
						|
 | 
						|
  FormPack              = NULL;
 | 
						|
  RawData               = NULL;
 | 
						|
  PackageInstance       = NULL;
 | 
						|
  NumberOfHiiDataTables = 0;
 | 
						|
  VariableSize          = 0;
 | 
						|
  TempValue             = 0;
 | 
						|
  SizeNeeded            = sizeof (EFI_HII_EXPORT_TABLE);
 | 
						|
 | 
						|
  //
 | 
						|
  // How many total tables are there?
 | 
						|
  //
 | 
						|
  for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
 | 
						|
    if ((Handle != 0) && (Handle != HandleDatabase->Handle)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    VariableExist = FALSE;
 | 
						|
    NumberOfHiiDataTables++;
 | 
						|
    PackageInstance = HandleDatabase->Buffer;
 | 
						|
    if (PackageInstance == NULL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Extract Size of Export Package
 | 
						|
    //
 | 
						|
    SizeNeeded = SizeNeeded + PackageInstance->IfrSize
 | 
						|
                            + PackageInstance->StringSize
 | 
						|
                            + sizeof (EFI_HII_DATA_TABLE)
 | 
						|
                            + sizeof (EFI_HII_DEVICE_PATH_PACK);
 | 
						|
 | 
						|
    //
 | 
						|
    // BUGBUG We aren't inserting Device path data yet
 | 
						|
    //
 | 
						|
    SizeNeeded = SizeNeeded + sizeof (EFI_DEVICE_PATH_PROTOCOL);
 | 
						|
 | 
						|
    //
 | 
						|
    // Extract Size of Variable Data
 | 
						|
    //
 | 
						|
    if (PackageInstance->IfrSize > 0) {
 | 
						|
      FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // No IFR? No variable information
 | 
						|
      //
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    RawData = (UINT8 *) FormPack;
 | 
						|
 | 
						|
    for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
      switch (RawData[Index]) {
 | 
						|
      case EFI_IFR_FORM_SET_OP:
 | 
						|
        CopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) &RawData[Index])->NvDataSize, sizeof (UINT16));
 | 
						|
        SizeNeeded    = SizeNeeded + VariableSize + sizeof (SETUP_MAP_NAME) + sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
        VariableExist = TRUE;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_IFR_VARSTORE_OP:
 | 
						|
        CopyMem (&VariableSize, &((EFI_IFR_VARSTORE *) &RawData[Index])->Size, sizeof (UINT16));
 | 
						|
        SizeNeeded = SizeNeeded + VariableSize + sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
        //
 | 
						|
        // We will be expanding the stored ASCII name to a Unicode string.  This will cause some memory overhead
 | 
						|
        // Since the VARSTORE size already takes in consideration the ASCII size, we need to size it and add another
 | 
						|
        // instance of it.  Essentially, 2 ASCII strings == 1 Unicode string in size.
 | 
						|
        //
 | 
						|
        TempValue     = (UINTN) ((EFI_IFR_VARSTORE *) &RawData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE);
 | 
						|
        SizeNeeded    = SizeNeeded + TempValue * 2;
 | 
						|
        VariableExist = TRUE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      Index = RawData[Index + 1] + Index;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If a variable exists for this handle, add an additional variable pack overhead to
 | 
						|
    // indicate that we will have an extra null Variable Pack to signify the end of the Variable Packs
 | 
						|
    //
 | 
						|
    if (VariableExist) {
 | 
						|
      SizeNeeded = SizeNeeded + sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (SizeNeeded > *BufferSize) {
 | 
						|
    *BufferSize = SizeNeeded;
 | 
						|
    return EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Zero out the incoming buffer
 | 
						|
  //
 | 
						|
  ZeroMem (Buffer, *BufferSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Cast the Buffer to EFI_HII_EXPORT_TABLE
 | 
						|
  //
 | 
						|
  ExportTable = (EFI_HII_EXPORT_TABLE *) Buffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set the Revision for the Export Table
 | 
						|
  //
 | 
						|
  CopyMem (&ExportTable->Revision, &gEfiHiiProtocolGuid, sizeof (EFI_GUID));
 | 
						|
 | 
						|
  ExportBuffer    = (UINT8 *) (UINTN) (((UINT8 *) ExportTable) + sizeof (EFI_HII_EXPORT_TABLE));
 | 
						|
  HandleDatabase  = HiiData->DatabaseHead;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check numeric value against the head of the database
 | 
						|
  //
 | 
						|
  for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
 | 
						|
    DataTable       = (EFI_HII_DATA_TABLE *) ExportBuffer;
 | 
						|
    PackageInstance = HandleDatabase->Buffer;
 | 
						|
    //
 | 
						|
    // If not asking for a specific handle, export the entire database
 | 
						|
    //
 | 
						|
    if (Handle == 0) {
 | 
						|
      ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables;
 | 
						|
      CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));
 | 
						|
      DataTable->HiiHandle        = PackageInstance->Handle;
 | 
						|
      DataTable->DevicePathOffset = (UINT32) (sizeof (EFI_HII_DATA_TABLE));
 | 
						|
 | 
						|
      //
 | 
						|
      // Start Dumping DevicePath
 | 
						|
      //
 | 
						|
      ExtractDevicePathData (DataTable, RawData, &ExportBuffer);
 | 
						|
 | 
						|
      if (((UINTN) ExportBuffer) == ((UINTN) DataTable)) {
 | 
						|
        //
 | 
						|
        // If there is no DevicePath information - set offset to 0 to signify the absence of data to parse
 | 
						|
        //
 | 
						|
        DataTable->DevicePathOffset = 0;
 | 
						|
      }
 | 
						|
 | 
						|
      DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
 | 
						|
 | 
						|
      if (PackageInstance->IfrSize > 0) {
 | 
						|
        FormPack  = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
 | 
						|
        RawData   = (UINT8 *) FormPack;
 | 
						|
        TempValue = 0;
 | 
						|
 | 
						|
        //
 | 
						|
        // Start dumping the Variable Data
 | 
						|
        //
 | 
						|
        ExtractVariableData (DataTable, RawData, &ExportBuffer);
 | 
						|
        DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
 | 
						|
 | 
						|
        if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {
 | 
						|
          DataTable->VariableDataOffset = 0;
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Start dumping the IFR data (Note:  It is in an IFR PACK)
 | 
						|
        //
 | 
						|
        CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);
 | 
						|
        ExportBuffer                = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);
 | 
						|
        DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
 | 
						|
 | 
						|
        //
 | 
						|
        // Start dumping the String data (Note:  It is in a String PACK)
 | 
						|
        //
 | 
						|
        if (PackageInstance->StringSize > 0) {
 | 
						|
          RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
 | 
						|
          CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
 | 
						|
          DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);
 | 
						|
 | 
						|
          CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
 | 
						|
          for (; TempValue != 0;) {
 | 
						|
            DataTable->NumberOfLanguages++;
 | 
						|
            ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
 | 
						|
            CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
 | 
						|
          }
 | 
						|
 | 
						|
          ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
 | 
						|
        } else {
 | 
						|
          DataTable->StringDataOffset = 0;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // No IFR? No variable information.  If Offset is 0, means there is none.  (Hmm - this might be prunable - no strings to export if no IFR - we always have a stub)
 | 
						|
        //
 | 
						|
        DataTable->VariableDataOffset = 0;
 | 
						|
        DataTable->IfrDataOffset      = 0;
 | 
						|
        DataTable->StringDataOffset   = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
 | 
						|
 | 
						|
        //
 | 
						|
        // Start dumping the String data - NOTE:  It is in String Pack form
 | 
						|
        //
 | 
						|
        if (PackageInstance->StringSize > 0) {
 | 
						|
          RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
 | 
						|
          CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
 | 
						|
          DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);
 | 
						|
 | 
						|
          CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
 | 
						|
          for (; TempValue != 0;) {
 | 
						|
            DataTable->NumberOfLanguages++;
 | 
						|
            ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
 | 
						|
            CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
 | 
						|
          }
 | 
						|
 | 
						|
          ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
 | 
						|
        } else {
 | 
						|
          DataTable->StringDataOffset = 0;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Match the numeric value with the database entry - if matched, extract PackageInstance
 | 
						|
      //
 | 
						|
      if (Handle == HandleDatabase->Handle) {
 | 
						|
        PackageInstance                     = HandleDatabase->Buffer;
 | 
						|
        ExportTable->NumberOfHiiDataTables  = NumberOfHiiDataTables;
 | 
						|
        DataTable->HiiHandle                = PackageInstance->Handle;
 | 
						|
        CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID));
 | 
						|
 | 
						|
        //
 | 
						|
        // Start Dumping DevicePath
 | 
						|
        //
 | 
						|
        ExtractDevicePathData (DataTable, RawData, &ExportBuffer);
 | 
						|
        DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
 | 
						|
 | 
						|
        if (PackageInstance->IfrSize > 0) {
 | 
						|
          FormPack  = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
 | 
						|
          RawData   = (UINT8 *) FormPack;
 | 
						|
          TempValue = 0;
 | 
						|
 | 
						|
          //
 | 
						|
          // Start dumping the Variable Data
 | 
						|
          //
 | 
						|
          ExtractVariableData (DataTable, RawData, &ExportBuffer);
 | 
						|
          DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
 | 
						|
 | 
						|
          if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) {
 | 
						|
            DataTable->VariableDataOffset = 0;
 | 
						|
          }
 | 
						|
          //
 | 
						|
          // Start dumping the IFR data
 | 
						|
          //
 | 
						|
          CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize);
 | 
						|
          ExportBuffer                = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize);
 | 
						|
          DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
 | 
						|
 | 
						|
          //
 | 
						|
          // Start dumping the String data - NOTE:  It is in String Pack form
 | 
						|
          //
 | 
						|
          if (PackageInstance->StringSize > 0) {
 | 
						|
            RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
 | 
						|
            CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
 | 
						|
            DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);
 | 
						|
 | 
						|
            CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
 | 
						|
            for (; TempValue != 0;) {
 | 
						|
              DataTable->NumberOfLanguages++;
 | 
						|
              ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
 | 
						|
              CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
 | 
						|
            }
 | 
						|
 | 
						|
            ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
 | 
						|
          } else {
 | 
						|
            DataTable->StringDataOffset = 0;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // No IFR? No variable information.  If Offset is 0, means there is none.
 | 
						|
          //
 | 
						|
          DataTable->VariableDataOffset = 0;
 | 
						|
          DataTable->IfrDataOffset      = 0;
 | 
						|
          DataTable->StringDataOffset   = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable));
 | 
						|
 | 
						|
          //
 | 
						|
          // Start dumping the String data - Note:  It is in String Pack form
 | 
						|
          //
 | 
						|
          if (PackageInstance->StringSize > 0) {
 | 
						|
            RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize);
 | 
						|
            CopyMem (ExportBuffer, RawData, PackageInstance->StringSize);
 | 
						|
            DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize);
 | 
						|
 | 
						|
            CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
 | 
						|
            for (; TempValue != 0;) {
 | 
						|
              DataTable->NumberOfLanguages++;
 | 
						|
              ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length;
 | 
						|
              CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32));
 | 
						|
            }
 | 
						|
 | 
						|
            ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK);
 | 
						|
          } else {
 | 
						|
            DataTable->StringDataOffset = 0;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HiiGetForms (
 | 
						|
  IN     EFI_HII_PROTOCOL   *This,
 | 
						|
  IN     EFI_HII_HANDLE     Handle,
 | 
						|
  IN     EFI_FORM_ID        FormId,
 | 
						|
  IN OUT UINTN              *BufferLengthTemp,
 | 
						|
  OUT    UINT8              *Buffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function allows a program to extract a form or form package that has
 | 
						|
  previously been registered with the EFI HII database.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  This         - A pointer to the EFI_HII_PROTOCOL instance.
 | 
						|
 | 
						|
  Handle       - Handle on which the form resides. Type EFI_HII_HANDLE is defined in
 | 
						|
                 EFI_HII_PROTOCOL.NewPack() in the Packages section.
 | 
						|
 | 
						|
  FormId       - The ID of the form to return. If the ID is zero, the entire form package is returned.
 | 
						|
                 Type EFI_FORM_ID is defined in "Related Definitions" below.
 | 
						|
 | 
						|
  BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if
 | 
						|
                 the length was sufficient and, if it was not, the length that is required to fit the
 | 
						|
                 requested form(s).
 | 
						|
 | 
						|
  Buffer       - The buffer designed to receive the form(s).
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS           -  Buffer filled with the requested forms. BufferLength
 | 
						|
                           was updated.
 | 
						|
 | 
						|
  EFI_INVALID_PARAMETER -  The handle is unknown.
 | 
						|
 | 
						|
  EFI_NOT_FOUND         -  A form on the requested handle cannot be found with the
 | 
						|
                           requested FormId.
 | 
						|
 | 
						|
  EFI_BUFFER_TOO_SMALL  - The buffer provided was not large enough to allow the form to be stored.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_PACKAGE_INSTANCE  *PackageInstance;
 | 
						|
  EFI_HII_DATA              *HiiData;
 | 
						|
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
 | 
						|
  EFI_HII_IFR_PACK          *FormPack;
 | 
						|
  EFI_IFR_FORM              *Form;
 | 
						|
  EFI_IFR_OP_HEADER         *Location;
 | 
						|
  UINT16                    *BufferLength = (UINT16 *) BufferLengthTemp;
 | 
						|
  UINTN                     FormLength;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  HiiData         = EFI_HII_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  HandleDatabase  = HiiData->DatabaseHead;
 | 
						|
 | 
						|
  PackageInstance = NULL;
 | 
						|
 | 
						|
  FormLength      = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check numeric value against the head of the database
 | 
						|
  //
 | 
						|
  for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
 | 
						|
    //
 | 
						|
    // Match the numeric value with the database entry - if matched, extract PackageInstance
 | 
						|
    //
 | 
						|
    if (Handle == HandleDatabase->Handle) {
 | 
						|
      PackageInstance = HandleDatabase->Buffer;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // No handle was found - error condition
 | 
						|
  //
 | 
						|
  if (PackageInstance == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Based on if there is IFR data in this package instance, determine
 | 
						|
  // what the location is of the beginning of the string data.
 | 
						|
  //
 | 
						|
  if (PackageInstance->IfrSize > 0) {
 | 
						|
    FormPack = (EFI_HII_IFR_PACK *) (&PackageInstance->IfrData);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // If there is no IFR data return an error
 | 
						|
    //
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If requesting the entire Form Package
 | 
						|
  //
 | 
						|
  if (FormId == 0) {
 | 
						|
    //
 | 
						|
    // Return an error if buffer is too small
 | 
						|
    //
 | 
						|
    if (PackageInstance->IfrSize > *BufferLength || Buffer == NULL) {
 | 
						|
      *BufferLength = (UINT16) PackageInstance->IfrSize;
 | 
						|
      return EFI_BUFFER_TOO_SMALL;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (Buffer, FormPack, PackageInstance->IfrSize);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    FormPack  = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
    Location  = (EFI_IFR_OP_HEADER *) FormPack;
 | 
						|
 | 
						|
    //
 | 
						|
    // Look for the FormId requested
 | 
						|
    //
 | 
						|
    for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
      switch (Location->OpCode) {
 | 
						|
      case EFI_IFR_FORM_OP:
 | 
						|
        Form = (EFI_IFR_FORM *) Location;
 | 
						|
 | 
						|
        //
 | 
						|
        // If we found a Form Op-code and it is of the correct Id, copy it and return
 | 
						|
        //
 | 
						|
        if (Form->FormId == FormId) {
 | 
						|
          //
 | 
						|
          // Calculate the total size of form
 | 
						|
          //
 | 
						|
          for (FormLength = 0; Location->OpCode != EFI_IFR_END_FORM_OP; ) {
 | 
						|
            FormLength += Location->Length;
 | 
						|
            Location    = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
          }
 | 
						|
          FormLength += Location->Length;
 | 
						|
          Location    = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
 | 
						|
          if ((Buffer == NULL) || (FormLength > *BufferLength)) {
 | 
						|
            *BufferLengthTemp = FormLength;
 | 
						|
            return EFI_BUFFER_TOO_SMALL;
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
          // Rewind to start offset of the found Form
 | 
						|
          //
 | 
						|
          Location   = (EFI_IFR_OP_HEADER *) ((CHAR8 *)Location - FormLength);
 | 
						|
          CopyMem (Buffer, Location, FormLength);
 | 
						|
          return EFI_SUCCESS;
 | 
						|
        }
 | 
						|
 | 
						|
      default:
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Go to the next Op-Code
 | 
						|
      //
 | 
						|
      Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Helper functions to HiiGetDefaultImage()
 | 
						|
//
 | 
						|
 | 
						|
STATIC
 | 
						|
UINT8*
 | 
						|
HiiGetDefaultImageInitPack (
 | 
						|
  IN OUT EFI_HII_VARIABLE_PACK_LIST  *VariablePackItem,
 | 
						|
  IN     EFI_IFR_VARSTORE            *VarStore
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
 | 
						|
    Initialize the EFI_HII_VARIABLE_PACK_LIST structure and
 | 
						|
    prepare it ready to be used by HiiGetDefaultImagePopulateMap ().
 | 
						|
 | 
						|
  Arguments:
 | 
						|
 | 
						|
    VariablePackItem     - Variable Package List.
 | 
						|
    VarStore             - IFR variable storage.
 | 
						|
 | 
						|
  Returns:
 | 
						|
 | 
						|
    Return the pointer to the Map space.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  CHAR16                *Name16;
 | 
						|
  CHAR8                 *Name8;
 | 
						|
  CHAR8                 *Map;
 | 
						|
  EFI_HII_VARIABLE_PACK *VariablePack;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set pointer the pack right after the node
 | 
						|
  //
 | 
						|
  VariablePackItem->VariablePack = (EFI_HII_VARIABLE_PACK *) (VariablePackItem + 1);
 | 
						|
  VariablePack                   = VariablePackItem->VariablePack;
 | 
						|
 | 
						|
  //
 | 
						|
  // Copy the var name to VariablePackItem from VarStore
 | 
						|
  // Needs ASCII->Unicode conversion.
 | 
						|
  //
 | 
						|
  ASSERT (VarStore->Header.Length > sizeof (*VarStore));
 | 
						|
  Name8  = (CHAR8 *) (VarStore + 1);
 | 
						|
  Name16 = (CHAR16 *) (VariablePack + 1);
 | 
						|
  Ascii2Unicode (Name16, Name8);
 | 
						|
 | 
						|
  //
 | 
						|
  // Compute the other fields of the VariablePackItem
 | 
						|
  //
 | 
						|
  VariablePack->VariableId         = VarStore->VarId;
 | 
						|
  CopyMem (&VariablePack->VariableGuid, &VarStore->Guid, sizeof (EFI_GUID));
 | 
						|
  VariablePack->VariableNameLength = (UINT32) ((StrLen (Name16) + 1) * 2);
 | 
						|
  VariablePack->Header.Length      = sizeof (*VariablePack)
 | 
						|
                                              + VariablePack->VariableNameLength
 | 
						|
                                              + VarStore->Size;
 | 
						|
  //
 | 
						|
  // Return the pointer to the Map space.
 | 
						|
  //
 | 
						|
  Map = (CHAR8 *) Name16 + VariablePack->VariableNameLength;
 | 
						|
 | 
						|
  return (UINT8 *)Map;
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
HiiGetDefaultImagePopulateMap (
 | 
						|
  IN OUT UINT8                        *Map,
 | 
						|
  IN     EFI_IFR_OP_HEADER            *FormSet,
 | 
						|
  IN     EFI_IFR_VARSTORE             *VarStore,
 | 
						|
  IN     UINTN                        DefaultMask
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
 | 
						|
   Fill the Map with all the default values either from NV or Hii database.
 | 
						|
 | 
						|
  Arguments:
 | 
						|
 | 
						|
   Map         - Memory pointer to hold the default values.
 | 
						|
   FormSet     - The starting EFI_IFR_OP_HEADER to begin retriving default values.
 | 
						|
   VarStore    - IFR variable storage.
 | 
						|
   DefaultMask - The mask used to get the default variable.
 | 
						|
 | 
						|
  Returns:
 | 
						|
 | 
						|
   VOID
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  EFI_IFR_OP_HEADER              *IfrItem;
 | 
						|
  UINT16                         VarId;
 | 
						|
  EFI_IFR_VARSTORE_SELECT        *VarSelect;
 | 
						|
  EFI_IFR_ONE_OF_OPTION          *OneOfOpt;
 | 
						|
  EFI_IFR_CHECKBOX               *CheckBox;
 | 
						|
  EFI_IFR_NUMERIC                *Numeric;
 | 
						|
  UINTN                          Size;
 | 
						|
  UINTN                          SizeTmp;
 | 
						|
  EFI_IFR_NV_DATA                *IfrNvData;
 | 
						|
  EFI_GUID                       Guid;
 | 
						|
  CHAR16                         *Name16;
 | 
						|
  CHAR8                          *Name8;
 | 
						|
  EFI_HANDLE                      CallbackHandle;
 | 
						|
  EFI_FORM_CALLBACK_PROTOCOL     *FormCallbackProt;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the Map's Name/Guid/Szie from the Varstore.
 | 
						|
  // VARSTORE contains the Name in ASCII format (@#$^&!), must convert it to Unicode.
 | 
						|
  //
 | 
						|
  ASSERT (VarStore->Header.Length >= sizeof (*VarStore));
 | 
						|
  Name8  = (CHAR8 *) (VarStore + 1);
 | 
						|
  Name16 = AllocateZeroPool ((VarStore->Header.Length - sizeof (*VarStore)) * sizeof (CHAR16));
 | 
						|
  Ascii2Unicode (Name16, Name8);
 | 
						|
  CopyMem (&Guid, &VarStore->Guid, sizeof(EFI_GUID));
 | 
						|
  Size = VarStore->Size;
 | 
						|
 | 
						|
  //
 | 
						|
  // First, check if the map exists in the NV. If so, get it from NV and exit.
 | 
						|
  //
 | 
						|
  if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {
 | 
						|
    //
 | 
						|
    // Check if Manufaturing Defaults exist in the NV.
 | 
						|
    //
 | 
						|
    Status = EfiLibHiiVariableOverrideBySuffix (
 | 
						|
                  HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE,
 | 
						|
                  Name16,
 | 
						|
                  &Guid,
 | 
						|
                  Size,
 | 
						|
                  Map
 | 
						|
                  );
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // All other cases default to Defaults. Check if Defaults exist in the NV.
 | 
						|
    //
 | 
						|
    Status = EfiLibHiiVariableOverrideBySuffix (
 | 
						|
                  HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE,
 | 
						|
                  Name16,
 | 
						|
                  &Guid,
 | 
						|
                  Size,
 | 
						|
                  Map
 | 
						|
                  );
 | 
						|
  }
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Either Defaults/Manufacturing variable exists and appears to be valid.
 | 
						|
    // The map is read, exit w/ success now.
 | 
						|
    //
 | 
						|
    FreePool (Name16);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // First, prime the map with what already is in the NV.
 | 
						|
  // This is needed to cover a situation where the IFR does not contain all the
 | 
						|
  // defaults; either deliberately not having appropriate IFR, or in case of IFR_STRING, there is no default.
 | 
						|
  // Ignore status. Either it gets read or not.
 | 
						|
  //
 | 
						|
  FormCallbackProt = NULL;
 | 
						|
  CopyMem (&CallbackHandle, &((EFI_IFR_FORM_SET*) FormSet)->CallbackHandle, sizeof (CallbackHandle));
 | 
						|
  if (CallbackHandle != NULL) {
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    (EFI_HANDLE) (UINTN) CallbackHandle,
 | 
						|
                    &gEfiFormCallbackProtocolGuid,
 | 
						|
                    (VOID *) &FormCallbackProt
 | 
						|
                    );
 | 
						|
  }
 | 
						|
  if ((NULL != FormCallbackProt) && (NULL != FormCallbackProt->NvRead)) {
 | 
						|
    //
 | 
						|
    // Attempt to read using NvRead() callback. Probe first for existence and correct variable size.
 | 
						|
    //
 | 
						|
    SizeTmp = 0;
 | 
						|
    Status = FormCallbackProt->NvRead (
 | 
						|
                    FormCallbackProt,
 | 
						|
                    Name16,
 | 
						|
                    &Guid,
 | 
						|
                    0,
 | 
						|
                    &SizeTmp,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    if ((EFI_BUFFER_TOO_SMALL == Status) && (SizeTmp == Size)) {
 | 
						|
      Status = FormCallbackProt->NvRead (
 | 
						|
                      FormCallbackProt,
 | 
						|
                      Name16,
 | 
						|
                      &Guid,
 | 
						|
                      0,
 | 
						|
                      &SizeTmp,
 | 
						|
                      Map
 | 
						|
                      );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
      ASSERT (SizeTmp == Size);
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // No callback available for this formset, read straight from NV. Deliberately ignore the Status.
 | 
						|
    // The buffer will only be written if variable exists nd has correct size.
 | 
						|
    //
 | 
						|
    Status = EfiLibHiiVariableRetrieveFromNv (
 | 
						|
                    Name16,
 | 
						|
                    &Guid,
 | 
						|
                    Size,
 | 
						|
                    (VOID **) &Map
 | 
						|
                    );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Iterate all IFR statements and for applicable, retrieve the default into the Map.
 | 
						|
  //
 | 
						|
  for (IfrItem = FormSet, VarId = 0;
 | 
						|
       IfrItem->OpCode != EFI_IFR_END_FORM_SET_OP;
 | 
						|
       IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length)
 | 
						|
      ) {
 | 
						|
 | 
						|
    //
 | 
						|
    // Observe VarStore switch.
 | 
						|
    //
 | 
						|
    if (EFI_IFR_VARSTORE_SELECT_OP == IfrItem->OpCode) {
 | 
						|
      VarSelect = (EFI_IFR_VARSTORE_SELECT *) IfrItem;
 | 
						|
      VarId = VarSelect->VarId;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip opcodes that reference other VarStore than that specific to current map.
 | 
						|
    //
 | 
						|
    if (VarId != VarStore->VarId) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Extract the default value from this opcode if applicable, and apply it to the map.
 | 
						|
    //
 | 
						|
    IfrNvData = (EFI_IFR_NV_DATA *) IfrItem;
 | 
						|
    switch (IfrItem->OpCode) {
 | 
						|
 | 
						|
      case EFI_IFR_ONE_OF_OP:
 | 
						|
        ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);
 | 
						|
        //
 | 
						|
        // Get to the first EFI_IFR_ONE_OF_OPTION_OP
 | 
						|
        //
 | 
						|
        IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length);
 | 
						|
        ASSERT (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode);
 | 
						|
 | 
						|
        OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;
 | 
						|
        //
 | 
						|
        // In the worst case, the first will be the default.
 | 
						|
        //
 | 
						|
        CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);
 | 
						|
 | 
						|
        while (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode) {
 | 
						|
 | 
						|
          OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem;
 | 
						|
            if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {
 | 
						|
              if (0 != (OneOfOpt->Flags & EFI_IFR_FLAG_MANUFACTURING)) {
 | 
						|
                //
 | 
						|
                // In the worst case, the first will be the default.
 | 
						|
                //
 | 
						|
                CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);
 | 
						|
                break;
 | 
						|
              }
 | 
						|
            } else {
 | 
						|
              if (OneOfOpt->Flags & EFI_IFR_FLAG_DEFAULT) {
 | 
						|
                //
 | 
						|
                // In the worst case, the first will be the default.
 | 
						|
                //
 | 
						|
                CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth);
 | 
						|
                break;
 | 
						|
              }
 | 
						|
            }
 | 
						|
 | 
						|
          IfrItem = (EFI_IFR_OP_HEADER *)((UINT8*)IfrItem + IfrItem->Length);
 | 
						|
        }
 | 
						|
        continue;
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_IFR_CHECKBOX_OP:
 | 
						|
        ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);
 | 
						|
        CheckBox = (EFI_IFR_CHECK_BOX *)IfrItem;
 | 
						|
        if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) {
 | 
						|
          if (0 != (CheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING)) {
 | 
						|
            *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          if (CheckBox->Flags & EFI_IFR_FLAG_DEFAULT) {
 | 
						|
            *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_IFR_NUMERIC_OP:
 | 
						|
        ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size);
 | 
						|
        Numeric = (EFI_IFR_NUMERIC *) IfrItem;
 | 
						|
        CopyMem (Map + IfrNvData->QuestionId, &Numeric->Default, IfrNvData->StorageWidth);
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_IFR_ORDERED_LIST_OP:
 | 
						|
      case EFI_IFR_PASSWORD_OP:
 | 
						|
      case EFI_IFR_STRING_OP:
 | 
						|
        //
 | 
						|
        // No support for default value for these opcodes.
 | 
						|
        //
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (Name16);
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HiiGetDefaultImage (
 | 
						|
  IN     EFI_HII_PROTOCOL            *This,
 | 
						|
  IN     EFI_HII_HANDLE              Handle,
 | 
						|
  IN     UINTN                       DefaultMask,
 | 
						|
  OUT    EFI_HII_VARIABLE_PACK_LIST  **VariablePackList
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
  Routine Description:
 | 
						|
 | 
						|
  This function allows a program to extract the NV Image
 | 
						|
  that represents the default storage image
 | 
						|
 | 
						|
  Arguments:
 | 
						|
    This             - A pointer to the EFI_HII_PROTOCOL instance.
 | 
						|
    Handle           - The HII handle from which will have default data retrieved.
 | 
						|
    UINTN            - Mask used to retrieve the default image.
 | 
						|
    VariablePackList - Callee allocated, tightly-packed, link list data
 | 
						|
                         structure that contain all default varaible packs
 | 
						|
                         from the Hii Database.
 | 
						|
 | 
						|
  Returns:
 | 
						|
    EFI_NOT_FOUND         - If Hii database does not contain any default images.
 | 
						|
    EFI_INVALID_PARAMETER - Invalid input parameter.
 | 
						|
    EFI_SUCCESS           - Operation successful.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_HANDLE_DATABASE        *HandleDatabase;
 | 
						|
  EFI_HII_PACKAGE_INSTANCE       *PackageInstance;
 | 
						|
  EFI_IFR_OP_HEADER              *FormSet;
 | 
						|
  EFI_IFR_OP_HEADER              *IfrItem;
 | 
						|
  EFI_IFR_VARSTORE               *VarStore;
 | 
						|
  EFI_IFR_VARSTORE               *VarStoreDefault;
 | 
						|
  UINTN                          SetupMapNameSize;
 | 
						|
  UINTN                          SizeOfMaps;
 | 
						|
  EFI_HII_VARIABLE_PACK_LIST     *PackList;
 | 
						|
  EFI_HII_VARIABLE_PACK_LIST     *PackListNext;
 | 
						|
  EFI_HII_VARIABLE_PACK_LIST     *PackListLast;
 | 
						|
  UINT8                          *Map;
 | 
						|
 | 
						|
 | 
						|
  //
 | 
						|
  // Find the IFR pack from the handle. Then get the formset from the pack.
 | 
						|
  //
 | 
						|
  PackageInstance = NULL;
 | 
						|
  HandleDatabase  = (EFI_HII_DATA_FROM_THIS (This))->DatabaseHead;
 | 
						|
  for ( ; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
 | 
						|
    if (Handle == HandleDatabase->Handle) {
 | 
						|
      PackageInstance = HandleDatabase->Buffer;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (PackageInstance == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  FormSet = (EFI_IFR_OP_HEADER *) ((UINT8 *) &PackageInstance->IfrData + sizeof (EFI_HII_IFR_PACK));
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the sizes of all the VARSTOREs in this VFR.
 | 
						|
  // Then allocate enough space for all of them plus all maps
 | 
						|
  //
 | 
						|
  SizeOfMaps = 0;
 | 
						|
  IfrItem    = FormSet;
 | 
						|
  while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {
 | 
						|
 | 
						|
    if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {
 | 
						|
      VarStore = (EFI_IFR_VARSTORE *) IfrItem;
 | 
						|
      //
 | 
						|
      // Size of the map
 | 
						|
      //
 | 
						|
      SizeOfMaps += VarStore->Size;
 | 
						|
      //
 | 
						|
      // add the size of the string, in Unicode
 | 
						|
      //
 | 
						|
      SizeOfMaps += (VarStore->Header.Length - sizeof (*VarStore)) * 2;
 | 
						|
      //
 | 
						|
      // Space for node
 | 
						|
      //
 | 
						|
      SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
      //
 | 
						|
      // Space for linked list node
 | 
						|
      //
 | 
						|
      SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST);
 | 
						|
    }
 | 
						|
 | 
						|
    IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If the FormSet OpCode has a non-zero NvDataSize. There is a default
 | 
						|
  // NvMap with ID=0, GUID that of the formset itself and "Setup" as name.
 | 
						|
  //
 | 
						|
  SetupMapNameSize = StrLen (SETUP_MAP_NAME) + 1;
 | 
						|
  VarStoreDefault  = AllocateZeroPool (sizeof (*VarStoreDefault) + SetupMapNameSize);
 | 
						|
 | 
						|
  if (0 != ((EFI_IFR_FORM_SET*)FormSet)->NvDataSize) {
 | 
						|
 | 
						|
    VarStoreDefault->Header.OpCode = EFI_IFR_VARSTORE_OP;
 | 
						|
    VarStoreDefault->Header.Length = (UINT8) (sizeof (*VarStoreDefault) + SetupMapNameSize);
 | 
						|
    Unicode2Ascii ((CHAR8 *) (VarStoreDefault + 1), SETUP_MAP_NAME);
 | 
						|
    CopyMem (&VarStoreDefault->Guid, &((EFI_IFR_FORM_SET*) FormSet)->Guid, sizeof (EFI_GUID));
 | 
						|
    VarStoreDefault->VarId = 0;
 | 
						|
    VarStoreDefault->Size = ((EFI_IFR_FORM_SET*) FormSet)->NvDataSize;
 | 
						|
 | 
						|
    //
 | 
						|
    // Size of the map
 | 
						|
    //
 | 
						|
    SizeOfMaps += VarStoreDefault->Size;
 | 
						|
    //
 | 
						|
    // add the size of the string
 | 
						|
    //
 | 
						|
    SizeOfMaps += sizeof (SETUP_MAP_NAME);
 | 
						|
    //
 | 
						|
    // Space for node
 | 
						|
    //
 | 
						|
    SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK);
 | 
						|
    //
 | 
						|
    // Space for linked list node
 | 
						|
    //
 | 
						|
    SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST);
 | 
						|
  }
 | 
						|
 | 
						|
  if (0 == SizeOfMaps) {
 | 
						|
    //
 | 
						|
    // The IFR does not have any explicit or default map(s).
 | 
						|
    //
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate the return buffer
 | 
						|
  //
 | 
						|
  PackList = AllocateZeroPool (SizeOfMaps);
 | 
						|
  ASSERT (NULL != PackList);
 | 
						|
 | 
						|
  PackListNext = PackList;
 | 
						|
  PackListLast = PackList;
 | 
						|
 | 
						|
  //
 | 
						|
  // Handle the default map first, if any.
 | 
						|
  //
 | 
						|
  if (0 != VarStoreDefault->Size) {
 | 
						|
 | 
						|
    Map = HiiGetDefaultImageInitPack (PackListNext, VarStoreDefault);
 | 
						|
 | 
						|
    HiiGetDefaultImagePopulateMap (Map, FormSet, VarStoreDefault, DefaultMask);
 | 
						|
 | 
						|
    PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);
 | 
						|
    PackListLast = PackListNext;
 | 
						|
    PackListNext = PackListNext->NextVariablePack;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  //
 | 
						|
  // Handle the explicit varstore(s)
 | 
						|
  //
 | 
						|
  IfrItem = FormSet;
 | 
						|
  while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) {
 | 
						|
 | 
						|
    if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) {
 | 
						|
 | 
						|
      Map = HiiGetDefaultImageInitPack (PackListNext, (EFI_IFR_VARSTORE *) IfrItem);
 | 
						|
 | 
						|
      HiiGetDefaultImagePopulateMap (Map, FormSet, (EFI_IFR_VARSTORE *) IfrItem, DefaultMask);
 | 
						|
 | 
						|
      PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length);
 | 
						|
      PackListLast = PackListNext;
 | 
						|
      PackListNext = PackListNext->NextVariablePack;
 | 
						|
    }
 | 
						|
 | 
						|
    IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length);
 | 
						|
  }
 | 
						|
 | 
						|
  PackListLast->NextVariablePack = NULL;
 | 
						|
  *VariablePackList = PackList;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HiiUpdateForm (
 | 
						|
  IN EFI_HII_PROTOCOL       *This,
 | 
						|
  IN EFI_HII_HANDLE         Handle,
 | 
						|
  IN EFI_FORM_LABEL         Label,
 | 
						|
  IN BOOLEAN                AddData,
 | 
						|
  IN EFI_HII_UPDATE_DATA    *Data
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  This function allows the caller to update a form that has
 | 
						|
  previously been registered with the EFI HII database.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Handle     - Hii Handle associated with the Formset to modify
 | 
						|
  Label      - Update information starting immediately after this label in the IFR
 | 
						|
  AddData    - If TRUE, add data.  If FALSE, remove data
 | 
						|
  Data       - If adding data, this is the pointer to the data to add
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS - Update success.
 | 
						|
  Other       - Update fail.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_PACKAGE_INSTANCE  *PackageInstance;
 | 
						|
  EFI_HII_DATA              *HiiData;
 | 
						|
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
 | 
						|
  EFI_HII_IFR_PACK          *FormPack;
 | 
						|
  EFI_IFR_OP_HEADER         *Location;
 | 
						|
  EFI_IFR_OP_HEADER         *DataLocation;
 | 
						|
  UINT8                     *OtherBuffer;
 | 
						|
  UINT8                     *TempBuffer;
 | 
						|
  UINT8                     *OrigTempBuffer;
 | 
						|
  UINTN                     TempBufferSize;
 | 
						|
  UINTN                     Index;
 | 
						|
 | 
						|
  OtherBuffer = NULL;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  HiiData         = EFI_HII_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  HandleDatabase  = HiiData->DatabaseHead;
 | 
						|
 | 
						|
  PackageInstance = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check numeric value against the head of the database
 | 
						|
  //
 | 
						|
  for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
 | 
						|
    //
 | 
						|
    // Match the numeric value with the database entry - if matched, extract PackageInstance
 | 
						|
    //
 | 
						|
    if (Handle == HandleDatabase->Handle) {
 | 
						|
      PackageInstance = HandleDatabase->Buffer;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // No handle was found - error condition
 | 
						|
  //
 | 
						|
  if (PackageInstance == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Calculate and allocate space for retrieval of IFR data
 | 
						|
  //
 | 
						|
  DataLocation    = (EFI_IFR_OP_HEADER *) &Data->Data;
 | 
						|
  TempBufferSize  = (CHAR8 *) (&PackageInstance->IfrData) - (CHAR8 *) (PackageInstance);
 | 
						|
 | 
						|
  for (Index = 0; Index < Data->DataCount; Index++) {
 | 
						|
    TempBufferSize += DataLocation->Length;
 | 
						|
    DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);
 | 
						|
  }
 | 
						|
 | 
						|
  TempBufferSize += PackageInstance->IfrSize + PackageInstance->StringSize;
 | 
						|
 | 
						|
  TempBuffer      = AllocateZeroPool (TempBufferSize);
 | 
						|
  ASSERT (TempBuffer != NULL);
 | 
						|
 | 
						|
  OrigTempBuffer  = TempBuffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // We update only packages with IFR information in it
 | 
						|
  //
 | 
						|
  if (PackageInstance->IfrSize == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    TempBuffer,
 | 
						|
    PackageInstance,
 | 
						|
    ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance))
 | 
						|
    );
 | 
						|
 | 
						|
  TempBuffer = TempBuffer + ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance));
 | 
						|
 | 
						|
  //
 | 
						|
  // Based on if there is IFR data in this package instance, determine
 | 
						|
  // what the location is of the beginning of the string data.
 | 
						|
  //
 | 
						|
  FormPack  = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
  Location  = (EFI_IFR_OP_HEADER *) FormPack;
 | 
						|
 | 
						|
  //
 | 
						|
  // Look for the FormId requested
 | 
						|
  //
 | 
						|
  for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
    switch (Location->OpCode) {
 | 
						|
    case EFI_IFR_FORM_SET_OP:
 | 
						|
      //
 | 
						|
      // If the FormSet has an update pending, pay attention.
 | 
						|
      //
 | 
						|
      if (Data->FormSetUpdate) {
 | 
						|
        ((EFI_IFR_FORM_SET *) Location)->CallbackHandle = Data->FormCallbackHandle;
 | 
						|
      }
 | 
						|
 | 
						|
      CopyMem (TempBuffer, Location, Location->Length);
 | 
						|
      TempBuffer = TempBuffer + Location->Length;
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_IFR_FORM_OP:
 | 
						|
      //
 | 
						|
      // If the Form has an update pending, pay attention.
 | 
						|
      //
 | 
						|
      if (Data->FormUpdate) {
 | 
						|
        ((EFI_IFR_FORM *) Location)->FormTitle = Data->FormTitle;
 | 
						|
      }
 | 
						|
 | 
						|
      CopyMem (TempBuffer, Location, Location->Length);
 | 
						|
      TempBuffer = TempBuffer + Location->Length;
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_IFR_LABEL_OP:
 | 
						|
      //
 | 
						|
      // If the label does not match the requested update point, ignore it
 | 
						|
      //
 | 
						|
      if (((EFI_IFR_LABEL *) Location)->LabelId != Label) {
 | 
						|
        //
 | 
						|
        // Copy the label
 | 
						|
        //
 | 
						|
        CopyMem (TempBuffer, Location, Location->Length);
 | 
						|
        TempBuffer = TempBuffer + Location->Length;
 | 
						|
 | 
						|
        //
 | 
						|
        // Go to the next Op-Code
 | 
						|
        //
 | 
						|
        Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      if (AddData) {
 | 
						|
        //
 | 
						|
        // Copy the label
 | 
						|
        //
 | 
						|
        CopyMem (TempBuffer, Location, Location->Length);
 | 
						|
        TempBuffer = TempBuffer + Location->Length;
 | 
						|
 | 
						|
        //
 | 
						|
        // Add the DataCount amount of opcodes to TempBuffer
 | 
						|
        //
 | 
						|
        DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data;
 | 
						|
        for (Index = 0; Index < Data->DataCount; Index++) {
 | 
						|
          CopyMem (TempBuffer, DataLocation, DataLocation->Length);
 | 
						|
          ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize += DataLocation->Length;
 | 
						|
          OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));
 | 
						|
          CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);
 | 
						|
          TempBuffer    = TempBuffer + DataLocation->Length;
 | 
						|
          DataLocation  = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length);
 | 
						|
        }
 | 
						|
        //
 | 
						|
        // Go to the next Op-Code
 | 
						|
        //
 | 
						|
        Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
        continue;
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Copy the label
 | 
						|
        //
 | 
						|
        CopyMem (TempBuffer, Location, Location->Length);
 | 
						|
        TempBuffer  = TempBuffer + Location->Length;
 | 
						|
        Location    = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
 | 
						|
        //
 | 
						|
        // Remove the DataCount amount of opcodes unless we run into an end of form or a label
 | 
						|
        //
 | 
						|
        for (Index = 0; Index < Data->DataCount; Index++) {
 | 
						|
          //
 | 
						|
          // If we are about to skip an end form - bail out, since that is illegal
 | 
						|
          //
 | 
						|
          if ((Location->OpCode == EFI_IFR_END_FORM_OP) || (Location->OpCode == EFI_IFR_LABEL_OP)) {
 | 
						|
            break;
 | 
						|
          }
 | 
						|
          //
 | 
						|
          // By skipping Location entries, we are in effect not copying what was previously there
 | 
						|
          //
 | 
						|
          ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize -= Location->Length;
 | 
						|
          OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN));
 | 
						|
          CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2);
 | 
						|
          Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
    default:
 | 
						|
      CopyMem (TempBuffer, Location, Location->Length);
 | 
						|
      TempBuffer = TempBuffer + Location->Length;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Go to the next Op-Code
 | 
						|
    //
 | 
						|
    Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Copy the last op-code left behind from the for loop
 | 
						|
  //
 | 
						|
  CopyMem (TempBuffer, Location, Location->Length);
 | 
						|
 | 
						|
  //
 | 
						|
  // Advance to beginning of strings and copy them
 | 
						|
  //
 | 
						|
  TempBuffer  = TempBuffer + Location->Length;
 | 
						|
  Location    = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length);
 | 
						|
  CopyMem (TempBuffer, Location, PackageInstance->StringSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the old buffer, and assign into our database the latest buffer
 | 
						|
  //
 | 
						|
  FreePool (HandleDatabase->Buffer);
 | 
						|
  HandleDatabase->Buffer = OrigTempBuffer;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |