+/*++\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ HiiDatabase.c\r
+\r
+Abstract:\r
+\r
+ This file contains the entry code to the HII database.\r
+\r
+--*/\r
+\r
+//\r
+// Include common header file for this module.\r
+//\r
+#include "CommonHeader.h"\r
+\r
+#include "HiiDatabase.h"\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeHiiDatabase (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initialize HII Database\r
+ \r
+Arguments:\r
+ (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
+\r
+Returns: \r
+ EFI_SUCCESS - Setup loaded.\r
+ other - Setup Error\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_DATA *HiiData;\r
+ EFI_HII_GLOBAL_DATA *GlobalData;\r
+ EFI_HANDLE *HandleBuffer;\r
+ EFI_HANDLE Handle;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+\r
+ //\r
+ // There will be only one HII Database in the system\r
+ // If there is another out there, someone is trying to install us\r
+ // again. Fail that scenario.\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiHiiProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+\r
+ //\r
+ // If there was no error, assume there is an installation and fail to load\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ HiiData = AllocatePool (sizeof (EFI_HII_DATA));\r
+\r
+ ASSERT (HiiData);\r
+\r
+ GlobalData = AllocateZeroPool (sizeof (EFI_HII_GLOBAL_DATA));\r
+\r
+ ASSERT (GlobalData);\r
+\r
+ //\r
+ // Seed the Font Database with a known non-character glyph\r
+ //\r
+ for (Index = 0; Index <= MAX_GLYPH_COUNT; Index++) {\r
+ //\r
+ // Seeding the UnicodeWeight with 0 signifies that it is uninitialized\r
+ //\r
+ GlobalData->NarrowGlyphs[Index].UnicodeWeight = 0;\r
+ GlobalData->WideGlyphs[Index].UnicodeWeight = 0;\r
+ GlobalData->NarrowGlyphs[Index].Attributes = 0;\r
+ GlobalData->WideGlyphs[Index].Attributes = 0;\r
+ CopyMem (GlobalData->NarrowGlyphs[Index].GlyphCol1, &mUnknownGlyph, NARROW_GLYPH_ARRAY_SIZE);\r
+ CopyMem (GlobalData->WideGlyphs[Index].GlyphCol1, &mUnknownGlyph, WIDE_GLYPH_ARRAY_SIZE);\r
+ }\r
+ //\r
+ // Fill in HII data\r
+ //\r
+ HiiData->Signature = EFI_HII_DATA_SIGNATURE;\r
+ HiiData->GlobalData = GlobalData;\r
+ HiiData->GlobalData->SystemKeyboardUpdate = FALSE;\r
+ HiiData->DatabaseHead = NULL;\r
+ HiiData->Hii.NewPack = HiiNewPack;\r
+ HiiData->Hii.RemovePack = HiiRemovePack;\r
+ HiiData->Hii.FindHandles = HiiFindHandles;\r
+ HiiData->Hii.ExportDatabase = HiiExportDatabase;\r
+ HiiData->Hii.GetGlyph = HiiGetGlyph;\r
+ HiiData->Hii.GetPrimaryLanguages = HiiGetPrimaryLanguages;\r
+ HiiData->Hii.GetSecondaryLanguages = HiiGetSecondaryLanguages;\r
+ HiiData->Hii.NewString = HiiNewString;\r
+ HiiData->Hii.GetString = HiiGetString;\r
+ HiiData->Hii.ResetStrings = HiiResetStrings;\r
+ HiiData->Hii.TestString = HiiTestString;\r
+ HiiData->Hii.GetLine = HiiGetLine;\r
+ HiiData->Hii.GetForms = HiiGetForms;\r
+ HiiData->Hii.GetDefaultImage = HiiGetDefaultImage;\r
+ HiiData->Hii.UpdateForm = HiiUpdateForm;\r
+ HiiData->Hii.GetKeyboardLayout = HiiGetKeyboardLayout;\r
+ HiiData->Hii.GlyphToBlt = HiiGlyphToBlt;\r
+\r
+ //\r
+ // Install protocol interface\r
+ //\r
+ Handle = NULL;\r
+ Status = gBS->InstallProtocolInterface (\r
+ &Handle,\r
+ &gEfiHiiProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &HiiData->Hii\r
+ );\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+HiiFindHandles (\r
+ IN EFI_HII_PROTOCOL *This,\r
+ IN OUT UINT16 *HandleBufferLength,\r
+ OUT EFI_HII_HANDLE Handle[1]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Determines the handles that are currently active in the database.\r
+ \r
+Arguments:\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+ EFI_HII_HANDLE_DATABASE *Database;\r
+ EFI_HII_DATA *HiiData;\r
+ UINTN HandleCount;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HiiData = EFI_HII_DATA_FROM_THIS (This);\r
+\r
+ Database = HiiData->DatabaseHead;\r
+\r
+ if (Database == NULL) {\r
+ *HandleBufferLength = 0;\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ for (HandleCount = 0; Database != NULL; HandleCount++) {\r
+ Database = Database->NextHandleDatabase;\r
+ }\r
+ //\r
+ // Is there a sufficient buffer for the data being passed back?\r
+ //\r
+ if (*HandleBufferLength >= (sizeof (EFI_HII_HANDLE) * HandleCount)) {\r
+ Database = HiiData->DatabaseHead;\r
+\r
+ //\r
+ // Copy the Head information\r
+ //\r
+ if (Database->Handle != 0) {\r
+ CopyMem (&Handle[0], &Database->Handle, sizeof (EFI_HII_HANDLE));\r
+ Database = Database->NextHandleDatabase;\r
+ }\r
+ //\r
+ // Copy more data if appropriate\r
+ //\r
+ for (HandleCount = 1; Database != NULL; HandleCount++) {\r
+ CopyMem (&Handle[HandleCount], &Database->Handle, sizeof (EFI_HII_HANDLE));\r
+ Database = Database->NextHandleDatabase;\r
+ }\r
+\r
+ *HandleBufferLength = (UINT16) (sizeof (EFI_HII_HANDLE) * HandleCount);\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // Insufficient buffer length\r
+ //\r
+ *HandleBufferLength = (UINT16) (sizeof (EFI_HII_HANDLE) * HandleCount);\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetPrimaryLanguages (\r
+ IN EFI_HII_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle,\r
+ OUT EFI_STRING *LanguageString\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ This function allows a program to determine what the primary languages that are supported on a given handle.\r
+\r
+Arguments:\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+ UINTN Count;\r
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
+ EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;\r
+ EFI_HII_DATA *HiiData;\r
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
+ EFI_HII_STRING_PACK *StringPack;\r
+ EFI_HII_STRING_PACK *Location;\r
+ UINT32 Length;\r
+ RELOFST Token;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HiiData = EFI_HII_DATA_FROM_THIS (This);\r
+\r
+ PackageInstance = NULL;\r
+ //\r
+ // Find matching handle in the handle database. Then get the package instance.\r
+ //\r
+ for (HandleDatabase = HiiData->DatabaseHead;\r
+ HandleDatabase != NULL;\r
+ HandleDatabase = HandleDatabase->NextHandleDatabase\r
+ ) {\r
+ if (Handle == HandleDatabase->Handle) {\r
+ PackageInstance = HandleDatabase->Buffer;\r
+ }\r
+ }\r
+ //\r
+ // No handle was found - error condition\r
+ //\r
+ if (PackageInstance == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ValidatePack (This, PackageInstance, &StringPackageInstance, NULL);\r
+\r
+ //\r
+ // Based on if there is IFR data in this package instance, determine\r
+ // what the location is of the beginning of the string data.\r
+ //\r
+ if (StringPackageInstance->IfrSize > 0) {\r
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize);\r
+ } else {\r
+ StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);\r
+ }\r
+\r
+ Location = StringPack;\r
+ //\r
+ // Remember that the string packages are formed into contiguous blocks of language data.\r
+ //\r
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
+ for (Count = 0; Length != 0; Count = Count + 3) {\r
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);\r
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
+ }\r
+\r
+ *LanguageString = AllocateZeroPool (2 * (Count + 1));\r
+\r
+ ASSERT (*LanguageString);\r
+\r
+ StringPack = (EFI_HII_STRING_PACK *) Location;\r
+\r
+ //\r
+ // Copy the 6 bytes to LanguageString - keep concatenating it. Shouldn't we just store uint8's since the ISO\r
+ // standard defines the lettering as all US English characters anyway? Save a few bytes.\r
+ //\r
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
+ for (Count = 0; Length != 0; Count = Count + 3) {\r
+ CopyMem (&Token, &StringPack->LanguageNameString, sizeof (RELOFST));\r
+ CopyMem (*LanguageString + Count, (VOID *) ((CHAR8 *) (StringPack) + Token), 6);\r
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);\r
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+HiiGetSecondaryLanguages (\r
+ IN EFI_HII_PROTOCOL *This,\r
+ IN EFI_HII_HANDLE Handle,\r
+ IN CHAR16 *PrimaryLanguage,\r
+ OUT EFI_STRING *LanguageString\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ This function allows a program to determine which secondary languages are supported \r
+ on a given handle for a given primary language.\r
+\r
+ Arguments:\r
+\r
+Returns: \r
+\r
+--*/\r
+{\r
+ UINTN Count;\r
+ EFI_HII_PACKAGE_INSTANCE *PackageInstance;\r
+ EFI_HII_PACKAGE_INSTANCE *StringPackageInstance;\r
+ EFI_HII_DATA *HiiData;\r
+ EFI_HII_HANDLE_DATABASE *HandleDatabase;\r
+ EFI_HII_STRING_PACK *StringPack;\r
+ RELOFST Token;\r
+ UINT32 Length;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HiiData = EFI_HII_DATA_FROM_THIS (This);\r
+ //\r
+ // Check numeric value against the head of the database\r
+ //\r
+ PackageInstance = NULL;\r
+ for (HandleDatabase = HiiData->DatabaseHead;\r
+ HandleDatabase != NULL;\r
+ HandleDatabase = HandleDatabase->NextHandleDatabase\r
+ ) {\r
+ //\r
+ // Match the numeric value with the database entry - if matched, extract PackageInstance\r
+ //\r
+ if (Handle == HandleDatabase->Handle) {\r
+ PackageInstance = HandleDatabase->Buffer;\r
+ }\r
+ }\r
+ //\r
+ // No handle was found - error condition\r
+ //\r
+ if (PackageInstance == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ValidatePack (This, PackageInstance, &StringPackageInstance, NULL);\r
+\r
+ //\r
+ // Based on if there is IFR data in this package instance, determine\r
+ // what the location is of the beginning of the string data.\r
+ //\r
+ if (StringPackageInstance->IfrSize > 0) {\r
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize);\r
+ } else {\r
+ StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData);\r
+ }\r
+\r
+ //\r
+ // Remember that the string packages are formed into contiguous blocks of language data.\r
+ //\r
+ for (; StringPack->Header.Length != 0;) {\r
+ //\r
+ // Find the PrimaryLanguage being requested\r
+ //\r
+ Token = StringPack->LanguageNameString;\r
+ if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + Token), PrimaryLanguage, 3) == 0) {\r
+ //\r
+ // Now that we found the primary, the secondary languages will follow immediately\r
+ // or the next character is a NULL if there are no secondary languages. We determine\r
+ // the number by getting the stringsize based on the StringPack origination + the LanguageNameString\r
+ // offset + 6 (which is the size of the first 3 letter ISO primary language name). If we get 2, there\r
+ // are no secondary languages (2 = null-terminator).\r
+ //\r
+ Count = StrSize ((VOID *) ((CHAR8 *) (StringPack) + Token + 6));\r
+\r
+ *LanguageString = AllocateZeroPool (2 * (Count + 1));\r
+\r
+ ASSERT (*LanguageString);\r
+\r
+ CopyMem (*LanguageString, (VOID *) ((CHAR8 *) (StringPack) + Token + 6), Count);\r
+ break;\r
+ }\r
+\r
+ CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32));\r
+ StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r