2. Added NULL pointer check before calling FreePool () to fix bugs when free memory. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2513 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			2220 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2220 lines
		
	
	
		
			72 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /**@file
 | |
|   Entry and initialization module for the browser.
 | |
| 
 | |
| Copyright (c) 2006 - 2007 Intel Corporation. <BR>
 | |
| 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"
 | |
| 
 | |
| FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = {
 | |
|   //
 | |
|   // Boot Manager
 | |
|   //
 | |
|   {
 | |
|     {
 | |
|       0x847bc3fe,
 | |
|       0xb974,
 | |
|       0x446d,
 | |
|       {
 | |
|         0x94,
 | |
|         0x49,
 | |
|         0x5a,
 | |
|         0xd5,
 | |
|         0x41,
 | |
|         0x2e,
 | |
|         0x99,
 | |
|         0x3b
 | |
|       }
 | |
|     },
 | |
|     NONE_FUNCTION_KEY_SETTING
 | |
|   },
 | |
|   //
 | |
|   // Device Manager
 | |
|   //
 | |
|   {
 | |
|     {
 | |
|       0x3ebfa8e6,
 | |
|       0x511d,
 | |
|       0x4b5b,
 | |
|       {
 | |
|         0xa9,
 | |
|         0x5f,
 | |
|         0xfb,
 | |
|         0x38,
 | |
|         0x26,
 | |
|         0xf,
 | |
|         0x1c,
 | |
|         0x27
 | |
|       }
 | |
|     },
 | |
|     NONE_FUNCTION_KEY_SETTING
 | |
|   },
 | |
|   //
 | |
|   // BMM Formset.
 | |
|   //
 | |
|   {
 | |
|     {
 | |
|       0x642237c7,
 | |
|       0x35d4,
 | |
|       0x472d,
 | |
|       {
 | |
|         0x83,
 | |
|         0x65,
 | |
|         0x12,
 | |
|         0xe0,
 | |
|         0xcc,
 | |
|         0xf2,
 | |
|         0x7a,
 | |
|         0x22
 | |
|       }
 | |
|     },
 | |
|     NONE_FUNCTION_KEY_SETTING
 | |
|   },
 | |
|   //
 | |
|   // BMM File Explorer Formset.
 | |
|   //
 | |
|   {
 | |
|     {
 | |
|       0x1f2d63e1,
 | |
|       0xfebd,
 | |
|       0x4dc7,
 | |
|       {
 | |
|         0x9c,
 | |
|         0xc5,
 | |
|         0xba,
 | |
|         0x2b,
 | |
|         0x1c,
 | |
|         0xef,
 | |
|         0x9c,
 | |
|         0x5b
 | |
|       }
 | |
|     },
 | |
|     NONE_FUNCTION_KEY_SETTING
 | |
|   },
 | |
| };
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| InitializeBinaryStructures (
 | |
|   IN  EFI_HII_HANDLE                           *Handle,
 | |
|   IN  BOOLEAN                                  UseDatabase,
 | |
|   IN  EFI_IFR_PACKET                           *Packet,
 | |
|   IN  UINT8                                    *NvMapOverride,
 | |
|   IN  UINTN                                    NumberOfIfrImages,
 | |
|   EFI_FILE_FORM_TAGS                           **FileFormTagsHead
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| InitializeTagStructures (
 | |
|   IN  EFI_IFR_BINARY                            *BinaryData,
 | |
|   OUT EFI_FILE_FORM_TAGS                        *FileFormTags
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| UI_MENU_OPTION        *
 | |
| DisplayHomePage (
 | |
|   IN UINTN                                    NumberOfIfrImages,
 | |
|   IN EFI_FILE_FORM_TAGS                       *FileFormTagsHead,
 | |
|   IN UINT8                                    *CallbackData
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| GetIfrBinaryData (
 | |
|   IN EFI_HII_PROTOCOL *Hii,
 | |
|   IN EFI_HII_HANDLE   HiiHandle,
 | |
|   IN EFI_IFR_PACKET   *Packet,
 | |
|   IN EFI_IFR_BINARY   *BinaryData
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| InstallPrint (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SendForm (
 | |
|   IN EFI_FORM_BROWSER_PROTOCOL        * This,
 | |
|   IN BOOLEAN                          UseDatabase,
 | |
|   IN EFI_HII_HANDLE                   * Handle,
 | |
|   IN UINTN                            HandleCount,
 | |
|   IN EFI_IFR_PACKET                   * Packet,
 | |
|   IN EFI_HANDLE                       CallbackHandle,
 | |
|   IN UINT8                            *NvMapOverride,
 | |
|   IN EFI_SCREEN_DESCRIPTOR            *ScreenDimensions, OPTIONAL
 | |
|   OUT BOOLEAN                         *ResetRequired OPTIONAL
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   This is the routine which an external caller uses to direct the browser
 | |
|   where to obtain it's information.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   UseDatabase -     If set to TRUE, then all information is retrieved from the HII database handle specified
 | |
|                     If set to FALSE, then the passed in Packet and CallbackHandle is used and Handle is ignored
 | |
| 
 | |
|   Handle -          A pointer to an array of Handles.  If HandleCount > 1 we display a list of the formsets for the handles specified
 | |
| 
 | |
|   HandleCount -     The number of Handles specified in Handle.
 | |
| 
 | |
|   Packet -          Valid only if UseDatabase is FALSE.  Packet defines the pages being passed into
 | |
|                     the browser.  This is composed of IFR data as well as String information.
 | |
| 
 | |
|   CallbackHandle -  The handle which contains the calling driver's EFI_FORM_CALLBACK_PROTOCOL interface.
 | |
| 
 | |
|   ScreenDimenions - This allows the browser to be called so that it occupies a portion of the physical screen instead of
 | |
|                     dynamically determining the screen dimensions.
 | |
| 
 | |
|   NvMapOverride -   This buffer is used only when there is no NV variable to define the current settings and the caller
 | |
|                     needs to provide to the browser the current settings for the "fake" NV variable.  If used, no saving
 | |
|                     of an NV variable will be possible.  This parameter is also ignored if HandleCount > 1.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_FORM_CALLBACK_PROTOCOL  *FormCallback;
 | |
|   EFI_FILE_FORM_TAGS          *FileFormTagsHead;
 | |
|   UI_MENU_OPTION              *Selection;
 | |
|   UI_MENU_OPTION              *AltSelection;
 | |
|   EFI_STATUS                  Status;
 | |
|   BOOLEAN                     Callback;
 | |
|   VOID                        *CallbackData;
 | |
|   EFI_HII_HANDLE              BackupHandle;
 | |
| 
 | |
|   ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
 | |
| 
 | |
|   gPreviousValue  = AllocatePool (0x1000);
 | |
|   CallbackData    = AllocatePool (0x10000);
 | |
|   ASSERT (gPreviousValue != NULL);
 | |
|   ASSERT (CallbackData != NULL);
 | |
| 
 | |
|   do {
 | |
|     //
 | |
|     // Seed the dimensions in the global
 | |
|     //
 | |
|     gST->ConOut->QueryMode (
 | |
|                   gST->ConOut,
 | |
|                   gST->ConOut->Mode->Mode,
 | |
|                   &gScreenDimensions.RightColumn,
 | |
|                   &gScreenDimensions.BottomRow
 | |
|                   );
 | |
| 
 | |
|     if (ScreenDimensions != NULL) {
 | |
|       //
 | |
|       // Check local dimension vs. global dimension.
 | |
|       //
 | |
|       if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) ||
 | |
|           (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow)
 | |
|           ) {
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       } else {
 | |
|         //
 | |
|         // Local dimension validation.
 | |
|         //
 | |
|         if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) &&
 | |
|             (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) &&
 | |
|             ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) &&
 | |
|             (
 | |
|               (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT +
 | |
|             SCROLL_ARROW_HEIGHT *
 | |
|             2 +
 | |
|             FRONT_PAGE_HEADER_HEIGHT +
 | |
|             FOOTER_HEIGHT +
 | |
|             1
 | |
|           )
 | |
|             ) {
 | |
|           CopyMem (&gScreenDimensions, ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR));
 | |
|         } else {
 | |
|           return EFI_INVALID_PARAMETER;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3);
 | |
|     gHelpBlockWidth   = gOptionBlockWidth;
 | |
|     gPromptBlockWidth = gOptionBlockWidth;
 | |
| 
 | |
|     //
 | |
|     // Initialize the strings for the browser, upon exit of the browser, the strings will be freed
 | |
|     //
 | |
|     InitializeBrowserStrings ();
 | |
| 
 | |
|     gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING;
 | |
|     gClassOfVfr         = EFI_SETUP_APPLICATION_SUBCLASS;
 | |
|     gResetRequired      = FALSE;
 | |
|     gExitRequired       = FALSE;
 | |
|     gSaveRequired       = FALSE;
 | |
|     gNvUpdateRequired   = FALSE;
 | |
|     gActiveIfr          = 0;
 | |
|     gConsistencyId      = 0;
 | |
|     gPriorMenuEntry     = 0;
 | |
|     BackupHandle        = *Handle;
 | |
|     gMenuRefreshHead    = NULL;
 | |
|     ASSERT (CallbackData);
 | |
|     ZeroMem (CallbackData, 0x10000);
 | |
| 
 | |
|     //
 | |
|     // We can recurse through this and might need to re-allocate this particular buffer
 | |
|     //
 | |
|     if (gPreviousValue == NULL) {
 | |
|       gPreviousValue = AllocatePool (0x1000);
 | |
|       ASSERT (gPreviousValue != NULL);
 | |
|     }
 | |
| 
 | |
|     Callback      = FALSE;
 | |
|     FormCallback  = NULL;
 | |
| 
 | |
|     if (CallbackHandle != NULL) {
 | |
|       //
 | |
|       // Retrieve the Callback protocol interface
 | |
|       //
 | |
|       Status = gBS->HandleProtocol (
 | |
|                       CallbackHandle,
 | |
|                       &gEfiFormCallbackProtocolGuid,
 | |
|                       (VOID **) &FormCallback
 | |
|                       );
 | |
| 
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         FreePool (CallbackData);
 | |
|         return Status;;
 | |
|       }
 | |
| 
 | |
|       Callback = TRUE;
 | |
|     }
 | |
|     //
 | |
|     // Initializes all the internal state structures for all IFR images in system
 | |
|     //
 | |
|     Status = InitializeBinaryStructures (Handle, UseDatabase, Packet, NvMapOverride, HandleCount, &FileFormTagsHead);
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreePool (CallbackData);
 | |
|       return Status;
 | |
|     }
 | |
|     //
 | |
|     // Beginning of the Presentation of the Data
 | |
|     //
 | |
|     if (UseDatabase && (HandleCount > 1)) {
 | |
|       Selection = DisplayHomePage (HandleCount, FileFormTagsHead, CallbackData);
 | |
|     } else {
 | |
|       //
 | |
|       // If passing something specific, we know there is only one Ifr
 | |
|       //
 | |
|       Selection = AllocateZeroPool (sizeof (UI_MENU_OPTION));
 | |
|       ASSERT (Selection != NULL);
 | |
|       Selection->IfrNumber  = 0;
 | |
|       Selection->Handle     = Handle[0];
 | |
|       UiInitMenu ();
 | |
|     }
 | |
| 
 | |
|     UiInitMenuList ();
 | |
| 
 | |
|     if (UseDatabase && (HandleCount > 1)) {
 | |
|       if (Selection == NULL) {
 | |
|         FreePool (CallbackData);
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
|     }
 | |
|     //
 | |
|     // Launch the setup browser with the user's selection information
 | |
|     //
 | |
|     AltSelection = SetupBrowser (Selection, Callback, FileFormTagsHead, CallbackData);
 | |
| 
 | |
|     //
 | |
|     // If the caller cares about Reset status, we can return to the caller if something happened that required a reset
 | |
|     //
 | |
|     if (ResetRequired != NULL) {
 | |
|       *ResetRequired = gResetRequired;
 | |
|     }
 | |
| 
 | |
|     if (Callback && (AltSelection != NULL)) {
 | |
|       if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) {
 | |
|         Status = FormCallback->Callback (
 | |
|                                 FormCallback,
 | |
|                                 AltSelection->ThisTag->Key,
 | |
|                                 CallbackData,
 | |
|                                 (EFI_HII_CALLBACK_PACKET **) &Packet
 | |
|                                 );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     *Handle = BackupHandle;
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreePool (CallbackData);
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     if (Callback && (AltSelection == NULL)) {
 | |
|       FreePool (CallbackData);
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     if (UseDatabase && (HandleCount > 1)) {
 | |
|     } else {
 | |
| 
 | |
|       if (gBinaryDataHead->UnRegisterOnExit) {
 | |
|         Hii->RemovePack (Hii, Handle[0]);
 | |
|       }
 | |
| 
 | |
|       if (Callback &&
 | |
|         ((AltSelection->ThisTag->SubClass == EFI_FRONT_PAGE_SUBCLASS) ||
 | |
|         (AltSelection->ThisTag->SubClass == EFI_SINGLE_USE_SUBCLASS))) {
 | |
|         //
 | |
|         // If this is the FrontPage, return after every selection
 | |
|         //
 | |
|         FreePool (Selection);
 | |
|         UiFreeMenu ();
 | |
| 
 | |
|         //
 | |
|         // Clean up the allocated data buffers
 | |
|         //
 | |
|         FreeData (FileFormTagsHead, NULL, NULL);
 | |
| 
 | |
|         gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
 | |
|         gST->ConOut->ClearScreen (gST->ConOut);
 | |
| 
 | |
|         FreePool (CallbackData);
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
| 
 | |
|       FreePool (Selection);
 | |
|       UiFreeMenu ();
 | |
| 
 | |
|       //
 | |
|       // Clean up the allocated data buffers
 | |
|       //
 | |
|       FreeData (FileFormTagsHead, NULL, NULL);
 | |
| 
 | |
|       gST->ConOut->ClearScreen (gST->ConOut);
 | |
| 
 | |
|       if (!Callback) {
 | |
|         FreePool (CallbackData);
 | |
|         return EFI_SUCCESS;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   } while (!EFI_ERROR (Status));
 | |
| 
 | |
|   FreePool (CallbackData);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InitializeSetup (
 | |
|   IN EFI_HANDLE           ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE     *SystemTable
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Initialize Setup
 | |
| 
 | |
| Arguments:
 | |
|   (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
 | |
| 
 | |
| Returns:
 | |
|   EFI_SUCCESS - Setup loaded.
 | |
|   other       - Setup Error
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_FORM_CONFIGURATION_DATA *FormData;
 | |
|   EFI_FORM_BROWSER_PROTOCOL   *FormBrowser;
 | |
|   EFI_HANDLE                  Handle;
 | |
|   EFI_HII_PACKAGES            *PackageList;
 | |
| 
 | |
|   //
 | |
|   // There will be only one FormConfig in the system
 | |
|   // If there is another out there, someone is trying to install us
 | |
|   // again.  Fail that scenario.
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (
 | |
|                   &gEfiFormBrowserProtocolGuid,
 | |
|                   NULL,
 | |
|                   (VOID **) &FormBrowser
 | |
|                   );
 | |
| 
 | |
|   gFirstIn = TRUE;
 | |
| 
 | |
|   //
 | |
|   // If there was no error, assume there is an installation and fail to load
 | |
|   //
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   FormData = AllocatePool (sizeof (EFI_FORM_CONFIGURATION_DATA));
 | |
| 
 | |
|   if (FormData == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   //
 | |
|   // Fill in HII data
 | |
|   //
 | |
|   FormData->Signature               = EFI_FORM_DATA_SIGNATURE;
 | |
|   FormData->FormConfig.SendForm     = SendForm;
 | |
|   FormData->FormConfig.CreatePopUp  = CreateDialog;
 | |
| 
 | |
|   //
 | |
|   // There should only be one HII image
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (
 | |
|                   &gEfiHiiProtocolGuid,
 | |
|                   NULL,
 | |
|                   (VOID **) &FormData->Hii
 | |
|                   );
 | |
| 
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   Hii         = FormData->Hii;
 | |
| 
 | |
|   PackageList = PreparePackages (1, &gEfiFormBrowserProtocolGuid, SetupBrowserStrings);
 | |
| 
 | |
|   Status      = Hii->NewPack (Hii, PackageList, &gHiiHandle);
 | |
| 
 | |
|   FreePool (PackageList);
 | |
| 
 | |
|   //
 | |
|   // Install protocol interface
 | |
|   //
 | |
|   Handle = NULL;
 | |
|   Status = gBS->InstallProtocolInterface (
 | |
|                   &Handle,
 | |
|                   &gEfiFormBrowserProtocolGuid,
 | |
|                   EFI_NATIVE_INTERFACE,
 | |
|                   &FormData->FormConfig
 | |
|                   );
 | |
| 
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   BannerData = AllocateZeroPool (sizeof (BANNER_DATA));
 | |
|   ASSERT (BannerData != NULL);
 | |
| 
 | |
|   Status = InstallPrint ();
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| GetQuestionHeader (
 | |
|   IN  EFI_TAG             *Tag,
 | |
|   IN  UINT8               *RawFormSet,
 | |
|   IN  UINT16              Index,
 | |
|   IN  EFI_FILE_FORM_TAGS  *FileFormTags,
 | |
|   IN  UINT16              CurrentVariable
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Initialize question tag's members.
 | |
| 
 | |
| Arguments:
 | |
|   Tag              - Pointer of the current EFI_TAG structure.
 | |
|   RawFormSet       - Pointer of the formset raw data.
 | |
|   Index            - Offset of the current opcode in the Ifr raw data.
 | |
|   FileFormTags     - Pointer of current EFI_FILE_FORM_TAGS structure.
 | |
|   CurrentVariable  - Current variable number.
 | |
| 
 | |
| Returns:
 | |
|   None.
 | |
| --*/
 | |
