diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib | |
download | zprj-master.tar.xz |
Diffstat (limited to 'EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib')
9 files changed, 5908 insertions, 0 deletions
diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.cif b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.cif new file mode 100644 index 0000000..7a843fc --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.cif @@ -0,0 +1,15 @@ +<component> + name = "UefiEfiIfrSupportLib" + category = ModulePart + LocalRoot = "EDK\Foundation\Library\Dxe\UefiEfiIfrSupportLib\" + RefName = "UefiEfiIfrSupportLib" +[files] +"UefiEfiIfrSupportLib.sdl" +"UefiEfiIfrSupportLib.mak" +"UefiIfrCommon.c" +"UefiIfrForm.c" +"UefiIfrLibrary.h" +"UefiIfrOpCodeCreation.c" +"UefiIfrString.c" +"UefiEfiIfrSupportLib.inf" +<endComponent> diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.inf b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.inf new file mode 100644 index 0000000..cc26951 --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.inf @@ -0,0 +1,49 @@ +#/*++ +# +# Copyright (c) 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# UfiIfrSupportLib.inf +# +# Abstract: +# +# Component description file. +# +#--*/ + +[defines] +BASE_NAME = UefiEfiIfrSupportLib +COMPONENT_TYPE = LIBRARY + +[sources.common] + UefiIfrCommon.c + UefiIfrForm.c + UefiIfrString.c + UefiIfrOpCodeCreation.c + UefiIfrLibrary.h + +[includes.common] + $(EDK_SOURCE)\Foundation\Efi + $(EDK_SOURCE)\Foundation\Framework + $(EDK_SOURCE)\Foundation + . + $(EDK_SOURCE)\Foundation\Include + $(EDK_SOURCE)\Foundation\Efi\Include + $(EDK_SOURCE)\Foundation\Framework\Include + $(EDK_SOURCE)\Foundation\Include\IndustryStandard + $(EDK_SOURCE)\Foundation\Core\Dxe + $(EDK_SOURCE)\Foundation\Library\Dxe\Include + +[libraries.common] + EfiGuidLib + EdkFrameworkProtocolLib + +[nmake.common] diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.mak b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.mak new file mode 100644 index 0000000..991cd72 --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.mak @@ -0,0 +1,70 @@ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2009, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#********************************************************************** + +#********************************************************************** +# $Header: /Alaska/SOURCE/Modules/SharkBayRefCodes/IntelEDK/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.mak 1 1/20/12 4:13a Jeffch $ +# +# $Revision: 1 $ +# +# $Date: 1/20/12 4:13a $ +#********************************************************************** +# Revision History +# ---------------- +# $Log: /Alaska/SOURCE/Modules/SharkBayRefCodes/IntelEDK/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.mak $ +# +# 1 1/20/12 4:13a Jeffch +# Create Intel EDK 1117 Patch 7. +# +# 1 9/27/11 6:35a Wesleychen +# Intel EDK initially releases. +# +# 2 9/02/09 3:55a Iminglin +# EIP24919 +# +#********************************************************************** +#********************************************************************** +#<AMI_FHDR_START> +# +# Name: UefiEfiIfrSupportLib.mak +# +# Description: +# +#<AMI_FHDR_END> +#********************************************************************** +$(UEFIEFIIFRSUPPORTLIB) : UefiEfiIfrSupportLib + +$(BUILD_DIR)\UefiEfiIfrSupportLib.lib : UefiEfiIfrSupportLib + +UefiEfiIfrSupportLib : $(BUILD_DIR)\UefiEfiIfrSupportLib.mak UefiEfiIfrSupportLibBin + +$(BUILD_DIR)\UefiEfiIfrSupportLib.mak : $(UefiEfiIfrSupportLib_DIR)\$(@B).cif $(UefiEfiIfrSupportLib_DIR)\$(@B).mak $(BUILD_RULES) + $(CIF2MAK) $(UefiEfiIfrSupportLib_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS) + +UefiEfiIfrSupportLibBin : $(EFIGUIDLIB) $(EDKFRAMEWORKPROTOCOLLIB) + $(MAKE) /$(MAKEFLAGS) $(EDK_DEFAULTS)\ + /f $(BUILD_DIR)\UefiEfiIfrSupportLib.mak all\ + TYPE=LIBRARY \ +#********************************************************************** +#********************************************************************** +#** ** +#** (C)Copyright 1985-2009, American Megatrends, Inc. ** +#** ** +#** All Rights Reserved. ** +#** ** +#** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** +#** ** +#** Phone: (770)-246-8600 ** +#** ** +#********************************************************************** +#**********************************************************************
\ No newline at end of file diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.sdl b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.sdl new file mode 100644 index 0000000..f7135b8 --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiEfiIfrSupportLib.sdl @@ -0,0 +1,26 @@ +TOKEN + Name = "UefiEfiIfrSupportLib_SUPPORT" + Value = "1" + Help = "Main switch to enable UefiEfiIfrSupportLib support in Project" + TokenType = Boolean + TargetEQU = Yes + TargetMAK = Yes + Master = Yes +End + +TOKEN + Name = "UEFIEFIIFRSUPPORTLIB" + Value = "$(BUILD_DIR)\UefiEfiIfrSupportLib.lib" + TokenType = Expression + TargetMAK = Yes +End + +PATH + Name = "UefiEfiIfrSupportLib_DIR" +End + +MODULE + Help = "Includes UefiEfiIfrSupportLib.mak to Project" + File = "UefiEfiIfrSupportLib.mak" +End + diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrCommon.c b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrCommon.c new file mode 100644 index 0000000..d2a66e0 --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrCommon.c @@ -0,0 +1,762 @@ +/*++ + +Copyright (c) 2007 - 2011, 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: + + UefiIfrCommon.c + +Abstract: + + Common Library Routines to assist handle HII elements. + +--*/ + +#include "UefiIfrLibrary.h" + +// +// Hii vendor device path template +// +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePathTemplate = { + { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (HII_VENDOR_DEVICE_PATH_NODE)), + (UINT8) ((sizeof (HII_VENDOR_DEVICE_PATH_NODE)) >> 8) + }, + EFI_IFR_TIANO_GUID, + }, + 0, + 0 + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + END_DEVICE_PATH_LENGTH, + 0 + } +}; + +// +// Hii relative protocols +// +BOOLEAN mHiiProtocolsInitialized = FALSE; + +EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase; +EFI_HII_STRING_PROTOCOL *gIfrLibHiiString; + +VOID +LocateHiiProtocols ( + VOID + ) +/*++ + +Routine Description: + This function locate Hii relative protocols for later usage. + +Arguments: + None. + +Returns: + None. + +--*/ +{ + EFI_STATUS Status; + + if (mHiiProtocolsInitialized) { + return; + } + + Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &gIfrLibHiiDatabase); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, &gIfrLibHiiString); + ASSERT_EFI_ERROR (Status); + + mHiiProtocolsInitialized = TRUE; +} + +EFI_HII_PACKAGE_LIST_HEADER * +PreparePackageList ( + IN UINTN NumberOfPackages, + IN EFI_GUID *GuidId, + ... + ) +/*++ + +Routine Description: + Assemble EFI_HII_PACKAGE_LIST according to the passed in packages. + +Arguments: + NumberOfPackages - Number of packages. + GuidId - Package GUID. + +Returns: + Pointer of EFI_HII_PACKAGE_LIST_HEADER. + +--*/ +{ + VA_LIST Marker; + EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; + UINT8 *PackageListData; + UINT32 PackageListLength; + UINT32 PackageLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + UINT8 *PackageArray; + UINTN Index; + + PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + + VA_START (Marker, GuidId); + for (Index = 0; Index < NumberOfPackages; Index++) { + EfiCopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32)); + PackageListLength += (PackageLength - sizeof (UINT32)); + } + VA_END (Marker); + + // + // Include the lenght of EFI_HII_PACKAGE_END + // + PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER); + PackageListHeader = EfiLibAllocateZeroPool (PackageListLength); + ASSERT (PackageListHeader != NULL); + EfiCopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID)); + PackageListHeader->PackageLength = PackageListLength; + + PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER); + + VA_START (Marker, GuidId); + for (Index = 0; Index < NumberOfPackages; Index++) { + PackageArray = (UINT8 *) VA_ARG (Marker, VOID *); + EfiCopyMem (&PackageLength, PackageArray, sizeof (UINT32)); + PackageLength -= sizeof (UINT32); + PackageArray += sizeof (UINT32); + EfiCopyMem (PackageListData, PackageArray, PackageLength); + PackageListData += PackageLength; + } + VA_END (Marker); + + // + // Append EFI_HII_PACKAGE_END + // + PackageHeader.Type = EFI_HII_PACKAGE_END; + PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER); + EfiCopyMem (PackageListData, &PackageHeader, PackageHeader.Length); + + return PackageListHeader; +} + +EFI_STATUS +CreateHiiDriverHandle ( + OUT EFI_HANDLE *DriverHandle + ) +/*++ + +Routine Description: + The HII driver handle passed in for HiiDatabase.NewPackageList() requires + that there should be DevicePath Protocol installed on it. + This routine create a virtual Driver Handle by installing a vendor device + path on it, so as to use it to invoke HiiDatabase.NewPackageList(). + +Arguments: + DriverHandle - Handle to be returned + +Returns: + EFI_SUCCESS - Handle destroy success. + EFI_OUT_OF_RESOURCES - Not enough memory. + +--*/ +{ + EFI_STATUS Status; + HII_VENDOR_DEVICE_PATH_NODE *VendorDevicePath; + + VendorDevicePath = EfiLibAllocateCopyPool (sizeof (HII_VENDOR_DEVICE_PATH), &mHiiVendorDevicePathTemplate); + if (VendorDevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Use memory address as unique ID to distinguish from different device paths + // + VendorDevicePath->UniqueId = (UINT64) ((UINTN) VendorDevicePath); + + *DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + VendorDevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DestroyHiiDriverHandle ( + IN EFI_HANDLE DriverHandle + ) +/*++ + +Routine Description: + Destroy the Driver Handle created by CreateHiiDriverHandle(). + +Arguments: + DriverHandle - Handle returned by CreateHiiDriverHandle() + +Returns: + EFI_SUCCESS - Handle destroy success. + other - Handle destroy fail. + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + &DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->UninstallProtocolInterface ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + DevicePath + ); + gBS->FreePool (DevicePath); + return Status; +} + +EFI_HII_HANDLE +DevicePathToHiiHandle ( + IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Find HII Handle associated with given Device Path. + +Arguments: + HiiDatabase - Point to EFI_HII_DATABASE_PROTOCOL instance. + DevicePath - Device Path associated with the HII package list handle. + +Returns: + Handle - HII package list Handle associated with the Device Path. + NULL - Hii Package list handle is not found. + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + UINTN BufferSize; + UINTN HandleCount; + UINTN Index; + EFI_HANDLE *Handles; + EFI_HANDLE Handle; + UINTN Size; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE *HiiHandles; + EFI_HII_HANDLE HiiHandle; + + // + // Locate Device Path Protocol handle buffer + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Search Driver Handle by Device Path + // + DriverHandle = NULL; + BufferSize = EfiDevicePathSize (DevicePath); + for(Index = 0; Index < HandleCount; Index++) { + Handle = Handles[Index]; + gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, &TmpDevicePath); + + // + // Check whether DevicePath match + // + Size = EfiDevicePathSize (TmpDevicePath); + if ((Size == BufferSize) && EfiCompareMem (DevicePath, TmpDevicePath, Size) == 0) { + DriverHandle = Handle; + break; + } + } + gBS->FreePool (Handles); + + if (DriverHandle == NULL) { + return NULL; + } + + // + // Retrieve all Hii Handles from HII database + // + BufferSize = 0x1000; + HiiHandles = EfiLibAllocatePool (BufferSize); + ASSERT (HiiHandles != NULL); + Status = HiiDatabase->ListPackageLists ( + HiiDatabase, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferSize, + HiiHandles + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + gBS->FreePool (HiiHandles); + HiiHandles = EfiLibAllocatePool (BufferSize); + ASSERT (HiiHandles != NULL); + + Status = HiiDatabase->ListPackageLists ( + HiiDatabase, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferSize, + HiiHandles + ); + } + + if (EFI_ERROR (Status)) { + gBS->FreePool (HiiHandles); + return NULL; + } + + // + // Search Hii Handle by Driver Handle + // + HiiHandle = NULL; + HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); + for (Index = 0; Index < HandleCount; Index++) { + Status = HiiDatabase->GetPackageListHandle ( + HiiDatabase, + HiiHandles[Index], + &Handle + ); + if (!EFI_ERROR (Status) && (Handle == DriverHandle)) { + HiiHandle = HiiHandles[Index]; + break; + } + } + + gBS->FreePool (HiiHandles); + return HiiHandle; +} + +EFI_STATUS +GetHiiHandles ( + IN OUT UINTN *HandleBufferLength, + OUT EFI_HII_HANDLE **HiiHandleBuffer + ) +/*++ + +Routine Description: + Determines the handles that are currently active in the database. + It's the caller's responsibility to free handle buffer. + +Arguments: + HiiDatabase - A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + HandleBufferLength - On input, a pointer to the length of the handle buffer. On output, + the length of the handle buffer that is required for the handles found. + HiiHandleBuffer - Pointer to an array of Hii Handles returned. + +Returns: + EFI_SUCCESS - Get an array of Hii Handles successfully. + EFI_INVALID_PARAMETER - Hii is NULL. + EFI_NOT_FOUND - Database not found. + +--*/ +{ + UINTN BufferLength; + EFI_STATUS Status; + + BufferLength = 0; + + LocateHiiProtocols (); + + // + // Try to find the actual buffer size for HiiHandle Buffer. + // + Status = gIfrLibHiiDatabase->ListPackageLists ( + gIfrLibHiiDatabase, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferLength, + *HiiHandleBuffer + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + *HiiHandleBuffer = EfiLibAllocateZeroPool (BufferLength); + Status = gIfrLibHiiDatabase->ListPackageLists ( + gIfrLibHiiDatabase, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferLength, + *HiiHandleBuffer + ); + // + // we should not fail here. + // + ASSERT_EFI_ERROR (Status); + } + + *HandleBufferLength = BufferLength; + + return Status; +} + +EFI_STATUS +ExtractGuidFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + OUT EFI_GUID *Guid + ) +/*++ + +Routine Description: + Extract Hii package list GUID for given HII handle. + +Arguments: + HiiHandle - Hii handle + Guid - Package list GUID + +Returns: + EFI_SUCCESS - Successfully extract GUID from Hii database. + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + + // + // Locate HII Database protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiDatabaseProtocolGuid, + NULL, + &HiiDatabase + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get HII PackageList + // + BufferSize = 0; + HiiPackageList = NULL; + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); + if (Status == EFI_BUFFER_TOO_SMALL) { + HiiPackageList = EfiLibAllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Extract GUID + // + EfiCopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID)); + + gBS->FreePool (HiiPackageList); + + return EFI_SUCCESS; +} + +EFI_STATUS +ExtractClassFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + OUT UINT16 *Class, + OUT EFI_STRING_ID *FormSetTitle, + OUT EFI_STRING_ID *FormSetHelp + ) +/*++ + +Routine Description: + Extract formset class for given HII handle. + +Arguments: + HiiHandle - Hii handle + Class - Class of the formset + FormSetTitle - Formset title string + FormSetHelp - Formset help string + +Returns: + EFI_SUCCESS - Successfully extract Class for specified Hii handle. + EFI_NOT_FOUND - Class not found. + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINT8 *Package; + UINT8 *FormSet; + UINT8 *OpCodeData; + UINT32 Offset; + UINT32 Offset2; + UINT32 PackageListLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + BOOLEAN ClassFound; + + *Class = EFI_NON_DEVICE_CLASS; + *FormSetTitle = 0; + *FormSetHelp = 0; + ClassFound = FALSE; + + // + // Locate HII Database protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiDatabaseProtocolGuid, + NULL, + &HiiDatabase + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get HII PackageList + // + BufferSize = 0; + HiiPackageList = NULL; + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); + if (Status == EFI_BUFFER_TOO_SMALL) { + HiiPackageList = EfiLibAllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get Form package from this HII package List + // + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + Offset2 = 0; + FormSet = NULL; + EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); + + while (Offset < PackageListLength) { + Package = ((UINT8 *) HiiPackageList) + Offset; + EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + + if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { + // + // Search Class Opcode in this Form Package + // + Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); + while (Offset2 < PackageHeader.Length) { + OpCodeData = Package + Offset2; + if (OpCodeData == NULL) { + return EFI_NOT_FOUND; + } + + if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { + // + // Find FormSet OpCode + // + EfiCopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); + EfiCopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); + } + + if ((((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_GUID_OP) && + (EfiCompareGuid (&mIfrVendorGuid, &((EFI_IFR_GUID *) OpCodeData)->Guid)) && + (((EFI_IFR_GUID_CLASS *) OpCodeData)->ExtendOpCode == EFI_IFR_EXTEND_OP_CLASS) + ) { + // + // Find GUIDed Class OpCode + // + EfiCopyMem (Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16)); + + // + // Till now, we ought to have found the formset Opcode + // + ClassFound = TRUE; + break; + } + + Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + } + + if (Offset2 < PackageHeader.Length) { + // + // Target formset found + // + break; + } + } + + Offset += PackageHeader.Length; + } + + gBS->FreePool (HiiPackageList); + + return ClassFound ? EFI_SUCCESS : EFI_NOT_FOUND; +} + +EFI_STATUS +ExtractClassGuidFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + OUT UINT8 *NumberOfClassGuid, + OUT EFI_GUID **ClassGuid, + OUT EFI_STRING_ID *FormSetTitle, + OUT EFI_STRING_ID *FormSetHelp + ) +/*++ + +Routine Description: + Extract formset ClassGuid for given HII handle. + +Arguments: + HiiHandle - Hii handle + NumberOfClassGuid - Number of ClassGuid + ClassGuid - Pointer to callee allocated buffer, an array of ClassGuid + FormSetTitle - Formset title string + FormSetHelp - Formset help string + +Returns: + EFI_SUCCESS - Successfully extract Class for specified Hii handle. + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINT8 *Package; + UINT8 *FormSet; + UINT8 *OpCodeData; + UINT32 Offset; + UINT32 Offset2; + UINT32 PackageListLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + + if (NumberOfClassGuid == NULL || ClassGuid == NULL || FormSetTitle == NULL || FormSetHelp == NULL) { + return EFI_INVALID_PARAMETER; + } + + *NumberOfClassGuid = 0; + *ClassGuid = NULL; + *FormSetTitle = 0; + *FormSetHelp = 0; + + // + // Locate HII Database protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiDatabaseProtocolGuid, + NULL, + &HiiDatabase + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get HII PackageList + // + BufferSize = 0; + HiiPackageList = NULL; + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); + if (Status == EFI_BUFFER_TOO_SMALL) { + HiiPackageList = EfiLibAllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); + } + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get Form package from this HII package List + // + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + Offset2 = 0; + FormSet = NULL; + EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); + + while (Offset < PackageListLength) { + Package = ((UINT8 *) HiiPackageList) + Offset; + EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + + if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) { + // + // Search Class Opcode in this Form Package + // + Offset2 = sizeof (EFI_HII_PACKAGE_HEADER); + while (Offset2 < PackageHeader.Length) { + OpCodeData = Package + Offset2; + if (OpCodeData == NULL) { + return EFI_NOT_FOUND; + } + + if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) { + // + // Find FormSet OpCode + // + EfiCopyMem (FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID)); + EfiCopyMem (FormSetHelp, &((EFI_IFR_FORM_SET *) OpCodeData)->Help, sizeof (EFI_STRING_ID)); + if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length > ((UINTN) &((EFI_IFR_FORM_SET *) 0)->Flags)) { + // + // New version of formset OpCode + // + *NumberOfClassGuid = ((EFI_IFR_FORM_SET *) OpCodeData)->Flags & 0x3; + *ClassGuid = EfiLibAllocateCopyPool ( + *NumberOfClassGuid * sizeof (EFI_GUID), + ((EFI_IFR_FORM_SET *) OpCodeData)->ClassGuid + ); + } + break; + } + + Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + } + + if (Offset2 < PackageHeader.Length) { + // + // Target formset found + // + break; + } + } + + Offset += PackageHeader.Length; + } + + gBS->FreePool (HiiPackageList); + + return EFI_SUCCESS; +} diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrForm.c b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrForm.c new file mode 100644 index 0000000..0fe6582 --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrForm.c @@ -0,0 +1,2249 @@ +/*++ + +Copyright (c) 2007 - 2008, 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: + + UefiIfrForm.c + +Abstract: + + Common Library Routines to assist handle HII elements. + +--*/ + +#include "UefiIfrLibrary.h" + +// +// Fake <ConfigHdr> +// +UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0"; + +STATIC +EFI_STATUS +GetPackageDataFromPackageList ( + IN EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList, + IN UINT32 PackageIndex, + OUT UINT32 *BufferLen, + OUT EFI_HII_PACKAGE_HEADER **Buffer + ) +{ + UINT32 Index; + EFI_HII_PACKAGE_HEADER *Package; + UINT32 Offset; + UINT32 PackageListLength; + EFI_HII_PACKAGE_HEADER PackageHeader = {0, 0}; + + ASSERT(HiiPackageList != NULL); + + if ((BufferLen == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Package = NULL; + Index = 0; + Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + EfiCopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32)); + while (Offset < PackageListLength) { + Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset); + EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + if (Index == PackageIndex) { + break; + } + Offset += PackageHeader.Length; + Index++; + } + if (Offset >= PackageListLength) { + // + // no package found in this Package List + // + return EFI_NOT_FOUND; + } + + *BufferLen = PackageHeader.Length; + *Buffer = Package; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +UpdateFormPackageData ( + IN EFI_GUID *FormSetGuid, + IN EFI_FORM_ID FormId, + IN EFI_HII_PACKAGE_HEADER *Package, + IN UINT32 PackageLength, + IN UINT16 Label, + IN BOOLEAN Insert, + IN EFI_HII_UPDATE_DATA *Data, + OUT UINT8 **TempBuffer, + OUT UINT32 *TempBufferSize + ) +{ + UINT8 *BufferPos; + EFI_HII_PACKAGE_HEADER PackageHeader; + UINT32 Offset; + EFI_IFR_OP_HEADER *IfrOpHdr; + BOOLEAN GetFormSet; + BOOLEAN GetForm; + UINT8 ExtendOpCode; + UINT16 LabelNumber; + BOOLEAN Updated; + + if ((TempBuffer == NULL) || (TempBufferSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *TempBufferSize = PackageLength; + if (Data != NULL) { + *TempBufferSize += Data->Offset; + } + *TempBuffer = EfiLibAllocateZeroPool (*TempBufferSize); + if (*TempBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + EfiCopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER); + BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER); + + EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + IfrOpHdr = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER)); + Offset = sizeof (EFI_HII_PACKAGE_HEADER); + GetFormSet = (FormSetGuid == NULL) ? TRUE : FALSE; + GetForm = FALSE; + Updated = FALSE; + + while (!Updated && Offset < PackageHeader.Length) { + EfiCopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length); + BufferPos += IfrOpHdr->Length; + *TempBufferSize += IfrOpHdr->Length; + + switch (IfrOpHdr->OpCode) { + case EFI_IFR_FORM_SET_OP : + if (FormSetGuid != NULL) { + if (EfiCompareMem (&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid, sizeof (EFI_GUID)) == 0) { + GetFormSet = TRUE; + } else { + GetFormSet = FALSE; + } + } + break; + + case EFI_IFR_FORM_OP: + if (EfiCompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) { + GetForm = TRUE; + } else { + GetForm = FALSE; + } + break; + + case EFI_IFR_GUID_OP : + if (!GetFormSet || !GetForm) { + // + // Go to the next Op-Code + // + break; + } + + if (!EfiCompareGuid (&((EFI_IFR_GUID *) IfrOpHdr)->Guid, &mIfrVendorGuid)) { + // + // GUID mismatch, skip this op-code + // + break; + } + + ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode; + EfiCopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16)); + if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label)) { + // + // Go to the next Op-Code + // + break; + } + + if (Insert) { + // + // Insert data after current Label, skip myself + // + Offset += IfrOpHdr->Length; + IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length); + } else { + // + // Replace data between two paired Label, try to find the next Label. + // + while (TRUE) { + Offset += IfrOpHdr->Length; + // + // Search the next label and Fail if not label found. + // + if (Offset >= PackageHeader.Length) { + goto Fail; + } + IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length); + if (IfrOpHdr->OpCode == EFI_IFR_GUID_OP) { + ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode; + if (EfiCompareGuid (&((EFI_IFR_GUID *) IfrOpHdr)->Guid, &mIfrVendorGuid) && ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) { + break; + } + } + } + } + + // + // Fill in the update data + // + if (Data != NULL) { + EfiCopyMem (BufferPos, Data->Data, Data->Offset); + BufferPos += Data->Offset; + *TempBufferSize += Data->Offset; + } + + // + // Copy the reset data + // + EfiCopyMem (BufferPos, IfrOpHdr, PackageHeader.Length - Offset); + *TempBufferSize += PackageHeader.Length - Offset; + + Updated = TRUE; + break; + default : + break; + } + + // + // Go to the next Op-Code + // + Offset += IfrOpHdr->Length; + IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length); + } + + // + // Update the package length. + // + PackageHeader.Length = *TempBufferSize; + EfiCopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER)); + +Fail: + if (!Updated) { + gBS->FreePool (*TempBuffer); + *TempBufferSize = 0; + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +IfrLibInitUpdateData ( + IN OUT EFI_HII_UPDATE_DATA *UpdateData, + IN UINT32 BufferSize + ) +/*++ + +Routine Description: + This function initialize the data structure for dynamic opcode. + +Arguments: + UpdateData - The adding data; + BufferSize - Length of the buffer to fill dynamic opcodes. + +Returns: + EFI_SUCCESS - Update data is initialized. + EFI_INVALID_PARAMETER - UpdateData is NULL. + EFI_OUT_OF_RESOURCES - No enough memory to allocate. + +--*/ +{ + if (UpdateData == NULL) { + return EFI_INVALID_PARAMETER; + } + + UpdateData->BufferSize = BufferSize; + UpdateData->Offset = 0; + UpdateData->Data = EfiLibAllocatePool (BufferSize); + + return (UpdateData->Data != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES; +} + +EFI_STATUS +IfrLibFreeUpdateData ( + IN EFI_HII_UPDATE_DATA *UpdateData + ) +/*++ + +Routine Description: + This function free the resource of update data. + +Arguments: + UpdateData - The adding data; + +Returns: + EFI_SUCCESS - Resource in UpdateData is released. + EFI_INVALID_PARAMETER - UpdateData is NULL. + +--*/ +{ + EFI_STATUS Status; + + if (UpdateData == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->FreePool (UpdateData->Data); + UpdateData->Data = NULL; + + return Status; +} + +EFI_STATUS +IfrLibUpdateForm ( + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *FormSetGuid, OPTIONAL + IN EFI_FORM_ID FormId, + IN UINT16 Label, + IN BOOLEAN Insert, + 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 + FormSetGuid - The formset should be updated. + FormId - The form should be updated. + Label - Update information starting immediately after this label in the IFR + Insert - If TRUE and Data is not NULL, insert data after Label. + If FALSE, replace opcodes between two labels with Data + Data - The adding data; If NULL, remove opcodes between two Label. + +Returns: + EFI_SUCCESS - Update success. + Other - Update fail. + +--*/ +{ + EFI_STATUS Status; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINT32 Index; + EFI_HII_PACKAGE_LIST_HEADER *UpdateBuffer; + UINTN BufferSize; + UINT8 *UpdateBufferPos; + EFI_HII_PACKAGE_HEADER PackageHeader; + EFI_HII_PACKAGE_HEADER *Package; + UINT32 PackageLength; + EFI_HII_PACKAGE_HEADER *TempBuffer; + UINT32 TempBufferSize; + BOOLEAN Updated; + + if (Data == NULL) { + return EFI_INVALID_PARAMETER; + } + + LocateHiiProtocols (); + HiiDatabase = gIfrLibHiiDatabase; + + // + // Get the orginal package list + // + BufferSize = 0; + HiiPackageList = NULL; + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); + if (Status == EFI_BUFFER_TOO_SMALL) { + HiiPackageList = EfiLibAllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList); + if (EFI_ERROR (Status)) { + gBS->FreePool (HiiPackageList); + return Status; + } + } + + // + // Calculate and allocate space for retrieval of IFR data + // + BufferSize += Data->Offset; + UpdateBuffer = EfiLibAllocateZeroPool (BufferSize); + if (UpdateBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + UpdateBufferPos = (UINT8 *) UpdateBuffer; + + // + // copy the package list header + // + EfiCopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER)); + UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER); + + Updated = FALSE; + for (Index = 0; ; Index++) { + Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package); + if (Status == EFI_SUCCESS) { + EfiCopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER)); + if ((PackageHeader.Type == EFI_HII_PACKAGE_FORMS) && !Updated) { + Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize); + if (!EFI_ERROR(Status)) { + if (FormSetGuid == NULL) { + Updated = TRUE; + } + EfiCopyMem (UpdateBufferPos, TempBuffer, TempBufferSize); + UpdateBufferPos += TempBufferSize; + gBS->FreePool (TempBuffer); + continue; + } + } + + EfiCopyMem (UpdateBufferPos, Package, PackageLength); + UpdateBufferPos += PackageLength; + } else if (Status == EFI_NOT_FOUND) { + break; + } else { + gBS->FreePool (HiiPackageList); + return Status; + } + } + + // + // Update package list length + // + BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer; + EfiCopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32)); + + gBS->FreePool (HiiPackageList); + + return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer); +} + +EFI_STATUS +IfrLibCreatePopUp ( + IN UINTN NumberOfLines, + OUT EFI_INPUT_KEY *KeyValue, + IN CHAR16 *String, + ... + ) +/*++ + +Routine Description: + Draw a dialog and return the selected key. + +Arguments: + NumberOfLines - The number of lines for the dialog box + KeyValue - The EFI_KEY value returned if HotKey is TRUE.. + String - Pointer to the first string in the list + ... - A series of (quantity == NumberOfLines) text strings which + will be used to construct the dialog box + +Returns: + EFI_SUCCESS - Displayed dialog and received user interaction + EFI_INVALID_PARAMETER - One of the parameters was invalid. + +--*/ +{ + UINTN Index; + UINTN Count; + UINTN Start; + UINTN End; + UINTN Top; + UINTN Bottom; + CHAR16 *StringPtr; + UINTN LeftColumn; + UINTN RightColumn; + UINTN TopRow; + UINTN BottomRow; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + VA_LIST Marker; + EFI_INPUT_KEY Key; + UINTN LargestString; + CHAR16 *StackString; + EFI_STATUS Status; + UINTN StringLen; + CHAR16 *LineBuffer; + CHAR16 **StringArray; + EFI_EVENT TimerEvent; + EFI_EVENT WaitList[2]; + UINTN CurrentAttribute; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut; + + if ((KeyValue == NULL) || (String == NULL)) { + return EFI_INVALID_PARAMETER; + } + + TopRow = 0; + BottomRow = 0; + LeftColumn = 0; + RightColumn = 0; + + ConOut = gST->ConOut; + ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow); + + DimensionsWidth = RightColumn - LeftColumn; + DimensionsHeight = BottomRow - TopRow; + + CurrentAttribute = ConOut->Mode->Attribute; + + LineBuffer = EfiLibAllocateZeroPool (DimensionsWidth * sizeof (CHAR16)); + ASSERT (LineBuffer != NULL); + + // + // Determine the largest string in the dialog box + // Notice we are starting with 1 since String is the first string + // + StringArray = EfiLibAllocateZeroPool (NumberOfLines * sizeof (CHAR16 *)); + LargestString = EfiStrLen (String); + StringArray[0] = String; + + VA_START (Marker, String); + for (Index = 1; Index < NumberOfLines; Index++) { + StackString = VA_ARG (Marker, CHAR16 *); + + if (StackString == NULL) { + return EFI_INVALID_PARAMETER; + } + + StringArray[Index] = StackString; + StringLen = EfiStrLen (StackString); + if (StringLen > LargestString) { + LargestString = StringLen; + } + } + + if ((LargestString + 2) > DimensionsWidth) { + LargestString = DimensionsWidth - 2; + } + + // + // Subtract the PopUp width from total Columns, allow for one space extra on + // each end plus a border. + // + Start = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1; + End = Start + LargestString + 1; + + Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1; + Bottom = Top + NumberOfLines + 2; + + // + // Disable cursor + // + ConOut->EnableCursor (ConOut, FALSE); + ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE); + + StringPtr = &LineBuffer[0]; + *StringPtr++ = BOXDRAW_DOWN_RIGHT; + for (Index = 0; Index < LargestString; Index++) { + *StringPtr++ = BOXDRAW_HORIZONTAL; + } + *StringPtr++ = BOXDRAW_DOWN_LEFT; + *StringPtr = L'\0'; + + ConOut->SetCursorPosition (ConOut, Start, Top); + ConOut->OutputString (ConOut, LineBuffer); + + for (Index = 0; Index < NumberOfLines; Index++) { + StringPtr = &LineBuffer[0]; + *StringPtr++ = BOXDRAW_VERTICAL; + + for (Count = 0; Count < LargestString; Count++) { + StringPtr[Count] = L' '; + } + + StringLen = EfiStrLen (StringArray[Index]); + if (StringLen > LargestString) { + StringLen = LargestString; + } + EfiCopyMem ( + StringPtr + ((LargestString - StringLen) / 2), + StringArray[Index], + StringLen * sizeof (CHAR16) + ); + StringPtr += LargestString; + + *StringPtr++ = BOXDRAW_VERTICAL; + *StringPtr = L'\0'; + + ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index); + ConOut->OutputString (ConOut, LineBuffer); + } + + StringPtr = &LineBuffer[0]; + *StringPtr++ = BOXDRAW_UP_RIGHT; + for (Index = 0; Index < LargestString; Index++) { + *StringPtr++ = BOXDRAW_HORIZONTAL; + } + *StringPtr++ = BOXDRAW_UP_LEFT; + *StringPtr = L'\0'; + + ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1); + ConOut->OutputString (ConOut, LineBuffer); + + do { + Status = gBS->CreateEvent (EFI_EVENT_TIMER, 0, NULL, NULL, &TimerEvent); + + // + // Set a timer event of 1 second expiration + // + gBS->SetTimer ( + TimerEvent, + TimerRelative, + 10000000 + ); + + // + // Wait for the keystroke event or the timer + // + WaitList[0] = gST->ConIn->WaitForKey; + WaitList[1] = TimerEvent; + Status = gBS->WaitForEvent (2, WaitList, &Index); + + // + // Check for the timer expiration + // + if (!EFI_ERROR (Status) && Index == 1) { + Status = EFI_TIMEOUT; + } + + gBS->CloseEvent (TimerEvent); + } while (Status == EFI_TIMEOUT); + + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + EfiCopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY)); + + ConOut->SetAttribute (ConOut, CurrentAttribute); + ConOut->EnableCursor (ConOut, TRUE); + + return Status; +} + +EFI_STATUS +ExtractDefault( + IN VOID *Buffer, + IN UINTN *BufferSize, + UINTN Number, + ... + ) +/*++ + + Routine Description: + + Configure the buffer accrording to ConfigBody strings. + + Arguments: + DefaultId - the ID of default. + Buffer - the start address of buffer. + BufferSize - the size of buffer. + Number - the number of the strings. + + Returns: + EFI_BUFFER_TOO_SMALL - the BufferSize is too small to operate. + EFI_INVALID_PARAMETER - Buffer is NULL or BufferSize is 0. + EFI_SUCCESS - Operation successful. + +--*/ +{ + VA_LIST Args; + UINTN Index; + UINT32 TotalLen; + UINT8 *BufCfgArray; + UINT8 *BufferPos; + UINT16 Offset; + UINT16 Width; + UINT8 *Value; + + if ((Buffer == NULL) || (BufferSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Offset = 0; + Width = 0; + Value = NULL; + + VA_START (Args, Number); + for (Index = 0; Index < Number; Index++) { + BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *); + EfiCopyMem (&TotalLen, BufCfgArray, sizeof (UINT32)); + BufferPos = BufCfgArray + sizeof (UINT32); + + while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) { + EfiCopyMem (&Offset, BufferPos, sizeof (UINT16)); + BufferPos += sizeof (UINT16); + EfiCopyMem (&Width, BufferPos, sizeof (UINT16)); + BufferPos += sizeof (UINT16); + Value = BufferPos; + BufferPos += Width; + + if ((UINTN)(Offset + Width) > *BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + EfiCopyMem ((UINT8 *)Buffer + Offset, Value, Width); + } + } + VA_END (Args); + + *BufferSize = (UINTN)Offset; + + return EFI_SUCCESS; +} + +EFI_STATUS +ExtractBlockName ( + IN UINT8 *Buffer, + OUT CHAR16 **BlockName + ) +/*++ + + Routine Description: + + Extract block name from the array generated by VFR compiler. The name of + this array is "Vfr + <StorageName> + BlockName", e.g. "VfrMyIfrNVDataBlockName". + Format of this array is: + Array length | 4-bytes + Offset | 2-bytes + Width | 2-bytes + Offset | 2-bytes + Width | 2-bytes + ... ... + + Arguments: + Buffer - Array generated by VFR compiler. + BlockName - The returned <BlockName> + + Returns: + EFI_OUT_OF_RESOURCES - Run out of memory resource. + EFI_INVALID_PARAMETER - Buffer is NULL or BlockName is NULL. + EFI_SUCCESS - Operation successful. + +--*/ +{ + UINTN Index; + UINT32 Length; + UINT32 BlockNameNumber; + UINTN HexStringBufferLen; + CHAR16 *StringPtr; + + if ((Buffer == NULL) || (BlockName == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate number of Offset/Width pair + // + EfiCopyMem (&Length, Buffer, sizeof (UINT32)); + BlockNameNumber = (Length - sizeof (UINT32)) / (sizeof (UINT16) * 2); + + // + // <BlockName> ::= &OFFSET=1234&WIDTH=1234 + // | 8 | 4 | 7 | 4 | + // + StringPtr = EfiLibAllocateZeroPool ((BlockNameNumber * (8 + 4 + 7 + 4) + 1) * sizeof (CHAR16)); + *BlockName = StringPtr; + if (StringPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Buffer += sizeof (UINT32); + for (Index = 0; Index < BlockNameNumber; Index++) { + EfiStrCpy (StringPtr, L"&OFFSET="); + StringPtr += 8; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + EfiStrCpy (StringPtr, L"&WIDTH="); + StringPtr += 7; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ExtractBlockConfig ( + IN UINT8 *Buffer, + OUT CHAR16 **BlockConfig + ) +/*++ + + Routine Description: + + Extract block config from the array generated by VFR compiler. The name of + this array is "Vfr + <StorageName> + Default<HexCh>4", e.g. "VfrMyIfrNVDataDefault0000". + + Arguments: + Buffer - Array generated by VFR compiler. + BlockConfig - The returned <BlockConfig> + + Returns: + EFI_OUT_OF_RESOURCES - Run out of memory resource. + EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL. + EFI_SUCCESS - Operation successful. + +--*/ +{ + UINT32 Length; + UINT16 Width; + UINTN HexStringBufferLen; + CHAR16 *StringPtr; + UINT8 *BufferEnd; + CHAR16 *StringEnd; + EFI_STATUS Status; + + if ((Buffer == NULL) || (BlockConfig == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate length of AltResp string + // Format of Default value array is: + // Array length | 4-bytes + // Offset | 2-bytes + // Width | 2-bytes + // Value | Variable length + // Offset | 2-bytes + // Width | 2-bytes + // Value | Variable length + // ... ... + // When value is 1 byte in length, overhead of AltResp string will be maximum, + // BlockConfig ::= <&OFFSET=1234&WIDTH=1234&VALUE=12>+ + // | 8 | 4 | 7 | 4 | 7 |2| + // so the maximum length of BlockConfig could be calculated as: + // (ArrayLength / 5) * (8 + 4 + 7 + 4 + 7 + 2) = ArrayLength * 6.4 < ArrayLength * 7 + // + EfiCopyMem (&Length, Buffer, sizeof (UINT32)); + BufferEnd = Buffer + Length; + StringPtr = EfiLibAllocatePool (Length * 7 * sizeof (CHAR16)); + *BlockConfig = StringPtr; + if (StringPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + StringEnd = StringPtr + (Length * 7); + + Buffer += sizeof (UINT32); + while (Buffer < BufferEnd) { + EfiStrCpy (StringPtr, L"&OFFSET="); + StringPtr += 8; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + EfiStrCpy (StringPtr, L"&WIDTH="); + StringPtr += 7; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + EfiCopyMem (&Width, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + EfiStrCpy (StringPtr, L"&VALUE="); + StringPtr += 7; + + HexStringBufferLen = StringEnd - StringPtr; + Status = BufToHexString (StringPtr, &HexStringBufferLen, Buffer, Width); + if (EFI_ERROR (Status)) { + return Status; + } + Buffer += Width; + StringPtr += (Width * 2); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ConstructConfigAltResp ( + IN EFI_STRING ConfigRequest, OPTIONAL + OUT EFI_STRING *Progress, + OUT EFI_STRING *ConfigAltResp, + IN EFI_GUID *Guid, + IN CHAR16 *Name, + IN EFI_HANDLE *DriverHandle, + IN VOID *BufferStorage, + IN UINTN BufferStorageSize, + IN VOID *BlockNameArray, OPTIONAL + IN UINTN NumberAltCfg, + ... +//IN UINT16 AltCfgId, +//IN VOID *DefaultValueArray, + ) +/*++ + + Routine Description: + + Construct <ConfigAltResp> for a buffer storage. + + Arguments: + ConfigRequest - The Config request string. If set to NULL, all the + configurable elements will be extracted from BlockNameArray. + ConfigAltResp - The returned <ConfigAltResp>. + Progress - On return, points to a character in the Request. + Guid - GUID of the buffer storage. + Name - Name of the buffer storage. + DriverHandle - The DriverHandle which is used to invoke HiiDatabase + protocol interface NewPackageList(). + BufferStorage - Content of the buffer storage. + BufferStorageSize - Length in bytes of the buffer storage. + BlockNameArray - Array generated by VFR compiler. + NumberAltCfg - Number of Default value array generated by VFR compiler. + The sequential input parameters will be number of + AltCfgId and DefaultValueArray pairs. When set to 0, + there will be no <AltResp>. + + Returns: + EFI_OUT_OF_RESOURCES - Run out of memory resource. + EFI_INVALID_PARAMETER - ConfigAltResp is NULL. + EFI_SUCCESS - Operation successful. + +--*/ +{ + EFI_STATUS Status; + CHAR16 *ConfigHdr; + CHAR16 *BlockName; + CHAR16 *DescHdr; + CHAR16 *StringPtr; + CHAR16 **AltCfg; + UINT16 AltCfgId; + VOID *DefaultValueArray; + UINTN StrBufferLen; + EFI_STRING ConfigResp; + EFI_STRING TempStr; + VA_LIST Args; + UINTN AltRespLen; + UINTN Index; + BOOLEAN NeedFreeConfigRequest; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + + if (ConfigAltResp == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Construct <ConfigHdr> : "GUID=...&NAME=...&PATH=..." + // + ConfigHdr = NULL; + StrBufferLen = 0; + Status = ConstructConfigHdr ( + ConfigHdr, + &StrBufferLen, + Guid, + Name, + DriverHandle + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + ConfigHdr = EfiLibAllocateZeroPool (StrBufferLen); + Status = ConstructConfigHdr ( + ConfigHdr, + &StrBufferLen, + Guid, + Name, + DriverHandle + ); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Construct <ConfigResp> + // + NeedFreeConfigRequest = FALSE; + if (ConfigRequest == NULL) { + // + // If ConfigRequest is set to NULL, export all configurable elements in BlockNameArray + // + Status = ExtractBlockName (BlockNameArray, &BlockName); + if (EFI_ERROR (Status)) { + return Status; + } + + ConfigRequest = EfiLibAllocateZeroPool (EfiStrSize (ConfigHdr) + EfiStrSize (BlockName) - sizeof (CHAR16)); + EfiStrCpy (ConfigRequest, ConfigHdr); + EfiStrCat (ConfigRequest, BlockName); + NeedFreeConfigRequest = TRUE; + } + + Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, &HiiConfigRouting); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = HiiConfigRouting->BlockToConfig ( + HiiConfigRouting, + ConfigRequest, + BufferStorage, + BufferStorageSize, + &ConfigResp, + (Progress == NULL) ? &TempStr : Progress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Construct <AltResp> + // + DescHdr = EfiLibAllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16)); + StringPtr = DescHdr; + AltCfg = EfiLibAllocateZeroPool (NumberAltCfg * sizeof (CHAR16 *)); + AltRespLen = 0; + VA_START (Args, NumberAltCfg); + for (Index = 0; Index < NumberAltCfg; Index++) { + AltCfgId = (UINT16) VA_ARG (Args, UINT16); + DefaultValueArray = (UINT8 *) VA_ARG (Args, VOID *); + + // + // '&' <ConfigHdr> + // + AltRespLen += (EfiStrLen (ConfigHdr) + 1); + + StringPtr = DescHdr + Index * 16; + EfiStrCpy (StringPtr, L"&ALTCFG="); + AltRespLen += (8 + sizeof (UINT16) * 2); + + StrBufferLen = 5; + BufToHexString (StringPtr + 8, &StrBufferLen, (UINT8 *) &AltCfgId, sizeof (UINT16)); + Status = ExtractBlockConfig (DefaultValueArray, &AltCfg[Index]); + if (EFI_ERROR (Status)) { + return Status; + } + AltRespLen += EfiStrLen (AltCfg[Index]); + } + VA_END (Args); + + // + // Generate the final <ConfigAltResp> + // + StrBufferLen = (EfiStrLen ((CHAR16 *) ConfigResp) + AltRespLen + 1) * sizeof (CHAR16); + TempStr = EfiLibAllocateZeroPool (StrBufferLen); + *ConfigAltResp = TempStr; + if (TempStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // <ConfigAltResp> ::= <ConfigResp> ['&' <AltResp>]* + // + EfiStrCpy (TempStr, ConfigResp); + for (Index = 0; Index < NumberAltCfg; Index++) { + EfiStrCat (TempStr, L"&"); + EfiStrCat (TempStr, ConfigHdr); + EfiStrCat (TempStr, DescHdr + Index * 16); + EfiStrCat (TempStr, AltCfg[Index]); + + gBS->FreePool (AltCfg[Index]); + } + + if (NeedFreeConfigRequest) { + gBS->FreePool (ConfigRequest); + } + gBS->FreePool (ConfigHdr); + gBS->FreePool (ConfigResp); + gBS->FreePool (DescHdr); + gBS->FreePool (AltCfg); + + return EFI_SUCCESS; +} + +STATIC +VOID +SwapBuffer ( + IN OUT UINT8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Swap bytes in the buffer. + +Arguments: + Buffer - Binary buffer. + BufferSize - Size of the buffer in bytes. + +Returns: + None. + +--*/ +{ + UINTN Index; + UINT8 Temp; + UINTN SwapCount; + + SwapCount = BufferSize / 2; + for (Index = 0; Index < SwapCount; Index++) { + Temp = Buffer[Index]; + Buffer[Index] = Buffer[BufferSize - 1 - Index]; + Buffer[BufferSize - 1 - Index] = Temp; + } +} + +VOID +ToLower ( + IN OUT CHAR16 *Str + ) +/*++ + +Routine Description: + Converts the unicode character of the string from uppercase to lowercase. + +Arguments: + Str - String to be converted + +Returns: + +--*/ +{ + CHAR16 *Ptr; + + for (Ptr = Str; *Ptr != L'\0'; Ptr++) { + if (*Ptr >= L'A' && *Ptr <= L'Z') { + *Ptr = (CHAR16) (*Ptr - L'A' + L'a'); + } + } +} + +EFI_STATUS +BufferToHexString ( + IN OUT CHAR16 *Str, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Converts binary buffer to Unicode string in reversed byte order from BufToHexString(). + +Arguments: + Str - String for output + Buffer - Binary buffer. + BufferSize - Size of the buffer in bytes. + +Returns: + EFI_SUCCESS - The function completed successfully. + +--*/ +{ + EFI_STATUS Status; + UINT8 *NewBuffer; + UINTN StrBufferLen; + + NewBuffer = EfiLibAllocateCopyPool (BufferSize, Buffer); + SwapBuffer (NewBuffer, BufferSize); + + StrBufferLen = BufferSize * 2 + 1; + Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize); + + gBS->FreePool (NewBuffer); + // + // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format. + // + ToLower (Str); + + return Status; +} + +EFI_STATUS +HexStringToBuffer ( + IN OUT UINT8 *Buffer, + IN OUT UINTN *BufferSize, + IN CHAR16 *Str + ) +/*++ + +Routine Description: + Converts Hex String to binary buffer in reversed byte order from HexStringToBuf(). + +Arguments: + Buffer - Pointer to buffer that receives the data. + BufferSize - Length in bytes of the buffer to hold converted data. + If routine return with EFI_SUCCESS, containing length of converted data. + If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired. + Str - String to be converted from. + +Returns: + EFI_SUCCESS - The function completed successfully. + +--*/ +{ + EFI_STATUS Status; + UINTN ConvertedStrLen; + + ConvertedStrLen = 0; + Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen); + if (!EFI_ERROR (Status)) { + SwapBuffer (Buffer, (ConvertedStrLen + 1) / 2); + } + + return Status; +} + +EFI_STATUS +ConfigStringToUnicode ( + IN OUT CHAR16 *UnicodeString, + IN OUT UINTN *StrBufferLen, + IN CHAR16 *ConfigString + ) +/*++ + +Routine Description: + Convert binary representation Config string (e.g. "0041004200430044") to the + original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e. + "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>"). + +Arguments: + UnicodeString - Original Unicode string. + StrBufferLen - On input: Length in bytes of buffer to hold the Unicode string. + Includes tailing '\0' character. + On output: + If return EFI_SUCCESS, containing length of Unicode string buffer. + If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. + ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+ + +Returns: + EFI_SUCCESS - Routine success. + EFI_BUFFER_TOO_SMALL - The string buffer is too small. + +--*/ +{ + UINTN Index; + UINTN Len; + UINTN BufferSize; + CHAR16 BackupChar; + + Len = EfiStrLen (ConfigString) / 4; + BufferSize = (Len + 1) * sizeof (CHAR16); + + if (*StrBufferLen < BufferSize) { + *StrBufferLen = BufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + *StrBufferLen = BufferSize; + + for (Index = 0; Index < Len; Index++) { + BackupChar = ConfigString[4]; + ConfigString[4] = L'\0'; + + HexStringToBuf ((UINT8 *) UnicodeString, &BufferSize, ConfigString, NULL); + + ConfigString[4] = BackupChar; + + ConfigString += 4; + UnicodeString += 1; + } + + // + // Add tailing '\0' character + // + *UnicodeString = L'\0'; + + return EFI_SUCCESS; +} + +EFI_STATUS +UnicodeToConfigString ( + IN OUT CHAR16 *ConfigString, + IN OUT UINTN *StrBufferLen, + IN CHAR16 *UnicodeString + ) +/*++ + +Routine Description: + Convert Unicode string to binary representation Config string, e.g. + "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e. + "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>"). + +Arguments: + ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+ + StrBufferLen - On input: Length in bytes of buffer to hold the Unicode string. + Includes tailing '\0' character. + On output: + If return EFI_SUCCESS, containing length of Unicode string buffer. + If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. + UnicodeString - Original Unicode string. + +Returns: + EFI_SUCCESS - Routine success. + EFI_BUFFER_TOO_SMALL - The string buffer is too small. + +--*/ +{ + UINTN Index; + UINTN Len; + UINTN BufferSize; + CHAR16 *String; + + Len = EfiStrLen (UnicodeString); + BufferSize = (Len * 4 + 1) * sizeof (CHAR16); + + if (*StrBufferLen < BufferSize) { + *StrBufferLen = BufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + *StrBufferLen = BufferSize; + String = ConfigString; + + for (Index = 0; Index < Len; Index++) { + BufToHexString (ConfigString, &BufferSize, (UINT8 *) UnicodeString, 2); + + ConfigString += 4; + UnicodeString += 1; + } + + // + // Add tailing '\0' character + // + *ConfigString = L'\0'; + + // + // Convert the uppercase to lowercase since <HexAf> is defined in lowercase format. + // + ToLower (String); + return EFI_SUCCESS; +} + +EFI_STATUS +ConstructConfigHdr ( + IN OUT CHAR16 *ConfigHdr, + IN OUT UINTN *StrBufferLen, + IN EFI_GUID *Guid, + IN CHAR16 *Name, OPTIONAL + IN EFI_HANDLE *DriverHandle + ) +/*++ + +Routine Description: + Construct <ConfigHdr> using routing information GUID/NAME/PATH. + +Arguments: + ConfigHdr - Pointer to the ConfigHdr string. + StrBufferLen - On input: Length in bytes of buffer to hold the ConfigHdr string. + Includes tailing '\0' character. + On output: + If return EFI_SUCCESS, containing length of ConfigHdr string buffer. + If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. + Guid - Routing information: GUID. + Name - Routing information: NAME. + DriverHandle - Driver handle which contains the routing information: PATH. + +Returns: + EFI_SUCCESS - Routine success. + EFI_BUFFER_TOO_SMALL - The ConfigHdr string buffer is too small. + +--*/ +{ + EFI_STATUS Status; + UINTN NameStrLen; + UINTN DevicePathSize; + UINTN BufferSize; + CHAR16 *StrPtr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (Name == NULL) { + // + // There will be no "NAME" in <ConfigHdr> for Name/Value storage + // + NameStrLen = 0; + } else { + // + // For buffer storage + // + NameStrLen = EfiStrLen (Name); + } + + // + // Retrieve DevicePath Protocol associated with this HiiPackageList + // + Status = gBS->HandleProtocol ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + &DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DevicePathSize = EfiDevicePathSize (DevicePath); + + // + // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL> + // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 | + // + BufferSize = (5 + 32 + 6 + NameStrLen * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16); + if (*StrBufferLen < BufferSize) { + *StrBufferLen = BufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + *StrBufferLen = BufferSize; + + StrPtr = ConfigHdr; + + EfiStrCpy (StrPtr, L"GUID="); + StrPtr += 5; + BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID)); + StrPtr += 32; + + // + // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044" + // + EfiStrCpy (StrPtr, L"&NAME="); + StrPtr += 6; + if (Name != NULL) { + BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16); + UnicodeToConfigString (StrPtr, &BufferSize, Name); + StrPtr += (NameStrLen * 4); + } + + EfiStrCpy (StrPtr, L"&PATH="); + StrPtr += 6; + BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize); + + return EFI_SUCCESS; +} + +BOOLEAN +IsConfigHdrMatch ( + IN EFI_STRING ConfigString, + IN EFI_GUID *StorageGuid, OPTIONAL + IN CHAR16 *StorageName OPTIONAL + ) +/*++ + +Routine Description: + Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>. + +Arguments: + ConfigString - Either <ConfigRequest> or <ConfigResp>. + StorageGuid - GUID of the storage. + StorageName - Name of the stoarge. + +Returns: + TRUE - Routing information is correct in ConfigString. + FALSE - Routing information is incorrect in ConfigString. + +--*/ +{ + EFI_STATUS Status; + BOOLEAN Match; + EFI_GUID Guid; + CHAR16 *Name; + CHAR16 *StrPtr; + UINTN BufferSize; + + // + // <ConfigHdr> ::= + // GUID=<HexCh>32&NAME=<Char>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL> + // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 | + // + if (EfiStrLen (ConfigString) <= (5 + 32 + 6)) { + return FALSE; + } + + // + // Compare GUID + // + if (StorageGuid != NULL) { + + StrPtr = ConfigString + 5 + 32; + if (*StrPtr != L'&') { + return FALSE; + } + *StrPtr = L'\0'; + + BufferSize = sizeof (EFI_GUID); + Status = HexStringToBuffer ( + (UINT8 *) &Guid, + &BufferSize, + ConfigString + 5 + ); + *StrPtr = L'&'; + + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (!EfiCompareGuid (&Guid, StorageGuid)) { + return FALSE; + } + } + + // + // Compare Name + // + Match = TRUE; + if (StorageName != NULL) { + StrPtr = ConfigString + 5 + 32 + 6; + while (*StrPtr != L'\0' && *StrPtr != L'&') { + StrPtr++; + } + if (*StrPtr != L'&') { + return FALSE; + } + + *StrPtr = L'\0'; + BufferSize = (((UINTN) StrPtr) - ((UINTN) &ConfigString[5 + 32 + 6])) / 4 + sizeof (CHAR16); + Name = EfiLibAllocatePool (BufferSize); + ASSERT (Name != NULL); + Status = ConfigStringToUnicode ( + Name, + &BufferSize, + ConfigString + 5 + 32 + 6 + ); + *StrPtr = L'&'; + + if (EFI_ERROR (Status) || (EfiStrCmp (Name, StorageName) != 0)) { + Match = FALSE; + } + gBS->FreePool (Name); + } + + return Match; +} + +BOOLEAN +FindBlockName ( + IN OUT CHAR16 *String, + UINTN Offset, + UINTN Width + ) +/*++ + +Routine Description: + Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string. + +Arguments: + String - The string to be searched in. + Offset - Offset in BlockName. + Width - Width in BlockName. + +Returns: + TRUE - Block name found. + FALSE - Block name not found. + +--*/ +{ + EFI_STATUS Status; + UINTN Data; + UINTN BufferSize; + UINTN ConvertedStrLen; + + while ((String = EfiStrStr (String, L"&OFFSET=")) != NULL) { + // + // Skip '&OFFSET=' + // + String = String + 8; + + Data = 0; + BufferSize = sizeof (UINTN); + Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen); + if (EFI_ERROR (Status)) { + return FALSE; + } + String = String + ConvertedStrLen; + + if (Data != Offset) { + continue; + } + + if (EfiStrnCmp (String, L"&WIDTH=", 7) != 0) { + return FALSE; + } + String = String + 7; + + Data = 0; + BufferSize = sizeof (UINTN); + Status = HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen); + if (EFI_ERROR (Status)) { + return FALSE; + } + if (Data == Width) { + return TRUE; + } + + String = String + ConvertedStrLen; + } + + return FALSE; +} + +EFI_STATUS +GetBrowserData ( + EFI_GUID *VariableGuid, OPTIONAL + CHAR16 *VariableName, OPTIONAL + UINTN *BufferSize, + UINT8 *Buffer + ) +/*++ + +Routine Description: + This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser. + +Arguments: + VariableGuid - An optional field to indicate the target variable GUID name to use. + VariableName - An optional field to indicate the target human-readable variable name. + BufferSize - On input: Length in bytes of buffer to hold retrived data. + On output: + If return EFI_BUFFER_TOO_SMALL, containg length of buffer desired. + Buffer - Buffer to hold retrived data. + +Returns: + EFI_SUCCESS - Routine success. + EFI_BUFFER_TOO_SMALL - The intput buffer is too small. + +--*/ +{ + EFI_STATUS Status; + CHAR16 *ConfigHdr; + CHAR16 *ConfigResp; + CHAR16 *StringPtr; + UINTN HeaderLen; + UINTN BufferLen; + CHAR16 *Progress; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + + // + // Locate protocols for use + // + Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, &FormBrowser2); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, &HiiConfigRouting); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Retrive formset storage data from Form Browser + // + ConfigHdr = mFakeConfigHdr; + HeaderLen = EfiStrLen (ConfigHdr); + + BufferLen = 0x4000; + ConfigResp = EfiLibAllocateZeroPool (BufferLen + (HeaderLen + 1) * sizeof (CHAR16)); + + StringPtr = ConfigResp + HeaderLen; + *StringPtr = L'&'; + StringPtr++; + + Status = FormBrowser2->BrowserCallback ( + FormBrowser2, + &BufferLen, + StringPtr, + TRUE, + VariableGuid, + VariableName + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + gBS->FreePool (ConfigResp); + ConfigResp = EfiLibAllocateZeroPool (BufferLen + (HeaderLen + 1) * sizeof (CHAR16)); + + StringPtr = ConfigResp + HeaderLen; + *StringPtr = L'&'; + StringPtr++; + + Status = FormBrowser2->BrowserCallback ( + FormBrowser2, + &BufferLen, + StringPtr, + TRUE, + VariableGuid, + VariableName + ); + } + if (EFI_ERROR (Status)) { + gBS->FreePool (ConfigResp); + return Status; + } + EfiCopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16)); + + // + // Convert <ConfigResp> to buffer data + // + Status = HiiConfigRouting->ConfigToBlock ( + HiiConfigRouting, + ConfigResp, + Buffer, + BufferSize, + &Progress + ); + gBS->FreePool (ConfigResp); + + return Status; +} + +EFI_STATUS +SetBrowserData ( + EFI_GUID *VariableGuid, OPTIONAL + CHAR16 *VariableName, OPTIONAL + UINTN BufferSize, + UINT8 *Buffer, + CHAR16 *RequestElement OPTIONAL + ) +/*++ + +Routine Description: + This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser. + +Arguments: + VariableGuid - An optional field to indicate the target variable GUID name to use. + VariableName - An optional field to indicate the target human-readable variable name. + BufferSize - Length in bytes of buffer to hold retrived data. + Buffer - Buffer to hold retrived data. + RequestElement - An optional field to specify which part of the buffer data + will be send back to Browser. If NULL, the whole buffer of + data will be committed to Browser. + <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>* + +Returns: + EFI_SUCCESS - Routine success. + Other - Updating Browser uncommitted data failed. + +--*/ +{ + EFI_STATUS Status; + CHAR16 *ConfigHdr; + CHAR16 *ConfigResp; + CHAR16 *StringPtr; + UINTN HeaderLen; + UINTN BufferLen; + CHAR16 *Progress; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + CHAR16 BlockName[33]; + CHAR16 *ConfigRequest; + CHAR16 *Request; + + // + // Locate protocols for use + // + Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, &FormBrowser2); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, &HiiConfigRouting); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Prepare <ConfigRequest> + // + ConfigHdr = mFakeConfigHdr; + HeaderLen = EfiStrLen (ConfigHdr); + + if (RequestElement == NULL) { + // + // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName> + // + BlockName[0] = L'\0'; + EfiStrCpy (BlockName, L"&OFFSET=0&WIDTH="); + + // + // String lenghth of L"&OFFSET=0&WIDTH=" is 16 + // + StringPtr = BlockName + 16; + BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16)); + BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN)); + + Request = BlockName; + } else { + Request = RequestElement; + } + + BufferLen = HeaderLen * sizeof (CHAR16) + EfiStrSize (Request); + ConfigRequest = EfiLibAllocateZeroPool (BufferLen); + + EfiCopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16)); + StringPtr = ConfigRequest + HeaderLen; + EfiStrCpy (StringPtr, Request); + + // + // Convert buffer to <ConfigResp> + // + Status = HiiConfigRouting->BlockToConfig ( + HiiConfigRouting, + ConfigRequest, + Buffer, + BufferSize, + &ConfigResp, + &Progress + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (ConfigRequest); + return Status; + } + + // + // Skip <ConfigHdr> and '&' + // + StringPtr = ConfigResp + HeaderLen + 1; + + // + // Change uncommitted data in Browser + // + Status = FormBrowser2->BrowserCallback ( + FormBrowser2, + &BufferSize, + StringPtr, + FALSE, + VariableGuid, + VariableName + ); + gBS->FreePool (ConfigResp); + gBS->FreePool (ConfigRequest); + return Status; +} + +BOOLEAN +HiiSetToDefaults ( + IN CONST EFI_STRING Request, OPTIONAL + IN UINT16 DefaultId + ) +/*++ + +Routine Description: + Reset the default value specified by DefaultId to the driver + configuration got by Request string. + + NULL request string support depends on the ExportConfig interface of + HiiConfigRouting protocol in UEFI specification. + +Arguments: + Request - A null-terminated Unicode string in + <MultiConfigRequest> format. It can be NULL. + If it is NULL, all configuration for the + entirety of the current HII database will be reset. + DefaultId - Specifies the type of defaults to retrieve. + +Returns: + TURE - The default value is set successfully. + FALSE - The default value can't be found and set. + +--*/ +{ + EFI_STRING ConfigAltResp; + EFI_STRING ConfigAltHdr; + EFI_STRING ConfigResp; + EFI_STRING Progress; + EFI_STRING StringPtr; + EFI_STRING StringHdr; + EFI_STRING CurString; + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + CHAR16 OrigChar; + UINT32 Index; + EFI_GUID *VarGuid; + EFI_STRING VarName; + EFI_STRING_ID DefaultName; + UINTN BufferSize; + UINT8 *PackageData; + UINTN IfrOffset; + EFI_IFR_OP_HEADER *IfrOpHdr; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + UINT32 PackageOffset; + UINTN PackageListLength; + EFI_HII_PACKAGE_HEADER PacakgeHeader; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + + DEBUG ((EFI_D_ERROR, "HiiSetToDefaults - enter\n")); + + Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting); + if (EFI_ERROR (Status)) { + return FALSE; + } + LocateHiiProtocols (); + + ConfigAltResp = NULL; + ConfigResp = NULL; + VarGuid = NULL; + VarName = NULL; + DevicePath = NULL; + ConfigAltHdr = NULL; + CurString = NULL; + Index = 0; + BufferSize = 0; + OrigChar = 0; + HiiHandle = NULL; + PackageData = NULL; + HiiPackageList = NULL; + + // + // Get the full requested value and deault value string. + // + if (Request != NULL) { + Status = HiiConfigRouting->ExtractConfig ( + HiiConfigRouting, + Request, + &Progress, + &ConfigAltResp + ); + } else { + Status = HiiConfigRouting->ExportConfig ( + HiiConfigRouting, + &ConfigAltResp + ); + } + + if (EFI_ERROR (Status)) { + return FALSE; + } + DEBUG ((EFI_D_ERROR, "HiiSetToDefaults - start\n")); + StringPtr = ConfigAltResp; + + while (StringPtr != L'\0') { + // + // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=... + // + StringHdr = StringPtr; + + if (EfiStrnCmp (StringPtr, L"GUID=", (sizeof(L"GUID=")/sizeof(CHAR16)) - 1) != 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + StringPtr += (sizeof(L"GUID=")/sizeof(CHAR16)) - 1; + CurString = StringPtr; + while (*StringPtr != L'\0' && EfiStrnCmp (StringPtr, L"&NAME=", (sizeof(L"&NAME=")/sizeof(CHAR16)) - 1) != 0) { + StringPtr++; + } + if (*StringPtr == L'\0') { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Get Guid value + // + BufferSize = sizeof (EFI_GUID); + VarGuid = EfiLibAllocatePool (BufferSize); + OrigChar = *StringPtr; + *StringPtr = L'\0'; + Status = HexStringToBuffer ((UINT8 *) VarGuid, &BufferSize, CurString); + *StringPtr = OrigChar; + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Get Name value VarName + // + StringPtr += (sizeof(L"&NAME=")/sizeof(CHAR16)) - 1; + CurString = StringPtr; + while (*StringPtr != L'\0' && EfiStrnCmp (StringPtr, L"&PATH=", (sizeof(L"&PATH=")/sizeof(CHAR16)) - 1) != 0) { + StringPtr++; + } + if (*StringPtr == L'\0') { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + OrigChar = *StringPtr; + *StringPtr = L'\0'; + BufferSize = 0; + Status = ConfigStringToUnicode (VarName, &BufferSize, CurString); + if (Status == EFI_BUFFER_TOO_SMALL) { + VarName = EfiLibAllocatePool (BufferSize); + Status = ConfigStringToUnicode (VarName, &BufferSize, CurString); + } + *StringPtr = OrigChar; + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Get Path value DevicePath + // + StringPtr += (sizeof(L"&PATH=")/sizeof(CHAR16)) - 1; + CurString = StringPtr; + for (; *StringPtr != L'\0' && *StringPtr != L'&'; StringPtr++); + OrigChar = *StringPtr; + *StringPtr = L'\0'; + Status = HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, CurString); + if (Status == EFI_BUFFER_TOO_SMALL) { + DevicePath = EfiLibAllocatePool (BufferSize); + Status = HexStringToBuffer ((UINT8 *) DevicePath, &BufferSize, CurString); + } + *StringPtr = OrigChar; + + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Get the Driver handle by the got device path. + // + HiiHandle = DevicePathToHiiHandle (gIfrLibHiiDatabase, DevicePath); + if (HiiHandle == NULL) { + // + // This request string has no its Hii package. + // Its default value and validating can't execute by parsing IFR data. + // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path. + // + Status = EFI_SUCCESS; + goto NextConfigAltResp; + } + + // + // 2. Get DefaultName string ID by parsing the PacakgeList + // + + // + // Get HiiPackage by HiiHandle + // + PackageListLength = 0; + HiiPackageList = NULL; + Status = gIfrLibHiiDatabase->ExportPackageLists (gIfrLibHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList); + + // + // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0. + // + if (Status != EFI_BUFFER_TOO_SMALL) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + HiiPackageList = EfiLibAllocatePool (PackageListLength); + if (HiiPackageList == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Get PackageList on HiiHandle + // + Status = gIfrLibHiiDatabase->ExportPackageLists (gIfrLibHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Parse the form package and get the default name string ID. + // + PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + Status = EFI_NOT_FOUND; + while (PackageOffset < PackageListLength) { + EfiCopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader)); + + // + // Parse IFR opcode to get default store opcode + // + if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) { + IfrOffset = sizeof (PacakgeHeader); + PackageData = (UINT8 *) HiiPackageList + PackageOffset; + while (IfrOffset < PacakgeHeader.Length) { + IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset); + // + // Match DefaultId to find its DefaultName + // + if (IfrOpHdr->OpCode == EFI_IFR_DEFAULTSTORE_OP) { + if (((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId == DefaultId) { + DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName; + Status = EFI_SUCCESS; + break; + } + } + IfrOffset += IfrOpHdr->Length; + } + // + // Only one form is in a package list. + // + break; + } + + // + // Go to next package. + // + PackageOffset += PacakgeHeader.Length; + } + + // + // Not found the matched default string ID + // + if (EFI_ERROR (Status)) { + Status = EFI_SUCCESS; + goto NextConfigAltResp; + } + + // + // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp) + // Get the default configuration string according to the found default name string ID. + // + Status = HiiConfigRouting->GetAltConfig ( + HiiConfigRouting, + ConfigAltResp, + VarGuid, + VarName, + DevicePath, + &DefaultName, // it can be NULL to get the current setting. + &ConfigResp + ); + + // + // The required setting can't be found. So, it is not required to be validated and set. + // + if (EFI_ERROR (Status)) { + Status = EFI_SUCCESS; + goto NextConfigAltResp; + } + // + // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set. + // + if (EfiStrStr (ConfigResp, L"&OFFSET=") == NULL) { + goto NextConfigAltResp; + } + + // + // 4. Set the default configuration information or Validate current setting by parse IFR code. + // Current Setting is in ConfigResp, will be set into buffer, then check it again. + // + // + // Set the default configuration information. + // + Status = HiiConfigRouting->RouteConfig (HiiConfigRouting, ConfigResp, &Progress); + + if (EFI_ERROR (Status)) { + goto Done; + } + +NextConfigAltResp: + // + // Free the allocated pacakge buffer and the got ConfigResp string. + // + if (HiiPackageList != NULL) { + gBS->FreePool (HiiPackageList); + HiiPackageList = NULL; + } + + if (ConfigResp != NULL) { + gBS->FreePool (ConfigResp); + ConfigResp = NULL; + } + + // + // Free the allocated buffer. + // + gBS->FreePool (VarGuid); + VarGuid = NULL; + + gBS->FreePool (VarName); + VarName = NULL; + + gBS->FreePool (DevicePath); + DevicePath = NULL; + + // + // 5. Jump to next ConfigAltResp for another Guid, Name, Path. + // + + // + // Get and Skip ConfigHdr + // + while (*StringPtr != L'\0' && *StringPtr != L'&') { + StringPtr++; + } + if (*StringPtr == L'\0') { + break; + } + + // + // Construct ConfigAltHdr string "&<ConfigHdr>&ALTCFG=\0" + // | 1 | EfiStrLen (ConfigHdr) | 8 | 1 | + // + ConfigAltHdr = EfiLibAllocateZeroPool ((1 + StringPtr - StringHdr + 8 + 1) * sizeof (CHAR16)); + if (ConfigAltHdr == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + EfiStrCpy (ConfigAltHdr, L"&"); + EfiStrnCat (ConfigAltHdr, StringHdr, StringPtr - StringHdr); + EfiStrCat (ConfigAltHdr, L"&ALTCFG="); + + // + // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr + // + while ((StringHdr = EfiStrStr (StringPtr, ConfigAltHdr)) != NULL) { + StringPtr = StringHdr + EfiStrLen (ConfigAltHdr); + if (*StringPtr == L'\0') { + break; + } + } + + // + // Free the allocated ConfigAltHdr string + // + gBS->FreePool (ConfigAltHdr); + if (*StringPtr == L'\0') { + break; + } + + // + // Find &GUID as the next ConfigHdr + // + StringPtr = EfiStrStr (StringPtr, L"&GUID"); + if (StringPtr == NULL) { + break; + } + + // + // Skip char '&' + // + StringPtr ++; + } + DEBUG ((EFI_D_ERROR, "HiiSetToDefaults - end\n")); + +Done: + if (VarGuid != NULL) { + gBS->FreePool (VarGuid); + } + + if (VarName != NULL) { + gBS->FreePool (VarName); + } + + if (DevicePath != NULL) { + gBS->FreePool (DevicePath); + } + + if (ConfigResp != NULL) { + gBS->FreePool (ConfigResp); + } + + if (ConfigAltResp != NULL) { + gBS->FreePool (ConfigAltResp); + } + + if (HiiPackageList != NULL) { + gBS->FreePool (HiiPackageList); + } + + if (EFI_ERROR (Status)) { + return FALSE; + } + + return TRUE; +} diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrLibrary.h b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrLibrary.h new file mode 100644 index 0000000..3baf851 --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrLibrary.h @@ -0,0 +1,1370 @@ +/*++ + +Copyright (c) 2007 - 2008, 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: + + UefiIfrLibrary.h + +Abstract: + + The file contain all library function for Ifr Operations. + +--*/ + +#ifndef _IFRLIBRARY_H +#define _IFRLIBRARY_H + +#include "Tiano.h" +#include "EfiDriverLib.h" +#include "TianoHii.h" + +#include EFI_PROTOCOL_DEFINITION (HiiFont) +#include EFI_PROTOCOL_DEFINITION (HiiImage) +#include EFI_PROTOCOL_DEFINITION (HiiString) +#include EFI_PROTOCOL_DEFINITION (HiiDatabase) +#include EFI_PROTOCOL_DEFINITION (HiiConfigRouting) +#include EFI_PROTOCOL_DEFINITION (HiiConfigAccess) +#include EFI_PROTOCOL_DEFINITION (FormBrowser2) +#include EFI_PROTOCOL_DEFINITION (SimpleTextOut) + +#include EFI_GUID_DEFINITION (GlobalVariable) + +#define IFR_LIB_DEFAULT_STRING_SIZE 0x200 + +// +// The architectural variable "Lang" and "LangCodes" are deprecated in UEFI +// specification. While, UEFI specification also states that these deprecated +// variables may be provided for backwards compatibility. +// If "LANG_SUPPORT" is defined, "Lang" and "LangCodes" will be produced; +// If "LANG_SUPPORT" is undefined, "Lang" and "LangCodes" will not be produced. +// +#define LANG_SUPPORT + +#define EFI_LANGUAGE_VARIABLE L"Lang" +#define EFI_LANGUAGE_CODES_VARIABLE L"LangCodes" + +#define UEFI_LANGUAGE_VARIABLE L"PlatformLang" +#define UEFI_LANGUAGE_CODES_VARIABLE L"PlatformLangCodes" + +// +// Limited buffer size recommended by RFC4646 (4.3. Length Considerations) +// (42 characters plus a NULL terminator) +// +#define RFC_3066_ENTRY_SIZE (42 + 1) +#define ISO_639_2_ENTRY_SIZE 3 + +#define INVALID_VARSTORE_ID 0 + +#define QUESTION_FLAGS (EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY) +#define QUESTION_FLAGS_MASK (~QUESTION_FLAGS) + +extern EFI_GUID mIfrVendorGuid; +extern EFI_HII_DATABASE_PROTOCOL *gIfrLibHiiDatabase; +extern EFI_HII_STRING_PROTOCOL *gIfrLibHiiString; + +#pragma pack(1) +typedef struct { + EFI_STRING_ID StringToken; + EFI_IFR_TYPE_VALUE Value; + UINT8 Flags; +} IFR_OPTION; +#pragma pack() + +#pragma pack(1) +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + UINT32 Reserved; + UINT64 UniqueId; +} HII_VENDOR_DEVICE_PATH_NODE; +#pragma pack() + +typedef struct { + HII_VENDOR_DEVICE_PATH_NODE Node; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +typedef struct { + // + // Buffer size allocated for Data. + // + UINT32 BufferSize; + + // + // Offset in Data to append the newly created opcode binary. + // It will be adjusted automatically in Create***OpCode(), and should be + // initialized to 0 before invocation of a serial of Create***OpCode() + // + UINT32 Offset; + + // + // The destination buffer for created op-codes + // + UINT8 *Data; +} EFI_HII_UPDATE_DATA; + +VOID +LocateHiiProtocols ( + VOID + ) +/*++ + +Routine Description: + This function locate Hii relative protocols for later usage. + +Arguments: + None. + +Returns: + None. + +--*/ +; + +// +// Exported Library functions +// +EFI_STATUS +CreateEndOpCode ( + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_END_OP opcode. + +Arguments: + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateDefaultOpCode ( + IN EFI_IFR_TYPE_VALUE *Value, + IN UINT8 Type, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_DEFAULT_OP opcode. + +Arguments: + Value - Value for the default + Type - Type for the default + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateActionOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN EFI_STRING_ID QuestionConfig, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_ACTION_OP opcode. + +Arguments: + QuestionId - Question ID + Prompt - String ID for Prompt + Help - String ID for Help + QuestionFlags - Flags in Question Header + QuestionConfig - String ID for configuration + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateSubTitleOpCode ( + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 Flags, + IN UINT8 Scope, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_SUBTITLE_OP opcode. + +Arguments: + Prompt - String ID for Prompt + Help - String ID for Help + Flags - Subtitle opcode flags + Scope - Subtitle Scope bit + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateTextOpCode ( + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN EFI_STRING_ID TextTwo, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_TEXT_OP opcode. + +Arguments: + Prompt - String ID for Prompt + Help - String ID for Help + TextTwo - String ID for text two + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateGotoOpCode ( + IN EFI_FORM_ID FormId, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN EFI_QUESTION_ID QuestionId, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_REF_OP opcode. + +Arguments: + FormId - Destination Form ID + Prompt - String ID for Prompt + Help - String ID for Help + QuestionFlags - Flags in Question Header + QuestionId - Question ID + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateOneOfOptionOpCode ( + IN UINTN OptionCount, + IN IFR_OPTION *OptionsList, + IN UINT8 Type, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +; + +EFI_STATUS +CreateOneOfOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 OneOfFlags, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_ONE_OF_OP opcode. + +Arguments: + QuestionId - Question ID + VarStoreId - Storage ID + VarOffset - Offset in Storage + Prompt - String ID for Prompt + Help - String ID for Help + QuestionFlags - Flags in Question Header + OneOfFlags - Flags for oneof opcode + OptionsList - List of options + OptionCount - Number of options in option list + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateOrderedListOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 Flags, + IN UINT8 DataType, + IN UINT8 MaxContainers, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_ORDERED_LIST_OP opcode. + +Arguments: + QuestionId - Question ID + VarStoreId - Storage ID + VarOffset - Offset in Storage + Prompt - String ID for Prompt + Help - String ID for Help + QuestionFlags - Flags in Question Header + Flags - Flags for ordered list opcode + DataType - Type for option value + MaxContainers - Maximum count for options in this ordered list + OptionsList - List of options + OptionCount - Number of options in option list + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateCheckBoxOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 CheckBoxFlags, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_CHECKBOX_OP opcode. + +Arguments: + QuestionId - Question ID + VarStoreId - Storage ID + VarOffset - Offset in Storage + Prompt - String ID for Prompt + Help - String ID for Help + QuestionFlags - Flags in Question Header + CheckBoxFlags - Flags for checkbox opcode + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateNumericOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 NumericFlags, + IN UINT64 Minimum, + IN UINT64 Maximum, + IN UINT64 Step, + IN UINT64 Default, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_NUMERIC_OP opcode. + +Arguments: + QuestionId - Question ID + VarStoreId - Storage ID + VarOffset - Offset in Storage + Prompt - String ID for Prompt + Help - String ID for Help + QuestionFlags - Flags in Question Header + NumericFlags - Flags for numeric opcode + Minimum - Numeric minimum value + Maximum - Numeric maximum value + Step - Numeric step for edit + Default - Numeric default value + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateStringOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 StringFlags, + IN UINT8 MinSize, + IN UINT8 MaxSize, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create EFI_IFR_STRING_OP opcode. + +Arguments: + QuestionId - Question ID + VarStoreId - Storage ID + VarOffset - Offset in Storage + Prompt - String ID for Prompt + Help - String ID for Help + QuestionFlags - Flags in Question Header + StringFlags - Flags for string opcode + MinSize - String minimum length + MaxSize - String maximum length + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_STATUS +CreateBannerOpCode ( + IN EFI_STRING_ID Title, + IN UINT16 LineNumber, + IN UINT8 Alignment, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + Create GUIDed opcode for banner. + +Arguments: + Title - String ID for title + LineNumber - Line number for this banner + Alignment - Alignment for this banner, left, center or right + Data - Destination for the created opcode binary + +Returns: + EFI_SUCCESS - Opcode create success + +--*/ +; + +EFI_HII_PACKAGE_LIST_HEADER * +PreparePackageList ( + IN UINTN NumberOfPackages, + IN EFI_GUID *GuidId, + ... + ) +/*++ + +Routine Description: + Assemble EFI_HII_PACKAGE_LIST according to the passed in packages. + +Arguments: + NumberOfPackages - Number of packages. + GuidId - Package GUID. + +Returns: + Pointer of EFI_HII_PACKAGE_LIST_HEADER. + +--*/ +; + +EFI_STATUS +CreateHiiDriverHandle ( + OUT EFI_HANDLE *DriverHandle + ) +/*++ + +Routine Description: + The HII driver handle passed in for HiiDatabase.NewPackageList() requires + that there should be DevicePath Protocol installed on it. + This routine create a virtual Driver Handle by installing a vendor device + path on it, so as to use it to invoke HiiDatabase.NewPackageList(). + +Arguments: + DriverHandle - Handle to be returned + +Returns: + EFI_SUCCESS - Handle destroy success. + EFI_OUT_OF_RESOURCES - Not enough memory. + +--*/ +; + +EFI_STATUS +DestroyHiiDriverHandle ( + IN EFI_HANDLE DriverHandle + ) +/*++ + +Routine Description: + Destroy the Driver Handle created by CreateHiiDriverHandle(). + +Arguments: + DriverHandle - Handle returned by CreateHiiDriverHandle() + +Returns: + EFI_SUCCESS - Handle destroy success. + other - Handle destroy fail. + +--*/ +; + +EFI_HII_HANDLE +DevicePathToHiiHandle ( + IN EFI_HII_DATABASE_PROTOCOL *HiiDatabase, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Find HII Handle associated with given Device Path. + +Arguments: + HiiDatabase - Point to EFI_HII_DATABASE_PROTOCOL instance. + DevicePath - Device Path associated with the HII package list handle. + +Returns: + Handle - HII package list Handle associated with the Device Path. + NULL - Hii Package list handle is not found. + +--*/ +; + +EFI_STATUS +ExtractDefault( + IN VOID *Buffer, + IN UINTN *BufferSize, + UINTN Number, + ... + ) +/*++ + + Routine Description: + Configure the buffer accrording to ConfigBody strings. + + Arguments: + DefaultId - the ID of default. + Buffer - the start address of buffer. + BufferSize - the size of buffer. + Number - the number of the strings. + + Returns: + EFI_BUFFER_TOO_SMALL - the BufferSize is too small to operate. + EFI_INVALID_PARAMETER - Buffer is NULL or BufferSize is 0. + EFI_SUCCESS - Operation successful. + +--*/ +; + +EFI_STATUS +ConstructConfigAltResp ( + IN EFI_STRING ConfigRequest, OPTIONAL + OUT EFI_STRING *Progress, + OUT EFI_STRING *ConfigAltResp, + IN EFI_GUID *Guid, + IN CHAR16 *Name, + IN EFI_HANDLE *DriverHandle, + IN VOID *BufferStorage, + IN UINTN BufferStorageSize, + IN VOID *BlockNameArray, OPTIONAL + IN UINTN NumberAltCfg, + ... +//IN UINT16 AltCfgId, +//IN VOID *DefaultValueArray, + ) +/*++ + + Routine Description: + + Construct <ConfigAltResp> for a buffer storage. + + Arguments: + ConfigRequest - The Config request string. If set to NULL, all the + configurable elements will be extracted from BlockNameArray. + ConfigAltResp - The returned <ConfigAltResp>. + Progress - On return, points to a character in the Request. + Guid - GUID of the buffer storage. + Name - Name of the buffer storage. + DriverHandle - The DriverHandle which is used to invoke HiiDatabase + protocol interface NewPackageList(). + BufferStorage - Content of the buffer storage. + BufferStorageSize - Length in bytes of the buffer storage. + BlockNameArray - Array generated by VFR compiler. + NumberAltCfg - Number of Default value array generated by VFR compiler. + The sequential input parameters will be number of + AltCfgId and DefaultValueArray pairs. When set to 0, + there will be no <AltResp>. + + Returns: + EFI_OUT_OF_RESOURCES - Run out of memory resource. + EFI_INVALID_PARAMETER - ConfigAltResp is NULL. + EFI_SUCCESS - Operation successful. + +--*/ +; + +EFI_STATUS +ExtractGuidFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + OUT EFI_GUID *Guid + ) +/*++ + +Routine Description: + Extract Hii package list GUID for given HII handle. + +Arguments: + HiiHandle - Hii handle + Guid - Package list GUID + +Returns: + EFI_SUCCESS - Successfully extract GUID from Hii database. + +--*/ +; + +EFI_STATUS +ExtractClassFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + OUT UINT16 *Class, + OUT EFI_STRING_ID *FormSetTitle, + OUT EFI_STRING_ID *FormSetHelp + ) +/*++ + +Routine Description: + Extract formset class for given HII handle. + +Arguments: + HiiHandle - Hii handle + Class - Class of the formset + FormSetTitle - Formset title string + FormSetHelp - Formset help string + +Returns: + EFI_SUCCESS - Successfully extract Class for specified Hii handle. + +--*/ +; + +EFI_STATUS +ExtractClassGuidFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + OUT UINT8 *NumberOfClassGuid, + OUT EFI_GUID **ClassGuid, + OUT EFI_STRING_ID *FormSetTitle, + OUT EFI_STRING_ID *FormSetHelp + ) +/*++ + +Routine Description: + Extract formset ClassGuid for given HII handle. + +Arguments: + HiiHandle - Hii handle + NumberOfClassGuid - Number of ClassGuid + ClassGuid - Pointer to callee allocated buffer, an array of ClassGuid + FormSetTitle - Formset title string + FormSetHelp - Formset help string + +Returns: + EFI_SUCCESS - Successfully extract Class for specified Hii handle. + +--*/ +; + +VOID +ToLower ( + IN OUT CHAR16 *Str + ) +/*++ + +Routine Description: + Converts the unicode character from uppercase to lowercase. + +Arguments: + Str - String to be converted + +Returns: + +--*/ +; + +EFI_STATUS +BufferToHexString ( + IN OUT CHAR16 *Str, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Converts binary buffer to Unicode string in reversed byte order to BufToHexString(). + +Arguments: + Str - String for output + Buffer - Binary buffer. + BufferSize - Size of the buffer in bytes. + +Returns: + EFI_SUCCESS - The function completed successfully. + +--*/ +; + +EFI_STATUS +HexStringToBuffer ( + IN OUT UINT8 *Buffer, + IN OUT UINTN *BufferSize, + IN CHAR16 *Str + ) +/*++ + +Routine Description: + Converts Hex String to binary buffer in reversed byte order to HexStringToBuf(). + +Arguments: + Buffer - Pointer to buffer that receives the data. + BufferSize - Length in bytes of the buffer to hold converted data. + If routine return with EFI_SUCCESS, containing length of converted data. + If routine return with EFI_BUFFER_TOO_SMALL, containg length of buffer desired. + Str - String to be converted from. + +Returns: + EFI_SUCCESS - The function completed successfully. + +--*/ +; + +EFI_STATUS +ConfigStringToUnicode ( + IN OUT CHAR16 *UnicodeString, + IN OUT UINTN *StrBufferLen, + IN CHAR16 *ConfigString + ) +/*++ + +Routine Description: + Convert binary representation Config string (e.g. "0041004200430044") to the + original string (e.g. "ABCD"). Config string appears in <ConfigHdr> (i.e. + "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>"). + +Arguments: + UnicodeString - Original Unicode string. + StrBufferLen - On input: Length in bytes of buffer to hold the Unicode string. + Includes tailing '\0' character. + On output: + If return EFI_SUCCESS, containing length of Unicode string buffer. + If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. + ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+ + +Returns: + EFI_SUCCESS - Routine success. + EFI_BUFFER_TOO_SMALL - The string buffer is too small. + +--*/ +; + +EFI_STATUS +UnicodeToConfigString ( + IN OUT CHAR16 *ConfigString, + IN OUT UINTN *StrBufferLen, + IN CHAR16 *UnicodeString + ) +/*++ + +Routine Description: + Convert Unicode string to binary representation Config string, e.g. + "ABCD" => "0041004200430044". Config string appears in <ConfigHdr> (i.e. + "&NAME=<string>"), or Name/Value pair in <ConfigBody> (i.e. "label=<string>"). + +Arguments: + ConfigString - Binary representation of Unicode String, <string> := (<HexCh>4)+ + StrBufferLen - On input: Length in bytes of buffer to hold the Unicode string. + Includes tailing '\0' character. + On output: + If return EFI_SUCCESS, containing length of Unicode string buffer. + If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. + UnicodeString - Original Unicode string. + +Returns: + EFI_SUCCESS - Routine success. + EFI_BUFFER_TOO_SMALL - The string buffer is too small. + +--*/ +; + +EFI_STATUS +ConstructConfigHdr ( + IN OUT CHAR16 *ConfigHdr, + IN OUT UINTN *StrBufferLen, + IN EFI_GUID *Guid, + IN CHAR16 *Name, OPTIONAL + IN EFI_HANDLE *DriverHandle + ) +/*++ + +Routine Description: + Construct <ConfigHdr> using routing information GUID/NAME/PATH. + +Arguments: + ConfigHdr - Pointer to the ConfigHdr string. + StrBufferLen - On input: Length in bytes of buffer to hold the ConfigHdr string. Includes tailing '\0' character. + On output: + If return EFI_SUCCESS, containing length of ConfigHdr string buffer. + If return EFI_BUFFER_TOO_SMALL, containg length of string buffer desired. + Guid - Routing information: GUID. + Name - Routing information: NAME. + DriverHandle - Driver handle which contains the routing information: PATH. + +Returns: + EFI_SUCCESS - Routine success. + EFI_BUFFER_TOO_SMALL - The ConfigHdr string buffer is too small. + +--*/ +; + +BOOLEAN +IsConfigHdrMatch ( + IN EFI_STRING ConfigString, + IN EFI_GUID *StorageGuid, OPTIONAL + IN CHAR16 *StorageName OPTIONAL + ) +/*++ + +Routine Description: + Determines if the Routing data (Guid and Name) is correct in <ConfigHdr>. + +Arguments: + ConfigString - Either <ConfigRequest> or <ConfigResp>. + StorageGuid - GUID of the storage. + StorageName - Name of the stoarge. + +Returns: + TRUE - Routing information is correct in ConfigString. + FALSE - Routing information is incorrect in ConfigString. + +--*/ +; + +BOOLEAN +FindBlockName ( + IN OUT CHAR16 *String, + UINTN Offset, + UINTN Width + ) +/*++ + +Routine Description: + Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string. + +Arguments: + String - The string to be searched in. + Offset - Offset in BlockName. + Width - Width in BlockName. + +Returns: + TRUE - Block name found. + FALSE - Block name not found. + +--*/ +; + +EFI_STATUS +GetBrowserData ( + EFI_GUID *VariableGuid, OPTIONAL + CHAR16 *VariableName, OPTIONAL + UINTN *BufferSize, + UINT8 *Buffer + ) +/*++ + +Routine Description: + This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser. + +Arguments: + VariableGuid - An optional field to indicate the target variable GUID name to use. + VariableName - An optional field to indicate the target human-readable variable name. + BufferSize - On input: Length in bytes of buffer to hold retrived data. + On output: + If return EFI_BUFFER_TOO_SMALL, containg length of buffer desired. + Buffer - Buffer to hold retrived data. + +Returns: + EFI_SUCCESS - Routine success. + EFI_BUFFER_TOO_SMALL - The intput buffer is too small. + +--*/ +; + +EFI_STATUS +GetHiiHandles ( + IN OUT UINTN *HandleBufferLength, + OUT EFI_HII_HANDLE **HiiHandleBuffer + ) +/*++ + +Routine Description: + Determines the handles that are currently active in the database. + It's the caller's responsibility to free handle buffer. + +Arguments: + HiiDatabase - A pointer to the EFI_HII_DATABASE_PROTOCOL instance. + HandleBufferLength - On input, a pointer to the length of the handle buffer. On output, + the length of the handle buffer that is required for the handles found. + HiiHandleBuffer - Pointer to an array of Hii Handles returned. + +Returns: + EFI_SUCCESS - Get an array of Hii Handles successfully. + EFI_INVALID_PARAMETER - Hii is NULL. + EFI_NOT_FOUND - Database not found. + +--*/ +; + +EFI_STATUS +SetBrowserData ( + EFI_GUID *VariableGuid, OPTIONAL + CHAR16 *VariableName, OPTIONAL + UINTN BufferSize, + UINT8 *Buffer, + CHAR16 *RequestElement OPTIONAL + ) +/*++ + +Routine Description: + This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser. + +Arguments: + VariableGuid - An optional field to indicate the target variable GUID name to use. + VariableName - An optional field to indicate the target human-readable variable name. + BufferSize - Length in bytes of buffer to hold retrived data. + Buffer - Buffer to hold retrived data. + RequestElement - An optional field to specify which part of the buffer data + will be send back to Browser. If NULL, the whole buffer of + data will be committed to Browser. + <RequestElement> ::= &OFFSET=<Number>&WIDTH=<Number>* + +Returns: + EFI_SUCCESS - Routine success. + Other - Updating Browser uncommitted data failed. + +--*/ +; + +EFI_STATUS +ConvertRfc3066LanguageToIso639Language ( + CHAR8 *LanguageRfc3066, + CHAR8 *LanguageIso639 + ) +/*++ + +Routine Description: + Convert language code from RFC3066 to ISO639-2. + +Arguments: + LanguageRfc3066 - RFC3066 language code. + LanguageIso639 - ISO639-2 language code. + +Returns: + EFI_SUCCESS - Language code converted. + EFI_NOT_FOUND - Language code not found. + +--*/ +; + +CHAR8 * +Rfc3066ToIso639 ( + CHAR8 *SupportedLanguages + ) +/*++ + +Routine Description: + Convert language code list from RFC3066 to ISO639-2, e.g. "en-US;fr-FR" will + be converted to "engfra". + +Arguments: + SupportedLanguages - The RFC3066 language list. + +Returns: + The ISO639-2 language list. + +--*/ +; + +EFI_STATUS +GetCurrentLanguage ( + OUT CHAR8 *Lang + ) +/*++ + +Routine Description: + Determine what is the current language setting + +Arguments: + Lang - Pointer of system language + +Returns: + Status code + +--*/ +; + +VOID +GetNextLanguage ( + IN OUT CHAR8 **LangCode, + OUT CHAR8 *Lang + ) +/*++ + +Routine Description: + Get next language from language code list. + +Arguments: + LangCode - The language code. + Lang - Returned language. + +Returns: + None. + +--*/ +; + +CHAR8 * +GetSupportedLanguages ( + IN EFI_HII_HANDLE HiiHandle + ) +/*++ + +Routine Description: + This function returns the list of supported languages, in the format specified + in UEFI specification Appendix M. + +Arguments: + HiiHandle - The HII package list handle. + +Returns: + The supported languages. + +--*/ +; + +UINT16 +GetSupportedLanguageNumber ( + IN EFI_HII_HANDLE HiiHandle + ) +/*++ + +Routine Description: + This function returns the number of supported languages + +Arguments: + HiiHandle - The HII package list handle. + +Returns: + The number of supported languages. + +--*/ +; + +EFI_STATUS +GetStringFromHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_STRING_ID StringId, + OUT EFI_STRING *String + ) +/*++ + +Routine Description: + Get string specified by StringId form the HiiHandle. + +Arguments: + HiiHandle - The HII handle of package list. + StringId - The String ID. + String - The output string. + +Returns: + EFI_NOT_FOUND - String is not found. + EFI_SUCCESS - Operation is successful. + EFI_OUT_OF_RESOURCES - There is not enought memory in the system. + EFI_INVALID_PARAMETER - The String is NULL. + +--*/ +; + +EFI_STATUS +GetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN EFI_STRING_ID StringId, + OUT EFI_STRING *String + ) +/*++ + +Routine Description: + Get the string given the StringId and String package Producer's Guid. + +Arguments: + ProducerGuid - The Guid of String package list. + StringId - The String ID. + String - The output string. + +Returns: + EFI_NOT_FOUND - String is not found. + EFI_SUCCESS - Operation is successful. + EFI_OUT_OF_RESOURCES - There is not enought memory in the system. + +--*/ +; + +EFI_STATUS +IfrLibNewString ( + IN EFI_HII_HANDLE PackageList, + OUT EFI_STRING_ID *StringId, + IN CONST EFI_STRING String + ) +/*++ + + Routine Description: + This function adds the string into String Package of each language. + + Arguments: + PackageList - Handle of the package list where this string will be added. + StringId - On return, contains the new strings id, which is unique within PackageList. + String - Points to the new null-terminated string. + + Returns: + EFI_SUCCESS - The new string was added successfully. + EFI_NOT_FOUND - The specified PackageList could not be found in database. + EFI_OUT_OF_RESOURCES - Could not add the string due to lack of resources. + EFI_INVALID_PARAMETER - String is NULL or StringId is NULL is NULL. + +--*/ +; + +EFI_STATUS +IfrLibGetString ( + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + OUT EFI_STRING String, + IN OUT UINTN *StringSize + ) +/*++ + + Routine Description: + This function try to retrieve string from String package of current language. + If fail, it try to retrieve string from String package of first language it support. + + Arguments: + PackageList - The package list in the HII database to search for the specified string. + StringId - The string's id, which is unique within PackageList. + String - Points to the new null-terminated string. + StringSize - On entry, points to the size of the buffer pointed to by String, in bytes. On return, + points to the length of the string, in bytes. + + Returns: + EFI_SUCCESS - The string was returned successfully. + EFI_NOT_FOUND - The string specified by StringId is not available. + EFI_BUFFER_TOO_SMALL - The buffer specified by StringLength is too small to hold the string. + EFI_INVALID_PARAMETER - The String or StringSize was NULL. + +--*/ +; + +EFI_STATUS +IfrLibSetString ( + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + IN CONST EFI_STRING String + ) +/*++ + + Routine Description: + This function updates the string in String package of current language. + + Arguments: + PackageList - The package list containing the strings. + StringId - The string's id, which is unique within PackageList. + String - Points to the new null-terminated string. + + Returns: + EFI_SUCCESS - The string was updated successfully. + EFI_NOT_FOUND - The string specified by StringId is not in the database. + EFI_INVALID_PARAMETER - The String was NULL. + EFI_OUT_OF_RESOURCES - The system is out of resources to accomplish the task. + +--*/ +; + +EFI_STATUS +IfrLibCreatePopUp ( + IN UINTN NumberOfLines, + OUT EFI_INPUT_KEY *KeyValue, + IN CHAR16 *String, + ... + ) +/*++ + +Routine Description: + Draw a dialog and return the selected key. + +Arguments: + NumberOfLines - The number of lines for the dialog box + KeyValue - The EFI_KEY value returned if HotKey is TRUE.. + String - Pointer to the first string in the list + ... - A series of (quantity == NumberOfLines) text strings which + will be used to construct the dialog box + +Returns: + EFI_SUCCESS - Displayed dialog and received user interaction + EFI_INVALID_PARAMETER - One of the parameters was invalid. + +--*/ +; + +EFI_STATUS +IfrLibInitUpdateData ( + IN OUT EFI_HII_UPDATE_DATA *UpdateData, + IN UINT32 BufferSize + ) +/*++ + +Routine Description: + This function initialize the data structure for dynamic opcode. + +Arguments: + UpdateData - The adding data; + BufferSize - Length of the buffer to fill dynamic opcodes. + +Returns: + EFI_SUCCESS - Update data is initialized. + EFI_INVALID_PARAMETER - UpdateData is NULL. + EFI_OUT_OF_RESOURCES - No enough memory to allocate. + +--*/ +; + +EFI_STATUS +IfrLibFreeUpdateData ( + IN EFI_HII_UPDATE_DATA *UpdateData + ) +/*++ + +Routine Description: + This function free the resource of update data. + +Arguments: + UpdateData - The adding data; + +Returns: + EFI_SUCCESS - Resource in UpdateData is released. + EFI_INVALID_PARAMETER - UpdateData is NULL. + +--*/ +; + +EFI_STATUS +IfrLibUpdateForm ( + IN EFI_HII_HANDLE Handle, + IN EFI_GUID *FormSetGuid, OPTIONAL + IN EFI_FORM_ID FormId, + IN UINT16 Label, + IN BOOLEAN Insert, + 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 + FormSetGuid - The formset should be updated. + FormId - The form should be updated. + Label - Update information starting immediately after this label in the IFR + Insert - If TRUE and Data is not NULL, insert data after Label. + If FALSE, replace opcodes between two labels with Data. + Data - The adding data; If NULL, remove opcodes between two Label. + +Returns: + EFI_SUCCESS - Update success. + Other - Update fail. + +--*/ +; + +BOOLEAN +HiiSetToDefaults ( + IN CONST EFI_STRING Request, OPTIONAL + IN UINT16 DefaultId + ) +/*++ + +Routine Description: + Reset the default value specified by DefaultId to the driver + configuration got by Request string. + + NULL request string support depends on the ExportConfig interface of + HiiConfigRouting protocol in UEFI specification. + +Arguments: + Request - A null-terminated Unicode string in + <MultiConfigRequest> format. It can be NULL. + If it is NULL, all configuration for the + entirety of the current HII database will be reset. + DefaultId - Specifies the type of defaults to retrieve. + +Returns: + TURE - The default value is set successfully. + FALSE - The default value can't be found and set. + +--*/ +; +#endif diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrOpCodeCreation.c b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrOpCodeCreation.c new file mode 100644 index 0000000..e6b37b8 --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrOpCodeCreation.c @@ -0,0 +1,638 @@ +/*++ + +Copyright (c) 2007 - 2009, 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: + + UefiIfrOpCodeCreation.c + +Abstract: + + Library Routines to create IFR independent of string data - assume tokens already exist + Primarily to be used for exporting op-codes at a label in pre-defined forms. + +Revision History: + +--*/ + +#include "UefiIfrLibrary.h" + +EFI_GUID mIfrVendorGuid = EFI_IFR_TIANO_GUID; + +STATIC +BOOLEAN +IsValidQuestionFlags ( + IN UINT8 Flags + ) +{ + return (Flags & (~QUESTION_FLAGS)) ? FALSE : TRUE; +} + +STATIC +BOOLEAN +IsValidValueType ( + IN UINT8 Type + ) +{ + return (Type <= EFI_IFR_TYPE_OTHER) ? TRUE : FALSE; +} + +STATIC +BOOLEAN +IsValidNumricFlags ( + IN UINT8 Flags + ) +{ + if (Flags & ~(EFI_IFR_NUMERIC_SIZE | EFI_IFR_DISPLAY)) { + return FALSE; + } + + if ((Flags & EFI_IFR_DISPLAY) > EFI_IFR_DISPLAY_UINT_HEX) { + return FALSE; + } + + return TRUE; +} + +STATIC +BOOLEAN +IsValidCheckboxFlags ( + IN UINT8 Flags + ) +{ + return (Flags <= EFI_IFR_CHECKBOX_DEFAULT_MFG) ? TRUE : FALSE; +} + +EFI_STATUS +CreateEndOpCode ( + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_END End; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (Data->Offset + sizeof (EFI_IFR_END) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + End.Header.Length = sizeof (EFI_IFR_END); + End.Header.OpCode = EFI_IFR_END_OP; + End.Header.Scope = 0; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &End, sizeof (EFI_IFR_END)); + Data->Offset += sizeof (EFI_IFR_END); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateDefaultOpCode ( + IN EFI_IFR_TYPE_VALUE *Value, + IN UINT8 Type, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_DEFAULT Default; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if ((Value == NULL) || !IsValidValueType (Type)) { + return EFI_INVALID_PARAMETER; + } + + if (Data->Offset + sizeof (EFI_IFR_DEFAULT) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + Default.Header.OpCode = EFI_IFR_DEFAULT_OP; + Default.Header.Length = sizeof (EFI_IFR_DEFAULT); + Default.Header.Scope = 0; + Default.Type = Type; + Default.DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + EfiCopyMem (&Default.Value, Value, sizeof(EFI_IFR_TYPE_VALUE)); + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &Default, sizeof (EFI_IFR_DEFAULT)); + Data->Offset += sizeof (EFI_IFR_DEFAULT); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateActionOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN EFI_STRING_ID QuestionConfig, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_ACTION Action; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (!IsValidQuestionFlags (QuestionFlags)) { + return EFI_INVALID_PARAMETER; + } + + if (Data->Offset + sizeof (EFI_IFR_ACTION) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + Action.Header.OpCode = EFI_IFR_ACTION_OP; + Action.Header.Length = sizeof (EFI_IFR_ACTION); + Action.Header.Scope = 0; + Action.Question.QuestionId = QuestionId; + Action.Question.Header.Prompt = Prompt; + Action.Question.Header.Help = Help; + Action.Question.VarStoreId = INVALID_VARSTORE_ID; + Action.Question.Flags = QuestionFlags; + Action.QuestionConfig = QuestionConfig; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &Action, sizeof (EFI_IFR_ACTION)); + Data->Offset += sizeof (EFI_IFR_ACTION); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateSubTitleOpCode ( + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 Flags, + IN UINT8 Scope, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_SUBTITLE Subtitle; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (Data->Offset + sizeof (EFI_IFR_SUBTITLE) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP; + Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE); + Subtitle.Header.Scope = Scope; + Subtitle.Statement.Prompt = Prompt; + Subtitle.Statement.Help = Help; + Subtitle.Flags = Flags; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE)); + Data->Offset += sizeof (EFI_IFR_SUBTITLE); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateTextOpCode ( + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN EFI_STRING_ID TextTwo, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_TEXT Text; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (Data->Offset + sizeof (EFI_IFR_TEXT) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + Text.Header.OpCode = EFI_IFR_TEXT_OP; + Text.Header.Length = sizeof (EFI_IFR_TEXT); + Text.Header.Scope = 0; + Text.Statement.Prompt = Prompt; + Text.Statement.Help = Help; + Text.TextTwo = TextTwo; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &Text, sizeof (EFI_IFR_TEXT)); + Data->Offset += sizeof (EFI_IFR_TEXT); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateGotoOpCode ( + IN EFI_FORM_ID FormId, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN EFI_QUESTION_ID QuestionId, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_REF Goto; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (!IsValidQuestionFlags (QuestionFlags)) { + return EFI_INVALID_PARAMETER; + } + + if (Data->Offset + sizeof (EFI_IFR_REF) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + Goto.Header.OpCode = EFI_IFR_REF_OP; + Goto.Header.Length = sizeof (EFI_IFR_REF); + Goto.Header.Scope = 0; + Goto.Question.Header.Prompt = Prompt; + Goto.Question.Header.Help = Help; + Goto.Question.VarStoreId = INVALID_VARSTORE_ID; + Goto.Question.QuestionId = QuestionId; + Goto.Question.Flags = QuestionFlags; + Goto.FormId = FormId; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &Goto, sizeof (EFI_IFR_REF)); + Data->Offset += sizeof (EFI_IFR_REF); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateOneOfOptionOpCode ( + IN UINTN OptionCount, + IN IFR_OPTION *OptionsList, + IN UINT8 Type, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + UINTN Index; + UINT8 *LocalBuffer; + EFI_IFR_ONE_OF_OPTION OneOfOption; + + ASSERT (Data != NULL && Data->Data != NULL); + + if ((OptionCount != 0) && (OptionsList == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (Data->Offset + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + for (Index = 0; Index < OptionCount; Index++) { + OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; + OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); + OneOfOption.Header.Scope = 0; + + OneOfOption.Option = OptionsList[Index].StringToken; + OneOfOption.Value = OptionsList[Index].Value; + OneOfOption.Flags = OptionsList[Index].Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG); + OneOfOption.Type = Type; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION)); + Data->Offset += sizeof (EFI_IFR_ONE_OF_OPTION); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateOneOfOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 OneOfFlags, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + UINTN Length; + EFI_IFR_ONE_OF OneOf; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (!IsValidNumricFlags (OneOfFlags) || + !IsValidQuestionFlags (QuestionFlags) || + ((OptionCount != 0) && (OptionsList == NULL))) { + return EFI_INVALID_PARAMETER; + } + + Length = sizeof (EFI_IFR_ONE_OF) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END); + if (Data->Offset + Length > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP; + OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF); + OneOf.Header.Scope = 1; + OneOf.Question.Header.Prompt = Prompt; + OneOf.Question.Header.Help = Help; + OneOf.Question.QuestionId = QuestionId; + OneOf.Question.VarStoreId = VarStoreId; + OneOf.Question.VarStoreInfo.VarOffset = VarOffset; + OneOf.Question.Flags = QuestionFlags; + OneOf.Flags = OneOfFlags; + EfiZeroMem ((VOID *) &OneOf.data, sizeof (MINMAXSTEP_DATA)); + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF)); + Data->Offset += sizeof (EFI_IFR_ONE_OF); + + CreateOneOfOptionOpCode (OptionCount, OptionsList, (OneOfFlags & EFI_IFR_NUMERIC_SIZE), Data); + + CreateEndOpCode (Data); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateOrderedListOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 OrderedListFlags, + IN UINT8 DataType, + IN UINT8 MaxContainers, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + UINTN Length; + EFI_IFR_ORDERED_LIST OrderedList; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (!IsValidQuestionFlags (QuestionFlags) || + ((OptionCount != 0) && (OptionsList == NULL))) { + return EFI_INVALID_PARAMETER; + } + + if ((OrderedListFlags & (~(EFI_IFR_UNIQUE_SET | EFI_IFR_NO_EMPTY_SET))) != 0) { + return EFI_INVALID_PARAMETER; + } + + Length = sizeof (EFI_IFR_ORDERED_LIST) + OptionCount * sizeof (EFI_IFR_ONE_OF_OPTION) + sizeof (EFI_IFR_END); + if (Data->Offset + Length > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP; + OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST); + OrderedList.Header.Scope = 1; + OrderedList.Question.Header.Prompt = Prompt; + OrderedList.Question.Header.Help = Help; + OrderedList.Question.QuestionId = QuestionId; + OrderedList.Question.VarStoreId = VarStoreId; + OrderedList.Question.VarStoreInfo.VarOffset = VarOffset; + OrderedList.Question.Flags = QuestionFlags; + OrderedList.MaxContainers = MaxContainers; + OrderedList.Flags = OrderedListFlags; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST)); + Data->Offset += sizeof (EFI_IFR_ORDERED_LIST); + + CreateOneOfOptionOpCode (OptionCount, OptionsList, DataType, Data); + + CreateEndOpCode (Data); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateCheckBoxOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 CheckBoxFlags, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_CHECKBOX CheckBox; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (!IsValidQuestionFlags (QuestionFlags) || !IsValidCheckboxFlags (CheckBoxFlags)) { + return EFI_INVALID_PARAMETER; + } + + if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP; + CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX); + CheckBox.Header.Scope = 0; + CheckBox.Question.QuestionId = QuestionId; + CheckBox.Question.VarStoreId = VarStoreId; + CheckBox.Question.VarStoreInfo.VarOffset = VarOffset; + CheckBox.Question.Header.Prompt = Prompt; + CheckBox.Question.Header.Help = Help; + CheckBox.Question.Flags = QuestionFlags; + CheckBox.Flags = CheckBoxFlags; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX)); + Data->Offset += sizeof (EFI_IFR_CHECKBOX); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateNumericOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 NumericFlags, + IN UINT64 Minimum, + IN UINT64 Maximum, + IN UINT64 Step, + IN UINT64 Default, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + UINTN Length; + EFI_STATUS Status; + EFI_IFR_NUMERIC Numeric; + MINMAXSTEP_DATA MinMaxStep; + EFI_IFR_TYPE_VALUE DefaultValue; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (!IsValidQuestionFlags (QuestionFlags) || !IsValidNumricFlags (NumericFlags)) { + return EFI_INVALID_PARAMETER; + } + + Length = sizeof (EFI_IFR_NUMERIC) + sizeof (EFI_IFR_DEFAULT) + sizeof (EFI_IFR_END); + if (Data->Offset + sizeof (EFI_IFR_CHECKBOX) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP; + Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC); + Numeric.Header.Scope = 1; + Numeric.Question.QuestionId = QuestionId; + Numeric.Question.VarStoreId = VarStoreId; + Numeric.Question.VarStoreInfo.VarOffset = VarOffset; + Numeric.Question.Header.Prompt = Prompt; + Numeric.Question.Header.Help = Help; + Numeric.Question.Flags = QuestionFlags; + Numeric.Flags = NumericFlags; + + switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) { + case EFI_IFR_NUMERIC_SIZE_1: + MinMaxStep.u8.MinValue = (UINT8) Minimum; + MinMaxStep.u8.MaxValue = (UINT8) Maximum; + MinMaxStep.u8.Step = (UINT8) Step; + break; + + case EFI_IFR_NUMERIC_SIZE_2: + MinMaxStep.u16.MinValue = (UINT16) Minimum; + MinMaxStep.u16.MaxValue = (UINT16) Maximum; + MinMaxStep.u16.Step = (UINT16) Step; + break; + + case EFI_IFR_NUMERIC_SIZE_4: + MinMaxStep.u32.MinValue = (UINT32) Minimum; + MinMaxStep.u32.MaxValue = (UINT32) Maximum; + MinMaxStep.u32.Step = (UINT32) Step; + break; + + case EFI_IFR_NUMERIC_SIZE_8: + MinMaxStep.u64.MinValue = Minimum; + MinMaxStep.u64.MaxValue = Maximum; + MinMaxStep.u64.Step = Step; + break; + } + + EfiCopyMem (&Numeric.data, &MinMaxStep, sizeof (MINMAXSTEP_DATA)); + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC)); + Data->Offset += sizeof (EFI_IFR_NUMERIC); + + DefaultValue.u64 = Default; + Status = CreateDefaultOpCode (&DefaultValue, (NumericFlags & EFI_IFR_NUMERIC_SIZE), Data); + if (EFI_ERROR(Status)) { + return Status; + } + + CreateEndOpCode (Data); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateStringOpCode ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_VARSTORE_ID VarStoreId, + IN UINT16 VarOffset, + IN EFI_STRING_ID Prompt, + IN EFI_STRING_ID Help, + IN UINT8 QuestionFlags, + IN UINT8 StringFlags, + IN UINT8 MinSize, + IN UINT8 MaxSize, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_STRING String; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (!IsValidQuestionFlags (QuestionFlags) || (StringFlags & (~EFI_IFR_STRING_MULTI_LINE))) { + return EFI_INVALID_PARAMETER; + } + + if (Data->Offset + sizeof (EFI_IFR_STRING) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + String.Header.OpCode = EFI_IFR_STRING_OP; + String.Header.Length = sizeof (EFI_IFR_STRING); + String.Header.Scope = 0; + String.Question.Header.Prompt = Prompt; + String.Question.Header.Help = Help; + String.Question.QuestionId = QuestionId; + String.Question.VarStoreId = VarStoreId; + String.Question.VarStoreInfo.VarOffset = VarOffset; + String.Question.Flags = QuestionFlags; + String.MinSize = MinSize; + String.MaxSize = MaxSize; + String.Flags = StringFlags; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &String, sizeof (EFI_IFR_STRING)); + Data->Offset += sizeof (EFI_IFR_STRING); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateBannerOpCode ( + IN EFI_STRING_ID Title, + IN UINT16 LineNumber, + IN UINT8 Alignment, + IN OUT EFI_HII_UPDATE_DATA *Data + ) +{ + EFI_IFR_GUID_BANNER Banner; + UINT8 *LocalBuffer; + + ASSERT (Data != NULL && Data->Data != NULL); + + if (Data->Offset + sizeof (EFI_IFR_GUID_BANNER) > Data->BufferSize) { + return EFI_BUFFER_TOO_SMALL; + } + + Banner.Header.OpCode = EFI_IFR_GUID_OP; + Banner.Header.Length = sizeof (EFI_IFR_GUID_BANNER); + Banner.Header.Scope = 0; + EfiCopyMem (&Banner.Guid, &mIfrVendorGuid, sizeof (EFI_IFR_GUID)); + Banner.ExtendOpCode = EFI_IFR_EXTEND_OP_BANNER; + Banner.Title = Title; + Banner.LineNumber = LineNumber; + Banner.Alignment = Alignment; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + EfiCopyMem (LocalBuffer, &Banner, sizeof (EFI_IFR_GUID_BANNER)); + Data->Offset += sizeof (EFI_IFR_GUID_BANNER); + + return EFI_SUCCESS; +} diff --git a/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrString.c b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrString.c new file mode 100644 index 0000000..5341941 --- /dev/null +++ b/EDK/Foundation/Library/Dxe/UefiEfiIfrSupportLib/UefiIfrString.c @@ -0,0 +1,729 @@ +/*++ + +Copyright (c) 2007 - 2011, 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: + + UefiIfrString.c + +Abstract: + + Common Library Routines to assist to handle String and Language. + +--*/ + +#include "UefiIfrLibrary.h" + +// +// Lookup table of ISO639-2 3 character language codes to ISO 639-1 2 character language codes +// Each entry is 5 CHAR8 values long. The first 3 CHAR8 values are the ISO 639-2 code. +// The last 2 CHAR8 values are the ISO 639-1 code. +// +CHAR8 Iso639ToRfc3066ConversionTable[] = +"\ +aaraa\ +abkab\ +afraf\ +amham\ +araar\ +asmas\ +aymay\ +azeaz\ +bakba\ +belbe\ +benbn\ +bihbh\ +bisbi\ +bodbo\ +brebr\ +bulbg\ +catca\ +cescs\ +corkw\ +cosco\ +cymcy\ +danda\ +deude\ +dzodz\ +ellel\ +engen\ +epoeo\ +estet\ +euseu\ +faofo\ +fasfa\ +fijfj\ +finfi\ +frafr\ +fryfy\ +gaiga\ +gdhgd\ +glggl\ +grngn\ +gujgu\ +hauha\ +hebhe\ +hinhi\ +hrvhr\ +hunhu\ +hyehy\ +ikuiu\ +ileie\ +inaia\ +indid\ +ipkik\ +islis\ +itait\ +jawjw\ +jpnja\ +kalkl\ +kankn\ +kasks\ +katka\ +kazkk\ +khmkm\ +kinrw\ +kirky\ +korko\ +kurku\ +laolo\ +latla\ +lavlv\ +linln\ +litlt\ +ltzlb\ +malml\ +marmr\ +mkdmk\ +mlgmg\ +mltmt\ +molmo\ +monmn\ +mrimi\ +msams\ +myamy\ +nauna\ +nepne\ +nldnl\ +norno\ +ocioc\ +ormom\ +panpa\ +polpl\ +porpt\ +pusps\ +quequ\ +rohrm\ +ronro\ +runrn\ +rusru\ +sagsg\ +sansa\ +sinsi\ +slksk\ +slvsl\ +smise\ +smosm\ +snasn\ +sndsd\ +somso\ +sotst\ +spaes\ +sqisq\ +srpsr\ +sswss\ +sunsu\ +swasw\ +swesv\ +tamta\ +tattt\ +telte\ +tgktg\ +tgltl\ +thath\ +tsnts\ +tuktk\ +twitw\ +uigug\ +ukruk\ +urdur\ +uzbuz\ +vievi\ +volvo\ +wolwo\ +xhoxh\ +yidyi\ +zhaza\ +zhozh\ +zulzu\ +"; + +EFI_STATUS +ConvertRfc3066LanguageToIso639Language ( + CHAR8 *LanguageRfc3066, + CHAR8 *LanguageIso639 + ) +/*++ + +Routine Description: + Convert language code from RFC3066 to ISO639-2. + +Arguments: + LanguageRfc3066 - RFC3066 language code. + LanguageIso639 - ISO639-2 language code. + +Returns: + EFI_SUCCESS - Language code converted. + EFI_NOT_FOUND - Language code not found. + +--*/ +{ + UINTN Index; + + if ((LanguageRfc3066[2] != '-') && (LanguageRfc3066[2] != 0)) { + EfiCopyMem (LanguageIso639, LanguageRfc3066, 3); + return EFI_SUCCESS; + } + + for (Index = 0; Iso639ToRfc3066ConversionTable[Index] != 0; Index += 5) { + if (EfiCompareMem (LanguageRfc3066, &Iso639ToRfc3066ConversionTable[Index + 3], 2) == 0) { + EfiCopyMem (LanguageIso639, &Iso639ToRfc3066ConversionTable[Index], 3); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +CHAR8 * +Rfc3066ToIso639 ( + CHAR8 *SupportedLanguages + ) +/*++ + +Routine Description: + Convert language code list from RFC3066 to ISO639-2, e.g. "en-US;fr-FR" will + be converted to "engfra". + +Arguments: + SupportedLanguages - The RFC3066 language list. + +Returns: + The ISO639-2 language list. + +--*/ +{ + CHAR8 *Languages; + CHAR8 *ReturnValue; + CHAR8 *LangCodes; + CHAR8 LangRfc3066[RFC_3066_ENTRY_SIZE]; + CHAR8 LangIso639[ISO_639_2_ENTRY_SIZE]; + EFI_STATUS Status; + + ReturnValue = EfiLibAllocateZeroPool (EfiAsciiStrSize (SupportedLanguages)); + if (ReturnValue == NULL) { + return ReturnValue; + } + + Languages = ReturnValue; + LangCodes = SupportedLanguages; + while (*LangCodes != 0) { + GetNextLanguage (&LangCodes, LangRfc3066); + + Status = ConvertRfc3066LanguageToIso639Language (LangRfc3066, LangIso639); + if (!EFI_ERROR (Status)) { + EfiCopyMem (Languages, LangIso639, 3); + Languages = Languages + 3; + } + } + + return ReturnValue; +} + +EFI_STATUS +GetCurrentLanguage ( + OUT CHAR8 *Lang + ) +/*++ + +Routine Description: + Determine what is the current language setting + +Arguments: + Lang - Pointer of system language + +Returns: + Status code + +--*/ +{ + EFI_STATUS Status; + UINTN Size; + + // + // Get current language setting + // + Size = RFC_3066_ENTRY_SIZE; + Status = gRT->GetVariable ( + L"PlatformLang", + &gEfiGlobalVariableGuid, + NULL, + &Size, + Lang + ); + + if (EFI_ERROR (Status)) { + EfiAsciiStrCpy (Lang, "en-US"); + } + + return Status; +} + +VOID +GetNextLanguage ( + IN OUT CHAR8 **LangCode, + OUT CHAR8 *Lang + ) +/*++ + +Routine Description: + Get next language from language code list (with separator ';'). + +Arguments: + LangCode - On input: point to first language in the list. On output: point to + next language in the list, or NULL if no more language in the list. + Lang - The first language in the list. + +Returns: + None. + +--*/ +{ + UINTN Index; + CHAR8 *StringPtr; + + if (LangCode == NULL || *LangCode == NULL) { + *Lang = 0; + return; + } + + Index = 0; + StringPtr = *LangCode; + while (StringPtr[Index] != 0 && StringPtr[Index] != ';') { + Index++; + } + + EfiCopyMem (Lang, StringPtr, Index); + Lang[Index] = 0; + + if (StringPtr[Index] == ';') { + Index++; + } + *LangCode = StringPtr + Index; +} + +CHAR8 * +GetSupportedLanguages ( + IN EFI_HII_HANDLE HiiHandle + ) +/*++ + +Routine Description: + This function returns the list of supported languages, in the format specified + in UEFI specification Appendix M. + +Arguments: + HiiHandle - The HII package list handle. + +Returns: + The supported languages. + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + CHAR8 *LanguageString; + + LocateHiiProtocols (); + + // + // Collect current supported Languages for given HII handle + // + BufferSize = 0x1000; + LanguageString = EfiLibAllocatePool (BufferSize); + Status = gIfrLibHiiString->GetLanguages (gIfrLibHiiString, HiiHandle, LanguageString, &BufferSize); + if (Status == EFI_BUFFER_TOO_SMALL) { + gBS->FreePool (LanguageString); + LanguageString = EfiLibAllocatePool (BufferSize); + Status = gIfrLibHiiString->GetLanguages (gIfrLibHiiString, HiiHandle, LanguageString, &BufferSize); + } + + if (EFI_ERROR (Status)) { + LanguageString = NULL; + } + + return LanguageString; +} + +UINT16 +GetSupportedLanguageNumber ( + IN EFI_HII_HANDLE HiiHandle + ) +/*++ + +Routine Description: + This function returns the number of supported languages + +Arguments: + HiiHandle - The HII package list handle. + +Returns: + The number of supported languages. + +--*/ +{ + CHAR8 *Languages; + CHAR8 *LanguageString; + UINT16 LangNumber; + CHAR8 Lang[RFC_3066_ENTRY_SIZE]; + + Languages = GetSupportedLanguages (HiiHandle); + if (Languages == NULL) { + return 0; + } + + LangNumber = 0; + LanguageString = Languages; + while (*LanguageString != 0) { + GetNextLanguage (&LanguageString, Lang); + LangNumber++; + } + gBS->FreePool (Languages); + + return LangNumber; +} + +EFI_STATUS +GetStringFromHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_STRING_ID StringId, + OUT EFI_STRING *String + ) +/*++ + +Routine Description: + Get string specified by StringId form the HiiHandle. + +Arguments: + HiiHandle - The HII handle of package list. + StringId - The String ID. + String - The output string. + +Returns: + EFI_NOT_FOUND - String is not found. + EFI_SUCCESS - Operation is successful. + EFI_OUT_OF_RESOURCES - There is not enought memory in the system. + EFI_INVALID_PARAMETER - The String is NULL. + +--*/ +{ + EFI_STATUS Status; + UINTN StringSize; + + if (String == NULL) { + return EFI_INVALID_PARAMETER; + } + + StringSize = IFR_LIB_DEFAULT_STRING_SIZE; + *String = EfiLibAllocateZeroPool (StringSize); + if (*String == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = IfrLibGetString (HiiHandle, StringId, *String, &StringSize); + if (Status == EFI_BUFFER_TOO_SMALL) { + gBS->FreePool (*String); + *String = EfiLibAllocateZeroPool (StringSize); + if (*String == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = IfrLibGetString (HiiHandle, StringId, *String, &StringSize); + } + + return Status; +} + +EFI_STATUS +GetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN EFI_STRING_ID StringId, + OUT EFI_STRING *String + ) +/*++ + +Routine Description: + Get the string given the StringId and String package Producer's Guid. + +Arguments: + ProducerGuid - The Guid of String package list. + StringId - The String ID. + String - The output string. + +Returns: + EFI_NOT_FOUND - String is not found. + EFI_SUCCESS - Operation is successful. + EFI_OUT_OF_RESOURCES - There is not enought memory in the system. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleBufferLen; + EFI_HII_HANDLE *HiiHandleBuffer; + EFI_GUID Guid; + + Status = GetHiiHandles (&HandleBufferLen, &HiiHandleBuffer); + if (HiiHandleBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + if (EFI_ERROR(Status)) { + return Status; + } + for (Index = 0; Index < (HandleBufferLen / sizeof (EFI_HII_HANDLE)); Index++) { + Status = ExtractGuidFromHiiHandle (HiiHandleBuffer[Index], &Guid); + if (EFI_ERROR(Status)) { + return Status; + } + if (EfiCompareGuid (&Guid, ProducerGuid) == TRUE) { + break; + } + } + + if (Index >= (HandleBufferLen / sizeof (EFI_HII_HANDLE))) { + Status = EFI_NOT_FOUND; + goto Out; + } + + Status = GetStringFromHandle (HiiHandleBuffer[Index], StringId, String); + +Out: + if (HiiHandleBuffer != NULL) { + gBS->FreePool (HiiHandleBuffer); + } + return Status; +} + +EFI_STATUS +IfrLibNewString ( + IN EFI_HII_HANDLE PackageList, + OUT EFI_STRING_ID *StringId, + IN CONST EFI_STRING String + ) +/*++ + + Routine Description: + This function adds the string into String Package of each language. + + Arguments: + PackageList - Handle of the package list where this string will be added. + StringId - On return, contains the new strings id, which is unique within PackageList. + String - Points to the new null-terminated string. + + Returns: + EFI_SUCCESS - The new string was added successfully. + EFI_NOT_FOUND - The specified PackageList could not be found in database. + EFI_OUT_OF_RESOURCES - Could not add the string due to lack of resources. + EFI_INVALID_PARAMETER - String is NULL or StringId is NULL is NULL. + +--*/ +{ + EFI_STATUS Status; + CHAR8 *Languages; + CHAR8 *LangStrings; + CHAR8 Lang[RFC_3066_ENTRY_SIZE]; + + Status = EFI_SUCCESS; + + LocateHiiProtocols (); + + Languages = GetSupportedLanguages (PackageList); + if (Languages == NULL) { + return EFI_NOT_FOUND; + } + + + if (StringId == NULL) { + return EFI_INVALID_PARAMETER; + } + *StringId = 0; + + LangStrings = Languages; + while (*LangStrings != 0) { + GetNextLanguage (&LangStrings, Lang); + + if (*StringId == 0) { + Status = gIfrLibHiiString->NewString ( + gIfrLibHiiString, + PackageList, + StringId, + Lang, + NULL, + String, + NULL + ); + } else { + Status = gIfrLibHiiString->SetString ( + gIfrLibHiiString, + PackageList, + *StringId, + Lang, + String, + NULL + ); + } + + if (EFI_ERROR (Status)) { + break; + } + } + + gBS->FreePool (Languages); + + return Status; +} + +EFI_STATUS +IfrLibGetString ( + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + OUT EFI_STRING String, + IN OUT UINTN *StringSize + ) +/*++ + + Routine Description: + This function try to retrieve string from String package of current language. + If fail, it try to retrieve string from String package of first language it support. + + Arguments: + PackageList - The package list in the HII database to search for the specified string. + StringId - The string's id, which is unique within PackageList. + String - Points to the new null-terminated string. + StringSize - On entry, points to the size of the buffer pointed to by String, in bytes. On return, + points to the length of the string, in bytes. + + Returns: + EFI_SUCCESS - The string was returned successfully. + EFI_NOT_FOUND - The string specified by StringId is not available. + EFI_BUFFER_TOO_SMALL - The buffer specified by StringLength is too small to hold the string. + EFI_INVALID_PARAMETER - The String or StringSize was NULL. + +--*/ +{ + EFI_STATUS Status; + CHAR8 *Languages; + CHAR8 *LangStrings; + CHAR8 Lang[RFC_3066_ENTRY_SIZE]; + CHAR8 CurrentLang[RFC_3066_ENTRY_SIZE]; + + LocateHiiProtocols (); + + GetCurrentLanguage (CurrentLang); + + Status = gIfrLibHiiString->GetString ( + gIfrLibHiiString, + CurrentLang, + PackageList, + StringId, + String, + StringSize, + NULL + ); + + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + Languages = GetSupportedLanguages (PackageList); + LangStrings = Languages; + GetNextLanguage (&LangStrings, Lang); + gBS->FreePool (Languages); + + Status = gIfrLibHiiString->GetString ( + gIfrLibHiiString, + Lang, + PackageList, + StringId, + String, + StringSize, + NULL + ); + } + + return Status; +} + +EFI_STATUS +IfrLibSetString ( + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + IN CONST EFI_STRING String + ) +/*++ + + Routine Description: + This function updates the string in String package of each language. + + Arguments: + PackageList - The package list containing the strings. + StringId - The string's id, which is unique within PackageList. + String - Points to the new null-terminated string. + + Returns: + EFI_SUCCESS - The string was updated successfully. + EFI_NOT_FOUND - The string specified by StringId is not in the database. + EFI_INVALID_PARAMETER - The String was NULL. + EFI_OUT_OF_RESOURCES - The system is out of resources to accomplish the task. + +--*/ +{ + EFI_STATUS Status; + CHAR8 *Languages; + CHAR8 *LangStrings; + CHAR8 Lang[RFC_3066_ENTRY_SIZE]; + + Status = EFI_SUCCESS; + + LocateHiiProtocols (); + + Languages = GetSupportedLanguages (PackageList); + if (Languages == NULL) { + return EFI_NOT_FOUND; + } + + LangStrings = Languages; + while (*LangStrings != 0) { + GetNextLanguage (&LangStrings, Lang); + + Status = gIfrLibHiiString->SetString ( + gIfrLibHiiString, + PackageList, + StringId, + Lang, + String, + NULL + ); + if (EFI_ERROR (Status)) { + break; + } + } + + gBS->FreePool (Languages); + + return Status; +} + |