mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 07:17:27 +00:00 
			
		
		
		
	 ebe43565f9
			
		
	
	
		ebe43565f9
		
	
	
	
	
		
			
			*** Press F9 in Uefi64 FrontPage shouldnot enter sub-menu ** [FT] Some UI error on multiple platforms on framework_20080811 ** [FT] UI test of How tall are you(Hex) on framework_20080811 To improve backward compatibility, add gEfiPrint2ProtocolGuid and rename gEfiPrintProtocolGuid to the previous GUID value used in EDK I. gEfiPrint2ProtocolGuid is a enhanced version of gEfiPrintProtocolGuid. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5768 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1690 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1690 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| Parser for IFR binary encoding.
 | |
| 
 | |
| Copyright (c) 2007 - 2008, Intel Corporation
 | |
| All rights reserved. This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Setup.h"
 | |
| #include "Ui.h"
 | |
| 
 | |
| UINT16           mStatementIndex;
 | |
| UINT16           mExpressionOpCodeIndex;
 | |
| 
 | |
| BOOLEAN          mInScopeSubtitle;
 | |
| BOOLEAN          mInScopeSuppress;
 | |
| BOOLEAN          mInScopeGrayOut;
 | |
| FORM_EXPRESSION  *mSuppressExpression;
 | |
| FORM_EXPRESSION  *mGrayOutExpression;
 | |
| 
 | |
| EFI_GUID  gTianoHiiIfrGuid = EFI_IFR_TIANO_GUID;
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID  mFrameworkHiiCompatibilityGuid = EFI_IFR_FRAMEWORK_GUID;
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Initialize Statement header members.
 | |
| 
 | |
|   @param  OpCodeData             Pointer of the raw OpCode data.
 | |
|   @param  FormSet                Pointer of the current FormSe.
 | |
|   @param  Form                   Pointer of the current Form.
 | |
| 
 | |
|   @return The Statement.
 | |
| 
 | |
| **/
 | |
| FORM_BROWSER_STATEMENT *
 | |
| CreateStatement (
 | |
|   IN UINT8                        *OpCodeData,
 | |
|   IN OUT FORM_BROWSER_FORMSET     *FormSet,
 | |
|   IN OUT FORM_BROWSER_FORM        *Form
 | |
|   )
 | |
