3404 lines
115 KiB
C
3404 lines
115 KiB
C
/** @file
|
|
Process VFCF related functions.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2015 - 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 "FBProcessVfcf.h"
|
|
#include "FBTargetInfo.h"
|
|
#include "Setup.h"
|
|
|
|
LIST_ENTRY mH2OBrowserImportFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (mH2OBrowserImportFormSetList);
|
|
LIST_ENTRY mH2OBrowserStaleImportFormSetList = INITIALIZE_LIST_HEAD_VARIABLE (mH2OBrowserStaleImportFormSetList);
|
|
LIST_ENTRY mH2OBrowserFormSetHiiResourceList = INITIALIZE_LIST_HEAD_VARIABLE (mH2OBrowserFormSetHiiResourceList);
|
|
H2O_FORM_BROWSER_FORMSET_HII_RESOURCE *mFormSetHiiResource = NULL;
|
|
UINT16 mImportInfoCount = 0;
|
|
IMPORT_INFO *mImportInfoList = NULL;
|
|
H2O_STATEMENT_ID mImportStatementId = 0;
|
|
EFI_HANDLE mImportFormUpdateNotifyHandle = NULL;
|
|
|
|
FORM_EXPRESSION *
|
|
CreateExpression (
|
|
IN OUT FORM_BROWSER_FORM *Form,
|
|
IN UINT8 *OpCode
|
|
);
|
|
|
|
/**
|
|
Copy string from the string ID of source Hii handle to the string ID of destination Hii handle.
|
|
If the string ID of destination Hii handle, it will create a new string ID.
|
|
|
|
@param[in] SrcHiiHandle Source Hii handle
|
|
@param[in] SrcStringId String ID of source Hii handle
|
|
@param[in] DstHiiHandle Destination Hii handle
|
|
@param[in] DstStringId Pointer to string ID of destination Hii handle
|
|
|
|
@retval EFI_SUCCESS Successfully copy string
|
|
@retval EFI_OUT_OF_RESOURCES Allocate pool fail
|
|
@retval Other Fail to copy string
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
CopyHiiString (
|
|
IN EFI_HII_HANDLE SrcHiiHandle,
|
|
IN EFI_STRING_ID SrcStringId,
|
|
IN EFI_HII_HANDLE DstHiiHandle,
|
|
IN OUT EFI_STRING_ID *DstStringId
|
|
)
|
|
{
|
|
EFI_STRING_ID StringId;
|
|
EFI_STATUS Status;
|
|
|
|
if (*DstStringId != 0 ||
|
|
mFormSetHiiResource == NULL ||
|
|
mFormSetHiiResource->HiiHandle != DstHiiHandle) {
|
|
return HiiCopyStringByStringId (SrcHiiHandle, SrcStringId, DstHiiHandle, DstStringId);
|
|
}
|
|
|
|
if (mFormSetHiiResource->NewStringIdIndex >= mFormSetHiiResource->NewStringIdCount) {
|
|
mFormSetHiiResource->NewStringIdList = ReallocatePool (
|
|
sizeof (EFI_STRING_ID *) * (mFormSetHiiResource->NewStringIdCount),
|
|
sizeof (EFI_STRING_ID *) * (mFormSetHiiResource->NewStringIdCount + FORMSET_HII_RESOURCE_STRING_ID_INCREMENT),
|
|
mFormSetHiiResource->NewStringIdList
|
|
);
|
|
if (mFormSetHiiResource->NewStringIdList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
mFormSetHiiResource->NewStringIdCount += FORMSET_HII_RESOURCE_STRING_ID_INCREMENT;
|
|
StringId = 0;
|
|
} else {
|
|
StringId = mFormSetHiiResource->NewStringIdList[mFormSetHiiResource->NewStringIdIndex];
|
|
}
|
|
|
|
Status = HiiCopyStringByStringId (SrcHiiHandle, SrcStringId, DstHiiHandle, &StringId);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
mFormSetHiiResource->NewStringIdList[mFormSetHiiResource->NewStringIdIndex++] = StringId;
|
|
|
|
*DstStringId = StringId;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Copy image from the image ID of source Hii handle to the image ID of destination Hii handle.
|
|
If the image ID of destination Hii handle is zero, it will create a new string ID.
|
|
|
|
@param[in] SrcHiiHandle Source Hii handle
|
|
@param[in] SrcImageId Image ID of source Hii handle
|
|
@param[in] DstHiiHandle Destination Hii handle
|
|
@param[in] DstImageId Pointer to image ID of destination Hii handle
|
|
|
|
@retval EFI_SUCCESS Successfully copy image
|
|
@retval EFI_OUT_OF_RESOURCES Allocate pool fail
|
|
@retval Other Fail to copy image
|
|
**/
|
|
EFI_STATUS
|
|
CopyHiiImage (
|
|
IN EFI_HII_HANDLE SrcHiiHandle,
|
|
IN EFI_IMAGE_ID SrcImageId,
|
|
IN EFI_HII_HANDLE DstHiiHandle,
|
|
IN OUT EFI_IMAGE_ID *DstImageId
|
|
)
|
|
{
|
|
EFI_IMAGE_ID ImageId;
|
|
EFI_STATUS Status;
|
|
|
|
if (*DstImageId != 0 ||
|
|
mFormSetHiiResource == NULL ||
|
|
mFormSetHiiResource->HiiHandle != DstHiiHandle) {
|
|
return HiiCopyImageByImageId (SrcHiiHandle, SrcImageId, DstHiiHandle, DstImageId);
|
|
}
|
|
|
|
if (mFormSetHiiResource->NewImageIdIndex == mFormSetHiiResource->NewImageIdCount) {
|
|
mFormSetHiiResource->NewImageIdList = ReallocatePool (
|
|
sizeof (EFI_STRING_ID *) * (mFormSetHiiResource->NewImageIdCount),
|
|
sizeof (EFI_STRING_ID *) * (mFormSetHiiResource->NewImageIdCount + FORMSET_HII_RESOURCE_IMAGE_ID_INCREMENT),
|
|
mFormSetHiiResource->NewImageIdList
|
|
);
|
|
if (mFormSetHiiResource->NewImageIdList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
mFormSetHiiResource->NewImageIdCount += FORMSET_HII_RESOURCE_IMAGE_ID_INCREMENT;
|
|
ImageId = 0;
|
|
} else {
|
|
ImageId = mFormSetHiiResource->NewImageIdList[mFormSetHiiResource->NewImageIdIndex];
|
|
}
|
|
Status = HiiCopyImageByImageId (SrcHiiHandle, SrcImageId, DstHiiHandle, &ImageId);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
mFormSetHiiResource->NewImageIdList[mFormSetHiiResource->NewImageIdIndex++] = ImageId;
|
|
|
|
*DstImageId = ImageId;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Create disableif expression with TRUE expression opcode.
|
|
|
|
@param[in, out] ExpressionOpCode Pointer to expression code.
|
|
|
|
@return Expression pointer or NULL if invalid input parameter or fail to allocate pool.
|
|
**/
|
|
FORM_EXPRESSION *
|
|
CreateDisableIfExpression (
|
|
IN OUT EXPRESSION_OPCODE *ExpressionOpCode
|
|
)
|
|
{
|
|
FORM_EXPRESSION *Expression;
|
|
|
|
if (ExpressionOpCode == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
|
|
if (Expression == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
Expression->Signature = FORM_EXPRESSION_SIGNATURE;
|
|
Expression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
|
|
InitializeListHead (&Expression->OpCodeListHead);
|
|
|
|
ZeroMem (ExpressionOpCode, sizeof (EXPRESSION_OPCODE));
|
|
ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
|
|
ExpressionOpCode->Operand = EFI_IFR_TRUE_OP;
|
|
ExpressionOpCode->Value.Type = EFI_IFR_TYPE_BOOLEAN;
|
|
ExpressionOpCode->Value.Value.b = TRUE;
|
|
InsertTailList (&Expression->OpCodeListHead, &ExpressionOpCode->Link);
|
|
|
|
return Expression;
|
|
}
|
|
|
|
/**
|
|
Insert disableif TRUE expression into expression list of statement.
|
|
|
|
@param[in] FormSet Pointer to formset
|
|
@param[in] Form Pointer to form
|
|
@param[in, out] Statement Pointer to statement
|
|
|
|
@retval EFI_SUCCESS Successfully insert disableif TRUE expression
|
|
@retval EFI_ABORTED Fail to create disableif TRUE expression
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool
|
|
**/
|
|
EFI_STATUS
|
|
InsertDisableIfExpression (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN FORM_BROWSER_FORM *Form,
|
|
IN OUT FORM_BROWSER_STATEMENT *Statement
|
|
)
|
|
{
|
|
FORM_EXPRESSION *Expression;
|
|
FORM_EXPRESSION_LIST *ExpressionList;
|
|
|
|
Expression = CreateDisableIfExpression (GetNewExpressionOpCode (FormSet));
|
|
if (Expression == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
InsertTailList (&Form->ExpressionListHead, &Expression->Link);
|
|
|
|
if (Statement->Expression == NULL) {
|
|
Statement->Expression = (FORM_EXPRESSION_LIST *) AllocateZeroPool (sizeof (FORM_EXPRESSION_LIST));
|
|
if (Statement->Expression == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Statement->Expression->Count = 1;
|
|
Statement->Expression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
|
|
Statement->Expression->Expression[0] = Expression;
|
|
} else {
|
|
ExpressionList = ReallocatePool (
|
|
(sizeof(FORM_EXPRESSION_LIST) + ((Statement->Expression->Count - 1) * sizeof(FORM_EXPRESSION *))),
|
|
(sizeof(FORM_EXPRESSION_LIST) + ((Statement->Expression->Count) * sizeof(FORM_EXPRESSION *))),
|
|
Statement->Expression
|
|
);
|
|
if (ExpressionList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Statement->Expression = ExpressionList;
|
|
ExpressionList->Expression[ExpressionList->Count++] = Expression;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Check if there is a matched name value node in the linked list.
|
|
|
|
@param[in] NameValueListHead Pointer to name value linked list.
|
|
@param[in] VariableName Pointer to request name
|
|
|
|
@retval TRUE There is a matched name value node in the linked list
|
|
@retval FALSE There is not a matched name value node in the linked list
|
|
**/
|
|
BOOLEAN
|
|
IsNameValueNodeExistence (
|
|
IN LIST_ENTRY *NameValueListHead,
|
|
IN CHAR16 *VariableName
|
|
)
|
|
{
|
|
NAME_VALUE_NODE *NameValueNode;
|
|
LIST_ENTRY *Link;
|
|
|
|
if (!IsListEmpty(NameValueListHead)) {
|
|
Link = GetFirstNode (NameValueListHead);
|
|
while (!IsNull (NameValueListHead, Link)) {
|
|
NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
|
|
|
|
if (StrCmp (VariableName, NameValueNode->Name) == 0) {
|
|
return TRUE;
|
|
}
|
|
|
|
Link = GetNextNode (NameValueListHead, Link);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Check if there is a imported question in form.
|
|
|
|
@param[in] Form Pointer to form
|
|
|
|
@retval TRUE There is a imported question in form
|
|
@retval FALSE There is not a imported question in form
|
|
**/
|
|
BOOLEAN
|
|
HaveImportQuestion (
|
|
IN FORM_BROWSER_FORM *Form
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT *Question;
|
|
|
|
Link = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, Link)) {
|
|
Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
Link = GetNextNode (&Form->StatementListHead, Link);
|
|
if (IS_IMPORT_STATEMENT (Question)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Check if there is a imported SCU question in form or formset.
|
|
|
|
@param[in] FormSet Pointer to formset
|
|
@param[in] Form Pointer to form
|
|
|
|
@retval TRUE There is a imported SCU question in form or formset
|
|
@retval FALSE There is not a imported SCU question in form or formset
|
|
**/
|
|
BOOLEAN
|
|
HaveImportScuQuestion (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN FORM_BROWSER_FORM *Form
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
LIST_ENTRY *FormLink;
|
|
FORM_BROWSER_STATEMENT *Question;
|
|
FORM_BROWSER_FORM *FormPtr;
|
|
|
|
if (Form != NULL) {
|
|
Link = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, Link)) {
|
|
Question = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
Link = GetNextNode (&Form->StatementListHead, Link);
|
|
if (IS_IMPORT_STATEMENT (Question) && CompareGuid (Question->ImportInfo->SrcFormSet->ClassGuid, &mScuFormSetGuid)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FormSet != NULL) {
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
|
FormPtr = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
if (HaveImportScuQuestion (NULL, FormPtr)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Check if specific formset is imported in current formset.
|
|
|
|
@param[in] CurrentFormSet Pointer to current formset
|
|
@param[in] ImportedFormset Pointer to imported formset
|
|
|
|
@retval TRUE Specific formset is imported in current formset
|
|
@retval FALSE Specific formset is not imported in current formset
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
HaveImportThisFormset (
|
|
IN FORM_BROWSER_FORMSET *CurrentFormSet,
|
|
IN FORM_BROWSER_FORMSET *ImportedFormset
|
|
)
|
|
{
|
|
LIST_ENTRY *FormLink;
|
|
FORM_BROWSER_FORM *Form;
|
|
LIST_ENTRY *QuestionLink;
|
|
FORM_BROWSER_STATEMENT *Question;
|
|
|
|
FormLink = GetFirstNode (&CurrentFormSet->FormListHead);
|
|
while (!IsNull (&CurrentFormSet->FormListHead, FormLink)) {
|
|
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
FormLink = GetNextNode (&CurrentFormSet->FormListHead, FormLink);
|
|
|
|
QuestionLink = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, QuestionLink)) {
|
|
Question = FORM_BROWSER_STATEMENT_FROM_LINK (QuestionLink);
|
|
QuestionLink = GetNextNode (&Form->StatementListHead, QuestionLink);
|
|
if (IS_IMPORT_STATEMENT (Question) && Question->ImportInfo->SrcFormSet == ImportedFormset) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Get available varstore ID from formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@return Varstore ID or zero if there is no available varstore ID.
|
|
**/
|
|
UINT16
|
|
GetAvailableVarstoreId (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORMSET_STORAGE *Storage;
|
|
UINT32 VarStoreId;
|
|
|
|
for (VarStoreId = 1; VarStoreId <= 0xFFFF; VarStoreId++) {
|
|
Link = GetFirstNode (&FormSet->StorageListHead);
|
|
while (!IsNull (&FormSet->StorageListHead, Link)) {
|
|
Storage = FORMSET_STORAGE_FROM_LINK (Link);
|
|
if (Storage->VarStoreId == VarStoreId) {
|
|
break;
|
|
}
|
|
|
|
Link = GetNextNode (&FormSet->StorageListHead, Link);
|
|
}
|
|
|
|
if (IsNull (&FormSet->StorageListHead, Link)) {
|
|
return (UINT16) VarStoreId;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Get available statement ID from formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@return Statement ID.
|
|
**/
|
|
H2O_STATEMENT_ID
|
|
GetAvailableStatementId (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
H2O_STATEMENT_ID MaxStatementId;
|
|
FORM_BROWSER_FORM *Form;
|
|
LIST_ENTRY *FormLink;
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
|
|
MaxStatementId = 0;
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
|
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
|
|
Link = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
Link = GetNextNode (&Form->StatementListHead, Link);
|
|
if (Statement->StatementId >= MaxStatementId) {
|
|
MaxStatementId = Statement->StatementId;
|
|
}
|
|
}
|
|
}
|
|
|
|
Link = GetFirstNode (&FormSet->StatementListOSF);
|
|
while (!IsNull (&FormSet->StatementListOSF, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
Link = GetNextNode (&FormSet->StatementListOSF, Link);
|
|
if (Statement->StatementId >= MaxStatementId) {
|
|
MaxStatementId = Statement->StatementId;
|
|
}
|
|
}
|
|
|
|
return (MaxStatementId + 1);
|
|
}
|
|
|
|
/**
|
|
Get available question ID from formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@return Question ID or zero if there is no available question ID.
|
|
**/
|
|
EFI_QUESTION_ID
|
|
GetAvailableQuestionId (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
LIST_ENTRY *FormLink;
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
FORM_BROWSER_FORM *Form;
|
|
EFI_QUESTION_ID QuestionId;
|
|
BOOLEAN IsValid;
|
|
|
|
for (QuestionId = 1; QuestionId < 0xFFFF; QuestionId++) {
|
|
IsValid = TRUE;
|
|
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink) && IsValid) {
|
|
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
|
|
Link = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
Link = GetNextNode (&Form->StatementListHead, Link);
|
|
if (Statement->QuestionId == QuestionId) {
|
|
IsValid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Link = GetFirstNode (&FormSet->StatementListOSF);
|
|
while (!IsNull (&FormSet->StatementListOSF, Link) && IsValid) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
Link = GetNextNode (&FormSet->StatementListOSF, Link);
|
|
if (Statement->QuestionId == QuestionId) {
|
|
IsValid = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (IsValid) {
|
|
return QuestionId;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Get available fake question ID from formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@return Fake question ID.
|
|
**/
|
|
EFI_QUESTION_ID
|
|
GetAvailableFakeQuestionId (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
EFI_QUESTION_ID FakeQuestionId;
|
|
LIST_ENTRY *FormLink;
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
FORM_BROWSER_FORM *Form;
|
|
|
|
FakeQuestionId = 0;
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
|
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
|
|
Link = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
Link = GetNextNode (&Form->StatementListHead, Link);
|
|
if (Statement->FakeQuestionId >= FakeQuestionId) {
|
|
FakeQuestionId = Statement->FakeQuestionId;
|
|
}
|
|
}
|
|
}
|
|
|
|
Link = GetFirstNode (&FormSet->StatementListOSF);
|
|
while (!IsNull (&FormSet->StatementListOSF, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
Link = GetNextNode (&FormSet->StatementListOSF, Link);
|
|
if (Statement->FakeQuestionId >= FakeQuestionId) {
|
|
FakeQuestionId = Statement->FakeQuestionId;
|
|
}
|
|
}
|
|
|
|
return (FakeQuestionId + 1);
|
|
}
|
|
|
|
/**
|
|
Based on destination question ID of import info, get question ID.
|
|
|
|
@param[in] DstFormSet Pointer to formset.
|
|
@param[in] ImportInfo Pointer to question import info.
|
|
|
|
@return Question ID.
|
|
**/
|
|
EFI_QUESTION_ID
|
|
GetQuestionId (
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN IMPORT_INFO *ImportInfo
|
|
)
|
|
{
|
|
switch (ImportInfo->DstId) {
|
|
|
|
case H2O_IFR_GUID_IMPORT_LOCAL_ID_USE_TARGET_ID:
|
|
if (ImportInfo->SrcId != 0 && GetStatementByQuestionId (DstFormSet, NULL, ImportInfo->SrcId) == NULL) {
|
|
return ImportInfo->SrcId;
|
|
}
|
|
return GetAvailableQuestionId (DstFormSet);
|
|
|
|
case H2O_IFR_GUID_IMPORT_LOCAL_ID_NON_CONFLICTING:
|
|
return GetAvailableQuestionId (DstFormSet);
|
|
|
|
default:
|
|
return ImportInfo->DstId;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Based on source statement, get question ID.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcStatement Pointer to source statement.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
|
|
@return Question ID or zero if input parameter is NULL.
|
|
**/
|
|
EFI_QUESTION_ID
|
|
GetQuestionIdBySrcStatement (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORM_BROWSER_STATEMENT *SrcStatement,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
FORM_BROWSER_STATEMENT *DstStatement;
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT_BUFFER *FBStatementBuffer;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
|
|
if (SrcFormSet == NULL || SrcStatement == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
for (Index = 0; Index < mImportInfoCount; Index++) {
|
|
if (IMPORT_INFO_FLAG_IS_QUESTION(mImportInfoList[Index].Flags) &&
|
|
mImportInfoList[Index].SrcId == SrcStatement->QuestionId &&
|
|
CompareGuid (&mImportInfoList[Index].SrcFormSetGuid, &SrcFormSet->Guid)) {
|
|
mImportInfoList[Index].DstId = GetQuestionId (DstFormSet, &mImportInfoList[Index]);
|
|
return mImportInfoList[Index].DstId;
|
|
}
|
|
}
|
|
|
|
Link = GetFirstNode (&DstFormSet->FBStatementBufferListHead);
|
|
while (!IsNull (&DstFormSet->FBStatementBufferListHead, Link)) {
|
|
FBStatementBuffer = FORM_BROWSER_STATEMENT_BUFFER_FROM_LINK (Link);
|
|
Link = GetNextNode (&DstFormSet->FBStatementBufferListHead, Link);
|
|
|
|
for (Index = 0; Index < FBStatementBuffer->StatementBufferListIndex; Index++) {
|
|
Statement = &FBStatementBuffer->StatementBufferList[Index];
|
|
if (Statement->ImportInfo != NULL &&
|
|
Statement->ImportInfo->SrcStatement != NULL &&
|
|
Statement->ImportInfo->SrcStatement->QuestionId == SrcStatement->QuestionId &&
|
|
Statement->ImportInfo->SrcFormSet != NULL &&
|
|
Statement->ImportInfo->SrcFormSet->HiiHandle == SrcFormSet->HiiHandle &&
|
|
CompareGuid (&Statement->ImportInfo->SrcFormSet->Guid, &SrcFormSet->Guid)) {
|
|
return Statement->QuestionId;
|
|
}
|
|
}
|
|
}
|
|
|
|
DstStatement = CreateDisabledStatementInLastForm (SrcFormSet, SrcStatement, DstFormSet);
|
|
if (DstStatement != NULL) {
|
|
return DstStatement->QuestionId;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
Get statement by the position in the form.
|
|
|
|
@param[in] Form Pointer to form.
|
|
@param[in] Position The position in the form.
|
|
|
|
@return Statement pointer or NULL if input parameter is NULL or not found.
|
|
**/
|
|
FORM_BROWSER_STATEMENT *
|
|
GetStatementByPosition (
|
|
IN FORM_BROWSER_FORM *Form,
|
|
IN UINT16 Position
|
|
)
|
|
{
|
|
UINT16 Count;
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
|
|
if (Form == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
Count = 0;
|
|
Link = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
if (Count == Position) {
|
|
return Statement;
|
|
}
|
|
|
|
Link = GetNextNode (&Form->StatementListHead, Link);
|
|
Count++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Get statement by the question ID in the form or formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
@param[in] Form Pointer to form.
|
|
@param[in] QuestionId Query question ID.
|
|
|
|
@return Statement pointer or NULL if invalid input parameter or not found.
|
|
**/
|
|
FORM_BROWSER_STATEMENT *
|
|
GetStatementByQuestionId (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN FORM_BROWSER_FORM *Form OPTIONAL,
|
|
IN EFI_QUESTION_ID QuestionId
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
LIST_ENTRY *FormLink;
|
|
FORM_BROWSER_FORM *FormPtr;
|
|
|
|
if (FormSet == NULL || QuestionId == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
if (Form != NULL) {
|
|
Link = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
if (Statement->QuestionId == QuestionId) {
|
|
return Statement;
|
|
}
|
|
|
|
Link = GetNextNode (&Form->StatementListHead, Link);
|
|
}
|
|
}
|
|
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
|
FormPtr = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
|
|
Link = GetFirstNode (&FormPtr->StatementListHead);
|
|
while (!IsNull (&FormPtr->StatementListHead, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
if (Statement->QuestionId == QuestionId) {
|
|
return Statement;
|
|
}
|
|
|
|
Link = GetNextNode (&FormPtr->StatementListHead, Link);
|
|
}
|
|
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Get form by the question ID.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
@param[in] QuestionId Query question ID.
|
|
|
|
@return Form pointer or NULL if invalid input parameter or not found.
|
|
**/
|
|
STATIC
|
|
FORM_BROWSER_FORM *
|
|
GetFormByQuestionId (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN EFI_QUESTION_ID QuestionId
|
|
)
|
|
{
|
|
LIST_ENTRY *FormLink;
|
|
FORM_BROWSER_FORM *Form;
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
|
|
if (FormSet == NULL || QuestionId == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
for (FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
!IsNull (&FormSet->FormListHead, FormLink);
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink)) {
|
|
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
|
|
for (Link = GetFirstNode (&Form->StatementListHead);
|
|
!IsNull (&Form->StatementListHead, Link);
|
|
Link = GetNextNode (&Form->StatementListHead, Link)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
|
|
if (Statement->QuestionId == QuestionId) {
|
|
return Form;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Get new statement from pre-allocated buffer of formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@return Statement or NULL if input parameter is NULL or fail to allocate pool.
|
|
**/
|
|
FORM_BROWSER_STATEMENT *
|
|
GetNewStatement (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_STATEMENT_BUFFER *FBStatementBuffer;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
|
|
if (FormSet == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (FormSet->FBStatementBufferListHead.ForwardLink == NULL) {
|
|
InitializeListHead (&FormSet->FBStatementBufferListHead);
|
|
}
|
|
|
|
Link = GetFirstNode (&FormSet->FBStatementBufferListHead);
|
|
while (!IsNull (&FormSet->FBStatementBufferListHead, Link)) {
|
|
FBStatementBuffer = FORM_BROWSER_STATEMENT_BUFFER_FROM_LINK (Link);
|
|
Link = GetNextNode (&FormSet->FBStatementBufferListHead, Link);
|
|
if (FBStatementBuffer->StatementBufferListIndex < FBStatementBuffer->StatementBufferListCount) {
|
|
Statement = &FBStatementBuffer->StatementBufferList[FBStatementBuffer->StatementBufferListIndex++];
|
|
return Statement;
|
|
}
|
|
}
|
|
|
|
FBStatementBuffer = AllocateZeroPool (sizeof (FORM_BROWSER_STATEMENT_BUFFER));
|
|
if (FBStatementBuffer == NULL) {
|
|
return NULL;
|
|
}
|
|
FBStatementBuffer->StatementBufferListCount = 100;
|
|
FBStatementBuffer->StatementBufferList = AllocateZeroPool (sizeof (FORM_BROWSER_STATEMENT) * FBStatementBuffer->StatementBufferListCount);
|
|
if (FBStatementBuffer->StatementBufferList == NULL) {
|
|
FreePool (FBStatementBuffer);
|
|
return NULL;
|
|
}
|
|
FBStatementBuffer->Signature = FORM_BROWSER_STATEMENT_BUFFER_SIGNATURE;
|
|
InsertTailList (&FormSet->FBStatementBufferListHead, &FBStatementBuffer->Link);
|
|
|
|
Statement = &FBStatementBuffer->StatementBufferList[FBStatementBuffer->StatementBufferListIndex++];
|
|
return Statement;
|
|
}
|
|
|
|
/**
|
|
Get new expression opcode from pre-allocated buffer of formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@return Expression opcode or NULL if input parameter is NULL or fail to allocate pool.
|
|
**/
|
|
EXPRESSION_OPCODE *
|
|
GetNewExpressionOpCode (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_EXPRESSION_BUFFER *FBExpressionBuffer;
|
|
EXPRESSION_OPCODE *ExpressionOpCode;
|
|
|
|
if (FormSet == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (FormSet->FBExpressionBufferListHead.ForwardLink == NULL) {
|
|
InitializeListHead (&FormSet->FBExpressionBufferListHead);
|
|
}
|
|
|
|
Link = GetFirstNode (&FormSet->FBExpressionBufferListHead);
|
|
while (!IsNull (&FormSet->FBExpressionBufferListHead, Link)) {
|
|
FBExpressionBuffer = FORM_BROWSER_EXPRESSION_BUFFER_FROM_LINK (Link);
|
|
Link = GetNextNode (&FormSet->FBExpressionBufferListHead, Link);
|
|
if (FBExpressionBuffer->ExpressionBufferListIndex < FBExpressionBuffer->ExpressionBufferListCount) {
|
|
ExpressionOpCode = &FBExpressionBuffer->ExpressionBufferList[FBExpressionBuffer->ExpressionBufferListIndex++];
|
|
return ExpressionOpCode;
|
|
}
|
|
}
|
|
|
|
FBExpressionBuffer = AllocateZeroPool (sizeof (FORM_BROWSER_EXPRESSION_BUFFER));
|
|
if (FBExpressionBuffer == NULL) {
|
|
return NULL;
|
|
}
|
|
FBExpressionBuffer->ExpressionBufferListCount = 100;
|
|
FBExpressionBuffer->ExpressionBufferList = AllocateZeroPool (sizeof (EXPRESSION_OPCODE) * FBExpressionBuffer->ExpressionBufferListCount);
|
|
if (FBExpressionBuffer->ExpressionBufferList == NULL) {
|
|
FreePool (FBExpressionBuffer);
|
|
return NULL;
|
|
}
|
|
FBExpressionBuffer->Signature = FORM_BROWSER_EXPRESSION_BUFFER_SIGNATURE;
|
|
InsertTailList (&FormSet->FBExpressionBufferListHead, &FBExpressionBuffer->Link);
|
|
|
|
ExpressionOpCode = &FBExpressionBuffer->ExpressionBufferList[FBExpressionBuffer->ExpressionBufferListIndex++];
|
|
return ExpressionOpCode;
|
|
}
|
|
|
|
/**
|
|
Get corresponding formset storage by input question.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
@param[in] Question Pointer to question.
|
|
|
|
@return Formset storage pointer or NULL if invalid input parameter or not found.
|
|
**/
|
|
FORMSET_STORAGE *
|
|
GetStorageByQuestion (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN FORM_BROWSER_STATEMENT *Question
|
|
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORMSET_STORAGE *Storage;
|
|
|
|
if (FormSet == NULL || Question == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
Link = GetFirstNode (&FormSet->StorageListHead);
|
|
while (!IsNull (&FormSet->StorageListHead, Link)) {
|
|
Storage = FORMSET_STORAGE_FROM_LINK (Link);
|
|
if (Storage->VarStoreId == Question->VarStoreId) {
|
|
return Storage;
|
|
}
|
|
|
|
Link = GetNextNode (&FormSet->StorageListHead, Link);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Get formset by formset GUID.
|
|
|
|
@param[in] FormSetGuid Pointer to formset GUID.
|
|
@param[in] ... A list of formset. A NULL terminates the list.
|
|
|
|
@return Formset pointer or NULL if invalid input parameter or not found.
|
|
**/
|
|
FORM_BROWSER_FORMSET *
|
|
GetFormSetByFormSetGuid (
|
|
IN EFI_GUID *FormSetGuid,
|
|
...
|
|
)
|
|
{
|
|
VA_LIST Args;
|
|
LIST_ENTRY *FormSetList;
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_FORMSET *FormSet;
|
|
|
|
if (FormSetGuid == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
VA_START (Args, FormSetGuid);
|
|
while ((FormSetList = VA_ARG (Args, LIST_ENTRY *)) != NULL) {
|
|
Link = GetFirstNode (FormSetList);
|
|
|
|
while (!IsNull (FormSetList, Link)) {
|
|
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
|
Link = GetNextNode (FormSetList, Link);
|
|
if (!ValidateFormSet(FormSet)) {
|
|
continue;
|
|
}
|
|
|
|
if (CompareGuid (FormSetGuid, &FormSet->Guid)) {
|
|
return FormSet;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Get source data (formset/form/statement/storage) by import info.
|
|
|
|
@param[in] ImportInfo Pointer to import info.
|
|
@param[out] SrcFormSet Double pointer to source formset.
|
|
@param[out] SrcForm Double pointer to source forms.
|
|
@param[out] SrcStatement Double pointer to source statement.
|
|
@param[out] SrcStorage Double pointer to source storage.
|
|
|
|
@retval EFI_SUCCESS Successfully get source data
|
|
@retval EFI_NOT_FOUND Can not find source data
|
|
**/
|
|
EFI_STATUS
|
|
GetSrcData (
|
|
IN IMPORT_INFO *ImportInfo,
|
|
OUT FORM_BROWSER_FORMSET **SrcFormSet,
|
|
OUT FORM_BROWSER_FORM **SrcForm,
|
|
OUT FORM_BROWSER_STATEMENT **SrcStatement,
|
|
OUT FORMSET_STORAGE **SrcStorage
|
|
)
|
|
{
|
|
FORM_BROWSER_FORMSET *FormSet;
|
|
FORM_BROWSER_FORM *Form;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
FORMSET_STORAGE *Storage;
|
|
|
|
FormSet = GetFormSetByFormSetGuid (
|
|
&ImportInfo->SrcFormSetGuid,
|
|
&mH2OBrowserImportFormSetList,
|
|
&gBrowserFormSetList,
|
|
NULL
|
|
);
|
|
if (FormSet == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Form = IdToForm (FormSet, ImportInfo->SrcFormId);
|
|
if (Form == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (IS_LINK_TARGET (ImportInfo->Type)) {
|
|
Statement = NULL;
|
|
Storage = NULL;
|
|
} else {
|
|
if (IMPORT_INFO_FLAG_IS_QUESTION (ImportInfo->Flags)) {
|
|
Statement = GetStatementByQuestionId (FormSet, Form, ImportInfo->SrcId);
|
|
} else {
|
|
Statement = GetStatementByPosition (Form, ImportInfo->SrcId);
|
|
}
|
|
if (Statement == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
if (Statement->QuestionId != 0 && Statement->VarStoreId != 0) {
|
|
Storage = GetStorageByQuestion (FormSet, Statement);
|
|
if (Storage == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
} else {
|
|
Storage = NULL;
|
|
}
|
|
}
|
|
|
|
*SrcFormSet = FormSet;
|
|
*SrcForm = Form;
|
|
*SrcStatement = Statement;
|
|
*SrcStorage = Storage;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get corresponding formset storage by input browser storage.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
@param[in] BrowserStorage Pointer to browser storage.
|
|
|
|
@return Formset storage pointer or NULL if not found.
|
|
**/
|
|
FORMSET_STORAGE *
|
|
GetFormSetStorage (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN BROWSER_STORAGE *BrowserStorage
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORMSET_STORAGE *FormSetStorage;
|
|
|
|
Link = GetFirstNode (&FormSet->StorageListHead);
|
|
while (!IsNull (&FormSet->StorageListHead, Link)) {
|
|
FormSetStorage = FORMSET_STORAGE_FROM_LINK (Link);
|
|
if (FormSetStorage->BrowserStorage == BrowserStorage) {
|
|
return FormSetStorage;
|
|
}
|
|
Link = GetNextNode (&FormSet->StorageListHead, Link);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Create imported formset by formset GUID.
|
|
|
|
@param[in] ImportFormsetGuid Pointer to formset GUID.
|
|
|
|
@return Formset pointer or NULL if formset is not found or fail to allocate pool.
|
|
**/
|
|
FORM_BROWSER_FORMSET *
|
|
CreateImportFormSet (
|
|
IN EFI_GUID *ImportFormsetGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HII_HANDLE HiiHandle;
|
|
FORM_BROWSER_FORMSET *ImportFormSet;
|
|
|
|
HiiHandle = HiiGetHiiHandleByFormSetGuid (ImportFormsetGuid);
|
|
if (HiiHandle == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
ImportFormSet = AllocateZeroPool (sizeof (FORM_BROWSER_FORMSET));
|
|
if (ImportFormSet == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
Status = InitializeFormSet (HiiHandle, ImportFormsetGuid, ImportFormSet);
|
|
if (EFI_ERROR (Status) || IsListEmpty (&ImportFormSet->FormListHead)) {
|
|
DestroyFormSet (ImportFormSet);
|
|
return NULL;
|
|
}
|
|
InsertTailList (&mH2OBrowserImportFormSetList, &ImportFormSet->Link);
|
|
|
|
//
|
|
// Remove imported formset from mFBPrivate.FormSetList because it may has duplicate formset in list.
|
|
//
|
|
RemoveEntryList (&ImportFormSet->DisplayLink);
|
|
InitializeListHead (&ImportFormSet->DisplayLink);
|
|
|
|
return ImportFormSet;
|
|
}
|
|
|
|
/**
|
|
Create imported formset storage.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcFormSetStorage Pointer to source formset storage.
|
|
@param[in, out] DstFormSet Pointer to destination formset.
|
|
|
|
@return Formset storage pointer or NULL if fail to allocate pool.
|
|
**/
|
|
FORMSET_STORAGE *
|
|
CreateImportStorage (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORMSET_STORAGE *SrcFormSetStorage,
|
|
IN OUT FORM_BROWSER_FORMSET *DstFormSet
|
|
)
|
|
{
|
|
FORMSET_STORAGE *DstFormSetStorage;
|
|
BROWSER_STORAGE *SrcBrowserStorage;
|
|
|
|
DstFormSetStorage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
|
|
if (DstFormSetStorage == NULL) {
|
|
return NULL;
|
|
}
|
|
DstFormSetStorage->Signature = FORMSET_STORAGE_SIGNATURE;
|
|
InsertTailList (&DstFormSet->StorageListHead, &DstFormSetStorage->Link);
|
|
|
|
SrcBrowserStorage = SrcFormSetStorage->BrowserStorage;
|
|
DstFormSetStorage->BrowserStorage = SrcBrowserStorage;
|
|
DstFormSetStorage->ConfigRequest = AllocateCopyPool (StrSize (SrcBrowserStorage->ConfigHdr), SrcBrowserStorage->ConfigHdr);
|
|
DstFormSetStorage->SpareStrLen = 0;
|
|
DstFormSetStorage->VarStoreId = GetAvailableVarstoreId (DstFormSet);;
|
|
|
|
return DstFormSetStorage;
|
|
}
|
|
|
|
/**
|
|
Create statement with disableif TRUE expression in last form of formset.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcStatement Pointer to source statement.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
|
|
@return Statement pointer or NULL if invalid parameter or fail to get question info.
|
|
**/
|
|
FORM_BROWSER_STATEMENT *
|
|
CreateDisabledStatementInLastForm (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORM_BROWSER_STATEMENT *SrcStatement,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORMSET_STORAGE *SrcStorage;
|
|
FORM_BROWSER_FORM *DstLastForm;
|
|
FORM_BROWSER_STATEMENT *DstStatement;
|
|
FORMSET_STORAGE *DstStorage;
|
|
|
|
if (SrcFormSet == NULL || SrcStatement == NULL || DstFormSet == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
SrcStorage = GetStorageByQuestion (SrcFormSet, SrcStatement);
|
|
if (SrcStorage == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (IsListEmpty (&DstFormSet->FormListHead)) {
|
|
return NULL;
|
|
}
|
|
|
|
DstLastForm = NULL;
|
|
Link = GetFirstNode (&DstFormSet->FormListHead);
|
|
while (!IsNull (&DstFormSet->FormListHead, Link)) {
|
|
DstLastForm = FORM_BROWSER_FORM_FROM_LINK (Link);
|
|
Link = GetNextNode (&DstFormSet->FormListHead, Link);
|
|
}
|
|
if (DstLastForm == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
DstStatement = GetNewStatement (DstFormSet);
|
|
if (DstStatement == NULL) {
|
|
return NULL;
|
|
}
|
|
DstStatement->StatementId = mImportStatementId++;
|
|
|
|
//
|
|
// Copy Statement info
|
|
//
|
|
InitializeListHead (&DstStatement->DefaultListHead);
|
|
InitializeListHead (&DstStatement->OptionListHead);
|
|
InitializeListHead (&DstStatement->InconsistentListHead);
|
|
InitializeListHead (&DstStatement->NoSubmitListHead);
|
|
InitializeListHead (&DstStatement->WarningListHead);
|
|
InitializeListHead (&DstStatement->PropertyListHead);
|
|
|
|
DstStatement->Signature = SrcStatement->Signature;
|
|
DstStatement->Operand = SrcStatement->Operand;
|
|
DstStatement->OpCode = SrcStatement->OpCode;
|
|
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcStatement->Prompt, DstFormSet->HiiHandle, &DstStatement->Prompt);
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcStatement->Help , DstFormSet->HiiHandle, &DstStatement->Help);
|
|
|
|
DstStatement->Expression = AllocateZeroPool (sizeof(FORM_EXPRESSION_LIST));
|
|
if (DstStatement->Expression == NULL) {
|
|
return NULL;
|
|
}
|
|
DstStatement->Expression->Count = 1;
|
|
DstStatement->Expression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
|
|
DstStatement->Expression->Expression[0] = CreateDisableIfExpression (GetNewExpressionOpCode (DstFormSet));
|
|
if (DstStatement->Expression->Expression[0] == NULL) {
|
|
return NULL;
|
|
}
|
|
InsertTailList (&DstLastForm->ExpressionListHead, &DstStatement->Expression->Expression[0]->Link);
|
|
|
|
//
|
|
// Copy Question info
|
|
//
|
|
DstStatement->QuestionId = GetAvailableQuestionId (DstFormSet);
|
|
DstStatement->VarStoreInfo.VarOffset = SrcStatement->VarStoreInfo.VarOffset;
|
|
DstStatement->QuestionFlags = SrcStatement->QuestionFlags;
|
|
|
|
if (SrcStatement->VarStoreId != 0) {
|
|
DstStorage = GetFormSetStorage (DstFormSet, SrcStorage->BrowserStorage);
|
|
if (DstStorage == NULL) {
|
|
DstStorage = CreateImportStorage (SrcFormSet, SrcStorage, DstFormSet);
|
|
}
|
|
if (DstStorage == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
DstStatement->Storage = DstStorage->BrowserStorage;
|
|
DstStatement->VarStoreId = DstStorage->VarStoreId;
|
|
}
|
|
|
|
//
|
|
// Copy Question HII Value info
|
|
//
|
|
switch (SrcStatement->Operand) {
|
|
|
|
case EFI_IFR_REF_OP:
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_REF;
|
|
|
|
if (SrcStatement->HiiValue.Value.ref.DevicePath != 0) {
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcStatement->HiiValue.Value.ref.DevicePath, DstFormSet->HiiHandle, &DstStatement->HiiValue.Value.ref.DevicePath);
|
|
}
|
|
|
|
CopyMem (
|
|
&DstStatement->HiiValue.Value.ref.FormSetGuid,
|
|
&SrcStatement->HiiValue.Value.ref.FormSetGuid,
|
|
sizeof (EFI_GUID)
|
|
);
|
|
|
|
if (DstStatement->HiiValue.Value.ref.DevicePath == 0 && CompareGuid (&DstStatement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {
|
|
//
|
|
// Originally, it is going into form or question in self formset.
|
|
// But here, it should use REF3 to describe.
|
|
//
|
|
CopyMem (
|
|
&DstStatement->HiiValue.Value.ref.FormSetGuid,
|
|
&SrcFormSet->Guid,
|
|
sizeof (EFI_GUID)
|
|
);
|
|
}
|
|
DstStatement->HiiValue.Value.ref.FormId = SrcStatement->HiiValue.Value.ref.FormId;
|
|
DstStatement->HiiValue.Value.ref.QuestionId = SrcStatement->HiiValue.Value.ref.QuestionId;
|
|
|
|
DstStatement->StorageWidth = SrcStatement->StorageWidth;
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstLastForm);
|
|
break;
|
|
|
|
case EFI_IFR_STRING_OP:
|
|
case EFI_IFR_PASSWORD_OP:
|
|
DstStatement->Minimum = SrcStatement->Minimum;
|
|
DstStatement->Maximum = SrcStatement->Maximum;
|
|
DstStatement->StorageWidth = SrcStatement->StorageWidth;
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
|
|
DstStatement->BufferValue = AllocateZeroPool (DstStatement->StorageWidth + sizeof (CHAR16));
|
|
DstStatement->HiiValue.Value.string = NewString ((CHAR16*) DstStatement->BufferValue, DstFormSet->HiiHandle);
|
|
|
|
DstStatement->HiiValue.Buffer = DstStatement->BufferValue;
|
|
DstStatement->HiiValue.BufferLen = DstStatement->StorageWidth + sizeof (CHAR16);
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstLastForm);
|
|
break;
|
|
|
|
case EFI_IFR_CHECKBOX_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstLastForm);
|
|
break;
|
|
|
|
case EFI_IFR_DATE_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
|
|
|
|
if ((DstStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
|
|
DstStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);
|
|
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstLastForm);
|
|
} else {
|
|
//
|
|
// Don't assign storage for RTC type of date/time
|
|
//
|
|
DstStatement->Storage = NULL;
|
|
DstStatement->StorageWidth = 0;
|
|
}
|
|
break;
|
|
|
|
case EFI_IFR_TIME_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
|
|
|
|
if ((DstStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
|
|
DstStatement->StorageWidth = (UINT16) sizeof (EFI_HII_TIME);
|
|
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstLastForm);
|
|
} else {
|
|
//
|
|
// Don't assign storage for RTC type of date/time
|
|
//
|
|
DstStatement->Storage = NULL;
|
|
DstStatement->StorageWidth = 0;
|
|
}
|
|
break;
|
|
|
|
case EFI_IFR_ONE_OF_OP:
|
|
case EFI_IFR_NUMERIC_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->Minimum = SrcStatement->Minimum;
|
|
DstStatement->Maximum = SrcStatement->Maximum;
|
|
DstStatement->Step = SrcStatement->Step;
|
|
DstStatement->StorageWidth = SrcStatement->StorageWidth;
|
|
DstStatement->HiiValue.Type = SrcStatement->HiiValue.Type;
|
|
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstLastForm);
|
|
break;
|
|
|
|
case EFI_IFR_ORDERED_LIST_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->MaxContainers = SrcStatement->MaxContainers;
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
|
|
DstStatement->BufferValue = NULL;
|
|
|
|
if (SrcStatement->BufferValue != NULL) {
|
|
DstStatement->StorageWidth = SrcStatement->StorageWidth;
|
|
DstStatement->BufferValue = AllocateZeroPool (SrcStatement->StorageWidth);
|
|
DstStatement->ValueType = SrcStatement->ValueType;
|
|
if (DstStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
|
|
DstStatement->HiiValue.Buffer = DstStatement->BufferValue;
|
|
DstStatement->HiiValue.BufferLen = DstStatement->StorageWidth;
|
|
}
|
|
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstLastForm);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DstStatement->ImportInfo = AllocateZeroPool (sizeof (FB_IMPORT_INFO));
|
|
if (DstStatement->ImportInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
DstStatement->ImportInfo->SrcFormSet = SrcFormSet;
|
|
DstStatement->ImportInfo->SrcForm = GetFormByQuestionId(SrcFormSet, SrcStatement->QuestionId);
|
|
DstStatement->ImportInfo->SrcStatement = SrcStatement;
|
|
|
|
InsertTailList (&DstLastForm->StatementListHead, &DstStatement->Link);
|
|
DstLastForm->NumberOfStatement++;
|
|
|
|
return DstStatement;
|
|
}
|
|
|
|
/**
|
|
Copy expression opcode.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcExpressionOpCode Pointer to source expression opcode.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
@param[in] DstForm Pointer to destination form.
|
|
@param[in] DstExpressionOpCode Pointer to destination expression opcode.
|
|
|
|
@retval EFI_SUCCESS Successfully copy expression opcode
|
|
@retval EFI_INVALID_PARAMETER Input parameter is NULL
|
|
@retval EFI_NOT_FOUND Fail to find source expression data
|
|
**/
|
|
EFI_STATUS
|
|
CopyExpressionOpCode (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN EXPRESSION_OPCODE *SrcExpressionOpCode,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN FORM_BROWSER_FORM *DstForm,
|
|
OUT EXPRESSION_OPCODE *DstExpressionOpCode
|
|
)
|
|
{
|
|
FORM_BROWSER_STATEMENT *SrcStatement;
|
|
FORM_BROWSER_STATEMENT *SrcStatement2;
|
|
EFI_QUESTION_ID DstQuestionId;
|
|
EFI_QUESTION_ID DstQuestionId2;
|
|
FORMSET_STORAGE *DstStorage;
|
|
FORMSET_STORAGE *SrcStorage;
|
|
LIST_ENTRY *Link;
|
|
FORM_EXPRESSION *SrcSubExpression;
|
|
FORM_EXPRESSION *DstSubExpression;
|
|
EFI_STATUS Status;
|
|
|
|
if (SrcFormSet == NULL || SrcExpressionOpCode == NULL || DstFormSet == NULL || DstForm == NULL || DstExpressionOpCode == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
DstQuestionId = 0;
|
|
DstQuestionId2 = 0;
|
|
|
|
if (SrcExpressionOpCode->QuestionId != 0) {
|
|
SrcStatement = GetStatementByQuestionId (SrcFormSet, NULL, SrcExpressionOpCode->QuestionId);
|
|
if (SrcStatement == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
DstQuestionId = GetQuestionIdBySrcStatement (SrcFormSet, SrcStatement, DstFormSet);
|
|
if (DstQuestionId == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
if (SrcExpressionOpCode->QuestionId2 != 0) {
|
|
SrcStatement2 = GetStatementByQuestionId (SrcFormSet, NULL, SrcExpressionOpCode->QuestionId2);
|
|
if (SrcStatement2 == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
DstQuestionId2 = GetQuestionIdBySrcStatement (SrcFormSet, SrcStatement2, DstFormSet);
|
|
if (DstQuestionId2 == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
}
|
|
|
|
CopyMem (DstExpressionOpCode, SrcExpressionOpCode, sizeof (EXPRESSION_OPCODE));
|
|
|
|
switch (SrcExpressionOpCode->Operand) {
|
|
|
|
case EFI_IFR_EQ_ID_VAL_OP:
|
|
if (SrcFormSet->HiiHandle == DstFormSet->HiiHandle) {
|
|
break;
|
|
}
|
|
DstExpressionOpCode->QuestionId = DstQuestionId;
|
|
break;
|
|
|
|
case EFI_IFR_EQ_ID_ID_OP:
|
|
DstExpressionOpCode->QuestionId = DstQuestionId;
|
|
DstExpressionOpCode->QuestionId2 = DstQuestionId2;
|
|
break;
|
|
|
|
case EFI_IFR_EQ_ID_VAL_LIST_OP:
|
|
DstExpressionOpCode->QuestionId = DstQuestionId;
|
|
DstExpressionOpCode->ValueList = AllocateCopyPool (SrcExpressionOpCode->ListLength * sizeof (UINT16), SrcExpressionOpCode->ValueList);
|
|
break;
|
|
|
|
case EFI_IFR_TO_STRING_OP:
|
|
case EFI_IFR_FIND_OP:
|
|
break;
|
|
|
|
case EFI_IFR_STRING_REF1_OP:
|
|
Status = CopyHiiString (SrcFormSet->HiiHandle, SrcExpressionOpCode->Value.Value.string, DstFormSet->HiiHandle, &DstExpressionOpCode->Value.Value.string);
|
|
if (EFI_ERROR (Status)) {
|
|
DstExpressionOpCode->Value.Value.string = 0;
|
|
}
|
|
break;
|
|
|
|
case EFI_IFR_RULE_REF_OP:
|
|
case EFI_IFR_SPAN_OP:
|
|
break;
|
|
|
|
case EFI_IFR_THIS_OP:
|
|
DstExpressionOpCode->QuestionId = DstQuestionId;
|
|
break;
|
|
|
|
case EFI_IFR_SECURITY_OP:
|
|
break;
|
|
|
|
case EFI_IFR_GET_OP:
|
|
case EFI_IFR_SET_OP:
|
|
if (SrcExpressionOpCode->VarStorage == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
DstStorage = GetFormSetStorage (DstFormSet, SrcExpressionOpCode->VarStorage);
|
|
if (DstStorage == NULL) {
|
|
if (SrcFormSet->StorageListHead.ForwardLink != NULL) {
|
|
Link = GetFirstNode (&SrcFormSet->StorageListHead);
|
|
while (!IsNull (&SrcFormSet->StorageListHead, Link)) {
|
|
SrcStorage = FORMSET_STORAGE_FROM_LINK (Link);
|
|
if ((UINTN) SrcStorage->BrowserStorage == (UINTN) SrcExpressionOpCode->VarStorage) {
|
|
DstStorage = CreateImportStorage (SrcFormSet, SrcStorage, DstFormSet);
|
|
break;
|
|
}
|
|
Link = GetNextNode (&SrcFormSet->StorageListHead, Link);
|
|
}
|
|
}
|
|
|
|
}
|
|
if (DstStorage == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
DstExpressionOpCode->VarStorage = DstStorage->BrowserStorage;
|
|
|
|
if (SrcExpressionOpCode->VarStoreInfo.VarName != 0) {
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcExpressionOpCode->VarStoreInfo.VarName, DstFormSet->HiiHandle, &DstExpressionOpCode->VarStoreInfo.VarName);
|
|
}
|
|
if (SrcExpressionOpCode->ValueName != NULL) {
|
|
DstExpressionOpCode->ValueName = AllocateCopyPool (StrSize (SrcExpressionOpCode->ValueName), SrcExpressionOpCode->ValueName);
|
|
}
|
|
break;
|
|
|
|
case EFI_IFR_QUESTION_REF1_OP:
|
|
DstExpressionOpCode->QuestionId = DstQuestionId;
|
|
break;
|
|
|
|
|
|
case EFI_IFR_QUESTION_REF3_OP:
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcExpressionOpCode->DevicePath, DstFormSet->HiiHandle, &DstExpressionOpCode->DevicePath);
|
|
break;
|
|
|
|
case EFI_IFR_TRUE_OP:
|
|
case EFI_IFR_FALSE_OP:
|
|
case EFI_IFR_ONE_OP:
|
|
case EFI_IFR_ZERO_OP:
|
|
case EFI_IFR_ONES_OP:
|
|
case EFI_IFR_UINT8_OP:
|
|
case EFI_IFR_UINT16_OP:
|
|
case EFI_IFR_UINT32_OP:
|
|
case EFI_IFR_UINT64_OP:
|
|
case EFI_IFR_UNDEFINED_OP:
|
|
case EFI_IFR_VERSION_OP:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (SrcExpressionOpCode->MapExpressionList.ForwardLink != NULL &&
|
|
SrcExpressionOpCode->MapExpressionList.BackLink != NULL &&
|
|
!IsListEmpty (&SrcExpressionOpCode->MapExpressionList)) {
|
|
InitializeListHead (&DstExpressionOpCode->MapExpressionList);
|
|
|
|
Link = GetFirstNode(&SrcExpressionOpCode->MapExpressionList);
|
|
while (!IsNull (&SrcExpressionOpCode->MapExpressionList, Link)) {
|
|
SrcSubExpression = FORM_EXPRESSION_FROM_LINK (Link);
|
|
Link = GetNextNode (&SrcExpressionOpCode->MapExpressionList, Link);
|
|
|
|
Status = CopyExpression (
|
|
SrcFormSet,
|
|
SrcSubExpression,
|
|
DstFormSet,
|
|
DstForm,
|
|
&DstSubExpression
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
InsertTailList (&DstExpressionOpCode->MapExpressionList, &DstSubExpression->Link);
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Copy expression.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcExpression Pointer to source expression.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
@param[in] DstForm Pointer to destination form.
|
|
@param[in] DstExpression Double pointer to destination expression.
|
|
|
|
@retval EFI_SUCCESS Successfully copy expression
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool
|
|
**/
|
|
EFI_STATUS
|
|
CopyExpression (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORM_EXPRESSION *SrcExpression,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN FORM_BROWSER_FORM *DstForm,
|
|
IN OUT FORM_EXPRESSION **DstExpression
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORM_EXPRESSION *Expression;
|
|
EXPRESSION_OPCODE *SrcExpressionOpCode;
|
|
EXPRESSION_OPCODE *DstExpressionOpCode;
|
|
EFI_STATUS Status;
|
|
|
|
Expression = AllocateCopyPool (sizeof (FORM_EXPRESSION), SrcExpression);
|
|
if (Expression == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
InitializeListHead (&Expression->OpCodeListHead);
|
|
if (SrcExpression->Error != 0) {
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcExpression->Error, DstFormSet->HiiHandle, &Expression->Error);
|
|
}
|
|
|
|
Link = GetFirstNode (&SrcExpression->OpCodeListHead);
|
|
while (!IsNull (&SrcExpression->OpCodeListHead, Link)) {
|
|
SrcExpressionOpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
|
|
Link = GetNextNode (&SrcExpression->OpCodeListHead, Link);
|
|
|
|
DstExpressionOpCode = GetNewExpressionOpCode (DstFormSet);
|
|
if (DstExpressionOpCode == NULL) {
|
|
continue;
|
|
}
|
|
Status = CopyExpressionOpCode (SrcFormSet, SrcExpressionOpCode, DstFormSet, DstForm, DstExpressionOpCode);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
InsertTailList (&Expression->OpCodeListHead, &DstExpressionOpCode->Link);
|
|
}
|
|
|
|
*DstExpression = Expression;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Copy default list of statement.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcStatement Pointer to source statement.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
@param[in] DstForm Pointer to destination form.
|
|
@param[in] DstStatement Pointer to destination statement.
|
|
|
|
@retval EFI_SUCCESS Successfully copy default list
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool
|
|
**/
|
|
EFI_STATUS
|
|
CopyDefaultList (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORM_BROWSER_STATEMENT *SrcStatement,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN FORM_BROWSER_FORM *DstForm,
|
|
IN OUT FORM_BROWSER_STATEMENT *DstStatement
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
QUESTION_DEFAULT *SrcDefault;
|
|
QUESTION_DEFAULT *DstDefault;
|
|
|
|
Link = GetFirstNode (&SrcStatement->DefaultListHead);
|
|
while (!IsNull (&SrcStatement->DefaultListHead, Link)) {
|
|
SrcDefault = QUESTION_DEFAULT_FROM_LINK (Link);
|
|
Link = GetNextNode (&SrcStatement->DefaultListHead, Link);
|
|
|
|
DstDefault = AllocateCopyPool (sizeof (QUESTION_DEFAULT), SrcDefault);
|
|
if (DstDefault == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
if (SrcDefault->ValueExpression != NULL) {
|
|
CopyExpression (SrcFormSet, SrcDefault->ValueExpression, DstFormSet, DstForm, &DstDefault->ValueExpression);
|
|
InsertTailList (&DstForm->ExpressionListHead, &DstDefault->ValueExpression->Link);
|
|
}
|
|
|
|
InsertTailList (&DstStatement->DefaultListHead, &DstDefault->Link);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Copy common expression list (inconsistent/warningif/nosubmitif) of statement.
|
|
|
|
@param[in] Type Expression type.
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcStatement Pointer to source statement.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
@param[in] DstForm Pointer to destination form.
|
|
@param[in] DstStatement Pointer to destination statement.
|
|
|
|
@retval EFI_SUCCESS Successfully copy common expression list
|
|
@retval EFI_UNSUPPORTED Unexpected expression type
|
|
@retval Other Fail to copy expression
|
|
**/
|
|
EFI_STATUS
|
|
CopyCommonListByType (
|
|
IN UINT32 Type,
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORM_BROWSER_STATEMENT *SrcStatement,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN FORM_BROWSER_FORM *DstForm,
|
|
IN OUT FORM_BROWSER_STATEMENT *DstStatement
|
|
)
|
|
{
|
|
LIST_ENTRY *SrcListHead;
|
|
LIST_ENTRY *DstListHead;
|
|
LIST_ENTRY *Link;
|
|
FORM_EXPRESSION *SrcExpression;
|
|
FORM_EXPRESSION *DstExpression;
|
|
EFI_STATUS Status;
|
|
|
|
switch (Type) {
|
|
|
|
case EFI_HII_EXPRESSION_INCONSISTENT_IF:
|
|
SrcListHead = &SrcStatement->InconsistentListHead;
|
|
DstListHead = &DstStatement->InconsistentListHead;
|
|
break;
|
|
|
|
case EFI_HII_EXPRESSION_WARNING_IF:
|
|
SrcListHead = &SrcStatement->WarningListHead;
|
|
DstListHead = &DstStatement->WarningListHead;
|
|
break;
|
|
|
|
case EFI_HII_EXPRESSION_NO_SUBMIT_IF:
|
|
SrcListHead = &SrcStatement->NoSubmitListHead;
|
|
DstListHead = &DstStatement->NoSubmitListHead;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Link = GetFirstNode (SrcListHead);
|
|
while (!IsNull (SrcListHead, Link)) {
|
|
SrcExpression = FORM_EXPRESSION_FROM_LINK (Link);
|
|
Link = GetNextNode (SrcListHead, Link);
|
|
|
|
Status = CopyExpression (SrcFormSet, SrcExpression, DstFormSet, DstForm, &DstExpression);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
InsertTailList (DstListHead, &DstExpression->Link);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Copy options of statement.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcStatement Pointer to source statement.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
@param[in] DstForm Pointer to destination form.
|
|
@param[in] DstStatement Pointer to destination statement.
|
|
|
|
@retval EFI_SUCCESS Successfully copy options
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool
|
|
**/
|
|
EFI_STATUS
|
|
CopyOptions (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORM_BROWSER_STATEMENT *SrcStatement,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN FORM_BROWSER_FORM *DstForm,
|
|
IN OUT FORM_BROWSER_STATEMENT *DstStatement
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
QUESTION_OPTION *SrcOption;
|
|
QUESTION_OPTION *DstOption;
|
|
UINTN Index;
|
|
|
|
DstStatement->NumberOfOptions = 0;
|
|
InitializeListHead (&DstStatement->OptionListHead);
|
|
|
|
Link = GetFirstNode (&SrcStatement->OptionListHead);
|
|
while (!IsNull (&SrcStatement->OptionListHead, Link)) {
|
|
SrcOption = QUESTION_OPTION_FROM_LINK (Link);
|
|
Link = GetNextNode (&SrcStatement->OptionListHead, Link);
|
|
|
|
DstOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
|
|
if (DstOption == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
DstOption->Signature = SrcOption->Signature;
|
|
DstOption->OpCode = SrcOption->OpCode;
|
|
DstOption->Flags = SrcOption->Flags;
|
|
DstOption->Value.Type = SrcOption->Value.Type;
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcOption->Text, DstFormSet->HiiHandle, &DstOption->Text);
|
|
CopyMem (&DstOption->Value.Value, &SrcOption->Value.Value, sizeof (EFI_IFR_TYPE_VALUE));
|
|
ExtendValueToU64 (&DstOption->Value);
|
|
InitializeListHead (&DstOption->PropertyListHead);
|
|
|
|
if (SrcOption->ImageId != 0) {
|
|
CopyHiiImage (SrcFormSet->HiiHandle, SrcOption->ImageId, DstFormSet->HiiHandle, &DstOption->ImageId);
|
|
}
|
|
|
|
if (SrcOption->SuppressExpression != NULL) {
|
|
DstOption->SuppressExpression = AllocateCopyPool(
|
|
(UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((SrcOption->SuppressExpression->Count -1) * sizeof(FORM_EXPRESSION *))),
|
|
SrcOption->SuppressExpression
|
|
);
|
|
if (DstOption->SuppressExpression == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
for (Index = 0; Index < SrcOption->SuppressExpression->Count; Index++) {
|
|
CopyExpression (
|
|
SrcFormSet,
|
|
SrcOption->SuppressExpression->Expression[Index],
|
|
DstFormSet,
|
|
DstForm,
|
|
&DstOption->SuppressExpression->Expression[Index]
|
|
);
|
|
InsertTailList (&DstForm->ExpressionListHead, &DstOption->SuppressExpression->Expression[Index]->Link);
|
|
}
|
|
}
|
|
|
|
|
|
DstStatement->NumberOfOptions++;
|
|
InsertTailList (&DstStatement->OptionListHead, &DstOption->Link);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Copy statement.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcForm Pointer to source form.
|
|
@param[in] SrcStatement Pointer to source statement.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
@param[in] DstForm Pointer to destination form.
|
|
@param[in] DstStatement Pointer to destination statement.
|
|
|
|
@retval EFI_SUCCESS Successfully copy statement
|
|
@retval EFI_INVALID_PARAMETER Input parameter is NULL
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate pool
|
|
**/
|
|
EFI_STATUS
|
|
CopyStatement (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORM_BROWSER_FORM *SrcForm,
|
|
IN FORM_BROWSER_STATEMENT *SrcStatement,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN FORM_BROWSER_FORM *DstForm,
|
|
OUT FORM_BROWSER_STATEMENT *DstStatement
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
if (SrcFormSet == NULL || SrcStatement == NULL || DstFormSet == NULL || DstStatement == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
InitializeListHead (&DstStatement->DefaultListHead);
|
|
InitializeListHead (&DstStatement->OptionListHead);
|
|
InitializeListHead (&DstStatement->InconsistentListHead);
|
|
InitializeListHead (&DstStatement->NoSubmitListHead);
|
|
InitializeListHead (&DstStatement->WarningListHead);
|
|
InitializeListHead (&DstStatement->PropertyListHead);
|
|
|
|
DstStatement->Signature = SrcStatement->Signature;
|
|
DstStatement->Operand = SrcStatement->Operand;
|
|
DstStatement->OpCode = SrcStatement->OpCode;
|
|
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcStatement->Prompt, DstFormSet->HiiHandle, &DstStatement->Prompt);
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcStatement->Help , DstFormSet->HiiHandle, &DstStatement->Help);
|
|
|
|
DstStatement->RefreshInterval = SrcStatement->RefreshInterval;
|
|
CopyMem (&DstStatement->RefreshGuid, &SrcStatement->RefreshGuid, sizeof (EFI_GUID));
|
|
DstStatement->Locked = SrcStatement->Locked;
|
|
|
|
if (SrcStatement->TextTwo != 0) {
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcStatement->TextTwo, DstFormSet->HiiHandle, &DstStatement->TextTwo);
|
|
}
|
|
|
|
if (SrcStatement->ImageId != 0) {
|
|
CopyHiiImage (SrcFormSet->HiiHandle, SrcStatement->ImageId, DstFormSet->HiiHandle, &DstStatement->ImageId);
|
|
}
|
|
|
|
if (!IsListEmpty (&SrcStatement->DefaultListHead)) {
|
|
CopyDefaultList (SrcFormSet, SrcStatement, DstFormSet, DstForm, DstStatement);
|
|
}
|
|
CopyCommonListByType (EFI_HII_EXPRESSION_INCONSISTENT_IF, SrcFormSet, SrcStatement, DstFormSet, DstForm, DstStatement);
|
|
CopyCommonListByType (EFI_HII_EXPRESSION_NO_SUBMIT_IF , SrcFormSet, SrcStatement, DstFormSet, DstForm, DstStatement);
|
|
CopyCommonListByType (EFI_HII_EXPRESSION_WARNING_IF , SrcFormSet, SrcStatement, DstFormSet, DstForm, DstStatement);
|
|
if (SrcStatement->ReadExpression != NULL) {
|
|
CopyExpression (SrcFormSet, SrcStatement->ReadExpression, DstFormSet, DstForm, &DstStatement->ReadExpression);
|
|
InsertTailList (&DstForm->ExpressionListHead, &DstStatement->ReadExpression->Link);
|
|
}
|
|
if (SrcStatement->WriteExpression != NULL) {
|
|
CopyExpression (SrcFormSet, SrcStatement->WriteExpression, DstFormSet, DstForm, &DstStatement->WriteExpression);
|
|
InsertTailList (&DstForm->ExpressionListHead, &DstStatement->WriteExpression->Link);
|
|
}
|
|
if (SrcStatement->ValueExpression != NULL) {
|
|
CopyExpression (SrcFormSet, SrcStatement->ValueExpression, DstFormSet, DstForm, &DstStatement->ValueExpression);
|
|
InsertTailList (&DstForm->ExpressionListHead, &DstStatement->ValueExpression->Link);
|
|
}
|
|
if (SrcStatement->Expression != NULL) {
|
|
DstStatement->Expression = AllocateCopyPool (
|
|
(UINTN) (sizeof(FORM_EXPRESSION_LIST) + ((SrcStatement->Expression->Count - 1) * sizeof(FORM_EXPRESSION *))),
|
|
SrcStatement->Expression
|
|
);
|
|
if (DstStatement->Expression == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
for (Index = 0; Index < SrcStatement->Expression->Count; Index++) {
|
|
CopyExpression (
|
|
SrcFormSet,
|
|
SrcStatement->Expression->Expression[Index],
|
|
DstFormSet,
|
|
DstForm,
|
|
&DstStatement->Expression->Expression[Index]
|
|
);
|
|
InsertTailList (&DstForm->ExpressionListHead, &DstStatement->Expression->Expression[Index]->Link);
|
|
}
|
|
}
|
|
|
|
DstStatement->ImportInfo = AllocateZeroPool (sizeof (FB_IMPORT_INFO));
|
|
if (DstStatement->ImportInfo != NULL) {
|
|
DstStatement->ImportInfo->SrcFormSet = SrcFormSet;
|
|
DstStatement->ImportInfo->SrcForm = SrcForm;
|
|
DstStatement->ImportInfo->SrcStatement = SrcStatement;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Copy question.
|
|
|
|
@param[in] SrcFormSet Pointer to source formset.
|
|
@param[in] SrcForm Pointer to source form.
|
|
@param[in] SrcStatement Pointer to source statement.
|
|
@param[in] SrcStorage Pointer to source formset storage.
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
@param[in] DstForm Pointer to destination form.
|
|
@param[in] DstStatement Pointer to destination statement.
|
|
|
|
@retval EFI_SUCCESS Successfully copy question
|
|
@retval EFI_INVALID_PARAMETER Input parameter is NULL
|
|
@retval EFI_ABORTED Fail to create formset storage
|
|
@retval Other Fail to create statement
|
|
**/
|
|
EFI_STATUS
|
|
CopyQuestion (
|
|
IN FORM_BROWSER_FORMSET *SrcFormSet,
|
|
IN FORM_BROWSER_FORM *SrcForm,
|
|
IN FORM_BROWSER_STATEMENT *SrcStatement,
|
|
IN FORMSET_STORAGE *SrcStorage,
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN FORM_BROWSER_FORM *DstForm,
|
|
OUT FORM_BROWSER_STATEMENT *DstStatement
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
FORMSET_STORAGE *DstStorage;
|
|
NAME_VALUE_NODE *NameValueNode;
|
|
|
|
if (SrcFormSet == NULL || SrcStatement == NULL || DstFormSet == NULL || DstStatement == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = CopyStatement (
|
|
SrcFormSet,
|
|
SrcForm,
|
|
SrcStatement,
|
|
DstFormSet,
|
|
DstForm,
|
|
DstStatement
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
DstStatement->QuestionId = SrcStatement->QuestionId;
|
|
DstStatement->VarStoreInfo.VarOffset = SrcStatement->VarStoreInfo.VarOffset;
|
|
DstStatement->QuestionFlags = SrcStatement->QuestionFlags;
|
|
|
|
if (SrcStatement->VarStoreId == 0) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
DstStorage = GetFormSetStorage (DstFormSet, SrcStorage->BrowserStorage);
|
|
if (DstStorage == NULL) {
|
|
DstStorage = CreateImportStorage (SrcFormSet, SrcStorage, DstFormSet);
|
|
}
|
|
if (DstStorage == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
DstStatement->Storage = DstStorage->BrowserStorage;
|
|
DstStatement->VarStoreId = DstStorage->VarStoreId;
|
|
|
|
//
|
|
// Initialize varname for Name/Value or EFI Variable
|
|
//
|
|
if ((DstStatement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
|
|
(DstStatement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
|
|
DstStatement->VariableName = GetString (SrcStatement->VarStoreInfo.VarName, SrcFormSet->HiiHandle);
|
|
ASSERT (DstStatement->VariableName != NULL);
|
|
if (DstStatement->VariableName == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
if (DstStatement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
|
|
if (!IsNameValueNodeExistence (&DstStatement->Storage->NameValueListHead, DstStatement->VariableName)) {
|
|
//
|
|
// Insert to Name/Value varstore list
|
|
//
|
|
NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
|
|
ASSERT (NameValueNode != NULL);
|
|
if (NameValueNode == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
|
|
NameValueNode->Name = AllocateCopyPool (StrSize (DstStatement->VariableName), DstStatement->VariableName);
|
|
ASSERT (NameValueNode->Name != NULL);
|
|
NameValueNode->Value = AllocateZeroPool (0x10);
|
|
ASSERT (NameValueNode->Value != NULL);
|
|
NameValueNode->EditValue = AllocateZeroPool (0x10);
|
|
ASSERT (NameValueNode->EditValue != NULL);
|
|
|
|
InsertTailList (&DstStatement->Storage->NameValueListHead, &NameValueNode->Link);
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Check if question ID of import question is conflict in destination formset.
|
|
|
|
@param[in] DstFormSet Pointer to destination formset.
|
|
@param[in] ImportInfo Pointer to import info.
|
|
|
|
@retval TRUE Question ID of import question is conflict in destination formset.
|
|
@retval FALSE Question ID of import question is not conflict in destination formset.
|
|
**/
|
|
BOOLEAN
|
|
IsIdConflict (
|
|
IN FORM_BROWSER_FORMSET *DstFormSet,
|
|
IN IMPORT_INFO *ImportInfo
|
|
)
|
|
{
|
|
if (DstFormSet == NULL || ImportInfo == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (IMPORT_INFO_FLAG_IS_QUESTION (ImportInfo->Flags)) {
|
|
if ((ImportInfo->DstId == 0 && GetStatementByQuestionId (DstFormSet, NULL, ImportInfo->SrcId) != NULL && !CompareGuid (&ImportInfo->SrcFormSetGuid, &DstFormSet->Guid)) ||
|
|
(ImportInfo->DstId != 0 &&
|
|
ImportInfo->DstId != 0xFFFF &&
|
|
GetStatementByQuestionId (DstFormSet, NULL, ImportInfo->DstId) != NULL)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Get formset HII resource by formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@return Formset HII resource pointer or NULL if not found.
|
|
**/
|
|
H2O_FORM_BROWSER_FORMSET_HII_RESOURCE *
|
|
GetFormSetHiiResource (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
H2O_FORM_BROWSER_FORMSET_HII_RESOURCE *FormSetHiiResource;
|
|
|
|
Link = GetFirstNode (&mH2OBrowserFormSetHiiResourceList);
|
|
while (!IsNull (&mH2OBrowserFormSetHiiResourceList, Link)) {
|
|
FormSetHiiResource = H2O_FORM_BROWSER_FORMSET_HII_RESOURCE_FROM_LINK (Link);
|
|
Link = GetNextNode (&mH2OBrowserFormSetHiiResourceList, Link);
|
|
|
|
if (FormSetHiiResource->HiiHandle == FormSet->HiiHandle &&
|
|
CompareGuid (&FormSetHiiResource->FormSetGuid, &FormSet->Guid)) {
|
|
return FormSetHiiResource;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Create formset HII resource by formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@return Formset HII resource pointer or NULL if fail to allocate pool.
|
|
**/
|
|
H2O_FORM_BROWSER_FORMSET_HII_RESOURCE *
|
|
CreateFormSetHiiResource (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
H2O_FORM_BROWSER_FORMSET_HII_RESOURCE *FormSetHiiResource;
|
|
|
|
FormSetHiiResource = AllocateZeroPool (sizeof (H2O_FORM_BROWSER_FORMSET_HII_RESOURCE));
|
|
if (FormSetHiiResource == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
FormSetHiiResource->Signature = H2O_FORM_BROWSER_FORMSET_HII_RESOURCE_SIGNATURE;
|
|
FormSetHiiResource->HiiHandle = FormSet->HiiHandle;
|
|
CopyGuid (&FormSetHiiResource->FormSetGuid, &FormSet->Guid);
|
|
|
|
FormSetHiiResource->NewStringIdCount = 50;
|
|
FormSetHiiResource->NewStringIdList = AllocateZeroPool (FormSetHiiResource->NewStringIdCount * sizeof (EFI_STRING_ID *));
|
|
if (FormSetHiiResource->NewStringIdList == NULL) {
|
|
FormSetHiiResource->NewStringIdCount = 0;
|
|
}
|
|
|
|
FormSetHiiResource->NewImageIdCount = 50;
|
|
FormSetHiiResource->NewImageIdList = AllocateZeroPool (FormSetHiiResource->NewImageIdCount * sizeof (EFI_IMAGE_ID *));
|
|
if (FormSetHiiResource->NewImageIdList == NULL) {
|
|
FormSetHiiResource->NewImageIdCount = 0;
|
|
}
|
|
|
|
InsertTailList (&mH2OBrowserFormSetHiiResourceList, &FormSetHiiResource->Link);
|
|
|
|
return FormSetHiiResource;
|
|
}
|
|
|
|
/**
|
|
Destroy invalid formset HII resource by checkinf HII handle.
|
|
|
|
**/
|
|
VOID
|
|
DestroyFormSetHiiResource (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_HII_HANDLE *HiiHandles;
|
|
LIST_ENTRY *Link;
|
|
H2O_FORM_BROWSER_FORMSET_HII_RESOURCE *FormSetHiiResource;
|
|
UINTN Index;
|
|
|
|
if (IsListEmpty (&mH2OBrowserFormSetHiiResourceList)) {
|
|
return;
|
|
}
|
|
|
|
HiiHandles = HiiGetHiiHandles (NULL);
|
|
if (HiiHandles == NULL) {
|
|
return;
|
|
}
|
|
|
|
Link = GetFirstNode (&mH2OBrowserFormSetHiiResourceList);
|
|
while (!IsNull (&mH2OBrowserFormSetHiiResourceList, Link)) {
|
|
FormSetHiiResource = H2O_FORM_BROWSER_FORMSET_HII_RESOURCE_FROM_LINK (Link);
|
|
Link = GetNextNode (&mH2OBrowserFormSetHiiResourceList, Link);
|
|
|
|
for (Index = 0; HiiHandles[Index] != NULL; Index++) {
|
|
if (HiiHandles[Index] == FormSetHiiResource->HiiHandle) {
|
|
break;
|
|
}
|
|
}
|
|
if (HiiHandles[Index] == NULL) {
|
|
RemoveEntryList (&FormSetHiiResource->Link);
|
|
FBFreePool ((VOID **) &FormSetHiiResource->NewStringIdList);
|
|
FBFreePool ((VOID **) &FormSetHiiResource->NewImageIdList);
|
|
FreePool (FormSetHiiResource);
|
|
}
|
|
}
|
|
|
|
FreePool (HiiHandles);
|
|
}
|
|
|
|
/**
|
|
Destroy all created imported formsets.
|
|
|
|
**/
|
|
VOID
|
|
DestroyImportFormSet (
|
|
VOID
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_FORMSET *OrgFormset;
|
|
FORM_BROWSER_FORMSET *FormSet;
|
|
|
|
if (mImportFormUpdateNotifyHandle != NULL) {
|
|
gHiiDatabase->UnregisterPackageNotify (gHiiDatabase, mImportFormUpdateNotifyHandle);
|
|
mImportFormUpdateNotifyHandle = NULL;
|
|
}
|
|
|
|
OrgFormset = mSystemLevelFormSet;
|
|
Link = GetFirstNode (&mH2OBrowserImportFormSetList);
|
|
while (!IsNull (&mH2OBrowserImportFormSetList, Link)) {
|
|
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
|
Link = GetNextNode (&mH2OBrowserImportFormSetList, Link);
|
|
|
|
mSystemLevelFormSet = FormSet;
|
|
RemoveEntryList (&FormSet->Link);
|
|
DestroyFormSet (FormSet);
|
|
}
|
|
Link = GetFirstNode (&mH2OBrowserStaleImportFormSetList);
|
|
while (!IsNull (&mH2OBrowserStaleImportFormSetList, Link)) {
|
|
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
|
Link = GetNextNode (&mH2OBrowserStaleImportFormSetList, Link);
|
|
|
|
RemoveEntryList (&FormSet->Link);
|
|
DestroyFormSet (FormSet);
|
|
}
|
|
mSystemLevelFormSet = OrgFormset;
|
|
|
|
DestroyFormSetHiiResource ();
|
|
}
|
|
|
|
/**
|
|
Initialize formset HII resource.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@retval EFI_SUCCESS Successfully initialize formset HII resource
|
|
@retval EFI_ABORTED Fail to create formset HII resource
|
|
**/
|
|
EFI_STATUS
|
|
InitializeFormSetHiiResource (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
mFormSetHiiResource = GetFormSetHiiResource (FormSet);
|
|
if (mFormSetHiiResource == NULL) {
|
|
mFormSetHiiResource = CreateFormSetHiiResource (FormSet);
|
|
}
|
|
if (mFormSetHiiResource == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
mFormSetHiiResource->NewStringIdIndex = 0;
|
|
mFormSetHiiResource->NewImageIdIndex = 0;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Remove the import formset data, which is about to be removed in HII database, from list.
|
|
|
|
@param [in] PackageType Package type of the notification.
|
|
@param [in] PackageGuid If PackageType is EFI_HII_PACKAGE_TYPE_GUID, then this is the pointer to the GUID from the Guid
|
|
field of EFI_HII_PACKAGE_GUID_HEADER. Otherwise, it must be NULL.
|
|
@param [in] Package Points to the package referred to by the notification Handle The handle of the package
|
|
list which contains the specified package.
|
|
@param [in] Handle The HII handle.
|
|
@param [in] NotifyType The type of change concerning the database. See EFI_HII_DATABASE_NOTIFY_TYPE.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ImportFormUpdateNotifyFn (
|
|
IN UINT8 PackageType,
|
|
IN CONST EFI_GUID *PackageGuid,
|
|
IN CONST EFI_HII_PACKAGE_HEADER *Package,
|
|
IN EFI_HII_HANDLE Handle,
|
|
IN EFI_HII_DATABASE_NOTIFY_TYPE NotifyType
|
|
)
|
|
{
|
|
LIST_ENTRY *Link;
|
|
FORM_BROWSER_FORMSET *FormSet;
|
|
|
|
Link = GetFirstNode (&mH2OBrowserImportFormSetList);
|
|
while (!IsNull (&mH2OBrowserImportFormSetList, Link)) {
|
|
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (Link);
|
|
Link = GetNextNode (&mH2OBrowserImportFormSetList, Link);
|
|
|
|
if (FormSet->HiiHandle == Handle) {
|
|
RemoveEntryList (&FormSet->Link);
|
|
InsertTailList (&mH2OBrowserStaleImportFormSetList, &FormSet->Link);
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
If there is a stale imported formset, reload the HII formsets which import this stale formset.
|
|
**/
|
|
VOID
|
|
ReloadHiiFormsetWithStaleImportData (
|
|
VOID
|
|
)
|
|
{
|
|
LIST_ENTRY *StaleFormSetLink;
|
|
FORM_BROWSER_FORMSET *StaleFormSet;
|
|
LIST_ENTRY *FormSetLink;
|
|
FORM_BROWSER_FORMSET *FormSet;
|
|
EFI_HII_HANDLE *HandleList;
|
|
UINTN HandleCount;
|
|
|
|
if (IsListEmpty (&mH2OBrowserStaleImportFormSetList)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Record the HiiHandle of formset which import the stale formset.
|
|
//
|
|
HandleList = NULL;
|
|
HandleCount = 0;
|
|
|
|
StaleFormSetLink = GetFirstNode (&mH2OBrowserStaleImportFormSetList);
|
|
while (!IsNull (&mH2OBrowserStaleImportFormSetList, StaleFormSetLink)) {
|
|
StaleFormSet = FORM_BROWSER_FORMSET_FROM_LINK (StaleFormSetLink);
|
|
StaleFormSetLink = GetNextNode (&mH2OBrowserStaleImportFormSetList, StaleFormSetLink);
|
|
|
|
FormSetLink = GetFirstNode (&gBrowserFormSetList);
|
|
while (!IsNull (&gBrowserFormSetList, FormSetLink)) {
|
|
FormSet = FORM_BROWSER_FORMSET_FROM_LINK (FormSetLink);
|
|
FormSetLink = GetNextNode (&gBrowserFormSetList, FormSetLink);
|
|
|
|
if (HaveImportThisFormset (FormSet, StaleFormSet)) {
|
|
HandleList = ReallocatePool (HandleCount * sizeof (EFI_HII_HANDLE), (HandleCount + 1) * sizeof (EFI_HII_HANDLE), HandleList);
|
|
if (HandleList == NULL) {
|
|
return;
|
|
}
|
|
|
|
HandleList[HandleCount++] = FormSet->HiiHandle;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Destroy stale imported formset.
|
|
//
|
|
StaleFormSetLink = GetFirstNode (&mH2OBrowserStaleImportFormSetList);
|
|
while (!IsNull (&mH2OBrowserStaleImportFormSetList, StaleFormSetLink)) {
|
|
StaleFormSet = FORM_BROWSER_FORMSET_FROM_LINK (StaleFormSetLink);
|
|
StaleFormSetLink = GetNextNode (&mH2OBrowserStaleImportFormSetList, StaleFormSetLink);
|
|
|
|
RemoveEntryList (&StaleFormSet->Link);
|
|
DestroyFormSet (StaleFormSet);
|
|
}
|
|
|
|
if (HandleList != NULL) {
|
|
LoadHiiFormset (HandleList, HandleCount);
|
|
FreePool (HandleList);
|
|
}
|
|
}
|
|
|
|
#define EFI_BITS_SHIFT_PER_UINT32 0x5
|
|
#define EFI_BITS_PER_UINT32 (1 << EFI_BITS_SHIFT_PER_UINT32)
|
|
#define EFI_FORM_ID_MAX 0xFFFF
|
|
#define EFI_FREE_FORM_ID_BITMAP_SIZE ((EFI_FORM_ID_MAX + 1) / EFI_BITS_PER_UINT32)
|
|
|
|
/**
|
|
|
|
Return a free Form ID
|
|
|
|
@param[in] FormSet Pointer to FormSet.
|
|
|
|
@retval UINT16 Return the free Form ID
|
|
|
|
**/
|
|
UINT16
|
|
GetFreeFormId (
|
|
FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
FORM_BROWSER_FORM *Form;
|
|
LIST_ENTRY *FormLink;
|
|
UINT32 FreeFormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE];
|
|
UINT32 Index;
|
|
UINT32 Offset;
|
|
UINT32 Mask;
|
|
|
|
for (Index = 0; Index < EFI_FREE_FORM_ID_BITMAP_SIZE; Index++) {
|
|
FreeFormIdBitMap[Index] = 0;
|
|
}
|
|
|
|
// Form ID 0 is reserved.
|
|
FreeFormIdBitMap[0] = 0x80000000;
|
|
|
|
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
|
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
|
|
Index = (Form->FormId / EFI_BITS_PER_UINT32);
|
|
Offset = (Form->FormId % EFI_BITS_PER_UINT32);
|
|
FreeFormIdBitMap[Index] |= (0x80000000 >> Offset);
|
|
}
|
|
|
|
for (Index = 0; Index < EFI_FREE_FORM_ID_BITMAP_SIZE; Index++) {
|
|
if (FreeFormIdBitMap[Index] != 0xFFFFFFFF) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERT (Index != EFI_FREE_FORM_ID_BITMAP_SIZE);
|
|
if (Index == EFI_FREE_FORM_ID_BITMAP_SIZE) {
|
|
return 0;
|
|
}
|
|
|
|
for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) {
|
|
if ((FreeFormIdBitMap[Index] & Mask) == 0) {
|
|
FreeFormIdBitMap[Index] |= Mask;
|
|
return (UINT16)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EFI_STATUS
|
|
CreateExpressionQIdMapForm (
|
|
FORM_BROWSER_FORMSET *FormSet,
|
|
FORM_BROWSER_FORM **Form
|
|
)
|
|
{
|
|
FORM_BROWSER_FORM *CurrentForm;
|
|
UINT16 FreeFormId;
|
|
|
|
CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
|
|
ASSERT (CurrentForm != NULL);
|
|
if (CurrentForm == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
FreeFormId = GetFreeFormId (FormSet);
|
|
if (FreeFormId == 0) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
|
|
CurrentForm->FormSet = FormSet;
|
|
|
|
InitializeListHead (&CurrentForm->ExpressionListHead);
|
|
InitializeListHead (&CurrentForm->StatementListHead);
|
|
InitializeListHead (&CurrentForm->ConfigRequestHead);
|
|
InitializeListHead (&CurrentForm->PropertyListHead);
|
|
InitializeListHead (&CurrentForm->TargetInfoListHead);
|
|
|
|
CurrentForm->FormType = STANDARD_MAP_FORM_TYPE;
|
|
CurrentForm->FormTitle = (EFI_STRING_ID) 1;
|
|
CurrentForm->FormId = FreeFormId;
|
|
|
|
InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
|
|
|
|
*Form = CurrentForm;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Set Statement to a goto question which can go to the specified TargetForm of TargetFormSet.
|
|
|
|
@param[in] TargetFormSet Pointer to target formset of goto question.
|
|
@param[in] TargetForm Pointer to target form of goto question.
|
|
@param[in] FormSet Pointer to formset.
|
|
@param[in, out] Statement Pointer to statement.
|
|
|
|
@retval EFI_SUCCESS Successfully set Statement to a goto question
|
|
@retval EFI_INVALID_PARAMETER Input parameter is NULL
|
|
@retval EFI_OUT_OF_RESOURCES Fail to allocate memory
|
|
**/
|
|
EFI_STATUS
|
|
SetGotoQuestion (
|
|
IN FORM_BROWSER_FORMSET *TargetFormSet,
|
|
IN FORM_BROWSER_FORM *TargetForm,
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN OUT FORM_BROWSER_STATEMENT *Statement
|
|
)
|
|
{
|
|
UINT8 *Buffer;
|
|
EFI_IFR_REF3 *Ref3Opcode;
|
|
|
|
if (TargetFormSet == NULL || TargetForm == NULL || FormSet == NULL || Statement == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Buffer = AllocateZeroPool (sizeof(FB_IMPORT_INFO) + sizeof(EFI_IFR_REF3));
|
|
if (Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Statement->ImportInfo = (FB_IMPORT_INFO *) Buffer;
|
|
Statement->OpCode = (EFI_IFR_OP_HEADER *) (Buffer + sizeof (FB_IMPORT_INFO));
|
|
|
|
InitializeListHead (&Statement->DefaultListHead);
|
|
InitializeListHead (&Statement->OptionListHead);
|
|
InitializeListHead (&Statement->InconsistentListHead);
|
|
InitializeListHead (&Statement->NoSubmitListHead);
|
|
InitializeListHead (&Statement->WarningListHead);
|
|
InitializeListHead (&Statement->PropertyListHead);
|
|
|
|
Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
|
|
Statement->Operand = EFI_IFR_REF_OP;
|
|
Statement->QuestionId = GetAvailableQuestionId (FormSet);
|
|
Statement->RefreshInterval = 0;
|
|
Statement->Locked = FALSE;
|
|
Statement->HiiValue.Type = EFI_IFR_TYPE_REF;
|
|
Statement->HiiValue.Value.ref.QuestionId = 0;
|
|
Statement->HiiValue.Value.ref.FormId = TargetForm->FormId;
|
|
CopyGuid (&Statement->HiiValue.Value.ref.FormSetGuid, &TargetFormSet->Guid);
|
|
|
|
CopyHiiString (TargetFormSet->HiiHandle, TargetForm->FormTitle, FormSet->HiiHandle, &Statement->Prompt);
|
|
CopyHiiString (TargetFormSet->HiiHandle, TargetForm->FormTitle, FormSet->HiiHandle, &Statement->Help);
|
|
|
|
Statement->ImportInfo->SrcFormSet = TargetFormSet;
|
|
Statement->ImportInfo->SrcForm = TargetForm;
|
|
Statement->ImportInfo->SrcStatement = NULL;
|
|
|
|
Ref3Opcode = (EFI_IFR_REF3 *) Statement->OpCode;
|
|
Ref3Opcode->Header.OpCode = EFI_IFR_REF_OP;
|
|
Ref3Opcode->Header.Length = sizeof (EFI_IFR_REF3);
|
|
Ref3Opcode->Question.Header.Prompt = Statement->Prompt;
|
|
Ref3Opcode->Question.Header.Help = Statement->Help;
|
|
Ref3Opcode->QuestionId = Statement->QuestionId;
|
|
Ref3Opcode->FormId = TargetForm->FormId;
|
|
CopyGuid ((VOID *) &Ref3Opcode->FormSetId, &TargetFormSet->Guid);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Process VFCF/VFR import for formset.
|
|
|
|
@param[in] DstFormSet Pointer to formset.
|
|
|
|
@retval EFI_SUCCESS Successfully process VFCF/VFR import
|
|
@retval EFI_INVALID_PARAMETER Input parameter is NULL
|
|
@retval EFI_ABORTED Fail to create formset HII resource
|
|
@retval Other Import info is not found or fail to initialize import required buffer
|
|
**/
|
|
EFI_STATUS
|
|
FBProcessImport (
|
|
IN OUT FORM_BROWSER_FORMSET *DstFormSet
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 Index;
|
|
IMPORT_INFO *ImportInfo;
|
|
FORM_BROWSER_FORM *DstForm;
|
|
FORM_BROWSER_STATEMENT *DstStatement;
|
|
FORM_BROWSER_FORMSET *SrcFormSet;
|
|
FORM_BROWSER_FORM *SrcForm;
|
|
FORM_BROWSER_STATEMENT *SrcStatement;
|
|
FORMSET_STORAGE *SrcStorage;
|
|
EFI_QUESTION_ID DstFakeQuestionId;
|
|
H2O_FORM_BROWSER_FORMSET_HII_RESOURCE *FormSetHiiResource;
|
|
FORM_BROWSER_FORM *ExpressionQIdMapForm;
|
|
UINTN ExpressionQIdMapCount;
|
|
|
|
if (DstFormSet == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
DeleteAllVfrImportNewStatements (DstFormSet);
|
|
|
|
mImportInfoCount = 0;
|
|
mImportInfoList = NULL;
|
|
GetImportInfoList (&DstFormSet->Guid, &mImportInfoList, &mImportInfoCount);
|
|
GetImportInfoListFromVfrFormSet (DstFormSet, &mImportInfoList, &mImportInfoCount);
|
|
GetImportInfoListFromTargetInfo (DstFormSet, &mImportInfoList, &mImportInfoCount);
|
|
if (mImportInfoCount == 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
InitializeFormSetHiiResource (DstFormSet);
|
|
|
|
for (Index = 0; Index < mImportInfoCount; Index++) {
|
|
if (GetFormSetByFormSetGuid (&mImportInfoList[Index].SrcFormSetGuid, &mH2OBrowserImportFormSetList, &gBrowserFormSetList, NULL) == NULL) {
|
|
CreateImportFormSet (&mImportInfoList[Index].SrcFormSetGuid);
|
|
}
|
|
}
|
|
|
|
mImportStatementId = GetAvailableStatementId (DstFormSet);
|
|
DstFakeQuestionId = GetAvailableFakeQuestionId (DstFormSet);
|
|
|
|
FormSetHiiResource = GetFormSetHiiResource (DstFormSet);
|
|
if (FormSetHiiResource == NULL) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
ExpressionQIdMapForm = NULL;
|
|
|
|
for (Index = 0; Index < mImportInfoCount; Index++) {
|
|
ImportInfo = &mImportInfoList[Index];
|
|
|
|
if (IsIdConflict (DstFormSet, ImportInfo)) {
|
|
continue;
|
|
}
|
|
|
|
if (ImportInfo->ExpressionQId != 0) {
|
|
//
|
|
// create a form to store expression questions
|
|
//
|
|
if (ExpressionQIdMapForm == NULL) {
|
|
Status = CreateExpressionQIdMapForm (DstFormSet, &ExpressionQIdMapForm);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
ImportInfo->DstFormId = ExpressionQIdMapForm->FormId;
|
|
DstForm = ExpressionQIdMapForm;
|
|
} else {
|
|
DstForm = IdToForm (DstFormSet, ImportInfo->DstFormId);
|
|
if (DstForm == NULL) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
Status = GetSrcData (ImportInfo, &SrcFormSet, &SrcForm, &SrcStatement, &SrcStorage);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
DstStatement = GetNewStatement (DstFormSet);
|
|
if (DstStatement == NULL) {
|
|
continue;
|
|
}
|
|
|
|
DstStatement->StatementId = mImportStatementId++;
|
|
|
|
if (IS_LINK_TARGET (ImportInfo->Type)) {
|
|
Status = SetGotoQuestion (SrcFormSet, SrcForm, DstFormSet, DstStatement);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
ImportInfo->DstId = DstStatement->QuestionId;
|
|
} else if (SrcStatement->Operand == EFI_IFR_SUBTITLE_OP ||
|
|
SrcStatement->Operand == EFI_IFR_TEXT_OP ||
|
|
SrcStatement->Operand == EFI_IFR_RESET_BUTTON_OP) {
|
|
Status = CopyStatement (SrcFormSet, SrcForm, SrcStatement, DstFormSet, DstForm, DstStatement);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
switch (SrcStatement->Operand) {
|
|
|
|
case EFI_IFR_SUBTITLE_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
break;
|
|
|
|
case EFI_IFR_TEXT_OP:
|
|
break;
|
|
|
|
case EFI_IFR_RESET_BUTTON_OP:
|
|
DstStatement->DefaultId = SrcStatement->DefaultId;
|
|
break;
|
|
}
|
|
|
|
DstStatement->FakeQuestionId = DstFakeQuestionId++;
|
|
} else {
|
|
Status = CopyQuestion (SrcFormSet, SrcForm, SrcStatement, SrcStorage, DstFormSet, DstForm, DstStatement);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
switch (SrcStatement->Operand) {
|
|
|
|
case EFI_IFR_ACTION_OP:
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_ACTION;
|
|
if (SrcStatement->QuestionConfig != 0) {
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcStatement->QuestionConfig, DstFormSet->HiiHandle, &DstStatement->QuestionConfig);
|
|
}
|
|
break;
|
|
|
|
case EFI_IFR_REF_OP:
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_REF;
|
|
|
|
if (SrcStatement->HiiValue.Value.ref.DevicePath != 0) {
|
|
CopyHiiString (SrcFormSet->HiiHandle, SrcStatement->HiiValue.Value.ref.DevicePath, DstFormSet->HiiHandle, &DstStatement->HiiValue.Value.ref.DevicePath);
|
|
}
|
|
|
|
CopyMem (
|
|
&DstStatement->HiiValue.Value.ref.FormSetGuid,
|
|
&SrcStatement->HiiValue.Value.ref.FormSetGuid,
|
|
sizeof (EFI_GUID)
|
|
);
|
|
|
|
if (DstStatement->HiiValue.Value.ref.DevicePath == 0 && CompareGuid (&DstStatement->HiiValue.Value.ref.FormSetGuid, &gZeroGuid)) {
|
|
//
|
|
// Originally, it is going into form or question in self formset.
|
|
// But here, it should use REF3.
|
|
//
|
|
CopyMem (
|
|
&DstStatement->HiiValue.Value.ref.FormSetGuid,
|
|
&SrcFormSet->Guid,
|
|
sizeof (EFI_GUID)
|
|
);
|
|
}
|
|
DstStatement->HiiValue.Value.ref.FormId = SrcStatement->HiiValue.Value.ref.FormId;
|
|
DstStatement->HiiValue.Value.ref.QuestionId = SrcStatement->HiiValue.Value.ref.QuestionId;
|
|
|
|
DstStatement->StorageWidth = SrcStatement->StorageWidth;
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstForm);
|
|
break;
|
|
|
|
case EFI_IFR_STRING_OP:
|
|
case EFI_IFR_PASSWORD_OP:
|
|
DstStatement->Minimum = SrcStatement->Minimum;
|
|
DstStatement->Maximum = SrcStatement->Maximum;
|
|
DstStatement->StorageWidth = SrcStatement->StorageWidth;
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
|
|
DstStatement->BufferValue = AllocateZeroPool (DstStatement->StorageWidth + sizeof (CHAR16));
|
|
DstStatement->HiiValue.Value.string = NewString ((CHAR16*) DstStatement->BufferValue, DstFormSet->HiiHandle);
|
|
|
|
DstStatement->HiiValue.Buffer = DstStatement->BufferValue;
|
|
DstStatement->HiiValue.BufferLen = DstStatement->StorageWidth + sizeof (CHAR16);
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstForm);
|
|
break;
|
|
|
|
case EFI_IFR_CHECKBOX_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->StorageWidth = (UINT16) sizeof (BOOLEAN);
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstForm);
|
|
break;
|
|
|
|
case EFI_IFR_DATE_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
|
|
|
|
if ((DstStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
|
|
DstStatement->StorageWidth = (UINT16) sizeof (EFI_HII_DATE);
|
|
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstForm);
|
|
} else {
|
|
//
|
|
// Don't assign storage for RTC type of date/time
|
|
//
|
|
DstStatement->Storage = NULL;
|
|
DstStatement->StorageWidth = 0;
|
|
}
|
|
break;
|
|
|
|
case EFI_IFR_TIME_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
|
|
|
|
if ((DstStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
|
|
DstStatement->StorageWidth = (UINT16) sizeof (EFI_HII_TIME);
|
|
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstForm);
|
|
} else {
|
|
//
|
|
// Don't assign storage for RTC type of date/time
|
|
//
|
|
DstStatement->Storage = NULL;
|
|
DstStatement->StorageWidth = 0;
|
|
}
|
|
break;
|
|
|
|
case EFI_IFR_ONE_OF_OP:
|
|
case EFI_IFR_NUMERIC_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
|
|
DstStatement->Minimum = SrcStatement->Minimum;
|
|
DstStatement->Maximum = SrcStatement->Maximum;
|
|
DstStatement->Step = SrcStatement->Step;
|
|
DstStatement->StorageWidth = SrcStatement->StorageWidth;
|
|
DstStatement->HiiValue.Type = SrcStatement->HiiValue.Type;
|
|
|
|
if (!IsListEmpty (&SrcStatement->OptionListHead)) {
|
|
CopyOptions (
|
|
SrcFormSet,
|
|
SrcStatement,
|
|
DstFormSet,
|
|
DstForm,
|
|
DstStatement
|
|
);
|
|
}
|
|
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstForm);
|
|
break;
|
|
|
|
case EFI_IFR_ORDERED_LIST_OP:
|
|
DstStatement->Flags = SrcStatement->Flags;
|
|
DstStatement->MaxContainers = SrcStatement->MaxContainers;
|
|
DstStatement->HiiValue.Type = EFI_IFR_TYPE_BUFFER;
|
|
DstStatement->BufferValue = NULL;
|
|
|
|
if (!IsListEmpty (&SrcStatement->OptionListHead)) {
|
|
CopyOptions (
|
|
SrcFormSet,
|
|
SrcStatement,
|
|
DstFormSet,
|
|
DstForm,
|
|
DstStatement
|
|
);
|
|
}
|
|
|
|
if (SrcStatement->BufferValue != NULL) {
|
|
DstStatement->StorageWidth = SrcStatement->StorageWidth;
|
|
DstStatement->BufferValue = AllocateZeroPool (SrcStatement->StorageWidth);
|
|
DstStatement->ValueType = SrcStatement->ValueType;
|
|
if (DstStatement->HiiValue.Type == EFI_IFR_TYPE_BUFFER) {
|
|
DstStatement->HiiValue.Buffer = DstStatement->BufferValue;
|
|
DstStatement->HiiValue.BufferLen = DstStatement->StorageWidth;
|
|
}
|
|
|
|
InitializeRequestElement (DstFormSet, DstStatement, DstForm);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (IMPORT_INFO_FLAG_IS_QUESTION (ImportInfo->Flags)) {
|
|
DstStatement->QuestionId = GetQuestionId (DstFormSet, ImportInfo);
|
|
} else {
|
|
DstStatement->QuestionId = GetAvailableQuestionId (DstFormSet);
|
|
}
|
|
ImportInfo->DstId = DstStatement->QuestionId;
|
|
}
|
|
|
|
if (ImportInfo->VfrFakeStatement != NULL) {
|
|
InsertNewStatementAfterFakeStatement (DstFormSet, DstForm, (FORM_BROWSER_STATEMENT *)ImportInfo->VfrFakeStatement, DstStatement);
|
|
} else {
|
|
InsertTailList (&DstForm->StatementListHead, &DstStatement->Link);
|
|
}
|
|
DstForm->NumberOfStatement++;
|
|
}
|
|
|
|
|
|
//
|
|
// update expression qid map list
|
|
//
|
|
ExpressionQIdMapCount = 0;
|
|
for (Index = 0, ImportInfo = mImportInfoList; Index < mImportInfoCount; Index++, ImportInfo++) {
|
|
if (ImportInfo->ExpressionQId == 0) {
|
|
continue;
|
|
}
|
|
ExpressionQIdMapCount++;
|
|
}
|
|
|
|
DstFormSet->ExpressionQIdMapList[0] = AllocateZeroPool (sizeof (EFI_QUESTION_ID) * ExpressionQIdMapCount);
|
|
DstFormSet->ExpressionQIdMapList[1] = AllocateZeroPool (sizeof (EFI_QUESTION_ID) * ExpressionQIdMapCount);
|
|
|
|
ExpressionQIdMapCount = 0;
|
|
for (Index = 0, ImportInfo = mImportInfoList; Index < mImportInfoCount; Index++, ImportInfo++) {
|
|
if (ImportInfo->ExpressionQId == 0) {
|
|
continue;
|
|
}
|
|
|
|
DstFormSet->ExpressionQIdMapList[0][ExpressionQIdMapCount] = ImportInfo->ExpressionQId;
|
|
DstFormSet->ExpressionQIdMapList[1][ExpressionQIdMapCount] = ImportInfo->DstId;
|
|
ExpressionQIdMapCount++;
|
|
}
|
|
|
|
DstFormSet->ExpressionQIdMapListCount = ExpressionQIdMapCount;
|
|
|
|
if (mImportFormUpdateNotifyHandle == NULL) {
|
|
gHiiDatabase->RegisterPackageNotify (
|
|
gHiiDatabase,
|
|
EFI_HII_PACKAGE_FORMS,
|
|
NULL,
|
|
ImportFormUpdateNotifyFn,
|
|
EFI_HII_DATABASE_NOTIFY_REMOVE_PACK,
|
|
&mImportFormUpdateNotifyHandle
|
|
);
|
|
}
|
|
|
|
FBFreePool ((VOID **) &mImportInfoList);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Process VFCF property for formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@retval EFI_SUCCESS Successfully process VFCF property
|
|
@retval EFI_INVALID_PARAMETER Input parameter is NULL
|
|
@retval Other Fail to get layout
|
|
**/
|
|
EFI_STATUS
|
|
FBProcessVfcfProperty (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *FormLink;
|
|
FORM_BROWSER_FORM *Form;
|
|
LIST_ENTRY *StatementLink;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
BOOLEAN IsQuestion;
|
|
H2O_PROPERTY_INFO *Property;
|
|
H2O_PROPERTY_VALUE PropValue;
|
|
UINT16 Position;
|
|
|
|
if (FormSet == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!HaveVfcfFormsetInfo (&FormSet->Guid)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Process enable property from VFCF.
|
|
// If form is disabled, destroy it.
|
|
// If statement is disabled, insert a disableif TRUE expression into statement.
|
|
//
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
|
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
|
|
if (!HaveVfcfFormInfo (&FormSet->Guid, Form->FormId)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check if form is enable or not.
|
|
//
|
|
Status = GetVfcfFormPropertyValue (
|
|
&FormSet->Guid,
|
|
Form->FormId,
|
|
H2O_IFR_STYLE_TYPE_FORM,
|
|
H2O_STYLE_PSEUDO_CLASS_NORMAL,
|
|
"enable",
|
|
NULL,
|
|
&Property,
|
|
&PropValue
|
|
);
|
|
if (!EFI_ERROR (Status) && !PropValue.H2OValue.Value.Bool) {
|
|
RemoveEntryList (&Form->Link);
|
|
DestroyForm (FormSet, Form);
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check if statement is enable or not.
|
|
//
|
|
Position = 0;
|
|
StatementLink = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, StatementLink)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementLink);
|
|
StatementLink = GetNextNode (&Form->StatementListHead, StatementLink);
|
|
|
|
IsQuestion = (BOOLEAN) (Statement->QuestionId != 0);
|
|
Status = GetVfcfStatementPropertyValue (
|
|
&FormSet->Guid,
|
|
IsQuestion,
|
|
(IsQuestion ? Statement->QuestionId : Position),
|
|
H2O_IFR_STYLE_TYPE_VFR_TREE_FLAG,
|
|
H2O_STYLE_PSEUDO_CLASS_NORMAL,
|
|
"enable",
|
|
NULL,
|
|
&Property,
|
|
&PropValue
|
|
);
|
|
if (!EFI_ERROR (Status) && !PropValue.H2OValue.Value.Bool) {
|
|
InsertDisableIfExpression (FormSet, Form, Statement);
|
|
}
|
|
Position++;
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
ReplaceExpressionOfStatement (
|
|
IN FORM_BROWSER_FORM *Form,
|
|
IN OUT FORM_BROWSER_STATEMENT *Statement,
|
|
IN FORM_EXPRESSION *Expression
|
|
)
|
|
{
|
|
UINTN Index;
|
|
FORM_EXPRESSION_LIST *ExpressionList;
|
|
|
|
InsertTailList (&Form->ExpressionListHead, &Expression->Link);
|
|
|
|
if (Statement->Expression == NULL) {
|
|
Statement->Expression = (FORM_EXPRESSION_LIST *) AllocateZeroPool (sizeof (FORM_EXPRESSION_LIST));
|
|
if (Statement->Expression == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Statement->Expression->Count = 1;
|
|
Statement->Expression->Signature = FORM_EXPRESSION_LIST_SIGNATURE;
|
|
Statement->Expression->Expression[0] = Expression;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
//
|
|
// find the same type expression, replace it
|
|
//
|
|
for (Index = 0; Index < Statement->Expression->Count; Index++) {
|
|
if (Statement->Expression->Expression[Index]->Type == Expression->Type) {
|
|
Statement->Expression->Expression[Index] = Expression;
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
//
|
|
// add a new expression
|
|
//
|
|
ExpressionList = ReallocatePool (
|
|
(sizeof(FORM_EXPRESSION_LIST) + ((Statement->Expression->Count - 1) * sizeof(FORM_EXPRESSION *))),
|
|
(sizeof(FORM_EXPRESSION_LIST) + ((Statement->Expression->Count) * sizeof(FORM_EXPRESSION *))),
|
|
Statement->Expression
|
|
);
|
|
if (ExpressionList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Statement->Expression = ExpressionList;
|
|
ExpressionList->Expression[ExpressionList->Count++] = Expression;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
ConvertExpressionQIdToQuestionId (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN EFI_QUESTION_ID *ExpressionQId
|
|
)
|
|
{
|
|
EFI_QUESTION_ID TmpExpressionQId;
|
|
EFI_QUESTION_ID *QuestionIdPtr;
|
|
UINTN Index;
|
|
|
|
TmpExpressionQId = *ExpressionQId;
|
|
for (Index = 0, QuestionIdPtr = FormSet->ExpressionQIdMapList[0]; Index < FormSet->ExpressionQIdMapListCount; Index++, QuestionIdPtr++) {
|
|
if (TmpExpressionQId == *QuestionIdPtr) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Maybe VfcfCompile.exe generate incorrect expression question id map
|
|
//
|
|
ASSERT (Index != FormSet->ExpressionQIdMapListCount);
|
|
if (Index == FormSet->ExpressionQIdMapListCount) {
|
|
*ExpressionQId = 0;
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// .vfcf file may use incorrect destination formset / form id / questions id
|
|
//
|
|
ASSERT (FormSet->ExpressionQIdMapList[1][Index] != 0xFFFF);
|
|
if (FormSet->ExpressionQIdMapList[1][Index] == 0xFFFF) {
|
|
*ExpressionQId = 0;
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
*ExpressionQId = FormSet->ExpressionQIdMapList[1][Index];
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
ReplaceExpression (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN FORM_BROWSER_FORM *Form,
|
|
IN OUT FORM_BROWSER_STATEMENT *Statement,
|
|
IN H2O_EXPRESSION_INFO *ExpressionInfo
|
|
)
|
|
{
|
|
UINT8 Operand;
|
|
UINT8 *OpCodeData;
|
|
UINTN OpCodeLength;
|
|
UINTN OpCodeOffset;
|
|
EFI_HII_VALUE *Value;
|
|
EXPRESSION_OPCODE *ExpressionOpCode;
|
|
FORM_EXPRESSION *FormExpression;
|
|
UINTN OpCodeArrayLength;
|
|
UINT8 *OpCodeArray;
|
|
EFI_STATUS Status;
|
|
|
|
OpCodeArray = ExpressionInfo->ExpressionOpcodes;
|
|
OpCodeArrayLength = ExpressionInfo->ExpressionSize;
|
|
|
|
FormExpression = CreateExpression (Form, OpCodeArray);
|
|
if (FormExpression == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
InitializeListHead (&FormExpression->OpCodeListHead);
|
|
switch (((EFI_IFR_OP_HEADER *) OpCodeArray)->OpCode) {
|
|
|
|
case EFI_IFR_GRAY_OUT_IF_OP:
|
|
FormExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
|
|
break;
|
|
|
|
case EFI_IFR_SUPPRESS_IF_OP:
|
|
FormExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
|
|
break;
|
|
|
|
case EFI_IFR_DISABLE_IF_OP:
|
|
FormExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
|
|
break;
|
|
|
|
default:
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = ReplaceExpressionOfStatement (Form, Statement, FormExpression);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// pass fisrt opcode
|
|
//
|
|
OpCodeArrayLength -= ((EFI_IFR_OP_HEADER *) OpCodeArray)->Length;
|
|
OpCodeOffset = ((EFI_IFR_OP_HEADER *) OpCodeArray)->Length;
|
|
|
|
while (OpCodeOffset <= OpCodeArrayLength) {
|
|
OpCodeData = OpCodeArray + OpCodeOffset;
|
|
|
|
OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
|
|
OpCodeOffset += OpCodeLength;
|
|
Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
|
|
|
|
|
|
//
|
|
// BUGBUG: it should check whether need EFI_IFR_END_OP
|
|
//
|
|
if (Operand == EFI_IFR_END_OP && OpCodeOffset > OpCodeArrayLength) {
|
|
continue ;
|
|
}
|
|
|
|
ExpressionOpCode = GetNewExpressionOpCode (FormSet);
|
|
if (ExpressionOpCode == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
|
|
ExpressionOpCode->Operand = Operand;
|
|
InitializeListHead (&ExpressionOpCode->Link);
|
|
|
|
Value = &ExpressionOpCode->Value;
|
|
|
|
switch (Operand) {
|
|
case EFI_IFR_EQ_ID_VAL_OP:
|
|
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
|
|
ConvertExpressionQIdToQuestionId (FormSet, &ExpressionOpCode->QuestionId);
|
|
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
|
|
CopyMem (&Value->Value.u16, &((EFI_IFR_EQ_ID_VAL *) OpCodeData)->Value, sizeof (UINT16));
|
|
break;
|
|
|
|
case EFI_IFR_EQ_ID_ID_OP:
|
|
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId1, sizeof (EFI_QUESTION_ID));
|
|
CopyMem (&ExpressionOpCode->QuestionId2, &((EFI_IFR_EQ_ID_ID *) OpCodeData)->QuestionId2, sizeof (EFI_QUESTION_ID));
|
|
ConvertExpressionQIdToQuestionId (FormSet, &ExpressionOpCode->QuestionId);
|
|
ConvertExpressionQIdToQuestionId (FormSet, &ExpressionOpCode->QuestionId2);
|
|
break;
|
|
|
|
case EFI_IFR_EQ_ID_VAL_LIST_OP:
|
|
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
|
|
ConvertExpressionQIdToQuestionId (FormSet, &ExpressionOpCode->QuestionId);
|
|
|
|
CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
|
|
ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->ValueList);
|
|
break;
|
|
|
|
case EFI_IFR_TO_STRING_OP:
|
|
case EFI_IFR_FIND_OP:
|
|
ExpressionOpCode->Format = (( EFI_IFR_TO_STRING *) OpCodeData)->Format;
|
|
break;
|
|
|
|
case EFI_IFR_STRING_REF1_OP:
|
|
Value->Type = EFI_IFR_TYPE_STRING;
|
|
CopyMem (&Value->Value.string, &(( EFI_IFR_STRING_REF1 *) OpCodeData)->StringId, sizeof (EFI_STRING_ID));
|
|
break;
|
|
|
|
case EFI_IFR_RULE_REF_OP:
|
|
ExpressionOpCode->RuleId = (( EFI_IFR_RULE_REF *) OpCodeData)->RuleId;
|
|
break;
|
|
|
|
case EFI_IFR_SPAN_OP:
|
|
ExpressionOpCode->Flags = (( EFI_IFR_SPAN *) OpCodeData)->Flags;
|
|
break;
|
|
|
|
case EFI_IFR_SECURITY_OP:
|
|
CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_SECURITY *) OpCodeData)->Permissions, sizeof (EFI_GUID));
|
|
break;
|
|
|
|
case EFI_IFR_MATCH2_OP:
|
|
CopyMem (&ExpressionOpCode->Guid, &((EFI_IFR_MATCH2 *) OpCodeData)->SyntaxType, sizeof (EFI_GUID));
|
|
break;
|
|
|
|
case EFI_IFR_QUESTION_REF1_OP:
|
|
CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_VAL_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
|
|
ConvertExpressionQIdToQuestionId (FormSet, &ExpressionOpCode->QuestionId);
|
|
break;
|
|
|
|
case EFI_IFR_QUESTION_REF3_OP:
|
|
if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_2)) {
|
|
CopyMem (&ExpressionOpCode->DevicePath, &(( EFI_IFR_QUESTION_REF3_2 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
|
|
|
|
if (OpCodeLength >= sizeof (EFI_IFR_QUESTION_REF3_3)) {
|
|
CopyMem (&ExpressionOpCode->Guid, &(( EFI_IFR_QUESTION_REF3_3 *) OpCodeData)->Guid, sizeof (EFI_GUID));
|
|
}
|
|
}
|
|
break;
|
|
|
|
//
|
|
// constant
|
|
//
|
|
case EFI_IFR_TRUE_OP:
|
|
Value->Type = EFI_IFR_TYPE_BOOLEAN;
|
|
Value->Value.b = TRUE;
|
|
break;
|
|
|
|
case EFI_IFR_FALSE_OP:
|
|
Value->Type = EFI_IFR_TYPE_BOOLEAN;
|
|
Value->Value.b = FALSE;
|
|
break;
|
|
|
|
case EFI_IFR_ONE_OP:
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
|
|
Value->Value.u8 = 1;
|
|
break;
|
|
|
|
case EFI_IFR_ZERO_OP:
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
|
|
Value->Value.u8 = 0;
|
|
break;
|
|
|
|
case EFI_IFR_ONES_OP:
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
|
|
Value->Value.u64 = 0xffffffffffffffffULL;
|
|
break;
|
|
|
|
case EFI_IFR_UINT8_OP:
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
|
|
Value->Value.u8 = (( EFI_IFR_UINT8 *) OpCodeData)->Value;
|
|
break;
|
|
|
|
case EFI_IFR_UINT16_OP:
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
|
|
CopyMem (&Value->Value.u16, &(( EFI_IFR_UINT16 *) OpCodeData)->Value, sizeof (UINT16));
|
|
break;
|
|
|
|
case EFI_IFR_UINT32_OP:
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
|
|
CopyMem (&Value->Value.u32, &(( EFI_IFR_UINT32 *) OpCodeData)->Value, sizeof (UINT32));
|
|
break;
|
|
|
|
case EFI_IFR_UINT64_OP:
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
|
|
CopyMem (&Value->Value.u64, &(( EFI_IFR_UINT64 *) OpCodeData)->Value, sizeof (UINT64));
|
|
break;
|
|
|
|
case EFI_IFR_UNDEFINED_OP:
|
|
Value->Type = EFI_IFR_TYPE_UNDEFINED;
|
|
break;
|
|
|
|
case EFI_IFR_VERSION_OP:
|
|
Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
|
|
Value->Value.u16 = EFI_IFR_SPECIFICATION_VERSION;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
InsertTailList (&FormExpression->OpCodeListHead, &ExpressionOpCode->Link);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
ReaplceExpressionList (
|
|
IN FORM_BROWSER_FORMSET *FormSet,
|
|
IN FORM_BROWSER_FORM *Form,
|
|
IN OUT FORM_BROWSER_STATEMENT *Statement,
|
|
UINTN NumberExpression,
|
|
H2O_EXPRESSION_INFO **ExpressionInfoList
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINTN LastExpressionIdx;
|
|
|
|
//
|
|
// only reserve the last expression when expression type is equal
|
|
//
|
|
for (LastExpressionIdx = NumberExpression - 1; LastExpressionIdx > 0; LastExpressionIdx--) {
|
|
if (ExpressionInfoList[LastExpressionIdx] == NULL) {
|
|
continue;
|
|
}
|
|
for (Index = 0; Index < LastExpressionIdx; Index++) {
|
|
if (ExpressionInfoList[Index] != NULL &&
|
|
((EFI_IFR_OP_HEADER *)ExpressionInfoList[Index]->ExpressionOpcodes)->OpCode
|
|
== ((EFI_IFR_OP_HEADER *)ExpressionInfoList[LastExpressionIdx]->ExpressionOpcodes)->OpCode) {
|
|
ExpressionInfoList[Index] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (Index = 0; Index < NumberExpression; Index++) {
|
|
if (ExpressionInfoList[Index] == NULL) {
|
|
continue;
|
|
}
|
|
|
|
Status = ReplaceExpression (FormSet, Form, Statement, ExpressionInfoList[Index]);
|
|
if (EFI_ERROR (Status)){
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Process VFCF expression for formset.
|
|
|
|
@param[in] FormSet Pointer to formset.
|
|
|
|
@retval EFI_SUCCESS Successfully process VFCF property
|
|
@retval EFI_INVALID_PARAMETER Input parameter is NULL
|
|
@retval Other Fail to get layout
|
|
**/
|
|
EFI_STATUS
|
|
FBProcessVfcfExpression (
|
|
IN FORM_BROWSER_FORMSET *FormSet
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *FormLink;
|
|
FORM_BROWSER_FORM *Form;
|
|
LIST_ENTRY *StatementLink;
|
|
FORM_BROWSER_STATEMENT *Statement;
|
|
UINT16 Position;
|
|
UINTN NumberExpression;
|
|
H2O_EXPRESSION_INFO **ExpressionInfoList;
|
|
|
|
ASSERT (FormSet != NULL);
|
|
if (FormSet == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!HaveVfcfFormsetInfo (&FormSet->Guid)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
FormLink = GetFirstNode (&FormSet->FormListHead);
|
|
while (!IsNull (&FormSet->FormListHead, FormLink)) {
|
|
Form = FORM_BROWSER_FORM_FROM_LINK (FormLink);
|
|
FormLink = GetNextNode (&FormSet->FormListHead, FormLink);
|
|
if (!HaveVfcfFormInfo (&FormSet->Guid, Form->FormId)) {
|
|
continue;
|
|
}
|
|
|
|
Position = 0;
|
|
StatementLink = GetFirstNode (&Form->StatementListHead);
|
|
while (!IsNull (&Form->StatementListHead, StatementLink)) {
|
|
Statement = FORM_BROWSER_STATEMENT_FROM_LINK (StatementLink);
|
|
StatementLink = GetNextNode (&Form->StatementListHead, StatementLink);
|
|
|
|
Status = GetVfcfStatementExpressionList (
|
|
&FormSet->Guid,
|
|
Form->FormId,
|
|
(BOOLEAN) (Statement->QuestionId != 0),
|
|
Statement->QuestionId,
|
|
Position,
|
|
&NumberExpression,
|
|
&ExpressionInfoList
|
|
);
|
|
if (EFI_ERROR (Status) && Status == EFI_NOT_FOUND) {
|
|
continue;
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = ReaplceExpressionList (
|
|
FormSet,
|
|
Form,
|
|
Statement,
|
|
NumberExpression,
|
|
ExpressionInfoList
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
FreePool (ExpressionInfoList);
|
|
|
|
Position++;
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|