| {
 | |
|   EFI_VARIABLE_DEFINITION *VariableDefinition;
 | |
| 
 | |
|   Tag->NumberOfLines  = 1;
 | |
|   Tag->VariableNumber = CurrentVariable;
 | |
|   CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
 | |
|   CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
 | |
|   CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8));
 | |
|   CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16));
 | |
|   CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16));
 | |
| 
 | |
|   VariableDefinition = FileFormTags->VariableDefinitions;
 | |
| 
 | |
|   for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
 | |
|     //
 | |
|     // Have we found the correct variable for the request?
 | |
|     //
 | |
|     if (CurrentVariable == VariableDefinition->VariableId) {
 | |
|       if (VariableDefinition->VariableSize < (UINTN) (Tag->StorageStart + Tag->StorageWidth)) {
 | |
|         VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth);
 | |
|       }
 | |
| 
 | |
|       if (VariableDefinition->NvRamMap != NULL) {
 | |
|         //
 | |
|         // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise
 | |
|         // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)
 | |
|         //
 | |
|         if (Tag->StorageWidth == (UINT16) 1) {
 | |
|           CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16));
 | |
|         }
 | |
| 
 | |
|         if (Tag->StorageWidth == (UINT16) 2) {
 | |
|           Index = (UINT16)
 | |
|             (
 | |
|               VariableDefinition->NvRamMap[Tag->StorageStart] +
 | |
|               (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100)
 | |
|             );
 | |
|           CopyMem (&Tag->Value, &Index, sizeof (UINT16));
 | |
|         }
 | |
