alder_lake_bios/Insyde/InsydeSetupPkg/Library/LayoutSupportLib/Layout.c

1403 lines
47 KiB
C

/** @file
;******************************************************************************
;* Copyright (c) 2013 - 2020, 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 "LayoutSupportLib.h"
STATIC
UINT32
InitLayoutRevision (
IN UINT8 *BlockDataBuffer,
IN UINT32 BlockDataBufferLength,
IN UINT32 CurrentBlockOffset
)
{
UINT32 BlockOffset;
UINT8 *BlockData;
UINT8 BlockType;
UINT8 BlockSize;
CHAR8 *IdentifierStr;
UINT32 ValueType;
if (BlockDataBuffer == NULL || BlockDataBufferLength == 0 || CurrentBlockOffset == 0) {
return LAYOUT_REVISION_UNKNOWN;
}
//
// Parse each layout block
//
BlockOffset = CurrentBlockOffset;
while (BlockOffset < BlockDataBufferLength) {
BlockData = BlockDataBuffer + BlockOffset;
BlockType = ((H2O_HII_LAYOUT_BLOCK *) BlockData)->BlockType;
BlockSize = ((H2O_HII_LAYOUT_BLOCK *) BlockData)->BlockSize;
if (BlockSize == 0) {
break;
}
BlockOffset += BlockSize;
switch (BlockType) {
case H2O_HII_LIBT_LAYOUT_BEGIN:
case H2O_HII_LIBT_LAYOUT_END:
case H2O_HII_LIBT_LAYOUT_DUP:
return LAYOUT_REVISION_2;
case H2O_HII_LIBT_PROPERTY:
IdentifierStr = (CHAR8 *)BlockData + ((H2O_HII_LIBT_PROPERTY_BLOCK *)BlockData)->IdentifierOffset;
ValueType = ((H2O_HII_LIBT_PROPERTY_BLOCK *)BlockData)->ValueType;
if ((AsciiStrCmp (IdentifierStr, "layout") == 0) ||
(AsciiStrCmp (IdentifierStr, "foreground-color") == 0) ||
(AsciiStrCmp (IdentifierStr, "visibility") == 0 && ValueType == H2O_PROPERTY_VALUE_TYPE_BOOLEAN)) {
return LAYOUT_REVISION_1;
}
break;
default:
break;
}
}
return LAYOUT_REVISION_2;
}
STATIC
UINT32
ParsePseudoClass (
IN CONST CHAR8 *PseudoClassStr
)
{
if (AsciiStrCmp (PseudoClassStr, ":selectable") == 0) {
return H2O_STYLE_PSEUDO_CLASS_SELECTABLE;
} else if (AsciiStrCmp (PseudoClassStr, ":grayout") == 0) {
return H2O_STYLE_PSEUDO_CLASS_GRAYOUT;
} else if (AsciiStrCmp (PseudoClassStr, ":highlight") == 0) {
return H2O_STYLE_PSEUDO_CLASS_HIGHLIGHT;
} else if (AsciiStrCmp (PseudoClassStr, ":link") == 0) {
return H2O_STYLE_PSEUDO_CLASS_LINK;
} else if (AsciiStrCmp (PseudoClassStr, ":visited") == 0) {
return H2O_STYLE_PSEUDO_CLASS_VISITED;
} else if (AsciiStrCmp (PseudoClassStr, ":hover") == 0) {
return H2O_STYLE_PSEUDO_CLASS_HOVER;
} else if (AsciiStrCmp (PseudoClassStr, ":focus") == 0) {
return H2O_STYLE_PSEUDO_CLASS_FOCUS;
} else if (AsciiStrCmp (PseudoClassStr, ":active") == 0) {
return H2O_STYLE_PSEUDO_CLASS_ACTIVE;
} else if (AsciiStrCmp (PseudoClassStr, ":enabled") == 0) {
return H2O_STYLE_PSEUDO_CLASS_ENABLED;
} else if (AsciiStrCmp (PseudoClassStr, ":disabled") == 0) {
return H2O_STYLE_PSEUDO_CLASS_DISABLED;
} else if (AsciiStrCmp (PseudoClassStr, ":not") == 0) {
return H2O_STYLE_PSEUDO_CLASS_NOT;
} else if (AsciiStrCmp (PseudoClassStr, ":help") == 0) {
return H2O_STYLE_PSEUDO_CLASS_HELP;
} else {
//
// default
//
return H2O_STYLE_PSEUDO_CLASS_NORMAL;
}
}
STATIC
VOID
CountLayoutOpCodes (
IN UINT8 *BlockDataBuffer,
IN UINT32 BlockDataBufferLength,
OUT UINT32 *NumberOfPanel,
OUT UINT32 *NumberOfStyle,
OUT UINT32 *NumberOfProperty,
OUT UINT32 *NumberOfHotKey
)
{
UINT32 BlockOffset;
UINT8 *BlockData;
UINT8 BlockType;
UINT8 BlockSize;
UINT32 PanelNum;
UINT32 StyleNum;
UINT32 PropertyNum;
UINT32 HotKeyNum;
PanelNum = 0;
StyleNum = 0;
PropertyNum = 0;
HotKeyNum = 0;
BlockOffset = 0;
while (BlockOffset < BlockDataBufferLength) {
BlockData = BlockDataBuffer + BlockOffset;
BlockType = ((H2O_HII_LAYOUT_BLOCK *) BlockData)->BlockType;
BlockSize = ((H2O_HII_LAYOUT_BLOCK *) BlockData)->BlockSize;
if (BlockSize == 0) {
break;
}
BlockOffset += BlockSize;
switch (BlockType) {
case H2O_HII_LIBT_PANEL_BEGIN:
PanelNum++;
break;
case H2O_HII_LIBT_STYLE_BEGIN:
StyleNum++;
break;
case H2O_HII_LIBT_PROPERTY:
StyleNum++;
PropertyNum++;
break;
case H2O_HII_LIBT_EXT_HOTKEY:
HotKeyNum++;
break;
}
}
*NumberOfPanel = PanelNum;
*NumberOfStyle = StyleNum;
*NumberOfProperty = PropertyNum;
*NumberOfHotKey = HotKeyNum;
}
STATIC
EFI_STATUS
ParseLayoutPkg (
IN UINT8 *PkgBuffer,
OUT LIST_ENTRY **LayoutListHead,
OUT LIST_ENTRY **VfrListHead
)
{
EFI_STATUS Status;
H2O_LAYOUT_PACKAGE_HDR *CurrentLayoutPkg;
H2O_LAYOUT_INFO *CurrentLayout;
H2O_PANEL_INFO *CurrentPanel;
H2O_STYLE_INFO *CurrentStyle;
H2O_PROPERTY_INFO *CurrentProperty;
H2O_VFR_INFO *CurrentVfr;
H2O_FORMSET_INFO *CurrentFormset;
H2O_FORM_INFO *CurrentForm;
H2O_HOTKEY_INFO *CurrentHotkey;
H2O_IMPORT_INFO *CurrentImport;
H2O_TARGET_INFO *CurrentTargetInfo;
H2O_STATEMENT_INFO *CurrentStatement;
H2O_EXPRESSION_INFO *CurrentExpression;
H2O_EXPRESSION_QID_MAP_INFO *CurrentExpressionQidMap;
UINT8 *BlockDataBuffer;
UINT32 BlockDataBufferLength;
UINT8 *BlockData;
UINT8 BlockType;
UINT8 BlockSize;
UINT32 BlockOffset;
UINTN ExpressionSize;
H2O_LAYOUT_ID OldLayoutId;
H2O_PANEL_ID OldPanelId;
LIST_ENTRY *Link;
LIST_ENTRY *LinkList;
H2O_LAYOUT_INFO *TempLayout;
H2O_PANEL_INFO *TempPanel;
H2O_STYLE_INFO *TempStyle;
H2O_STYLE_INFO NewStyleInfo;
H2O_PROPERTY_INFO NewProperty;
H2O_PROPERTY_INFO *TempProperty;
H2O_HII_LIBT_EXT_IMPORT_BLOCK *ImportBlock;
H2O_HII_LIBT_IMPORT_TARGET_BEGIN_BLOCK *ImportTargetBlock;
H2O_HII_LIBT_LINK_TARGET_BEGIN_BLOCK *LinkTargetBlock;
H2O_HII_LIBT_LAYOUT_BEGIN_BLOCK *LayoutBeginBlock;
H2O_HII_LIBT_EXT_STATEMENT_BLOCK *StatementBlock;
UINT32 PanelIndex;
UINT32 PanelCount;
H2O_PANEL_INFO *PanelBuffer;
UINT32 StyleIndex;
UINT32 StyleCount;
H2O_STYLE_INFO *StyleBuffer;
UINT32 PropertyIndex;
UINT32 PropertyCount;
H2O_PROPERTY_INFO *PropertyBuffer;
UINT32 HotKeyIndex;
UINT32 HotKeyCount;
H2O_HOTKEY_INFO *HotKeyBuffer;
if (PkgBuffer == NULL || LayoutListHead == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = EFI_SUCCESS;
CurrentLayoutPkg = NULL;
CurrentLayout = NULL;
CurrentPanel = NULL;
CurrentStyle = NULL;
CurrentProperty = NULL;
CurrentVfr = NULL;
CurrentFormset = NULL;
CurrentForm = NULL;
CurrentHotkey = NULL;
CurrentStatement = NULL;
CurrentTargetInfo = NULL;
TempLayout = NULL;
TempPanel = NULL;
//
// Layout Pkg
//
CurrentLayoutPkg = (H2O_LAYOUT_PACKAGE_HDR *) (PkgBuffer + sizeof(UINT32));
if (CurrentLayoutPkg->Header.Type != H2O_HII_PACKAGE_LAYOUTS) {
return EFI_INVALID_PARAMETER;
}
//
// Block Data Buffer
//
BlockDataBuffer = (UINT8 *)(CurrentLayoutPkg + 1);
BlockDataBufferLength = CurrentLayoutPkg->Header.Length - CurrentLayoutPkg->HdrSize;
CountLayoutOpCodes (BlockDataBuffer, BlockDataBufferLength, &PanelCount, &StyleCount, &PropertyCount, &HotKeyCount);
PanelBuffer = AllocateZeroPool (sizeof (H2O_PANEL_INFO) * PanelCount);
StyleBuffer = AllocateZeroPool (sizeof (H2O_STYLE_INFO) * StyleCount);
PropertyBuffer = AllocateZeroPool (sizeof (H2O_PROPERTY_INFO) * PropertyCount);
HotKeyBuffer = AllocateZeroPool (sizeof (H2O_HOTKEY_INFO) * HotKeyCount);
if ((PanelBuffer == NULL && PanelCount != 0) ||
(StyleBuffer == NULL && StyleCount != 0) ||
(PropertyBuffer == NULL && PropertyCount != 0) ||
(HotKeyBuffer == NULL && HotKeyCount != 0)) {
return EFI_OUT_OF_RESOURCES;
}
PanelIndex = 0;
StyleIndex = 0;
PropertyIndex = 0;
HotKeyIndex = 0;
//
// Init Layout List
//
*LayoutListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
if (*LayoutListHead == NULL) {
return EFI_OUT_OF_RESOURCES;
}
InitializeListHead (*LayoutListHead);
//
// Init Vfr List
//
*VfrListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
if (*VfrListHead == NULL) {
return EFI_OUT_OF_RESOURCES;
}
InitializeListHead (*VfrListHead);
//
// Parse each layout block
//
BlockOffset = 0;
while (BlockOffset < BlockDataBufferLength) {
BlockData = BlockDataBuffer + BlockOffset;
BlockType = ((H2O_HII_LAYOUT_BLOCK *) BlockData)->BlockType;
BlockSize = ((H2O_HII_LAYOUT_BLOCK *) BlockData)->BlockSize;
if (BlockSize == 0) {
break;
}
BlockOffset += BlockSize;
switch (BlockType) {
case H2O_HII_LIBT_LAYOUT_BEGIN:
LayoutBeginBlock = (H2O_HII_LIBT_LAYOUT_BEGIN_BLOCK *)BlockData;
LinkList = *LayoutListHead;
for (Link = GetFirstNode (LinkList), CurrentLayout = NULL; !IsNull (LinkList, Link); Link = GetNextNode (LinkList, Link)) {
TempLayout = H2O_LAYOUT_INFO_NODE_FROM_LINK (Link);
if (TempLayout->LayoutId == LayoutBeginBlock->LayoutId &&
CompareGuid (&TempLayout->DisplayEngineGuid[0], &LayoutBeginBlock->DisplayEngineGuid[0]) &&
CompareGuid (&TempLayout->DisplayEngineGuid[1], &LayoutBeginBlock->DisplayEngineGuid[1]) &&
CompareGuid (&TempLayout->DisplayEngineGuid[2], &LayoutBeginBlock->DisplayEngineGuid[2])) {
CurrentLayout = TempLayout;
break;
}
}
if (CurrentLayout != NULL) {
break;
}
CurrentLayout = AllocateZeroPool (sizeof (H2O_LAYOUT_INFO));
if (CurrentLayout == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CurrentLayout->Signature = H2O_LAYOUT_INFO_NODE_SIGNATURE;
CurrentLayout->LayoutId = LayoutBeginBlock->LayoutId;
CopyGuid (&CurrentLayout->DisplayEngineGuid[0], &LayoutBeginBlock->DisplayEngineGuid[0]);
CopyGuid (&CurrentLayout->DisplayEngineGuid[1], &LayoutBeginBlock->DisplayEngineGuid[1]);
CopyGuid (&CurrentLayout->DisplayEngineGuid[2], &LayoutBeginBlock->DisplayEngineGuid[2]);
CurrentLayout->Revision = InitLayoutRevision (BlockDataBuffer, BlockDataBufferLength, BlockOffset);
InitializeListHead (&CurrentLayout->PanelListHead);
InitializeListHead (&CurrentLayout->HotkeyListHead);
InitializeListHead (&CurrentLayout->StyleListHead);
InsertTailList (*LayoutListHead, &CurrentLayout->Link);
break;
case H2O_HII_LIBT_LAYOUT_END:
CurrentLayout = NULL;
CurrentPanel = NULL;
CurrentHotkey = NULL;
CurrentStyle = NULL;
break;
case H2O_HII_LIBT_PANEL_BEGIN:
if (CurrentLayout == NULL || PanelBuffer == NULL) {
ASSERT (FALSE);
CurrentPanel = NULL;
break;
}
LinkList = &CurrentLayout->PanelListHead;
for (Link = GetFirstNode (LinkList), CurrentPanel = NULL; !IsNull (LinkList, Link); Link = GetNextNode (LinkList, Link)) {
TempPanel = H2O_PANEL_INFO_NODE_FROM_LINK (Link);
if (TempPanel->PanelId == ((H2O_HII_LIBT_PANEL_BEGIN_BLOCK *)BlockData)->PanelId &&
TempPanel->PanelType == ((H2O_HII_LIBT_PANEL_BEGIN_BLOCK *)BlockData)->PanelType &&
CompareGuid (&TempPanel->PanelTypeGuid, &((H2O_HII_LIBT_PANEL_BEGIN_BLOCK *)BlockData)->PanelTypeGuid)) {
CurrentPanel = TempPanel;
break;
}
}
if (CurrentPanel != NULL) {
break;
}
CurrentPanel = &PanelBuffer[PanelIndex++];
CurrentPanel->Signature = H2O_PANEL_INFO_NODE_SIGNATURE;
CurrentPanel->PanelId = ((H2O_HII_LIBT_PANEL_BEGIN_BLOCK *)BlockData)->PanelId;
CurrentPanel->PanelType = ((H2O_HII_LIBT_PANEL_BEGIN_BLOCK *)BlockData)->PanelType;
CopyMem (&CurrentPanel->PanelTypeGuid, &((H2O_HII_LIBT_PANEL_BEGIN_BLOCK *)BlockData)->PanelTypeGuid, sizeof (EFI_GUID));
CopyMem (&CurrentPanel->TargetFormsetGuid, &((H2O_HII_LIBT_PANEL_BEGIN_BLOCK *)BlockData)->TargetFormsetGuid, sizeof (EFI_GUID));
CurrentPanel->TargetFormId = ((H2O_HII_LIBT_PANEL_BEGIN_BLOCK *)BlockData)->TargetFormId;
CurrentPanel->ParentLayout = CurrentLayout;
InitializeListHead (&CurrentPanel->StyleListHead);
InsertTailList (&CurrentLayout->PanelListHead, &CurrentPanel->Link);
break;
case H2O_HII_LIBT_PANEL_END:
CurrentPanel = NULL;
CurrentStyle = NULL;
break;
case H2O_HII_LIBT_STYLE_BEGIN:
if (CurrentHotkey != NULL) {
LinkList = &CurrentHotkey->StyleListHead;
} else if (CurrentStatement != NULL) {
LinkList = &CurrentStatement->StyleListHead;
} else if (CurrentTargetInfo != NULL) {
LinkList = &CurrentTargetInfo->StyleListHead;
} else if (CurrentForm != NULL) {
LinkList = &CurrentForm->StyleListHead;
} else if (CurrentFormset != NULL) {
LinkList = &CurrentFormset->StyleListHead;
} else if (CurrentPanel != NULL) {
LinkList = &CurrentPanel->StyleListHead;
} else if (CurrentLayout != NULL) {
LinkList = &CurrentLayout->StyleListHead;
} else {
LinkList = NULL;
}
if (LinkList == NULL || StyleBuffer == NULL) {
ASSERT (FALSE);
CurrentStyle = NULL;
break;
}
NewStyleInfo.StyleType = ((H2O_HII_LIBT_STYLE_BEGIN_BLOCK *)BlockData)->Type;
NewStyleInfo.ClassName = (CHAR8 *)BlockData + ((H2O_HII_LIBT_STYLE_BEGIN_BLOCK *)BlockData)->ClassNameOffset;
NewStyleInfo.PseudoClass = ParsePseudoClass ((CHAR8 *)BlockData + ((H2O_HII_LIBT_STYLE_BEGIN_BLOCK *)BlockData)->PseudoClassOffset);
for (Link = GetFirstNode (LinkList), CurrentStyle = NULL; !IsNull (LinkList, Link); Link = GetNextNode (LinkList, Link)) {
TempStyle = H2O_STYLE_INFO_NODE_FROM_LINK (Link);
if (TempStyle->StyleType == NewStyleInfo.StyleType &&
TempStyle->PseudoClass == NewStyleInfo.PseudoClass &&
AsciiStrCmp (TempStyle->ClassName, NewStyleInfo.ClassName) == 0) {
CurrentStyle = TempStyle;
break;
}
}
if (CurrentStyle != NULL) {
break;
}
CurrentStyle = &StyleBuffer[StyleIndex++];
CurrentStyle->Signature = H2O_STYLE_INFO_NODE_SIGNATURE;
CurrentStyle->StyleType = NewStyleInfo.StyleType;
CurrentStyle->ClassName = NewStyleInfo.ClassName;
CurrentStyle->PseudoClass = NewStyleInfo.PseudoClass;
InitializeListHead (&CurrentStyle->PropertyListHead);
InsertTailList (LinkList, &CurrentStyle->Link);
break;
case H2O_HII_LIBT_STYLE_END:
CurrentStyle = NULL;
break;
case H2O_HII_LIBT_PROPERTY:
if (PropertyBuffer == NULL) {
ASSERT (FALSE);
CurrentProperty = NULL;
break;
}
if (CurrentStyle == NULL) {
if (StyleBuffer == NULL) {
break;
}
NewStyleInfo.ClassName = NULL;
NewStyleInfo.PseudoClass = H2O_STYLE_PSEUDO_CLASS_NORMAL;
if (CurrentHotkey != NULL) {
LinkList = &CurrentHotkey->StyleListHead;
NewStyleInfo.StyleType = H2O_IFR_STYLE_TYPE_VFR_TREE_FLAG | H2O_IFR_STYLE_TYPE_HOTKEY;
} else if (CurrentStatement != NULL) {
LinkList = &CurrentStatement->StyleListHead;
NewStyleInfo.StyleType = H2O_IFR_STYLE_TYPE_VFR_TREE_FLAG;
} else if (CurrentTargetInfo != NULL) {
LinkList = &CurrentTargetInfo->StyleListHead;
NewStyleInfo.StyleType = H2O_IFR_STYLE_TYPE_VFR_TREE_FLAG;
} else if (CurrentForm != NULL) {
LinkList = &CurrentForm->StyleListHead;
NewStyleInfo.StyleType = H2O_IFR_STYLE_TYPE_VFR_TREE_FLAG | H2O_IFR_STYLE_TYPE_FORM;
} else if (CurrentFormset != NULL) {
LinkList = &CurrentFormset->StyleListHead;
NewStyleInfo.StyleType = H2O_IFR_STYLE_TYPE_VFR_TREE_FLAG | H2O_IFR_STYLE_TYPE_FORMSET;
} else if (CurrentPanel != NULL) {
LinkList = &CurrentPanel->StyleListHead;
NewStyleInfo.StyleType = H2O_IFR_STYLE_TYPE_PANEL;
} else if (CurrentLayout != NULL) {
LinkList = &CurrentLayout->StyleListHead;
NewStyleInfo.StyleType = H2O_IFR_STYLE_TYPE_LAYOUT;
} else {
ASSERT (FALSE);
CurrentProperty = NULL;
break;
}
for (Link = GetFirstNode (LinkList); !IsNull (LinkList, Link); Link = GetNextNode (LinkList, Link)) {
TempStyle = H2O_STYLE_INFO_NODE_FROM_LINK (Link);
if (TempStyle->StyleType == NewStyleInfo.StyleType &&
TempStyle->PseudoClass == NewStyleInfo.PseudoClass &&
TempStyle->ClassName == NewStyleInfo.ClassName) {
CurrentStyle = TempStyle;
break;
}
}
if (CurrentStyle == NULL) {
CurrentStyle = &StyleBuffer[StyleIndex++];
CurrentStyle->Signature = H2O_STYLE_INFO_NODE_SIGNATURE;
CurrentStyle->StyleType = NewStyleInfo.StyleType;
CurrentStyle->ClassName = NewStyleInfo.ClassName;
CurrentStyle->PseudoClass = NewStyleInfo.PseudoClass;
InitializeListHead (&CurrentStyle->PropertyListHead);
InsertTailList (LinkList, &CurrentStyle->Link);
}
}
NewProperty.ValueType = ((H2O_HII_LIBT_PROPERTY_BLOCK *)BlockData)->ValueType;
NewProperty.IdentifierStr = (CHAR8 *)BlockData + ((H2O_HII_LIBT_PROPERTY_BLOCK *)BlockData)->IdentifierOffset;
NewProperty.IdentifierStrSize = (UINT32) AsciiStrSize (NewProperty.IdentifierStr);
CurrentProperty = NULL;
LinkList = &CurrentStyle->PropertyListHead;
for (Link = GetFirstNode (LinkList), CurrentProperty = NULL; !IsNull (LinkList, Link); Link = GetNextNode (LinkList, Link)) {
TempProperty = H2O_PROPERTY_INFO_NODE_FROM_LINK (Link);
if (TempProperty->IdentifierStrSize == NewProperty.IdentifierStrSize &&
TempProperty->ValueType == NewProperty.ValueType &&
AsciiStrCmp (TempProperty->IdentifierStr, NewProperty.IdentifierStr) == 0) {
CurrentProperty = TempProperty;
break;
}
}
if (CurrentProperty == NULL) {
CurrentProperty = &PropertyBuffer[PropertyIndex++];
CurrentProperty->Signature = H2O_PROPERTY_INFO_NODE_SIGNATURE;
CurrentProperty->ValueType = NewProperty.ValueType;
CurrentProperty->IdentifierStr = NewProperty.IdentifierStr;
CurrentProperty->IdentifierStrSize = NewProperty.IdentifierStrSize;
InsertTailList (&CurrentStyle->PropertyListHead, &CurrentProperty->Link);
CurrentStyle->PropertyCount++;
}
CopyMem (&CurrentProperty->H2OValue, &((H2O_HII_LIBT_PROPERTY_BLOCK *)BlockData)->H2OValue, sizeof (H2O_VALUE));
CurrentProperty->ValueStr = (CHAR8 *)BlockData + ((H2O_HII_LIBT_PROPERTY_BLOCK *)BlockData)->ValueOffset;
break;
case H2O_HII_LIBT_LAYOUT_DUP:
OldLayoutId = ((H2O_HII_LIBT_LAYOUT_DUP_BLOCK *)BlockData)->OldLayoutId;
Link = *LayoutListHead;
Link = Link->ForwardLink;
do {
TempLayout = H2O_LAYOUT_INFO_NODE_FROM_LINK (Link);
if (OldLayoutId == TempLayout->LayoutId) {
CurrentLayout = AllocateCopyPool (sizeof (H2O_LAYOUT_INFO), TempLayout);
if (CurrentLayout == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// New LayoutId
//
CurrentLayout->LayoutId = ((H2O_HII_LIBT_LAYOUT_DUP_BLOCK *)BlockData)->LayoutId;
InitializeListHead (&CurrentLayout->PanelListHead);
InitializeListHead (&CurrentLayout->HotkeyListHead);
InsertTailList (*LayoutListHead, &CurrentLayout->Link);
break;
}
Link = Link->ForwardLink;
} while (IsNodeAtEnd (*LayoutListHead, Link));
break;
case H2O_HII_LIBT_PANEL_DUP:
if (CurrentLayout == NULL) {
ASSERT (FALSE);
CurrentPanel = NULL;
break;
}
OldLayoutId = ((H2O_HII_LIBT_PANEL_DUP_BLOCK *)BlockData)->OldLayoutId;
Link = *LayoutListHead;
Link = Link->ForwardLink;
do {
//
// Found OldLayoutId
//
TempLayout = H2O_LAYOUT_INFO_NODE_FROM_LINK (Link);
if (OldLayoutId == TempLayout->LayoutId) {
OldPanelId = ((H2O_HII_LIBT_PANEL_DUP_BLOCK *)BlockData)->OldPanelId;
Link = &TempLayout->PanelListHead;
Link = Link->ForwardLink;
do {
//
// Found OldPanelId
//
TempPanel = H2O_PANEL_INFO_NODE_FROM_LINK (Link);
if (OldPanelId == TempPanel->PanelId) {
CurrentPanel = AllocateCopyPool (sizeof (H2O_PANEL_INFO), TempPanel);
if (CurrentPanel == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// New PanelId
//
CurrentPanel->PanelId = ((H2O_HII_LIBT_PANEL_DUP_BLOCK *)BlockData)->PanelId;
ASSERT (CurrentLayout != NULL);
if (CurrentLayout != NULL) {
InsertTailList (&CurrentLayout->PanelListHead, &CurrentPanel->Link);
}
break;
}
Link = Link->ForwardLink;
} while (IsNodeAtEnd (&TempLayout->PanelListHead, Link));
break;
}
Link = Link->ForwardLink;
} while (IsNodeAtEnd (*LayoutListHead, Link));
break;
case H2O_HII_LIBT_EXT2:
break;
case H2O_HII_LIBT_EXT4:
break;
case H2O_HII_LIBT_EXT_VFR:
CurrentVfr = AllocateZeroPool (sizeof (H2O_VFR_INFO));
if (CurrentVfr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CurrentVfr->Signature = H2O_VFR_INFO_NODE_SIGNATURE;
CurrentVfr->VfrId = ((H2O_HII_LIBT_EXT_VFR_BLOCK *)BlockData)->VfrId;
InitializeListHead (&CurrentVfr->FormsetListHead);
InsertTailList (*VfrListHead, &CurrentVfr->Link);
break;
case H2O_HII_LIBT_EXT_VFR_END:
CurrentVfr = NULL;
CurrentFormset = NULL;
CurrentForm = NULL;
CurrentHotkey = NULL;
CurrentStyle = NULL;
break;
case H2O_HII_LIBT_EXT_FORMSET:
if (CurrentVfr == NULL) {
ASSERT (FALSE);
break;
}
CurrentFormset = AllocateZeroPool (sizeof (H2O_FORMSET_INFO));
if (CurrentFormset == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CurrentFormset->Signature = H2O_FORMSET_INFO_NODE_SIGNATURE;
CurrentFormset->FormsetBlock = (H2O_HII_LIBT_EXT_FORMSET_BLOCK *)BlockData;
CopyMem (&CurrentFormset->FormsetId, &((H2O_HII_LIBT_EXT_FORMSET_BLOCK *)BlockData)->FormsetId, sizeof (EFI_GUID));
InitializeListHead (&CurrentFormset->FormListHead);
InitializeListHead (&CurrentFormset->HotkeyListHead);
InitializeListHead (&CurrentFormset->StyleListHead);
InitializeListHead (&CurrentFormset->ExpressionQIdMapList);
InsertTailList (&CurrentVfr->FormsetListHead, &CurrentFormset->Link);
break;
case H2O_HII_LIBT_EXT_FORMSET_END:
CurrentFormset = NULL;
CurrentForm = NULL;
CurrentHotkey = NULL;
CurrentStyle = NULL;
break;
case H2O_HII_LIBT_EXT_FORM:
if (CurrentFormset == NULL) {
ASSERT (FALSE);
break;
}
CurrentForm = AllocateZeroPool (sizeof (H2O_FORM_INFO));
if (CurrentForm == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CurrentForm->Signature = H2O_FORM_INFO_NODE_SIGNATURE;
CurrentForm->FormBlock = (H2O_HII_LIBT_EXT_FORM_BLOCK *)BlockData;
InitializeListHead (&CurrentForm->StyleListHead);
InitializeListHead (&CurrentForm->HotkeyListHead);
InitializeListHead (&CurrentForm->ImportListHead);
InitializeListHead (&CurrentForm->StatementListHead);
InitializeListHead (&CurrentForm->TargetListHead);
InsertTailList (&CurrentFormset->FormListHead, &CurrentForm->Link);
break;
case H2O_HII_LIBT_EXT_FORM_END:
CurrentForm = NULL;
CurrentHotkey = NULL;
CurrentStyle = NULL;
break;
case H2O_HII_LIBT_EXT_HOTKEY:
if ((CurrentStatement == NULL &&
CurrentForm == NULL &&
CurrentFormset == NULL &&
CurrentLayout == NULL) ||
HotKeyBuffer == NULL) {
ASSERT (FALSE);
break;
}
CurrentHotkey = &HotKeyBuffer[HotKeyIndex++];
CurrentHotkey->Signature = H2O_HOTKEY_INFO_NODE_SIGNATURE;
CurrentHotkey->HotkeyBlock = (H2O_HII_LIBT_EXT_HOTKEY_BLOCK *)BlockData;
InitializeListHead (&CurrentHotkey->StyleListHead);
if (CurrentStatement != NULL) {
InsertTailList (&CurrentStatement->HotkeyListHead, &CurrentHotkey->Link);
} else if (CurrentForm != NULL) {
InsertTailList (&CurrentForm->HotkeyListHead, &CurrentHotkey->Link);
} else if (CurrentFormset != NULL) {
InsertTailList (&CurrentFormset->HotkeyListHead, &CurrentHotkey->Link);
} else if (CurrentLayout != NULL) {
InsertTailList (&CurrentLayout->HotkeyListHead, &CurrentHotkey->Link);
}
break;
case H2O_HII_LIBT_EXT_HOTKEY_END:
CurrentHotkey = NULL;
CurrentStyle = NULL;
break;
case H2O_HII_LIBT_EXT_IMPORT:
ASSERT (CurrentForm != NULL);
if (CurrentForm == NULL) {
break ;
}
CurrentImport = AllocateZeroPool (sizeof (H2O_IMPORT_INFO));
if (CurrentImport == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ImportBlock = (H2O_HII_LIBT_EXT_IMPORT_BLOCK *)BlockData;
CurrentImport->Signature = H2O_IMPORT_INFO_NODE_SIGNATURE;
CopyGuid (&CurrentImport->TargetFormsetGuid, &ImportBlock->TargetFormsetGuid);
CurrentImport->Flags = ImportBlock->Flags;
CurrentImport->TargetFormId = ImportBlock->TargetFormId;
CurrentImport->TargetId = ImportBlock->TargetId;
CurrentImport->LocalId = ImportBlock->LocalId;
InitializeListHead (&CurrentImport->Link);
InsertTailList (&CurrentForm->ImportListHead, &CurrentImport->Link);
break;
case H2O_HII_LIBT_EXT_STATEMENT:
if (CurrentForm == NULL) {
ASSERT (FALSE);
break;
}
CurrentStatement = AllocateZeroPool (sizeof (H2O_STATEMENT_INFO));
if (CurrentStatement == NULL) {
return EFI_OUT_OF_RESOURCES;
}
StatementBlock = (H2O_HII_LIBT_EXT_STATEMENT_BLOCK *)BlockData;
CurrentStatement->Signature = H2O_STATEMENT_INFO_NODE_SIGNATURE;
CurrentStatement->IsQuestion = ((StatementBlock->Flags & H2O_HII_STATEMENT_QUESTION) == H2O_HII_STATEMENT_QUESTION);
CurrentStatement->Position = StatementBlock->Position;
CurrentStatement->StatementId = StatementBlock->StatementId;
CurrentStatement->QuestionId = StatementBlock->QuestionId;
InitializeListHead (&CurrentStatement->Link);
InitializeListHead (&CurrentStatement->StyleListHead);
InitializeListHead (&CurrentStatement->HotkeyListHead);
InitializeListHead (&CurrentStatement->ExpressionListHead);
InsertTailList (&CurrentForm->StatementListHead, &CurrentStatement->Link);
break;
case H2O_HII_LIBT_EXT_STATEMENT_END:
CurrentStatement = NULL;
CurrentHotkey = NULL;
CurrentStyle = NULL;
break;
case H2O_HII_LIBT_EXPRESSION:
ASSERT (CurrentStatement != NULL);
if (CurrentStatement == NULL) {
break;
}
ExpressionSize = ((H2O_HII_LAYOUT_BLOCK *) BlockData)->BlockSize - sizeof (H2O_HII_LIBT_EXPRESSION_BLOCK) + 1;
CurrentExpression = AllocateZeroPool (sizeof (H2O_EXPRESSION_INFO) + ExpressionSize - 1);
ASSERT (CurrentExpression != NULL);
if (CurrentExpression == NULL) {
break;
}
CurrentExpression->Signature = H2O_EXPRESSION_INFO_NODE_SIGNATURE;
CurrentExpression->ExpressionSize = ExpressionSize;
CopyMem (
CurrentExpression->ExpressionOpcodes,
&(((H2O_HII_LIBT_EXPRESSION_BLOCK *)BlockData)->ExpressionOpcodes),
ExpressionSize
);
InitializeListHead (&CurrentExpression->Link);
InsertTailList (&CurrentStatement->ExpressionListHead, &CurrentExpression->Link);
CurrentStatement->ExpressionCount++;
break;
case H2O_HII_LIBT_EXPRESSION_QID_MAP:
ASSERT (CurrentFormset != NULL);
if (CurrentFormset == NULL) {
break;
}
CurrentExpressionQidMap = AllocateZeroPool (sizeof (H2O_EXPRESSION_QID_MAP_INFO));
if (CurrentExpressionQidMap == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CurrentExpressionQidMap->Signature = H2O_EXPRESSION_QID_MAP_INFO_NODE_SIGNATURE;
CurrentExpressionQidMap->ExpressionQIdMapBlock = (H2O_HII_LIBT_EXPRESSION_QID_MAP_BLOCK *) BlockData;
InitializeListHead (&CurrentExpressionQidMap->Link);
InsertTailList (&CurrentFormset->ExpressionQIdMapList, &CurrentExpressionQidMap->Link);
break ;
case H2O_HII_LIBT_IMPORT_TARGET_BEGIN:
case H2O_HII_LIBT_LINK_TARGET_BEGIN:
ASSERT (CurrentForm != NULL);
if (CurrentForm == NULL) {
break;
}
CurrentTargetInfo = AllocateZeroPool (sizeof (H2O_TARGET_INFO));
if (CurrentTargetInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CurrentTargetInfo->Signature = H2O_TARGET_INFO_NODE_SIGNATURE;
CurrentTargetInfo->VfcfOpcode = BlockType;
if (BlockType == H2O_HII_LIBT_IMPORT_TARGET_BEGIN) {
ImportTargetBlock = (H2O_HII_LIBT_IMPORT_TARGET_BEGIN_BLOCK *) BlockData;
CurrentTargetInfo->TargetLabelId = ImportTargetBlock->TargetLabelId;
CurrentTargetInfo->TargetFormId = ImportTargetBlock->TargetFormId;
CopyGuid (&CurrentTargetInfo->TargetFormsetGuid, (VOID *) &ImportTargetBlock->TargetFormsetGuid);
} else {
LinkTargetBlock = (H2O_HII_LIBT_LINK_TARGET_BEGIN_BLOCK *) BlockData;
CurrentTargetInfo->TargetFormId = LinkTargetBlock->TargetFormId;
CurrentTargetInfo->TargetLabelId = LinkTargetBlock->TargetLabelId;
CopyGuid (&CurrentTargetInfo->TargetFormsetGuid, (VOID *) &LinkTargetBlock->TargetFormsetGuid);
}
InitializeListHead (&CurrentTargetInfo->Link);
InitializeListHead (&CurrentTargetInfo->StyleListHead);
InsertTailList (&CurrentForm->TargetListHead, &CurrentTargetInfo->Link);
break;
case H2O_HII_LIBT_IMPORT_TARGET_END:
case H2O_HII_LIBT_LINK_TARGET_END:
CurrentTargetInfo = NULL;
CurrentStyle = NULL;
break;
default:
ASSERT (FALSE);
break;
}
}
return Status;
}
STATIC
EFI_STATUS
GetLayoutPackage (
IN EFI_HII_HANDLE HiiHandle,
OUT UINT8 **LayoutPackage
)
{
EFI_STATUS Status;
EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList;
EFI_HII_PACKAGE_HEADER *Package;
UINT32 PackageLength;
UINTN BufferSize;
UINTN Offset;
if (LayoutPackage == NULL) {
return EFI_INVALID_PARAMETER;
}
*LayoutPackage = NULL;
//
// Locate HiiDatabase Protocol
//
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get the HII package list by HiiHandle
//
BufferSize = 0;
HiiPackageList = NULL;
Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
if (Status == EFI_BUFFER_TOO_SMALL) {
HiiPackageList = (EFI_HII_PACKAGE_LIST_HEADER *) AllocatePool (BufferSize);
if (HiiPackageList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = HiiDatabase->ExportPackageLists (HiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
if (EFI_ERROR (Status)) {
SafeFreePool ((VOID **) &HiiPackageList);
return Status;
}
} else {
return Status;
}
//
// Find layout package by package type
//
Status = EFI_NOT_FOUND;
Offset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
PackageLength = HiiPackageList->PackageLength;
while (Offset < PackageLength) {
Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
if (Package->Type == H2O_HII_PACKAGE_LAYOUTS) {
*LayoutPackage = (UINT8 *) AllocatePool (PackageLength);
if (*LayoutPackage != NULL) {
CopyMem (*LayoutPackage, Package, PackageLength);
Status = EFI_SUCCESS;
} else {
Status = EFI_BUFFER_TOO_SMALL;
}
break;
}
Offset += Package->Length;
}
if (Offset >= PackageLength) {
Status = EFI_NOT_FOUND;
}
SafeFreePool ((VOID **) &HiiPackageList);
return Status;
}
EFI_STATUS
GetLayoutTreeAndVfrTree (
OUT LIST_ENTRY **LayoutListHead,
OUT LIST_ENTRY **VfrListHead
)
{
EFI_STATUS Status;
LAYOUT_DATABASE_PROTOCOL *LayoutDatabase;
UINT8 *PkgBuffer;
LIST_ENTRY *TempLayoutListHead;
LIST_ENTRY *TempVfrListHead;
ASSERT (LayoutListHead != NULL);
ASSERT (VfrListHead != NULL);
if (LayoutListHead == NULL || VfrListHead == NULL) {
return EFI_INVALID_PARAMETER;
}
*LayoutListHead = NULL;
*LayoutListHead = NULL;
Status = gBS->LocateProtocol (&gLayoutDatabaseProtocolGuid, NULL, (VOID **) &LayoutDatabase);
if (EFI_ERROR (Status)) {
return Status;
}
TempLayoutListHead = LayoutDatabase->LayoutListHead;
TempVfrListHead = LayoutDatabase->VfrListHead;
if (TempLayoutListHead == NULL) {
//
// Get layout pkg buffer
//
PkgBuffer = NULL;
Status = GetLayoutPackage (LayoutDatabase->LayoutPkgHiiHandle, &PkgBuffer);
//
// BUGBUG: HiiDatabase not support layout pkg yet
//
if (EFI_ERROR (Status)) {
//return Status;
}
PkgBuffer = (UINT8 *)(UINTN *)LayoutDatabase->LayoutPkgAddr;
if (PkgBuffer == NULL) {
return EFI_NOT_FOUND;
}
//
// Parse layout pkg into layout list
//
Status = ParseLayoutPkg(PkgBuffer, &TempLayoutListHead, &TempVfrListHead);
if (Status != EFI_SUCCESS) {
return Status;
}
LayoutDatabase->LayoutListHead = TempLayoutListHead;
LayoutDatabase->VfrListHead = TempVfrListHead;
}
*LayoutListHead = LayoutDatabase->LayoutListHead;
*VfrListHead = LayoutDatabase->VfrListHead;
return EFI_SUCCESS;
}
EFI_STATUS
GetLayoutById (
IN UINT32 LayoutId,
IN EFI_GUID *DisplayEngineGuid,
OUT H2O_LAYOUT_INFO **Layout
)
{
EFI_STATUS Status;
LIST_ENTRY *LayoutList;
LIST_ENTRY *VfrListHead;
LIST_ENTRY *LayoutLink;
H2O_LAYOUT_INFO *LayoutInfo;
ASSERT (Layout != NULL);
ASSERT (DisplayEngineGuid != NULL);
if ((Layout == NULL) || (DisplayEngineGuid == NULL)) {
return EFI_INVALID_PARAMETER;
}
Status = GetLayoutTreeAndVfrTree (&LayoutList, &VfrListHead);
if (EFI_ERROR (Status) || LayoutList == NULL) {
return Status;
}
//
// Get Layout
//
LayoutLink = GetFirstNode (LayoutList);
while (!IsNull (LayoutList, LayoutLink)) {
LayoutInfo = H2O_LAYOUT_INFO_NODE_FROM_LINK (LayoutLink);
if ((LayoutInfo->LayoutId == LayoutId) &&
((CompareGuid(&LayoutInfo->DisplayEngineGuid[0], DisplayEngineGuid)) ||
(CompareGuid(&LayoutInfo->DisplayEngineGuid[1], DisplayEngineGuid)) ||
(CompareGuid(&LayoutInfo->DisplayEngineGuid[2], DisplayEngineGuid)))) {
*Layout = LayoutInfo;
return EFI_SUCCESS;
}
LayoutLink = GetNextNode (LayoutList, LayoutLink);
}
return EFI_NOT_FOUND;
}
EFI_STATUS
GetFormsetLayoutByGuid (
IN EFI_GUID *FormsetGuid,
OUT H2O_FORMSET_INFO **Formset
)
{
EFI_STATUS Status;
LIST_ENTRY *LayoutListHead;
LIST_ENTRY *VfrListHead;
LIST_ENTRY *FormsetListHead;
LIST_ENTRY *VfrLink;
LIST_ENTRY *FormsetLink;
H2O_VFR_INFO *TempVfr;
H2O_FORMSET_INFO *TempFormset;
Status = GetLayoutTreeAndVfrTree (&LayoutListHead, &VfrListHead);
if (EFI_ERROR (Status) || VfrListHead == NULL) {
return EFI_NOT_FOUND;
}
//
// Get vfr
//
VfrLink = VfrListHead;
if (IsNull (VfrLink, VfrLink->ForwardLink)) {
return EFI_NOT_FOUND;
}
*Formset = NULL;
TempFormset = NULL;
do {
VfrLink = VfrLink->ForwardLink;
TempVfr = H2O_VFR_INFO_NODE_FROM_LINK (VfrLink);
//
// Get formset
//
FormsetListHead = &TempVfr->FormsetListHead;
FormsetLink = FormsetListHead;
if (IsNull (FormsetLink, FormsetLink->ForwardLink)) {
continue;
}
do {
FormsetLink = FormsetLink->ForwardLink;;
TempFormset = H2O_FORMSET_INFO_NODE_FROM_LINK (FormsetLink);
if (CompareGuid (&(TempFormset->FormsetId), FormsetGuid)) {
*Formset = TempFormset;
break;
}
} while (!IsNodeAtEnd (FormsetListHead, FormsetLink));
if (*Formset != NULL) {
break;
}
} while (!IsNodeAtEnd (VfrListHead, VfrLink));
if (*Formset == NULL) {
*Formset = TempFormset;
return EFI_NOT_FOUND;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
GetLayoutIdByGuid (
IN EFI_GUID *FormsetGuid,
OUT UINT32 *LayoutId
)
{
EFI_STATUS Status;
H2O_PROPERTY_INFO *Property;
H2O_PROPERTY_VALUE PropValue;
UINT32 FormsetLayoutId;
Status = GetVfcfFormsetLayoutId (FormsetGuid, &FormsetLayoutId);
if (!EFI_ERROR (Status)) {
*LayoutId = FormsetLayoutId;
return Status;
}
Status = GetVfcfFormsetPropertyValue (
FormsetGuid,
H2O_IFR_STYLE_TYPE_FORMSET,
H2O_STYLE_PSEUDO_CLASS_NORMAL,
"layout",
NULL,
&Property,
&PropValue
);
if (!EFI_ERROR (Status)) {
*LayoutId = PropValue.H2OValue.Value.U16;
}
return Status;
}
STATIC
VOID
FreeSetupMenuData (
IN H2O_FORM_BROWSER_SM *SetupMenuData
)
{
if (SetupMenuData == NULL) {
return;
}
if (SetupMenuData->TitleString != NULL) {
FreePool (SetupMenuData->TitleString);
}
if (SetupMenuData->CoreVersionString != NULL) {
FreePool (SetupMenuData->CoreVersionString);
}
if (SetupMenuData->SetupMenuInfoList != NULL) {
FreePool (SetupMenuData->SetupMenuInfoList);
}
FreePool (SetupMenuData);
}
STATIC
EFI_STATUS
GetLayoutByDEGuid (
IN EFI_GUID *FsGuid,
IN EFI_GUID *DEGuid,
OUT H2O_LAYOUT_INFO **Layout
)
{
EFI_STATUS Status;
BOOLEAN IsScu;
EFI_SETUP_UTILITY_APPLICATION_PROTOCOL *SetupUtilityApp;
H2O_FORM_BROWSER_PROTOCOL *FB;
H2O_FORM_BROWSER_SM *SetupMenuData;
EFI_GUID ScuFormSetGuid = {0x9f85453e, 0x2f03, 0x4989, 0xad, 0x3b, 0x4a, 0x84, 0x07, 0x91, 0xaf, 0x3a};
UINT32 LayoutId;
H2O_LAYOUT_INFO *LayoutInfo;
if (FsGuid == NULL || DEGuid == NULL || Layout == NULL) {
return EFI_INVALID_PARAMETER;
}
IsScu = FALSE;
Status = gBS->LocateProtocol (&gEfiSetupUtilityApplicationProtocolGuid, NULL, (VOID **) &SetupUtilityApp);
if (!EFI_ERROR (Status) && SetupUtilityApp->VfrDriverState == InitializeSetupUtility) {
IsScu = TRUE;
} else {
Status = gBS->LocateProtocol (&gH2OFormBrowserProtocolGuid, NULL, (VOID **) &FB);
if (!EFI_ERROR (Status)) {
Status = FB->GetSMInfo (FB, &SetupMenuData);
if (!EFI_ERROR (Status)) {
if (SetupMenuData->NumberOfSetupMenus > 1) {
IsScu = TRUE;
}
FreeSetupMenuData (SetupMenuData);
}
}
}
Status = EFI_NOT_FOUND;
LayoutId = 0;
if (IsScu) {
//
// The formset has setup menu will get SCU layout first
//
Status = GetLayoutIdByGuid (&ScuFormSetGuid, &LayoutId);
}
if (EFI_ERROR (Status)) {
Status = GetLayoutIdByGuid (FsGuid, &LayoutId);
if (EFI_ERROR (Status)) {
Status = GetLayoutIdByGuid (&gZeroGuid, &LayoutId);
}
}
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return Status;
}
Status = GetLayoutById (LayoutId, DEGuid, &LayoutInfo);
if (EFI_ERROR (Status)) {
Status = GetLayoutIdByGuid (&gZeroGuid, &LayoutId);
ASSERT_EFI_ERROR (Status);
Status = GetLayoutById (LayoutId, DEGuid, &LayoutInfo);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
return Status;
}
}
*Layout = LayoutInfo;
return EFI_SUCCESS;
}
H2O_FORM_INFO *
GetFormLayoutByFormId (
IN H2O_FORMSET_INFO *Formset,
IN UINT32 FormId
)
{
LIST_ENTRY *FormLink;
H2O_FORM_INFO *FormInfo;
if (Formset == NULL) {
return NULL;
}
FormLink = &Formset->FormListHead;
if (IsNull (FormLink, FormLink->ForwardLink)) {
return NULL;
}
do {
FormLink = FormLink->ForwardLink;
FormInfo = H2O_FORM_INFO_NODE_FROM_LINK (FormLink);
if (FormInfo->FormBlock->FormId == FormId) {
return FormInfo;
}
} while (!IsNodeAtEnd (&Formset->FormListHead, FormLink));
return NULL;
}
EFI_STATUS
GetPanelById (
IN EFI_GUID *FsGuid,
IN EFI_GUID *DEGuid,
IN UINT32 PanelId,
OUT H2O_PANEL_INFO **Panel
)
{
EFI_STATUS Status;
H2O_LAYOUT_INFO *LayoutInfo;
H2O_PANEL_INFO *PanelInfo;
if (FsGuid == NULL || DEGuid == NULL || Panel == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = GetLayoutByDEGuid (FsGuid, DEGuid, &LayoutInfo);
if (EFI_ERROR (Status)) {
return Status;
}
PanelInfo = GetPanelInfo (LayoutInfo, PanelId);
if (PanelInfo == NULL) {
return EFI_NOT_FOUND;
}
*Panel = PanelInfo;
return EFI_SUCCESS;
}
H2O_STATEMENT_INFO *
GetStatementLayoutByQuestionId (
IN H2O_FORMSET_INFO *Formset,
IN H2O_FORM_INFO *FormInfo,
IN BOOLEAN IsQuestion,
IN UINT16 Id
)
{
LIST_ENTRY *FormLink;
LIST_ENTRY *StatementLink;
H2O_FORM_INFO *Form;
H2O_STATEMENT_INFO *Statement;
if (Formset == NULL) {
return NULL;
}
if (IsListEmpty (&Formset->FormListHead)) {
return NULL;
}
FormLink = GetFirstNode (&Formset->FormListHead);
while (!IsNull (&Formset->FormListHead, FormLink)) {
Form = H2O_FORM_INFO_NODE_FROM_LINK (FormLink);
FormLink = GetNextNode (&Formset->FormListHead, FormLink);
if (IsListEmpty (&Form->StatementListHead)) {
continue;
}
StatementLink = GetFirstNode (&Form->StatementListHead);
while (!IsNull (&Form->StatementListHead, StatementLink)) {
Statement = H2O_STATEMENT_INFO_NODE_FROM_LINK (StatementLink);
StatementLink = GetNextNode (&Form->StatementListHead, StatementLink);
if (Statement->IsQuestion == IsQuestion &&
Statement->QuestionId == Id) {
return Statement;
}
}
}
return NULL;
}
H2O_PANEL_INFO *
GetNextPanel (
IN H2O_LAYOUT_INFO *LayoutInfo,
IN H2O_PANEL_INFO *PanelInfo
)
{
LIST_ENTRY *PanelLink;
H2O_PANEL_INFO *Panel;
if (LayoutInfo == NULL) {
return NULL;
}
if (IsListEmpty (&LayoutInfo->PanelListHead)) {
return NULL;
}
if (PanelInfo == NULL) {
PanelLink = GetFirstNode (&LayoutInfo->PanelListHead);
Panel = H2O_PANEL_INFO_NODE_FROM_LINK (PanelLink);
return Panel;
}
PanelLink = GetFirstNode (&LayoutInfo->PanelListHead);
while (!IsNull (&LayoutInfo->PanelListHead, PanelLink)) {
Panel = H2O_PANEL_INFO_NODE_FROM_LINK (PanelLink);
PanelLink = GetNextNode (&LayoutInfo->PanelListHead, PanelLink);
if (Panel == PanelInfo) {
break;
}
}
if (IsNull (&LayoutInfo->PanelListHead, PanelLink)) {
return NULL;
}
Panel = H2O_PANEL_INFO_NODE_FROM_LINK (PanelLink);
return Panel;
}
VOID
SafeFreePool(
IN VOID **Buffer
)
{
if (*Buffer != NULL) {
FreePool (*Buffer);
}
*Buffer = NULL;
}