alder_lake_bios/Insyde/InsydeSetupPkg/Drivers/H2OFormBrowserDxe/Link.c

1392 lines
40 KiB
C

/** @file
For H2O Setup Link protocol
;******************************************************************************
;* Copyright (c) 2013 - 2021, Insyde Software Corp. All Rights Reserved.
;*
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
;* transmit, broadcast, present, recite, release, license or otherwise exploit
;* any part of this publication in any form, by any means, without the prior
;* written permission of Insyde Software Corporation.
;*
;******************************************************************************
*/
#include "InternalH2OFormBrowser.h"
extern H2O_FORM_BROWSER_PRIVATE_DATA mFBPrivate;
STATIC
BOOLEAN
ChkHasFormSet (
IN CONST EFI_HII_HANDLE HiiHandle,
IN CONST EFI_GUID *FormsetGuid
)
{
EFI_STATUS Status;
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
UINTN BufferSize;
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
UINT8 *Package;
UINT8 *OpCodeData;
UINT32 Offset;
UINT32 PackageOffset;
UINT32 PackageListLength;
EFI_HII_PACKAGE_HEADER PackageHeader;
if (HiiHandle == NULL || FormsetGuid == NULL) {
return FALSE;
}
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
if (EFI_ERROR (Status)) {
return FALSE;
}
Status = FBHiiExportPackageLists (HiiHandle, &BufferSize, &HiiPackageList);
if (EFI_ERROR (Status)) {
return FALSE;
}
//
// Get Form package and check form set class GUID in this HII package list
//
Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
while (Offset < PackageListLength) {
Package = (UINT8 *) HiiPackageList + Offset;
CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
while (PackageOffset < PackageHeader.Length) {
OpCodeData = Package + PackageOffset;
if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP &&
CompareGuid ((EFI_GUID *) (VOID *) (&((EFI_IFR_FORM_SET *) OpCodeData)->Guid), FormsetGuid)) {
FreePool (HiiPackageList);
return TRUE;
}
PackageOffset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
}
}
Offset += PackageHeader.Length;
}
FreePool (HiiPackageList);
return FALSE;
}
STATIC
BOOLEAN
ChkHasClassGuid (
IN CONST EFI_HII_HANDLE HiiHandle,
IN CONST EFI_GUID *ClassGuid,
OUT EFI_GUID *FormsetGuid
)
{
EFI_STATUS Status;
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
UINTN BufferSize;
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
UINT8 *Package;
UINT8 *OpCodeData;
UINT32 Offset;
UINT32 PackageOffset;
UINT32 PackageListLength;
EFI_HII_PACKAGE_HEADER PackageHeader;
EFI_IFR_FORM_SET *FormSet;
UINT32 Index;
UINT32 ClassGuidCount;
EFI_GUID *ClassGuidList;
if (HiiHandle == NULL || ClassGuid == NULL || FormsetGuid == NULL) {
return FALSE;
}
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
if (EFI_ERROR (Status)) {
return FALSE;
}
Status = FBHiiExportPackageLists (HiiHandle, &BufferSize, &HiiPackageList);
if (EFI_ERROR (Status)) {
return FALSE;
}
//
// Get Form package and check form set class GUID in this HII package list
//
Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
while (Offset < PackageListLength) {
Package = (UINT8 *) HiiPackageList + Offset;
CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
PackageOffset = sizeof (EFI_HII_PACKAGE_HEADER);
while (PackageOffset < PackageHeader.Length) {
OpCodeData = Package + PackageOffset;
if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
FormSet = (EFI_IFR_FORM_SET *) OpCodeData;
ClassGuidCount = (FormSet->Header.Length - sizeof (EFI_IFR_FORM_SET)) / sizeof (EFI_GUID);
ClassGuidList = (EFI_GUID *)(FormSet + 1);
for (Index = 0; Index < ClassGuidCount; Index ++) {
if (CompareGuid (&ClassGuidList[Index], ClassGuid)) {
CopyGuid (FormsetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);
FreePool (HiiPackageList);
return TRUE;
}
}
}
PackageOffset += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
}
}
Offset += PackageHeader.Length;
}
FreePool (HiiPackageList);
return FALSE;
}
STATIC
EFI_STATUS
GetDevicePathStrByHiiHandle (
IN CONST EFI_HII_HANDLE HiiHandle,
OUT CHAR16 **DevicePathStr
)
{
EFI_STATUS Status;
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToText;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_HANDLE DriverHandle;
if (HiiHandle == NULL || DevicePathStr == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
if (EFI_ERROR (Status)) {
return Status;
}
Status = HiiDatabase->GetPackageListHandle (HiiDatabase, HiiHandle, &DriverHandle);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->HandleProtocol (DriverHandle, &gEfiDevicePathProtocolGuid, (VOID**) &DevicePath);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **) &DevicePathToText);
if (EFI_ERROR (Status)) {
return Status;
}
*DevicePathStr = DevicePathToText->ConvertDevicePathToText (DevicePath, FALSE, TRUE);
if (*DevicePathStr == NULL) {
EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
GetFirstFormId (
IN CONST EFI_HII_HANDLE HiiHandle,
IN CONST EFI_GUID *FormSetGuid,
OUT EFI_FORM_ID *FirstFormId
)
{
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
EFI_STATUS Status;
UINTN BufferSize;
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
UINT8 *Package;
UINT8 *OpCodeData;
UINT32 Offset;
UINT32 Offset2;
UINT32 PackageListLength;
EFI_HII_PACKAGE_HEADER PackageHeader;
BOOLEAN Found;
EFI_IFR_FORM_SET *FormSet;
EFI_GUID ZeroGuid;
if (HiiHandle == NULL || FormSetGuid == NULL || FirstFormId == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
if (EFI_ERROR (Status)) {
return Status;
}
Status = FBHiiExportPackageLists (HiiHandle, &BufferSize, &HiiPackageList);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get Form package from this HII package List
//
Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
Offset2 = 0;
PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
if (PackageListLength > BufferSize) {
PackageListLength = (UINT32)BufferSize;
}
ZeroMem (&ZeroGuid, sizeof(EFI_GUID));
FormSet = NULL;
Found = FALSE;
while (Offset < PackageListLength) {
Package = ((UINT8 *) HiiPackageList) + Offset;
CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
//
// Search FormSet Opcode in this Form Package
//
Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
while (Offset2 < PackageHeader.Length) {
OpCodeData = Package + Offset2;
if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
FormSet = (EFI_IFR_FORM_SET *) OpCodeData;
if (!CompareGuid (FormSetGuid, &ZeroGuid) &&
!CompareGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid)) {
FormSet = NULL;
}
}
if (FormSet != NULL && (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_OP)) {
*FirstFormId = ((EFI_IFR_FORM *) OpCodeData)->FormId;
Found = TRUE;
break;
}
//
// Go to next opcode
//
Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < sizeof (EFI_IFR_OP_HEADER)) {
break;
}
}
}
if (Found) {
break;
}
//
// Go to next package
//
Offset += PackageHeader.Length;
if (PackageHeader.Length == 0) {
break;
}
}
FreePool (HiiPackageList);
return Found ? EFI_SUCCESS : EFI_NOT_FOUND;
}
STATIC
EFI_STATUS
GetAllFirstFormId (
IN CONST UINT32 FormSetCount,
IN CONST EFI_HII_HANDLE *HiiHandleList,
IN CONST EFI_GUID *FormSetGuidList,
OUT EFI_FORM_ID **FirstFormIdList
)
{
EFI_STATUS Status;
UINT32 Index;
EFI_FORM_ID *ResultFormIdList;
if (FormSetCount == 0 || HiiHandleList == NULL || FormSetGuidList == NULL) {
return EFI_INVALID_PARAMETER;
}
ResultFormIdList = AllocateZeroPool (sizeof (EFI_FORM_ID) * FormSetCount);
if (ResultFormIdList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
for (Index = 0; Index < FormSetCount; Index ++) {
Status = GetFirstFormId (
HiiHandleList[Index],
&FormSetGuidList[Index],
&ResultFormIdList[Index]
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return Status;
}
}
*FirstFormIdList = ResultFormIdList;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
GetFormSetInfo (
IN CONST EFI_HII_HANDLE HiiHandle,
IN OUT EFI_GUID *FormSetGuid,
OUT EFI_STRING_ID *FormSetTitleStrId,
OUT EFI_STRING_ID *FormSetHelpStrId,
OUT EFI_FORM_ID *RootFormId
)
{
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
EFI_STATUS Status;
UINTN BufferSize;
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
UINT8 *Package;
UINT8 *OpCodeData;
UINT32 Offset;
UINT32 Offset2;
UINT32 PackageListLength;
EFI_HII_PACKAGE_HEADER PackageHeader;
BOOLEAN Found;
EFI_IFR_FORM_SET *FormSet;
EFI_GUID ZeroGuid;
if (HiiHandle == NULL || FormSetGuid == NULL || FormSetTitleStrId == NULL || FormSetHelpStrId == NULL || RootFormId == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
if (EFI_ERROR (Status)) {
return Status;
}
Status = FBHiiExportPackageLists (HiiHandle, &BufferSize, &HiiPackageList);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get Form package from this HII package List
//
Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
Offset2 = 0;
PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
if (PackageListLength > BufferSize) {
PackageListLength = (UINT32)BufferSize;
}
ZeroMem (&ZeroGuid, sizeof(EFI_GUID));
FormSet = NULL;
Found = FALSE;
while (Offset < PackageListLength) {
Package = ((UINT8 *) HiiPackageList) + Offset;
CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
if (PackageHeader.Type == EFI_HII_PACKAGE_FORMS) {
//
// Search FormSet Opcode in this Form Package
//
Offset2 = sizeof (EFI_HII_PACKAGE_HEADER);
while (Offset2 < PackageHeader.Length) {
OpCodeData = Package + Offset2;
if (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_SET_OP) {
FormSet = (EFI_IFR_FORM_SET *) OpCodeData;
if (CompareGuid (FormSetGuid, &ZeroGuid) || CompareGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid)) {
CopyGuid (FormSetGuid, (EFI_GUID *)(VOID *)&FormSet->Guid);
*FormSetTitleStrId = FormSet->FormSetTitle;
*FormSetHelpStrId = FormSet->Help;
} else {
FormSet = NULL;
}
}
if (FormSet != NULL && (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode == EFI_IFR_FORM_OP)) {
*RootFormId = ((EFI_IFR_FORM *) OpCodeData)->FormId;
Found = TRUE;
break;
}
//
// Go to next opcode
//
Offset2 += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
if (((EFI_IFR_OP_HEADER *) OpCodeData)->Length < sizeof (EFI_IFR_OP_HEADER)) {
break;
}
}
}
if (Found) {
break;
}
//
// Go to next package
//
Offset += PackageHeader.Length;
if (PackageHeader.Length == 0) {
break;
}
}
FreePool (HiiPackageList);
return Found ? EFI_SUCCESS : EFI_NOT_FOUND;
}
STATIC
EFI_STATUS
GetHiiHandleByFormSetGuid (
IN CONST EFI_GUID *FormsetGuid,
OUT UINT32 *FormsetCount,
OUT EFI_HII_HANDLE *HiiHandleList,
OUT EFI_GUID *FormsetGuidList
)
{
EFI_HII_HANDLE *HiiHandles;
UINTN Index;
if (FormsetGuid == NULL || FormsetCount == NULL || HiiHandleList == NULL) {
return EFI_INVALID_PARAMETER;
}
HiiHandles = HiiGetHiiHandles (NULL);
if (HiiHandles == NULL) {
return EFI_NOT_FOUND;
}
(*FormsetCount) = 0;
for (Index = 0; HiiHandles[Index] != NULL; Index++) {
if (ChkHasFormSet (HiiHandles[Index], FormsetGuid)) {
HiiHandleList[(*FormsetCount)] = HiiHandles[Index];
CopyGuid (&FormsetGuidList[(*FormsetCount)], FormsetGuid);
(*FormsetCount)++;
}
}
FreePool (HiiHandles);
if ((*FormsetCount) != 0) {
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
STATIC
EFI_STATUS
GetFormsetsByClassGuid (
IN CONST EFI_GUID *ClassGuid,
OUT UINT32 *FormsetCount,
OUT EFI_HII_HANDLE *HiiHandleList,
OUT EFI_GUID *FormsetGuidList
)
{
EFI_HII_HANDLE *HiiHandles;
UINT32 Index;
if (ClassGuid == NULL || FormsetCount == NULL || HiiHandleList == NULL || FormsetGuidList == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Get all HiiHandles in current hii database
//
HiiHandles = HiiGetHiiHandles (NULL);
if (HiiHandles == NULL) {
return EFI_NOT_FOUND;
}
(*FormsetCount) = 0;
for (Index = 0; HiiHandles[Index] != NULL; Index++) {
//
// Get HiiFormPkg by HiiHandle, and check this ClassGuid in its formset
// If true, return FormsetGuid
//
if (!ChkHasClassGuid (HiiHandles[Index], ClassGuid, &FormsetGuidList[(*FormsetCount)])) {
continue;
}
if (CompareGuid (ClassGuid, &FormsetGuidList[(*FormsetCount)])) {
continue;
}
HiiHandleList[(*FormsetCount)] = HiiHandles[Index];
(*FormsetCount) ++;
}
FreePool (HiiHandles);
if ((*FormsetCount) != 0) {
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
STATIC
EFI_STATUS
GetFormsetsByLink (
IN CONST EFI_GUID *FormsetGuid,
IN CONST UINT32 IncludeCount,
IN CONST UINT32 ExcludeCount,
IN CONST EFI_GUID *IncludeList,
IN CONST EFI_GUID *ExcludeList,
OUT UINT32 *FormsetCount,
OUT EFI_HII_HANDLE **HiiHandleList,
OUT EFI_GUID **FormsetGuidList
)
{
EFI_STATUS Status;
UINT32 IncludeIndex;
UINT32 ExcludeIndex;
UINT32 Count;
UINT32 IncludeFormsetCount;
EFI_HII_HANDLE *IncludeHiiHandleList;
EFI_GUID *IncludeFormsetGuidList;
UINT32 ExcludeFormsetCount;
EFI_HII_HANDLE *ExcludeHiiHandleList;
EFI_GUID *ExcludeFormsetGuidList;
UINT32 ResultFormsetCount;
EFI_HII_HANDLE *ResultHiiHandleList;
EFI_GUID *ResultFormsetGuidList;
BOOLEAN Skip;
IncludeHiiHandleList = (EFI_HII_HANDLE *)AllocateZeroPool (sizeof (EFI_HII_HANDLE) * 100);
IncludeFormsetGuidList = (EFI_GUID *)AllocateZeroPool (sizeof (EFI_GUID) * 100);
ExcludeHiiHandleList = (EFI_HII_HANDLE *)AllocateZeroPool (sizeof (EFI_HII_HANDLE) * 100);
ExcludeFormsetGuidList = (EFI_GUID *)AllocateZeroPool (sizeof (EFI_GUID) * 100);
ResultHiiHandleList = (EFI_HII_HANDLE *)AllocateZeroPool (sizeof (EFI_HII_HANDLE) * 100);
ResultFormsetGuidList = (EFI_GUID *)AllocateZeroPool (sizeof (EFI_GUID) * 100);
if (IncludeHiiHandleList == NULL || IncludeFormsetGuidList == NULL ||
ExcludeHiiHandleList == NULL || ExcludeFormsetGuidList == NULL ||
ResultHiiHandleList == NULL || ResultFormsetGuidList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Get Include Formsets
//
IncludeFormsetCount = 0;
for (IncludeIndex = 0; IncludeIndex < IncludeCount; IncludeIndex ++) {
if (!CompareGuid (&IncludeList[IncludeIndex], FormsetGuid)) {
//
// Formset Guid
//
Count = 0;
Status = GetHiiHandleByFormSetGuid (
&IncludeList[IncludeIndex],
&Count,
&IncludeHiiHandleList[IncludeFormsetCount],
&IncludeFormsetGuidList[IncludeFormsetCount]
);
if (Status == EFI_SUCCESS) {
IncludeFormsetCount += Count;
continue;
}
}
//
// Class Guid
//
Count = 0;
Status = GetFormsetsByClassGuid (
&IncludeList[IncludeIndex],
&Count,
&IncludeHiiHandleList[IncludeFormsetCount],
&IncludeFormsetGuidList[IncludeFormsetCount]
);
if (Status == EFI_SUCCESS) {
IncludeFormsetCount += Count;
}
}
//
// Get Exclude Formsets
//
ExcludeFormsetCount = 0;
for (ExcludeIndex = 0; ExcludeIndex < ExcludeCount; ExcludeIndex ++) {
//
// Formset Guid
//
Count = 0;
Status = GetHiiHandleByFormSetGuid (
&ExcludeList[ExcludeIndex],
&Count,
&ExcludeHiiHandleList[ExcludeFormsetCount],
&ExcludeFormsetGuidList[ExcludeFormsetCount]
);
if (Status == EFI_SUCCESS) {
ExcludeFormsetCount += Count;
continue;
}
//
// Class Guid
//
Count = 0;
Status = GetFormsetsByClassGuid (
&ExcludeList[ExcludeIndex],
&Count,
&ExcludeHiiHandleList[ExcludeFormsetCount],
&ExcludeFormsetGuidList[ExcludeFormsetCount]
);
if (Status == EFI_SUCCESS) {
ExcludeFormsetCount += Count;
}
}
//
// Merge Formsets
//
ResultFormsetCount = 0;
for (IncludeIndex = 0; IncludeIndex < IncludeFormsetCount; IncludeIndex ++) {
Skip = FALSE;
for (ExcludeIndex = 0; ExcludeIndex < ExcludeFormsetCount; ExcludeIndex ++) {
if ((IncludeHiiHandleList[IncludeIndex] == ExcludeHiiHandleList[ExcludeIndex]) ||
CompareGuid (&IncludeFormsetGuidList[IncludeIndex], &ExcludeFormsetGuidList[ExcludeIndex])) {
Skip = TRUE;
break;
}
}
if (!Skip) {
ResultHiiHandleList[ResultFormsetCount] = IncludeHiiHandleList[IncludeIndex];
CopyGuid (&ResultFormsetGuidList[ResultFormsetCount], (EFI_GUID *)(VOID *)&IncludeFormsetGuidList[IncludeIndex]);
ResultFormsetCount ++;
}
}
*FormsetCount = ResultFormsetCount;
*HiiHandleList = (ResultFormsetCount == 0) ? NULL : (EFI_HII_HANDLE *)AllocateCopyPool (sizeof (EFI_HII_HANDLE) * ResultFormsetCount, ResultHiiHandleList);
*FormsetGuidList = (ResultFormsetCount == 0) ? NULL : (EFI_GUID *)AllocateCopyPool (sizeof (EFI_GUID) * ResultFormsetCount, ResultFormsetGuidList);
FreePool (IncludeHiiHandleList);
FreePool (IncludeFormsetGuidList);
FreePool (ExcludeHiiHandleList);
FreePool (ExcludeFormsetGuidList);
FreePool (ResultHiiHandleList);
FreePool (ResultFormsetGuidList);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
GetIncludeByPcd (
IN CONST EFI_GUID *FormsetGuid,
OUT UINT32 *IncludeCount,
OUT EFI_GUID **IncludeList
)
{
UINTN TokenNum;
EFI_GUID *Guid;
EFI_GUID *TempGuidList;
UINT32 Count;
if (FormsetGuid == NULL || IncludeCount == NULL || IncludeList == NULL) {
return EFI_INVALID_PARAMETER;
}
TempGuidList = (EFI_GUID *)AllocateZeroPool (sizeof (EFI_GUID) * 100);
if (TempGuidList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Count = 0;
TokenNum = LibPcdGetNextToken(FormsetGuid, 0);
while (TokenNum != 0) {
Guid = (EFI_GUID *) LibPcdGetExPtr(FormsetGuid, TokenNum);
CopyGuid (&TempGuidList[Count], Guid);
Count ++;
TokenNum = LibPcdGetNextToken(FormsetGuid, TokenNum);
}
if (Count == 0) {
FreePool (TempGuidList);
return EFI_NOT_FOUND;
}
*IncludeCount = Count;
*IncludeList = (EFI_GUID *)AllocateCopyPool (sizeof (EFI_GUID) * Count, TempGuidList);
FreePool (TempGuidList);
return EFI_SUCCESS;
}
//
// Form IfrParse.c
//
EFI_STATUS
InitializeRequestElement (
IN OUT FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_STATEMENT *Question,
IN OUT FORM_BROWSER_FORM *Form
);
FORM_BROWSER_STATEMENT *
CreateQuestion (
IN UINT8 *OpCodeData,
IN OUT FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_FORM *Form
);
STATIC
FORM_BROWSER_STATEMENT *
CreateGotoFormSetQuestion (
IN CONST EFI_HII_HANDLE RefHiiHandle,
IN CONST EFI_GUID *RefFormsetGuid,
IN CONST EFI_FORM_ID RefFormId,
IN OUT FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_FORM *Form,
IN OUT UINT8 *OpCodeData
)
{
EFI_STATUS Status;
EFI_GUID FormsetGuid;
EFI_STRING_ID FormSetTitleStrId;
EFI_STRING_ID FormSetHelpStrId;
EFI_STRING_ID Prompt;
EFI_STRING_ID Help;
EFI_STRING_ID DevicePath;
EFI_FORM_ID EntryFormId;
CHAR16 *String;
EFI_IFR_REF4 *GotoFormSetOp;
FORM_BROWSER_STATEMENT *Statement;
EFI_HII_VALUE *Value;
if (RefHiiHandle == 0 || RefFormsetGuid == NULL || FormSet == NULL || Form == NULL || OpCodeData == NULL) {
return NULL;
}
CopyMem (&FormsetGuid, RefFormsetGuid, sizeof (EFI_GUID));
GetFormSetInfo (RefHiiHandle, &FormsetGuid, &FormSetTitleStrId, &FormSetHelpStrId, &EntryFormId);
if (RefFormId != 0) {
EntryFormId = RefFormId;
} else {
Status = GetFirstFormId (RefHiiHandle, RefFormsetGuid, &EntryFormId);
if (EFI_ERROR (Status)) {
return NULL;
}
}
String = HiiGetString (RefHiiHandle, FormSetTitleStrId, NULL);
if (String != NULL) {
Prompt = NewString (String, FormSet->HiiHandle);
FreePool (String);
} else {
Prompt = 0;
}
String = HiiGetString (RefHiiHandle, FormSetHelpStrId, NULL);
if (String != NULL) {
Help = NewString (String, FormSet->HiiHandle);
FreePool (String);
} else {
Help = 0;
}
Status = GetDevicePathStrByHiiHandle (RefHiiHandle, &String);
if (!EFI_ERROR (Status)) {
DevicePath = NewString (String, FormSet->HiiHandle);
FreePool (String);
} else {
DevicePath = 0;
}
GotoFormSetOp = (EFI_IFR_REF4 *)OpCodeData;
GotoFormSetOp->Header.OpCode = EFI_IFR_REF_OP;
GotoFormSetOp->Header.Length = sizeof (EFI_IFR_REF4);
GotoFormSetOp->Question.Header.Prompt = Prompt;
GotoFormSetOp->Question.Header.Help = Help;
GotoFormSetOp->Question.QuestionId = H2O_QUESTION_ID_INVALID;
GotoFormSetOp->Question.VarStoreId = 0;
GotoFormSetOp->Question.VarStoreInfo.VarOffset = 0;
GotoFormSetOp->Question.Flags = 0;
GotoFormSetOp->FormId = EntryFormId;
GotoFormSetOp->QuestionId = 0;
GotoFormSetOp->DevicePath = DevicePath;
CopyMem (&GotoFormSetOp->FormSetId, &FormsetGuid, sizeof (EFI_GUID));
Statement = CreateQuestion (OpCodeData, FormSet, Form);
if (Statement == NULL) {
return NULL;
}
Value = &Statement->HiiValue;
Value->Type = EFI_IFR_TYPE_REF;
CopyMem (&Value->Value.ref.FormId , &GotoFormSetOp->FormId , sizeof (EFI_FORM_ID));
CopyMem (&Value->Value.ref.QuestionId , &GotoFormSetOp->QuestionId, sizeof (EFI_QUESTION_ID));
CopyMem (&Value->Value.ref.FormSetGuid, &GotoFormSetOp->FormSetId , sizeof (EFI_GUID));
CopyMem (&Value->Value.ref.DevicePath , &GotoFormSetOp->DevicePath, sizeof (EFI_STRING_ID));
Statement->StorageWidth = (UINT16) sizeof (EFI_HII_REF);
InitializeRequestElement (FormSet, Statement, Form);
return Statement;
}
/**
Free resources of a link Statement.
@param[in] FormSet Pointer of the FormSet
**/
VOID
DestroyLinkStatements (
IN OUT FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
LINK_STATEMENT_NODE *LinkStatementNode;
if (FormSet == NULL || FormSet->LinkStatementListHead.ForwardLink == NULL) {
return;
}
while (!IsListEmpty (&FormSet->LinkStatementListHead)) {
Link = GetFirstNode (&FormSet->LinkStatementListHead);
LinkStatementNode = LINK_STATEMENT_NODE_FROM_LINK (Link);
if (LinkStatementNode->Statement->Prompt != 0) {
DeleteString (LinkStatementNode->Statement->Prompt, FormSet->HiiHandle);
}
if (LinkStatementNode->Statement->Help!= 0) {
DeleteString (LinkStatementNode->Statement->Help, FormSet->HiiHandle);
}
if (LinkStatementNode->Statement->HiiValue.Value.ref.DevicePath != 0) {
DeleteString (LinkStatementNode->Statement->HiiValue.Value.ref.DevicePath, FormSet->HiiHandle);
}
RemoveEntryList (&LinkStatementNode->Link);
FreePool (LinkStatementNode);
}
}
//
// Form OemSvcUpdateLinkFormSetIds.c
//
EFI_STATUS
OemSvcUpdateLinkFormSetIds (
IN CONST EFI_GUID *FormsetGuid,
IN OUT UINT32 *FormsetCount,
IN OUT EFI_HII_HANDLE **HiiHandleList,
IN OUT EFI_GUID **FormsetGuidList,
IN OUT UINT32 **EntryFormIdList OPTIONAL
);
BOOLEAN
ChkInHiiHandleList (
IN EFI_HII_HANDLE HiiHandle
)
{
UINT32 FBHiiHandleIndex;
for (FBHiiHandleIndex = 0; FBHiiHandleIndex < mFBPrivate.HiiHandleCount; FBHiiHandleIndex ++) {
if (mFBPrivate.HiiHandleList[FBHiiHandleIndex] == HiiHandle) {
return TRUE;
}
}
return FALSE;
}
STATIC
BOOLEAN
ChkInNeedAddHiiHandleList (
IN OUT EFI_HII_HANDLE HiiHandle
)
{
LIST_ENTRY *Link;
HII_HANDLE_ENTRY *HiiHandleEntry;
Link = GetFirstNode (&mFBPrivate.NeedAddHiiHandleList);
while (!IsNull (&mFBPrivate.NeedAddHiiHandleList, Link)) {
HiiHandleEntry = (HII_HANDLE_ENTRY *) Link;
Link = GetNextNode (&mFBPrivate.NeedAddHiiHandleList, Link);
if (HiiHandleEntry->HiiHandle == HiiHandle) {
return TRUE;
}
}
return FALSE;
}
EFI_STATUS
InsertHiiHandle (
IN EFI_HII_HANDLE HiiHandle
)
{
EFI_HII_HANDLE *NewHiiHandleList;
if (HiiHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Update HiiHandleList
//
NewHiiHandleList = AllocateZeroPool ((mFBPrivate.HiiHandleCount + 1) * sizeof (EFI_HII_HANDLE));
if (NewHiiHandleList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (NewHiiHandleList, mFBPrivate.HiiHandleList, mFBPrivate.HiiHandleCount * sizeof (EFI_HII_HANDLE));
NewHiiHandleList[mFBPrivate.HiiHandleCount] = HiiHandle;
if (mFBPrivate.HiiHandleList != NULL) {
FreePool (mFBPrivate.HiiHandleList);
}
mFBPrivate.HiiHandleList = NewHiiHandleList;
mFBPrivate.HiiHandleCount++;
return EFI_SUCCESS;
}
EFI_STATUS
RemoveHiiHandle (
IN EFI_HII_HANDLE HiiHandle
)
{
UINT32 Index;
LIST_ENTRY *Link;
FORM_BROWSER_FORMSET *FormSet;
if (HiiHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
Link = GetFirstNode (&mFBPrivate.FormSetList);
while (!IsNull (&mFBPrivate.FormSetList, Link)) {
FormSet = FORM_BROWSER_FORMSET_FROM_DISPLAY_LINK (Link);
Link = GetNextNode (&mFBPrivate.FormSetList, Link);
if (FormSet->HiiHandle == HiiHandle) {
return EFI_ABORTED;
}
}
for (Index = 0; Index < mFBPrivate.HiiHandleCount; Index++) {
if (mFBPrivate.HiiHandleList[Index] == HiiHandle) {
CopyMem (
&mFBPrivate.HiiHandleList[Index],
&mFBPrivate.HiiHandleList[Index + 1],
sizeof (EFI_HII_HANDLE) * (mFBPrivate.HiiHandleCount - Index - 1)
);
mFBPrivate.HiiHandleCount--;
if (mFBPrivate.HiiHandleCount == 0) {
FreePool (mFBPrivate.HiiHandleList);
mFBPrivate.HiiHandleList = NULL;
}
break;
}
}
return EFI_SUCCESS;
}
EFI_STATUS
InsertNeedAddHiiHandle (
IN OUT EFI_HII_HANDLE HiiHandle
)
{
HII_HANDLE_ENTRY *HiiHandleEntry;
if (HiiHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
HiiHandleEntry = AllocateZeroPool (sizeof (HII_HANDLE_ENTRY));
if (HiiHandleEntry == NULL) {
return EFI_OUT_OF_RESOURCES;
}
HiiHandleEntry->HiiHandle = HiiHandle;
InsertTailList (&mFBPrivate.NeedAddHiiHandleList, &HiiHandleEntry->Link);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
EnsureAllFormsetsInFB (
IN OUT UINT32 FormsetCount,
IN OUT EFI_HII_HANDLE *HiiHandleList
)
{
UINT32 Index;
EFI_HII_HANDLE HiiHandle;
if (FormsetCount == 0 || HiiHandleList == NULL) {
return EFI_INVALID_PARAMETER;
}
for (Index = 0; Index < FormsetCount; Index++) {
HiiHandle = HiiHandleList[Index];
if (!ChkInHiiHandleList (HiiHandle) &&
!ChkInNeedAddHiiHandleList (HiiHandle)) {
InsertHiiHandle (HiiHandle);
InsertNeedAddHiiHandle (HiiHandle);
}
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
GetAllFormsets (
IN LINK_DATA *LinkData,
IN FORM_BROWSER_FORMSET *FormSet,
OUT UINT32 *FormsetCount,
OUT EFI_HII_HANDLE **HiiHandleList,
OUT EFI_GUID **FormsetGuidList
)
{
EFI_STATUS Status;
UINT32 IncludeCount;
UINT32 ExcludeCount;
EFI_GUID *IncludeList;
EFI_GUID *ExcludeList;
EFI_GUID *TempIncludeList;
if (LinkData == NULL || FormSet == NULL) {
return EFI_INVALID_PARAMETER;
}
IncludeCount = LinkData->CurrentIncludeItemCount;
ExcludeCount = LinkData->CurrentExcludeItemCount;
if (IncludeCount == 0) {
//
// Empty include guid of link
//
// 1. Get formset guids from pcd
//
GetIncludeByPcd (&FormSet->Guid, &IncludeCount, &IncludeList);
//
// 2. Add this formset guid into include guid
//
TempIncludeList = AllocateZeroPool (sizeof (EFI_GUID) * (IncludeCount + 1));
if (TempIncludeList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (IncludeCount != 0) {
CopyMem (TempIncludeList, IncludeList, sizeof (EFI_GUID) * IncludeCount);
FreePool (IncludeList);
}
IncludeList = TempIncludeList;
CopyGuid (&IncludeList[IncludeCount], &FormSet->Guid);
IncludeCount ++;
} else {
IncludeList = LinkData->IncludeGuidArray;
}
ExcludeList = LinkData->ExcludeGuidArray;
Status = GetFormsetsByLink (
&FormSet->Guid,
IncludeCount,
ExcludeCount,
IncludeList,
ExcludeList,
FormsetCount,
HiiHandleList,
FormsetGuidList
);
if (EFI_ERROR (Status)) {
return Status;
}
if (IncludeList != NULL) {
FreePool (IncludeList);
}
if (ExcludeList != NULL) {
FreePool (ExcludeList);
}
return EFI_SUCCESS;
}
EFI_STATUS
ParseLinkOpCodeInsertGuid (
IN UINT16 Function,
IN EFI_GUID *Guid,
IN OUT LINK_DATA *LinkData
)
{
UINT32 *ItemCount;
EFI_GUID **GuidArray;
EFI_GUID *TempGuidArray;
if (Function == H2O_IFR_EXT_INCLUDE_FORM_SET) {
ItemCount = &LinkData->CurrentIncludeItemCount;
GuidArray = &LinkData->IncludeGuidArray;
} else {
ItemCount = &LinkData->CurrentExcludeItemCount;
GuidArray = &LinkData->ExcludeGuidArray;
}
TempGuidArray = AllocateZeroPool (sizeof (EFI_GUID) * ((*ItemCount) + 1));
if (TempGuidArray == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (TempGuidArray + (*ItemCount), Guid, sizeof (EFI_GUID));
if ((*ItemCount) != 0) {
CopyMem (TempGuidArray, (*GuidArray), sizeof (EFI_GUID) * (*ItemCount));
FreePool (*GuidArray);
}
*GuidArray = TempGuidArray;
(*ItemCount) ++;
return EFI_SUCCESS;
}
EFI_STATUS
ParseLinkOpCodeEnd (
IN LINK_DATA *LinkData,
IN OUT FORM_BROWSER_FORMSET *FormSet,
IN OUT FORM_BROWSER_FORM *Form
)
{
EFI_STATUS Status;
UINT32 FormsetCount;
EFI_HII_HANDLE *HiiHandleList;
EFI_GUID *FormsetGuidList;
EFI_FORM_ID *EntryFormIdList;
UINT32 *FormIdList;
UINT32 Index;
LINK_STATEMENT_NODE *LinkStatementNode;
LIST_ENTRY *Link;
EFI_STATUS OemSvcStatus;
if (LinkData == NULL || FormSet == NULL) {
return EFI_INVALID_PARAMETER;
}
if (Form == NULL) {
//
// compatiable link opcode in formset
//
Link = GetFirstNode (&FormSet->FormListHead);
Form = FORM_BROWSER_FORM_FROM_LINK (Link);
}
Status = GetAllFormsets (
LinkData,
FormSet,
&FormsetCount,
&HiiHandleList,
&FormsetGuidList
);
if (EFI_ERROR (Status)) {
return Status;
}
if (FormsetCount != 0) {
Status = GetAllFirstFormId (FormsetCount, HiiHandleList, FormsetGuidList, &EntryFormIdList);
if (EFI_ERROR (Status)) {
return Status;
}
FormIdList = (UINT32 *)(VOID *)EntryFormIdList;
} else {
FormIdList = NULL;
}
//
// Oem update formset list
//
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices Call: OemSvcUpdateLinkFormSetIds \n"));
OemSvcStatus = OemSvcUpdateLinkFormSetIds (&FormSet->Guid, &FormsetCount, &HiiHandleList, &FormsetGuidList, &FormIdList);
DEBUG_OEM_SVC ((DEBUG_INFO, "OemKernelServices OemSvcUpdateLinkFormSetIds Status: %r\n", OemSvcStatus));
if (FormsetCount == 0 || HiiHandleList == NULL || FormsetGuidList == NULL) {
return EFI_NOT_FOUND;
}
Status = EnsureAllFormsetsInFB (FormsetCount, HiiHandleList);
if (EFI_ERROR (Status)) {
return Status;
}
if (FormIdList == NULL) {
EntryFormIdList = (EFI_FORM_ID *)AllocateZeroPool (sizeof (EFI_FORM_ID) * FormsetCount);
if (EntryFormIdList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
} else {
EntryFormIdList = (EFI_FORM_ID *)(VOID *)FormIdList;
}
//
// Add REF4 questions in this formset's root form
//
for (Index = 0; Index < FormsetCount; Index ++) {
LinkStatementNode = (LINK_STATEMENT_NODE *)AllocateZeroPool (sizeof (LINK_STATEMENT_NODE));
if (LinkStatementNode == NULL) {
return EFI_OUT_OF_RESOURCES;
}
LinkStatementNode->Statement = CreateGotoFormSetQuestion (
HiiHandleList[Index],
&FormsetGuidList[Index],
EntryFormIdList[Index],
FormSet,
Form,
(UINT8 *)&LinkStatementNode->Ref4Opcode
);
if (LinkStatementNode->Statement != NULL) {
InsertTailList (&FormSet->LinkStatementListHead, &LinkStatementNode->Link);
} else {
FreePool (LinkStatementNode);
}
}
FreePool (HiiHandleList);
FreePool (FormsetGuidList);
FreePool (EntryFormIdList);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
SetUsedQuestionId (
IN UINT8 *UsedQuestionIdMap,
IN EFI_QUESTION_ID QuestionId
)
{
if (UsedQuestionIdMap == NULL || QuestionId == H2O_QUESTION_ID_INVALID) {
return EFI_INVALID_PARAMETER;
}
if (!IS_MASK(UsedQuestionIdMap, QuestionId)) {
SET_MASK (UsedQuestionIdMap, QuestionId);
return EFI_SUCCESS;
}
//
// QuestionId Redefined
//
ASSERT (TRUE);
return EFI_INVALID_PARAMETER;
}
STATIC
EFI_STATUS
SetUsedQuestionIdInForm (
IN UINT8 *UsedQuestionIdMap,
IN CONST FORM_BROWSER_FORM *Form
)
{
LIST_ENTRY *Link;
FORM_BROWSER_STATEMENT *CurrentStatement;
if (Form == NULL) {
return EFI_INVALID_PARAMETER;
}
Link = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, Link)) {
CurrentStatement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
Link = GetNextNode (&Form->StatementListHead, Link);
SetUsedQuestionId (UsedQuestionIdMap, CurrentStatement->QuestionId);
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
SetUsedQuestionIdInFormset (
IN UINT8 *UsedQuestionIdMap,
IN CONST FORM_BROWSER_FORMSET *Formset
)
{
LIST_ENTRY *Link;
FORM_BROWSER_FORM *CurrentForm;
if (Formset == NULL) {
return EFI_INVALID_PARAMETER;
}
Link = GetFirstNode (&Formset->FormListHead);
while (!IsNull (&Formset->FormListHead, Link)) {
CurrentForm = FORM_BROWSER_FORM_FROM_LINK (Link);
Link = GetNextNode (&Formset->FormListHead, Link);
SetUsedQuestionIdInForm (UsedQuestionIdMap, CurrentForm);
}
return EFI_SUCCESS;
}
STATIC
EFI_QUESTION_ID
GetUnusedQuestionId (
IN UINT8 *UsedQuestionIdMap
)
{
EFI_QUESTION_ID QuestionId;
if (UsedQuestionIdMap == NULL) {
return H2O_QUESTION_ID_INVALID;
}
for (QuestionId = 1; QuestionId < H2O_QUESTION_ID_MAX; QuestionId++) {
if (!IS_MASK(UsedQuestionIdMap, QuestionId)) {
SET_MASK (UsedQuestionIdMap, QuestionId);
return QuestionId;
}
}
return H2O_QUESTION_ID_INVALID;
}
EFI_STATUS
SetAllQuestionIdValid (
IN FORM_BROWSER_FORMSET *FormSet
)
{
LIST_ENTRY *Link;
LINK_STATEMENT_NODE *LinkStatementNode;
UINT8 *UsedQuestionIdMap;
if (FormSet == NULL) {
return EFI_INVALID_PARAMETER;
}
UsedQuestionIdMap = (UINT8 *)AllocateZeroPool (H2O_QUESTION_ID_MAX / 8);
if (UsedQuestionIdMap == NULL) {
return EFI_OUT_OF_RESOURCES;
}
SetUsedQuestionIdInFormset (UsedQuestionIdMap, FormSet);
Link = GetFirstNode (&FormSet->LinkStatementListHead);
while (!IsNull (&FormSet->LinkStatementListHead, Link)) {
LinkStatementNode = LINK_STATEMENT_NODE_FROM_LINK (Link);
Link = GetNextNode (&FormSet->LinkStatementListHead, Link);
LinkStatementNode->Statement->QuestionId = GetUnusedQuestionId (UsedQuestionIdMap);
}
FreePool (UsedQuestionIdMap);
return EFI_SUCCESS;
}