|       } else {
 | |
|         Index = 0;
 | |
|         CopyMem (&Tag->Value, &Index, sizeof (UINT16));
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| VOID
 | |
| GetNumericHeader (
 | |
|   IN  EFI_TAG             *Tag,
 | |
|   IN  UINT8               *RawFormSet,
 | |
|   IN  UINT16              Index,
 | |
|   IN  UINT16              NumberOfLines,
 | |
|   IN  EFI_FILE_FORM_TAGS  *FileFormTags,
 | |
|   IN  UINT16              CurrentVariable
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Initialize numeric tag's members.
 | |
| 
 | |
| Arguments:
 | |
|   Tag              - Pointer of the current EFI_TAG structure.
 | |
|   RawFormSet       - Pointer of the formset raw data.
 | |
|   Index            - Offset of the current opcode in the Ifr raw data.
 | |
|   NumberOfLines    - Number of lines this opcode occupied.
 | |
|   FileFormTags     - Pointer of current EFI_FILE_FORM_TAGS structure.
 | |
|   CurrentVariable  - Current variable number.
 | |
| 
 | |
| Returns:
 | |
|   None.
 | |
| --*/
 | |
| {
 | |
|   EFI_VARIABLE_DEFINITION *VariableDefinition;
 | |
| 
 | |
|   Tag->NumberOfLines  = NumberOfLines;
 | |
|   Tag->VariableNumber = CurrentVariable;
 | |
|   CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
 | |
|   CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16));
 | |
|   CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8));
 | |
|   CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16));
 | |
|   CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16));
 | |
|   CopyMem (&Tag->Minimum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Minimum, sizeof (UINT16));
 | |
|   CopyMem (&Tag->Maximum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Maximum, sizeof (UINT16));
 | |
|   CopyMem (&Tag->Step, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Step, sizeof (UINT16));
 | |
|   CopyMem (&Tag->Default, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Default, sizeof (UINT16));
 | |
