From 878ddf1fc3540a715f63594ed22b6929e881afb4 Mon Sep 17 00:00:00 2001 From: bbahnsen Date: Fri, 21 Apr 2006 22:54:32 +0000 Subject: Initial import. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524 --- .../UserInterface/HiiDataBase/Dxe/Fonts.c | 263 ++++ .../UserInterface/HiiDataBase/Dxe/Forms.c | 1564 ++++++++++++++++++++ .../UserInterface/HiiDataBase/Dxe/HiiDatabase.c | 413 ++++++ .../UserInterface/HiiDataBase/Dxe/HiiDatabase.dxs | 26 + .../UserInterface/HiiDataBase/Dxe/HiiDatabase.h | 302 ++++ .../UserInterface/HiiDataBase/Dxe/HiiDatabase.mbd | 44 + .../UserInterface/HiiDataBase/Dxe/HiiDatabase.msa | 80 + .../UserInterface/HiiDataBase/Dxe/Keyboard.c | 43 + .../UserInterface/HiiDataBase/Dxe/Package.c | 677 +++++++++ .../UserInterface/HiiDataBase/Dxe/Strings.c | 1276 ++++++++++++++++ .../UserInterface/HiiDataBase/Dxe/build.xml | 47 + 11 files changed, 4735 insertions(+) create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Fonts.c create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.c create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.dxs create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.h create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.mbd create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Keyboard.c create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Strings.c create mode 100644 EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/build.xml (limited to 'EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe') diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Fonts.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Fonts.c new file mode 100644 index 0000000000..52dc12e877 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Fonts.c @@ -0,0 +1,263 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Fonts.c + +Abstract: + + This file contains the Glyph/Font processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +// +// We only need to define a wide glyph, since we will seed the narrow glyph with EFI_NARROW_GLYPH size of +// this data structure +// +UINT8 mUnknownGlyph[38] = { + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xAA, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xAA +}; + +EFI_STATUS +EFIAPI +HiiGetGlyph ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Source, + IN OUT UINT16 *Index, + OUT UINT8 **GlyphBuffer, + OUT UINT16 *BitWidth, + IN OUT UINT32 *InternalStatus + ) +/*++ + +Routine Description: + Translates a Unicode character into the corresponding font glyph. + If the Source was pointing to a non-spacing character, the next Source[*Index] + character will be parsed and OR'd to the GlyphBuffer until a spacing character + is found in the Source. Since non-spacing characters are considered to be the + same pixel width as a regular character their BitWidth will be reflected correctly + however due to their special attribute, they are considered to be zero advancing width. + This basically means that the cursor would not advance, thus the character that follows + it would overlay the non-spacing character. The Index is modified to reflect both the + incoming array entry into the Source string but also the outgoing array entry after having + parsed the equivalent of a single Glyph's worth of data. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_DATA *HiiData; + UINTN Count; + BOOLEAN Narrow; + UINTN Location; + UINTN SearchLocation; + UINTN Value; + CHAR16 Character; + UINTN Attributes; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + GlobalData = HiiData->GlobalData; + Count = sizeof (GlobalData->NarrowGlyphs->GlyphCol1); + + Location = *Index; + SearchLocation = *Index; + Narrow = TRUE; + + if (Source[Location] == NARROW_CHAR || Source[Location] == WIDE_CHAR) { + *InternalStatus = 0; + } + // + // We don't know what glyph database to look in - let's figure it out + // + if (*InternalStatus == 0) { + // + // Determine if we are looking for narrow or wide glyph data + // + do { + if (Source[SearchLocation] == NARROW_CHAR || Source[SearchLocation] == WIDE_CHAR) { + // + // We found something that identifies what glyph database to look in + // + if (Source[SearchLocation] == WIDE_CHAR) { + Narrow = FALSE; + *BitWidth = WIDE_WIDTH; + *InternalStatus = WIDE_CHAR; + Location++; + break; + } else { + Narrow = TRUE; + *BitWidth = NARROW_WIDTH; + *InternalStatus = NARROW_CHAR; + Location++; + break; + } + } + } while (SearchLocation-- > 0); + } + + if (*InternalStatus == NARROW_CHAR) { + Narrow = TRUE; + *BitWidth = NARROW_WIDTH; + } else if (*InternalStatus == WIDE_CHAR) { + Narrow = FALSE; + *BitWidth = WIDE_WIDTH; + } else { + // + // Without otherwise knowing what the width is narrow (e.g. someone passed in a string with index of 0 + // we wouldn't be able to determine the width of the data.) + // BUGBUG - do we go to wide database and if exist, ignore narrow? Check Unicode spec.... + // + Narrow = TRUE; + *BitWidth = NARROW_WIDTH; + } + + Character = Source[Location]; + + if (Narrow) { + if (GlobalData->NarrowGlyphs[Character].UnicodeWeight != 0x0000) { + *GlyphBuffer = (UINT8 *) (&GlobalData->NarrowGlyphs[Character]); + Attributes = GlobalData->NarrowGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING; + } else { + // + // Glyph is uninitialized - return an error, but hand back the glyph + // + *GlyphBuffer = (UINT8 *) (&GlobalData->NarrowGlyphs[Character]); + *Index = (UINT16) (Location + 1); + return EFI_NOT_FOUND; + } + } else { + // + // Wide character + // + if (GlobalData->WideGlyphs[Character].UnicodeWeight != 0x0000) { + *GlyphBuffer = (UINT8 *) (&GlobalData->WideGlyphs[Character]); + Attributes = GlobalData->WideGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING; + } else { + // + // Glyph is uninitialized - return an error, but hand back the glyph + // + *GlyphBuffer = (UINT8 *) (&GlobalData->WideGlyphs[Character]); + *Index = (UINT16) (Location + 1); + return EFI_NOT_FOUND; + } + } + // + // This is a non-spacing character. It will be followed by either more non-spacing + // characters or a regular character. We need to OR together the data associated with each. + // + for (; Attributes != 0; Location++) { + // + // Character is the Unicode value which is the index into the Glyph array. + // + Character = Source[Location]; + + if (Narrow) { + for (Value = 0; Value != Count; Value++) { + *GlyphBuffer[Location + Value] |= GlobalData->NarrowGlyphs[Character].GlyphCol1[Value]; + } + + Attributes = GlobalData->NarrowGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING; + } else { + for (Value = 0; Value != Count; Value++) { + *GlyphBuffer[Location + Value] |= GlobalData->WideGlyphs[Character].GlyphCol1[Value]; + *GlyphBuffer[Location + Value + Count] |= GlobalData->WideGlyphs[Character].GlyphCol2[Value]; + } + + Attributes = GlobalData->WideGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING; + } + } + // + // Source[*Index] should point to the next character to process + // + *Index = (UINT16) (Location + 1); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiGlyphToBlt ( + IN EFI_HII_PROTOCOL *This, + IN UINT8 *GlyphBuffer, + IN EFI_UGA_PIXEL Foreground, + IN EFI_UGA_PIXEL Background, + IN UINTN Count, + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_UGA_PIXEL *BltBuffer + ) +{ + UINTN X; + UINTN Y; + + // + // Convert Monochrome bitmap of the Glyph to BltBuffer structure + // + for (Y = 0; Y < Height; Y++) { + for (X = 0; X < Width; X++) { + if ((((EFI_NARROW_GLYPH *) GlyphBuffer)->GlyphCol1[Y] & (1 << X)) != 0) { + BltBuffer[Y * Width * Count + (Width - X - 1)] = Foreground; + } else { + BltBuffer[Y * Width * Count + (Width - X - 1)] = Background; + } + } + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c new file mode 100644 index 0000000000..a0a9619197 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c @@ -0,0 +1,1564 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Forms.c + +Abstract: + + This file contains the form processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +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; + } + } +} + +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; + } + } +} + +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; +} + +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 ¨C 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 ¨C 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 + ); + } + // + // 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 + ); + } else { + Status = gRT->GetVariable ( + (CHAR16 *) SETUP_MAP_NAME, + (EFI_GUID *)(UINTN)&VariableContents->VariableGuid, + NULL, + &TempValue, + ExportBuffer + ); + } + + 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 + ); + } else { + Status = gRT->GetVariable ( + String, + (EFI_GUID *)(UINTN)&VariableContents->VariableGuid, + NULL, + &TempValue, + ExportBuffer + ); + } + + 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 InsufficientSize; + 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; + InsufficientSize = FALSE; + 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; + + 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_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) { + if (Location->Length > *BufferLength || Buffer == NULL) { + *BufferLength = Location->Length; + return EFI_BUFFER_TOO_SMALL; + } else { + for (; Location->OpCode != EFI_IFR_END_FORM_OP;) { + CopyMem (Buffer, Location, Location->Length); + Buffer = Buffer + Location->Length; + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + } + + CopyMem (Buffer, Location, Location->Length); + return EFI_SUCCESS; + } + } + + default: + break; + } + // + // Go to the next Op-Code + // + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + } + } + + return EFI_SUCCESS; +} + +// +// 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. + // + gBS->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; + } + } + + gBS->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); + 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 + // + gBS->FreePool (HandleDatabase->Buffer); + HandleDatabase->Buffer = OrigTempBuffer; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.c new file mode 100644 index 0000000000..ce34eff5bd --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.c @@ -0,0 +1,413 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + HiiDatabase.c + +Abstract: + + This file contains the entry code to the HII database. + +--*/ + +#include "HiiDatabase.h" + +EFI_STATUS +EFIAPI +InitializeHiiDatabase ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Initialize HII Database + +Arguments: + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + EFI_SUCCESS - Setup loaded. + other - Setup Error + +--*/ +{ + EFI_STATUS Status; + EFI_HII_DATA *HiiData; + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HANDLE *HandleBuffer; + EFI_HANDLE Handle; + UINTN HandleCount; + UINTN Index; + + // + // There will be only one HII Database in the system + // If there is another out there, someone is trying to install us + // again. Fail that scenario. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiHiiProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + // + // If there was no error, assume there is an installation and fail to load + // + if (!EFI_ERROR (Status)) { + if (HandleBuffer != NULL) { + gBS->FreePool (HandleBuffer); + } + + return EFI_DEVICE_ERROR; + } + + HiiData = AllocatePool (sizeof (EFI_HII_DATA)); + + ASSERT (HiiData); + + GlobalData = AllocateZeroPool (sizeof (EFI_HII_GLOBAL_DATA)); + + ASSERT (GlobalData); + + // + // Seed the Font Database with a known non-character glyph + // + for (Index = 0; Index <= MAX_GLYPH_COUNT; Index++) { + // + // Seeding the UnicodeWeight with 0 signifies that it is uninitialized + // + GlobalData->NarrowGlyphs[Index].UnicodeWeight = 0; + GlobalData->WideGlyphs[Index].UnicodeWeight = 0; + GlobalData->NarrowGlyphs[Index].Attributes = 0; + GlobalData->WideGlyphs[Index].Attributes = 0; + CopyMem (GlobalData->NarrowGlyphs[Index].GlyphCol1, &mUnknownGlyph, NARROW_GLYPH_ARRAY_SIZE); + CopyMem (GlobalData->WideGlyphs[Index].GlyphCol1, &mUnknownGlyph, WIDE_GLYPH_ARRAY_SIZE); + } + // + // Fill in HII data + // + HiiData->Signature = EFI_HII_DATA_SIGNATURE; + HiiData->GlobalData = GlobalData; + HiiData->GlobalData->SystemKeyboardUpdate = FALSE; + HiiData->DatabaseHead = NULL; + HiiData->Hii.NewPack = HiiNewPack; + HiiData->Hii.RemovePack = HiiRemovePack; + HiiData->Hii.FindHandles = HiiFindHandles; + HiiData->Hii.ExportDatabase = HiiExportDatabase; + HiiData->Hii.GetGlyph = HiiGetGlyph; + HiiData->Hii.GetPrimaryLanguages = HiiGetPrimaryLanguages; + HiiData->Hii.GetSecondaryLanguages = HiiGetSecondaryLanguages; + HiiData->Hii.NewString = HiiNewString; + HiiData->Hii.GetString = HiiGetString; + HiiData->Hii.ResetStrings = HiiResetStrings; + HiiData->Hii.TestString = HiiTestString; + HiiData->Hii.GetLine = HiiGetLine; + HiiData->Hii.GetForms = HiiGetForms; + HiiData->Hii.GetDefaultImage = HiiGetDefaultImage; + HiiData->Hii.UpdateForm = HiiUpdateForm; + HiiData->Hii.GetKeyboardLayout = HiiGetKeyboardLayout; + HiiData->Hii.GlyphToBlt = HiiGlyphToBlt; + + // + // Install protocol interface + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiHiiProtocolGuid, + EFI_NATIVE_INTERFACE, + &HiiData->Hii + ); + + ASSERT_EFI_ERROR (Status); + + return Status; +} + +EFI_STATUS +EFIAPI +HiiFindHandles ( + IN EFI_HII_PROTOCOL *This, + IN OUT UINT16 *HandleBufferLength, + OUT EFI_HII_HANDLE Handle[1] + ) +/*++ + +Routine Description: + Determines the handles that are currently active in the database. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_HANDLE_DATABASE *Database; + EFI_HII_DATA *HiiData; + UINTN HandleCount; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + GlobalData = HiiData->GlobalData; + + Database = HiiData->DatabaseHead; + + if (Database == NULL) { + *HandleBufferLength = 0; + return EFI_NOT_FOUND; + } + + for (HandleCount = 0; Database != NULL; HandleCount++) { + Database = Database->NextHandleDatabase; + } + // + // Is there a sufficient buffer for the data being passed back? + // + if (*HandleBufferLength >= (sizeof (EFI_HII_HANDLE) * HandleCount)) { + Database = HiiData->DatabaseHead; + + // + // Copy the Head information + // + if (Database->Handle != 0) { + CopyMem (&Handle[0], &Database->Handle, sizeof (EFI_HII_HANDLE)); + Database = Database->NextHandleDatabase; + } + // + // Copy more data if appropriate + // + for (HandleCount = 1; Database != NULL; HandleCount++) { + CopyMem (&Handle[HandleCount], &Database->Handle, sizeof (EFI_HII_HANDLE)); + Database = Database->NextHandleDatabase; + } + + *HandleBufferLength = (UINT16) (sizeof (EFI_HII_HANDLE) * HandleCount); + return EFI_SUCCESS; + } else { + // + // Insufficient buffer length + // + *HandleBufferLength = (UINT16) (sizeof (EFI_HII_HANDLE) * HandleCount); + return EFI_BUFFER_TOO_SMALL; + } +} + +EFI_STATUS +EFIAPI +HiiGetPrimaryLanguages ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + OUT EFI_STRING *LanguageString + ) +/*++ + +Routine Description: + + This function allows a program to determine what the primary languages that are supported on a given handle. + +Arguments: + +Returns: + +--*/ +{ + UINTN Count; + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_STRING_PACK *StringPack; + EFI_HII_STRING_PACK *Location; + UINT32 Length; + RELOFST Token; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + PackageInstance = NULL; + // + // Find matching handle in the handle database. Then get the package instance. + // + for (HandleDatabase = HiiData->DatabaseHead; + HandleDatabase != NULL; + HandleDatabase = HandleDatabase->NextHandleDatabase + ) { + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + ValidatePack (This, PackageInstance, &StringPackageInstance, NULL); + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize); + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + } + + Location = StringPack; + // + // Remember that the string packages are formed into contiguous blocks of language data. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (Count = 0; Length != 0; Count = Count + 3) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + + *LanguageString = AllocateZeroPool (2 * (Count + 1)); + + ASSERT (*LanguageString); + + StringPack = (EFI_HII_STRING_PACK *) Location; + + // + // Copy the 6 bytes to LanguageString - keep concatenating it. Shouldn't we just store uint8's since the ISO + // standard defines the lettering as all US English characters anyway? Save a few bytes. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (Count = 0; Length != 0; Count = Count + 3) { + CopyMem (&Token, &StringPack->LanguageNameString, sizeof (RELOFST)); + CopyMem (*LanguageString + Count, (VOID *) ((CHAR8 *) (StringPack) + Token), 6); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiGetSecondaryLanguages ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CHAR16 *PrimaryLanguage, + OUT EFI_STRING *LanguageString + ) +/*++ + +Routine Description: + + This function allows a program to determine which secondary languages are supported + on a given handle for a given primary language. + + Arguments: + +Returns: + +--*/ +{ + UINTN Count; + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_STRING_PACK *StringPack; + EFI_HII_STRING_PACK *Location; + RELOFST Token; + UINT32 Length; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + // + // Check numeric value against the head of the database + // + PackageInstance = NULL; + for (HandleDatabase = HiiData->DatabaseHead; + HandleDatabase != NULL; + HandleDatabase = HandleDatabase->NextHandleDatabase + ) { + // + // Match the numeric value with the database entry - if matched, extract PackageInstance + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + ValidatePack (This, PackageInstance, &StringPackageInstance, NULL); + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize); + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + } + + Location = StringPack; + + // + // Remember that the string packages are formed into contiguous blocks of language data. + // + for (; StringPack->Header.Length != 0;) { + // + // Find the PrimaryLanguage being requested + // + Token = StringPack->LanguageNameString; + if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + Token), PrimaryLanguage, 3) == 0) { + // + // Now that we found the primary, the secondary languages will follow immediately + // or the next character is a NULL if there are no secondary languages. We determine + // the number by getting the stringsize based on the StringPack origination + the LanguageNameString + // offset + 6 (which is the size of the first 3 letter ISO primary language name). If we get 2, there + // are no secondary languages (2 = null-terminator). + // + Count = StrSize ((VOID *) ((CHAR8 *) (StringPack) + Token + 6)); + + *LanguageString = AllocateZeroPool (2 * (Count + 1)); + + ASSERT (*LanguageString); + + CopyMem (*LanguageString, (VOID *) ((CHAR8 *) (StringPack) + Token + 6), Count); + break; + } + + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + } + + return EFI_SUCCESS; +} + diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.dxs b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.dxs new file mode 100644 index 0000000000..86c8ac4ce2 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + HiiDatabase.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.h b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.h new file mode 100644 index 0000000000..c50cd958a0 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.h @@ -0,0 +1,302 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + HiiDatabase.h + +Abstract: + + This file contains global defines and prototype definitions + for the HII database. + +--*/ + +#ifndef _HIIDATABASE_H +#define _HIIDATABASE_H + +// +// HII Database Global data +// +#define EFI_HII_DATA_SIGNATURE EFI_SIGNATURE_32 ('H', 'i', 'i', 'P') + +#define MAX_GLYPH_COUNT 65535 +#define NARROW_GLYPH_ARRAY_SIZE 19 +#define WIDE_GLYPH_ARRAY_SIZE 38 + +#define SETUP_MAP_NAME L"Setup" +#define HII_VARIABLE_SUFFIX_USER_DATA L"UserSavedData" +#define HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE L"DefaultOverride" +#define HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE L"ManufacturingOverride" + +typedef struct _EFI_HII_HANDLE_DATABASE { + VOID *Buffer; // Actual buffer pointer + EFI_HII_HANDLE Handle; // Monotonically increasing value to signify the value returned to caller + UINT32 NumberOfTokens; // The initial number of tokens when first registered + struct _EFI_HII_HANDLE_DATABASE *NextHandleDatabase; +} EFI_HII_HANDLE_DATABASE; + +typedef struct { + EFI_NARROW_GLYPH NarrowGlyphs[MAX_GLYPH_COUNT]; + EFI_WIDE_GLYPH WideGlyphs[MAX_GLYPH_COUNT]; + EFI_KEY_DESCRIPTOR SystemKeyboardLayout[106]; + EFI_KEY_DESCRIPTOR OverrideKeyboardLayout[106]; + BOOLEAN SystemKeyboardUpdate; // Has the SystemKeyboard been updated? +} EFI_HII_GLOBAL_DATA; + +typedef struct { + UINTN Signature; + + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_HANDLE_DATABASE *DatabaseHead; // Head of the Null-terminated singly-linked list of handles. + EFI_HII_PROTOCOL Hii; +} EFI_HII_DATA; + +typedef struct { + EFI_HII_HANDLE Handle; + EFI_GUID Guid; + EFI_HII_HANDLE_PACK HandlePack; + UINTN IfrSize; + UINTN StringSize; + EFI_HII_IFR_PACK *IfrData; // All the IFR data stored here + EFI_HII_STRING_PACK *StringData; // All the String data stored at &IfrData + IfrSize (StringData is just a label - never referenced) +} EFI_HII_PACKAGE_INSTANCE; + +typedef struct { + EFI_HII_PACK_HEADER Header; + EFI_IFR_FORM_SET FormSet; + EFI_IFR_END_FORM_SET EndFormSet; +} EFI_FORM_SET_STUB; + +#define EFI_HII_DATA_FROM_THIS(a) CR (a, EFI_HII_DATA, Hii, EFI_HII_DATA_SIGNATURE) + +#define NARROW_WIDTH 8 +#define WIDE_WIDTH 16 + +extern UINT8 mUnknownGlyph[38]; + +// +// Prototypes +// +EFI_STATUS +GetPackSize ( + IN VOID *Pack, + OUT UINTN *PackSize, + OUT UINT32 *NumberOfTokens + ) +; + +EFI_STATUS +ValidatePack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGE_INSTANCE *PackageInstance, + OUT EFI_HII_PACKAGE_INSTANCE **StringPackageInstance, + OUT UINT32 *TotalStringCount + ) +; + +// +// Public Interface Prototypes +// +EFI_STATUS +EFIAPI +InitializeHiiDatabase ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +EFIAPI +HiiNewPack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGES *PackageList, + OUT EFI_HII_HANDLE *Handle + ) +; + +EFI_STATUS +EFIAPI +HiiRemovePack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ) +; + +EFI_STATUS +EFIAPI +HiiFindHandles ( + IN EFI_HII_PROTOCOL *This, + IN OUT UINT16 *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle + ) +; + +EFI_STATUS +EFIAPI +HiiExportDatabase ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +; + +EFI_STATUS +EFIAPI +HiiGetGlyph ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Source, + IN OUT UINT16 *Index, + OUT UINT8 **GlyphBuffer, + OUT UINT16 *BitWidth, + IN OUT UINT32 *InternalStatus + ) +; + +EFI_STATUS +EFIAPI +HiiGlyphToBlt ( + IN EFI_HII_PROTOCOL *This, + IN UINT8 *GlyphBuffer, + IN EFI_UGA_PIXEL Foreground, + IN EFI_UGA_PIXEL Background, + IN UINTN Count, + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_UGA_PIXEL *BltBuffer + ) +; + +EFI_STATUS +EFIAPI +HiiNewString ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString + ) +; + +EFI_STATUS +EFIAPI +HiiGetString ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINTN *BufferLength, + OUT EFI_STRING StringBuffer + ) +; + +EFI_STATUS +EFIAPI +HiiResetStrings ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ) +; + +EFI_STATUS +EFIAPI +HiiTestString ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *StringToTest, + IN OUT UINT32 *FirstMissing, + OUT UINT32 *GlyphBufferSize + ) +; + +EFI_STATUS +EFIAPI +HiiGetPrimaryLanguages ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + OUT EFI_STRING *LanguageString + ) +; + +EFI_STATUS +EFIAPI +HiiGetSecondaryLanguages ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CHAR16 *PrimaryLanguage, + OUT EFI_STRING *LanguageString + ) +; + +EFI_STATUS +EFIAPI +HiiGetLine ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN OUT UINT16 *Index, + IN UINT16 LineWidth, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, + OUT EFI_STRING StringBuffer + ) +; + +EFI_STATUS +EFIAPI +HiiGetForms ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + IN OUT UINTN *BufferLength, + OUT UINT8 *Buffer + ) +; + +EFI_STATUS +EFIAPI +HiiGetDefaultImage ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList + ) +; + +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 + ) +; + +EFI_STATUS +EFIAPI +HiiGetKeyboardLayout ( + IN EFI_HII_PROTOCOL *This, + OUT UINT16 *DescriptorCount, + OUT EFI_KEY_DESCRIPTOR *Descriptor + ) +; + +EFI_STATUS +HiiCompareLanguage ( + IN CHAR16 *LanguageStringLocation, + IN CHAR16 *Language + ) +; + +#endif diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.mbd b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.mbd new file mode 100644 index 0000000000..03f2ed9463 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.mbd @@ -0,0 +1,44 @@ + + + + + HiiDatabase + FCD337AB-B1D3-4EF8-957C-8048606FF670 + 0 + FIX ME! + Copyright (c) 2004-2006, Intel Corporation + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseLib + BaseMemoryLib + BaseDebugLibReportStatusCode + UefiDriverEntryPoint + DxeMemoryAllocationLib + DxeReportStatusCodeLib + EdkIfrSupportLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa new file mode 100644 index 0000000000..3eb5332c81 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa @@ -0,0 +1,80 @@ + + + + + HiiDatabase + DXE_DRIVER + BS_DRIVER + FCD337AB-B1D3-4EF8-957C-8048606FF670 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, Intel Corporation + + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + BaseLib + DebugLib + UefiDriverEntryPoint + MemoryAllocationLib + BaseMemoryLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + EdkIfrSupportLib + + + HiiDatabase.c + HiiDatabase.h + Forms.c + Strings.c + Package.c + Fonts.c + Keyboard.c + HiiDatabase.dxs + + + MdePkg + EdkModulePkg + + + Hii + FormCallback + + + + L"Lang" + + 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } + + + + + + GlobalVariable + + + + + InitializeHiiDatabase + + + diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Keyboard.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Keyboard.c new file mode 100644 index 0000000000..8e9417fc83 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Keyboard.c @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Keyboard.c + +Abstract: + + This file contains the keyboard processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +EFI_STATUS +EFIAPI +HiiGetKeyboardLayout ( + IN EFI_HII_PROTOCOL *This, + OUT UINT16 *DescriptorCount, + OUT EFI_KEY_DESCRIPTOR *Descriptor + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c new file mode 100644 index 0000000000..3e9e5364e9 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c @@ -0,0 +1,677 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +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; + EFI_WIDE_GLYPH *WideGlyph; + + 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 = 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; + WideGlyph = (EFI_WIDE_GLYPH *) Local; + 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; + WideGlyph = (EFI_WIDE_GLYPH *) Local; + 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; + UINTN Count; + + 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 (Count = 0; 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 + // + gBS->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; + gBS->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; +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Strings.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Strings.c new file mode 100644 index 0000000000..742a01dc43 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Strings.c @@ -0,0 +1,1276 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Strings.c + +Abstract: + + This file contains the string processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +VOID +AsciiToUnicode ( + IN UINT8 *Lang, + IN UINT16 *Language + ) +{ + UINT8 Count; + + // + // Convert the ASCII Lang variable to a Unicode Language variable + // + for (Count = 0; Count < 3; Count++) { + Language[Count] = (CHAR16) Lang[Count]; + } +} + +EFI_STATUS +EFIAPI +HiiTestString ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *StringToTest, + IN OUT UINT32 *FirstMissing, + OUT UINT32 *GlyphBufferSize + ) +/*++ + +Routine Description: + Test if all of the characters in a string have corresponding font characters. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_DATA *HiiData; + UINTN Count; + BOOLEAN Narrow; + UINTN Location; + UINT8 GlyphCol1[19]; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + GlobalData = HiiData->GlobalData; + Count = 0; + Narrow = TRUE; + + ZeroMem (GlyphCol1, sizeof (GlyphCol1)); + + // + // Walk through the string until you hit the null terminator + // + for (; StringToTest[*FirstMissing] != 0x00; (*FirstMissing)++) { + Location = *FirstMissing; + // + // Rewind through the string looking for a glyph width identifier + // + for (; Location != 0; Location--) { + if (StringToTest[Location] == NARROW_CHAR || StringToTest[Location] == WIDE_CHAR) { + // + // We found something that identifies what glyph database to look in + // + if (StringToTest[Location] == WIDE_CHAR) { + Narrow = FALSE; + } else { + Narrow = TRUE; + } + } + } + + if (Narrow) { + if (CompareMem ( + GlobalData->NarrowGlyphs[StringToTest[*FirstMissing]].GlyphCol1, + &mUnknownGlyph, + NARROW_GLYPH_ARRAY_SIZE + ) == 0 + ) { + // + // Break since this glyph isn't defined + // + return EFI_NOT_FOUND; + } + } else { + // + // Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size + // + if (CompareMem ( + GlobalData->WideGlyphs[StringToTest[*FirstMissing]].GlyphCol1, + &mUnknownGlyph, + WIDE_GLYPH_ARRAY_SIZE + ) == 0 + ) { + // + // Break since this glyph isn't defined + // + return EFI_NOT_FOUND; + } + } + + Count++; + } + + if (Narrow) { + *GlyphBufferSize = (UINT32) (Count * sizeof (EFI_NARROW_GLYPH)); + } else { + *GlyphBufferSize = (UINT32) (Count * sizeof (EFI_WIDE_GLYPH)); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +HiiNewString2 ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString, + IN BOOLEAN ResetStrings + ) +/*++ + +Routine Description: + + This function allows a new String to be added to an already existing String Package. + We will make a buffer the size of the package + EfiStrSize of the new string. We will + copy the string package that first gets changed and the following language packages until + we encounter the NULL string package. All this time we will ensure that the offsets have + been adjusted. + +Arguments: + + This - Pointer to the HII protocol. + Language - Pointer to buffer which contains the language code of this NewString. + Handle - Handle of the package instance to be processed. + Reference - The token number for the string. If 0, new string token to be returned through this parameter. + NewString - Buffer pointer for the new string. + ResetStrings - Indicate if we are resetting a string. + +Returns: + + EFI_SUCCESS - The string has been added or reset to Hii database. + EFI_INVALID_PARAMETER - Some parameter passed in is invalid. + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_STRING_PACK *StringPack; + EFI_HII_STRING_PACK *NewStringPack; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_PACKAGE_INSTANCE *NewBuffer; + UINT8 *Location; + UINT8 *StringLocation; + RELOFST *StringPointer; + UINTN Count; + UINTN Size; + UINTN Index; + UINTN SecondIndex; + BOOLEAN AddString; + EFI_STATUS Status; + UINTN Increment; + UINTN StringCount; + UINT32 TotalStringCount; + UINT32 OriginalStringCount; + RELOFST StringSize; + UINT32 Length; + RELOFST Offset; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + PackageInstance = NULL; + AddString = FALSE; + Increment = 0; + StringCount = 0; + TotalStringCount = 0; + OriginalStringCount = 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; + if (ResetStrings) { + TotalStringCount = HandleDatabase->NumberOfTokens; + } + break; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = ValidatePack (This, PackageInstance, &StringPackageInstance, &TotalStringCount); + + // + // This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value + // + Count = StringPackageInstance->IfrSize; + + // + // This is the size of the complete series of string packs + // + Size = StringPackageInstance->StringSize; + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + Location = (UINT8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize; + } else { + Location = (UINT8 *) (&StringPackageInstance->IfrData); + } + // + // We allocate a buffer which is big enough for both adding and resetting string. + // The size is slightly larger than the real size of the packages when we are resetting a string. + // + NewBuffer = AllocateZeroPool ( + sizeof (EFI_HII_PACKAGE_INSTANCE) - + 2 * sizeof (VOID *) + + StringPackageInstance->IfrSize + + StringPackageInstance->StringSize + + sizeof (RELOFST) + + StrSize (NewString) + ); + ASSERT (NewBuffer); + + // + // Copy data to new buffer + // + NewBuffer->Handle = StringPackageInstance->Handle; + NewBuffer->IfrSize = StringPackageInstance->IfrSize; + + // + // The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string + // package to begin with. + // + NewBuffer->StringSize = StringPackageInstance->StringSize + StrSize (NewString) + sizeof (EFI_HII_STRING_PACK); + + if (StringPackageInstance->IfrSize > 0) { + CopyMem (&NewBuffer->IfrData, &StringPackageInstance->IfrData, StringPackageInstance->IfrSize); + } + + StringPack = (EFI_HII_STRING_PACK *) Location; + + // + // There may be multiple instances packed together of strings + // so we must walk the self describing structures until we encounter + // what we are looking for. In the meantime, copy everything we encounter + // to the new buffer. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (; Length != 0;) { + // + // If passed in Language ISO value is in this string pack's language string + // then we are dealing with the strings we want. + // + CopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST)); + Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language); + + if (!EFI_ERROR (Status)) { + break; + } + + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length); + + Count = Count + Length; + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + // + // Found the language pack to update on a particular handle + // We need to Copy the Contents of this pack and adjust the offset values associated + // with adding/changing a string. This is a particular piece of code that screams for + // it being prone to programming error. + // + // + // Copy the string package up to the string data + // + StringPointer = (RELOFST *) (StringPack + 1); + CopyMem ( + ((CHAR8 *) (&NewBuffer->IfrData) + Count), + StringPack, + (UINTN) ((UINTN) (StringPointer) - (UINTN) (StringPack)) + ); + + // + // Determine the number of StringPointers + // + if (!ResetStrings) { + CopyMem (&TotalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST)); + } else { + // + // If we are resetting the strings, use the original value when exported + // + CopyMem (&OriginalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST)); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString -= + ( + (RELOFST) (OriginalStringCount - TotalStringCount) * + sizeof (RELOFST) + ); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName -= + ( + (RELOFST) (OriginalStringCount - TotalStringCount) * + sizeof (RELOFST) + ); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers = TotalStringCount; + *Reference = (STRING_REF) (TotalStringCount); + } + // + // If the token value is not valid, error out + // + if ((*Reference >= TotalStringCount) && !ResetStrings) { + gBS->FreePool (NewBuffer); + return EFI_INVALID_PARAMETER; + } + // + // If Reference is 0, update it with what the new token reference will be and turn the AddString flag on + // + if (*Reference == 0) { + *Reference = (STRING_REF) (TotalStringCount); + AddString = TRUE; + } + + if (AddString) { + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString += sizeof (RELOFST); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName += sizeof (RELOFST); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers++; + } + // + // Increment offset by amount of copied data + // + Count = Count + ((UINTN) (StringPointer) - (UINTN) StringPack); + + for (Index = 0; Index < TotalStringCount; Index++) { + // + // If we are pointing to the size of the changing string value + // then cache the old string value so you know what the difference is + // + if (Index == *Reference) { + CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST)); + + StringLocation = ((UINT8 *) (StringPack) + Offset); + for (SecondIndex = 0; + (StringLocation[SecondIndex] != 0) || (StringLocation[SecondIndex + 1] != 0); + SecondIndex = SecondIndex + 2 + ) + ; + SecondIndex = SecondIndex + 2; + + Size = SecondIndex; + + // + // NewString is a passed in local string which is assumed to be aligned + // + Size = StrSize (NewString) - Size; + } + // + // If we are about to copy the offset of the string that follows the changed string make + // sure that the offsets are adjusted accordingly + // + if ((Index > *Reference) && !ResetStrings) { + CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST)); + Offset = (RELOFST) (Offset + Size); + CopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST)); + } + // + // If we are adding a string that means we will have an extra string pointer that will affect all string offsets + // + if (AddString) { + CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST)); + Offset = (UINT32) (Offset + sizeof (RELOFST)); + CopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST)); + } + // + // If resetting the strings, we need to reduce the offset by the difference in the strings + // + if (ResetStrings) { + CopyMem (&Length, &StringPointer[Index], sizeof (RELOFST)); + Length = Length - ((RELOFST) (OriginalStringCount - TotalStringCount) * sizeof (RELOFST)); + CopyMem (&StringPointer[Index], &Length, sizeof (RELOFST)); + } + // + // Notice that if the string was being added as a new token, we don't have to worry about the + // offsets changing in the other indexes + // + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringPointer[Index], sizeof (RELOFST)); + Count = Count + sizeof (RELOFST); + StringCount++; + } + // + // If we are adding a new string the above for loop did not copy the offset for us + // + if (AddString) { + // + // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous + // offset's string and create an offset to our new string. + // + CopyMem (&Offset, &StringPointer[Index - 1], sizeof (RELOFST)); + StringLocation = (UINT8 *) StringPack; + StringLocation = StringLocation + Offset - sizeof (RELOFST); + + // + // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues + // + for (Length = 0; + (StringLocation[Length] != 0) || (StringLocation[Length + 1] != 0); + Length = (RELOFST) (Length + 2) + ) + ; + Length = (RELOFST) (Length + 2); + + StringSize = (RELOFST) (Offset + Length); + + // + // Copy the new string offset + // + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringSize, sizeof (RELOFST)); + Count = Count + sizeof (RELOFST); + + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + Length = Length + sizeof (RELOFST); + CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32)); + } + // + // Set Location to the First String + // + if (ResetStrings) { + Index = OriginalStringCount; + } + // + // Set Location to the First String + // + Location = (UINT8 *) &StringPointer[Index]; + Index = 0; + + // + // Keep copying strings until you run into two CHAR16's in a row that are NULL + // + do { + if ((*Reference == Increment) && !AddString) { + StringLocation = ((UINT8 *) (&NewBuffer->IfrData) + Count); + CopyMem (StringLocation, NewString, StrSize (NewString)); + + // + // Advance the destination location by Count number of bytes + // + Count = Count + StrSize (NewString); + + // + // Add the difference between the new string and the old string to the length + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + + // + // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues + // + StringLocation = (UINT8 *) &Location[Index]; + for (Offset = 0; + (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0); + Offset = (RELOFST) (Offset + 2) + ) + ; + Offset = (RELOFST) (Offset + 2); + + Length = Length + (UINT32) StrSize (NewString) - Offset; + + CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32)); + } else { + StringLocation = (UINT8 *) &Location[Index]; + for (Offset = 0; + (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0); + Offset = (RELOFST) (Offset + 2) + ) + ; + Offset = (RELOFST) (Offset + 2); + + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringLocation, Offset); + + // + // Advance the destination location by Count number of bytes + // + Count = Count + Offset; + } + // + // Retrieve the number of characters to advance the index - should land at beginning of next string + // + Index = Index + Offset; + Increment++; + StringCount--; + Offset = 0; + } while (StringCount > 0); + + // + // If we are adding a new string, then the above do/while will not suffice + // + if (AddString) { + Offset = (RELOFST) StrSize (NewString); + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), NewString, Offset); + + Count = Count + StrSize (NewString); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + Length = Length + (UINT32) StrSize (NewString); + CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32)); + } + + if (ResetStrings) { + // + // Skip the remainder of strings in the string package + // + StringCount = OriginalStringCount - TotalStringCount; + + while (StringCount > 0) { + StringLocation = (UINT8 *) &Location[Index]; + for (Offset = 0; + (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0); + Offset = (RELOFST) (Offset + 2) + ) + ; + Offset = (RELOFST) (Offset + 2); + Index = Index + Offset; + StringCount--; + + // + // Adjust the size of the string pack by the string size we just skipped. + // Also reduce the length by the size of a RelativeOffset value since we + // obviously would have skipped that as well. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + Length = Length - Offset - sizeof (RELOFST); + CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32)); + } + } + + StringPack = (EFI_HII_STRING_PACK *) &Location[Index]; + + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (; Length != 0;) { + + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length); + + Count = Count + Length; + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + // + // Copy the null terminator to the new buffer + // + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, sizeof (EFI_HII_STRING_PACK)); + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + Location = (UINT8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize; + StringPack = (EFI_HII_STRING_PACK *) Location; + Location = (UINT8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize; + NewStringPack = (EFI_HII_STRING_PACK *) Location; + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + NewStringPack = (EFI_HII_STRING_PACK *) (&NewBuffer->IfrData); + } + + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (; Length != 0;) { + // + // Since we updated the old version of the string data as we moved things over + // And we had a chicken-egg problem with the data we copied, let's post-fix the new + // buffer with accurate length data. + // + CopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32)); + CopyMem (&NewStringPack->Header.Length, &StringPack->Header.Length, sizeof (UINT32)); + CopyMem (&StringPack->Header.Length, &Count, sizeof (UINT32)); + + CopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32)); + NewStringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (NewStringPack) + Count); + CopyMem (&Count, &StringPack->Header.Length, sizeof (UINT32)); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Count); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + + GetPackSize ((VOID *) ((CHAR8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize), &NewBuffer->StringSize, NULL); + + // + // Search through the handles until the requested handle is found. + // + for (HandleDatabase = HiiData->DatabaseHead; + HandleDatabase->Handle != 0; + HandleDatabase = HandleDatabase->NextHandleDatabase + ) { + if (HandleDatabase->Handle == StringPackageInstance->Handle) { + // + // Free the previous buffer associated with this handle, and assign the new buffer to the handle + // + gBS->FreePool (HandleDatabase->Buffer); + HandleDatabase->Buffer = NewBuffer; + break; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiNewString ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString + ) +/*++ + +Routine Description: + This function allows a new String to be added to an already existing String Package. + We will make a buffer the size of the package + StrSize of the new string. We will + copy the string package that first gets changed and the following language packages until + we encounter the NULL string package. All this time we will ensure that the offsets have + been adjusted. + +Arguments: + +Returns: + +--*/ +{ + UINTN Index; + CHAR16 *LangCodes; + CHAR16 Lang[4]; + STRING_REF OriginalValue; + EFI_STATUS Status; + + // + // To avoid a warning 4 uninitialized variable warning + // + Status = EFI_SUCCESS; + + Status = HiiGetPrimaryLanguages ( + This, + Handle, + &LangCodes + ); + + if (!EFI_ERROR (Status)) { + OriginalValue = *Reference; + + if (Language == NULL) { + for (Index = 0; LangCodes[Index] != 0; Index += 3) { + *Reference = OriginalValue; + CopyMem (Lang, &LangCodes[Index], 6); + Lang[3] = 0; + Status = HiiNewString2 ( + This, + Lang, + Handle, + Reference, + NewString, + FALSE + ); + + } + } else { + Status = HiiNewString2 ( + This, + Language, + Handle, + Reference, + NewString, + FALSE + ); + } + + gBS->FreePool (LangCodes); + } + + return Status; +} + +EFI_STATUS +EFIAPI +HiiResetStrings ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ) +/*++ + +Routine Description: + + This function removes any new strings that were added after the initial string export for this handle. + +Arguments: + +Returns: + +--*/ +{ + UINTN Index; + CHAR16 *LangCodes; + CHAR16 Lang[4]; + STRING_REF Reference; + CHAR16 NewString; + EFI_STATUS Status; + + Reference = 1; + NewString = 0; + + HiiGetPrimaryLanguages ( + This, + Handle, + &LangCodes + ); + + for (Index = 0; LangCodes[Index] != 0; Index += 3) { + CopyMem (Lang, &LangCodes[Index], 6); + Lang[3] = 0; + Status = HiiNewString2 ( + This, + Lang, + Handle, + &Reference, + &NewString, + TRUE + ); + + } + + gBS->FreePool (LangCodes); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiGetString ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINTN *BufferLengthTemp, + OUT EFI_STRING StringBuffer + ) +/*++ + +Routine Description: + + This function extracts a string from a package already registered with the EFI HII database. + +Arguments: + This - A pointer to the EFI_HII_PROTOCOL instance. + Handle - The HII handle on which the string resides. + Token - The string token assigned to the string. + Raw - If TRUE, the string is returned unedited in the internal storage format described + above. If false, the string returned is edited by replacing with + and by removing special characters such as the prefix. + LanguageString - Pointer to a NULL-terminated string containing a single ISO 639-2 language + identifier, indicating the language to print. If the LanguageString is empty (starts + with a NULL), the default system language will be used to determine the language. + BufferLength - Length of the StringBuffer. If the status reports that the buffer width is too + small, this parameter is filled with the length of the buffer needed. + StringBuffer - The buffer designed to receive the characters in the string. Type EFI_STRING is + defined in String. + +Returns: + EFI_INVALID_PARAMETER - If input parameter is invalid. + EFI_BUFFER_TOO_SMALL - If the *BufferLength is too small. + EFI_SUCCESS - Operation is successful. + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_STRING_PACK *StringPack; + RELOFST *StringPointer; + EFI_STATUS Status; + UINTN DataSize; + CHAR8 Lang[3]; + CHAR16 Language[3]; + UINT32 Length; + UINTN Count; + RELOFST Offset; + UINT16 *Local; + UINT16 Zero; + UINT16 Narrow; + UINT16 Wide; + UINT16 NoBreak; + BOOLEAN LangFound; + UINT16 *BufferLength = (UINT16 *) BufferLengthTemp; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + LangFound = TRUE; + + DataSize = sizeof (Lang); + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + PackageInstance = NULL; + Zero = 0; + Narrow = NARROW_CHAR; + Wide = WIDE_CHAR; + NoBreak = NON_BREAKING_CHAR; + + // + // Check numeric value against the head of the database + // + for (HandleDatabase = HiiData->DatabaseHead; + 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; + } + + Status = ValidatePack (This, PackageInstance, &StringPackageInstance, NULL); + + // + // If there is no specified language, assume the system default language + // + if (LanguageString == NULL) { + // + // Get system default language + // + Status = gRT->GetVariable ( + (CHAR16 *) L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + Lang + ); + + if (EFI_ERROR (Status)) { + // + // If Lang doesn't exist, just use the first language you find + // + LangFound = FALSE; + goto LangNotFound; + } + // + // Convert the ASCII Lang variable to a Unicode Language variable + // + AsciiToUnicode ((UINT8 *)Lang, Language); + } else { + // + // Copy input ISO value to Language variable + // + CopyMem (Language, LanguageString, 6); + } + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // +LangNotFound: + if (StringPackageInstance->IfrSize > 0) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize); + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + } + // + // If Token is 0, extract entire string package + // + if (Token == 0) { + // + // Compute the entire string pack length, including all languages' and the terminating pack's. + // + Length = 0; + while (0 != StringPack->Header.Length) { + Length += StringPack->Header.Length; + StringPack = (VOID*)(((UINT8*)StringPack) + StringPack->Header.Length); + } + // + // Back to the start of package. + // + StringPack = (VOID*)(((UINT8*)StringPack) - Length); + // + // Terminating zero sub-pack. + // + Length += sizeof (EFI_HII_STRING_PACK); + + // + // If trying to get the entire string package and have insufficient space. Return error. + // + if (Length > *BufferLength || StringBuffer == NULL) { + *BufferLength = (UINT16)Length; + return EFI_BUFFER_TOO_SMALL; + } + // + // Copy the Pack to the caller's buffer. + // + *BufferLength = (UINT16)Length; + CopyMem (StringBuffer, StringPack, Length); + + return EFI_SUCCESS; + } + // + // There may be multiple instances packed together of strings + // so we must walk the self describing structures until we encounter + // what we are looking for, and then extract the string we are looking for + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (; Length != 0;) { + // + // If passed in Language ISO value is in this string pack's language string + // then we are dealing with the strings we want. + // + CopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST)); + Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language); + + // + // If we cannot find the lang variable, we skip this check and use the first language available + // + if (LangFound) { + if (EFI_ERROR (Status)) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + continue; + } + } + + StringPointer = (RELOFST *) (StringPack + 1); + + // + // We have the right string package - size it, and copy it to the StringBuffer + // + if (Token >= StringPack->NumStringPointers) { + return EFI_INVALID_PARAMETER; + } else { + CopyMem (&Offset, &StringPointer[Token], sizeof (RELOFST)); + } + // + // Since StringPack is a packed structure, we need to determine the string's + // size safely, thus byte-wise. Post-increment the size to include the null-terminator + // + Local = (UINT16 *) ((CHAR8 *) (StringPack) + Offset); + for (Count = 0; CompareMem (&Local[Count], &Zero, 2); Count++) + ; + Count++; + + Count = Count * sizeof (CHAR16);; + + if (*BufferLength >= Count && StringBuffer != NULL) { + // + // Copy the string to the user's buffer + // + if (Raw) { + CopyMem (StringBuffer, Local, Count); + } else { + for (Count = 0; CompareMem (Local, &Zero, 2); Local++) { + // + // Skip "Narraw, Wide, NoBreak" + // + if (CompareMem (Local, &Narrow, 2) && + CompareMem (Local, &Wide, 2) && + CompareMem (Local, &NoBreak, 2)) { + CopyMem (&StringBuffer[Count++], Local, 2); + } + } + // + // Add "NULL" at the end. + // + CopyMem (&StringBuffer[Count], &Zero, 2); + Count++; + Count *= sizeof (CHAR16); + } + + *BufferLength = (UINT16) Count; + return EFI_SUCCESS; + } else { + *BufferLength = (UINT16) Count; + return EFI_BUFFER_TOO_SMALL; + } + + } + + LangFound = FALSE; + goto LangNotFound; +} + +EFI_STATUS +EFIAPI +HiiGetLine ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN OUT UINT16 *Index, + IN UINT16 LineWidth, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, + OUT EFI_STRING StringBuffer + ) +/*++ + +Routine Description: + + This function allows a program to extract a part of a string of not more than a given width. + With repeated calls, this allows a calling program to extract "lines" of text that fit inside + columns. The effort of measuring the fit of strings inside columns is localized to this call. + +Arguments: + +Returns: + +--*/ +{ + UINTN Count; + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_STRING_PACK *StringPack; + RELOFST *StringPointer; + CHAR16 *Location; + EFI_STATUS Status; + UINTN DataSize; + CHAR8 Lang[3]; + CHAR16 Language[3]; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + + PackageInstance = NULL; + DataSize = 4; + + // + // 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; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = ValidatePack (This, PackageInstance, &StringPackageInstance, NULL); + + // + // If there is no specified language, assume the system default language + // + if (LanguageString == NULL) { + // + // Get system default language + // + Status = gRT->GetVariable ( + (CHAR16 *) L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + Lang + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Convert the ASCII Lang variable to a Unicode Language variable + // + AsciiToUnicode ((UINT8 *)Lang, Language); + } else { + // + // Copy input ISO value to Language variable + // + CopyMem (Language, LanguageString, 6); + } + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize); + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + } + + StringPointer = (RELOFST *) (StringPack + 1); + + // + // There may be multiple instances packed together of strings + // so we must walk the self describing structures until we encounter + // what we are looking for, and then extract the string we are looking for + // + for (; StringPack->Header.Length != 0;) { + // + // If passed in Language ISO value is in this string pack's language string + // then we are dealing with the strings we want. + // + Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language); + + if (EFI_ERROR (Status)) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length); + continue; + } + + Location = (CHAR16 *) ((CHAR8 *) (StringPack) + StringPointer[Token] +*Index * 2); + + // + // If the size of the remaining string is less than the LineWidth + // then copy the entire thing + // + if (StrSize (Location) <= LineWidth) { + if (*BufferLength >= StrSize (Location)) { + StrCpy (StringBuffer, Location); + return EFI_SUCCESS; + } else { + *BufferLength = (UINT16) StrSize (Location); + return EFI_BUFFER_TOO_SMALL; + } + } else { + // + // Rewind the string from the maximum size until we see a space the break the line + // + for (Count = LineWidth; Location[Count] != 0x0020; Count--) + ; + + // + // Put the index at the next character + // + *Index = (UINT16) (Count + 1); + + if (*BufferLength >= Count) { + StrnCpy (StringBuffer, Location, Count); + return EFI_SUCCESS; + } else { + *BufferLength = (UINT16) Count; + return EFI_BUFFER_TOO_SMALL; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +HiiCompareLanguage ( + IN CHAR16 *LanguageStringLocation, + IN CHAR16 *Language + ) +{ + UINT8 *Local; + UINTN Index; + CHAR16 *InputString; + CHAR16 *OriginalInputString; + + // + // Allocate a temporary buffer for InputString + // + InputString = AllocateZeroPool (0x100); + + ASSERT (InputString); + + OriginalInputString = InputString; + + Local = (UINT8 *) LanguageStringLocation; + + // + // Determine the size of this packed string safely (e.g. access by byte), post-increment + // to include the null-terminator + // + for (Index = 0; Local[Index] != 0; Index = Index + 2) + ; + // + // MARMAR Index = Index + 2; + // + // This is a packed structure that this location comes from, so let's make sure + // the value is aligned by copying it to a local variable and working on it. + // + CopyMem (InputString, LanguageStringLocation, Index); + + for (Index = 0; Index < 3; Index++) { + InputString[Index] = (CHAR16) (InputString[Index] | 0x20); + Language[Index] = (CHAR16) (Language[Index] | 0x20); + } + // + // If the Language is the same return success + // + if (CompareMem (LanguageStringLocation, Language, 6) == 0) { + gBS->FreePool (InputString); + return EFI_SUCCESS; + } + // + // Skip the first three letters that comprised the primary language, + // see if what is being compared against is a secondary language + // + InputString = InputString + 3; + + // + // If the Language is not the same as the Primary language, see if there are any + // secondary languages, and if there are see if we have a match. If not, return an error. + // + for (Index = 0; InputString[Index] != 0; Index = Index + 3) { + // + // Getting in here means we have a secondary language + // + if (CompareMem (&InputString[Index], Language, 6) == 0) { + gBS->FreePool (InputString); + return EFI_SUCCESS; + } + } + // + // If nothing was found, return the error + // + gBS->FreePool (OriginalInputString); + return EFI_NOT_FOUND; + +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/build.xml b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/build.xml new file mode 100644 index 0000000000..7ffdb7c013 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3