/** @file HII Library implementation that uses DXE protocols and services. Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include "InternalHiiLib.h" EFI_HII_DATABASE_PROTOCOL *mHiiDatabaseProt; EFI_HII_STRING_PROTOCOL *mHiiStringProt; /** The constructor function of Hii Library. The constructor function caches the value of default HII protocol instances. @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 UefiHiiLibConstructor ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; Status = gBS->LocateProtocol ( &gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &mHiiDatabaseProt ); ASSERT_EFI_ERROR (Status); ASSERT (mHiiDatabaseProt != NULL); Status = gBS->LocateProtocol ( &gEfiHiiStringProtocolGuid, NULL, (VOID **) &mHiiStringProt ); ASSERT_EFI_ERROR (Status); ASSERT (mHiiStringProt != NULL); return EFI_SUCCESS; } EFI_HII_PACKAGE_LIST_HEADER * InternalHiiLibPreparePackages ( IN UINTN NumberOfPackages, IN CONST EFI_GUID *GuidId, OPTIONAL 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; for (Index = 0; Index < NumberOfPackages; Index++) { CopyMem (&PackageLength, VA_ARG (Marker, VOID *), sizeof (UINT32)); PackageListLength += (PackageLength - sizeof (UINT32)); } // // Include the lenght of EFI_HII_PACKAGE_END // PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER); PackageListHeader = AllocateZeroPool (PackageListLength); ASSERT (PackageListHeader != NULL); CopyMem (&PackageListHeader->PackageListGuid, GuidId, sizeof (EFI_GUID)); PackageListHeader->PackageLength = PackageListLength; PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER); Marker = MarkerBackup; for (Index = 0; Index < NumberOfPackages; Index++) { PackageArray = (UINT8 *) VA_ARG (Marker, VOID *); 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; } 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; } EFI_STATUS EFIAPI HiiLibAddPackages ( IN UINTN NumberOfPackages, IN CONST EFI_GUID *GuidId, IN EFI_HANDLE DriverHandle, OPTIONAL OUT EFI_HII_HANDLE *HiiHandle, OPTIONAL ... ) { 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; } EFI_STATUS EFIAPI HiiLibAddFontPackageToHiiDatabase ( IN UINTN FontSize, IN CONST UINT8 *FontBinary, IN CONST EFI_GUID *GuidId, OUT EFI_HII_HANDLE *HiiHandle OPTIONAL ) { EFI_STATUS Status; UINT8 *Location; EFI_HII_SIMPLE_FONT_PACKAGE_HDR *SimplifiedFont; UINTN PackageLength; EFI_HII_PACKAGE_LIST_HEADER *PackageList; UINT8 *Package; // // Add 4 bytes to the header for entire length for HiiLibPreparePackageList use only. // Looks ugly. Might be updated when font tool is ready. // PackageLength = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) + FontSize + 4; Package = AllocateZeroPool (PackageLength); if (Package == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (Package, &PackageLength, 4); SimplifiedFont = (EFI_HII_SIMPLE_FONT_PACKAGE_HDR*) (Package + 4); SimplifiedFont->Header.Length = (UINT32) (PackageLength - 4); SimplifiedFont->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS; SimplifiedFont->NumberOfNarrowGlyphs = (UINT16) (FontSize / sizeof (EFI_NARROW_GLYPH)); Location = (UINT8 *) (&SimplifiedFont->NumberOfWideGlyphs + 1); CopyMem (Location, FontBinary, FontSize); // // Add this simplified font package to a package list then install it. // PackageList = HiiLibPreparePackageList (1, GuidId, Package); Status = mHiiDatabaseProt->NewPackageList (mHiiDatabaseProt, PackageList, NULL, HiiHandle); ASSERT_EFI_ERROR (Status); SafeFreePool (PackageList); SafeFreePool (Package); return EFI_SUCCESS; } VOID EFIAPI HiiLibRemovePackages ( IN EFI_HII_HANDLE HiiHandle ) { EFI_STATUS Status; ASSERT (HiiHandle != NULL); Status = mHiiDatabaseProt->RemovePackageList (mHiiDatabaseProt, HiiHandle); ASSERT_EFI_ERROR (Status); } 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); 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; } 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); // // 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)) { return Status; } // // Extract GUID // CopyMem (Guid, &HiiPackageList->PackageListGuid, sizeof (EFI_GUID)); gBS->FreePool (HiiPackageList); return EFI_SUCCESS; } 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; } } gBS->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) { gBS->FreePool (HiiHandles); HiiHandles = AllocatePool (BufferSize); ASSERT (HiiHandles != NULL); Status = mHiiDatabaseProt->ListPackageLists ( mHiiDatabaseProt, EFI_HII_PACKAGE_TYPE_ALL, NULL, &BufferSize, HiiHandles ); } if (EFI_ERROR (Status)) { gBS->FreePool (HiiHandles); return NULL; } // // Search Hii Handle by Driver Handle // HiiHandle = NULL; HandleCount = BufferSize / sizeof (EFI_HII_HANDLE); for (Index = 0; Index < HandleCount; Index++) { Status = mHiiDatabaseProt->GetPackageListHandle ( mHiiDatabaseProt, HiiHandles[Index], &Handle ); if (!EFI_ERROR (Status) && (Handle == DriverHandle)) { HiiHandle = HiiHandles[Index]; break; } } gBS->FreePool (HiiHandles); return HiiHandle; } 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); }