/*++ | |
Copyright (c) 2006, Intel Corporation | |
All rights reserved. This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
Module Name: | |
Package.c | |
Abstract: | |
This file contains the package processing code to the HII database. | |
--*/ | |
#include "HiiDatabase.h" | |
EFI_STATUS | |
GetPackSize ( | |
IN VOID *Pack, | |
OUT UINTN *PackSize, | |
OUT UINT32 *NumberOfTokens | |
) | |
/*++ | |
Routine Description: | |
Determines the passed in Pack's size and returns the value. | |
Arguments: | |
Returns: | |
--*/ | |
{ | |
EFI_HII_STRING_PACK *StringPack; | |
UINT16 Type; | |
UINT32 Length; | |
*PackSize = 0; | |
Type = EFI_HII_IFR; | |
if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) { | |
// | |
// The header contains the full IFR length | |
// | |
CopyMem (&Length, &((EFI_HII_PACK_HEADER *) Pack)->Length, sizeof (Length)); | |
*PackSize = (UINTN) Length; | |
return EFI_SUCCESS; | |
} | |
Type = EFI_HII_STRING; | |
if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) { | |
// | |
// The header contains the STRING package length | |
// The assumption is that the strings for all languages | |
// are a contiguous block of data and there is a series of | |
// these package instances which will terminate with a NULL package | |
// instance. | |
// | |
StringPack = (EFI_HII_STRING_PACK *) Pack; | |
// | |
// There may be multiple instances packed together of strings | |
// so we must walk the self describing structures until we encounter | |
// the NULL structure to determine the full size. | |
// | |
CopyMem (&Length, &StringPack->Header.Length, sizeof (Length)); | |
if (NumberOfTokens != NULL) { | |
CopyMem (NumberOfTokens, &StringPack->NumStringPointers, sizeof (UINT32)); | |
} | |
while (Length != 0) { | |
*PackSize = *PackSize + Length; | |
StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) StringPack + Length); | |
CopyMem (&Length, &StringPack->Header.Length, sizeof (Length)); | |
} | |
// | |
// Encountered a length of 0, so let's add the space for the NULL terminator | |
// pack's length and call it done. | |
// | |
*PackSize = *PackSize + sizeof (EFI_HII_STRING_PACK); | |
return EFI_SUCCESS; | |
} | |
// | |
// We only determine the size of the non-global Package types. | |
// If neither IFR or STRING data were found, return an error | |
// | |
return EFI_NOT_FOUND; | |
} | |
EFI_STATUS | |
ValidatePack ( | |
IN EFI_HII_PROTOCOL *This, | |
IN EFI_HII_PACKAGE_INSTANCE *PackageInstance, | |
OUT EFI_HII_PACKAGE_INSTANCE **StringPackageInstance, | |
OUT UINT32 *TotalStringCount | |
) | |
/*++ | |
Routine Description: | |
Verifies that the package instance is using the correct handle for string operations. | |
Arguments: | |
Returns: | |
--*/ | |
{ | |
EFI_HII_DATA *HiiData; | |
EFI_HII_HANDLE_DATABASE *HandleDatabase; | |
EFI_HII_PACKAGE_INSTANCE *HandlePackageInstance; | |
UINT8 *RawData; | |
EFI_GUID Guid; | |
EFI_HII_IFR_PACK *FormPack; | |
UINTN Index; | |
if (This == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
HiiData = EFI_HII_DATA_FROM_THIS (This); | |
HandleDatabase = HiiData->DatabaseHead; | |
ZeroMem (&Guid, sizeof (EFI_GUID)); | |
*StringPackageInstance = PackageInstance; | |
// | |
// Based on if there is IFR data in this package instance, determine | |
// what the location is of the beginning of the string data. | |
// | |
if (PackageInstance->IfrSize > 0) { | |
FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); | |
} else { | |
// | |
// If there is no IFR data assume the caller knows what they are doing. | |
// | |
return EFI_SUCCESS; | |
} | |
RawData = (UINT8 *) FormPack; | |
for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { | |
if (RawData[Index] == EFI_IFR_FORM_SET_OP) { | |
// | |
// Cache the guid for this formset | |
// | |
CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); | |
break; | |
} | |
Index = RawData[Index + 1] + Index; | |
} | |
// | |
// If there is no string package, and the PackageInstance->IfrPack.Guid and PackageInstance->Guid are | |
// different, we should return the correct handle for the caller to use for strings. | |
// | |
if ((PackageInstance->StringSize == 0) && (!CompareGuid (&Guid, &PackageInstance->Guid))) { | |
// | |
// Search the database for a handle that matches the PackageInstance->Guid | |
// | |
for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { | |
// | |
// Get Ifrdata and extract the Guid for it | |
// | |
HandlePackageInstance = HandleDatabase->Buffer; | |
ASSERT (HandlePackageInstance->IfrSize != 0); | |
FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&HandlePackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); | |
RawData = (UINT8 *) FormPack; | |
for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { | |
if (RawData[Index] == EFI_IFR_FORM_SET_OP) { | |
// | |
// Cache the guid for this formset | |
// | |
CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); | |
break; | |
} | |
Index = RawData[Index + 1] + Index; | |
} | |
// | |
// If the Guid from the new handle matches the original Guid referenced in the original package data | |
// return the appropriate package instance data to use. | |
// | |
if (CompareGuid (&Guid, &PackageInstance->Guid)) { | |
if (TotalStringCount != NULL) { | |
*TotalStringCount = HandleDatabase->NumberOfTokens; | |
} | |
*StringPackageInstance = HandlePackageInstance; | |
} | |
} | |
// | |
// end for | |
// | |
} else { | |
return EFI_SUCCESS; | |
} | |
return EFI_SUCCESS; | |
} | |
EFI_STATUS | |
EFIAPI | |
HiiNewPack ( | |
IN EFI_HII_PROTOCOL *This, | |
IN EFI_HII_PACKAGES *Packages, | |
OUT EFI_HII_HANDLE *Handle | |
) | |
/*++ | |
Routine Description: | |
Extracts the various packs from a package list. | |
Arguments: | |
This - Pointer of HII protocol. | |
Packages - Pointer of HII packages. | |
Handle - Handle value to be returned. | |
Returns: | |
EFI_SUCCESS - Pacakges has added to HII database successfully. | |
EFI_INVALID_PARAMETER - Invalid parameter. | |
--*/ | |
{ | |
EFI_HII_PACKAGE_INSTANCE *PackageInstance; | |
EFI_HII_DATA *HiiData; | |
EFI_HII_HANDLE_DATABASE *HandleDatabase; | |
EFI_HII_HANDLE_DATABASE *Database; | |
EFI_HII_PACK_HEADER *PackageHeader; | |
EFI_HII_GLOBAL_DATA *GlobalData; | |
EFI_HII_IFR_PACK *IfrPack; | |
EFI_HII_STRING_PACK *StringPack; | |
EFI_HII_FONT_PACK *FontPack; | |
EFI_HII_KEYBOARD_PACK *KeyboardPack; | |
EFI_STATUS Status; | |
UINTN IfrSize; | |
UINTN StringSize; | |
UINTN TotalStringSize; | |
UINTN InstanceSize; | |
UINTN Count; | |
UINTN Index; | |
UINT16 Member; | |
EFI_GUID Guid; | |
EFI_FORM_SET_STUB FormSetStub; | |
UINT8 *Location; | |
UINT16 Unicode; | |
UINT16 NumWideGlyphs; | |
UINT16 NumNarrowGlyphs; | |
UINT32 NumberOfTokens; | |
UINT32 TotalTokenNumber; | |
UINT8 *Local; | |
EFI_NARROW_GLYPH *NarrowGlyph; | |
EFI_WIDE_GLYPH *WideGlyph; | |
if (Packages->NumberOfPackages == 0 || This == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
HiiData = EFI_HII_DATA_FROM_THIS (This); | |
GlobalData = HiiData->GlobalData; | |
Database = HiiData->DatabaseHead; | |
PackageInstance = NULL; | |
IfrPack = NULL; | |
StringPack = NULL; | |
InstanceSize = 0; | |
IfrSize = 0; | |
StringSize = 0; | |
TotalStringSize = 0; | |
NumberOfTokens = 0; | |
TotalTokenNumber = 0; | |
// | |
// Search through the passed in Packages for the IfrPack and any StringPack. | |
// | |
for (Index = 0; Index < Packages->NumberOfPackages; Index++) { | |
PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *)); | |
switch (PackageHeader->Type) { | |
case EFI_HII_IFR: | |
// | |
// There shoule be only one Ifr package. | |
// | |
ASSERT (IfrPack == NULL); | |
IfrPack = (EFI_HII_IFR_PACK *) PackageHeader; | |
break; | |
case EFI_HII_STRING: | |
StringPack = (EFI_HII_STRING_PACK *) PackageHeader; | |
// | |
// Sending me a String Package. Get its size. | |
// | |
Status = GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens); | |
ASSERT (!EFI_ERROR (Status)); | |
// | |
// The size which GetPackSize() returns include the null terminator. So if multiple | |
// string packages are passed in, merge all these packages, and only pad one null terminator. | |
// | |
if (TotalStringSize > 0) { | |
TotalStringSize -= sizeof (EFI_HII_STRING_PACK); | |
} | |
TotalStringSize += StringSize; | |
TotalTokenNumber += NumberOfTokens; | |
break; | |
} | |
} | |
// | |
// If sending a StringPack without an IfrPack, you must include a GuidId | |
// | |
if ((StringPack != NULL) && (IfrPack == NULL)) { | |
if (Packages->GuidId == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
} | |
// | |
// If passing in an IfrPack and a GuidId is provided, ensure they are the same value. | |
// | |
if ((IfrPack != NULL) && (Packages->GuidId != NULL)) { | |
Location = ((UINT8 *) IfrPack); | |
Location = (UINT8 *) (((UINTN) Location) + sizeof (EFI_HII_PACK_HEADER)); | |
// | |
// Advance to the Form Set Op-code | |
// | |
for (Count = 0; ((EFI_IFR_OP_HEADER *) &Location[Count])->OpCode != EFI_IFR_FORM_SET_OP;) { | |
Count = Count + ((EFI_IFR_OP_HEADER *) &Location[Count])->Length; | |
} | |
// | |
// Copy to local variable | |
// | |
CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &Location[Count])->Guid, sizeof (EFI_GUID)); | |
// | |
// Check to see if IfrPack->Guid != GuidId | |
// | |
if (!CompareGuid (&Guid, Packages->GuidId)) { | |
// | |
// If a string package is present, the GUIDs should have agreed. Return an error | |
// | |
if (StringPack != NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
} | |
} | |
// | |
// If someone is passing in a string only, create a dummy IfrPack with a Guid | |
// to enable future searching of this data. | |
// | |
if ((IfrPack == NULL) && (StringPack != NULL)) { | |
ZeroMem (&FormSetStub, sizeof (FormSetStub)); | |
FormSetStub.Header.Type = EFI_HII_IFR; | |
FormSetStub.Header.Length = sizeof (EFI_FORM_SET_STUB); | |
FormSetStub.FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP; | |
FormSetStub.FormSet.Header.Length = (UINT8) sizeof (EFI_IFR_FORM_SET); | |
// | |
// Dummy string | |
// | |
FormSetStub.FormSet.FormSetTitle = 0x02; | |
CopyMem (&FormSetStub.FormSet.Guid, Packages->GuidId, sizeof (EFI_GUID)); | |
FormSetStub.EndFormSet.Header.OpCode = EFI_IFR_END_FORM_SET_OP; | |
FormSetStub.EndFormSet.Header.Length = (UINT8) sizeof (EFI_IFR_END_FORM_SET); | |
IfrPack = (EFI_HII_IFR_PACK *) &FormSetStub; | |
} | |
if (IfrPack != NULL) { | |
// | |
// Sending me an IFR Package. Get its size. | |
// | |
Status = GetPackSize ((VOID *) IfrPack, &IfrSize, NULL); | |
ASSERT (!EFI_ERROR (Status)); | |
} | |
// | |
// Prepare the internal package instace buffer to store package data. | |
// | |
InstanceSize = IfrSize + TotalStringSize; | |
if (InstanceSize != 0) { | |
PackageInstance = AllocateZeroPool (InstanceSize + sizeof (EFI_HII_PACKAGE_INSTANCE)); | |
ASSERT (PackageInstance); | |
// | |
// If there is no DatabaseHead allocated - allocate one | |
// | |
if (HiiData->DatabaseHead == NULL) { | |
HiiData->DatabaseHead = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE)); | |
ASSERT (HiiData->DatabaseHead); | |
} | |
// | |
// If the head is being used (Handle is non-zero), allocate next Database and | |
// add it to the linked-list | |
// | |
if (HiiData->DatabaseHead->Handle != 0) { | |
HandleDatabase = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE)); | |
ASSERT (HandleDatabase); | |
for (; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) | |
; | |
// | |
// We are sitting on the Database entry which contains the null Next pointer. Fix it. | |
// | |
Database->NextHandleDatabase = HandleDatabase; | |
} | |
Database = HiiData->DatabaseHead; | |
// | |
// Initialize this instance data | |
// | |
for (*Handle = 1; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) { | |
// | |
// Since the first Database instance will have a passed back handle of 1, we will continue | |
// down the linked list of entries until we encounter the end of the linked list. Each time | |
// we go down one level deeper, increment the handle value that will be passed back. | |
// | |
if (Database->Handle >= *Handle) { | |
*Handle = Database->Handle + 1; | |
} | |
} | |
PackageInstance->Handle = *Handle; | |
PackageInstance->IfrSize = IfrSize; | |
PackageInstance->StringSize = TotalStringSize; | |
if (Packages->GuidId != NULL) { | |
CopyMem (&PackageInstance->Guid, Packages->GuidId, sizeof (EFI_GUID)); | |
} | |
Database->Buffer = PackageInstance; | |
Database->Handle = PackageInstance->Handle; | |
Database->NumberOfTokens = TotalTokenNumber; | |
Database->NextHandleDatabase = NULL; | |
} | |
// | |
// Copy the Ifr package data into package instance. | |
// | |
if (IfrSize > 0) { | |
CopyMem (&PackageInstance->IfrData, IfrPack, IfrSize); | |
} | |
// | |
// Main loop to store package data into HII database. | |
// | |
StringSize = 0; | |
TotalStringSize = 0; | |
for (Index = 0; Index < Packages->NumberOfPackages; Index++) { | |
PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *)); | |
switch (PackageHeader->Type) { | |
case EFI_HII_STRING: | |
StringPack = (EFI_HII_STRING_PACK *) PackageHeader; | |
// | |
// The size which GetPackSize() returns include the null terminator. So if multiple | |
// string packages are passed in, merge all these packages, and only pad one null terminator. | |
// | |
if (TotalStringSize > 0) { | |
TotalStringSize -= sizeof (EFI_HII_STRING_PACK); | |
} | |
GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens); | |
CopyMem ((CHAR8 *) (&PackageInstance->IfrData) + IfrSize + TotalStringSize, StringPack, StringSize); | |
TotalStringSize += StringSize; | |
break; | |
case EFI_HII_HANDLES: | |
CopyMem (&PackageInstance->HandlePack, PackageHeader, sizeof (EFI_HII_HANDLE_PACK)); | |
break; | |
case EFI_HII_FONT: | |
FontPack = (EFI_HII_FONT_PACK *) PackageHeader; | |
// | |
// Add whatever narrow glyphs were passed to us if undefined | |
// | |
CopyMem (&NumNarrowGlyphs, &FontPack->NumberOfNarrowGlyphs, sizeof (UINT16)); | |
for (Count = 0; Count <= NumNarrowGlyphs; Count++) { | |
Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + (sizeof (EFI_NARROW_GLYPH)) * Count; | |
NarrowGlyph = (EFI_NARROW_GLYPH *) Local; | |
CopyMem (&Member, &NarrowGlyph->UnicodeWeight, sizeof (UINT16)); | |
// | |
// If the glyph is already defined, do not overwrite it. It is what it is. | |
// | |
CopyMem (&Unicode, &GlobalData->NarrowGlyphs[Member].UnicodeWeight, sizeof (UINT16)); | |
if (Unicode == 0) { | |
CopyMem (&GlobalData->NarrowGlyphs[Member], Local, sizeof (EFI_NARROW_GLYPH)); | |
} | |
} | |
// | |
// Add whatever wide glyphs were passed to us if undefined | |
// | |
CopyMem (&NumWideGlyphs, &FontPack->NumberOfWideGlyphs, sizeof (UINT16)); | |
for (Count = 0; Count <= NumWideGlyphs; Count++) { | |
Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + | |
(sizeof (EFI_NARROW_GLYPH)) * | |
NumNarrowGlyphs; | |
WideGlyph = (EFI_WIDE_GLYPH *) Local; | |
CopyMem ( | |
&Member, | |
(UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count), | |
sizeof (UINT16) | |
); | |
// | |
// If the glyph is already defined, do not overwrite it. It is what it is. | |
// | |
CopyMem (&Unicode, &GlobalData->WideGlyphs[Member].UnicodeWeight, sizeof (UINT16)); | |
if (Unicode == 0) { | |
Local = (UINT8*)(&FontPack->NumberOfWideGlyphs + sizeof(UINT8)) + (sizeof(EFI_NARROW_GLYPH)) * NumNarrowGlyphs; | |
WideGlyph = (EFI_WIDE_GLYPH *) Local; | |
CopyMem ( | |
&GlobalData->WideGlyphs[Member], | |
(UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count), | |
sizeof (EFI_WIDE_GLYPH) | |
); | |
} | |
} | |
break; | |
case EFI_HII_KEYBOARD: | |
KeyboardPack = (EFI_HII_KEYBOARD_PACK *) PackageHeader; | |
// | |
// Sending me a Keyboard Package | |
// | |
if (KeyboardPack->DescriptorCount > 105) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// If someone updates the Descriptors with a count of 0, blow aware the overrides. | |
// | |
if (KeyboardPack->DescriptorCount == 0) { | |
ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106); | |
} | |
if (KeyboardPack->DescriptorCount < 106 && KeyboardPack->DescriptorCount > 0) { | |
// | |
// If SystemKeyboard was updated already, then steer changes to the override database | |
// | |
if (GlobalData->SystemKeyboardUpdate) { | |
ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106); | |
for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) { | |
CopyMem (&Member, &KeyboardPack->Descriptor[Count].Key, sizeof (UINT16)); | |
CopyMem ( | |
&GlobalData->OverrideKeyboardLayout[Member], | |
&KeyboardPack->Descriptor[Count], | |
sizeof (EFI_KEY_DESCRIPTOR) | |
); | |
} | |
} else { | |
// | |
// SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database. | |
// | |
ZeroMem (GlobalData->SystemKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106); | |
for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) { | |
CopyMem (&Member, &KeyboardPack->Descriptor->Key, sizeof (UINT16)); | |
CopyMem ( | |
&GlobalData->SystemKeyboardLayout[Member], | |
&KeyboardPack->Descriptor[Count], | |
sizeof (EFI_KEY_DESCRIPTOR) | |
); | |
} | |
// | |
// Just updated the system keyboard database, reflect that in the global flag. | |
// | |
GlobalData->SystemKeyboardUpdate = TRUE; | |
} | |
} | |
break; | |
default: | |
break; | |
} | |
} | |
return EFI_SUCCESS; | |
} | |
EFI_STATUS | |
EFIAPI | |
HiiRemovePack ( | |
IN EFI_HII_PROTOCOL *This, | |
IN EFI_HII_HANDLE Handle | |
) | |
/*++ | |
Routine Description: | |
Removes the various packs from a Handle | |
Arguments: | |
Returns: | |
--*/ | |
{ | |
EFI_HII_PACKAGE_INSTANCE *PackageInstance; | |
EFI_HII_DATA *HiiData; | |
EFI_HII_HANDLE_DATABASE *HandleDatabase; | |
EFI_HII_HANDLE_DATABASE *PreviousHandleDatabase; | |
UINTN Count; | |
if (This == NULL || Handle == 0) { | |
return EFI_INVALID_PARAMETER; | |
} | |
HiiData = EFI_HII_DATA_FROM_THIS (This); | |
HandleDatabase = HiiData->DatabaseHead; | |
PackageInstance = NULL; | |
// | |
// Initialize the Previous with the Head of the Database | |
// | |
PreviousHandleDatabase = HandleDatabase; | |
for (Count = 0; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { | |
// | |
// Match the numeric value with the database entry - if matched, | |
// free the package instance and apply fix-up to database linked list | |
// | |
if (Handle == HandleDatabase->Handle) { | |
PackageInstance = HandleDatabase->Buffer; | |
// | |
// Free the Package Instance | |
// | |
gBS->FreePool (PackageInstance); | |
// | |
// If this was the only Handle in the database | |
// | |
if (HiiData->DatabaseHead == HandleDatabase) { | |
HiiData->DatabaseHead = NULL; | |
} | |
// | |
// Make the parent->Next point to the current->Next | |
// | |
PreviousHandleDatabase->NextHandleDatabase = HandleDatabase->NextHandleDatabase; | |
gBS->FreePool (HandleDatabase); | |
return EFI_SUCCESS; | |
} | |
// | |
// If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is | |
// | |
PreviousHandleDatabase = HandleDatabase; | |
} | |
// | |
// No handle was found - error condition | |
// | |
if (PackageInstance == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
return EFI_SUCCESS; | |
} |