|   Tag->ResetRequired  = (BOOLEAN) (((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Flags & EFI_IFR_FLAG_RESET_REQUIRED);
 | |
| 
 | |
|   VariableDefinition  = FileFormTags->VariableDefinitions;
 | |
| 
 | |
|   for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
 | |
|     //
 | |
|     // Have we found the correct variable for the request?
 | |
|     //
 | |
|     if (CurrentVariable == VariableDefinition->VariableId) {
 | |
|       if (VariableDefinition->VariableSize <= (UINTN) (Tag->StorageStart + Tag->StorageWidth)) {
 | |
|         if (Tag->StorageWidth == 0) {
 | |
|           VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + 2);
 | |
|         } else {
 | |
|           VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (VariableDefinition->NvRamMap != NULL) {
 | |
|         //
 | |
|         // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise
 | |
|         // we will never be looking for the data in Tag->Value (e.g. strings, password, etc)
 | |
|         //
 | |
|         if (Tag->StorageWidth == (UINT16) 1) {
 | |
|           CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16));
 | |
|         }
 | |
| 
 | |
|         if (Tag->StorageWidth == (UINT16) 2) {
 | |
|           Index = (UINT16)
 | |
|             (
 | |
|               VariableDefinition->NvRamMap[Tag->StorageStart] +
 | |
|                 (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100)
 | |
|             );
 | |
|           CopyMem (&Tag->Value, &Index, sizeof (UINT16));
 | |
|         }
 | |
|       } else {
 | |
|         CopyMem (&Tag->Value, &Tag->Default, sizeof (UINT16));
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| VOID
 | |
| GetTagCount (
 | |
|   IN      UINT8                                 *RawFormSet,
 | |
|   IN OUT  UINT16                                *NumberOfTags
 | |
|   )
 | |
| {
 | |
|   UINT16  Index;
 | |
| 
 | |
|   //
 | |
|   // Assume on entry we are pointing to an OpCode - reasonably this should
 | |
|   // be a FormOp since the purpose is to count the tags in a particular Form.
 | |
|   //
 | |
|   for (Index = 0; RawFormSet[Index] != EFI_IFR_END_FORM_OP;) {
 | |
|     //
 | |
|     // If we encounter the end of a form set, bail out
 | |
|     //
 | |
|     if (RawFormSet[Index] == EFI_IFR_END_FORM_SET_OP) {
 | |
|       break;
 | |
|     }
 | |
|     //
 | |
|     // We treat date/time internally as three op-codes
 | |
|     //
 | |
|     if (RawFormSet[Index] == EFI_IFR_DATE_OP || RawFormSet[Index] == EFI_IFR_TIME_OP) {
 | |
|       *NumberOfTags = (UINT16) (*NumberOfTags + 3);
 | |
|     } else {
 | |
|       //
 | |
|       // Assume that we could have no more tags than op-codes
 | |
|       //
 | |
|       (*NumberOfTags)++;
 | |
|     }
 | |
| 
 | |
|     Index = (UINT16) (Index + RawFormSet[Index + 1]);
 | |
|   }
 | |
|   //
 | |
|   // Increase the tag count by one so it is inclusive of the end_form_op
 | |
|   //
 | |
|   (*NumberOfTags)++;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| VOID
 | |
| AddNextInconsistentTag (
 | |
|   IN OUT  EFI_INCONSISTENCY_DATA  **InconsistentTagsPtr
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Initialize the next inconsistent tag data and add it to the inconsistent tag list.
 | |
| 
 | |
| Arguments:
 | |
|  InconsistentTagsPtr   - Pointer of the inconsistent tag's pointer.
 | |
| 
 | |
| Returns:
 | |
|   None.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_INCONSISTENCY_DATA  *PreviousInconsistentTags;
 | |
|   EFI_INCONSISTENCY_DATA  *InconsistentTags;
 | |
| 
 | |
|   InconsistentTags = *InconsistentTagsPtr;
 | |
|   //
 | |
|   // We just hit the end of an inconsistent expression.  Let's allocate the ->Next structure
 | |
|   //
 | |
|   InconsistentTags->Next = AllocatePool (sizeof (EFI_INCONSISTENCY_DATA));
 | |
|   ASSERT (InconsistentTags->Next != NULL);
 | |
| 
 | |
|   //
 | |
|   // Preserve current Tag entry
 | |
|   //
 | |
|   PreviousInconsistentTags  = InconsistentTags;
 | |
| 
 | |
|   InconsistentTags          = InconsistentTags->Next;
 | |
| 
 | |
|   //
 | |
|   // This will zero on the entry including the ->Next so I don't have to do it
 | |
|   //
 | |
|   ZeroMem (InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA));
 | |
| 
 | |
|   //
 | |
|   // Point our Previous field to the previous entry
 | |
|   //
 | |
|   InconsistentTags->Previous  = PreviousInconsistentTags;
 | |
| 
 | |
|   *InconsistentTagsPtr        = InconsistentTags;
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| InitializeTagStructures (
 | |
|   IN  EFI_IFR_BINARY                            *BinaryData,
 | |
|   OUT EFI_FILE_FORM_TAGS                        *FileFormTags
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   UINT8                   *RawFormSet;
 | |
|   UINT16                  Index;
 | |
|   UINT16                  QuestionIndex;
 | |
|   UINT16                  NumberOfTags;
 | |
|   INT16                   CurrTag;
 | |
|   UINT8                   TagLength;
 | |
|   EFI_FORM_TAGS           *FormTags;
 | |
|   EFI_FORM_TAGS           *SavedFormTags;
 | |
|   EFI_INCONSISTENCY_DATA  *InconsistentTags;
 | |
|   EFI_VARIABLE_DEFINITION *VariableDefinitions;
 | |
|   UINTN                   Count;
 | |
|   UINT16                  Class;
 | |
|   UINT16                  SubClass;
 | |
|   UINT16                  TempValue;
 | |
|   UINT16                  CurrentVariable;
 | |
|   UINT16                  CurrentVariable2;
 | |
| 
 | |
|   //
 | |
|   // Initialize some Index variable and Status
 | |
|   //
 | |
|   Count             = 0;
 | |
|   Class             = 0;
 | |
|   SubClass          = 0;
 | |
|   CurrentVariable   = 0;
 | |
|   CurrentVariable2  = 0;
 | |
|   QuestionIndex     = 0;
 | |
|   NumberOfTags      = 1;
 | |
|   Status            = EFI_SUCCESS;
 | |
|   FormTags          = &FileFormTags->FormTags;
 | |
|   FormTags->Next    = NULL;
 | |
|   if (FileFormTags->InconsistentTags == NULL) {
 | |
|     InconsistentTags = NULL;
 | |
|   } else {
 | |
|     InconsistentTags = FileFormTags->InconsistentTags;
 | |
|   }
 | |
| 
 | |
|   if (FileFormTags->VariableDefinitions == NULL) {
 | |
|     VariableDefinitions = NULL;
 | |
|   } else {
 | |
|     VariableDefinitions = FileFormTags->VariableDefinitions;
 | |
|   }
 | |
|   //
 | |
|   // RawFormSet now points to the beginning of the forms portion of
 | |
|   // the specific IFR Binary.
 | |
|   //
 | |
|   RawFormSet = (UINT8 *) BinaryData->FormBinary;
 | |
| 
 | |
|   //
 | |
|   // Determine the number of tags for the first form
 | |
|   //
 | |
|   GetTagCount (&RawFormSet[0], &NumberOfTags);
 | |
| 
 | |
|   SavedFormTags = FormTags;
 | |
| 
 | |
|   if (FormTags->Tags != NULL) {
 | |
|     do {
 | |
|       //
 | |
|       // Advance FormTags to the last entry
 | |
|       //
 | |
|       for (; FormTags->Next != NULL; FormTags = FormTags->Next)
 | |
|         ;
 | |
| 
 | |
|       //
 | |
|       // Walk through each of the tags and free the IntList allocation
 | |
|       //
 | |
|       for (Index = 0; Index < NumberOfTags; Index++) {
 | |
|         if (FormTags->Tags[Index].IntList != NULL) {
 | |
|           FreePool (FormTags->Tags[Index].IntList);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       FreePool (FormTags->Tags);
 | |
| 
 | |
|       ASSERT (FormTags->Next == NULL);
 | |
| 
 | |
|       FormTags->Tags  = NULL;
 | |
| 
 | |
|       FormTags        = SavedFormTags;
 | |
| 
 | |
|     } while (FormTags->Next != NULL);
 | |
|   }
 | |
| 
 | |
|   Index = 0;
 | |
| 
 | |
|   //
 | |
|   // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|   // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|   // the tag structure with current values from the NV
 | |
|   //
 | |
|   if (FormTags->Tags == NULL) {
 | |
|     //
 | |
|     // Allocate memory for our tags on the first form
 | |
|     //
 | |
|     FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
 | |
|     ASSERT (FormTags->Tags);
 | |
|   }
 | |
|   //
 | |
|   // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|   // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|   // the tag structure with current values from the NV
 | |
|   //
 | |
|   if (InconsistentTags == NULL) {
 | |
|     //
 | |
|     // We just hit the end of an inconsistent expression.  Let's allocate the ->Next structure
 | |
|     //
 | |
|     InconsistentTags = AllocateZeroPool (sizeof (EFI_INCONSISTENCY_DATA));
 | |
|     ASSERT (InconsistentTags != NULL);
 | |
| 
 | |
|     FileFormTags->InconsistentTags = InconsistentTags;
 | |
|   }
 | |
| 
 | |
|   ZeroMem (FormTags->Tags, NumberOfTags * sizeof (EFI_TAG));
 | |
| 
 | |
|   for (CurrTag = 0; RawFormSet[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
 | |
|     //
 | |
|     // Operand = IFR OpCode
 | |
|     //
 | |
|     FormTags->Tags[CurrTag].Operand = RawFormSet[Index];
 | |
| 
 | |
|     //
 | |
|     // Assume for now 0 lines occupied by this OpCode
 | |
|     //
 | |
|     FormTags->Tags[CurrTag].NumberOfLines = 0;
 | |
| 
 | |
|     FormTags->Tags[CurrTag].Class         = Class;
 | |
|     FormTags->Tags[CurrTag].SubClass      = SubClass;
 | |
| 
 | |
|     //
 | |
|     // Determine the length of the Tag so we can later skip to the next tag in the form
 | |
|     //
 | |
|     TagLength = RawFormSet[Index + 1];
 | |
|     //
 | |
|     // get the length
 | |
|     //
 | |
|     // Operate on the Found OpCode
 | |
|     //
 | |
|     switch (RawFormSet[Index]) {
 | |
| 
 | |
|     case EFI_IFR_FORM_OP:
 | |
|       //
 | |
|       // If there was no variable op-code defined, create a dummy entry for one
 | |
|       //
 | |
|       if (FileFormTags->VariableDefinitions == NULL) {
 | |
|         FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
 | |
|         ASSERT (FileFormTags->VariableDefinitions != NULL);
 | |
|         IfrToFormTag (
 | |
|           RawFormSet[Index],
 | |
|           &FormTags->Tags[CurrTag],
 | |
|           (VOID *) &RawFormSet[Index],
 | |
|           FileFormTags->VariableDefinitions
 | |
|           );
 | |
|       } else {
 | |
|         IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_SUBTITLE_OP:
 | |
|     case EFI_IFR_TEXT_OP:
 | |
|     case EFI_IFR_REF_OP:
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_VARSTORE_OP:
 | |
|       if (FileFormTags->VariableDefinitions == NULL) {
 | |
|         VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
 | |
|         ASSERT (VariableDefinitions != NULL);
 | |
|         FileFormTags->VariableDefinitions = VariableDefinitions;
 | |
|       }
 | |
| 
 | |
|       IfrToFormTag (
 | |
|         RawFormSet[Index],
 | |
|         &FormTags->Tags[CurrTag],
 | |
|         (VOID *) &RawFormSet[Index],
 | |
|         FileFormTags->VariableDefinitions
 | |
|         );
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_VARSTORE_SELECT_OP:
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &RawFormSet[Index])->VarId, sizeof (UINT16));
 | |
|       CurrentVariable2 = CurrentVariable;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_VARSTORE_SELECT_PAIR_OP:
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       CopyMem(&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *)&RawFormSet[Index])->VarId, sizeof (UINT16));
 | |
|       CopyMem (
 | |
|         &CurrentVariable2,
 | |
|         &((EFI_IFR_VARSTORE_SELECT_PAIR *) &RawFormSet[Index])->SecondaryVarId,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_END_FORM_OP:
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (FormTags->Next == NULL) {
 | |
|         //
 | |
|         // We just hit the end of a form.  Let's allocate the ->Next structure
 | |
|         //
 | |
|         FormTags->Next = AllocatePool (sizeof (EFI_FORM_TAGS));
 | |
|         ASSERT (FormTags->Next);
 | |
|       }
 | |
| 
 | |
|       FormTags = FormTags->Next;
 | |
|       ZeroMem (FormTags, sizeof (EFI_FORM_TAGS));
 | |
| 
 | |
|       //
 | |
|       // Reset the tag count to one
 | |
|       //
 | |
|       NumberOfTags = 1;
 | |
| 
 | |
|       //
 | |
|       // Reset the CurrTag value (it will be incremented, after this case statement
 | |
|       // so set to a negative one so that we get the desired effect.)  Fish can beat me later.
 | |
|       //
 | |
|       CurrTag = -1;
 | |
| 
 | |
|       //
 | |
|       // Determine the number of tags after this form.  If this is the last
 | |
|       // form, then we will count the endformset and preserve that information
 | |
|       // in the tag structure.
 | |
|       //
 | |
|       GetTagCount (&RawFormSet[Index + TagLength], &NumberOfTags);
 | |
| 
 | |
|       //
 | |
|       // Allocate memory for our tags
 | |
|       //
 | |
|       FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG));
 | |
|       ASSERT (FormTags->Tags);
 | |
|       break;
 | |
| 
 | |
|     //
 | |
|     // Two types of tags constitute the One Of question: a one-of header and
 | |
|     // several one-of options.
 | |
|     //
 | |
|     case EFI_IFR_ONE_OF_OP:
 | |
|     case EFI_IFR_ORDERED_LIST_OP:
 | |
|       GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
 | |
| 
 | |
|       //
 | |
|       // Store away the CurrTag since what follows will be the answer that we
 | |
|       // need to place into the appropriate location in the tag array
 | |
|       //
 | |
|       //
 | |
|       // record for setting default later
 | |
|       //
 | |
|       QuestionIndex = (UINT16) CurrTag;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_ONE_OF_OPTION_OP:
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       FormTags->Tags[QuestionIndex].Flags = ((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Flags;
 | |
|       CopyMem (
 | |
|         &FormTags->Tags[QuestionIndex].Key,
 | |
|         &((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Key,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
|       FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_CHECKBOX_OP:
 | |
|       GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_NUMERIC_OP:
 | |
|       GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_DATE_OP:
 | |
|       //
 | |
|       // Date elements come in as a Year, Month, Day.  We need to process them as a country-based
 | |
|       // Order.  It is much easier to do it here than anywhere else.
 | |
|       //
 | |
|       // For US standards - we want Month/Day/Year, thus we advance "Index" +1, +2, +0 while CurrTag is +0, +1, +2
 | |
|       //
 | |
|       GetNumericHeader (
 | |
|         &FormTags->Tags[CurrTag],
 | |
|         RawFormSet,
 | |
|         (UINT16) (Index + TagLength),
 | |
|         (UINT16) 0,
 | |
|         FileFormTags,
 | |
|         CurrentVariable
 | |
|         );
 | |
| 
 | |
|       //
 | |
|       // The current language selected + the Date operand
 | |
|       //
 | |
|       FormTags->Tags[CurrTag + 1].Operand = RawFormSet[Index];
 | |
|       GetNumericHeader (
 | |
|         &FormTags->Tags[CurrTag + 1],
 | |
|         RawFormSet,
 | |
|         (UINT16) (Index + TagLength + RawFormSet[Index + TagLength + 1]),
 | |
|         (UINT16) 0,
 | |
|         FileFormTags,
 | |
|         CurrentVariable
 | |
|         );
 | |
| 
 | |
|       //
 | |
|       // The current language selected + the Date operand
 | |
|       //
 | |
|       FormTags->Tags[CurrTag + 2].Operand = RawFormSet[Index];
 | |
|       GetNumericHeader (&FormTags->Tags[CurrTag + 2], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable);
 | |
| 
 | |
|       CurrTag   = (INT16) (CurrTag + 2);
 | |
| 
 | |
|       Index     = (UINT16) (Index + TagLength);
 | |
|       //
 | |
|       // get the length
 | |
|       //
 | |
|       TagLength = RawFormSet[Index + 1];
 | |
|       Index     = (UINT16) (Index + TagLength);
 | |
|       //
 | |
|       // get the length
 | |
|       //
 | |
|       TagLength = RawFormSet[Index + 1];
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_TIME_OP:
 | |
|       GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 0, FileFormTags, CurrentVariable);
 | |
| 
 | |
|       if (Count == 2) {
 | |
|         //
 | |
|         // Override the GetQuestionHeader information - date/time are treated very differently
 | |
|         //
 | |
|         FormTags->Tags[CurrTag].NumberOfLines = 1;
 | |
|         Count = 0;
 | |
|       } else {
 | |
|         //
 | |
|         // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines
 | |
|         // associated with them, and the third has 1 line to allow to space beyond the choice.
 | |
|         //
 | |
|         Count++;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_PASSWORD_OP:
 | |
|     case EFI_IFR_STRING_OP:
 | |
|       GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable);
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_SUPPRESS_IF_OP:
 | |
|     case EFI_IFR_GRAYOUT_IF_OP:
 | |
|       InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;
 | |
|       gConsistencyId++;
 | |
| 
 | |
|       //
 | |
|       // Since this op-code doesn't use the next field(s), initialize them with something invalid.
 | |
|       // Unfortunately 0 is a valid offset value for a QuestionId
 | |
|       //
 | |
|       InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
 | |
|       InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
 | |
| 
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (InconsistentTags->Next == NULL) {
 | |
|         AddNextInconsistentTag (&InconsistentTags);
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InconsistentTags = InconsistentTags->Next;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_FORM_SET_OP:
 | |
|       CopyMem (
 | |
|         &FormTags->Tags[CurrTag].GuidValue,
 | |
|         &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Guid,
 | |
|         sizeof (EFI_GUID)
 | |
|         );
 | |
|       CopyMem (
 | |
|         &FormTags->Tags[CurrTag].CallbackHandle,
 | |
|         &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->CallbackHandle,
 | |
|         sizeof (EFI_PHYSICAL_ADDRESS)
 | |
|         );
 | |
|       CopyMem (&FormTags->Tags[CurrTag].Class, &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class, sizeof (UINT8));
 | |
|       CopyMem (
 | |
|         &FormTags->Tags[CurrTag].SubClass,
 | |
|         &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass,
 | |
|         sizeof (UINT8)
 | |
|         );
 | |
|       CopyMem (
 | |
|         &FormTags->Tags[CurrTag].NvDataSize,
 | |
|         &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->NvDataSize,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
|       Class     = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class;
 | |
|       SubClass  = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass;
 | |
|       //
 | |
|       // If the formset has a size value, that means someone must be using this, so create a variable
 | |
|       // We also shall reserve the formid of 0 for this specific purpose.
 | |
|       //
 | |
|       if ((FileFormTags->VariableDefinitions == NULL) && (FormTags->Tags[CurrTag].NvDataSize > 0)) {
 | |
|         FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION));
 | |
|         ASSERT (FileFormTags->VariableDefinitions != NULL);
 | |
|         IfrToFormTag (
 | |
|           RawFormSet[Index],
 | |
|           &FormTags->Tags[CurrTag],
 | |
|           (VOID *) &RawFormSet[Index],
 | |
|           FileFormTags->VariableDefinitions
 | |
|           );
 | |
|       } else {
 | |
|         IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_BANNER_OP:
 | |
|       if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) {
 | |
|         TempValue = 0;
 | |
|         CopyMem (&TempValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment, sizeof (UINT8));
 | |
|         //
 | |
|         // If this is the special timeout value, we will dynamically figure out where to put it
 | |
|         // Also the least significant byte refers to the TimeOut desired.
 | |
|         //
 | |
|         if (TempValue == EFI_IFR_BANNER_TIMEOUT) {
 | |
|           CopyMem (&FrontPageTimeOutTitle, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title, sizeof (UINT16));
 | |
|           if (FrontPageTimeOutValue != (INT16) -1) {
 | |
|             CopyMem (&FrontPageTimeOutValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber, sizeof (UINT16));
 | |
|           }
 | |
|           break;
 | |
|         }
 | |
| 
 | |
|         CopyMem (
 | |
|           &BannerData->Banner[((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber][
 | |
|           ((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment],
 | |
|           &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title,
 | |
|           sizeof (STRING_REF)
 | |
|           );
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_INCONSISTENT_IF_OP:
 | |
|       CopyMem (
 | |
|         &FormTags->Tags[CurrTag].Text,
 | |
|         &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
|       gConsistencyId++;
 | |
| 
 | |
|       InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode;
 | |
|       CopyMem (&InconsistentTags->Popup, &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup, sizeof (UINT16));
 | |
| 
 | |
|       //
 | |
|       // Since this op-code doesn't use the next field(s), initialize them with something invalid.
 | |
|       // Unfortunately 0 is a valid offset value for a QuestionId
 | |
|       //
 | |
|       InconsistentTags->QuestionId1     = INVALID_OFFSET_VALUE;
 | |
|       InconsistentTags->QuestionId2     = INVALID_OFFSET_VALUE;
 | |
| 
 | |
|       InconsistentTags->VariableNumber  = CurrentVariable;
 | |
| 
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (InconsistentTags->Next == NULL) {
 | |
|         AddNextInconsistentTag (&InconsistentTags);
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InconsistentTags = InconsistentTags->Next;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_EQ_ID_VAL_OP:
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
| 
 | |
|       InconsistentTags->Operand = ((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Header.OpCode;
 | |
|       CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));
 | |
|       CopyMem (
 | |
|         &InconsistentTags->QuestionId1,
 | |
|         &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->QuestionId,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
| 
 | |
|       //
 | |
|       // Since this op-code doesn't use the next field(s), initialize them with something invalid.
 | |
|       // Unfortunately 0 is a valid offset value for a QuestionId
 | |
|       //
 | |
|       InconsistentTags->Width               = FormTags->Tags[CurrTag].StorageWidth;
 | |
|       InconsistentTags->QuestionId2         = INVALID_OFFSET_VALUE;
 | |
|       InconsistentTags->ConsistencyId       = gConsistencyId;
 | |
|       FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
 | |
| 
 | |
|       InconsistentTags->VariableNumber      = CurrentVariable;
 | |
| 
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (InconsistentTags->Next == NULL) {
 | |
|         AddNextInconsistentTag (&InconsistentTags);
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InconsistentTags = InconsistentTags->Next;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_EQ_VAR_VAL_OP:
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
| 
 | |
|       InconsistentTags->Operand = ((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Header.OpCode;
 | |
|       CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16));
 | |
|       CopyMem (
 | |
|         &InconsistentTags->QuestionId1,
 | |
|         &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->VariableId,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
| 
 | |
|       //
 | |
|       // Since this op-code doesn't use the next field(s), initialize them with something invalid.
 | |
|       // Unfortunately 0 is a valid offset value for a QuestionId
 | |
|       //
 | |
|       InconsistentTags->QuestionId2         = INVALID_OFFSET_VALUE;
 | |
|       InconsistentTags->ConsistencyId       = gConsistencyId;
 | |
|       FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
 | |
| 
 | |
|       InconsistentTags->VariableNumber      = CurrentVariable;
 | |
| 
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (InconsistentTags->Next == NULL) {
 | |
|         AddNextInconsistentTag (&InconsistentTags);
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InconsistentTags = InconsistentTags->Next;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_EQ_ID_ID_OP:
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
| 
 | |
|       InconsistentTags->Operand = ((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->Header.OpCode;
 | |
|       CopyMem (
 | |
|         &InconsistentTags->QuestionId1,
 | |
|         &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId1,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
|       CopyMem (
 | |
|         &InconsistentTags->QuestionId2,
 | |
|         &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId2,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
| 
 | |
|       InconsistentTags->Width               = FormTags->Tags[CurrTag].StorageWidth;
 | |
|       InconsistentTags->ConsistencyId       = gConsistencyId;
 | |
|       FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
 | |
| 
 | |
|       InconsistentTags->VariableNumber      = CurrentVariable;
 | |
|       InconsistentTags->VariableNumber2     = CurrentVariable2;
 | |
| 
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (InconsistentTags->Next == NULL) {
 | |
|         AddNextInconsistentTag (&InconsistentTags);
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InconsistentTags = InconsistentTags->Next;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_AND_OP:
 | |
|     case EFI_IFR_OR_OP:
 | |
|     case EFI_IFR_NOT_OP:
 | |
|     case EFI_IFR_GT_OP:
 | |
|     case EFI_IFR_GE_OP:
 | |
|     case EFI_IFR_TRUE_OP:
 | |
|     case EFI_IFR_FALSE_OP:
 | |
|       InconsistentTags->Operand = ((EFI_IFR_NOT *) &RawFormSet[Index])->Header.OpCode;
 | |
| 
 | |
|       //
 | |
|       // Since this op-code doesn't use the next field(s), initialize them with something invalid.
 | |
|       // Unfortunately 0 is a valid offset value for a QuestionId
 | |
|       //
 | |
| 
 | |
|       //
 | |
|       // Reserve INVALID_OFFSET_VALUE - 1 for TRUE or FALSE because they are inconsistency tags also, but
 | |
|       // have no coresponding id. The examination of id is needed by evaluating boolean expression.
 | |
|       //
 | |
|       if (RawFormSet[Index] == EFI_IFR_TRUE_OP ||
 | |
|           RawFormSet[Index] == EFI_IFR_FALSE_OP) {
 | |
|         InconsistentTags->QuestionId1         = INVALID_OFFSET_VALUE - 1;
 | |
|       } else {
 | |
|         InconsistentTags->QuestionId1         = INVALID_OFFSET_VALUE;
 | |
|       }
 | |
|       InconsistentTags->QuestionId2         = INVALID_OFFSET_VALUE;
 | |
|       InconsistentTags->ConsistencyId       = gConsistencyId;
 | |
|       FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
 | |
| 
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (InconsistentTags->Next == NULL) {
 | |
|         AddNextInconsistentTag (&InconsistentTags);
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InconsistentTags = InconsistentTags->Next;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_EQ_ID_LIST_OP:
 | |
|       IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
| 
 | |
|       InconsistentTags->Operand = ((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->Header.OpCode;
 | |
|       CopyMem (
 | |
|         &InconsistentTags->QuestionId1,
 | |
|         &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->QuestionId,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
|       CopyMem (
 | |
|         &InconsistentTags->ListLength,
 | |
|         &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->ListLength,
 | |
|         sizeof (UINT16)
 | |
|         );
 | |
|       InconsistentTags->ValueList = FormTags->Tags[CurrTag].IntList;
 | |
| 
 | |
|       //
 | |
|       // Since this op-code doesn't use the next field(s), initialize them with something invalid.
 | |
|       // Unfortunately 0 is a valid offset value for a QuestionId
 | |
|       //
 | |
|       InconsistentTags->Width               = FormTags->Tags[CurrTag].StorageWidth;
 | |
|       InconsistentTags->QuestionId2         = INVALID_OFFSET_VALUE;
 | |
|       InconsistentTags->ConsistencyId       = gConsistencyId;
 | |
|       FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId;
 | |
| 
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (InconsistentTags->Next == NULL) {
 | |
|         AddNextInconsistentTag (&InconsistentTags);
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InconsistentTags = InconsistentTags->Next;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_END_IF_OP:
 | |
|       InconsistentTags->Operand = ((EFI_IFR_END_EXPR *) &RawFormSet[Index])->Header.OpCode;
 | |
| 
 | |
|       //
 | |
|       // Since this op-code doesn't use the next field(s), initialize them with something invalid.
 | |
|       // Unfortunately 0 is a valid offset value for a QuestionId
 | |
|       //
 | |
|       InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE;
 | |
|       InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE;
 | |
| 
 | |
|       //
 | |
|       // Test for an allocated buffer.  If already allocated this is due to having called this routine
 | |
|       // once for sizing of the NV storage.  We then loaded the NV variable and can correctly initialize
 | |
|       // the tag structure with current values from the NV
 | |
|       //
 | |
|       if (InconsistentTags->Next == NULL) {
 | |
|         AddNextInconsistentTag (&InconsistentTags);
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       InconsistentTags = InconsistentTags->Next;
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_END_ONE_OF_OP:
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|     //
 | |
|     // End of switch
 | |
|     //
 | |
|     // Per spec., we ignore ops that we don't know how to deal with.  Skip to next tag
 | |
|     //
 | |
|     Index = (UINT16) (Index + TagLength);
 | |
|   }
 | |
|   //
 | |
|   // End of Index
 | |
|   //
 | |
|   // When we eventually exit, make sure we mark the last tag with an op-code
 | |
|   //
 | |
|   FormTags->Tags[CurrTag].Operand = RawFormSet[Index];
 | |
| 
 | |
|   IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL);
 | |
| 
 | |
|   //
 | |
|   // Place this as an end of the database marker
 | |
|   //
 | |
|   InconsistentTags->Operand = 0xFF;
 | |
| 
 | |
|   //
 | |
|   // This is the Head of the linked list of pages.  Each page is an array of tags
 | |
|   //
 | |
|   FormTags          = &FileFormTags->FormTags;
 | |
|   InconsistentTags  = FileFormTags->InconsistentTags;
 | |
| 
 | |
|   for (; InconsistentTags->Operand != 0xFF;) {
 | |
|     if (InconsistentTags->QuestionId1 != INVALID_OFFSET_VALUE) {
 | |
|       //
 | |
|       // Search the tags for the tag which corresponds to this ID
 | |
|       //
 | |
|       for (CurrTag = 0; FormTags->Tags[0].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
 | |
|         //
 | |
|         // If we hit the end of a form, go to the next set of Tags.
 | |
|         // Remember - EndFormSet op-codes sit on their own page after an end form.
 | |
|         //
 | |
|         if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {
 | |
|           //
 | |
|           // Reset the CurrTag value (it will be incremented, after this case statement
 | |
|           // so set to a negative one so that we get the desired effect.)  Fish can beat me later.
 | |
|           //
 | |
|           CurrTag   = -1;
 | |
|           FormTags  = FormTags->Next;
 | |
|           continue;
 | |
|         }
 | |
| 
 | |
|         if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId1) {
 | |
|           FormTags->Tags[CurrTag].Consistency++;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     FormTags = &FileFormTags->FormTags;
 | |
| 
 | |
|     if (InconsistentTags->QuestionId2 != INVALID_OFFSET_VALUE) {
 | |
|       //
 | |
|       // Search the tags for the tag which corresponds to this ID
 | |
|       //
 | |
|       for (CurrTag = 0; FormTags->Tags[CurrTag].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) {
 | |
|         //
 | |
|         // If we hit the end of a form, go to the next set of Tags.
 | |
|         // Remember - EndFormSet op-codes sit on their own page after an end form.
 | |
|         //
 | |
|         if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) {
 | |
|           //
 | |
|           // Reset the CurrTag value (it will be incremented, after this case statement
 | |
|           // so set to a negative one so that we get the desired effect.)  Fish can beat me later.
 | |
|           //
 | |
|           CurrTag   = -1;
 | |
|           FormTags  = FormTags->Next;
 | |
|           continue;
 | |
|         }
 | |
| 
 | |
|         if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId2) {
 | |
|           FormTags->Tags[CurrTag].Consistency++;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     InconsistentTags = InconsistentTags->Next;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| InitPage (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   CHAR16  *HomePageString;
 | |
|   CHAR16  *HomeEscapeString;
 | |
| 
 | |
|   //
 | |
|   // Displays the Header and Footer borders
 | |
|   //
 | |
|   DisplayPageFrame ();
 | |
| 
 | |
|   HomePageString    = GetToken (STRING_TOKEN (HOME_PAGE_TITLE), gHiiHandle);
 | |
|   HomeEscapeString  = GetToken (STRING_TOKEN (HOME_ESCAPE_STRING), gHiiHandle);
 | |
| 
 | |
|   gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
 | |
|   //
 | |
|   //  PrintStringAt ((gScreenDimensions.RightColumn - GetStringWidth(HomePageString)/2)/2, 1, HomePageString);
 | |
|   //
 | |
|   PrintStringAt (
 | |
|     (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - GetStringWidth (HomePageString) / 2) / 2,
 | |
|     1,
 | |
|     HomePageString
 | |
|     );
 | |
|   PrintAt (
 | |
|     gScreenDimensions.LeftColumn + 2,
 | |
|     gScreenDimensions.BottomRow - 3,
 | |
|     (CHAR16 *) L"%c%c%s",
 | |
|     ARROW_UP,
 | |
|     ARROW_DOWN,
 | |
|     gMoveHighlight
 | |
|     );
 | |
|   PrintAt (
 | |
|     gScreenDimensions.RightColumn - (GetStringWidth (HomeEscapeString) / 2) - 2,
 | |
|     gScreenDimensions.BottomRow - 3,
 | |
|     (CHAR16 *) L" %s",
 | |
|     HomeEscapeString
 | |
|     );
 | |
|   gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
 | |
|   FreePool (HomeEscapeString);
 | |
|   FreePool (HomePageString);
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| CHAR16 *
 | |
| GetToken (
 | |
|   IN  STRING_REF                              Token,
 | |
|   IN  EFI_HII_HANDLE                          HiiHandle
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Get the string based on the TokenID and HII Handle.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Token       - The Token ID.
 | |
|   HiiHandle   - Handle of Ifr to be fetched.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   The output string.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   CHAR16      *Buffer;
 | |
|   UINTN       BufferLength;
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   //
 | |
|   // Set default string size assumption at no more than 256 bytes
 | |
|   //
 | |
|   BufferLength  = 0x100;
 | |
| 
 | |
|   Buffer        = AllocateZeroPool (BufferLength);
 | |
|   ASSERT (Buffer != NULL);
 | |
| 
 | |
|   Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|       //
 | |
|       // Free the old pool
 | |
|       //
 | |
|       FreePool (Buffer);
 | |
| 
 | |
|       //
 | |
|       // Allocate new pool with correct value
 | |
|       //
 | |
|       Buffer = AllocatePool (BufferLength);
 | |
|       ASSERT (Buffer != NULL);
 | |
| 
 | |
|       Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer);
 | |
| 
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         return Buffer;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|   }
 | |
| 
 | |
|   return Buffer;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| PopulateHomePage (
 | |
|   IN UINTN                                    NumberOfIfrImages,
 | |
|   IN EFI_FILE_FORM_TAGS                       *FileFormTagsHead
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS          Status;
 | |
|   UINTN               Index;
 | |
|   EFI_IFR_BINARY      *IfrBinary;
 | |
|   CHAR16              *StringPtr;
 | |
|   EFI_FILE_FORM_TAGS  *FileFormTags;
 | |
|   EFI_FORM_TAGS       LocalTags;
 | |
| 
 | |
|   FileFormTags = FileFormTagsHead;
 | |
| 
 | |
|   UiInitMenu ();
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   // If there are no images
 | |
|   //
 | |
|   if (NumberOfIfrImages == 0) {
 | |
|     Status = EFI_NO_MEDIA;
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // IfrBinary points to the beginning of the Binary data linked-list
 | |
|   //
 | |
|   IfrBinary = gBinaryDataHead;
 | |
| 
 | |
|   //
 | |
|   // Print the entries which were in the default language.
 | |
|   //
 | |
|   for (Index = 0; Index < NumberOfIfrImages; Index++) {
 | |
|     LocalTags = FileFormTags->FormTags;
 | |
| 
 | |
|     //
 | |
|     // Populate the Menu
 | |
|     //
 | |
|     StringPtr = GetToken (IfrBinary->TitleToken, IfrBinary->Handle);
 | |
| 
 | |
|     //
 | |
|     // If the default language doesn't exist, don't add a menu option yet
 | |
|     //
 | |
|     if (StringPtr[0] != CHAR_NULL) {
 | |
|       //
 | |
|       // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do
 | |
|       // it in UiFreeMenu.
 | |
|       //
 | |
|       UiAddMenuOption (StringPtr, IfrBinary->Handle, LocalTags.Tags, IfrBinary->FormBinary, Index);
 | |
|     }
 | |
|     //
 | |
|     // Advance to the next HII handle
 | |
|     //
 | |
|     IfrBinary     = IfrBinary->Next;
 | |
|     FileFormTags  = FileFormTags->NextFile;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| UI_MENU_OPTION *
 | |
| DisplayHomePage (
 | |
|   IN UINTN                                    NumberOfIfrImages,
 | |
|   IN EFI_FILE_FORM_TAGS                       *FileFormTagsHead,
 | |
|   IN UINT8                                    *CallbackData
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS      Status;
 | |
|   UI_MENU_OPTION  *Selection;
 | |
| 
 | |
|   //
 | |
|   // This prints the basic home page template which the user sees
 | |
|   //
 | |
|   InitPage ();
 | |
| 
 | |
|   Status = PopulateHomePage (NumberOfIfrImages, FileFormTagsHead);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Selection = NULL;
 | |
|     return Selection;
 | |
|   }
 | |
| 
 | |
|   Selection = UiDisplayMenu (FALSE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData);
 | |
| 
 | |
|   return Selection;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| InitializeBinaryStructures (
 | |
|   IN  EFI_HII_HANDLE                        *Handle,
 | |
|   IN  BOOLEAN                               UseDatabase,
 | |
|   IN  EFI_IFR_PACKET                        *Packet,
 | |
|   IN  UINT8                                 *NvMapOverride,
 | |
|   IN  UINTN                                 NumberOfIfrImages,
 | |
|   OUT EFI_FILE_FORM_TAGS                    **FileFormTagsHead
 | |
|   )
 | |
| {
 | |
|   UINTN                       HandleIndex;
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_IFR_BINARY              *BinaryData;
 | |
|   EFI_FILE_FORM_TAGS          *FileFormTags;
 | |
|   UINTN                       SizeOfNvStore;
 | |
|   EFI_FORM_CALLBACK_PROTOCOL  *FormCallback;
 | |
|   EFI_VARIABLE_DEFINITION     *VariableDefinition;
 | |
|   EFI_VARIABLE_DEFINITION     *OverrideDefinition;
 | |
|   VOID                        *NvMap;
 | |
|   UINTN                       NvMapSize;
 | |
|   EFI_HII_VARIABLE_PACK_LIST  *NvMapListHead;
 | |
|   EFI_HII_VARIABLE_PACK_LIST  *NvMapListNode;
 | |
| 
 | |
|   //
 | |
|   // Initialize some variables to avoid warnings
 | |
|   //
 | |
|   BinaryData        = NULL;
 | |
|   *FileFormTagsHead = NULL;
 | |
|   FileFormTags      = NULL;
 | |
|   gBinaryDataHead   = NULL;
 | |
|   Status            = EFI_SUCCESS;
 | |
|   FormCallback      = NULL;
 | |
|   NvMap             = NULL;
 | |
|   NvMapSize         = 0;
 | |
| 
 | |
|   if (NumberOfIfrImages > 1) {
 | |
|     NvMapOverride = NULL;
 | |
|   }
 | |
| 
 | |
|   for (HandleIndex = 0; HandleIndex < NumberOfIfrImages; HandleIndex += 1) {
 | |
|     //
 | |
|     // If the buffers are uninitialized, allocate them, otherwise work on the ->Next members
 | |
|     //
 | |
|     if ((BinaryData == NULL) || (FileFormTags == NULL)) {
 | |
|       //
 | |
|       // Allocate memory for our Binary Data
 | |
|       //
 | |
|       BinaryData = AllocateZeroPool (sizeof (EFI_IFR_BINARY));
 | |
|       ASSERT (BinaryData);
 | |
| 
 | |
|       //
 | |
|       // Preserve the Head of what will be a linked-list.
 | |
|       //
 | |
|       gBinaryDataHead       = BinaryData;
 | |
|       gBinaryDataHead->Next = NULL;
 | |
| 
 | |
|       if (UseDatabase) {
 | |
|         Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
 | |
|       } else {
 | |
|         Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
 | |
|       }
 | |
|       //
 | |
|       // Allocate memory for our File Form Tags
 | |
|       //
 | |
|       FileFormTags = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
 | |
|       ASSERT (FileFormTags);
 | |
| 
 | |
|       //
 | |
|       // Preserve the Head of what will be a linked-list.
 | |
|       //
 | |
|       *FileFormTagsHead             = FileFormTags;
 | |
|       (*FileFormTagsHead)->NextFile = NULL;
 | |
| 
 | |
|     } else {
 | |
|       //
 | |
|       // Allocate memory for our Binary Data linked-list
 | |
|       // Each handle represents a Binary and we will store that data away.
 | |
|       //
 | |
|       BinaryData->Next = AllocateZeroPool (sizeof (EFI_IFR_BINARY));
 | |
|       ASSERT (BinaryData->Next);
 | |
| 
 | |
|       BinaryData        = BinaryData->Next;
 | |
|       BinaryData->Next  = NULL;
 | |
| 
 | |
|       if (UseDatabase) {
 | |
|         Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData);
 | |
|       } else {
 | |
|         Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData);
 | |
|       }
 | |
| 
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         return EFI_DEVICE_ERROR;
 | |
|       }
 | |
|       //
 | |
|       // Allocate memory for our FileFormTags linked-list
 | |
|       // Each allocation reserves handle represents a Binary and we will store that data away.
 | |
|       //
 | |
|       FileFormTags->NextFile = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS));
 | |
|       ASSERT (FileFormTags->NextFile);
 | |
| 
 | |
|       FileFormTags = FileFormTags->NextFile;
 | |
|     }
 | |
|     //
 | |
|     // endif
 | |
|     //
 | |
|     // Tag Structure Initialization
 | |
|     //
 | |
|     Status              = InitializeTagStructures (BinaryData, FileFormTags);
 | |
| 
 | |
|     VariableDefinition  = FileFormTags->VariableDefinitions;
 | |
| 
 | |
|     //
 | |
|     // Allocate memory for our NVRAM Maps for all of our variables
 | |
|     //
 | |
|     for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
 | |
|       //
 | |
|       // Pad the fake variable size accordingly - this value should reflect the size of information that is not accounted by
 | |
|       // the mainstream NVRAM variable such as DATE/TIME information that the browser needs to track but is saved to an RTC
 | |
|       //
 | |
|       VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableSize + VariableDefinition->VariableFakeSize);
 | |
| 
 | |
|       //
 | |
|       // In the case where a file has no "real" NV data, we should pad the buffer accordingly
 | |
|       //
 | |
|       if (VariableDefinition->VariableSize == 0) {
 | |
|         if (VariableDefinition->VariableFakeSize != 0) {
 | |
|           VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize);
 | |
|           ASSERT (VariableDefinition->NvRamMap != NULL);
 | |
|         }
 | |
|       } else {
 | |
|         VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize);
 | |
|         ASSERT (VariableDefinition->NvRamMap != NULL);
 | |
|       }
 | |
| 
 | |
|       if (VariableDefinition->VariableFakeSize != 0) {
 | |
|         VariableDefinition->FakeNvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize);
 | |
|         ASSERT (VariableDefinition->FakeNvRamMap != NULL);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Status = gBS->HandleProtocol (
 | |
|                     (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle,
 | |
|                     &gEfiFormCallbackProtocolGuid,
 | |
|                     (VOID **) &FormCallback
 | |
|                     );
 | |
| 
 | |
|     //
 | |
|     // Since we might have multiple variables, if there is an NvMapOverride we need to use the EFI_VARIABLE_DEFINITION
 | |
|     // information as the information that we pass back and forth.  NOTE that callbacks that are initiated will only have the
 | |
|     // NVRAM data refreshed based on the op-code that initiated the callback.  In other words, we will pass to the caller a single
 | |
|     // NVRAM map for a single variable based on the op-code that the user selected.
 | |
|     //
 | |
|     if (NvMapOverride != NULL) {
 | |
|       VariableDefinition  = FileFormTags->VariableDefinitions;
 | |
|       OverrideDefinition  = ((EFI_VARIABLE_DEFINITION *) NvMapOverride);
 | |
| 
 | |
|       //
 | |
|       // Search through the variable definitions.  There should be sufficient passed in settings for the variable op-codes specified
 | |
|       //
 | |
|       for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
 | |
|         if ((!CompareMem (VariableDefinition->VariableName, L"Setup", 10)) && (VariableDefinition->Next == NULL)) {
 | |
|           if (VariableDefinition->VariableSize != 0) {
 | |
|             CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableSize);
 | |
|           } else {
 | |
|             CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableFakeSize);
 | |
|           }
 | |
|           break;
 | |
|         } else {
 | |
|           VariableDefinition->NvRamMap = OverrideDefinition->NvRamMap;
 | |
|         }
 | |
|         //
 | |
|         // There should NEVER be a ->Next for VariableDefinition and a NULL ->Next for the OverrideDefinition
 | |
|         //
 | |
|         ASSERT (OverrideDefinition->Next);
 | |
|         OverrideDefinition = OverrideDefinition->Next;
 | |
|       }
 | |
|     } else {
 | |
|       VariableDefinition = FileFormTags->VariableDefinitions;
 | |
| 
 | |
|       //
 | |
|       // Search through the variable definitions.  There should be sufficient passed in settings for the variable op-codes specified
 | |
|       //
 | |
|       for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) {
 | |
|         SizeOfNvStore = VariableDefinition->VariableSize;
 | |
| 
 | |
|         //
 | |
|         // Getting the NvStore and placing it into our Global Data
 | |
|         //
 | |
|         if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
 | |
|           Status = FormCallback->NvRead (
 | |
|                                   FormCallback,
 | |
|                                   VariableDefinition->VariableName,
 | |
|                                   &VariableDefinition->Guid,
 | |
|                                   NULL,
 | |
|                                   &SizeOfNvStore,
 | |
|                                   (VOID *) VariableDefinition->NvRamMap
 | |
|                                   );
 | |
|         } else {
 | |
|           Status = gRT->GetVariable (
 | |
|                           VariableDefinition->VariableName,
 | |
|                           &VariableDefinition->Guid,
 | |
|                           NULL,
 | |
|                           &SizeOfNvStore,
 | |
|                           (VOID *) VariableDefinition->NvRamMap
 | |
|                           );
 | |
|         }
 | |
| 
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           //
 | |
|           // If there is a variable that exists already and it is larger than what we calculated the
 | |
|           // storage needs to be, we must assume the variable size from GetVariable is correct and not
 | |
|           // allow the truncation of the variable.  It is very possible that the user who created the IFR
 | |
|           // we are cracking is not referring to a variable that was in a previous map, however we cannot
 | |
|           // allow it's truncation.
 | |
|           //
 | |
|           if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|             //
 | |
|             // If the buffer was too small, we should have the expanded size requirement in SizeOfNvStore now.
 | |
|             //
 | |
|             VariableDefinition->VariableSize = (UINT16) SizeOfNvStore;
 | |
| 
 | |
|             //
 | |
|             // Free the buffer that was allocated that was too small
 | |
|             //
 | |
|             FreePool (VariableDefinition->NvRamMap);
 | |
|             FreePool (VariableDefinition->FakeNvRamMap);
 | |
| 
 | |
|             VariableDefinition->NvRamMap = AllocateZeroPool (SizeOfNvStore);
 | |
|             VariableDefinition->FakeNvRamMap = AllocateZeroPool (SizeOfNvStore + VariableDefinition->VariableFakeSize);
 | |
|             ASSERT (VariableDefinition->NvRamMap);
 | |
|             ASSERT (VariableDefinition->FakeNvRamMap);
 | |
| 
 | |
|             if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) {
 | |
|               Status = FormCallback->NvRead (
 | |
|                                       FormCallback,
 | |
|                                       VariableDefinition->VariableName,
 | |
|                                       &VariableDefinition->Guid,
 | |
|                                       NULL,
 | |
|                                       &SizeOfNvStore,
 | |
|                                       (VOID *) VariableDefinition->NvRamMap
 | |
|                                       );
 | |
|             } else {
 | |
|               Status = gRT->GetVariable (
 | |
|                               VariableDefinition->VariableName,
 | |
|                               &VariableDefinition->Guid,
 | |
|                               NULL,
 | |
|                               &SizeOfNvStore,
 | |
|                               (VOID *) VariableDefinition->NvRamMap
 | |
|                               );
 | |
|             }
 | |
|           }
 | |
|           //
 | |
|           // if the variable was not found, we will retrieve default values
 | |
|           //
 | |
|           if (Status == EFI_NOT_FOUND) {
 | |
| 
 | |
|             if (0 == CompareMem (VariableDefinition->VariableName, L"Setup", 10)) {
 | |
| 
 | |
|               NvMapListHead = NULL;
 | |
| 
 | |
|               Status = Hii->GetDefaultImage (Hii, Handle[HandleIndex], EFI_IFR_FLAG_DEFAULT, &NvMapListHead);
 | |
| 
 | |
|               if (!EFI_ERROR (Status)) {
 | |
|                 ASSERT_EFI_ERROR (NULL != NvMapListHead);
 | |
| 
 | |
|                 NvMapListNode = NvMapListHead;
 | |
| 
 | |
|                 while (NULL != NvMapListNode) {
 | |
|                   if (VariableDefinition->VariableId == NvMapListNode->VariablePack->VariableId) {
 | |
|                     NvMap     = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength);
 | |
|                     NvMapSize = NvMapListNode->VariablePack->Header.Length  - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength;
 | |
|                     break;
 | |
|                     }
 | |
|                   NvMapListNode = NvMapListNode->NextVariablePack;
 | |
|                 }
 | |
| 
 | |
|                 //
 | |
|                 // Free the buffer that was allocated.
 | |
|                 //
 | |
|                 FreePool (VariableDefinition->NvRamMap);
 | |
|                 FreePool (VariableDefinition->FakeNvRamMap);
 | |
| 
 | |
|                 //
 | |
|                 // Allocate, copy the NvRamMap.
 | |
|                 //
 | |
|                 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize - VariableDefinition->VariableSize);
 | |
|                 VariableDefinition->VariableSize = (UINT16) NvMapSize;
 | |
|                 VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + VariableDefinition->VariableSize);
 | |
| 
 | |
|                 VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize);
 | |
|                 VariableDefinition->FakeNvRamMap = AllocateZeroPool (NvMapSize + VariableDefinition->VariableFakeSize);
 | |
| 
 | |
|                 CopyMem (VariableDefinition->NvRamMap, NvMap, NvMapSize);
 | |
|                 FreePool (NvMapListHead);
 | |
|               }
 | |
| 
 | |
|             }
 | |
|             Status = EFI_SUCCESS;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     InitializeTagStructures (BinaryData, FileFormTags);
 | |
|   }
 | |
|   //
 | |
|   // endfor
 | |
|   //
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| GetIfrBinaryData (
 | |
|   IN      EFI_HII_PROTOCOL *Hii,
 | |
|   IN      EFI_HII_HANDLE   HiiHandle,
 | |
|   IN      EFI_IFR_PACKET   *Packet,
 | |
|   IN OUT  EFI_IFR_BINARY   *BinaryData
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Fetch the Ifr binary data.
 | |
| 
 | |
| Arguments:
 | |
|   Hii         - Point to HII protocol.
 | |
|   HiiHandle   - Handle of Ifr to be fetched.
 | |
|   Packet      - Pointer to IFR packet.
 | |
|   BinaryData  - Buffer to copy the string into
 | |
| 
 | |
| Returns:
 | |
|   Returns the number of CHAR16 characters that were copied into the OutputString buffer.
 | |
| 
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS        Status;
 | |
|   EFI_HII_PACKAGES  *PackageList;
 | |
|   UINTN             BufferSize;
 | |
|   VOID              *Buffer;
 | |
|   UINT8             *RawFormBinary;
 | |
|   EFI_IFR_FORM_SET  *FormOp;
 | |
|   UINT16            Index;
 | |
|   UINT16            Index2;
 | |
|   UINT16            TitleToken;
 | |
| 
 | |
|   //
 | |
|   // Initialize the TitleToken to 0 just in case not found
 | |
|   //
 | |
|   TitleToken = 0;
 | |
| 
 | |
|   //
 | |
|   // Try for a 32K Buffer
 | |
|   //
 | |
|   BufferSize = 0x8000;
 | |
| 
 | |
|   //
 | |
|   // Allocate memory for our Form binary
 | |
|   //
 | |
|   Buffer = AllocateZeroPool (BufferSize);
 | |
|   ASSERT (Buffer);
 | |
| 
 | |
|   if (Packet == NULL) {
 | |
|     Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer);
 | |
| 
 | |
|     if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
| 
 | |
|       FreePool (Buffer);
 | |
| 
 | |
|       //
 | |
|       // Allocate memory for our Form binary
 | |
|       //
 | |
|       Buffer = AllocatePool (BufferSize);
 | |
|       ASSERT (Buffer);
 | |
| 
 | |
|       Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer);
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // Copies the data to local usable buffer
 | |
|     //
 | |
|     CopyMem (Buffer, Packet->IfrData, Packet->IfrData->Header.Length);
 | |
| 
 | |
|     //
 | |
|     // Register the string data with HII
 | |
|     //
 | |
|     PackageList = PreparePackages (2, NULL, Packet->IfrData, Packet->StringData);
 | |
| 
 | |
|     Status      = Hii->NewPack (Hii, PackageList, &HiiHandle);
 | |
| 
 | |
|     FreePool (PackageList);
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // We now have the IFR binary in our Buffer
 | |
|   //
 | |
|   BinaryData->IfrPackage  = Buffer;
 | |
|   RawFormBinary           = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER));
 | |
|   BinaryData->FormBinary  = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER));
 | |
|   BinaryData->Handle      = HiiHandle;
 | |
| 
 | |
|   //
 | |
|   // If a packet was passed in, remove the string data when exiting.
 | |
|   //
 | |
|   if (Packet != NULL) {
 | |
|     BinaryData->UnRegisterOnExit = TRUE;
 | |
|   } else {
 | |
|     BinaryData->UnRegisterOnExit = FALSE;
 | |
|   }
 | |
|   //
 | |
|   // Walk through the FormSet Opcodes looking for the FormSet opcode
 | |
|   // If we hit EFI_IFR_END_SET_OP we know we hit the end of the FormSet.
 | |
|   //
 | |
|   for (Index = 0; RawFormBinary[Index] != EFI_IFR_END_FORM_SET_OP;) {
 | |
|     FormOp  = (EFI_IFR_FORM_SET *) &RawFormBinary[Index];
 | |
|     Index   = (UINT16) (Index + FormOp->Header.Length);
 | |
| 
 | |
|     if (FormOp->Header.OpCode == EFI_IFR_FORM_SET_OP) {
 | |
|       TitleToken = FormOp->FormSetTitle;
 | |
|       //
 | |
|       // If displaying FrontPage - set the flag signifying it
 | |
|       //
 | |
|       switch (FormOp->SubClass) {
 | |
|       case EFI_FRONT_PAGE_SUBCLASS:
 | |
|         FrontPageHandle = HiiHandle;
 | |
| 
 | |
|       default:
 | |
|         gClassOfVfr = FormOp->SubClass;
 | |
|       }
 | |
|       //
 | |
|       // Match GUID to find out the function key setting. If match fail, use the default setting.
 | |
|       //
 | |
|       for (Index2 = 0; Index2 < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index2++) {
 | |
|         if (CompareGuid ((EFI_GUID *)(UINTN)&FormOp->Guid, &(gFunctionKeySettingTable[Index2].FormSetGuid))) {
 | |
|           //
 | |
|           // Update the function key setting.
 | |
|           //
 | |
|           gFunctionKeySetting = gFunctionKeySettingTable[Index2].KeySetting;
 | |
|           //
 | |
|           // Function key prompt can not be displayed if the function key has been disabled.
 | |
|           //
 | |
|           if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) {
 | |
|             gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
 | |
|           }
 | |
| 
 | |
|           if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) {
 | |
|             gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
 | |
|           }
 | |
| 
 | |
|           if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) {
 | |
|             gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
 | |
|           }
 | |
| 
 | |
|           if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) {
 | |
|             gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   BinaryData->TitleToken = TitleToken;
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_HANDLE          PrintHandle     = NULL;
 | |
| EFI_PRINT_PROTOCOL  mPrintProtocol  = { UnicodeVSPrint };
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| InstallPrint (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   return gBS->InstallProtocolInterface (
 | |
|                 &PrintHandle,
 | |
|                 &gEfiPrintProtocolGuid,
 | |
|                 EFI_NATIVE_INTERFACE,
 | |
|                 &mPrintProtocol
 | |
|                 );
 | |
| }
 |