1392 lines
40 KiB
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;
|
|
}
|
|
|