git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2579 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			674 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			674 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2006 - 2007, Intel Corporation                                                         
 | 
						|
All rights reserved. This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  Package.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  This file contains the package processing code to the HII database.
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
 | 
						|
#include "HiiDatabase.h"
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
GetPackSize (
 | 
						|
  IN  VOID                *Pack,
 | 
						|
  OUT UINTN               *PackSize,
 | 
						|
  OUT UINT32              *NumberOfTokens
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Determines the passed in Pack's size and returns the value.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns: 
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_STRING_PACK *StringPack;
 | 
						|
  UINT16              Type;
 | 
						|
  UINT32              Length;
 | 
						|
 | 
						|
  *PackSize = 0;
 | 
						|
 | 
						|
  Type      = EFI_HII_IFR;
 | 
						|
  if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) {
 | 
						|
    //
 | 
						|
    // The header contains the full IFR length
 | 
						|
    //
 | 
						|
    CopyMem (&Length, &((EFI_HII_PACK_HEADER *) Pack)->Length, sizeof (Length));
 | 
						|
    *PackSize = (UINTN) Length;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Type = EFI_HII_STRING;
 | 
						|
  if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) {
 | 
						|
    //
 | 
						|
    // The header contains the STRING package length
 | 
						|
    // The assumption is that the strings for all languages
 | 
						|
    // are a contiguous block of data and there is a series of
 | 
						|
    // these package instances which will terminate with a NULL package
 | 
						|
    // instance.
 | 
						|
    //
 | 
						|
    StringPack = (EFI_HII_STRING_PACK *) Pack;
 | 
						|
 | 
						|
    //
 | 
						|
    // There may be multiple instances packed together of strings
 | 
						|
    // so we must walk the self describing structures until we encounter
 | 
						|
    // the NULL structure to determine the full size.
 | 
						|
    //
 | 
						|
    CopyMem (&Length, &StringPack->Header.Length, sizeof (Length));
 | 
						|
    if (NumberOfTokens != NULL) {
 | 
						|
      CopyMem (NumberOfTokens, &StringPack->NumStringPointers, sizeof (UINT32));
 | 
						|
    }
 | 
						|
 | 
						|
    while (Length != 0) {
 | 
						|
      *PackSize   = *PackSize + Length;
 | 
						|
      StringPack  = (EFI_HII_STRING_PACK *) ((CHAR8 *) StringPack + Length);
 | 
						|
      CopyMem (&Length, &StringPack->Header.Length, sizeof (Length));
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Encountered a length of 0, so let's add the space for the NULL terminator
 | 
						|
    // pack's length and call it done.
 | 
						|
    //
 | 
						|
    *PackSize = *PackSize + sizeof (EFI_HII_STRING_PACK);
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // We only determine the size of the non-global Package types.
 | 
						|
  // If neither IFR or STRING data were found, return an error
 | 
						|
  //
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
ValidatePack (
 | 
						|
  IN   EFI_HII_PROTOCOL          *This,
 | 
						|
  IN   EFI_HII_PACKAGE_INSTANCE  *PackageInstance,
 | 
						|
  OUT  EFI_HII_PACKAGE_INSTANCE  **StringPackageInstance,
 | 
						|
  OUT  UINT32                    *TotalStringCount
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Verifies that the package instance is using the correct handle for string operations.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns: 
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_DATA              *HiiData;
 | 
						|
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
 | 
						|
  EFI_HII_PACKAGE_INSTANCE  *HandlePackageInstance;
 | 
						|
  UINT8                     *RawData;
 | 
						|
  EFI_GUID                  Guid;
 | 
						|
  EFI_HII_IFR_PACK          *FormPack;
 | 
						|
  UINTN                     Index;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  HiiData         = EFI_HII_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  HandleDatabase  = HiiData->DatabaseHead;
 | 
						|
  ZeroMem (&Guid, sizeof (EFI_GUID));
 | 
						|
 | 
						|
  *StringPackageInstance = PackageInstance;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // If there is no IFR data assume the caller knows what they are doing.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  RawData = (UINT8 *) FormPack;
 | 
						|
 | 
						|
  for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
    if (RawData[Index] == EFI_IFR_FORM_SET_OP) {
 | 
						|
      //
 | 
						|
      // Cache the guid for this formset
 | 
						|
      //
 | 
						|
      CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Index = RawData[Index + 1] + Index;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If there is no string package, and the PackageInstance->IfrPack.Guid and PackageInstance->Guid are
 | 
						|
  // different, we should return the correct handle for the caller to use for strings.
 | 
						|
  //
 | 
						|
  if ((PackageInstance->StringSize == 0) && (!CompareGuid (&Guid, &PackageInstance->Guid))) {
 | 
						|
    //
 | 
						|
    // Search the database for a handle that matches the PackageInstance->Guid
 | 
						|
    //
 | 
						|
    for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
 | 
						|
      //
 | 
						|
      // Get Ifrdata and extract the Guid for it
 | 
						|
      //
 | 
						|
      HandlePackageInstance = HandleDatabase->Buffer;
 | 
						|
 | 
						|
      ASSERT (HandlePackageInstance->IfrSize != 0);
 | 
						|
 | 
						|
      FormPack  = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&HandlePackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
      RawData   = (UINT8 *) FormPack;
 | 
						|
 | 
						|
      for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) {
 | 
						|
        if (RawData[Index] == EFI_IFR_FORM_SET_OP) {
 | 
						|
          //
 | 
						|
          // Cache the guid for this formset
 | 
						|
          //
 | 
						|
          CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID));
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        Index = RawData[Index + 1] + Index;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // If the Guid from the new handle matches the original Guid referenced in the original package data
 | 
						|
      // return the appropriate package instance data to use.
 | 
						|
      //
 | 
						|
      if (CompareGuid (&Guid, &PackageInstance->Guid)) {
 | 
						|
        if (TotalStringCount != NULL) {
 | 
						|
          *TotalStringCount = HandleDatabase->NumberOfTokens;
 | 
						|
        }
 | 
						|
 | 
						|
        *StringPackageInstance = HandlePackageInstance;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // end for
 | 
						|
    //
 | 
						|
  } else {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HiiNewPack (
 | 
						|
  IN  EFI_HII_PROTOCOL    *This,
 | 
						|
  IN  EFI_HII_PACKAGES    *Packages,
 | 
						|
  OUT EFI_HII_HANDLE      *Handle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Extracts the various packs from a package list.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  This      - Pointer of HII protocol.
 | 
						|
  Packages  - Pointer of HII packages.
 | 
						|
  Handle    - Handle value to be returned.
 | 
						|
 | 
						|
Returns: 
 | 
						|
 | 
						|
  EFI_SUCCESS           - Pacakges has added to HII database successfully.
 | 
						|
  EFI_INVALID_PARAMETER - Invalid parameter.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_PACKAGE_INSTANCE  *PackageInstance;
 | 
						|
  EFI_HII_DATA              *HiiData;
 | 
						|
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
 | 
						|
  EFI_HII_HANDLE_DATABASE   *Database;
 | 
						|
  EFI_HII_PACK_HEADER       *PackageHeader;
 | 
						|
  EFI_HII_GLOBAL_DATA       *GlobalData;
 | 
						|
  EFI_HII_IFR_PACK          *IfrPack;
 | 
						|
  EFI_HII_STRING_PACK       *StringPack;
 | 
						|
  EFI_HII_FONT_PACK         *FontPack;
 | 
						|
  EFI_HII_KEYBOARD_PACK     *KeyboardPack;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  UINTN                     IfrSize;
 | 
						|
  UINTN                     StringSize;
 | 
						|
  UINTN                     TotalStringSize;
 | 
						|
  UINTN                     InstanceSize;
 | 
						|
  UINTN                     Count;
 | 
						|
  UINTN                     Index;
 | 
						|
  UINT16                    Member;
 | 
						|
  EFI_GUID                  Guid;
 | 
						|
  EFI_FORM_SET_STUB         FormSetStub;
 | 
						|
  UINT8                     *Location;
 | 
						|
  UINT16                    Unicode;
 | 
						|
  UINT16                    NumWideGlyphs;
 | 
						|
  UINT16                    NumNarrowGlyphs;
 | 
						|
  UINT32                    NumberOfTokens;
 | 
						|
  UINT32                    TotalTokenNumber;
 | 
						|
  UINT8                     *Local;
 | 
						|
  EFI_NARROW_GLYPH          *NarrowGlyph;
 | 
						|
 | 
						|
  if (Packages->NumberOfPackages == 0 || This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  HiiData           = EFI_HII_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  GlobalData        = HiiData->GlobalData;
 | 
						|
 | 
						|
  Database          = HiiData->DatabaseHead;
 | 
						|
 | 
						|
  PackageInstance   = NULL;
 | 
						|
  IfrPack           = NULL;
 | 
						|
  StringPack        = NULL;
 | 
						|
  InstanceSize      = 0;
 | 
						|
  IfrSize           = 0;
 | 
						|
  StringSize        = 0;
 | 
						|
  TotalStringSize   = 0;
 | 
						|
  NumberOfTokens    = 0;
 | 
						|
  TotalTokenNumber  = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Search through the passed in Packages for the IfrPack and any StringPack.
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
 | 
						|
 | 
						|
    PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *));
 | 
						|
 | 
						|
    switch (PackageHeader->Type) {
 | 
						|
    case EFI_HII_IFR:
 | 
						|
      //
 | 
						|
      // There shoule be only one Ifr package.
 | 
						|
      //
 | 
						|
      ASSERT (IfrPack == NULL);
 | 
						|
      IfrPack = (EFI_HII_IFR_PACK *) PackageHeader;
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_HII_STRING:
 | 
						|
      StringPack = (EFI_HII_STRING_PACK *) PackageHeader;
 | 
						|
      //
 | 
						|
      // Sending me a String Package. Get its size.
 | 
						|
      //
 | 
						|
      Status = GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens);
 | 
						|
      ASSERT (!EFI_ERROR (Status));
 | 
						|
 | 
						|
      //
 | 
						|
      // The size which GetPackSize() returns include the null terminator. So if multiple
 | 
						|
      // string packages are passed in, merge all these packages, and only pad one null terminator.
 | 
						|
      //
 | 
						|
      if (TotalStringSize > 0) {
 | 
						|
        TotalStringSize -= sizeof (EFI_HII_STRING_PACK);
 | 
						|
      }
 | 
						|
 | 
						|
      TotalStringSize += StringSize;
 | 
						|
      TotalTokenNumber += NumberOfTokens;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If sending a StringPack without an IfrPack, you must include a GuidId
 | 
						|
  //
 | 
						|
  if ((StringPack != NULL) && (IfrPack == NULL)) {
 | 
						|
    if (Packages->GuidId == NULL) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If passing in an IfrPack and a GuidId is provided, ensure they are the same value.
 | 
						|
  //
 | 
						|
  if ((IfrPack != NULL) && (Packages->GuidId != NULL)) {
 | 
						|
    Location  = ((UINT8 *) IfrPack);
 | 
						|
    Location  = (UINT8 *) (((UINTN) Location) + sizeof (EFI_HII_PACK_HEADER));
 | 
						|
 | 
						|
    //
 | 
						|
    // Advance to the Form Set Op-code
 | 
						|
    //
 | 
						|
    for (Count = 0; ((EFI_IFR_OP_HEADER *) &Location[Count])->OpCode != EFI_IFR_FORM_SET_OP;) {
 | 
						|
      Count = Count + ((EFI_IFR_OP_HEADER *) &Location[Count])->Length;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Copy to local variable
 | 
						|
    //
 | 
						|
    CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &Location[Count])->Guid, sizeof (EFI_GUID));
 | 
						|
 | 
						|
    //
 | 
						|
    // Check to see if IfrPack->Guid != GuidId
 | 
						|
    //
 | 
						|
    if (!CompareGuid (&Guid, Packages->GuidId)) {
 | 
						|
      //
 | 
						|
      // If a string package is present, the GUIDs should have agreed.  Return an error
 | 
						|
      //
 | 
						|
      if (StringPack != NULL) {
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If someone is passing in a string only, create a dummy IfrPack with a Guid
 | 
						|
  // to enable future searching of this data.
 | 
						|
  //
 | 
						|
  if ((IfrPack == NULL) && (StringPack != NULL)) {
 | 
						|
    ZeroMem (&FormSetStub, sizeof (FormSetStub));
 | 
						|
 | 
						|
    FormSetStub.Header.Type           = EFI_HII_IFR;
 | 
						|
    FormSetStub.Header.Length         = sizeof (EFI_FORM_SET_STUB);
 | 
						|
 | 
						|
    FormSetStub.FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP;
 | 
						|
    FormSetStub.FormSet.Header.Length = (UINT8) sizeof (EFI_IFR_FORM_SET);
 | 
						|
    //
 | 
						|
    // Dummy string
 | 
						|
    //
 | 
						|
    FormSetStub.FormSet.FormSetTitle  = 0x02;
 | 
						|
    CopyMem (&FormSetStub.FormSet.Guid, Packages->GuidId, sizeof (EFI_GUID));
 | 
						|
 | 
						|
    FormSetStub.EndFormSet.Header.OpCode  = EFI_IFR_END_FORM_SET_OP;
 | 
						|
    FormSetStub.EndFormSet.Header.Length  = (UINT8) sizeof (EFI_IFR_END_FORM_SET);
 | 
						|
    IfrPack = (EFI_HII_IFR_PACK *) &FormSetStub;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IfrPack != NULL) {
 | 
						|
    //
 | 
						|
    // Sending me an IFR Package. Get its size.
 | 
						|
    //
 | 
						|
    Status = GetPackSize ((VOID *) IfrPack, &IfrSize, NULL);
 | 
						|
    ASSERT (!EFI_ERROR (Status));
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Prepare the internal package instace buffer to store package data.
 | 
						|
  //
 | 
						|
  InstanceSize = IfrSize + TotalStringSize;
 | 
						|
 | 
						|
  if (InstanceSize != 0) {
 | 
						|
    PackageInstance = AllocateZeroPool (InstanceSize + sizeof (EFI_HII_PACKAGE_INSTANCE));
 | 
						|
 | 
						|
    ASSERT (PackageInstance);
 | 
						|
 | 
						|
    //
 | 
						|
    // If there is no DatabaseHead allocated - allocate one
 | 
						|
    //
 | 
						|
    if (HiiData->DatabaseHead == NULL) {
 | 
						|
      HiiData->DatabaseHead = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE));
 | 
						|
      ASSERT (HiiData->DatabaseHead);
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If the head is being used (Handle is non-zero), allocate next Database and
 | 
						|
    // add it to the linked-list
 | 
						|
    //
 | 
						|
    if (HiiData->DatabaseHead->Handle != 0) {
 | 
						|
      HandleDatabase = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE));
 | 
						|
 | 
						|
      ASSERT (HandleDatabase);
 | 
						|
 | 
						|
      for (; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase)
 | 
						|
        ;
 | 
						|
 | 
						|
      //
 | 
						|
      // We are sitting on the Database entry which contains the null Next pointer.  Fix it.
 | 
						|
      //
 | 
						|
      Database->NextHandleDatabase = HandleDatabase;
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    Database = HiiData->DatabaseHead;
 | 
						|
 | 
						|
    //
 | 
						|
    // Initialize this instance data
 | 
						|
    //
 | 
						|
    for (*Handle = 1; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) {
 | 
						|
      //
 | 
						|
      // Since the first Database instance will have a passed back handle of 1, we will continue
 | 
						|
      // down the linked list of entries until we encounter the end of the linked list.  Each time
 | 
						|
      // we go down one level deeper, increment the handle value that will be passed back.
 | 
						|
      //
 | 
						|
      if (Database->Handle >= *Handle) {
 | 
						|
        *Handle = (EFI_HII_HANDLE) (Database->Handle + 1);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    PackageInstance->Handle     = *Handle;
 | 
						|
    PackageInstance->IfrSize    = IfrSize;
 | 
						|
    PackageInstance->StringSize = TotalStringSize;
 | 
						|
    if (Packages->GuidId != NULL) {
 | 
						|
      CopyMem (&PackageInstance->Guid, Packages->GuidId, sizeof (EFI_GUID));
 | 
						|
    }
 | 
						|
 | 
						|
    Database->Buffer              = PackageInstance;
 | 
						|
    Database->Handle              = PackageInstance->Handle;
 | 
						|
    Database->NumberOfTokens      = TotalTokenNumber;
 | 
						|
    Database->NextHandleDatabase  = NULL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Copy the Ifr package data into package instance.
 | 
						|
  //
 | 
						|
  if (IfrSize > 0) {
 | 
						|
    CopyMem (&PackageInstance->IfrData, IfrPack, IfrSize);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Main loop to store package data into HII database.
 | 
						|
  //
 | 
						|
  StringSize      = 0;
 | 
						|
  TotalStringSize = 0;
 | 
						|
 | 
						|
  for (Index = 0; Index < Packages->NumberOfPackages; Index++) {
 | 
						|
 | 
						|
    PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *));
 | 
						|
 | 
						|
    switch (PackageHeader->Type) {
 | 
						|
    case EFI_HII_STRING:
 | 
						|
      StringPack = (EFI_HII_STRING_PACK *) PackageHeader;
 | 
						|
      //
 | 
						|
      // The size which GetPackSize() returns include the null terminator. So if multiple
 | 
						|
      // string packages are passed in, merge all these packages, and only pad one null terminator.
 | 
						|
      //
 | 
						|
      if (TotalStringSize > 0) {
 | 
						|
        TotalStringSize -= sizeof (EFI_HII_STRING_PACK);
 | 
						|
      }
 | 
						|
 | 
						|
      GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens);
 | 
						|
      CopyMem ((CHAR8 *) (&PackageInstance->IfrData) + IfrSize + TotalStringSize, StringPack, StringSize);
 | 
						|
 | 
						|
      TotalStringSize += StringSize;
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_HII_HANDLES:
 | 
						|
      CopyMem (&PackageInstance->HandlePack, PackageHeader, sizeof (EFI_HII_HANDLE_PACK));
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_HII_FONT:
 | 
						|
      FontPack = (EFI_HII_FONT_PACK *) PackageHeader;
 | 
						|
      //
 | 
						|
      // Add whatever narrow glyphs were passed to us if undefined
 | 
						|
      //
 | 
						|
      CopyMem (&NumNarrowGlyphs, &FontPack->NumberOfNarrowGlyphs, sizeof (UINT16));
 | 
						|
      for (Count = 0; Count <= NumNarrowGlyphs; Count++) {
 | 
						|
        Local       = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + (sizeof (EFI_NARROW_GLYPH)) * Count;
 | 
						|
        NarrowGlyph = (EFI_NARROW_GLYPH *) Local;
 | 
						|
        CopyMem (&Member, &NarrowGlyph->UnicodeWeight, sizeof (UINT16));
 | 
						|
        //
 | 
						|
        // If the glyph is already defined, do not overwrite it.  It is what it is.
 | 
						|
        //
 | 
						|
        CopyMem (&Unicode, &GlobalData->NarrowGlyphs[Member].UnicodeWeight, sizeof (UINT16));
 | 
						|
        if (Unicode == 0) {
 | 
						|
          CopyMem (&GlobalData->NarrowGlyphs[Member], Local, sizeof (EFI_NARROW_GLYPH));
 | 
						|
        }
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Add whatever wide glyphs were passed to us if undefined
 | 
						|
      //
 | 
						|
      CopyMem (&NumWideGlyphs, &FontPack->NumberOfWideGlyphs, sizeof (UINT16));
 | 
						|
      for (Count = 0; Count <= NumWideGlyphs; Count++) {
 | 
						|
        Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) +
 | 
						|
          (sizeof (EFI_NARROW_GLYPH)) *
 | 
						|
          NumNarrowGlyphs;
 | 
						|
        CopyMem (
 | 
						|
          &Member,
 | 
						|
          (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count),
 | 
						|
          sizeof (UINT16)
 | 
						|
          );
 | 
						|
        //
 | 
						|
        // If the glyph is already defined, do not overwrite it.  It is what it is.
 | 
						|
        //
 | 
						|
        CopyMem (&Unicode, &GlobalData->WideGlyphs[Member].UnicodeWeight, sizeof (UINT16));
 | 
						|
        if (Unicode == 0) {
 | 
						|
          Local = (UINT8*)(&FontPack->NumberOfWideGlyphs + sizeof(UINT8)) + (sizeof(EFI_NARROW_GLYPH)) * NumNarrowGlyphs;
 | 
						|
          CopyMem (
 | 
						|
            &GlobalData->WideGlyphs[Member],
 | 
						|
            (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count),
 | 
						|
            sizeof (EFI_WIDE_GLYPH)
 | 
						|
            );
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    case EFI_HII_KEYBOARD:
 | 
						|
      KeyboardPack = (EFI_HII_KEYBOARD_PACK *) PackageHeader;
 | 
						|
      //
 | 
						|
      // Sending me a Keyboard Package
 | 
						|
      //
 | 
						|
      if (KeyboardPack->DescriptorCount > 105) {
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // If someone updates the Descriptors with a count of 0, blow aware the overrides.
 | 
						|
      //
 | 
						|
      if (KeyboardPack->DescriptorCount == 0) {
 | 
						|
        ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
 | 
						|
      }
 | 
						|
 | 
						|
      if (KeyboardPack->DescriptorCount < 106 && KeyboardPack->DescriptorCount > 0) {
 | 
						|
        //
 | 
						|
        // If SystemKeyboard was updated already, then steer changes to the override database
 | 
						|
        //
 | 
						|
        if (GlobalData->SystemKeyboardUpdate) {
 | 
						|
          ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
 | 
						|
          for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) {
 | 
						|
            CopyMem (&Member, &KeyboardPack->Descriptor[Count].Key, sizeof (UINT16));
 | 
						|
            CopyMem (
 | 
						|
              &GlobalData->OverrideKeyboardLayout[Member],
 | 
						|
              &KeyboardPack->Descriptor[Count],
 | 
						|
              sizeof (EFI_KEY_DESCRIPTOR)
 | 
						|
              );
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database.
 | 
						|
          //
 | 
						|
          ZeroMem (GlobalData->SystemKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106);
 | 
						|
          for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) {
 | 
						|
            CopyMem (&Member, &KeyboardPack->Descriptor->Key, sizeof (UINT16));
 | 
						|
            CopyMem (
 | 
						|
              &GlobalData->SystemKeyboardLayout[Member],
 | 
						|
              &KeyboardPack->Descriptor[Count],
 | 
						|
              sizeof (EFI_KEY_DESCRIPTOR)
 | 
						|
              );
 | 
						|
          }
 | 
						|
          //
 | 
						|
          // Just updated the system keyboard database, reflect that in the global flag.
 | 
						|
          //
 | 
						|
          GlobalData->SystemKeyboardUpdate = TRUE;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
HiiRemovePack (
 | 
						|
  IN EFI_HII_PROTOCOL    *This,
 | 
						|
  IN EFI_HII_HANDLE      Handle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Removes the various packs from a Handle
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns: 
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_HII_PACKAGE_INSTANCE  *PackageInstance;
 | 
						|
  EFI_HII_DATA              *HiiData;
 | 
						|
  EFI_HII_HANDLE_DATABASE   *HandleDatabase;
 | 
						|
  EFI_HII_HANDLE_DATABASE   *PreviousHandleDatabase;
 | 
						|
 | 
						|
  if (This == NULL || Handle == 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  HiiData         = EFI_HII_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  HandleDatabase  = HiiData->DatabaseHead;
 | 
						|
  PackageInstance = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize the Previous with the Head of the Database
 | 
						|
  //
 | 
						|
  PreviousHandleDatabase = HandleDatabase;
 | 
						|
 | 
						|
  for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) {
 | 
						|
    //
 | 
						|
    // Match the numeric value with the database entry - if matched,
 | 
						|
    // free the package instance and apply fix-up to database linked list
 | 
						|
    //
 | 
						|
    if (Handle == HandleDatabase->Handle) {
 | 
						|
      PackageInstance = HandleDatabase->Buffer;
 | 
						|
 | 
						|
      //
 | 
						|
      // Free the Package Instance
 | 
						|
      //
 | 
						|
      FreePool (PackageInstance);
 | 
						|
 | 
						|
      //
 | 
						|
      // If this was the only Handle in the database
 | 
						|
      //
 | 
						|
      if (HiiData->DatabaseHead == HandleDatabase) {
 | 
						|
        HiiData->DatabaseHead = NULL;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // Make the parent->Next point to the current->Next
 | 
						|
      //
 | 
						|
      PreviousHandleDatabase->NextHandleDatabase = HandleDatabase->NextHandleDatabase;
 | 
						|
      FreePool (HandleDatabase);
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is
 | 
						|
    //
 | 
						|
    PreviousHandleDatabase = HandleDatabase;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // No handle was found - error condition
 | 
						|
  //
 | 
						|
  if (PackageInstance == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |