/** @file | |
Implement protocol interface related to package registrations. | |
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> | |
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 "HiiDatabase.h" | |
#include "HiiHandle.h" | |
BOOLEAN mInFrameworkHiiNewPack = FALSE; | |
BOOLEAN mInFrameworkHiiRemovePack = FALSE; | |
BOOLEAN mInFrameworkUpdatePakcage = FALSE; | |
UINT64 mGuidCount = 0; | |
EFI_GUID mGuidBase = { 0x14f95e01, 0xd562, 0x432e, { 0x84, 0x4a, 0x95, 0xa4, 0x39, 0x5, 0x10, 0x7e }}; | |
/** | |
Get the number of Form, STRING and Font packages in the package list passed in. | |
@param Packages Package List. | |
@param IfrPackageCount Number of IFR Packages. | |
@param StringPackageCount Number of String Packages. | |
@param FontPackageCount Number of Font Packages. | |
@retval EFI_INVALID_PARAMETER If the Package List has package with type of | |
EFI_HII_PACKAGE_KEYBOARD_LAYOUT, EFI_HII_PACKAGE_FONTS, EFI_HII_PACKAGE_IMAGES. | |
@retval EFI_SUCCESS Successfully get the number of IFR and STRING package. | |
**/ | |
EFI_STATUS | |
GetPackageCount ( | |
IN CONST EFI_HII_PACKAGES *Packages, | |
OUT UINTN *IfrPackageCount, | |
OUT UINTN *StringPackageCount, | |
OUT UINTN *FontPackageCount | |
) | |
{ | |
UINTN Index; | |
TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray; | |
ASSERT (Packages != NULL); | |
ASSERT (IfrPackageCount != NULL); | |
ASSERT (StringPackageCount != NULL); | |
ASSERT (FontPackageCount != NULL); | |
*IfrPackageCount = 0; | |
*StringPackageCount = 0; | |
*FontPackageCount = 0; | |
TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) (((UINT8 *) &Packages->GuidId) + sizeof (Packages->GuidId)); | |
for (Index = 0; Index < Packages->NumberOfPackages; Index++) { | |
// | |
// The current UEFI HII build tool generate a binary in the format defined by | |
// TIANO_AUTOGEN_PACKAGES_HEADER. We assume that all packages generated in | |
// this binary is with same package type. So the returned IfrPackageCount and StringPackageCount | |
// may not be the exact number of valid package number in the binary generated | |
// by HII Build tool. | |
// | |
switch (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type) { | |
case EFI_HII_IFR: | |
*IfrPackageCount += 1; | |
break; | |
case EFI_HII_STRING: | |
*StringPackageCount += 1; | |
break; | |
case EFI_HII_FONT: | |
*FontPackageCount += 1; | |
break; | |
// | |
// The following fonts are invalid for a module that using Framework to UEFI thunk layer. | |
// | |
default: | |
ASSERT (FALSE); | |
return EFI_INVALID_PARAMETER; | |
break; | |
} | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Insert the String Package into the Package Lists which has the TAG GUID matching | |
the PackageListGuid of the String Package. | |
The Package List must have only IFR Package and no String Package. | |
Otherwise, ASSERT. | |
@param Private The HII THUNK driver context data. | |
@param StringPackageThunkContext The HII THUNK context data. | |
@param StringPackageListHeader The String Package List Header. | |
**/ | |
VOID | |
UpdatePackListWithOnlyIfrPack ( | |
IN HII_THUNK_PRIVATE_DATA *Private, | |
IN HII_THUNK_CONTEXT *StringPackageThunkContext, | |
IN CONST EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader | |
) | |
{ | |
EFI_STATUS Status; | |
LIST_ENTRY *Link; | |
HII_THUNK_CONTEXT *ThunkContext; | |
Link = GetFirstNode (&Private->ThunkContextListHead); | |
while (!IsNull (&Private->ThunkContextListHead, Link)) { | |
ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link); | |
if (StringPackageThunkContext != ThunkContext) { | |
// | |
// Skip the String Package Thunk Entry itself. | |
// | |
if (CompareGuid (&StringPackageListHeader->PackageListGuid, &ThunkContext->TagGuid)) { | |
ASSERT (ThunkContext->StringPackageCount == 0 && ThunkContext->IfrPackageCount == 1); | |
ThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS); | |
Status = mHiiDatabase->UpdatePackageList ( | |
mHiiDatabase, | |
ThunkContext->UefiHiiHandle, | |
StringPackageListHeader | |
); | |
ASSERT_EFI_ERROR (Status); | |
ThunkContext->SharingStringPack = TRUE; | |
StringPackageThunkContext->SharingStringPack = TRUE; | |
} | |
} | |
Link = GetNextNode (&Private->ThunkContextListHead, Link); | |
} | |
} | |
/** | |
Caculate the size of UEFI Simple Font Package that is needed to | |
convert all the font a Framework Font Paackage. | |
ONLY Narrow Font is supported. Wide Font is discarded. | |
If the Package Header is not of EFI_HII_FONT type, then ASSERT. | |
@param PackHeader Pointer to Framework Font Package. | |
@return The size of the UEFI Simple Font Package. | |
**/ | |
UINTN | |
GetUefiSimpleFontPackSize ( | |
IN CONST EFI_HII_PACK_HEADER * PackHeader | |
) | |
{ | |
UINTN Size; | |
EFI_HII_FONT_PACK *FwFontPack; | |
FwFontPack = (EFI_HII_FONT_PACK *) PackHeader; | |
ASSERT (FwFontPack->Header.Type == EFI_HII_FONT); | |
Size = sizeof (EFI_HII_SIMPLE_FONT_PACKAGE_HDR) | |
+ (FwFontPack->NumberOfNarrowGlyphs * sizeof (EFI_NARROW_GLYPH)); | |
return Size; | |
} | |
/** | |
Convert Font Package in Framework format to a newly allocated UEFI | |
Simple Font Package. | |
ONLY Narrow Font is supported. Wide Font is discarded. | |
If memory allocation fails, then ASSERT. | |
@param PackHeader Pointer to Framework Font Package header. | |
@return UEFI Simple Font Package. | |
**/ | |
EFI_HII_SIMPLE_FONT_PACKAGE_HDR * | |
FrameworkFontPackToUefiSimpliedFont ( | |
IN CONST EFI_HII_PACK_HEADER * PackHeader | |
) | |
{ | |
EFI_HII_SIMPLE_FONT_PACKAGE_HDR *FontPack; | |
UINTN Size; | |
EFI_NARROW_GLYPH *FwNarrowGlyph; | |
EFI_NARROW_GLYPH *NarrowGlyph; | |
UINTN Idx; | |
EFI_HII_FONT_PACK *FwFontPack; | |
Size = GetUefiSimpleFontPackSize (PackHeader); | |
FwFontPack = (EFI_HII_FONT_PACK *) PackHeader; | |
FontPack = AllocateZeroPool (Size); | |
ASSERT (FontPack != NULL); | |
// | |
// Prepare the Header information. | |
// | |
FontPack->Header.Length = (UINT32) Size; | |
FontPack->Header.Type = EFI_HII_PACKAGE_SIMPLE_FONTS; | |
FontPack->NumberOfNarrowGlyphs = FwFontPack->NumberOfNarrowGlyphs; | |
// | |
// ONLY Narrow Font is supported. Wide Font is discarded. | |
// | |
FontPack->NumberOfWideGlyphs = 0; | |
// | |
// Copy Narrow Glyph | |
// | |
NarrowGlyph = (EFI_NARROW_GLYPH *) (FontPack + 1); | |
FwNarrowGlyph = (EFI_NARROW_GLYPH *) (FwFontPack + 1); | |
CopyMem (NarrowGlyph, FwNarrowGlyph, sizeof (EFI_NARROW_GLYPH) * FwFontPack->NumberOfNarrowGlyphs); | |
for (Idx = 0; Idx < FwFontPack->NumberOfNarrowGlyphs; Idx++) { | |
// | |
// Clear the GLYPH_NON_BREAKING (EFI_GLYPH_WIDE is used here as they are all 0x02) | |
// attribute which is not defined in UEFI EFI_NARROW_GLYPH | |
// | |
NarrowGlyph[Idx].Attributes = (UINT8) (NarrowGlyph[Idx].Attributes & ~(EFI_GLYPH_WIDE)); | |
} | |
return FontPack; | |
} | |
/** | |
Prepare a UEFI Package List from a Framework HII package list registered | |
from a Framework HII NewPack () function. | |
If either Packages or PackageListGuid is NULL, then ASSERT. | |
@param Packages The Framework HII Package List. | |
@param PackageListGuid The Package List GUID. | |
@return The UEFI Package List. | |
**/ | |
EFI_HII_PACKAGE_LIST_HEADER * | |
PrepareUefiPackageListFromFrameworkHiiPackages ( | |
IN CONST EFI_HII_PACKAGES *Packages, | |
IN CONST EFI_GUID *PackageListGuid | |
) | |
{ | |
UINTN NumberOfPackages; | |
EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; | |
UINT8 *PackageListData; | |
UINT32 PackageListLength; | |
UINT32 PackageLength; | |
EFI_HII_PACKAGE_HEADER PackageHeader; | |
UINTN Index; | |
TIANO_AUTOGEN_PACKAGES_HEADER **TianoAutogenPackageHdrArray; | |
EFI_HII_SIMPLE_FONT_PACKAGE_HDR *FontPack; | |
ASSERT (Packages != NULL); | |
ASSERT (PackageListGuid != NULL); | |
TianoAutogenPackageHdrArray = (TIANO_AUTOGEN_PACKAGES_HEADER **) ((UINT8 *) &Packages->GuidId + sizeof (Packages->GuidId)); | |
NumberOfPackages = Packages->NumberOfPackages; | |
PackageListLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER); | |
for (Index = 0; Index < NumberOfPackages; Index++) { | |
if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) { | |
// | |
// There is no tool to generate Font package in Framework HII's implementation. | |
// Therefore, Font Package be a C structure defined in Framework HII code. | |
// Therefore, Font Package will be in Framework HII format defined by EFI_HII_FONT_PACK. | |
// We need to create a UEFI Simple Font Package and copy over all data. Hence, EFI_HII_FONT | |
// is handled differently than EFI_HII_IFR and EFI_HII_STRING. | |
// | |
PackageListLength = (UINT32) (PackageListLength + GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader)); | |
} else { | |
// | |
// For EFI_HII_IFR and EFI_HII_STRING, EDK II's VFR Compiler and Build.exe will generate a binary in a format | |
// defined by TIANO_AUTOGEN_PACKAGES_HEADER. A Framework HII's EFI_HII_PACK_HEADER is inserted before | |
// the UEFI package data. | |
// | |
CopyMem (&PackageLength, &TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length, sizeof (UINT32)); | |
// | |
// EFI_HII_PACK_HEADER.FrameworkPackageHeader.Length include the sizeof FrameworkPackageHeader itself. | |
// | |
PackageListLength += (PackageLength - sizeof(EFI_HII_PACK_HEADER)); | |
} | |
} | |
// | |
// Include the lenght of EFI_HII_PACKAGE_END | |
// | |
PackageListLength += sizeof (EFI_HII_PACKAGE_HEADER); | |
PackageListHeader = AllocateZeroPool (PackageListLength); | |
ASSERT (PackageListHeader != NULL); | |
CopyMem (&PackageListHeader->PackageListGuid, PackageListGuid, sizeof (EFI_GUID)); | |
PackageListHeader->PackageLength = PackageListLength; | |
PackageListData = ((UINT8 *) PackageListHeader) + sizeof (EFI_HII_PACKAGE_LIST_HEADER); | |
// | |
// Build the UEFI Package List. | |
// | |
for (Index = 0; Index < NumberOfPackages; Index++) { | |
if (TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Type == EFI_HII_FONT) { | |
PackageLength = (UINT32) GetUefiSimpleFontPackSize (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader); | |
FontPack = FrameworkFontPackToUefiSimpliedFont (&TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader); | |
CopyMem (PackageListData, FontPack, PackageLength); | |
FreePool (FontPack); | |
} else { | |
CopyMem (&PackageLength, &(TianoAutogenPackageHdrArray[Index]->FrameworkPackageHeader.Length), sizeof (UINT32)); | |
PackageLength -= sizeof (EFI_HII_PACK_HEADER); | |
CopyMem (PackageListData, &(TianoAutogenPackageHdrArray[Index]->PackageHeader), 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; | |
} | |
/** | |
Generate a Random GUID. | |
@param Guid On output, a Random GUID will be filled. | |
**/ | |
VOID | |
GenerateRandomGuid ( | |
OUT EFI_GUID * Guid | |
) | |
{ | |
CopyGuid (Guid, &mGuidBase); | |
mGuidCount++; | |
*((UINT64 *) Guid) = *((UINT64 *) Guid) + mGuidCount; | |
} | |
/** | |
Given a Package List with only a IFR package, find the Package List that only has a String Package based on | |
the TAG GUID. Then export the String Package from the Package List and insert it | |
to the given IFR package. | |
This is to handle the case of Framework HII interface which allow String Package | |
and IFR package to be registered using two different NewPack () calls. | |
@param Private The HII THUNK driver context data. | |
@param IfrThunkContext Package List with only a IFR package. | |
@retval EFI_SUCCESS If the String Package is found and inserted to the | |
Package List with only a IFR package. | |
@retval EFI_NOT_FOUND No String Package matching the TAG GUID is found. | |
**/ | |
EFI_STATUS | |
FindStringPackAndUpdatePackListWithOnlyIfrPack ( | |
IN HII_THUNK_PRIVATE_DATA *Private, | |
IN HII_THUNK_CONTEXT *IfrThunkContext | |
) | |
{ | |
EFI_STATUS Status; | |
LIST_ENTRY *Link; | |
EFI_HII_PACKAGE_LIST_HEADER *StringPackageListHeader; | |
UINTN Size; | |
HII_THUNK_CONTEXT *ThunkContext; | |
Link = GetFirstNode (&Private->ThunkContextListHead); | |
while (!IsNull (&Private->ThunkContextListHead, Link)) { | |
ThunkContext = HII_THUNK_CONTEXT_FROM_LINK (Link); | |
if (ThunkContext != IfrThunkContext) { | |
if (CompareGuid (&IfrThunkContext->TagGuid, &ThunkContext->TagGuid) && (ThunkContext->IfrPackageCount == 0)) { | |
StringPackageListHeader = NULL; | |
Status = ExportPackageLists (ThunkContext->UefiHiiHandle, &StringPackageListHeader, &Size); | |
ASSERT_EFI_ERROR (Status); | |
if (StringPackageListHeader == NULL) { | |
return EFI_NOT_FOUND; | |
} | |
IfrThunkContext->StringPackageCount = GetPackageCountByType (StringPackageListHeader, EFI_HII_PACKAGE_STRINGS); | |
// | |
// Add Function to only get only String Packages from the Package List | |
// | |
Status = mHiiDatabase->UpdatePackageList ( | |
mHiiDatabase, | |
IfrThunkContext->UefiHiiHandle, | |
StringPackageListHeader | |
); | |
ASSERT_EFI_ERROR (Status); | |
FreePool (StringPackageListHeader); | |
IfrThunkContext->SharingStringPack = TRUE; | |
ThunkContext->SharingStringPack = TRUE; | |
return EFI_SUCCESS; | |
} | |
} | |
Link = GetNextNode (&Private->ThunkContextListHead, Link); | |
} | |
// | |
// A Form Package must have a String Package to function. | |
// If ASSERT here, check the sequence of call to Hii->NewPack. | |
// String Pack must be registered before Ifr Package is registered. | |
// | |
ASSERT (FALSE); | |
return EFI_NOT_FOUND; | |
} | |
/** | |
Register the Package List passed from the Framework HII NewPack () interface. | |
The FRAMEWORK_EFI_HII_HANDLE will be returned. | |
@param This The EFI_HII_PROTOCOL context data. Only used | |
to call HiiRemovePack. | |
@param Private The HII THUNK driver context data. | |
@param Packages Package List. | |
@param Handle On output, a FRAMEWORK_EFI_HII_HANDLE number is | |
returned. | |
@retval EFI_SUCCESS The Package List is registered successfully in | |
the database. | |
@retval EFI_UNSUPPORTED The number of IFR package in the package list | |
is greater than 1. | |
@retval EFI_OUT_OF_RESOURCE Not enough resouce. | |
**/ | |
EFI_STATUS | |
UefiRegisterPackageList ( | |
IN EFI_HII_PROTOCOL *This, | |
IN HII_THUNK_PRIVATE_DATA *Private, | |
IN EFI_HII_PACKAGES *Packages, | |
OUT FRAMEWORK_EFI_HII_HANDLE *Handle | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN StringPackageCount; | |
UINTN IfrPackageCount; | |
UINTN FontPackageCount; | |
EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader; | |
HII_THUNK_CONTEXT *ThunkContext; | |
HII_THUNK_CONTEXT *ThunkContextToRemove; | |
EFI_GUID GuidId; | |
EFI_HII_PACKAGE_HEADER *IfrPackage; | |
PackageListHeader = NULL; | |
Status = GetPackageCount (Packages, &IfrPackageCount, &StringPackageCount, &FontPackageCount); | |
ASSERT_EFI_ERROR (Status); | |
if (IfrPackageCount > 1) { | |
// | |
// HII Thunk only handle package with 0 or 1 IFR package. | |
// | |
ASSERT (FALSE); | |
return EFI_UNSUPPORTED; | |
} | |
ThunkContext = CreateThunkContext (Private, StringPackageCount, IfrPackageCount); | |
if (ThunkContext == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
ThunkContext->ByFrameworkHiiNewPack = TRUE; | |
if (Packages->GuidId == NULL) { | |
// | |
// UEFI HII Database require Package List GUID must be unique. | |
// | |
// If Packages->GuidId is NULL, the caller of FramworkHii->NewPack is registering | |
// packages with at least 1 StringPack and 1 IfrPack. Therefore, Packages->GuidId is | |
// not used as the name of the package list. Formset GUID is used as the Package List | |
// GUID instead. | |
// | |
ASSERT ((StringPackageCount >=1 && IfrPackageCount == 1) || (FontPackageCount > 0)); | |
if (IfrPackageCount > 0) { | |
IfrPackage = GetIfrPackage (Packages); | |
if (IfrPackage == NULL) { | |
Status = EFI_NOT_FOUND; | |
goto Done; | |
} | |
GetFormSetGuid (IfrPackage, &ThunkContext->TagGuid); | |
} else { | |
ASSERT (FontPackageCount > 0); | |
GenerateRandomGuid (&ThunkContext->TagGuid); | |
} | |
} else { | |
ThunkContextToRemove = TagGuidToIfrPackThunkContext (Private, Packages->GuidId); | |
if (IfrPackageCount > 0 && | |
StringPackageCount > 0 && | |
(ThunkContextToRemove != NULL)) { | |
DEBUG((EFI_D_WARN, "Framework code registers HII package list with the same GUID more than once.\n")); | |
DEBUG((EFI_D_WARN, "Remove the previously registered package list and register the new one.\n")); | |
HiiRemovePack (This, ThunkContextToRemove->FwHiiHandle); | |
} | |
CopyGuid (&ThunkContext->TagGuid, Packages->GuidId); | |
} | |
// | |
// UEFI HII require EFI_HII_CONFIG_ACCESS_PROTOCOL to be installed on a EFI_HANDLE, so | |
// that Setup Utility can load the Buffer Storage using this protocol. An UEFI VFR can only | |
// produce IFR package generated with Buffer Storage type and EFI Variable Storage. | |
// The default EFI_HII_CONFIG_ACCESS_PROTOCOL is used to Get/Set the Buffer Storage. | |
// | |
if (IfrPackageCount != 0) { | |
InstallDefaultConfigAccessProtocol (Packages, ThunkContext); | |
} | |
PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &ThunkContext->TagGuid); | |
Status = mHiiDatabase->NewPackageList ( | |
mHiiDatabase, | |
PackageListHeader, | |
ThunkContext->UefiHiiDriverHandle, | |
&ThunkContext->UefiHiiHandle | |
); | |
if (Status == EFI_INVALID_PARAMETER) { | |
FreePool (PackageListHeader); | |
// | |
// UEFI HII database does not allow two package list with the same GUID. | |
// In Framework HII implementation, Packages->GuidId is used as an identifier to associate | |
// a PackageList with only IFR to a Package list the with String package. | |
// | |
GenerateRandomGuid (&GuidId); | |
PackageListHeader = PrepareUefiPackageListFromFrameworkHiiPackages (Packages, &GuidId); | |
Status = mHiiDatabase->NewPackageList ( | |
mHiiDatabase, | |
PackageListHeader, | |
ThunkContext->UefiHiiDriverHandle, | |
&ThunkContext->UefiHiiHandle | |
); | |
} | |
// | |
// BUGBUG: Remove when development is done | |
// | |
ASSERT_EFI_ERROR (Status); | |
if (EFI_ERROR (Status)) { | |
goto Done; | |
} | |
if (IfrPackageCount == 0) { | |
if (StringPackageCount != 0) { | |
// | |
// Look for a Package List with only IFR Package with the same TAG GUID name. | |
// If found one, add the String Packages to the found Package List. | |
// This is needed because Framework HII Module may not register the String Package | |
// and IFR Package in one NewPack () call. | |
// | |
UpdatePackListWithOnlyIfrPack ( | |
Private, | |
ThunkContext, | |
PackageListHeader | |
); | |
} | |
} else { | |
if (StringPackageCount == 0) { | |
// | |
// Look for the String Package with the same TAG GUID name and add | |
// the found String Package to this Package List. | |
// This is needed because Framework HII Module may not register the String Package | |
// and IFR Package in one NewPack () call. | |
// | |
Status = FindStringPackAndUpdatePackListWithOnlyIfrPack ( | |
Private, | |
ThunkContext | |
); | |
if (EFI_ERROR (Status)) { | |
goto Done; | |
} | |
} | |
// | |
// Parse the Formset. Must be called after FindStringPackAndUpdatePackListWithOnlyIfrPack is called so | |
// that String Package is ready. | |
// | |
ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle); | |
ASSERT (ThunkContext->FormSet != NULL); | |
} | |
Done: | |
if (EFI_ERROR (Status)) { | |
DestroyThunkContext (ThunkContext); | |
} else { | |
InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link); | |
*Handle = ThunkContext->FwHiiHandle; | |
} | |
if (PackageListHeader != NULL) { | |
FreePool (PackageListHeader); | |
} | |
return Status; | |
} | |
/** | |
Registers the various packages that are passed in a Package List. | |
@param This Pointer of Frameowk HII protocol instance. | |
@param Packages Pointer of HII packages. | |
@param Handle Handle value to be returned. | |
@retval EFI_SUCCESS Packages has added to HII database successfully. | |
@retval EFI_INVALID_PARAMETER If Handle or Packages is NULL. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
HiiNewPack ( | |
IN EFI_HII_PROTOCOL *This, | |
IN EFI_HII_PACKAGES *Packages, | |
OUT FRAMEWORK_EFI_HII_HANDLE *Handle | |
) | |
{ | |
EFI_STATUS Status; | |
HII_THUNK_PRIVATE_DATA *Private; | |
EFI_TPL OldTpl; | |
if (Handle == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (Packages == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
// | |
// We use a simple Global variable to inform NewOrAddPackNotify() | |
// that the package list registered here is already registered | |
// in the HII Thunk Layer. So NewOrAddPackNotify () does not need to | |
// call registered the Package List again. | |
// | |
mInFrameworkHiiNewPack = TRUE; | |
Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This); | |
Status = UefiRegisterPackageList ( | |
This, | |
Private, | |
Packages, | |
Handle | |
); | |
mInFrameworkHiiNewPack = FALSE; | |
gBS->RestoreTPL (OldTpl); | |
return Status; | |
} | |
/** | |
Remove a package from the HII database. | |
@param This Pointer of Frameowk HII protocol instance. | |
@param Handle Handle value to be removed. | |
@retval EFI_SUCCESS Packages has added to HII database successfully. | |
@retval EFI_INVALID_PARAMETER If Handle or Packages is NULL. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
HiiRemovePack ( | |
IN EFI_HII_PROTOCOL *This, | |
IN FRAMEWORK_EFI_HII_HANDLE Handle | |
) | |
{ | |
EFI_STATUS Status; | |
HII_THUNK_PRIVATE_DATA *Private; | |
HII_THUNK_CONTEXT *ThunkContext; | |
EFI_TPL OldTpl; | |
OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
mInFrameworkHiiRemovePack = TRUE; | |
Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This); | |
ThunkContext = FwHiiHandleToThunkContext (Private, Handle); | |
if (ThunkContext != NULL) { | |
Status = mHiiDatabase->RemovePackageList ( | |
mHiiDatabase, | |
ThunkContext->UefiHiiHandle | |
); | |
ASSERT_EFI_ERROR (Status); | |
if (ThunkContext->IfrPackageCount != 0) { | |
UninstallDefaultConfigAccessProtocol (ThunkContext); | |
} | |
DestroyThunkContext (ThunkContext); | |
}else { | |
Status = EFI_NOT_FOUND; | |
} | |
mInFrameworkHiiRemovePack = FALSE; | |
gBS->RestoreTPL (OldTpl); | |
return Status; | |
} | |
/** | |
This notification function will be called when a Package List is registered | |
using UEFI HII interface. The Package List registered need to be recorded in | |
Framework Thunk module as Thunk Module may need to look for String Package in | |
the package registered. | |
If the Package List registered is not either Sting Package or IFR package, | |
then ASSERT. If the NotifyType is not ADD_PACK or NEW_PACK, then ASSERT. | |
Both cases means UEFI HII Database itself is buggy. | |
@param PackageType The Package Type. | |
@param PackageGuid The Package GUID. | |
@param Package The Package Header. | |
@param Handle The HII Handle of this Package List. | |
@param NotifyType The reason of the notification. | |
@retval EFI_SUCCESS The notification function is successful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
NewOrAddPackNotify ( | |
IN UINT8 PackageType, | |
IN CONST EFI_GUID *PackageGuid, | |
IN CONST EFI_HII_PACKAGE_HEADER *Package, | |
IN EFI_HII_HANDLE Handle, | |
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType | |
) | |
{ | |
EFI_STATUS Status; | |
HII_THUNK_PRIVATE_DATA *Private; | |
HII_THUNK_CONTEXT *ThunkContext; | |
ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS || PackageType == EFI_HII_PACKAGE_FORMS); | |
ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_ADD_PACK || NotifyType == EFI_HII_DATABASE_NOTIFY_NEW_PACK); | |
Status = EFI_SUCCESS; | |
Private = mHiiThunkPrivateData; | |
if (mInFrameworkHiiNewPack || mInFrameworkUpdatePakcage) { | |
return EFI_SUCCESS; | |
} | |
// | |
// We will create a ThunkContext to log the package list only if the | |
// package is not registered with by Framework HII Thunk module yet. | |
// | |
ThunkContext = UefiHiiHandleToThunkContext (Private, Handle); | |
if (ThunkContext == NULL) { | |
ThunkContext = CreateThunkContextForUefiHiiHandle (Handle); | |
ASSERT (ThunkContext != NULL); | |
InsertTailList (&Private->ThunkContextListHead, &ThunkContext->Link); | |
} | |
if (PackageType == EFI_HII_PACKAGE_FORMS) { | |
if (ThunkContext->FormSet != NULL) { | |
DestroyFormSet (ThunkContext->FormSet); | |
} | |
// | |
// Reparse the FormSet. | |
// | |
ThunkContext->FormSet = ParseFormSet (ThunkContext->UefiHiiHandle); | |
} | |
return Status; | |
} | |
/** | |
This notification function will be called when a Package List is removed | |
using UEFI HII interface. The Package List removed need to be removed from | |
Framework Thunk module too. | |
If the Package List registered is not Sting Package, | |
then ASSERT. If the NotifyType is not REMOVE_PACK, then ASSERT. | |
Both cases means UEFI HII Database itself is buggy. | |
@param PackageType The Package Type. | |
@param PackageGuid The Package GUID. | |
@param Package The Package Header. | |
@param Handle The HII Handle of this Package List. | |
@param NotifyType The reason of the notification. | |
@retval EFI_SUCCESS The notification function is successful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
RemovePackNotify ( | |
IN UINT8 PackageType, | |
IN CONST EFI_GUID *PackageGuid, | |
IN CONST EFI_HII_PACKAGE_HEADER *Package, | |
IN EFI_HII_HANDLE Handle, | |
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType | |
) | |
{ | |
EFI_STATUS Status; | |
HII_THUNK_PRIVATE_DATA *Private; | |
HII_THUNK_CONTEXT *ThunkContext; | |
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList; | |
UINTN BufferSize; | |
Status = EFI_SUCCESS; | |
ASSERT (PackageType == EFI_HII_PACKAGE_STRINGS); | |
ASSERT (NotifyType == EFI_HII_DATABASE_NOTIFY_REMOVE_PACK); | |
if (mInFrameworkHiiRemovePack || mInFrameworkUpdatePakcage) { | |
return EFI_SUCCESS; | |
} | |
Private = mHiiThunkPrivateData; | |
ThunkContext = UefiHiiHandleToThunkContext (Private, Handle); | |
// | |
// BugBug: Change to ASSERT if HII Database fix the bug and to also invoke | |
// NEW_PACK_NOTIFY for package (String Package) created internally. | |
// | |
if (ThunkContext != NULL) { | |
if (!ThunkContext->ByFrameworkHiiNewPack) { | |
HiiPackageList = NULL; | |
Status = ExportPackageLists (Handle, &HiiPackageList, &BufferSize); | |
ASSERT_EFI_ERROR (Status); | |
if (HiiPackageList == NULL) { | |
return EFI_NOT_FOUND; | |
} | |
if (GetPackageCountByType (HiiPackageList, EFI_HII_PACKAGE_STRINGS) == 1) { | |
// | |
// If the string package will be removed is the last string package | |
// in the package list, we will remove the HII Thunk entry from the | |
// database. | |
// | |
DestroyThunkContextForUefiHiiHandle (Private, Handle); | |
} | |
FreePool (HiiPackageList); | |
} | |
} | |
return Status; | |
} | |