diff --git a/MdeModulePkg/Library/UefiHiiLib/HiiLanguage.c b/MdeModulePkg/Library/UefiHiiLib/HiiLanguage.c new file mode 100644 index 0000000000..147e5a3942 --- /dev/null +++ b/MdeModulePkg/Library/UefiHiiLib/HiiLanguage.c @@ -0,0 +1,206 @@ +/** @file + Language related HII Library implementation. + + Copyright (c) 2006 - 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. + +**/ + + +#include "InternalHiiLib.h" + +/** + Get next language from language code list (with separator ';'). + + If LangCode is NULL, then ASSERT. + If Lang is NULL, then ASSERT. + + @param 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. + @param Lang The first language in the list. + +**/ +VOID +EFIAPI +HiiLibGetNextLanguage ( + IN OUT CHAR8 **LangCode, + OUT CHAR8 *Lang + ) +{ + UINTN Index; + CHAR8 *StringPtr; + + ASSERT (LangCode != NULL); + ASSERT (*LangCode != NULL); + ASSERT (Lang != NULL); + + Index = 0; + StringPtr = *LangCode; + while (StringPtr[Index] != 0 && StringPtr[Index] != ';') { + Index++; + } + + CopyMem (Lang, StringPtr, Index); + Lang[Index] = 0; + + if (StringPtr[Index] == ';') { + Index++; + } + *LangCode = StringPtr + Index; +} + + +/** + This function returns the list of supported languages, in the format specified + in UEFI specification Appendix M. + + If HiiHandle is not a valid Handle in the default HII database, then ASSERT. + + @param HiiHandle The HII package list handle. + + @retval !NULL The supported languages. + @retval NULL If Supported Languages can not be retrived. + +**/ +CHAR8 * +EFIAPI +HiiLibGetSupportedLanguages ( + IN EFI_HII_HANDLE HiiHandle + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + CHAR8 *LanguageString; + + ASSERT (IsHiiHandleRegistered (HiiHandle)); + // + // Collect current supported Languages for given HII handle + // First try allocate 4K buffer to store the current supported languages. + // + BufferSize = 0x1000; + LanguageString = AllocateZeroPool (BufferSize); + if (LanguageString == NULL) { + return NULL; + } + + Status = mHiiStringProt->GetLanguages (mHiiStringProt, HiiHandle, LanguageString, &BufferSize); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (LanguageString); + LanguageString = AllocateZeroPool (BufferSize); + if (LanguageString == NULL) { + return NULL; + } + + Status = mHiiStringProt->GetLanguages (mHiiStringProt, HiiHandle, LanguageString, &BufferSize); + } + + if (EFI_ERROR (Status)) { + LanguageString = NULL; + } + + return LanguageString; +} + + +/** + This function returns the number of supported languages on HiiHandle. + + If HiiHandle is not a valid Handle in the default HII database, then ASSERT. + If not enough resource to complete the operation, then ASSERT. + + @param HiiHandle The HII package list handle. + + @return The number of supported languages. + +**/ +UINT16 +EFIAPI +HiiLibGetSupportedLanguageNumber ( + IN EFI_HII_HANDLE HiiHandle + ) +{ + CHAR8 *Languages; + CHAR8 *LanguageString; + UINT16 LangNumber; + CHAR8 Lang[RFC_3066_ENTRY_SIZE]; + + Languages = HiiLibGetSupportedLanguages (HiiHandle); + if (Languages == NULL) { + return 0; + } + + LangNumber = 0; + LanguageString = Languages; + while (*LanguageString != 0) { + HiiLibGetNextLanguage (&LanguageString, Lang); + LangNumber++; + } + FreePool (Languages); + + return LangNumber; +} + +/** + This function returns the list of supported 2nd languages, in the format specified + in UEFI specification Appendix M. + + If HiiHandle is not a valid Handle in the default HII database, then ASSERT. + If not enough resource to complete the operation, then ASSERT. + + @param HiiHandle The HII package list handle. + @param FirstLanguage Pointer to language name buffer. + + @return The supported languages. + +**/ +CHAR8 * +EFIAPI +HiiLibGetSupportedSecondaryLanguages ( + IN EFI_HII_HANDLE HiiHandle, + IN CONST CHAR8 *FirstLanguage + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + CHAR8 *LanguageString; + + ASSERT (HiiHandle != NULL); + ASSERT (IsHiiHandleRegistered (HiiHandle)); + // + // Collect current supported 2nd Languages for given HII handle + // First try allocate 4K buffer to store the current supported 2nd languages. + // + BufferSize = 0x1000; + LanguageString = AllocateZeroPool (BufferSize); + if (LanguageString == NULL) { + return NULL; + } + + Status = mHiiStringProt->GetSecondaryLanguages (mHiiStringProt, HiiHandle, FirstLanguage, LanguageString, &BufferSize); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (LanguageString); + LanguageString = AllocateZeroPool (BufferSize); + if (LanguageString == NULL) { + return NULL; + } + + Status = mHiiStringProt->GetSecondaryLanguages (mHiiStringProt, HiiHandle, FirstLanguage, LanguageString, &BufferSize); + } + + if (EFI_ERROR (Status)) { + LanguageString = NULL; + } + + return LanguageString; +} + + diff --git a/MdeModulePkg/Library/UefiHiiLib/HiiLib.c b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c new file mode 100644 index 0000000000..975a064a39 --- /dev/null +++ b/MdeModulePkg/Library/UefiHiiLib/HiiLib.c @@ -0,0 +1,698 @@ +/** @file + HII Library implementation that uses DXE protocols and services. + + Copyright (c) 2006 - 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. + +**/ + +#include "InternalHiiLib.h" + +CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabaseProt = NULL; +CONST EFI_HII_STRING_PROTOCOL *mHiiStringProt = NULL; + +/** + This function locate Hii relative protocols for later usage. + + The constructor function caches the protocol pointer of HII Database Protocol + and Hii String Protocol. + + It will ASSERT() if either of the protocol can't be located. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +HiiLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabaseProt); + ASSERT_EFI_ERROR (Status); + + Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &mHiiStringProt); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + + +/** + This funciton build the package list based on the package number, + the GUID of the package list and the list of pointer which point to + package header that defined by UEFI VFR compiler and StringGather + tool. + + #pragma pack (push, 1) + typedef struct { + UINT32 BinaryLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + } EDKII_AUTOGEN_PACKAGES_HEADER; + #pragma pack (pop) + + If there is not enough resource for the new package list, + the function will ASSERT. + + @param NumberOfPackages The number of packages be + @param GuidId The GUID for the package list to be generated. + @param Marker The variable argument list. Each entry represent a specific package header that is + generated by VFR compiler and StrGather tool. The first 4 bytes is a UINT32 value + that indicate the overall length of the package. + + @return The pointer to the package list header. + +**/ +EFI_HII_PACKAGE_LIST_HEADER * +InternalHiiLibPreparePackages ( + IN UINTN NumberOfPackages, + IN CONST EFI_GUID *GuidId, + IN VA_LIST Marker + ) +{ + EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; + UINT8 *PackageListData; + UINT32 PackageListLength; + UINT32 PackageLength; + EFI_HII_PACKAGE_HEADER PackageHeader; + UINT8 *PackageArray; + UINTN Index; + VA_LIST MarkerBackup; + + PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + + MarkerBackup = Marker; + + // + // Count the lenth of the final package list. + // + for (Index = 0; Index < NumberOfPackages; Index++) { + CopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32)); + // + // Do not count the BinaryLength field. + // + PackageListLength += (PackageLength - sizeof (UINT32)); + } + + // + // Include the lenght of EFI_HII_PACKAGE_END + // + PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER); + PackageListHeader = AllocateZeroPool (PackageListLength); + ASSERT (PackageListHeader != NULL); + + CopyGuid (&PackageListHeader->PackageListGuid, GuidId); + PackageListHeader->PackageLength = PackageListLength; + + PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER); + + Marker = MarkerBackup; + // + // Prepare the final package list. + // + for (Index = 0; Index < NumberOfPackages; Index++) { + PackageArray = (UINT8 *) VA_ARG (Marker, VOID *); + // + // CopyMem is used for UINT32 to cover the unaligned address access. + // + CopyMem (&PackageLength, PackageArray, sizeof (UINT32)); + PackageLength -= sizeof (UINT32); + PackageArray += sizeof (UINT32); + CopyMem (PackageListData, PackageArray, PackageLength); + PackageListData += PackageLength; + } + + // + // Append EFI_HII_PACKAGE_END + // + PackageHeader.Type = EFI_HII_PACKAGE_END; + PackageHeader.Length = sizeof (EFI_HII_PACKAGE_HEADER); + CopyMem (PackageListData, &PackageHeader, PackageHeader.Length); + + return PackageListHeader; +} + +/** + Assemble EFI_HII_PACKAGE_LIST according to the passed in packages. + + If GuidId is NULL, then ASSERT. + If not enough resource to complete the operation, then ASSERT. + + @param NumberOfPackages Number of packages. + @param GuidId Package GUID. + @param ... Variable argument list for packages to be assembled. + + @return Pointer of EFI_HII_PACKAGE_LIST_HEADER. + +**/ +EFI_HII_PACKAGE_LIST_HEADER * +EFIAPI +HiiLibPreparePackageList ( + IN UINTN NumberOfPackages, + IN CONST EFI_GUID *GuidId, + ... + ) +{ + EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; + VA_LIST Marker; + + ASSERT (GuidId != NULL); + + VA_START (Marker, GuidId); + PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Marker); + VA_END (Marker); + + return PackageListHeader; +} + + +/** + This function allocates pool for an EFI_HII_PACKAGE_LIST structure + with additional space that is big enough to host all packages described by the variable + argument list of package pointers. The allocated structure is initialized using NumberOfPackages, + GuidId, and the variable length argument list of package pointers. + + Then, EFI_HII_PACKAGE_LIST will be register to the default System HII Database. The + Handle to the newly registered Package List is returned throught HiiHandle. + + If HiiHandle is NULL, then ASSERT. + + @param NumberOfPackages The number of HII packages to register. + @param GuidId Package List GUID ID. + @param DriverHandle Optional. If not NULL, the DriverHandle on which an instance of DEVICE_PATH_PROTOCOL is installed. + This DriverHandle uniquely defines the device that the added packages are associated with. + @param HiiHandle On output, the HiiHandle is update with the handle which can be used to retrieve the Package + List later. If the functions failed to add the package to the default HII database, this value will + be set to NULL. + @param ... The variable argument list describing all HII Package. + + @return EFI_SUCCESS If the packages are successfully added to the default HII database. + @return EFI_OUT_OF_RESOURCE Not enough resource to complete the operation. + +**/ +EFI_STATUS +EFIAPI +HiiLibAddPackages ( + IN UINTN NumberOfPackages, + IN CONST EFI_GUID *GuidId, + IN EFI_HANDLE DriverHandle, OPTIONAL + OUT EFI_HII_HANDLE *HiiHandle, + ... + ) +{ + VA_LIST Args; + EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; + EFI_STATUS Status; + + ASSERT (HiiHandle != NULL); + + VA_START (Args, HiiHandle); + PackageListHeader = InternalHiiLibPreparePackages (NumberOfPackages, GuidId, Args); + + Status = mHiiDatabaseProt->NewPackageList (mHiiDatabaseProt, PackageListHeader, DriverHandle, HiiHandle); + if (HiiHandle != NULL) { + if (EFI_ERROR (Status)) { + *HiiHandle = NULL; + } + } + + FreePool (PackageListHeader); + VA_END (Args); + + return Status; +} + +/** + Removes a package list from the default HII database. + + If HiiHandle is NULL, then ASSERT. + If HiiHandle is not a valid EFI_HII_HANDLE in the default HII database, then ASSERT. + + @param HiiHandle The handle that was previously registered to the data base that is requested for removal. + List later. + +**/ +VOID +EFIAPI +HiiLibRemovePackages ( + IN EFI_HII_HANDLE HiiHandle + ) +{ + EFI_STATUS Status; + ASSERT (IsHiiHandleRegistered (HiiHandle)); + + Status = mHiiDatabaseProt->RemovePackageList (mHiiDatabaseProt, HiiHandle); + ASSERT_EFI_ERROR (Status); +} + + +/** + Determines the handles that are currently active in the database. + It's the caller's responsibility to free handle buffer. + + If HandleBufferLength is NULL, then ASSERT. + If HiiHandleBuffer is NULL, then ASSERT. + + @param 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. + @param HiiHandleBuffer Pointer to an array of Hii Handles returned. + + @retval EFI_SUCCESS Get an array of Hii Handles successfully. + +**/ +EFI_STATUS +EFIAPI +HiiLibGetHiiHandles ( + IN OUT UINTN *HandleBufferLength, + OUT EFI_HII_HANDLE **HiiHandleBuffer + ) +{ + UINTN BufferLength; + EFI_STATUS Status; + + ASSERT (HandleBufferLength != NULL); + ASSERT (HiiHandleBuffer != NULL); + + BufferLength = 0; + + // + // Try to find the actual buffer size for HiiHandle Buffer. + // + Status = mHiiDatabaseProt->ListPackageLists ( + mHiiDatabaseProt, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferLength, + *HiiHandleBuffer + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + *HiiHandleBuffer = AllocateZeroPool (BufferLength); + ASSERT (*HiiHandleBuffer != NULL); + Status = mHiiDatabaseProt->ListPackageLists ( + mHiiDatabaseProt, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferLength, + *HiiHandleBuffer + ); + // + // we should not fail here. + // + ASSERT_EFI_ERROR (Status); + } + + *HandleBufferLength = BufferLength; + + return Status; +} + +/** + Extract Hii package list GUID for given HII handle. + + If HiiHandle could not be found in the default HII database, then ASSERT. + If Guid is NULL, then ASSERT. + + @param Handle Hii handle + @param Guid Package list GUID + + @retval EFI_SUCCESS Successfully extract GUID from Hii database. + +**/ +EFI_STATUS +EFIAPI +HiiLibExtractGuidFromHiiHandle ( + IN EFI_HII_HANDLE Handle, + OUT EFI_GUID *Guid + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + + ASSERT (Guid != NULL); + ASSERT (IsHiiHandleRegistered (Handle)); + + // + // Get HII PackageList + // + BufferSize = 0; + HiiPackageList = NULL; + + Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList); + ASSERT (Status != EFI_NOT_FOUND); + + if (Status == EFI_BUFFER_TOO_SMALL) { + HiiPackageList = AllocatePool (BufferSize); + ASSERT (HiiPackageList != NULL); + + Status = mHiiDatabaseProt->ExportPackageLists (mHiiDatabaseProt, Handle, &BufferSize, HiiPackageList); + } + if (EFI_ERROR (Status)) { + FreePool (HiiPackageList); + return Status; + } + + // + // Extract GUID + // + CopyGuid (Guid, &HiiPackageList->PackageListGuid); + + FreePool (HiiPackageList); + + return EFI_SUCCESS; +} + +/** + Find HII Handle in the default HII database associated with given Device Path. + + If DevicePath is NULL, then ASSERT. + + @param DevicePath Device Path associated with the HII package list + handle. + + @retval Handle HII package list Handle associated with the Device + Path. + @retval NULL Hii Package list handle is not found. + +**/ +EFI_HII_HANDLE +EFIAPI +HiiLibDevicePathToHiiHandle ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + 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; + + ASSERT (DevicePath != NULL); + + // + // 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 = GetDevicePathSize (DevicePath); + for(Index = 0; Index < HandleCount; Index++) { + Handle = Handles[Index]; + gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **) &TmpDevicePath); + + // + // Check whether DevicePath match + // + Size = GetDevicePathSize (TmpDevicePath); + if ((Size == BufferSize) && CompareMem (DevicePath, TmpDevicePath, Size) == 0) { + DriverHandle = Handle; + break; + } + } + FreePool (Handles); + + if (DriverHandle == NULL) { + return NULL; + } + + // + // Retrieve all Hii Handles from HII database + // + BufferSize = 0x1000; + HiiHandles = AllocatePool (BufferSize); + ASSERT (HiiHandles != NULL); + Status = mHiiDatabaseProt->ListPackageLists ( + mHiiDatabaseProt, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferSize, + HiiHandles + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (HiiHandles); + HiiHandles = AllocatePool (BufferSize); + ASSERT (HiiHandles != NULL); + + Status = mHiiDatabaseProt->ListPackageLists ( + mHiiDatabaseProt, + EFI_HII_PACKAGE_TYPE_ALL, + NULL, + &BufferSize, + HiiHandles + ); + } + + if (EFI_ERROR (Status)) { + 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 = mHiiDatabaseProt->GetPackageListHandle ( + mHiiDatabaseProt, + HiiHandles[Index], + &Handle + ); + if (!EFI_ERROR (Status) && (Handle == DriverHandle)) { + HiiHandle = HiiHandles[Index]; + break; + } + } + + FreePool (HiiHandles); + return HiiHandle; +} + +/** + Exports the contents of one or all package lists in the HII database into a buffer. + + If Handle is not NULL and not a valid EFI_HII_HANDLE registered in the database, + then ASSERT. + If PackageListHeader is NULL, then ASSERT. + If PackageListSize is NULL, then ASSERT. + + @param Handle The HII Handle. + @param PackageListHeader A pointer to a buffer that will contain the results of + the export function. + @param PackageListSize On output, the length of the buffer that is required for the exported data. + + @retval EFI_SUCCESS Package exported. + + @retval EFI_OUT_OF_RESOURCES Not enought memory to complete the operations. + +**/ +EFI_STATUS +EFIAPI +HiiLibExportPackageLists ( + IN EFI_HII_HANDLE Handle, + OUT EFI_HII_PACKAGE_LIST_HEADER **PackageListHeader, + OUT UINTN *PackageListSize + ) +{ + EFI_STATUS Status; + UINTN Size; + EFI_HII_PACKAGE_LIST_HEADER *PackageListHdr; + + ASSERT (PackageListSize != NULL); + ASSERT (PackageListHeader != NULL); + + if (Handle != NULL) { + ASSERT (IsHiiHandleRegistered (Handle)); + } + + Size = 0; + PackageListHdr = NULL; + Status = mHiiDatabaseProt->ExportPackageLists ( + mHiiDatabaseProt, + Handle, + &Size, + PackageListHdr + ); + ASSERT_EFI_ERROR (Status != EFI_BUFFER_TOO_SMALL); + + if (Status == EFI_BUFFER_TOO_SMALL) { + PackageListHdr = AllocateZeroPool (Size); + + if (PackageListHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } else { + Status = mHiiDatabaseProt->ExportPackageLists ( + mHiiDatabaseProt, + Handle, + &Size, + PackageListHdr + ); + } + } + + if (!EFI_ERROR (Status)) { + *PackageListHeader = PackageListHdr; + *PackageListSize = Size; + } else { + FreePool (PackageListHdr); + } + + return Status; +} + +/** + + This function returns a list of the package handles of the + specified type that are currently active in the HII database. The + pseudo-type EFI_HII_PACKAGE_TYPE_ALL will cause all package + handles to be listed. + + If HandleBufferLength is NULL, then ASSERT. + If HandleBuffer is NULL, the ASSERT. + If PackageType is EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is + NULL, then ASSERT. + If PackageType is not EFI_HII_PACKAGE_TYPE_GUID and PackageGuid is not + NULL, then ASSERT. + + + @param PackageType Specifies the package type of the packages + to list or EFI_HII_PACKAGE_TYPE_ALL for + all packages to be listed. + + @param PackageGuid If PackageType is + EFI_HII_PACKAGE_TYPE_GUID, then this is + the pointer to the GUID which must match + the Guid field of + EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it + must be NULL. + + @param HandleBufferLength On output, the length of the handle buffer + that is required for the handles found. + + @param HandleBuffer On output, an array of EFI_HII_HANDLE instances returned. + The caller is responcible to free this pointer allocated. + + @retval EFI_SUCCESS The matching handles are outputed successfully. + HandleBufferLength is updated with the actual length. + @retval EFI_OUT_OF_RESOURCES Not enough resource to complete the operation. + @retval EFI_NOT_FOUND No matching handle could not be found in database. +**/ +EFI_STATUS +EFIAPI +HiiLibListPackageLists ( + IN UINT8 PackageType, + IN CONST EFI_GUID *PackageGuid, + IN OUT UINTN *HandleBufferLength, + OUT EFI_HII_HANDLE **HandleBuffer + ) +{ + EFI_STATUS Status; + + ASSERT (HandleBufferLength != NULL); + ASSERT (HandleBuffer != NULL); + + *HandleBufferLength = 0; + *HandleBuffer = NULL; + + if (PackageType == EFI_HII_PACKAGE_TYPE_GUID) { + ASSERT (PackageGuid != NULL); + } else { + ASSERT (PackageGuid == NULL); + } + + Status = mHiiDatabaseProt->ListPackageLists ( + mHiiDatabaseProt, + PackageType, + PackageGuid, + HandleBufferLength, + *HandleBuffer + ); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + // + // No packages is registered to UEFI HII Database, just return. + // + // + return Status; + } + + *HandleBuffer = AllocateZeroPool (*HandleBufferLength); + + if (*HandleBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return mHiiDatabaseProt->ListPackageLists ( + mHiiDatabaseProt, + PackageType, + PackageGuid, + HandleBufferLength, + *HandleBuffer + ); + +} +/** + This function check if the Hii Handle is a valid handle registered + in the HII database. + + @param HiiHandle The HII Handle. + + @retval TRUE If it is a valid HII handle. + @retval FALSE If it is a invalid HII handle. +**/ +BOOLEAN +IsHiiHandleRegistered ( + EFI_HII_HANDLE HiiHandle + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; + + ASSERT (HiiHandle != NULL); + + HiiPackageList = NULL; + BufferSize = 0; + + Status = mHiiDatabaseProt->ExportPackageLists ( + mHiiDatabaseProt, + HiiHandle, + &BufferSize, + HiiPackageList + ); + + return (BOOLEAN) (Status == EFI_BUFFER_TOO_SMALL); +} + diff --git a/MdeModulePkg/Library/UefiHiiLib/HiiString.c b/MdeModulePkg/Library/UefiHiiLib/HiiString.c new file mode 100644 index 0000000000..cd4944152a --- /dev/null +++ b/MdeModulePkg/Library/UefiHiiLib/HiiString.c @@ -0,0 +1,602 @@ +/** @file + HII Library implementation that uses DXE protocols and services. + + Copyright (c) 2006 - 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. + +**/ + + +#include "InternalHiiLib.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. +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST 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\ +"; + + + +/** + This function adds the string into String Package of each language + supported by the package list. + + If String is NULL, then ASSERT. + If StringId is NULL, the ASSERT. + If PackageList could not be found in the default HII database, then ASSERT. + + @param PackageList Handle of the package list where this string will + be added. + @param StringId On return, contains the new strings id, which is + unique within PackageList. + @param String Points to the new null-terminated string. + + @retval EFI_SUCCESS The new string was added successfully. + @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources. + +**/ +EFI_STATUS +EFIAPI +HiiLibNewString ( + IN EFI_HII_HANDLE PackageList, + OUT EFI_STRING_ID *StringId, + IN CONST EFI_STRING String + ) +{ + EFI_STATUS Status; + CHAR8 *Languages; + CHAR8 *LangStrings; + CHAR8 Lang[RFC_3066_ENTRY_SIZE]; + + ASSERT (String != NULL); + ASSERT (StringId != NULL); + + Status = EFI_SUCCESS; + + Languages = HiiLibGetSupportedLanguages (PackageList); + + LangStrings = Languages; + while (*LangStrings != 0) { + HiiLibGetNextLanguage (&LangStrings, Lang); + + // + // For each language supported by the package, + // a string token is created. + // + Status = mHiiStringProt->NewString ( + mHiiStringProt, + PackageList, + StringId, + Lang, + NULL, + String, + NULL + ); + if (EFI_ERROR (Status)) { + break; + } + } + + FreePool (Languages); + + return Status; + +} + + +/** + This function update the specified string in String Package of each language + supported by the package list. + + If String is NULL, then ASSERT. + If PackageList could not be found in the default HII database, then ASSERT. + If StringId is not found in PackageList, then ASSERT. + + @param PackageList Handle of the package list where this string will + be added. + @param StringId Ths String Id to be updated. + @param String Points to the new null-terminated string. + + @retval EFI_SUCCESS The new string was added successfully. + @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources. + +**/ +EFI_STATUS +EFIAPI +HiiLibSetString ( + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + IN CONST EFI_STRING String + ) +{ + EFI_STATUS Status; + CHAR8 *Languages; + CHAR8 *LangStrings; + CHAR8 Lang[RFC_3066_ENTRY_SIZE]; + + ASSERT (IsHiiHandleRegistered (PackageList)); + + Status = EFI_SUCCESS; + + Languages = HiiLibGetSupportedLanguages (PackageList); + ASSERT (Languages != NULL); + + LangStrings = Languages; + while (*LangStrings != 0) { + HiiLibGetNextLanguage (&LangStrings, Lang); + + // + // For each language supported by the package, + // the string is updated. + // + Status = mHiiStringProt->SetString ( + mHiiStringProt, + PackageList, + StringId, + Lang, + String, + NULL + ); + if (EFI_ERROR (Status)) { + break; + } + } + + FreePool (Languages); + + return Status; +} + + +/** + Get the string given the StringId and String package Producer's Guid. The caller + is responsible to free the *String. + + If PackageList with the matching ProducerGuid is not found, then ASSERT. + If PackageList with the matching ProducerGuid is found but no String is + specified by StringId is found, then ASSERT. + + @param ProducerGuid The Guid of String package list. + @param StringId The String ID. + @param String The output string. + + @retval EFI_SUCCESS Operation is successful. + @retval EFI_OUT_OF_RESOURCES There is not enought memory in the system. + +**/ +EFI_STATUS +EFIAPI +HiiLibGetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN EFI_STRING_ID StringId, + OUT EFI_STRING *String + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleBufferLen; + EFI_HII_HANDLE *HiiHandleBuffer; + EFI_GUID Guid; + + Status = HiiLibGetHiiHandles (&HandleBufferLen, &HiiHandleBuffer); + if (EFI_ERROR(Status)) { + return Status; + } + for (Index = 0; Index < (HandleBufferLen / sizeof (EFI_HII_HANDLE)); Index++) { + Status = HiiLibExtractGuidFromHiiHandle (HiiHandleBuffer[Index], &Guid); + if (EFI_ERROR(Status)) { + return Status; + } + if (CompareGuid (&Guid, ProducerGuid)) { + break; + } + } + + if (Index >= (HandleBufferLen / sizeof (EFI_HII_HANDLE))) { + // + // If PackageList with the matching ProducerGuid is not found, then ASSERT. + // + ASSERT (FALSE); + Status = EFI_NOT_FOUND; + goto Out; + } + + Status = HiiLibGetStringFromHandle (HiiHandleBuffer[Index], StringId, String); + +Out: + if (HiiHandleBuffer != NULL) { + FreePool (HiiHandleBuffer); + } + return Status; +} + +/** + This function try to retrieve string from String package of current language. + If fails, it try to retrieve string from String package of first language it support. + + If StringSize is NULL, then ASSERT. + If String is NULL and *StringSize is not 0, then ASSERT. + If PackageList could not be found in the default HII database, then ASSERT. + If StringId is not found in PackageList, then ASSERT. + + @param PackageList The package list in the HII database to search for + the specified string. + @param StringId The string's id, which is unique within + PackageList. + @param String Points to the new null-terminated string. + @param 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. + + @retval EFI_SUCCESS The string was returned successfully. + @retval EFI_NOT_FOUND The string specified by StringId is not available. + @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringLength is too small + to hold the string. + +**/ +EFI_STATUS +EFIAPI +HiiLibGetString ( + IN EFI_HII_HANDLE PackageList, + IN EFI_STRING_ID StringId, + OUT EFI_STRING String, + IN OUT UINTN *StringSize + ) +{ + EFI_STATUS Status; + CHAR8 *Languages; + CHAR8 *LangStrings; + CHAR8 Lang[RFC_3066_ENTRY_SIZE]; + CHAR8 CurrentLang[RFC_3066_ENTRY_SIZE]; + + ASSERT (StringSize != NULL); + ASSERT (!(*StringSize != 0 && String == NULL)); + ASSERT (IsHiiHandleRegistered (PackageList)); + + GetCurrentLanguage (CurrentLang); + + Status = mHiiStringProt->GetString ( + mHiiStringProt, + CurrentLang, + PackageList, + StringId, + String, + StringSize, + NULL + ); + + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + Languages = HiiLibGetSupportedLanguages (PackageList); + ASSERT (Languages != NULL); + + LangStrings = Languages; + HiiLibGetNextLanguage (&LangStrings, Lang); + FreePool (Languages); + + Status = mHiiStringProt->GetString ( + mHiiStringProt, + Lang, + PackageList, + StringId, + String, + StringSize, + NULL + ); + } + + return Status; +} + + +/** + Get string specified by StringId form the HiiHandle. The caller + is responsible to free the *String. + + If String is NULL, then ASSERT. + If HiiHandle could not be found in the default HII database, then ASSERT. + If StringId is not found in PackageList, then ASSERT. + + @param HiiHandle The HII handle of package list. + @param StringId The String ID. + @param String The output string. + + @retval EFI_NOT_FOUND String is not found. + @retval EFI_SUCCESS Operation is successful. + @retval EFI_OUT_OF_RESOURCES There is not enought memory in the system. + +**/ +EFI_STATUS +EFIAPI +HiiLibGetStringFromHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN EFI_STRING_ID StringId, + OUT EFI_STRING *String + ) +{ + EFI_STATUS Status; + UINTN StringSize; + + ASSERT (String != NULL); + + StringSize = HII_LIB_DEFAULT_STRING_SIZE; + *String = AllocateZeroPool (StringSize); + if (*String == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = HiiLibGetString (HiiHandle, StringId, *String, &StringSize); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (*String); + *String = AllocateZeroPool (StringSize); + if (*String == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = HiiLibGetString (HiiHandle, StringId, *String, &StringSize); + } + + return Status; +} + + + +/** + Convert language code from RFC3066 to ISO639-2. + + @param LanguageRfc3066 RFC3066 language code. + @param LanguageIso639 ISO639-2 language code. + + @retval EFI_SUCCESS Language code converted. + @retval EFI_NOT_FOUND Language code not found. + +**/ +EFI_STATUS +EFIAPI +ConvertRfc3066LanguageToIso639Language ( + IN CHAR8 *LanguageRfc3066, + OUT CHAR8 *LanguageIso639 + ) +{ + UINTN Index; + + if ((LanguageRfc3066[2] != '-') && (LanguageRfc3066[2] != 0)) { + CopyMem (LanguageIso639, LanguageRfc3066, 3); + return EFI_SUCCESS; + } + + for (Index = 0; Iso639ToRfc3066ConversionTable[Index] != 0; Index += 5) { + if (CompareMem (LanguageRfc3066, &Iso639ToRfc3066ConversionTable[Index + 3], 2) == 0) { + CopyMem (LanguageIso639, &Iso639ToRfc3066ConversionTable[Index], 3); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Convert language code from ISO639-2 to RFC3066. + + LanguageIso639 contain a single ISO639-2 code such as + "eng" or "fra". + + The LanguageRfc3066 must be a buffer large enough + for RFC_3066_ENTRY_SIZE characters. + + If LanguageIso639 is NULL, then ASSERT. + If LanguageRfc3066 is NULL, then ASSERT. + + @param LanguageIso639 ISO639-2 language code. + @param LanguageRfc3066 RFC3066 language code. + + @retval EFI_SUCCESS Language code converted. + @retval EFI_NOT_FOUND Language code not found. + +**/ +EFI_STATUS +EFIAPI +ConvertIso639LanguageToRfc3066Language ( + IN CONST CHAR8 *LanguageIso639, + OUT CHAR8 *LanguageRfc3066 + ) +{ + UINTN Index; + + for (Index = 0; Iso639ToRfc3066ConversionTable[Index] != 0; Index += 5) { + if (CompareMem (LanguageIso639, &Iso639ToRfc3066ConversionTable[Index], 3) == 0) { + CopyMem (LanguageRfc3066, &Iso639ToRfc3066ConversionTable[Index + 3], 2); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + Convert language code list from RFC3066 to ISO639-2, e.g. "en-US;fr-FR" will + be converted to "engfra". + + @param SupportedLanguages The RFC3066 language list. + + @return The ISO639-2 language list. + +**/ +CHAR8 * +EFIAPI +Rfc3066ToIso639 ( + CHAR8 *SupportedLanguages + ) +{ + CHAR8 *Languages; + CHAR8 *ReturnValue; + CHAR8 *LangCodes; + CHAR8 LangRfc3066[RFC_3066_ENTRY_SIZE]; + CHAR8 LangIso639[ISO_639_2_ENTRY_SIZE]; + EFI_STATUS Status; + + ReturnValue = AllocateZeroPool (AsciiStrSize (SupportedLanguages)); + if (ReturnValue == NULL) { + return ReturnValue; + } + + Languages = ReturnValue; + LangCodes = SupportedLanguages; + while (*LangCodes != 0) { + HiiLibGetNextLanguage (&LangCodes, LangRfc3066); + + Status = ConvertRfc3066LanguageToIso639Language (LangRfc3066, LangIso639); + if (!EFI_ERROR (Status)) { + CopyMem (Languages, LangIso639, 3); + Languages = Languages + 3; + } + } + + return ReturnValue; +} + + diff --git a/MdeModulePkg/Library/UefiHiiLib/InternalHiiLib.h b/MdeModulePkg/Library/UefiHiiLib/InternalHiiLib.h new file mode 100644 index 0000000000..18d168ec70 --- /dev/null +++ b/MdeModulePkg/Library/UefiHiiLib/InternalHiiLib.h @@ -0,0 +1,53 @@ +/** @file + Internal include file for the HII Library instance. + + 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. + +**/ + +#ifndef __INTERNAL_HII_LIB_H__ +#define __INTERNAL_HII_LIB_H__ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define HII_LIB_DEFAULT_STRING_SIZE 0x200 + + +extern CONST EFI_HII_DATABASE_PROTOCOL *mHiiDatabaseProt; +extern CONST EFI_HII_STRING_PROTOCOL *mHiiStringProt; + +/** + This function check if the Hii Handle is a valid handle registered + in the HII database. + + @param HiiHandle The HII Handle. + + @retval TRUE If it is a valid HII handle. + @retval FALSE If it is a invalid HII handle. +**/ +BOOLEAN +IsHiiHandleRegistered ( + EFI_HII_HANDLE HiiHandle + ); + +#endif diff --git a/MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf b/MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf new file mode 100644 index 0000000000..f355d02f1b --- /dev/null +++ b/MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf @@ -0,0 +1,60 @@ +#/** @file +# Instance of HII Library using DXE protocols and services. +# +# HII Library implementation that uses DXE protocols and services. +# +# Copyright (c) 2006 - 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. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiHiiLib + FILE_GUID = 3143687A-7C80-404e-B5FE-2D88980E1B1C + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = HiiLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + + CONSTRUCTOR = HiiLibConstructor + +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + HiiLib.c + HiiString.c + HiiLanguage.c + InternalHiiLib.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + BaseMemoryLib + BaseLib + DebugLib + UefiBootServicesTableLib + DevicePathLib + UefiLib + +[Protocols] + gEfiHiiDatabaseProtocolGuid # ALWAYS_CONSUMED + gEfiHiiStringProtocolGuid # ALWAYS_CONSUMED + gEfiDevicePathProtocolGuid + +[Depex] + gEfiHiiDatabaseProtocolGuid AND + gEfiHiiStringProtocolGuid + diff --git a/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrForm.c b/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrForm.c new file mode 100644 index 0000000000..b6da34a6b3 --- /dev/null +++ b/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrForm.c @@ -0,0 +1,1394 @@ +/** @file +Utility functions which helps in opcode creation, HII configuration string manipulations, +pop up window creations, setup browser persistence data set and get. + +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. + +**/ + +#include "UefiIfrLibraryInternal.h" + +CONST EFI_FORM_BROWSER2_PROTOCOL *mFormBrowser2 = NULL; +CONST EFI_HII_CONFIG_ROUTING_PROTOCOL *mIfrSupportLibHiiConfigRouting = NULL; + +/** + This function locate FormBrowser2 protocols for later usage. + + @return Status the status to locate protocol. +**/ +EFI_STATUS +LocateFormBrowser2Protocols ( + VOID + ) +{ + EFI_STATUS Status; + // + // Locate protocols for later usage + // + if (mFormBrowser2 == NULL) { + Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mFormBrowser2); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (mIfrSupportLibHiiConfigRouting == NULL) { + Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &mIfrSupportLibHiiConfigRouting); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} + +// +// Fake +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0"; + +/** + Draw a dialog and return the selected key. + + @param NumberOfLines The number of lines for the dialog box + @param KeyValue The EFI_KEY value returned if HotKey is TRUE.. + @param Marker A series of (quantity == NumberOfLines - 1) text + strings which will be used to construct the dialog + box + + @retval EFI_SUCCESS Displayed dialog and received user interaction + @retval EFI_INVALID_PARAMETER One of the parameters was invalid. + @retval EFI_OUT_OF_RESOURCES There is no enough available memory space. + +**/ +EFI_STATUS +EFIAPI +IfrLibCreatePopUp2 ( + IN UINTN NumberOfLines, + OUT EFI_INPUT_KEY *KeyValue, + IN VA_LIST Marker + ) +{ + UINTN Index; + UINTN Count; + UINTN Start; + UINTN Top; + CHAR16 *StringPtr; + UINTN LeftColumn; + UINTN RightColumn; + UINTN TopRow; + UINTN BottomRow; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + 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_OUTPUT_PROTOCOL *ConOut; + CHAR16 *String; + + String = VA_ARG (Marker, CHAR16 *); + + 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 = AllocateZeroPool (DimensionsWidth * sizeof (CHAR16)); + if (LineBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Determine the largest string in the dialog box + // Notice we are starting with 1 since String is the first string + // + StringArray = AllocateZeroPool (NumberOfLines * sizeof (CHAR16 *)); + if (StringArray == NULL) { + FreePool (LineBuffer); + return EFI_OUT_OF_RESOURCES; + } + LargestString = StrLen (String); + StringArray[0] = String; + + for (Index = 1; Index < NumberOfLines; Index++) { + StackString = VA_ARG (Marker, CHAR16 *); + + if (StackString == NULL) { + FreePool (LineBuffer); + FreePool (StringArray); + return EFI_INVALID_PARAMETER; + } + + StringArray[Index] = StackString; + StringLen = StrLen (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; + + Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1; + + // + // 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 = StrLen (StringArray[Index]); + if (StringLen > LargestString) { + StringLen = LargestString; + } + CopyMem ( + 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 (EVT_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); + CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY)); + + ConOut->SetAttribute (ConOut, CurrentAttribute); + ConOut->EnableCursor (ConOut, TRUE); + + FreePool (LineBuffer); + FreePool (StringArray); + + return Status; +} + + +/** + Draw a dialog and return the selected key. + + @param NumberOfLines The number of lines for the dialog box + @param KeyValue The EFI_KEY value returned if HotKey is TRUE.. + @param String Pointer to the first string in the list + @param ... A series of (quantity == NumberOfLines - 1) text + strings which will be used to construct the dialog + box + + @retval EFI_SUCCESS Displayed dialog and received user interaction + @retval EFI_INVALID_PARAMETER One of the parameters was invalid. + +**/ +EFI_STATUS +EFIAPI +IfrLibCreatePopUp ( + IN UINTN NumberOfLines, + OUT EFI_INPUT_KEY *KeyValue, + IN CHAR16 *String, + ... + ) +{ + EFI_STATUS Status; + VA_LIST Marker; + + VA_START (Marker, KeyValue); + + Status = IfrLibCreatePopUp2 (NumberOfLines, KeyValue, Marker); + + VA_END (Marker); + + return Status; +} + +/** + Extract block name from the array generated by VFR compiler. The name of + this array is "Vfr + + 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 + ... ... + + @param Buffer Array generated by VFR compiler. + @param BlockName The returned + + @retval EFI_OUT_OF_RESOURCES Run out of memory resource. + @retval EFI_INVALID_PARAMETER Buffer is NULL or BlockName is NULL. + @retval EFI_SUCCESS Operation successful. + +**/ +EFI_STATUS +ExtractBlockName ( + IN UINT8 *Buffer, + OUT CHAR16 **BlockName + ) + +{ + 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 + // + CopyMem (&Length, Buffer, sizeof (UINT32)); + BlockNameNumber = (Length - sizeof (UINT32)) / (sizeof (UINT16) * 2); + + // + // ::= &OFFSET=1234&WIDTH=1234 + // | 8 | 4 | 7 | 4 | + // + StringPtr = AllocateZeroPool ((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++) { + StrCpy (StringPtr, L"&OFFSET="); + StringPtr += 8; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + StrCpy (StringPtr, L"&WIDTH="); + StringPtr += 7; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + } + + return EFI_SUCCESS; +} + +/** + + Extract block config from the array generated by VFR compiler. The name of + this array is "Vfr + + Default4", e.g. "VfrMyIfrNVDataDefault0000". + + @param Buffer - Array generated by VFR compiler. + @param BlockConfig - The returned + + @retval EFI_OUT_OF_RESOURCES - Run out of memory resource. + @retval EFI_INVALID_PARAMETER - Buffer is NULL or BlockConfig is NULL. + @retval EFI_SUCCESS - Operation successful. + +**/ +EFI_STATUS +ExtractBlockConfig ( + IN UINT8 *Buffer, + OUT CHAR16 **BlockConfig + ) +{ + 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 + // + CopyMem (&Length, Buffer, sizeof (UINT32)); + BufferEnd = Buffer + Length; + StringPtr = AllocatePool (Length * 7 * sizeof (CHAR16)); + *BlockConfig = StringPtr; + if (StringPtr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + StringEnd = StringPtr + (Length * 7); + + Buffer += sizeof (UINT32); + while (Buffer < BufferEnd) { + StrCpy (StringPtr, L"&OFFSET="); + StringPtr += 8; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + StrCpy (StringPtr, L"&WIDTH="); + StringPtr += 7; + + HexStringBufferLen = 5; + BufToHexString (StringPtr, &HexStringBufferLen, Buffer, sizeof (UINT16)); + CopyMem (&Width, Buffer, sizeof (UINT16)); + Buffer += sizeof (UINT16); + StringPtr += 4; + + StrCpy (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; +} + +/** + Construct for a buffer storage. + + @param ConfigRequest The Config request string. If set to NULL, all the + configurable elements will be extracted from BlockNameArray. + @param ConfigAltResp The returned . + @param Progress On return, points to a character in the Request. + @param Guid GUID of the buffer storage. + @param Name Name of the buffer storage. + @param DriverHandle The DriverHandle which is used to invoke HiiDatabase + protocol interface NewPackageList(). + @param BufferStorage Content of the buffer storage. + @param BufferStorageSize Length in bytes of the buffer storage. + @param BlockNameArray Array generated by VFR compiler. + @param 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 . + + retval EFI_OUT_OF_RESOURCES Run out of memory resource. + retval EFI_INVALID_PARAMETER ConfigAltResp is NULL. + retval 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, + ) +{ + 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; + UINTN Len; + + if (ConfigAltResp == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Construct : "GUID=...&NAME=...&PATH=..." + // + ConfigHdr = NULL; + StrBufferLen = 0; + Status = ConstructConfigHdr ( + ConfigHdr, + &StrBufferLen, + Guid, + Name, + DriverHandle + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + ConfigHdr = AllocateZeroPool (StrBufferLen); + Status = ConstructConfigHdr ( + ConfigHdr, + &StrBufferLen, + Guid, + Name, + DriverHandle + ); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Construct + // + 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; + } + + Len = StrSize (ConfigHdr); + ConfigRequest = AllocateZeroPool (Len + StrSize (BlockName) - sizeof (CHAR16)); + StrCpy (ConfigRequest, ConfigHdr); + StrCat (ConfigRequest, BlockName); + NeedFreeConfigRequest = TRUE; + } + + Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &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 + // + DescHdr = AllocateZeroPool (NumberAltCfg * 16 * sizeof (CHAR16)); + StringPtr = DescHdr; + AltCfg = AllocateZeroPool (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 *); + + // + // '&' + // + AltRespLen += (StrLen (ConfigHdr) + 1); + + StringPtr = DescHdr + Index * 16; + StrCpy (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 += StrLen (AltCfg[Index]); + } + VA_END (Args); + + // + // Generate the final + // + StrBufferLen = (StrLen ((CHAR16 *) ConfigResp) + AltRespLen + 1) * sizeof (CHAR16); + TempStr = AllocateZeroPool (StrBufferLen); + *ConfigAltResp = TempStr; + if (TempStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // ::= ['&' ]* + // + StrCpy (TempStr, ConfigResp); + for (Index = 0; Index < NumberAltCfg; Index++) { + StrCat (TempStr, L"&"); + StrCat (TempStr, ConfigHdr); + StrCat (TempStr, DescHdr + Index * 16); + StrCat (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; +} + +/** + Swap bytes in the buffer. This is a internal function. + + @param Buffer Binary buffer. + @param BufferSize Size of the buffer in bytes. + + @return None. + +**/ +VOID +SwapBuffer ( + IN OUT UINT8 *Buffer, + IN UINTN BufferSize + ) +{ + 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; + } +} + +/** + Converts the unicode character of the string from uppercase to lowercase. + This is a internal function. + + @param Str String to be converted + +**/ +VOID +EFIAPI +ToLower ( + IN OUT CHAR16 *Str + ) +{ + CHAR16 *Ptr; + + for (Ptr = Str; *Ptr != L'\0'; Ptr++) { + if (*Ptr >= L'A' && *Ptr <= L'Z') { + *Ptr = (CHAR16) (*Ptr - L'A' + L'a'); + } + } +} + + +/** + Converts binary buffer to Unicode string in reversed byte order from BufToHexString(). + + @param Str String for output + @param Buffer Binary buffer. + @param BufferSize Size of the buffer in bytes. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_OUT_OF_RESOURCES There is no enough available memory space. + +**/ +EFI_STATUS +EFIAPI +BufInReverseOrderToHexString ( + IN OUT CHAR16 *Str, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +{ + EFI_STATUS Status; + UINT8 *NewBuffer; + UINTN StrBufferLen; + + NewBuffer = AllocateCopyPool (BufferSize, Buffer); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + SwapBuffer (NewBuffer, BufferSize); + + StrBufferLen = BufferSize * sizeof (CHAR16) + 1; + Status = BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize); + + FreePool (NewBuffer); + // + // Convert the uppercase to lowercase since is defined in lowercase format. + // + ToLower (Str); + + return Status; +} + + +/** + Converts Hex String to binary buffer in reversed byte order from HexStringToBuf(). + + @param Buffer Pointer to buffer that receives the data. + @param 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. + @param Str String to be converted from. + + @retval EFI_SUCCESS The function completed successfully. + @retval RETURN_BUFFER_TOO_SMALL The input BufferSize is too small to hold the output. BufferSize + will be updated to the size required for the converstion. + +**/ +EFI_STATUS +EFIAPI +HexStringToBufInReverseOrder ( + IN OUT UINT8 *Buffer, + IN OUT UINTN *BufferSize, + IN CHAR16 *Str + ) +{ + EFI_STATUS Status; + UINTN ConvertedStrLen; + + ConvertedStrLen = 0; + Status = HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen); + if (!EFI_ERROR (Status)) { + SwapBuffer (Buffer, (ConvertedStrLen + 1) / 2); + } + + return Status; +} + +/** + Convert binary representation Config string (e.g. "0041004200430044") to the + original string (e.g. "ABCD"). Config string appears in (i.e. + "&NAME="), or Name/Value pair in (i.e. "label="). + + @param UnicodeString Original Unicode string. + @param 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. + @param ConfigString Binary representation of Unicode String, := (4)+ + + @retval EFI_SUCCESS Operation completes successfully. + @retval EFI_BUFFER_TOO_SMALL The string buffer is too small. + +**/ +EFI_STATUS +EFIAPI +ConfigStringToUnicode ( + IN OUT CHAR16 *UnicodeString, + IN OUT UINTN *StrBufferLen, + IN CHAR16 *ConfigString + ) +{ + UINTN Index; + UINTN Len; + UINTN BufferSize; + CHAR16 BackupChar; + + Len = StrLen (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; +} + +/** + Convert Unicode string to binary representation Config string, e.g. + "ABCD" => "0041004200430044". Config string appears in (i.e. + "&NAME="), or Name/Value pair in (i.e. "label="). + + @param ConfigString Binary representation of Unicode String, := (4)+ + @param 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. + @param UnicodeString Original Unicode string. + + @retval EFI_SUCCESS Operation completes successfully. + @retval EFI_BUFFER_TOO_SMALL The string buffer is too small. + +**/ +EFI_STATUS +EFIAPI +UnicodeToConfigString ( + IN OUT CHAR16 *ConfigString, + IN OUT UINTN *StrBufferLen, + IN CHAR16 *UnicodeString + ) +{ + UINTN Index; + UINTN Len; + UINTN BufferSize; + CHAR16 *String; + + Len = StrLen (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 is defined in lowercase format. + // + ToLower (String); + return EFI_SUCCESS; +} + +/** + Construct using routing information GUID/NAME/PATH. + + @param ConfigHdr Pointer to the ConfigHdr string. + @param 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. + @param Guid Routing information: GUID. + @param Name Routing information: NAME. + @param DriverHandle Driver handle which contains the routing + information: PATH. + + @retval EFI_SUCCESS Operation completes successfully. + @retval EFI_BUFFER_TOO_SMALL The ConfigHdr string buffer is too small. + +**/ +EFI_STATUS +EFIAPI +ConstructConfigHdr ( + IN OUT CHAR16 *ConfigHdr, + IN OUT UINTN *StrBufferLen, + IN CONST EFI_GUID *Guid, + IN CHAR16 *Name, OPTIONAL + IN EFI_HANDLE *DriverHandle + ) +{ + 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 for Name/Value storage + // + NameStrLen = 0; + } else { + // + // For buffer storage + // + NameStrLen = StrLen (Name); + } + + // + // Retrieve DevicePath Protocol associated with this HiiPackageList + // + Status = gBS->HandleProtocol ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DevicePathSize = GetDevicePathSize (DevicePath); + + // + // GUID=32&NAME=NameStrLen&PATH=DevicePathStrLen + // | 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; + + StrCpy (StrPtr, L"GUID="); + StrPtr += 5; + BufInReverseOrderToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID)); + StrPtr += 32; + + // + // Convert name string, e.g. name "ABCD" => "&NAME=0041004200430044" + // + StrCpy (StrPtr, L"&NAME="); + StrPtr += 6; + if (Name != NULL) { + BufferSize = (NameStrLen * 4 + 1) * sizeof (CHAR16); + UnicodeToConfigString (StrPtr, &BufferSize, Name); + StrPtr += (NameStrLen * 4); + } + + StrCpy (StrPtr, L"&PATH="); + StrPtr += 6; + BufInReverseOrderToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize); + + return EFI_SUCCESS; +} + +/** + Determines if the Routing data (Guid and Name) is correct in . + + @param ConfigString Either or . + @param StorageGuid GUID of the storage. + @param StorageName Name of the stoarge. + + @retval TRUE Routing information is correct in ConfigString. + @retval FALSE Routing information is incorrect in ConfigString. + +**/ +BOOLEAN +IsConfigHdrMatch ( + IN EFI_STRING ConfigString, + IN EFI_GUID *StorageGuid, OPTIONAL + IN CHAR16 *StorageName OPTIONAL + ) +{ + EFI_STATUS Status; + BOOLEAN Match; + EFI_GUID Guid; + CHAR16 *Name; + CHAR16 *StrPtr; + UINTN BufferSize; + + // + // ::= + // GUID=32&NAME=NameStrLen&PATH=DevicePathStrLen + // | 5 | 32 | 6 | NameStrLen*4 | 6 | DevicePathStrLen | 1 | + // + if (StrLen (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 = HexStringToBufInReverseOrder ( + (UINT8 *) &Guid, + &BufferSize, + ConfigString + 5 + ); + *StrPtr = L'&'; + + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (!CompareGuid (&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 = AllocatePool (BufferSize); + ASSERT (Name != NULL); + Status = ConfigStringToUnicode ( + Name, + &BufferSize, + ConfigString + 5 + 32 + 6 + ); + *StrPtr = L'&'; + + if (EFI_ERROR (Status) || (StrCmp (Name, StorageName) != 0)) { + Match = FALSE; + } + gBS->FreePool (Name); + } + + return Match; +} + +/** + Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string. + + @param String The string to be searched in. + @param Offset Offset in BlockName. + @param Width Width in BlockName. + + @retval TRUE Block name found. + @retval FALSE Block name not found. + +**/ +BOOLEAN +EFIAPI +FindBlockName ( + IN OUT CHAR16 *String, + IN UINTN Offset, + IN UINTN Width + ) +{ + EFI_STATUS Status; + UINTN Data; + UINTN BufferSize; + UINTN ConvertedStrLen; + + while ((String = StrStr (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 (StrnCmp (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; +} + + +/** + This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser. + + @param VariableGuid An optional field to indicate the target variable + GUID name to use. + @param VariableName An optional field to indicate the target + human-readable variable name. + @param 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. + @param Buffer Buffer to hold retrived data. + + @retval EFI_SUCCESS Operation completes successfully. + @retval EFI_BUFFER_TOO_SMALL The intput buffer is too small. + @retval EFI_OUT_OF_RESOURCES There is no enough available memory space. + +**/ +EFI_STATUS +EFIAPI +GetBrowserData ( + IN CONST EFI_GUID *VariableGuid, OPTIONAL + IN CONST CHAR16 *VariableName, OPTIONAL + IN OUT UINTN *BufferSize, + IN OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status; + CONST CHAR16 *ConfigHdr; + CHAR16 *ConfigResp; + CHAR16 *StringPtr; + UINTN HeaderLen; + UINTN BufferLen; + CHAR16 *Progress; + + // + // Locate protocols for use + // + Status = LocateFormBrowser2Protocols (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Retrive formset storage data from Form Browser + // + ConfigHdr = mFakeConfigHdr; + HeaderLen = StrLen (ConfigHdr); + + // + // First try allocate 0x4000 buffer for the formet storage data. + // + BufferLen = 0x4000; + ConfigResp = AllocateZeroPool (BufferLen + HeaderLen); + if (ConfigResp == NULL) { + BufferLen = 0; + } + + StringPtr = ConfigResp + HeaderLen; + *StringPtr = L'&'; + StringPtr++; + + Status = mFormBrowser2->BrowserCallback ( + mFormBrowser2, + &BufferLen, + StringPtr, + TRUE, + VariableGuid, + VariableName + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + if (ConfigResp != NULL) { + FreePool (ConfigResp); + } + + ConfigResp = AllocateZeroPool (BufferLen + HeaderLen); + if (ConfigResp == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StringPtr = ConfigResp + HeaderLen; + *StringPtr = L'&'; + StringPtr++; + + Status = mFormBrowser2->BrowserCallback ( + mFormBrowser2, + &BufferLen, + StringPtr, + TRUE, + VariableGuid, + VariableName + ); + } + if (EFI_ERROR (Status)) { + FreePool (ConfigResp); + return Status; + } + CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16)); + + // + // Convert to buffer data + // + Status = mIfrSupportLibHiiConfigRouting->ConfigToBlock ( + mIfrSupportLibHiiConfigRouting, + ConfigResp, + Buffer, + BufferSize, + &Progress + ); + FreePool (ConfigResp); + + return Status; +} + + +/** + This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser. + + @param VariableGuid An optional field to indicate the target variable + GUID name to use. + @param VariableName An optional field to indicate the target + human-readable variable name. + @param BufferSize Length in bytes of buffer to hold retrived data. + @param Buffer Buffer to hold retrived data. + @param 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. ::= + &OFFSET=&WIDTH=* + + @retval EFI_SUCCESS Operation completes successfully. + @retval EFI_OUT_OF_RESOURCES There is no enough available memory space. + @retval Other Updating Browser uncommitted data failed. + +**/ +EFI_STATUS +EFIAPI +SetBrowserData ( + IN CONST EFI_GUID *VariableGuid, OPTIONAL + IN CONST CHAR16 *VariableName, OPTIONAL + IN UINTN BufferSize, + IN CONST UINT8 *Buffer, + IN CONST CHAR16 *RequestElement OPTIONAL + ) +{ + EFI_STATUS Status; + CONST CHAR16 *ConfigHdr; + CHAR16 *ConfigResp; + CHAR16 *StringPtr; + UINTN HeaderLen; + UINTN BufferLen; + CHAR16 *Progress; + CHAR16 BlockName[33]; + CHAR16 *ConfigRequest; + CONST CHAR16 *Request; + + // + // Locate protocols for use + // + Status = LocateFormBrowser2Protocols (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Prepare + // + ConfigHdr = mFakeConfigHdr; + HeaderLen = StrLen (ConfigHdr); + + if (RequestElement == NULL) { + // + // RequestElement not specified, use "&OFFSET=0&WIDTH=" as + // + BlockName[0] = L'\0'; + StrCpy (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) + StrSize (Request); + ConfigRequest = AllocateZeroPool (BufferLen); + if (ConfigRequest == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16)); + StringPtr = ConfigRequest + HeaderLen; + StrCpy (StringPtr, Request); + + // + // Convert buffer to + // + Status = mIfrSupportLibHiiConfigRouting->BlockToConfig ( + mIfrSupportLibHiiConfigRouting, + ConfigRequest, + Buffer, + BufferSize, + &ConfigResp, + &Progress + ); + if (EFI_ERROR (Status)) { + FreePool (ConfigRequest); + return Status; + } + + // + // Skip and '&' + // + StringPtr = ConfigResp + HeaderLen + 1; + + // + // Change uncommitted data in Browser + // + Status = mFormBrowser2->BrowserCallback ( + mFormBrowser2, + &BufferSize, + StringPtr, + FALSE, + VariableGuid, + VariableName + ); + FreePool (ConfigRequest); + return Status; +} diff --git a/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrLibraryInternal.h b/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrLibraryInternal.h new file mode 100644 index 0000000000..43897b9920 --- /dev/null +++ b/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrLibraryInternal.h @@ -0,0 +1,37 @@ +/** @file +Utility functions which helps in opcode creation, HII configuration string manipulations, +pop up window creations, setup browser persistence data set and get. + +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. + + +**/ + +#ifndef _IFRLIBRARY_INTERNAL_H_ +#define _IFRLIBRARY_INTERNAL_H_ + + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +#endif + diff --git a/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrOpCodeCreation.c b/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrOpCodeCreation.c new file mode 100644 index 0000000000..9b48a27e19 --- /dev/null +++ b/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrOpCodeCreation.c @@ -0,0 +1,891 @@ +/** @file + 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. + + +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. + + +**/ + +#include "UefiIfrLibraryInternal.h" + +/** + Check if the input question flags is a valid value. + The valid combination of question flags includes + EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY. + + @param Flags The question flags to check. + + @retval TRUE If the question flag is a valid combination. + @retval FALSE If the question flag is an invalid combination. + +**/ +BOOLEAN +IsValidQuestionFlags ( + IN UINT8 Flags + ) +{ + return (BOOLEAN) (((Flags & (~QUESTION_FLAGS)) != 0) ? FALSE : TRUE); +} + +/** + Check if the input value type is a valid type. + The valid value type is smaller or equal than EFI_IFR_TYPE_OTHER. + + @param Type The value type to check. + + @retval TRUE If the value type is valid. + @retval FALSE If the value type is invalid. + +**/ +BOOLEAN +IsValidValueType ( + IN UINT8 Type + ) +{ + return (BOOLEAN) ((Type <= EFI_IFR_TYPE_OTHER) ? TRUE : FALSE); +} + +/** + Check if the input numeric flags is a valid value. + + @param Flags The numeric flags to check. + + @retval TRUE If the numeric flags is valid. + @retval FALSE If the numeric flags is invalid. + +**/ +BOOLEAN +IsValidNumricFlags ( + IN UINT8 Flags + ) +{ + if ((Flags & ~(EFI_IFR_NUMERIC_SIZE | EFI_IFR_DISPLAY)) != 0) { + return FALSE; + } + + if ((Flags & EFI_IFR_DISPLAY) > EFI_IFR_DISPLAY_UINT_HEX) { + return FALSE; + } + + return TRUE; +} + +/** + Check if the checkbox flags is a valid value. + + @param Flags The checkbox flags to check. + + @retval TRUE If the checkbox flags is valid. + @retval FALSE If the checkbox flags is invalid. + +**/ +BOOLEAN +IsValidCheckboxFlags ( + IN UINT8 Flags + ) +{ + return (BOOLEAN) ((Flags <= EFI_IFR_CHECKBOX_DEFAULT_MFG) ? TRUE : FALSE); +} + +/** + Create EFI_IFR_END_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + +**/ +EFI_STATUS +EFIAPI +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; + // + // CopyMem is used for EFI_IFR_END to cover the unaligned address access. + // + CopyMem (LocalBuffer, &End, sizeof (EFI_IFR_END)); + Data->Offset += sizeof (EFI_IFR_END); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_DEFAULT_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param Value Value for the default + @param Type Type for the default + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER The type is not valid. + +**/ +EFI_STATUS +EFIAPI +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; + CopyMem (&Default.Value, Value, sizeof(EFI_IFR_TYPE_VALUE)); + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + // + // CopyMem is used for EFI_IFR_DEFAULT to cover the unaligned address access. + // + CopyMem (LocalBuffer, &Default, sizeof (EFI_IFR_DEFAULT)); + Data->Offset += sizeof (EFI_IFR_DEFAULT); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_ACTION_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param QuestionId Question ID + @param Prompt String ID for Prompt + @param Help String ID for Help + @param QuestionFlags Flags in Question Header + @param QuestionConfig String ID for configuration + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. + +**/ +EFI_STATUS +EFIAPI +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; + // + // CopyMem is used for EFI_IFR_ACTION to cover the unaligned address access. + // + CopyMem (LocalBuffer, &Action, sizeof (EFI_IFR_ACTION)); + Data->Offset += sizeof (EFI_IFR_ACTION); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_SUBTITLE_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param Prompt String ID for Prompt + @param Help String ID for Help + @param Flags Subtitle opcode flags + @param Scope Subtitle Scope bit + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + +**/ +EFI_STATUS +EFIAPI +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; + // + // CopyMem is used for EFI_IFR_SUBTITLE to cover the unaligned address access. + // + CopyMem (LocalBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE)); + Data->Offset += sizeof (EFI_IFR_SUBTITLE); + + return EFI_SUCCESS; +} + + +/** + Create EFI_IFR_TEXT_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param Prompt String ID for Prompt + @param Help String ID for Help + @param TextTwo String ID for text two + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + +**/ +EFI_STATUS +EFIAPI +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; + // + // CopyMem is used for EFI_IFR_TEXT to cover the unaligned address access. + // + CopyMem (LocalBuffer, &Text, sizeof (EFI_IFR_TEXT)); + Data->Offset += sizeof (EFI_IFR_TEXT); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_REF_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param FormId Destination Form ID + @param Prompt String ID for Prompt + @param Help String ID for Help + @param QuestionFlags Flags in Question Header + @param QuestionId Question ID + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. + +**/ +EFI_STATUS +EFIAPI +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; + // + // CopyMem is used for EFI_IFR_REF to cover the unaligned address access. + // + CopyMem (LocalBuffer, &Goto, sizeof (EFI_IFR_REF)); + Data->Offset += sizeof (EFI_IFR_REF); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_ONE_OF_OPTION_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param OptionCount The number of options. + @param OptionsList The list of Options. + @param Type The data type. + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER If OptionCount is not zero but OptionsList is NULL. + +**/ +EFI_STATUS +EFIAPI +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 = (UINT8) (OptionsList[Index].Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)); + OneOfOption.Type = Type; + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + // + // CopyMem is used for EFI_IFR_ONF_OF_OPTION to cover the unaligned address access. + // + CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION)); + Data->Offset += sizeof (EFI_IFR_ONE_OF_OPTION); + } + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_ONE_OF_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param QuestionId Question ID + @param VarStoreId Storage ID + @param VarOffset Offset in Storage + @param Prompt String ID for Prompt + @param Help String ID for Help + @param QuestionFlags Flags in Question Header + @param OneOfFlags Flags for oneof opcode + @param OptionsList List of options + @param OptionCount Number of options in option list + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. + +**/ +EFI_STATUS +EFIAPI +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; + ZeroMem ((VOID *) &OneOf.data, sizeof (MINMAXSTEP_DATA)); + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + // + // CopyMem is used for EFI_IFR_ONF_OF to cover the unaligned address access. + // + CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF)); + Data->Offset += sizeof (EFI_IFR_ONE_OF); + + CreateOneOfOptionOpCode (OptionCount, OptionsList, (UINT8) (OneOfFlags & EFI_IFR_NUMERIC_SIZE), Data); + + CreateEndOpCode (Data); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_ORDERED_LIST_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param QuestionId Question ID + @param VarStoreId Storage ID + @param VarOffset Offset in Storage + @param Prompt String ID for Prompt + @param Help String ID for Help + @param QuestionFlags Flags in Question Header + @param OrderedListFlags Flags for ordered list opcode + @param DataType Type for option value + @param MaxContainers Maximum count for options in this ordered list + @param OptionsList List of options + @param OptionCount Number of options in option list + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. + +**/ +EFI_STATUS +EFIAPI +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 != 0) && + (OrderedListFlags != EFI_IFR_UNIQUE_SET) && + (OrderedListFlags != EFI_IFR_NO_EMPTY_SET)) { + 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; + // + // CopyMem is used for EFI_IFR_ORDERED_LIST to cover the unaligned address access. + // + CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST)); + Data->Offset += sizeof (EFI_IFR_ORDERED_LIST); + + CreateOneOfOptionOpCode (OptionCount, OptionsList, DataType, Data); + + CreateEndOpCode (Data); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_CHECKBOX_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param QuestionId Question ID + @param VarStoreId Storage ID + @param VarOffset Offset in Storage + @param Prompt String ID for Prompt + @param Help String ID for Help + @param QuestionFlags Flags in Question Header + @param CheckBoxFlags Flags for checkbox opcode + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. + +**/ +EFI_STATUS +EFIAPI +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; + // + // CopyMem is used for EFI_IFR_CHECKBOX to cover the unaligned address access. + // + CopyMem (LocalBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX)); + Data->Offset += sizeof (EFI_IFR_CHECKBOX); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_NUMERIC_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param QuestionId Question ID + @param VarStoreId Storage ID + @param VarOffset Offset in Storage + @param Prompt String ID for Prompt + @param Help String ID for Help + @param QuestionFlags Flags in Question Header + @param NumericFlags Flags for numeric opcode + @param Minimum Numeric minimum value + @param Maximum Numeric maximum value + @param Step Numeric step for edit + @param Default Numeric default value + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. + +**/ +EFI_STATUS +EFIAPI +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 + ) +{ + 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; + } + + 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; + } + + CopyMem (&Numeric.data, &MinMaxStep, sizeof (MINMAXSTEP_DATA)); + + LocalBuffer = (UINT8 *) Data->Data + Data->Offset; + // + // CopyMem is used for EFI_IFR_NUMERIC to cover the unaligned address access. + // + CopyMem (LocalBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC)); + Data->Offset += sizeof (EFI_IFR_NUMERIC); + + DefaultValue.u64 = Default; + Status = CreateDefaultOpCode (&DefaultValue, (UINT8) (NumericFlags & EFI_IFR_NUMERIC_SIZE), Data); + if (EFI_ERROR(Status)) { + return Status; + } + + CreateEndOpCode (Data); + + return EFI_SUCCESS; +} + +/** + Create EFI_IFR_STRING_OP opcode. + + If Data is NULL or Data->Data is NULL, then ASSERT. + + @param QuestionId Question ID + @param VarStoreId Storage ID + @param VarOffset Offset in Storage + @param Prompt String ID for Prompt + @param Help String ID for Help + @param QuestionFlags Flags in Question Header + @param StringFlags Flags for string opcode + @param MinSize String minimum length + @param MaxSize String maximum length + @param Data Destination for the created opcode binary + + @retval EFI_SUCCESS Opcode is created successfully. + @retval EFI_BUFFER_TOO_SMALL The space reserved in Data field is too small. + @retval EFI_INVALID_PARAMETER If QuestionFlags is not valid. + +**/ +EFI_STATUS +EFIAPI +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) != 0) { + 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; + // + // CopyMem is used for EFI_IFR_STRING to cover the unaligned address access. + // + CopyMem (LocalBuffer, &String, sizeof (EFI_IFR_STRING)); + Data->Offset += sizeof (EFI_IFR_STRING); + + return EFI_SUCCESS; +} + + diff --git a/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrSupportLib.inf b/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrSupportLib.inf new file mode 100644 index 0000000000..b2eaae0515 --- /dev/null +++ b/MdeModulePkg/Library/UefiIfrSupportLib/UefiIfrSupportLib.inf @@ -0,0 +1,56 @@ +#/** @file +# Instance of IFR Support Library. +# +# This library contains functions to do IFR opcode creation and utility +# functions to help module to interact with a UEFI Form Browser. +# +# Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved. +# +# 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. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UefiIfrSupportLib + FILE_GUID = bf38668e-e231-4baa-99e4-8c0e4c35dca6 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = IfrSupportLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + EDK_RELEASE_VERSION = 0x00020000 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources.common] + UefiIfrForm.c + UefiIfrLibraryInternal.h + UefiIfrOpCodeCreation.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + MemoryAllocationLib + DevicePathLib + BaseLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + +[Protocols] + gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiHiiConfigRoutingProtocolGuid + gEfiFormBrowser2ProtocolGuid