mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-31 19:23:54 +01:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4599 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1122 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1122 lines
		
	
	
		
			32 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
| Copyright (c) 2007, 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.
 | |
| 
 | |
| Module Name:
 | |
| 
 | |
|   UefiIfrForm.c
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
|   Common Library Routines to assist handle HII elements.
 | |
| 
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "UefiIfrLibraryInternal.h"
 | |
| 
 | |
| //
 | |
| // Fake <ConfigHdr>
 | |
| //
 | |
| UINT16 mFakeConfigHdr[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=0";
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| GetPackageDataFromPackageList (
 | |
|   IN  EFI_HII_PACKAGE_LIST_HEADER *HiiPackageList,
 | |
|   IN  UINT32                      PackageIndex,
 | |
|   OUT UINT32                      *BufferLen,
 | |
|   OUT EFI_HII_PACKAGE_HEADER      **Buffer
 | |
|   )
 | |
| {
 | |
|   UINT32                        Index;
 | |
|   EFI_HII_PACKAGE_HEADER        *Package;
 | |
|   UINT32                        Offset;
 | |
|   UINT32                        PackageListLength;
 | |
|   EFI_HII_PACKAGE_HEADER        PackageHeader = {0, 0};
 | |
| 
 | |
|   ASSERT(HiiPackageList != NULL);
 | |
| 
 | |
|   if ((BufferLen == NULL) || (Buffer == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Package = NULL;
 | |
|   Index   = 0;
 | |
|   Offset  = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
 | |
|   CopyMem (&PackageListLength, &HiiPackageList->PackageLength, sizeof (UINT32));
 | |
|   while (Offset < PackageListLength) {
 | |
|     Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
 | |
|     CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
|     if (Index == PackageIndex) {
 | |
|       break;
 | |
|     }
 | |
|     Offset += PackageHeader.Length;
 | |
|     Index++;
 | |
|   }
 | |
|   if (Offset >= PackageListLength) {
 | |
|     //
 | |
|     // no package found in this Package List
 | |
|     //
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   *BufferLen = PackageHeader.Length;
 | |
|   *Buffer    = Package;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| UpdateFormPackageData (
 | |
|   IN  EFI_GUID               *FormSetGuid,
 | |
|   IN  EFI_FORM_ID            FormId,
 | |
|   IN  EFI_HII_PACKAGE_HEADER *Package,
 | |
|   IN  UINT32                 PackageLength,
 | |
|   IN  UINT16                 Label,
 | |
|   IN  BOOLEAN                Insert,
 | |
|   IN  EFI_HII_UPDATE_DATA    *Data,
 | |
|   OUT UINT8                  **TempBuffer,
 | |
|   OUT UINT32                 *TempBufferSize
 | |
|   )
 | |
| {
 | |
|   UINTN                     AddSize;
 | |
|   UINT8                     *BufferPos;
 | |
|   EFI_HII_PACKAGE_HEADER    PackageHeader;
 | |
|   UINTN                     Offset;
 | |
|   EFI_IFR_OP_HEADER         *IfrOpHdr;
 | |
|   BOOLEAN                   GetFormSet;
 | |
|   BOOLEAN                   GetForm;
 | |
|   UINT8                     ExtendOpCode;
 | |
|   UINT16                    LabelNumber;
 | |
|   BOOLEAN                   Updated;
 | |
|   EFI_IFR_OP_HEADER         *AddOpCode;
 | |
| 
 | |
|   if ((TempBuffer == NULL) || (TempBufferSize == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *TempBufferSize = PackageLength;
 | |
|   if (Data != NULL) {
 | |
|     *TempBufferSize += Data->Offset;
 | |
|   }
 | |
|   *TempBuffer = AllocateZeroPool (*TempBufferSize);
 | |
|   if (*TempBuffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   CopyMem (*TempBuffer, Package, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
|   *TempBufferSize = sizeof (EFI_HII_PACKAGE_HEADER);
 | |
|   BufferPos = *TempBuffer + sizeof (EFI_HII_PACKAGE_HEADER);
 | |
| 
 | |
|   CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
|   IfrOpHdr   = (EFI_IFR_OP_HEADER *)((UINT8 *) Package + sizeof (EFI_HII_PACKAGE_HEADER));
 | |
|   Offset     = sizeof (EFI_HII_PACKAGE_HEADER);
 | |
|   GetFormSet = (BOOLEAN) ((FormSetGuid == NULL) ? TRUE : FALSE);
 | |
|   GetForm    = FALSE;
 | |
|   Updated    = FALSE;
 | |
| 
 | |
|   while (Offset < PackageHeader.Length) {
 | |
|     CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
 | |
|     BufferPos += IfrOpHdr->Length;
 | |
|     *TempBufferSize += IfrOpHdr->Length;
 | |
| 
 | |
|     switch (IfrOpHdr->OpCode) {
 | |
|     case EFI_IFR_FORM_SET_OP :
 | |
|       if (FormSetGuid != NULL) {
 | |
|         if (CompareMem (&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid, sizeof (EFI_GUID)) == 0) {
 | |
|           GetFormSet = TRUE;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_FORM_OP:
 | |
|       if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
 | |
|         GetForm = TRUE;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_IFR_GUID_OP :
 | |
|       if (!GetFormSet || !GetForm || Updated) {
 | |
|         //
 | |
|         // Go to the next Op-Code
 | |
|         //
 | |
|         Offset   += IfrOpHdr->Length;
 | |
|         IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
 | |
|       CopyMem (&LabelNumber, &((EFI_IFR_GUID_LABEL *)IfrOpHdr)->Number, sizeof (UINT16));
 | |
|       if ((ExtendOpCode != EFI_IFR_EXTEND_OP_LABEL) || (LabelNumber != Label)) {
 | |
|         //
 | |
|         // Go to the next Op-Code
 | |
|         //
 | |
|         Offset   += IfrOpHdr->Length;
 | |
|         IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       if (Insert && (Data != NULL)) {
 | |
|         //
 | |
|         // insert the DataCount amount of opcodes to TempBuffer if Data is NULL remove
 | |
|         // DataCount amount of opcodes unless runing into a label.
 | |
|         //
 | |
|         AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;
 | |
|         AddSize   = 0;
 | |
|         while (AddSize < Data->Offset) {
 | |
|           CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
 | |
|           BufferPos += AddOpCode->Length;
 | |
|           *TempBufferSize += AddOpCode->Length;
 | |
| 
 | |
|           AddSize += AddOpCode->Length;
 | |
|           AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);
 | |
|         }
 | |
|       } else {
 | |
|         //
 | |
|         // Search the next Label.
 | |
|         //
 | |
|         while (TRUE) {
 | |
|           Offset   += IfrOpHdr->Length;
 | |
|           //
 | |
|           // Search the next label and Fail if not label found.
 | |
|           //
 | |
|           if (Offset >= PackageHeader.Length) {
 | |
|             goto Fail;
 | |
|           }
 | |
|           IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
 | |
|           if (IfrOpHdr->OpCode == EFI_IFR_GUID_OP) {
 | |
|             ExtendOpCode = ((EFI_IFR_GUID_LABEL *) IfrOpHdr)->ExtendOpCode;
 | |
|             if (ExtendOpCode == EFI_IFR_EXTEND_OP_LABEL) {
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         if (Data != NULL) {
 | |
|           AddOpCode = (EFI_IFR_OP_HEADER *)Data->Data;
 | |
|           AddSize   = 0;
 | |
|           while (AddSize < Data->Offset) {
 | |
|             CopyMem (BufferPos, AddOpCode, AddOpCode->Length);
 | |
|             BufferPos += AddOpCode->Length;
 | |
|             *TempBufferSize += AddOpCode->Length;
 | |
| 
 | |
|             AddSize   += AddOpCode->Length;
 | |
|             AddOpCode = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (AddOpCode) + AddOpCode->Length);
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // copy the next label
 | |
|         //
 | |
|         CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
 | |
|         BufferPos += IfrOpHdr->Length;
 | |
|         *TempBufferSize += IfrOpHdr->Length;
 | |
|       }
 | |
| 
 | |
|       Updated = TRUE;
 | |
|       break;
 | |
|     default :
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Go to the next Op-Code
 | |
|     //
 | |
|     Offset   += IfrOpHdr->Length;
 | |
|     IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Update the package length.
 | |
|   //
 | |
|   PackageHeader.Length = *TempBufferSize;
 | |
|   CopyMem (*TempBuffer, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
| 
 | |
| Fail:
 | |
|   if (!Updated) {
 | |
|     gBS->FreePool (*TempBuffer);
 | |
|     *TempBufferSize = 0;
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   This function allows the caller to update a form that has
 | |
|   previously been registered with the EFI HII database.
 | |
| 
 | |
|   @param  Handle                 Hii Handle
 | |
|   @param  FormSetGuid            The formset should be updated.
 | |
|   @param  FormId                 The form should be updated.
 | |
|   @param  Label                  Update information starting immediately after this
 | |
|                                  label in the IFR
 | |
|   @param  Insert                 If TRUE and Data is not NULL, insert data after
 | |
|                                  Label. If FALSE, replace opcodes between two
 | |
|                                  labels with Data
 | |
|   @param  Data                   The adding data; If NULL, remove opcodes between
 | |
|                                  two Label.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Update success.
 | |
|   @retval Other                  Update fail.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrLibUpdateForm (
 | |
|   IN EFI_HII_HANDLE            Handle,
 | |
|   IN EFI_GUID                  *FormSetGuid, OPTIONAL
 | |
|   IN EFI_FORM_ID               FormId,
 | |
|   IN UINT16                    Label,
 | |
|   IN BOOLEAN                   Insert,
 | |
|   IN EFI_HII_UPDATE_DATA       *Data
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   EFI_HII_DATABASE_PROTOCOL    *HiiDatabase;
 | |
|   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
 | |
|   UINT32                       Index;
 | |
|   EFI_HII_PACKAGE_LIST_HEADER  *UpdateBuffer;
 | |
|   UINTN                        BufferSize;
 | |
|   UINT8                        *UpdateBufferPos;
 | |
|   EFI_HII_PACKAGE_HEADER       PackageHeader;
 | |
|   EFI_HII_PACKAGE_HEADER       *Package;
 | |
|   UINT32                       PackageLength;
 | |
|   EFI_HII_PACKAGE_HEADER       *TempBuffer;
 | |
|   UINT32                       TempBufferSize;
 | |
|   BOOLEAN                      Updated;
 | |
| 
 | |
|   if (Data == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   LocateHiiProtocols ();
 | |
|   HiiDatabase = gIfrLibHiiDatabase;
 | |
| 
 | |
|   //
 | |
|   // Get the orginal package list
 | |
|   //
 | |
|   BufferSize = 0;
 | |
|   HiiPackageList   = NULL;
 | |
|   Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
 | |
|   if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|     HiiPackageList = AllocatePool (BufferSize);
 | |
|     ASSERT (HiiPackageList != NULL);
 | |
| 
 | |
|     Status = HiiDatabase->ExportPackageLists (HiiDatabase, Handle, &BufferSize, HiiPackageList);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       gBS->FreePool (HiiPackageList);
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Calculate and allocate space for retrieval of IFR data
 | |
|   //
 | |
|   BufferSize += Data->Offset;
 | |
|   UpdateBuffer = AllocateZeroPool (BufferSize);
 | |
|   if (UpdateBuffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   UpdateBufferPos = (UINT8 *) UpdateBuffer;
 | |
| 
 | |
|   //
 | |
|   // copy the package list header
 | |
|   //
 | |
|   CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
 | |
|   UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
 | |
| 
 | |
|   Updated = FALSE;
 | |
|   for (Index = 0; ; Index++) {
 | |
|     Status = GetPackageDataFromPackageList (HiiPackageList, Index, &PackageLength, &Package);
 | |
|     if (Status == EFI_SUCCESS) {
 | |
|       CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
|       if ((PackageHeader.Type == EFI_HII_PACKAGE_FORM) && !Updated) {
 | |
|         Status = UpdateFormPackageData (FormSetGuid, FormId, Package, PackageLength, Label, Insert, Data, (UINT8 **)&TempBuffer, &TempBufferSize);
 | |
|         if (!EFI_ERROR(Status)) {
 | |
|           if (FormSetGuid == NULL) {
 | |
|             Updated = TRUE;
 | |
|           }
 | |
|           CopyMem (UpdateBufferPos, TempBuffer, TempBufferSize);
 | |
|           UpdateBufferPos += TempBufferSize;
 | |
|           gBS->FreePool (TempBuffer);
 | |
|           continue;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       CopyMem (UpdateBufferPos, Package, PackageLength);
 | |
|       UpdateBufferPos += PackageLength;
 | |
|     } else if (Status == EFI_NOT_FOUND) {
 | |
|       break;
 | |
|     } else {
 | |
|       gBS->FreePool (HiiPackageList);
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Update package list length
 | |
|   //
 | |
|   BufferSize = UpdateBufferPos - (UINT8 *) UpdateBuffer;
 | |
|   CopyMem (&UpdateBuffer->PackageLength, &BufferSize, sizeof (UINT32));
 | |
| 
 | |
|   gBS->FreePool (HiiPackageList);
 | |
| 
 | |
|   return HiiDatabase->UpdatePackageList (HiiDatabase, Handle, UpdateBuffer);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Draw a dialog and return the selected key.
 | |
| 
 | |
|   @param  NumberOfLines          The number of lines for the dialog box
 | |
|   @param  KeyValue               The EFI_KEY value returned if HotKey is TRUE..
 | |
|   @param  String                 Pointer to the first string in the list
 | |
|   @param  ...                    A series of (quantity == NumberOfLines) text
 | |
|                                  strings which will be used to construct the dialog
 | |
|                                  box
 | |
| 
 | |
|   @retval EFI_SUCCESS            Displayed dialog and received user interaction
 | |
|   @retval EFI_INVALID_PARAMETER  One of the parameters was invalid.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| IfrLibCreatePopUp (
 | |
|   IN  UINTN                       NumberOfLines,
 | |
|   OUT EFI_INPUT_KEY               *KeyValue,
 | |
|   IN  CHAR16                      *String,
 | |
|   ...
 | |
|   )
 | |
| {
 | |
|   UINTN                         Index;
 | |
|   UINTN                         Count;
 | |
|   UINTN                         Start;
 | |
|   UINTN                         Top;
 | |
|   CHAR16                        *StringPtr;
 | |
|   UINTN                         LeftColumn;
 | |
|   UINTN                         RightColumn;
 | |
|   UINTN                         TopRow;
 | |
|   UINTN                         BottomRow;
 | |
|   UINTN                         DimensionsWidth;
 | |
|   UINTN                         DimensionsHeight;
 | |
|   VA_LIST                       Marker;
 | |
|   EFI_INPUT_KEY                 Key;
 | |
|   UINTN                         LargestString;
 | |
|   CHAR16                        *StackString;
 | |
|   EFI_STATUS                    Status;
 | |
|   UINTN                         StringLen;
 | |
|   CHAR16                        *LineBuffer;
 | |
|   CHAR16                        **StringArray;
 | |
|   EFI_EVENT                     TimerEvent;
 | |
|   EFI_EVENT                     WaitList[2];
 | |
|   UINTN                         CurrentAttribute;
 | |
|   EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut;
 | |
| 
 | |
|   if ((KeyValue == NULL) || (String == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   TopRow      = 0;
 | |
|   BottomRow   = 0;
 | |
|   LeftColumn  = 0;
 | |
|   RightColumn = 0;
 | |
| 
 | |
|   ConOut = gST->ConOut;
 | |
|   ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &RightColumn, &BottomRow);
 | |
| 
 | |
|   DimensionsWidth  = RightColumn - LeftColumn;
 | |
|   DimensionsHeight = BottomRow - TopRow;
 | |
| 
 | |
|   CurrentAttribute = ConOut->Mode->Attribute;
 | |
| 
 | |
|   LineBuffer = AllocateZeroPool (DimensionsWidth * sizeof (CHAR16));
 | |
|   ASSERT (LineBuffer != NULL);
 | |
| 
 | |
|   //
 | |
|   // Determine the largest string in the dialog box
 | |
|   // Notice we are starting with 1 since String is the first string
 | |
|   //
 | |
|   StringArray = AllocateZeroPool (NumberOfLines * sizeof (CHAR16 *));
 | |
|   LargestString = StrLen (String);
 | |
|   StringArray[0] = String;
 | |
| 
 | |
|   VA_START (Marker, String);
 | |
|   for (Index = 1; Index < NumberOfLines; Index++) {
 | |
|     StackString = VA_ARG (Marker, CHAR16 *);
 | |
| 
 | |
|     if (StackString == NULL) {
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     StringArray[Index] = StackString;
 | |
|     StringLen = StrLen (StackString);
 | |
|     if (StringLen > LargestString) {
 | |
|       LargestString = StringLen;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((LargestString + 2) > DimensionsWidth) {
 | |
|     LargestString = DimensionsWidth - 2;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Subtract the PopUp width from total Columns, allow for one space extra on
 | |
|   // each end plus a border.
 | |
|   //
 | |
|   Start     = (DimensionsWidth - LargestString - 2) / 2 + LeftColumn + 1;
 | |
| 
 | |
|   Top       = ((DimensionsHeight - NumberOfLines - 2) / 2) + TopRow - 1;
 | |
| 
 | |
|   //
 | |
|   // Disable cursor
 | |
|   //
 | |
|   ConOut->EnableCursor (ConOut, FALSE);
 | |
|   ConOut->SetAttribute (ConOut, EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE);
 | |
| 
 | |
|   StringPtr = &LineBuffer[0];
 | |
|   *StringPtr++ = BOXDRAW_DOWN_RIGHT;
 | |
|   for (Index = 0; Index < LargestString; Index++) {
 | |
|     *StringPtr++ = BOXDRAW_HORIZONTAL;
 | |
|   }
 | |
|   *StringPtr++ = BOXDRAW_DOWN_LEFT;
 | |
|   *StringPtr = L'\0';
 | |
| 
 | |
|   ConOut->SetCursorPosition (ConOut, Start, Top);
 | |
|   ConOut->OutputString (ConOut, LineBuffer);
 | |
| 
 | |
|   for (Index = 0; Index < NumberOfLines; Index++) {
 | |
|     StringPtr = &LineBuffer[0];
 | |
|     *StringPtr++ = BOXDRAW_VERTICAL;
 | |
| 
 | |
|     for (Count = 0; Count < LargestString; Count++) {
 | |
|       StringPtr[Count] = L' ';
 | |
|     }
 | |
| 
 | |
|     StringLen = StrLen (StringArray[Index]);
 | |
|     if (StringLen > LargestString) {
 | |
|       StringLen = LargestString;
 | |
|     }
 | |
|     CopyMem (
 | |
|       StringPtr + ((LargestString - StringLen) / 2),
 | |
|       StringArray[Index],
 | |
|       StringLen * sizeof (CHAR16)
 | |
|       );
 | |
|     StringPtr += LargestString;
 | |
| 
 | |
|     *StringPtr++ = BOXDRAW_VERTICAL;
 | |
|     *StringPtr = L'\0';
 | |
| 
 | |
|     ConOut->SetCursorPosition (ConOut, Start, Top + 1 + Index);
 | |
|     ConOut->OutputString (ConOut, LineBuffer);
 | |
|   }
 | |
| 
 | |
|   StringPtr = &LineBuffer[0];
 | |
|   *StringPtr++ = BOXDRAW_UP_RIGHT;
 | |
|   for (Index = 0; Index < LargestString; Index++) {
 | |
|     *StringPtr++ = BOXDRAW_HORIZONTAL;
 | |
|   }
 | |
|   *StringPtr++ = BOXDRAW_UP_LEFT;
 | |
|   *StringPtr = L'\0';
 | |
| 
 | |
|   ConOut->SetCursorPosition (ConOut, Start, Top + NumberOfLines + 1);
 | |
|   ConOut->OutputString (ConOut, LineBuffer);
 | |
| 
 | |
|   do {
 | |
|     Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
 | |
| 
 | |
|     //
 | |
|     // Set a timer event of 1 second expiration
 | |
|     //
 | |
|     gBS->SetTimer (
 | |
|           TimerEvent,
 | |
|           TimerRelative,
 | |
|           10000000
 | |
|           );
 | |
| 
 | |
|     //
 | |
|     // Wait for the keystroke event or the timer
 | |
|     //
 | |
|     WaitList[0] = gST->ConIn->WaitForKey;
 | |
|     WaitList[1] = TimerEvent;
 | |
|     Status      = gBS->WaitForEvent (2, WaitList, &Index);
 | |
| 
 | |
|     //
 | |
|     // Check for the timer expiration
 | |
|     //
 | |
|     if (!EFI_ERROR (Status) && Index == 1) {
 | |
|       Status = EFI_TIMEOUT;
 | |
|     }
 | |
| 
 | |
|     gBS->CloseEvent (TimerEvent);
 | |
|   } while (Status == EFI_TIMEOUT);
 | |
| 
 | |
|   Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | |
|   CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY));
 | |
| 
 | |
|   ConOut->SetAttribute (ConOut, CurrentAttribute);
 | |
|   ConOut->EnableCursor (ConOut, TRUE);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Configure the buffer accrording to ConfigBody strings.
 | |
| 
 | |
|   @param  DefaultId              the ID of default.
 | |
|   @param  Buffer                 the start address of buffer.
 | |
|   @param  BufferSize             the size of buffer.
 | |
|   @param  Number                 the number of the strings.
 | |
| 
 | |
|   @retval EFI_BUFFER_TOO_SMALL   the BufferSize is too small to operate.
 | |
|   @retval EFI_INVALID_PARAMETER  Buffer is NULL or BufferSize is 0.
 | |
|   @retval EFI_SUCCESS            Operation successful.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| ExtractDefault(
 | |
|   IN VOID                         *Buffer,
 | |
|   IN UINTN                        *BufferSize,
 | |
|   UINTN                           Number,
 | |
|   ...
 | |
|   )
 | |
| {
 | |
|   VA_LIST                         Args;
 | |
|   UINTN                           Index;
 | |
|   UINT32                          TotalLen;
 | |
|   UINT8                           *BufCfgArray;
 | |
|   UINT8                           *BufferPos;
 | |
|   UINT16                          Offset;
 | |
|   UINT16                          Width;
 | |
|   UINT8                           *Value;
 | |
| 
 | |
|   if ((Buffer == NULL) || (BufferSize == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Offset = 0;
 | |
|   Width  = 0;
 | |
|   Value  = NULL;
 | |
| 
 | |
|   VA_START (Args, Number);
 | |
|   for (Index = 0; Index < Number; Index++) {
 | |
|     BufCfgArray = (UINT8 *) VA_ARG (Args, VOID *);
 | |
|     CopyMem (&TotalLen, BufCfgArray, sizeof (UINT32));
 | |
|     BufferPos = BufCfgArray + sizeof (UINT32);
 | |
| 
 | |
|     while ((UINT32)(BufferPos - BufCfgArray) < TotalLen) {
 | |
|       CopyMem (&Offset, BufferPos, sizeof (UINT16));
 | |
|       BufferPos += sizeof (UINT16);
 | |
|       CopyMem (&Width, BufferPos, sizeof (UINT16));
 | |
|       BufferPos += sizeof (UINT16);
 | |
|       Value = BufferPos;
 | |
|       BufferPos += Width;
 | |
| 
 | |
|       if ((UINTN)(Offset + Width) > *BufferSize) {
 | |
|         return EFI_BUFFER_TOO_SMALL;
 | |
|       }
 | |
| 
 | |
|       CopyMem ((UINT8 *)Buffer + Offset, Value, Width);
 | |
|     }
 | |
|   }
 | |
|   VA_END (Args);
 | |
| 
 | |
|   *BufferSize = (UINTN)Offset;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Swap bytes in the buffer.
 | |
| 
 | |
|   @param  Buffer                 Binary buffer.
 | |
|   @param  BufferSize             Size of the buffer in bytes.
 | |
| 
 | |
|   @return None.
 | |
| 
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| SwapBuffer (
 | |
|   IN OUT UINT8     *Buffer,
 | |
|   IN UINTN         BufferSize
 | |
|   )
 | |
| {
 | |
|   UINTN  Index;
 | |
|   UINT8  Temp;
 | |
|   UINTN  SwapCount;
 | |
| 
 | |
|   SwapCount = (BufferSize - 1) / 2;
 | |
|   for (Index = 0; Index < SwapCount; Index++) {
 | |
|     Temp = Buffer[Index];
 | |
|     Buffer[Index] = Buffer[BufferSize - 1 - Index];
 | |
|     Buffer[BufferSize - 1 - Index] = Temp;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Converts binary buffer to Unicode string in reversed byte order from R8_BufToHexString().
 | |
| 
 | |
|   @param  Str                    String for output
 | |
|   @param  Buffer                 Binary buffer.
 | |
|   @param  BufferSize             Size of the buffer in bytes.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The function completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| BufferToHexString (
 | |
|   IN OUT CHAR16    *Str,
 | |
|   IN UINT8         *Buffer,
 | |
|   IN UINTN         BufferSize
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINT8       *NewBuffer;
 | |
|   UINTN       StrBufferLen;
 | |
| 
 | |
|   NewBuffer = AllocateCopyPool (BufferSize, Buffer);
 | |
|   SwapBuffer (NewBuffer, BufferSize);
 | |
| 
 | |
|   StrBufferLen = (BufferSize + 1) * sizeof (CHAR16);
 | |
|   Status = R8_BufToHexString (Str, &StrBufferLen, NewBuffer, BufferSize);
 | |
| 
 | |
|   gBS->FreePool (NewBuffer);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Converts Hex String to binary buffer in reversed byte order from R8_HexStringToBuf().
 | |
| 
 | |
|   @param  Buffer                 Pointer to buffer that receives the data.
 | |
|   @param  BufferSize             Length in bytes of the buffer to hold converted
 | |
|                                  data. If routine return with EFI_SUCCESS,
 | |
|                                  containing length of converted data. If routine
 | |
|                                  return with EFI_BUFFER_TOO_SMALL, containg length
 | |
|                                  of buffer desired.
 | |
|   @param  Str                    String to be converted from.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The function completed successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| HexStringToBuffer (
 | |
|   IN OUT UINT8         *Buffer,
 | |
|   IN OUT UINTN         *BufferSize,
 | |
|   IN CHAR16            *Str
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       ConvertedStrLen;
 | |
| 
 | |
|   ConvertedStrLen = 0;
 | |
|   Status = R8_HexStringToBuf (Buffer, BufferSize, Str, &ConvertedStrLen);
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     SwapBuffer (Buffer, ConvertedStrLen);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Construct <ConfigHdr> using routing information GUID/NAME/PATH.
 | |
| 
 | |
|   @param  ConfigHdr              Pointer to the ConfigHdr string.
 | |
|   @param  StrBufferLen           On input: Length in bytes of buffer to hold the
 | |
|                                  ConfigHdr string. Includes tailing '\0' character.
 | |
|                                  On output: If return EFI_SUCCESS, containing
 | |
|                                  length of ConfigHdr string buffer. If return
 | |
|                                  EFI_BUFFER_TOO_SMALL, containg length of string
 | |
|                                  buffer desired.
 | |
|   @param  Guid                   Routing information: GUID.
 | |
|   @param  Name                   Routing information: NAME.
 | |
|   @param  DriverHandle           Driver handle which contains the routing
 | |
|                                  information: PATH.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Routine success.
 | |
|   @retval EFI_BUFFER_TOO_SMALL   The ConfigHdr string buffer is too small.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| ConstructConfigHdr (
 | |
|   IN OUT CHAR16                *ConfigHdr,
 | |
|   IN OUT UINTN                 *StrBufferLen,
 | |
|   IN EFI_GUID                  *Guid,
 | |
|   IN CHAR16                    *Name, OPTIONAL
 | |
|   IN EFI_HANDLE                *DriverHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   UINTN                     NameStrLen;
 | |
|   UINTN                     DevicePathSize;
 | |
|   UINTN                     BufferSize;
 | |
|   CHAR16                    *StrPtr;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | |
| 
 | |
|   if (Name == NULL) {
 | |
|     //
 | |
|     // There will be no "NAME" in <ConfigHdr> for  Name/Value storage
 | |
|     //
 | |
|     NameStrLen = 0;
 | |
|   } else {
 | |
|     //
 | |
|     // For buffer storage
 | |
|     //
 | |
|     NameStrLen = StrLen (Name);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve DevicePath Protocol associated with this HiiPackageList
 | |
|   //
 | |
|   Status = gBS->HandleProtocol (
 | |
|                   DriverHandle,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   (VOID **) &DevicePath
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   DevicePathSize = GetDevicePathSize (DevicePath);
 | |
| 
 | |
|   //
 | |
|   // GUID=<HexCh>32&NAME=<Alpha>NameStrLen&PATH=<HexChar>DevicePathStrLen <NULL>
 | |
|   // | 5  |   32   |  6  |   NameStrLen   |  6  |    DevicePathStrLen   |
 | |
|   //
 | |
|   BufferSize = (5 + 32 + 6 + NameStrLen + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16);
 | |
|   if (*StrBufferLen < BufferSize) {
 | |
|     *StrBufferLen = BufferSize;
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   *StrBufferLen = BufferSize;
 | |
| 
 | |
|   StrPtr = ConfigHdr;
 | |
| 
 | |
|   StrCpy (StrPtr, L"GUID=");
 | |
|   StrPtr += 5;
 | |
|   BufferToHexString (StrPtr, (UINT8 *) Guid, sizeof (EFI_GUID));
 | |
|   StrPtr += 32;
 | |
| 
 | |
|   StrCpy (StrPtr, L"&NAME=");
 | |
|   StrPtr += 6;
 | |
|   if (Name != NULL) {
 | |
|     StrCpy (StrPtr, Name);
 | |
|     StrPtr += NameStrLen;
 | |
|   }
 | |
| 
 | |
|   StrCpy (StrPtr, L"&PATH=");
 | |
|   StrPtr += 6;
 | |
|   BufferToHexString (StrPtr, (UINT8 *) DevicePath, DevicePathSize);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Search BlockName "&OFFSET=Offset&WIDTH=Width" in a string.
 | |
| 
 | |
|   @param  String                 The string to be searched in.
 | |
|   @param  Offset                 Offset in BlockName.
 | |
|   @param  Width                  Width in BlockName.
 | |
| 
 | |
|   @retval TRUE                   Block name found.
 | |
|   @retval FALSE                  Block name not found.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| FindBlockName (
 | |
|   IN OUT CHAR16                *String,
 | |
|   UINTN                        Offset,
 | |
|   UINTN                        Width
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       Data;
 | |
|   UINTN       BufferSize;
 | |
|   UINTN       ConvertedStrLen;
 | |
| 
 | |
|   while ((String = StrStr (String, L"&OFFSET=")) != NULL) {
 | |
|     //
 | |
|     // Skip '&OFFSET='
 | |
|     //
 | |
|     String = String + 8;
 | |
| 
 | |
|     Data = 0;
 | |
|     BufferSize = sizeof (UINTN);
 | |
|     Status = R8_HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return FALSE;
 | |
|     }
 | |
|     String = String + ConvertedStrLen;
 | |
| 
 | |
|     if (Data != Offset) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if (StrnCmp (String, L"&WIDTH=", 7) != 0) {
 | |
|       return FALSE;
 | |
|     }
 | |
|     String = String + 7;
 | |
| 
 | |
|     Data = 0;
 | |
|     BufferSize = sizeof (UINTN);
 | |
|     Status = R8_HexStringToBuf ((UINT8 *) &Data, &BufferSize, String, &ConvertedStrLen);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return FALSE;
 | |
|     }
 | |
|     if (Data == Width) {
 | |
|       return TRUE;
 | |
|     }
 | |
| 
 | |
|     String = String + ConvertedStrLen;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   This routine is invoked by ConfigAccess.Callback() to retrived uncommitted data from Form Browser.
 | |
| 
 | |
|   @param  VariableGuid           An optional field to indicate the target variable
 | |
|                                  GUID name to use.
 | |
|   @param  VariableName           An optional field to indicate the target
 | |
|                                  human-readable variable name.
 | |
|   @param  BufferSize             On input: Length in bytes of buffer to hold
 | |
|                                  retrived data. On output: If return
 | |
|                                  EFI_BUFFER_TOO_SMALL, containg length of buffer
 | |
|                                  desired.
 | |
|   @param  Buffer                 Buffer to hold retrived data.
 | |
| 
 | |
|   @retval EFI_SUCCESS            Routine success.
 | |
|   @retval EFI_BUFFER_TOO_SMALL   The intput buffer is too small.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| GetBrowserData (
 | |
|   EFI_GUID                   *VariableGuid, OPTIONAL
 | |
|   CHAR16                     *VariableName, OPTIONAL
 | |
|   UINTN                      *BufferSize,
 | |
|   UINT8                      *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   CHAR16                          *ConfigHdr;
 | |
|   CHAR16                          *ConfigResp;
 | |
|   CHAR16                          *StringPtr;
 | |
|   UINTN                           HeaderLen;
 | |
|   UINTN                           BufferLen;
 | |
|   CHAR16                          *Progress;
 | |
|   EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;
 | |
|   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
 | |
| 
 | |
|   //
 | |
|   // Locate protocols for use
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrive formset storage data from Form Browser
 | |
|   //
 | |
|   ConfigHdr = mFakeConfigHdr;
 | |
|   HeaderLen = StrLen (ConfigHdr);
 | |
| 
 | |
|   BufferLen = 0x4000;
 | |
|   ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
 | |
| 
 | |
|   StringPtr = ConfigResp + HeaderLen;
 | |
|   *StringPtr = L'&';
 | |
|   StringPtr++;
 | |
| 
 | |
|   Status = FormBrowser2->BrowserCallback (
 | |
|                            FormBrowser2,
 | |
|                            &BufferLen,
 | |
|                            StringPtr,
 | |
|                            TRUE,
 | |
|                            VariableGuid,
 | |
|                            VariableName
 | |
|                            );
 | |
|   if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|     gBS->FreePool (ConfigResp);
 | |
|     ConfigResp = AllocateZeroPool (BufferLen + HeaderLen);
 | |
| 
 | |
|     StringPtr = ConfigResp + HeaderLen;
 | |
|     *StringPtr = L'&';
 | |
|     StringPtr++;
 | |
| 
 | |
|     Status = FormBrowser2->BrowserCallback (
 | |
|                              FormBrowser2,
 | |
|                              &BufferLen,
 | |
|                              StringPtr,
 | |
|                              TRUE,
 | |
|                              VariableGuid,
 | |
|                              VariableName
 | |
|                              );
 | |
|   }
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->FreePool (ConfigResp);
 | |
|     return Status;
 | |
|   }
 | |
|   CopyMem (ConfigResp, ConfigHdr, HeaderLen * sizeof (UINT16));
 | |
| 
 | |
|   //
 | |
|   // Convert <ConfigResp> to buffer data
 | |
|   //
 | |
|   Status = HiiConfigRouting->ConfigToBlock (
 | |
|                                HiiConfigRouting,
 | |
|                                ConfigResp,
 | |
|                                Buffer,
 | |
|                                BufferSize,
 | |
|                                &Progress
 | |
|                                );
 | |
|   gBS->FreePool (ConfigResp);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   This routine is invoked by ConfigAccess.Callback() to update uncommitted data of Form Browser.
 | |
| 
 | |
|   @param  VariableGuid           An optional field to indicate the target variable
 | |
|                                  GUID name to use.
 | |
|   @param  VariableName           An optional field to indicate the target
 | |
|                                  human-readable variable name.
 | |
|   @param  BufferSize             Length in bytes of buffer to hold retrived data.
 | |
|   @param  Buffer                 Buffer to hold retrived data.
 | |
|   @param  RequestElement         An optional field to specify which part of the
 | |
|                                  buffer data will be send back to Browser. If NULL,
 | |
|                                  the whole buffer of data will be committed to
 | |
|                                  Browser. <RequestElement> ::=
 | |
|                                  &OFFSET=<Number>&WIDTH=<Number>*
 | |
| 
 | |
|   @retval EFI_SUCCESS            Routine success.
 | |
|   @retval Other                  Updating Browser uncommitted data failed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| SetBrowserData (
 | |
|   EFI_GUID                   *VariableGuid, OPTIONAL
 | |
|   CHAR16                     *VariableName, OPTIONAL
 | |
|   UINTN                      BufferSize,
 | |
|   UINT8                      *Buffer,
 | |
|   CHAR16                     *RequestElement  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   CHAR16                          *ConfigHdr;
 | |
|   CHAR16                          *ConfigResp;
 | |
|   CHAR16                          *StringPtr;
 | |
|   UINTN                           HeaderLen;
 | |
|   UINTN                           BufferLen;
 | |
|   CHAR16                          *Progress;
 | |
|   EFI_FORM_BROWSER2_PROTOCOL      *FormBrowser2;
 | |
|   EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;
 | |
|   CHAR16                          BlockName[33];
 | |
|   CHAR16                          *ConfigRequest;
 | |
|   CHAR16                          *Request;
 | |
| 
 | |
|   //
 | |
|   // Locate protocols for use
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Prepare <ConfigRequest>
 | |
|   //
 | |
|   ConfigHdr = mFakeConfigHdr;
 | |
|   HeaderLen = StrLen (ConfigHdr);
 | |
| 
 | |
|   if (RequestElement == NULL) {
 | |
|     //
 | |
|     // RequestElement not specified, use "&OFFSET=0&WIDTH=<BufferSize>" as <BlockName>
 | |
|     //
 | |
|     BlockName[0] = L'\0';
 | |
|     StrCpy (BlockName, L"&OFFSET=0&WIDTH=");
 | |
| 
 | |
|     //
 | |
|     // String lenghth of L"&OFFSET=0&WIDTH=" is 16
 | |
|     //
 | |
|     StringPtr = BlockName + 16;
 | |
|     BufferLen = sizeof (BlockName) - (16 * sizeof (CHAR16));
 | |
|     R8_BufToHexString (StringPtr, &BufferLen, (UINT8 *) &BufferSize, sizeof (UINTN));
 | |
| 
 | |
|     Request = BlockName;
 | |
|   } else {
 | |
|     Request = RequestElement;
 | |
|   }
 | |
| 
 | |
|   BufferLen = HeaderLen * sizeof (CHAR16) + StrSize (Request);
 | |
|   ConfigRequest = AllocateZeroPool (BufferLen);
 | |
| 
 | |
|   CopyMem (ConfigRequest, ConfigHdr, HeaderLen * sizeof (CHAR16));
 | |
|   StringPtr = ConfigRequest + HeaderLen;
 | |
|   StrCpy (StringPtr, Request);
 | |
| 
 | |
|   //
 | |
|   // Convert buffer to <ConfigResp>
 | |
|   //
 | |
|   Status = HiiConfigRouting->BlockToConfig (
 | |
|                                 HiiConfigRouting,
 | |
|                                 ConfigRequest,
 | |
|                                 Buffer,
 | |
|                                 BufferSize,
 | |
|                                 &ConfigResp,
 | |
|                                 &Progress
 | |
|                                 );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->FreePool (ConfigResp);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Skip <ConfigHdr> and '&'
 | |
|   //
 | |
|   StringPtr = ConfigResp + HeaderLen + 1;
 | |
| 
 | |
|   //
 | |
|   // Change uncommitted data in Browser
 | |
|   //
 | |
|   Status = FormBrowser2->BrowserCallback (
 | |
|                            FormBrowser2,
 | |
|                            &BufferSize,
 | |
|                            StringPtr,
 | |
|                            FALSE,
 | |
|                            NULL,
 | |
|                            NULL
 | |
|                            );
 | |
|   gBS->FreePool (ConfigResp);
 | |
|   return Status;
 | |
| }
 |