| {
 | |
|   FORM_BROWSER_STATEMENT    *Statement;
 | |
|   EFI_IFR_STATEMENT_HEADER  *StatementHdr;
 | |
| 
 | |
|   if (Form == NULL) {
 | |
|     //
 | |
|     // We are currently not in a Form Scope, so just skip this Statement
 | |
|     //
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   Statement = &FormSet->StatementBuffer[mStatementIndex];
 | |
|   mStatementIndex++;
 | |
| 
 | |
|   InitializeListHead (&Statement->DefaultListHead);
 | |
|   InitializeListHead (&Statement->OptionListHead);
 | |
|   InitializeListHead (&Statement->InconsistentListHead);
 | |
|   InitializeListHead (&Statement->NoSubmitListHead);
 | |
| 
 | |
|   Statement->Signature = FORM_BROWSER_STATEMENT_SIGNATURE;
 | |
| 
 | |
|   Statement->Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
 | |
| 
 | |
|   StatementHdr = (EFI_IFR_STATEMENT_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
 | |
|   CopyMem (&Statement->Prompt, &StatementHdr->Prompt, sizeof (EFI_STRING_ID));
 | |
|   CopyMem (&Statement->Help, &StatementHdr->Help, sizeof (EFI_STRING_ID));
 | |
| 
 | |
|   if (mInScopeSuppress) {
 | |
|     Statement->SuppressExpression = mSuppressExpression;
 | |
|   }
 | |
| 
 | |
|   if (mInScopeGrayOut) {
 | |
|     Statement->GrayOutExpression = mGrayOutExpression;
 | |
|   }
 | |
| 
 | |
|   Statement->InSubtitle = mInScopeSubtitle;
 | |
| 
 | |
|   //
 | |
|   // Insert this Statement into current Form
 | |
|   //
 | |
|   InsertTailList (&Form->StatementListHead, &Statement->Link);
 | |
| 
 | |
|   return Statement;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| UpdateCheckBoxStringToken (
 | |
|   IN CONST FORM_BROWSER_FORMSET *FormSet,
 | |
|   IN       FORM_BROWSER_STATEMENT *Statement
 | |
|   )
 | |
| {
 | |
|   CHAR16                  Str[MAXIMUM_VALUE_CHARACTERS];
 | |
|   EFI_STRING_ID           Id;
 | |
|   EFI_STATUS              Status;
 | |
| 
 | |
|   ASSERT (Statement != NULL);
 | |
|   ASSERT (Statement->Operand == EFI_IFR_CHECKBOX_OP);
 | |
|   
 | |
|   UnicodeValueToString (Str, 0, Statement->VarStoreInfo.VarName, MAXIMUM_VALUE_CHARACTERS - 1);
 | |
|   
 | |
|   Status = HiiLibNewString (FormSet->HiiHandle, &Id, Str);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Statement->VarStoreInfo.VarName = Id;
 | |
|     
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsNextOpCodeGuidedVarEqName (
 | |
|   UINT8 *OpCodeData
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Get next opcode
 | |
|   //
 | |
|   OpCodeData += ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
 | |
|   if (*OpCodeData == EFI_IFR_GUID_OP) {
 | |
|     if (CompareGuid (&mFrameworkHiiCompatibilityGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
 | |
|       //
 | |
|       // Specific GUIDed opcodes to support IFR generated from Framework HII VFR 
 | |
|       //
 | |
|       if ((((EFI_IFR_GUID_VAREQNAME *) OpCodeData)->ExtendOpCode) == EFI_IFR_EXTEND_OP_VAREQNAME) {
 | |
|         return TRUE;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initialize Question's members.
 | |
| 
 | |
|   @param  OpCodeData             Pointer of the raw OpCode data.
 | |
|   @param  FormSet                Pointer of the current FormSet.
 | |
|   @param  Form                   Pointer of the current Form.
 | |
| 
 | |
|   @return The Question.
 | |
| 
 | |
| **/
 | |
| FORM_BROWSER_STATEMENT *
 | |
| CreateQuestion (
 | |
|   IN UINT8                        *OpCodeData,
 | |
|   IN OUT FORM_BROWSER_FORMSET     *FormSet,
 | |
|   IN OUT FORM_BROWSER_FORM        *Form
 | |
|   )
 | |
| {
 | |
|   FORM_BROWSER_STATEMENT   *Statement;
 | |
|   EFI_IFR_QUESTION_HEADER  *QuestionHdr;
 | |
|   LIST_ENTRY               *Link;
 | |
|   FORMSET_STORAGE          *Storage;
 | |
|   NAME_VALUE_NODE          *NameValueNode;
 | |
|   EFI_STATUS               Status;
 | |
| 
 | |
|   Statement = CreateStatement (OpCodeData, FormSet, Form);
 | |
|   if (Statement == NULL) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   QuestionHdr = (EFI_IFR_QUESTION_HEADER *) (OpCodeData + sizeof (EFI_IFR_OP_HEADER));
 | |
|   CopyMem (&Statement->QuestionId, &QuestionHdr->QuestionId, sizeof (EFI_QUESTION_ID));
 | |
|   CopyMem (&Statement->VarStoreId, &QuestionHdr->VarStoreId, sizeof (EFI_VARSTORE_ID));
 | |
|   CopyMem (&Statement->VarStoreInfo.VarOffset, &QuestionHdr->VarStoreInfo.VarOffset, sizeof (UINT16));
 | |
| 
 | |
|   Statement->QuestionFlags = QuestionHdr->Flags;
 | |
| 
 | |
|   if (Statement->VarStoreId == 0) {
 | |
|     //
 | |
|     // VarStoreId of zero indicates no variable storage
 | |
|     //
 | |
|     return Statement;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Take a look at next OpCode to see whether it is a GUIDed opcode to support
 | |
|   // Framework Compatibility
 | |
|   //
 | |
|   if (FeaturePcdGet (PcdFrameworkHiiCompatibilitySupport)) {
 | |
|     if ((*OpCodeData == EFI_IFR_CHECKBOX_OP) && IsNextOpCodeGuidedVarEqName (OpCodeData)) {
 | |
|       Status = UpdateCheckBoxStringToken (FormSet, Statement);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         return NULL;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Find Storage for this Question
 | |
|   //
 | |
|   Link = GetFirstNode (&FormSet->StorageListHead);
 | |
|   while (!IsNull (&FormSet->StorageListHead, Link)) {
 | |
|     Storage = FORMSET_STORAGE_FROM_LINK (Link);
 | |
| 
 | |
|     if (Storage->VarStoreId == Statement->VarStoreId) {
 | |
|       Statement->Storage = Storage;
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Link = GetNextNode (&FormSet->StorageListHead, Link);
 | |
|   }
 | |
|   ASSERT (Statement->Storage != NULL);
 | |
| 
 | |
|   //
 | |
|   // Initialilze varname for Name/Value or EFI Variable
 | |
|   //
 | |
|   if ((Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) ||
 | |
|       (Statement->Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE)) {
 | |
|     Statement->VariableName = GetToken (Statement->VarStoreInfo.VarName, FormSet->HiiHandle);
 | |
|     ASSERT (Statement->VariableName != NULL);
 | |
| 
 | |
|     if (Statement->Storage->Type == EFI_HII_VARSTORE_NAME_VALUE) {
 | |
|       //
 | |
|       // Insert to Name/Value varstore list
 | |
|       //
 | |
|       NameValueNode = AllocateZeroPool (sizeof (NAME_VALUE_NODE));
 | |
|       ASSERT (NameValueNode != NULL);
 | |
|       NameValueNode->Signature = NAME_VALUE_NODE_SIGNATURE;
 | |
|       NameValueNode->Name = AllocateCopyPool (StrSize (Statement->VariableName), Statement->VariableName);
 | |
|       ASSERT (NameValueNode->Name != NULL);
 | |
|       NameValueNode->Value = AllocateZeroPool (0x10);
 | |
|       ASSERT (NameValueNode->Value != NULL);
 | |
|       NameValueNode->EditValue = AllocateZeroPool (0x10);
 | |
|       ASSERT (NameValueNode->EditValue != NULL);
 | |
| 
 | |
|       InsertTailList (&Statement->Storage->NameValueListHead, &NameValueNode->Link);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Statement;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Allocate a FORM_EXPRESSION node.
 | |
| 
 | |
|   @param  Form                   The Form associated with this Expression
 | |
| 
 | |
|   @return Pointer to a FORM_EXPRESSION data structure.
 | |
| 
 | |
| **/
 | |
| FORM_EXPRESSION *
 | |
| CreateExpression (
 | |
|   IN OUT FORM_BROWSER_FORM        *Form
 | |
|   )
 | |
| {
 | |
|   FORM_EXPRESSION  *Expression;
 | |
| 
 | |
|   Expression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
 | |
|   Expression->Signature = FORM_EXPRESSION_SIGNATURE;
 | |
|   InitializeListHead (&Expression->OpCodeListHead);
 | |
| 
 | |
|   return Expression;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Allocate a FORMSET_STORAGE data structure and insert to FormSet Storage List.
 | |
| 
 | |
|   @param  FormSet                Pointer of the current FormSet
 | |
| 
 | |
|   @return Pointer to a FORMSET_STORAGE data structure.
 | |
| 
 | |
| **/
 | |
| FORMSET_STORAGE *
 | |
| CreateStorage (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet
 | |
|   )
 | |
| {
 | |
|   FORMSET_STORAGE  *Storage;
 | |
| 
 | |
|   Storage = AllocateZeroPool (sizeof (FORMSET_STORAGE));
 | |
|   Storage->Signature = FORMSET_STORAGE_SIGNATURE;
 | |
|   InitializeListHead (&Storage->NameValueListHead);
 | |
|   InsertTailList (&FormSet->StorageListHead, &Storage->Link);
 | |
| 
 | |
|   return Storage;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Create ConfigHdr string for a storage.
 | |
| 
 | |
|   @param  FormSet                Pointer of the current FormSet
 | |
|   @param  Storage                Pointer of the storage
 | |
| 
 | |
|   @retval EFI_SUCCESS            Initialize ConfigHdr success
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| InitializeConfigHdr (
 | |
|   IN FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN OUT FORMSET_STORAGE   *Storage
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       StrBufferLen;
 | |
|   CHAR16      *Name;
 | |
| 
 | |
|   if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
 | |
|     Name = Storage->Name;
 | |
|   } else {
 | |
|     Name = NULL;
 | |
|   }
 | |
| 
 | |
|   StrBufferLen = 0;
 | |
|   Status = ConstructConfigHdr (
 | |
|              Storage->ConfigHdr,
 | |
|              &StrBufferLen,
 | |
|              &Storage->Guid,
 | |
|              Name,
 | |
|              FormSet->DriverHandle
 | |
|              );
 | |
|   if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|     Storage->ConfigHdr = AllocateZeroPool (StrBufferLen);
 | |
|     Status = ConstructConfigHdr (
 | |
|                Storage->ConfigHdr,
 | |
|                &StrBufferLen,
 | |
|                &Storage->Guid,
 | |
|                Name,
 | |
|                FormSet->DriverHandle
 | |
|                );
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Storage->ConfigRequest = AllocateCopyPool (StrBufferLen, Storage->ConfigHdr);
 | |
|   Storage->SpareStrLen = 0;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Initialize Request Element of a Question. <RequestElement> ::= '&'<BlockName> | '&'<Label>
 | |
| 
 | |
|   @param  FormSet                Pointer of the current FormSet.
 | |
|   @param  Question               The Question to be initialized.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Function success.
 | |
|   @retval EFI_INVALID_PARAMETER  No storage associated with the Question.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| InitializeRequestElement (
 | |
|   IN OUT FORM_BROWSER_FORMSET     *FormSet,
 | |
|   IN OUT FORM_BROWSER_STATEMENT   *Question
 | |
|   )
 | |
| {
 | |
|   FORMSET_STORAGE  *Storage;
 | |
|   UINTN            StrLen;
 | |
|   UINTN            StringSize;
 | |
|   CHAR16           *NewStr;
 | |
|   CHAR16           RequestElement[30];
 | |
| 
 | |
|   Storage = Question->Storage;
 | |
|   if (Storage == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (Storage->Type == EFI_HII_VARSTORE_EFI_VARIABLE) {
 | |
|     //
 | |
|     // <ConfigRequest> is unnecessary for EFI variable storage,
 | |
|     // GetVariable()/SetVariable() will be used to retrieve/save values
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Prepare <RequestElement>
 | |
|   //
 | |
|   if (Storage->Type == EFI_HII_VARSTORE_BUFFER) {
 | |
|     StrLen = UnicodeSPrint (
 | |
|                RequestElement,
 | |
|                30 * sizeof (CHAR16),
 | |
|                L"&OFFSET=%x&WIDTH=%x",
 | |
|                Question->VarStoreInfo.VarOffset,
 | |
|                Question->StorageWidth
 | |
|                );
 | |
|     Question->BlockName = AllocateCopyPool ((StrLen + 1) * sizeof (CHAR16), RequestElement);
 | |
|   } else {
 | |
|     StrLen = UnicodeSPrint (RequestElement, 30 * sizeof (CHAR16), L"&%s", Question->VariableName);
 | |
|   }
 | |
| 
 | |
|   if ((Question->Operand == EFI_IFR_PASSWORD_OP) && ((Question->QuestionFlags & EFI_IFR_FLAG_CALLBACK) == EFI_IFR_FLAG_CALLBACK)) {
 | |
|     //
 | |
|     // Password with CALLBACK flag is stored in encoded format,
 | |
|     // so don't need to append it to <ConfigRequest>
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Append <RequestElement> to <ConfigRequest>
 | |
|   //
 | |
|   if (StrLen > Storage->SpareStrLen) {
 | |
|     //
 | |
|     // Old String buffer is not sufficient for RequestElement, allocate a new one
 | |
|     //
 | |
|     StringSize = (Storage->ConfigRequest != NULL) ? StrSize (Storage->ConfigRequest) : sizeof (CHAR16);
 | |
|     NewStr = AllocateZeroPool (StringSize + CONFIG_REQUEST_STRING_INCREMENTAL * sizeof (CHAR16));
 | |
|     if (Storage->ConfigRequest != NULL) {
 | |
|       CopyMem (NewStr, Storage->ConfigRequest, StringSize);
 | |
|       gBS->FreePool (Storage->ConfigRequest);
 | |
|     }
 | |
|     Storage->ConfigRequest = NewStr;
 | |
|     Storage->SpareStrLen   = CONFIG_REQUEST_STRING_INCREMENTAL;
 | |
|   }
 | |
| 
 | |
|   StrCat (Storage->ConfigRequest, RequestElement);
 | |
|   Storage->ElementCount++;
 | |
|   Storage->SpareStrLen -= StrLen;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Free resources of a Expression.
 | |
| 
 | |
|   @param  FormSet                Pointer of the Expression
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DestroyExpression (
 | |
|   IN FORM_EXPRESSION   *Expression
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY         *Link;
 | |
|   EXPRESSION_OPCODE  *OpCode;
 | |
| 
 | |
|   while (!IsListEmpty (&Expression->OpCodeListHead)) {
 | |
|     Link = GetFirstNode (&Expression->OpCodeListHead);
 | |
|     OpCode = EXPRESSION_OPCODE_FROM_LINK (Link);
 | |
|     RemoveEntryList (&OpCode->Link);
 | |
| 
 | |
|     SafeFreePool (OpCode->ValueList);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free this Expression
 | |
|   //
 | |
|   gBS->FreePool (Expression);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Free resources of a storage.
 | |
| 
 | |
|   @param  Storage                Pointer of the storage
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DestroyStorage (
 | |
|   IN FORMSET_STORAGE   *Storage
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY         *Link;
 | |
|   NAME_VALUE_NODE    *NameValueNode;
 | |
| 
 | |
|   if (Storage == NULL) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   SafeFreePool (Storage->Name);
 | |
|   SafeFreePool (Storage->Buffer);
 | |
|   SafeFreePool (Storage->EditBuffer);
 | |
| 
 | |
|   while (!IsListEmpty (&Storage->NameValueListHead)) {
 | |
|     Link = GetFirstNode (&Storage->NameValueListHead);
 | |
|     NameValueNode = NAME_VALUE_NODE_FROM_LINK (Link);
 | |
|     RemoveEntryList (&NameValueNode->Link);
 | |
| 
 | |
|     SafeFreePool (NameValueNode->Name);
 | |
|     SafeFreePool (NameValueNode->Value);
 | |
|     SafeFreePool (NameValueNode->EditValue);
 | |
|     SafeFreePool (NameValueNode);
 | |
|   }
 | |
| 
 | |
|   SafeFreePool (Storage->ConfigHdr);
 | |
|   SafeFreePool (Storage->ConfigRequest);
 | |
| 
 | |
|   gBS->FreePool (Storage);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Free resources of a Statement.
 | |
| 
 | |
|   @param  Statement              Pointer of the Statement
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DestroyStatement (
 | |
|   IN OUT FORM_BROWSER_STATEMENT  *Statement
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY        *Link;
 | |
|   QUESTION_DEFAULT  *Default;
 | |
|   QUESTION_OPTION   *Option;
 | |
|   FORM_EXPRESSION   *Expression;
 | |
| 
 | |
|   //
 | |
|   // Free Default value List
 | |
|   //
 | |
|   while (!IsListEmpty (&Statement->DefaultListHead)) {
 | |
|     Link = GetFirstNode (&Statement->DefaultListHead);
 | |
|     Default = QUESTION_DEFAULT_FROM_LINK (Link);
 | |
|     RemoveEntryList (&Default->Link);
 | |
| 
 | |
|     gBS->FreePool (Default);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free Options List
 | |
|   //
 | |
|   while (!IsListEmpty (&Statement->OptionListHead)) {
 | |
|     Link = GetFirstNode (&Statement->OptionListHead);
 | |
|     Option = QUESTION_OPTION_FROM_LINK (Link);
 | |
|     RemoveEntryList (&Option->Link);
 | |
| 
 | |
|     gBS->FreePool (Option);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free Inconsistent List
 | |
|   //
 | |
|   while (!IsListEmpty (&Statement->InconsistentListHead)) {
 | |
|     Link = GetFirstNode (&Statement->InconsistentListHead);
 | |
|     Expression = FORM_EXPRESSION_FROM_LINK (Link);
 | |
|     RemoveEntryList (&Expression->Link);
 | |
| 
 | |
|     DestroyExpression (Expression);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free NoSubmit List
 | |
|   //
 | |
|   while (!IsListEmpty (&Statement->NoSubmitListHead)) {
 | |
|     Link = GetFirstNode (&Statement->NoSubmitListHead);
 | |
|     Expression = FORM_EXPRESSION_FROM_LINK (Link);
 | |
|     RemoveEntryList (&Expression->Link);
 | |
| 
 | |
|     DestroyExpression (Expression);
 | |
|   }
 | |
| 
 | |
|   SafeFreePool (Statement->VariableName);
 | |
|   SafeFreePool (Statement->BlockName);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Free resources of a Form.
 | |
| 
 | |
|   @param  Form                   Pointer of the Form.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DestroyForm (
 | |
|   IN OUT FORM_BROWSER_FORM  *Form
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY              *Link;
 | |
|   FORM_EXPRESSION         *Expression;
 | |
|   FORM_BROWSER_STATEMENT  *Statement;
 | |
| 
 | |
|   //
 | |
|   // Free Form Expressions
 | |
|   //
 | |
|   while (!IsListEmpty (&Form->ExpressionListHead)) {
 | |
|     Link = GetFirstNode (&Form->ExpressionListHead);
 | |
|     Expression = FORM_EXPRESSION_FROM_LINK (Link);
 | |
|     RemoveEntryList (&Expression->Link);
 | |
| 
 | |
|     DestroyExpression (Expression);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free Statements/Questions
 | |
|   //
 | |
|   while (!IsListEmpty (&Form->StatementListHead)) {
 | |
|     Link = GetFirstNode (&Form->StatementListHead);
 | |
|     Statement = FORM_BROWSER_STATEMENT_FROM_LINK (Link);
 | |
|     RemoveEntryList (&Statement->Link);
 | |
| 
 | |
|     DestroyStatement (Statement);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free this Form
 | |
|   //
 | |
|   gBS->FreePool (Form);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Free resources allocated for a FormSet.
 | |
| 
 | |
|   @param  FormSet                Pointer of the FormSet
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DestroyFormSet (
 | |
|   IN OUT FORM_BROWSER_FORMSET  *FormSet
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY            *Link;
 | |
|   FORMSET_STORAGE       *Storage;
 | |
|   FORMSET_DEFAULTSTORE  *DefaultStore;
 | |
|   FORM_BROWSER_FORM     *Form;
 | |
| 
 | |
|   //
 | |
|   // Free IFR binary buffer
 | |
|   //
 | |
|   SafeFreePool (FormSet->IfrBinaryData);
 | |
| 
 | |
|   //
 | |
|   // Free FormSet Storage
 | |
|   //
 | |
|   if (FormSet->StorageListHead.ForwardLink != NULL) {
 | |
|     while (!IsListEmpty (&FormSet->StorageListHead)) {
 | |
|       Link = GetFirstNode (&FormSet->StorageListHead);
 | |
|       Storage = FORMSET_STORAGE_FROM_LINK (Link);
 | |
|       RemoveEntryList (&Storage->Link);
 | |
| 
 | |
|       DestroyStorage (Storage);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free FormSet Default Store
 | |
|   //
 | |
|   if (FormSet->DefaultStoreListHead.ForwardLink != NULL) {
 | |
|     while (!IsListEmpty (&FormSet->DefaultStoreListHead)) {
 | |
|       Link = GetFirstNode (&FormSet->DefaultStoreListHead);
 | |
|       DefaultStore = FORMSET_DEFAULTSTORE_FROM_LINK (Link);
 | |
|       RemoveEntryList (&DefaultStore->Link);
 | |
| 
 | |
|       gBS->FreePool (DefaultStore);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free Forms
 | |
|   //
 | |
|   if (FormSet->FormListHead.ForwardLink != NULL) {
 | |
|     while (!IsListEmpty (&FormSet->FormListHead)) {
 | |
|       Link = GetFirstNode (&FormSet->FormListHead);
 | |
|       Form = FORM_BROWSER_FORM_FROM_LINK (Link);
 | |
|       RemoveEntryList (&Form->Link);
 | |
| 
 | |
|       DestroyForm (Form);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   SafeFreePool (FormSet->StatementBuffer);
 | |
|   SafeFreePool (FormSet->ExpressionBuffer);
 | |
| 
 | |
|   SafeFreePool (FormSet);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Tell whether this Operand is an Expression OpCode or not
 | |
| 
 | |
|   @param  Operand                Operand of an IFR OpCode.
 | |
| 
 | |
|   @retval TRUE                   This is an Expression OpCode.
 | |
|   @retval FALSE                  Not an Expression OpCode.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsExpressionOpCode (
 | |
|   IN UINT8              Operand
 | |
|   )
 | |
| {
 | |
|   if (((Operand >= EFI_IFR_EQ_ID_VAL_OP) && (Operand <= EFI_IFR_NOT_OP)) ||
 | |
|       ((Operand >= EFI_IFR_MATCH_OP) && (Operand <= EFI_IFR_SPAN_OP)) ||
 | |
|       (Operand == EFI_IFR_CATENATE_OP) ||
 | |
|       (Operand == EFI_IFR_TO_LOWER_OP) ||
 | |
|       (Operand == EFI_IFR_TO_UPPER_OP) ||
 | |
|       (Operand == EFI_IFR_VERSION_OP)
 | |
|      ) {
 | |
|     return TRUE;
 | |
|   } else {
 | |
|     return FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Calculate number of Statemens(Questions) and Expression OpCodes.
 | |
| 
 | |
|   @param  FormSet                The FormSet to be counted.
 | |
|   @param  NumberOfStatement      Number of Statemens(Questions)
 | |
|   @param  NumberOfExpression     Number of Expression OpCodes
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| CountOpCodes (
 | |
|   IN  FORM_BROWSER_FORMSET  *FormSet,
 | |
|   IN OUT  UINT16            *NumberOfStatement,
 | |
|   IN OUT  UINT16            *NumberOfExpression
 | |
|   )
 | |
| {
 | |
|   UINT16  StatementCount;
 | |
|   UINT16  ExpressionCount;
 | |
|   UINT8   *OpCodeData;
 | |
|   UINTN   Offset;
 | |
|   UINTN   OpCodeLen;
 | |
| 
 | |
|   Offset = 0;
 | |
|   StatementCount = 0;
 | |
|   ExpressionCount = 0;
 | |
| 
 | |
|   while (Offset < FormSet->IfrBinaryLength) {
 | |
|     OpCodeData = FormSet->IfrBinaryData + Offset;
 | |
|     OpCodeLen = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
 | |
|     Offset += OpCodeLen;
 | |
| 
 | |
|     if (IsExpressionOpCode (((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode)) {
 | |
|       ExpressionCount++;
 | |
|     } else {
 | |
|       StatementCount++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   *NumberOfStatement = StatementCount;
 | |
|   *NumberOfExpression = ExpressionCount;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Parse opcodes in the formset IFR binary.
 | |
| 
 | |
|   @param  FormSet                Pointer of the FormSet data structure.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Opcode parse success.
 | |
|   @retval Other                  Opcode parse fail.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| ParseOpCodes (
 | |
|   IN FORM_BROWSER_FORMSET              *FormSet
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   UINT16                  Index;
 | |
|   FORM_BROWSER_FORM       *CurrentForm;
 | |
|   FORM_BROWSER_STATEMENT  *CurrentStatement;
 | |
|   EXPRESSION_OPCODE       *ExpressionOpCode;
 | |
|   FORM_EXPRESSION         *CurrentExpression;
 | |
|   UINT8                   Operand;
 | |
|   UINT8                   Scope;
 | |
|   UINTN                   OpCodeOffset;
 | |
|   UINTN                   OpCodeLength;
 | |
|   UINT8                   *OpCodeData;
 | |
|   UINT8                   ScopeOpCode;
 | |
|   FORMSET_STORAGE         *Storage;
 | |
|   FORMSET_DEFAULTSTORE    *DefaultStore;
 | |
|   QUESTION_DEFAULT        *CurrentDefault;
 | |
|   QUESTION_OPTION         *CurrentOption;
 | |
|   CHAR8                   *AsciiString;
 | |
|   UINT16                  NumberOfStatement;
 | |
|   UINT16                  NumberOfExpression;
 | |
|   EFI_IMAGE_ID            *ImageId;
 | |
|   BOOLEAN                 SuppressForOption;
 | |
|   BOOLEAN                 InScopeOptionSuppress;
 | |
|   FORM_EXPRESSION         *OptionSuppressExpression;
 | |
|   BOOLEAN                 InScopeDisable;
 | |
|   UINT16                  DepthOfDisable;
 | |
|   BOOLEAN                 OpCodeDisabled;
 | |
|   BOOLEAN                 SingleOpCodeExpression;
 | |
|   BOOLEAN                 InScopeDefault;
 | |
|   EFI_HII_VALUE           *Value;
 | |
| 
 | |
|   mInScopeSubtitle         = FALSE;
 | |
|   SuppressForOption        = FALSE;
 | |
|   mInScopeSuppress         = FALSE;
 | |
|   InScopeOptionSuppress    = FALSE;
 | |
|   mInScopeGrayOut          = FALSE;
 | |
|   InScopeDisable           = FALSE;
 | |
|   DepthOfDisable           = 0;
 | |
|   OpCodeDisabled           = FALSE;
 | |
|   SingleOpCodeExpression   = FALSE;
 | |
|   InScopeDefault           = FALSE;
 | |
|   CurrentExpression        = NULL;
 | |
|   CurrentDefault           = NULL;
 | |
|   CurrentOption            = NULL;
 | |
|   OptionSuppressExpression = NULL;
 | |
| 
 | |
|   //
 | |
|   // Get the number of Statements and Expressions
 | |
|   //
 | |
|   CountOpCodes (FormSet, &NumberOfStatement, &NumberOfExpression);
 | |
| 
 | |
|   mStatementIndex = 0;
 | |
|   FormSet->StatementBuffer = AllocateZeroPool (NumberOfStatement * sizeof (FORM_BROWSER_STATEMENT));
 | |
|   if (FormSet->StatementBuffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   mExpressionOpCodeIndex = 0;
 | |
|   FormSet->ExpressionBuffer = AllocateZeroPool (NumberOfExpression * sizeof (EXPRESSION_OPCODE));
 | |
|   if (FormSet->ExpressionBuffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   InitializeListHead (&FormSet->StorageListHead);
 | |
|   InitializeListHead (&FormSet->DefaultStoreListHead);
 | |
|   InitializeListHead (&FormSet->FormListHead);
 | |
| 
 | |
|   CurrentForm = NULL;
 | |
|   CurrentStatement = NULL;
 | |
| 
 | |
|   ResetScopeStack ();
 | |
| 
 | |
|   OpCodeOffset = 0;
 | |
|   while (OpCodeOffset < FormSet->IfrBinaryLength) {
 | |
|     OpCodeData = FormSet->IfrBinaryData + OpCodeOffset;
 | |
| 
 | |
|     OpCodeLength = ((EFI_IFR_OP_HEADER *) OpCodeData)->Length;
 | |
|     OpCodeOffset += OpCodeLength;
 | |
|     Operand = ((EFI_IFR_OP_HEADER *) OpCodeData)->OpCode;
 | |
|     Scope = ((EFI_IFR_OP_HEADER *) OpCodeData)->Scope;
 | |
| 
 | |
|     //
 | |
|     // If scope bit set, push onto scope stack
 | |
|     //
 | |
|     if (Scope != 0) {
 | |
|       PushScope (Operand);
 | |
|     }
 | |
| 
 | |
|     if (OpCodeDisabled) {
 | |
|       //
 | |
|       // DisableIf Expression is evaluated to be TRUE, try to find its end.
 | |
|       // Here only cares the EFI_IFR_DISABLE_IF and EFI_IFR_END
 | |
|       //
 | |
|       if (Operand == EFI_IFR_DISABLE_IF_OP) {
 | |
|         DepthOfDisable++;
 | |
|       } else if (Operand == EFI_IFR_END_OP) {
 | |
|         Status = PopScope (&ScopeOpCode);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           return Status;
 | |
|         }
 | |
| 
 | |
|         if (ScopeOpCode == EFI_IFR_DISABLE_IF_OP) {
 | |
|           if (DepthOfDisable == 0) {
 | |
|             InScopeDisable = FALSE;
 | |
|             OpCodeDisabled = FALSE;
 | |
|           } else {
 | |
|             DepthOfDisable--;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (IsExpressionOpCode (Operand)) {
 | |
|       ExpressionOpCode = &FormSet->ExpressionBuffer[mExpressionOpCodeIndex];
 | |
|       mExpressionOpCodeIndex++;
 | |
| 
 | |
|       ExpressionOpCode->Signature = EXPRESSION_OPCODE_SIGNATURE;
 | |
|       ExpressionOpCode->Operand = Operand;
 | |
|       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));
 | |
| 
 | |
|         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));
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_EQ_ID_LIST_OP:
 | |
|         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
 | |
|         CopyMem (&ExpressionOpCode->ListLength, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->ListLength, sizeof (UINT16));
 | |
|         ExpressionOpCode->ValueList = AllocateCopyPool (ExpressionOpCode->ListLength * sizeof (UINT16), &((EFI_IFR_EQ_ID_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_THIS_OP:
 | |
|         ExpressionOpCode->QuestionId = CurrentStatement->QuestionId;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_QUESTION_REF1_OP:
 | |
|         CopyMem (&ExpressionOpCode->QuestionId, &((EFI_IFR_EQ_ID_LIST *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
 | |
|         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_OTHER;
 | |
|         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 (&CurrentExpression->OpCodeListHead, &ExpressionOpCode->Link);
 | |
| 
 | |
|       if (SingleOpCodeExpression) {
 | |
|         //
 | |
|         // There are two cases to indicate the end of an Expression:
 | |
|         // for single OpCode expression: one Expression OpCode
 | |
|         // for expression consists of more than one OpCode: EFI_IFR_END
 | |
|         //
 | |
|         SingleOpCodeExpression = FALSE;
 | |
| 
 | |
|         if (InScopeDisable) {
 | |
|           //
 | |
|           // Evaluate DisableIf expression
 | |
|           //
 | |
|           Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             return Status;
 | |
|           }
 | |
|           if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
 | |
|             return EFI_INVALID_PARAMETER;
 | |
|           }
 | |
| 
 | |
|           OpCodeDisabled = CurrentExpression->Result.Value.b;
 | |
|         }
 | |
| 
 | |
|         CurrentExpression = NULL;
 | |
|       }
 | |
| 
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Parse the Opcode
 | |
|     //
 | |
|     switch (Operand) {
 | |
| 
 | |
|     case EFI_IFR_FORM_SET_OP:
 | |
|       //
 | |
|       // check the formset GUID
 | |
|       //
 | |
|       if (CompareMem (&FormSet->Guid, &((EFI_IFR_FORM_SET *) OpCodeData)->Guid, sizeof (EFI_GUID)) != 0) {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|       CopyMem (&FormSet->FormSetTitle, &((EFI_IFR_FORM_SET *) OpCodeData)->FormSetTitle, sizeof (EFI_STRING_ID));
 | |
|       CopyMem (&FormSet->Help,         &((EFI_IFR_FORM_SET *) OpCodeData)->Help,         sizeof (EFI_STRING_ID));
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_FORM_OP:
 | |
|       //
 | |
|       // Create a new Form for this FormSet
 | |
|       //
 | |
|       CurrentForm = AllocateZeroPool (sizeof (FORM_BROWSER_FORM));
 | |
|       CurrentForm->Signature = FORM_BROWSER_FORM_SIGNATURE;
 | |
|       InitializeListHead (&CurrentForm->ExpressionListHead);
 | |
|       InitializeListHead (&CurrentForm->StatementListHead);
 | |
| 
 | |
|       CopyMem (&CurrentForm->FormId,    &((EFI_IFR_FORM *) OpCodeData)->FormId,    sizeof (UINT16));
 | |
|       CopyMem (&CurrentForm->FormTitle, &((EFI_IFR_FORM *) OpCodeData)->FormTitle, sizeof (EFI_STRING_ID));
 | |
| 
 | |
|       //
 | |
|       // Insert into Form list of this FormSet
 | |
|       //
 | |
|       InsertTailList (&FormSet->FormListHead, &CurrentForm->Link);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Storage
 | |
|     //
 | |
|     case EFI_IFR_VARSTORE_OP:
 | |
|       //
 | |
|       // Create a buffer Storage for this FormSet
 | |
|       //
 | |
|       Storage = CreateStorage (FormSet);
 | |
|       Storage->Type = EFI_HII_VARSTORE_BUFFER;
 | |
| 
 | |
|       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
 | |
|       CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE *) OpCodeData)->Guid,       sizeof (EFI_GUID));
 | |
|       CopyMem (&Storage->Size,       &((EFI_IFR_VARSTORE *) OpCodeData)->Size,       sizeof (UINT16));
 | |
| 
 | |
|       Storage->Buffer = AllocateZeroPool (Storage->Size);
 | |
|       Storage->EditBuffer = AllocateZeroPool (Storage->Size);
 | |
| 
 | |
|       AsciiString = (CHAR8 *) ((EFI_IFR_VARSTORE *) OpCodeData)->Name;
 | |
|       Storage->Name = AllocateZeroPool (AsciiStrSize (AsciiString) * 2);
 | |
|       ASSERT (Storage->Name != NULL);
 | |
|       for (Index = 0; AsciiString[Index] != 0; Index++) {
 | |
|         Storage->Name[Index] = (CHAR16) AsciiString[Index];
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Initialize <ConfigHdr>
 | |
|       //
 | |
|       InitializeConfigHdr (FormSet, Storage);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_VARSTORE_NAME_VALUE_OP:
 | |
|       //
 | |
|       // Create a name/value Storage for this FormSet
 | |
|       //
 | |
|       Storage = CreateStorage (FormSet);
 | |
|       Storage->Type = EFI_HII_VARSTORE_NAME_VALUE;
 | |
| 
 | |
|       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
 | |
|       CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE_NAME_VALUE *) OpCodeData)->Guid,       sizeof (EFI_GUID));
 | |
| 
 | |
|       //
 | |
|       // Initialize <ConfigHdr>
 | |
|       //
 | |
|       InitializeConfigHdr (FormSet, Storage);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_VARSTORE_EFI_OP:
 | |
|       //
 | |
|       // Create a EFI variable Storage for this FormSet
 | |
|       //
 | |
|       Storage = CreateStorage (FormSet);
 | |
|       Storage->Type = EFI_HII_VARSTORE_EFI_VARIABLE;
 | |
| 
 | |
|       CopyMem (&Storage->VarStoreId, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->VarStoreId, sizeof (EFI_VARSTORE_ID));
 | |
|       CopyMem (&Storage->Guid,       &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Guid,       sizeof (EFI_GUID));
 | |
|       CopyMem (&Storage->Attributes, &((EFI_IFR_VARSTORE_EFI *) OpCodeData)->Attributes, sizeof (UINT32));
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // DefaultStore
 | |
|     //
 | |
|     case EFI_IFR_DEFAULTSTORE_OP:
 | |
|       DefaultStore = AllocateZeroPool (sizeof (FORMSET_DEFAULTSTORE));
 | |
|       DefaultStore->Signature = FORMSET_DEFAULTSTORE_SIGNATURE;
 | |
| 
 | |
|       CopyMem (&DefaultStore->DefaultId,   &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultId,   sizeof (UINT16));
 | |
|       CopyMem (&DefaultStore->DefaultName, &((EFI_IFR_DEFAULTSTORE *) OpCodeData)->DefaultName, sizeof (EFI_STRING_ID));
 | |
| 
 | |
|       //
 | |
|       // Insert to DefaultStore list of this Formset
 | |
|       //
 | |
|       InsertTailList (&FormSet->DefaultStoreListHead, &DefaultStore->Link);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Statements
 | |
|     //
 | |
|     case EFI_IFR_SUBTITLE_OP:
 | |
|       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
 | |
|       CurrentStatement->Flags = ((EFI_IFR_SUBTITLE *) OpCodeData)->Flags;
 | |
| 
 | |
|       if (Scope != 0) {
 | |
|         mInScopeSubtitle = TRUE;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TEXT_OP:
 | |
|       CurrentStatement = CreateStatement (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       CopyMem (&CurrentStatement->TextTwo, &((EFI_IFR_TEXT *) OpCodeData)->TextTwo, sizeof (EFI_STRING_ID));
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Questions
 | |
|     //
 | |
|     case EFI_IFR_ACTION_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       if (OpCodeLength == sizeof (EFI_IFR_ACTION_1)) {
 | |
|         //
 | |
|         // No QuestionConfig present, so no configuration string will be processed
 | |
|         //
 | |
|         CurrentStatement->QuestionConfig = 0;
 | |
|       } else {
 | |
|         CopyMem (&CurrentStatement->QuestionConfig, &((EFI_IFR_ACTION *) OpCodeData)->QuestionConfig, sizeof (EFI_STRING_ID));
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_RESET_BUTTON_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       CopyMem (&CurrentStatement->DefaultId, &((EFI_IFR_RESET_BUTTON *) OpCodeData)->DefaultId, sizeof (EFI_DEFAULT_ID));
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_REF_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       CopyMem (&CurrentStatement->RefFormId, &((EFI_IFR_REF *) OpCodeData)->FormId, sizeof (EFI_FORM_ID));
 | |
|       if (OpCodeLength >= sizeof (EFI_IFR_REF2)) {
 | |
|         CopyMem (&CurrentStatement->RefQuestionId, &((EFI_IFR_REF2 *) OpCodeData)->QuestionId, sizeof (EFI_QUESTION_ID));
 | |
| 
 | |
|         if (OpCodeLength >= sizeof (EFI_IFR_REF3)) {
 | |
|           CopyMem (&CurrentStatement->RefFormSetId, &((EFI_IFR_REF3 *) OpCodeData)->FormSetId, sizeof (EFI_GUID));
 | |
| 
 | |
|           if (OpCodeLength >= sizeof (EFI_IFR_REF4)) {
 | |
|             CopyMem (&CurrentStatement->RefDevicePath, &((EFI_IFR_REF4 *) OpCodeData)->DevicePath, sizeof (EFI_STRING_ID));
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_ONE_OF_OP:
 | |
|     case EFI_IFR_NUMERIC_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       CurrentStatement->Flags = ((EFI_IFR_ONE_OF *) OpCodeData)->Flags;
 | |
|       Value = &CurrentStatement->HiiValue;
 | |
| 
 | |
|       switch (CurrentStatement->Flags & EFI_IFR_NUMERIC_SIZE) {
 | |
|       case EFI_IFR_NUMERIC_SIZE_1:
 | |
|         CurrentStatement->Minimum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MinValue;
 | |
|         CurrentStatement->Maximum = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.MaxValue;
 | |
|         CurrentStatement->Step    = ((EFI_IFR_NUMERIC *) OpCodeData)->data.u8.Step;
 | |
|         CurrentStatement->StorageWidth = sizeof (UINT8);
 | |
|         Value->Type = EFI_IFR_TYPE_NUM_SIZE_8;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_NUMERIC_SIZE_2:
 | |
|         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MinValue, sizeof (UINT16));
 | |
|         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.MaxValue, sizeof (UINT16));
 | |
|         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u16.Step,     sizeof (UINT16));
 | |
|         CurrentStatement->StorageWidth = sizeof (UINT16);
 | |
|         Value->Type = EFI_IFR_TYPE_NUM_SIZE_16;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_NUMERIC_SIZE_4:
 | |
|         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MinValue, sizeof (UINT32));
 | |
|         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.MaxValue, sizeof (UINT32));
 | |
|         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u32.Step,     sizeof (UINT32));
 | |
|         CurrentStatement->StorageWidth = sizeof (UINT32);
 | |
|         Value->Type = EFI_IFR_TYPE_NUM_SIZE_32;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_NUMERIC_SIZE_8:
 | |
|         CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MinValue, sizeof (UINT64));
 | |
|         CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.MaxValue, sizeof (UINT64));
 | |
|         CopyMem (&CurrentStatement->Step,    &((EFI_IFR_NUMERIC *) OpCodeData)->data.u64.Step,     sizeof (UINT64));
 | |
|         CurrentStatement->StorageWidth = sizeof (UINT64);
 | |
|         Value->Type = EFI_IFR_TYPE_NUM_SIZE_64;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InitializeRequestElement (FormSet, CurrentStatement);
 | |
| 
 | |
|       if ((Operand == EFI_IFR_ONE_OF_OP) && Scope != 0) {
 | |
|         SuppressForOption = TRUE;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_ORDERED_LIST_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       CurrentStatement->Flags = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->Flags;
 | |
|       CurrentStatement->MaxContainers = ((EFI_IFR_ORDERED_LIST *) OpCodeData)->MaxContainers;
 | |
|       CurrentStatement->StorageWidth = (UINT16)(CurrentStatement->MaxContainers * sizeof (UINT8));
 | |
|       InitializeRequestElement (FormSet, CurrentStatement);
 | |
| 
 | |
|       //
 | |
|       // No buffer type is defined in EFI_IFR_TYPE_VALUE, so a Configuration Driver
 | |
|       // has to use FormBrowser2.Callback() to retrieve the uncommited data for
 | |
|       // an interactive orderedlist (i.e. with EFI_IFR_FLAG_CALLBACK flag set).
 | |
|       //
 | |
|       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_OTHER;
 | |
|       CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth);
 | |
| 
 | |
|       if (Scope != 0) {
 | |
|         SuppressForOption = TRUE;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_CHECKBOX_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       CurrentStatement->Flags = ((EFI_IFR_CHECKBOX *) OpCodeData)->Flags;
 | |
|       CurrentStatement->StorageWidth = sizeof (BOOLEAN);
 | |
|       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_BOOLEAN;
 | |
| 
 | |
|       InitializeRequestElement (FormSet, CurrentStatement);
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_STRING_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       //
 | |
|       // MinSize is the minimum number of characters that can be accepted for this opcode,
 | |
|       // MaxSize is the maximum number of characters that can be accepted for this opcode.
 | |
|       // The characters are stored as Unicode, so the storage width should multiply 2.
 | |
|       //
 | |
|       CurrentStatement->Minimum = ((EFI_IFR_STRING *) OpCodeData)->MinSize;
 | |
|       CurrentStatement->Maximum = ((EFI_IFR_STRING *) OpCodeData)->MaxSize;
 | |
|       CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
 | |
|       CurrentStatement->Flags = ((EFI_IFR_STRING *) OpCodeData)->Flags;
 | |
| 
 | |
|       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
 | |
|       CurrentStatement->BufferValue = AllocateZeroPool (CurrentStatement->StorageWidth + sizeof (CHAR16));
 | |
| 
 | |
|       InitializeRequestElement (FormSet, CurrentStatement);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_PASSWORD_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       //
 | |
|       // MinSize is the minimum number of characters that can be accepted for this opcode,
 | |
|       // MaxSize is the maximum number of characters that can be accepted for this opcode.
 | |
|       // The characters are stored as Unicode, so the storage width should multiply 2.
 | |
|       //
 | |
|       CopyMem (&CurrentStatement->Minimum, &((EFI_IFR_PASSWORD *) OpCodeData)->MinSize, sizeof (UINT16));
 | |
|       CopyMem (&CurrentStatement->Maximum, &((EFI_IFR_PASSWORD *) OpCodeData)->MaxSize, sizeof (UINT16));
 | |
|       CurrentStatement->StorageWidth = (UINT16)((UINTN) CurrentStatement->Maximum * sizeof (CHAR16));
 | |
| 
 | |
|       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_STRING;
 | |
|       CurrentStatement->BufferValue = AllocateZeroPool ((CurrentStatement->StorageWidth + sizeof (CHAR16)));
 | |
| 
 | |
|       InitializeRequestElement (FormSet, CurrentStatement);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_DATE_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       CurrentStatement->Flags = ((EFI_IFR_DATE *) OpCodeData)->Flags;
 | |
|       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_DATE;
 | |
| 
 | |
|       if ((CurrentStatement->Flags & EFI_QF_DATE_STORAGE) == QF_DATE_STORAGE_NORMAL) {
 | |
|         CurrentStatement->StorageWidth = sizeof (EFI_HII_DATE);
 | |
| 
 | |
|         InitializeRequestElement (FormSet, CurrentStatement);
 | |
|       } else {
 | |
|         //
 | |
|         // Don't assign storage for RTC type of date/time
 | |
|         //
 | |
|         CurrentStatement->Storage = NULL;
 | |
|         CurrentStatement->StorageWidth = 0;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TIME_OP:
 | |
|       CurrentStatement = CreateQuestion (OpCodeData, FormSet, CurrentForm);
 | |
| 
 | |
|       CurrentStatement->Flags = ((EFI_IFR_TIME *) OpCodeData)->Flags;
 | |
|       CurrentStatement->HiiValue.Type = EFI_IFR_TYPE_TIME;
 | |
| 
 | |
|       if ((CurrentStatement->Flags & QF_TIME_STORAGE) == QF_TIME_STORAGE_NORMAL) {
 | |
|         CurrentStatement->StorageWidth = sizeof (EFI_IFR_TIME);
 | |
| 
 | |
|         InitializeRequestElement (FormSet, CurrentStatement);
 | |
|       } else {
 | |
|         //
 | |
|         // Don't assign storage for RTC type of date/time
 | |
|         //
 | |
|         CurrentStatement->Storage = NULL;
 | |
|         CurrentStatement->StorageWidth = 0;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Default
 | |
|     //
 | |
|     case EFI_IFR_DEFAULT_OP:
 | |
|       //
 | |
|       // EFI_IFR_DEFAULT appear in scope of a Question,
 | |
|       // It creates a default value for the current question.
 | |
|       // A Question may have more than one Default value which have different default types.
 | |
|       //
 | |
|       CurrentDefault = AllocateZeroPool (sizeof (QUESTION_DEFAULT));
 | |
|       CurrentDefault->Signature = QUESTION_DEFAULT_SIGNATURE;
 | |
| 
 | |
|       CurrentDefault->Value.Type = ((EFI_IFR_DEFAULT *) OpCodeData)->Type;
 | |
|       CopyMem (&CurrentDefault->DefaultId, &((EFI_IFR_DEFAULT *) OpCodeData)->DefaultId, sizeof (UINT16));
 | |
|       CopyMem (&CurrentDefault->Value.Value, &((EFI_IFR_DEFAULT *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
 | |
|       ExtendValueToU64 (&CurrentDefault->Value);
 | |
| 
 | |
|       //
 | |
|       // Insert to Default Value list of current Question
 | |
|       //
 | |
|       InsertTailList (&CurrentStatement->DefaultListHead, &CurrentDefault->Link);
 | |
| 
 | |
|       if (Scope != 0) {
 | |
|         InScopeDefault = TRUE;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Option
 | |
|     //
 | |
|     case EFI_IFR_ONE_OF_OPTION_OP:
 | |
|       //
 | |
|       // EFI_IFR_ONE_OF_OPTION appear in scope of a Question.
 | |
|       // It create a selection for use in current Question.
 | |
|       //
 | |
|       CurrentOption = AllocateZeroPool (sizeof (QUESTION_OPTION));
 | |
|       CurrentOption->Signature = QUESTION_OPTION_SIGNATURE;
 | |
| 
 | |
|       CurrentOption->Flags = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Flags;
 | |
|       CurrentOption->Value.Type = ((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Type;
 | |
|       CopyMem (&CurrentOption->Text, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Option, sizeof (EFI_STRING_ID));
 | |
|       CopyMem (&CurrentOption->Value.Value, &((EFI_IFR_ONE_OF_OPTION *) OpCodeData)->Value, sizeof (EFI_IFR_TYPE_VALUE));
 | |
|       ExtendValueToU64 (&CurrentOption->Value);
 | |
| 
 | |
|       if (InScopeOptionSuppress) {
 | |
|         CurrentOption->SuppressExpression = OptionSuppressExpression;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Insert to Option list of current Question
 | |
|       //
 | |
|       InsertTailList (&CurrentStatement->OptionListHead, &CurrentOption->Link);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Conditional
 | |
|     //
 | |
|     case EFI_IFR_NO_SUBMIT_IF_OP:
 | |
|     case EFI_IFR_INCONSISTENT_IF_OP:
 | |
|       //
 | |
|       // Create an Expression node
 | |
|       //
 | |
|       CurrentExpression = CreateExpression (CurrentForm);
 | |
|       CopyMem (&CurrentExpression->Error, &((EFI_IFR_INCONSISTENT_IF *) OpCodeData)->Error, sizeof (EFI_STRING_ID));
 | |
| 
 | |
|       if (Operand == EFI_IFR_NO_SUBMIT_IF_OP) {
 | |
|         CurrentExpression->Type = EFI_HII_EXPRESSION_NO_SUBMIT_IF;
 | |
|         InsertTailList (&CurrentStatement->NoSubmitListHead, &CurrentExpression->Link);
 | |
|       } else {
 | |
|         CurrentExpression->Type = EFI_HII_EXPRESSION_INCONSISTENT_IF;
 | |
|         InsertTailList (&CurrentStatement->InconsistentListHead, &CurrentExpression->Link);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_SUPPRESS_IF_OP:
 | |
|       //
 | |
|       // Question and Option will appear in scope of this OpCode
 | |
|       //
 | |
|       CurrentExpression = CreateExpression (CurrentForm);
 | |
|       CurrentExpression->Type = EFI_HII_EXPRESSION_SUPPRESS_IF;
 | |
|       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
 | |
| 
 | |
|       if (SuppressForOption) {
 | |
|         InScopeOptionSuppress = TRUE;
 | |
|         OptionSuppressExpression = CurrentExpression;
 | |
|       } else {
 | |
|         mInScopeSuppress = TRUE;
 | |
|         mSuppressExpression = CurrentExpression;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_GRAY_OUT_IF_OP:
 | |
|       //
 | |
|       // Questions will appear in scope of this OpCode
 | |
|       //
 | |
|       CurrentExpression = CreateExpression (CurrentForm);
 | |
|       CurrentExpression->Type = EFI_HII_EXPRESSION_GRAY_OUT_IF;
 | |
|       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
 | |
| 
 | |
|       mInScopeGrayOut = TRUE;
 | |
|       mGrayOutExpression = CurrentExpression;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_DISABLE_IF_OP:
 | |
|       //
 | |
|       // The DisableIf expression should only rely on constant, so it could be
 | |
|       // evaluated at initialization and it will not be queued
 | |
|       //
 | |
|       CurrentExpression = AllocateZeroPool (sizeof (FORM_EXPRESSION));
 | |
|       CurrentExpression->Signature = FORM_EXPRESSION_SIGNATURE;
 | |
|       CurrentExpression->Type = EFI_HII_EXPRESSION_DISABLE_IF;
 | |
|       InitializeListHead (&CurrentExpression->OpCodeListHead);
 | |
| 
 | |
|       InScopeDisable = TRUE;
 | |
|       OpCodeDisabled = FALSE;
 | |
| 
 | |
|       //
 | |
|       // Take a look at next OpCode to see whether current expression consists
 | |
|       // of single OpCode
 | |
|       //
 | |
|       if (((EFI_IFR_OP_HEADER *) (OpCodeData + OpCodeLength))->Scope == 0) {
 | |
|         SingleOpCodeExpression = TRUE;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Expression
 | |
|     //
 | |
|     case EFI_IFR_VALUE_OP:
 | |
|       CurrentExpression = CreateExpression (CurrentForm);
 | |
|       CurrentExpression->Type = EFI_HII_EXPRESSION_VALUE;
 | |
|       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
 | |
| 
 | |
|       if (InScopeDefault) {
 | |
|         //
 | |
|         // Used for default (EFI_IFR_DEFAULT)
 | |
|         //
 | |
|         CurrentDefault->ValueExpression = CurrentExpression;
 | |
|       } else {
 | |
|         //
 | |
|         // If used for a question, then the question will be read-only
 | |
|         //
 | |
|         CurrentStatement->ValueExpression = CurrentExpression;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_RULE_OP:
 | |
|       CurrentExpression = CreateExpression (CurrentForm);
 | |
|       CurrentExpression->Type = EFI_HII_EXPRESSION_RULE;
 | |
| 
 | |
|       CurrentExpression->RuleId = ((EFI_IFR_RULE *) OpCodeData)->RuleId;
 | |
|       InsertTailList (&CurrentForm->ExpressionListHead, &CurrentExpression->Link);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Image
 | |
|     //
 | |
|     case EFI_IFR_IMAGE_OP:
 | |
|       //
 | |
|       // Get ScopeOpcode from top of stack
 | |
|       //
 | |
|       PopScope (&ScopeOpCode);
 | |
|       PushScope (ScopeOpCode);
 | |
| 
 | |
|       switch (ScopeOpCode) {
 | |
|       case EFI_IFR_FORM_SET_OP:
 | |
|         ImageId = &FormSet->ImageId;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_FORM_OP:
 | |
|         ImageId = &CurrentForm->ImageId;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_ONE_OF_OPTION_OP:
 | |
|         ImageId = &CurrentOption->ImageId;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         ImageId = &CurrentStatement->ImageId;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       CopyMem (ImageId, &((EFI_IFR_IMAGE *) OpCodeData)->Id, sizeof (EFI_IMAGE_ID));
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Refresh
 | |
|     //
 | |
|     case EFI_IFR_REFRESH_OP:
 | |
|       CurrentStatement->RefreshInterval = ((EFI_IFR_REFRESH *) OpCodeData)->RefreshInterval;
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Vendor specific
 | |
|     //
 | |
|     case EFI_IFR_GUID_OP:
 | |
|       if (CompareGuid (&gTianoHiiIfrGuid, (EFI_GUID *)(OpCodeData + sizeof (EFI_IFR_OP_HEADER)))) {
 | |
|         //
 | |
|         // Tiano specific GUIDed opcodes
 | |
|         //
 | |
|         switch (((EFI_IFR_GUID_LABEL *) OpCodeData)->ExtendOpCode) {
 | |
|         case EFI_IFR_EXTEND_OP_LABEL:
 | |
|           //
 | |
|           // just ignore label
 | |
|           //
 | |
|           break;
 | |
| 
 | |
|         case EFI_IFR_EXTEND_OP_BANNER:
 | |
|           if (FormSet->SubClass == EFI_FRONT_PAGE_SUBCLASS) {
 | |
|             CopyMem (
 | |
|               &BannerData->Banner[((EFI_IFR_GUID_BANNER *) OpCodeData)->LineNumber][
 | |
|               ((EFI_IFR_GUID_BANNER *) OpCodeData)->Alignment],
 | |
|               &((EFI_IFR_GUID_BANNER *) OpCodeData)->Title,
 | |
|               sizeof (EFI_STRING_ID)
 | |
|               );
 | |
|           }
 | |
|           break;
 | |
| 
 | |
|         case EFI_IFR_EXTEND_OP_CLASS:
 | |
|           CopyMem (&FormSet->Class, &((EFI_IFR_GUID_CLASS *) OpCodeData)->Class, sizeof (UINT16));
 | |
|           break;
 | |
| 
 | |
|         case EFI_IFR_EXTEND_OP_SUBCLASS:
 | |
|           CopyMem (&FormSet->SubClass, &((EFI_IFR_GUID_SUBCLASS *) OpCodeData)->SubClass, sizeof (UINT16));
 | |
|           break;
 | |
| 
 | |
|         default:
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Scope End
 | |
|     //
 | |
|     case EFI_IFR_END_OP:
 | |
|       Status = PopScope (&ScopeOpCode);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         ResetScopeStack ();
 | |
|         return Status;
 | |
|       }
 | |
| 
 | |
|       switch (ScopeOpCode) {
 | |
|       case EFI_IFR_FORM_SET_OP:
 | |
|         //
 | |
|         // End of FormSet, update FormSet IFR binary length
 | |
|         // to stop parsing substantial OpCodes
 | |
|         //
 | |
|         FormSet->IfrBinaryLength = OpCodeOffset;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_FORM_OP:
 | |
|         //
 | |
|         // End of Form
 | |
|         //
 | |
|         CurrentForm = NULL;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_ONE_OF_OPTION_OP:
 | |
|         //
 | |
|         // End of Option
 | |
|         //
 | |
|         CurrentOption = NULL;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_SUBTITLE_OP:
 | |
|         mInScopeSubtitle = FALSE;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_NO_SUBMIT_IF_OP:
 | |
|       case EFI_IFR_INCONSISTENT_IF_OP:
 | |
|         //
 | |
|         // Ignore end of EFI_IFR_NO_SUBMIT_IF and EFI_IFR_INCONSISTENT_IF
 | |
|         //
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_SUPPRESS_IF_OP:
 | |
|         if (SuppressForOption) {
 | |
|           InScopeOptionSuppress = FALSE;
 | |
|         } else {
 | |
|           mInScopeSuppress = FALSE;
 | |
|         }
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_GRAY_OUT_IF_OP:
 | |
|         mInScopeGrayOut = FALSE;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_DISABLE_IF_OP:
 | |
|         InScopeDisable = FALSE;
 | |
|         OpCodeDisabled = FALSE;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_ONE_OF_OP:
 | |
|       case EFI_IFR_ORDERED_LIST_OP:
 | |
|         SuppressForOption = FALSE;
 | |
|         break;
 | |
| 
 | |
|       case EFI_IFR_DEFAULT_OP:
 | |
|         InScopeDefault = FALSE;
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         if (IsExpressionOpCode (ScopeOpCode)) {
 | |
|           if (InScopeDisable) {
 | |
|             //
 | |
|             // Evaluate DisableIf expression
 | |
|             //
 | |
|             Status = EvaluateExpression (FormSet, CurrentForm, CurrentExpression);
 | |
|             if (EFI_ERROR (Status)) {
 | |
|               return Status;
 | |
|             }
 | |
|             if (CurrentExpression->Result.Type != EFI_IFR_TYPE_BOOLEAN) {
 | |
|               return EFI_INVALID_PARAMETER;
 | |
|             }
 | |
| 
 | |
|             OpCodeDisabled = CurrentExpression->Result.Value.b;
 | |
|             //
 | |
|             // DisableIf Expression is only used once and not quequed, free it
 | |
|             //
 | |
|             DestroyExpression (CurrentExpression);
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // End of current Expression
 | |
|           //
 | |
|           CurrentExpression = NULL;
 | |
|         }
 | |
|         break;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |