git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8325 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			3609 lines
		
	
	
		
			113 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3609 lines
		
	
	
		
			113 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   HII Library implementation that uses DXE protocols and services.
 | |
| 
 | |
|   Copyright (c) 2006 - 2008, 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 "InternalHiiLib.h"
 | |
| 
 | |
| #define GUID_CONFIG_STRING_TYPE 0x00
 | |
| #define NAME_CONFIG_STRING_TYPE 0x01
 | |
| #define PATH_CONFIG_STRING_TYPE 0x02
 | |
| 
 | |
| #define ACTION_SET_DEFAUTL_VALUE 0x01
 | |
| #define ACTION_VALIDATE_SETTING  0x02
 | |
| 
 | |
| #define HII_LIB_DEFAULT_VARSTORE_SIZE  0x200
 | |
| 
 | |
| typedef struct {
 | |
|   LIST_ENTRY          Entry;      // Link to Block array
 | |
|   UINT16              Offset;
 | |
|   UINT16              Width;
 | |
|   UINT8               OpCode;
 | |
|   UINT8               Scope;
 | |
| } IFR_BLOCK_DATA;
 | |
| 
 | |
| //
 | |
| // <ConfigHdr> Template
 | |
| //
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR16 mConfigHdrTemplate[] = L"GUID=00000000000000000000000000000000&NAME=0000&PATH=00";
 | |
| 
 | |
| EFI_FORM_BROWSER2_PROTOCOL  *mUefiFormBrowser2 = NULL;
 | |
| 
 | |
| //
 | |
| // Template used to mark the end of a list of packages 
 | |
| //
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED CONST EFI_HII_PACKAGE_HEADER  mEndOfPakageList = {
 | |
|   sizeof (EFI_HII_PACKAGE_HEADER),
 | |
|   EFI_HII_PACKAGE_END
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Extract Hii package list GUID for given HII handle.
 | |
| 
 | |
|   If HiiHandle could not be found in the HII database, then ASSERT.
 | |
|   If Guid is NULL, then ASSERT.
 | |
| 
 | |
|   @param  Handle              Hii handle
 | |
|   @param  Guid                Package list GUID
 | |
| 
 | |
|   @retval EFI_SUCCESS         Successfully extract GUID from Hii database.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InternalHiiExtractGuidFromHiiHandle (
 | |
|   IN      EFI_HII_HANDLE      Handle,
 | |
|   OUT     EFI_GUID            *Guid
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   UINTN                        BufferSize;
 | |
|   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
 | |
| 
 | |
|   ASSERT (Guid != NULL);
 | |
|   ASSERT (Handle != NULL);
 | |
| 
 | |
|   //
 | |
|   // Get HII PackageList
 | |
|   //
 | |
|   BufferSize = 0;
 | |
|   HiiPackageList = NULL;
 | |
| 
 | |
|   Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
 | |
|   ASSERT (Status != EFI_NOT_FOUND);
 | |
|   
 | |
|   if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|     HiiPackageList = AllocatePool (BufferSize);
 | |
|     ASSERT (HiiPackageList != NULL);
 | |
| 
 | |
|     Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, Handle, &BufferSize, HiiPackageList);
 | |
|   }
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FreePool (HiiPackageList);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Extract GUID
 | |
|   //
 | |
|   CopyGuid (Guid, &HiiPackageList->PackageListGuid);
 | |
| 
 | |
|   FreePool (HiiPackageList);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Registers a list of packages in the HII Database and returns the HII Handle
 | |
|   associated with that registration.  If an HII Handle has already been registered
 | |
|   with the same PackageListGuid, then NULL is returned.  If there are not enough 
 | |
|   resources to perform the registration, then NULL is returned.  If an empty list 
 | |
|   of packages is passed in, then NULL is returned.  If the size of the list of 
 | |
|   package is 0, then NULL is returned.
 | |
| 
 | |
|   The variable arguments are pointers which point to package header that defined 
 | |
|   by UEFI VFR compiler and StringGather tool.
 | |
| 
 | |
|   #pragma pack (push, 1)
 | |
|   typedef struct {
 | |
|     UINT32                  BinaryLength;
 | |
|     EFI_HII_PACKAGE_HEADER  PackageHeader;
 | |
|   } EDKII_AUTOGEN_PACKAGES_HEADER;
 | |
|   #pragma pack (pop)
 | |
|   
 | |
|   @param[in]  PackageListGuid  The GUID of the package list.
 | |
|   @param[in]  DeviceHandle     If not NULL, the Device Handle on which 
 | |
|                                an instance of DEVICE_PATH_PROTOCOL is installed.
 | |
|                                This Device Handle uniquely defines the device that 
 | |
|                                the added packages are associated with.
 | |
|   @param[in]  ...              The variable argument list that contains pointers 
 | |
|                                to packages terminated by a NULL.
 | |
| 
 | |
|   @retval NULL   A HII Handle has already been registered in the HII Database with
 | |
|                  the same PackageListGuid.
 | |
|   @retval NULL   The HII Handle could not be created.
 | |
|   @retval NULL   An empty list of packages was passed in.
 | |
|   @retval NULL   All packages are empty.
 | |
|   @retval Other  The HII Handle associated with the newly registered package list.
 | |
| 
 | |
| **/
 | |
| EFI_HII_HANDLE
 | |
| EFIAPI
 | |
| HiiAddPackages (
 | |
|   IN CONST EFI_GUID    *PackageListGuid,
 | |
|   IN       EFI_HANDLE  DeviceHandle  OPTIONAL,
 | |
|   ...
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   EFI_HII_HANDLE               *HiiHandleBuffer;
 | |
|   VA_LIST                      Args;
 | |
|   UINT32                       *Package;
 | |
|   EFI_HII_PACKAGE_LIST_HEADER  *PackageListHeader;
 | |
|   EFI_HII_HANDLE               HiiHandle;
 | |
|   UINT32                       Length;
 | |
|   UINT8                        *Data;
 | |
| 
 | |
|   ASSERT (PackageListGuid != NULL);
 | |
| 
 | |
|   //
 | |
|   // Check to see if an HII Handle has already been registered with the same 
 | |
|   // PackageListGuid
 | |
|   //
 | |
|   HiiHandleBuffer = HiiGetHiiHandles (PackageListGuid);
 | |
|   if (HiiHandleBuffer != NULL) {
 | |
|     FreePool (HiiHandleBuffer);
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Calculate the length of all the packages in the variable argument list
 | |
|   //
 | |
|   for (Length = 0, VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {
 | |
|     Length += (ReadUnaligned32 (Package) - sizeof (UINT32));
 | |
|   }
 | |
|   VA_END (Args);
 | |
| 
 | |
|   //
 | |
|   // If there are no packages in the variable argument list or all the packages 
 | |
|   // are empty, then return a NULL HII Handle
 | |
|   //
 | |
|   if (Length == 0) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Add the length of the Package List Header and the terminating Package Header 
 | |
|   //
 | |
|   Length += sizeof (EFI_HII_PACKAGE_LIST_HEADER) + sizeof (EFI_HII_PACKAGE_HEADER);
 | |
| 
 | |
|   //
 | |
|   // Allocate the storage for the entire Package List
 | |
|   //
 | |
|   PackageListHeader = AllocateZeroPool (Length);
 | |
| 
 | |
|   //
 | |
|   // If the Packahge List can not be allocated, then return a NULL HII Handle
 | |
|   //
 | |
|   if (PackageListHeader == NULL) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fill in the GUID and Length of the Package List Header
 | |
|   //
 | |
|   CopyGuid (&PackageListHeader->PackageListGuid, PackageListGuid);
 | |
|   PackageListHeader->PackageLength = Length;
 | |
| 
 | |
|   //
 | |
|   // Initialize a pointer to the beginning if the Package List data
 | |
|   //
 | |
|   Data = (UINT8 *)(PackageListHeader + 1);
 | |
| 
 | |
|   //
 | |
|   // Copy the data from each package in the variable argument list
 | |
|   //
 | |
|   for (VA_START (Args, DeviceHandle); (Package = VA_ARG (Args, UINT32 *)) != NULL; ) {
 | |
|     Length = ReadUnaligned32 (Package) - sizeof (UINT32);
 | |
|     CopyMem (Data, Package + 1, Length);
 | |
|     Data += Length;
 | |
|   }
 | |
|   VA_END (Args);
 | |
| 
 | |
|   //
 | |
|   // Append a package of type EFI_HII_PACKAGE_END to mark the end of the package list
 | |
|   //
 | |
|   CopyMem (Data, &mEndOfPakageList, sizeof (mEndOfPakageList));
 | |
| 
 | |
|   //
 | |
|   // Register the package list with the HII Database
 | |
|   //
 | |
|   Status = gHiiDatabase->NewPackageList (
 | |
|                            gHiiDatabase, 
 | |
|                            PackageListHeader, 
 | |
|                            DeviceHandle, 
 | |
|                            &HiiHandle
 | |
|                            );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     HiiHandle = NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free the allocated package list
 | |
|   //
 | |
|   FreePool (PackageListHeader);
 | |
| 
 | |
|   //
 | |
|   // Return the new HII Handle
 | |
|   //
 | |
|   return HiiHandle;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Removes a package list from the HII database.
 | |
| 
 | |
|   If HiiHandle is NULL, then ASSERT.
 | |
|   If HiiHandle is not a valid EFI_HII_HANDLE in the HII database, then ASSERT.
 | |
| 
 | |
|   @param[in]  HiiHandle   The handle that was previously registered in the HII database
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| HiiRemovePackages (
 | |
|   IN      EFI_HII_HANDLE      HiiHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   ASSERT (HiiHandle != NULL);
 | |
|   Status = gHiiDatabase->RemovePackageList (gHiiDatabase, HiiHandle);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Retrieves the array of all the HII Handles or the HII handle of a specific
 | |
|   package list in the HII Database.
 | |
|   This array is terminated with a NULL HII Handle.
 | |
|   This function allocates the returned array using AllocatePool().
 | |
|   The caller is responsible for freeing the array with FreePool().
 | |
| 
 | |
|   @param[in]  PackageListGuid  An optional parameter that is used to request 
 | |
|                                an HII Handle that is associatd with a specific
 | |
|                                Package List GUID.  If this parameter is NULL
 | |
|                                then all the HII Handles in the HII Database
 | |
|                                are returned.  If this parameter is not NULL
 | |
|                                then at most 1 HII Handle is returned.
 | |
| 
 | |
|   @retval NULL   No HII handles were found in the HII database
 | |
|   @retval NULL   The array of HII Handles could not be retrieved
 | |
|   @retval Other  A pointer to the NULL terminated array of HII Handles
 | |
| 
 | |
| **/
 | |
| EFI_HII_HANDLE *
 | |
| EFIAPI
 | |
| HiiGetHiiHandles (
 | |
|   IN CONST EFI_GUID  *PackageListGuid  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS      Status;
 | |
|   UINTN           HandleBufferLength;
 | |
|   EFI_HII_HANDLE  TempHiiHandleBuffer;
 | |
|   EFI_HII_HANDLE  *HiiHandleBuffer;
 | |
|   EFI_GUID        Guid;
 | |
|   UINTN           Index;
 | |
| 
 | |
|   //
 | |
|   // Retrieve the size required for the buffer of all HII handles.
 | |
|   //
 | |
|   HandleBufferLength = 0;
 | |
|   Status = gHiiDatabase->ListPackageLists (
 | |
|                            gHiiDatabase,
 | |
|                            EFI_HII_PACKAGE_TYPE_ALL,
 | |
|                            NULL,
 | |
|                            &HandleBufferLength,
 | |
|                            &TempHiiHandleBuffer
 | |
|                            );
 | |
| 
 | |
|   //
 | |
|   // If ListPackageLists() returns EFI_SUCCESS for a zero size, 
 | |
|   // then there are no HII handles in the HII database.  If ListPackageLists() 
 | |
|   // returns an error other than EFI_BUFFER_TOO_SMALL, then there are no HII 
 | |
|   // handles in the HII database.
 | |
|   //
 | |
|   if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|     //
 | |
|     // Return NULL if the size can not be retrieved, or if there are no HII 
 | |
|     // handles in the HII Database
 | |
|     //
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Allocate the array of HII handles to hold all the HII Handles and a NULL terminator
 | |
|   //
 | |
|   HiiHandleBuffer = AllocateZeroPool (HandleBufferLength + sizeof (EFI_HII_HANDLE));
 | |
|   if (HiiHandleBuffer == NULL) {
 | |
|     //
 | |
|     // Return NULL if allocation fails.
 | |
|     //
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve the array of HII Handles in the HII Database
 | |
|   //
 | |
|   Status = gHiiDatabase->ListPackageLists (
 | |
|                            gHiiDatabase,
 | |
|                            EFI_HII_PACKAGE_TYPE_ALL,
 | |
|                            NULL,
 | |
|                            &HandleBufferLength,
 | |
|                            HiiHandleBuffer
 | |
|                            );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Free the buffer and return NULL if the HII handles can not be retrieved.
 | |
|     //
 | |
|     FreePool (HiiHandleBuffer);
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   if (PackageListGuid == NULL) {
 | |
|     //
 | |
|     // Return the NULL terminated array of HII handles in the HII Database
 | |
|     //
 | |
|     return HiiHandleBuffer;
 | |
|   } else {
 | |
|     for (Index = 0; HiiHandleBuffer[Index] != NULL; Index++) {
 | |
|       Status = InternalHiiExtractGuidFromHiiHandle (HiiHandleBuffer[Index], &Guid);
 | |
|       ASSERT_EFI_ERROR (Status);
 | |
|       if (CompareGuid (&Guid, PackageListGuid)) {
 | |
|         HiiHandleBuffer[0] = HiiHandleBuffer[Index];
 | |
|         HiiHandleBuffer[1] = NULL;
 | |
|         return HiiHandleBuffer;
 | |
|       }
 | |
|     }
 | |
|     FreePool (HiiHandleBuffer);
 | |
|     return NULL;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Converts all hex dtring characters in range ['A'..'F'] to ['a'..'f'] for 
 | |
|   hex digits that appear between a '=' and a '&' in a config string.
 | |
| 
 | |
|   If String is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in] String  Pointer to a Null-terminated Unicode string.
 | |
| 
 | |
|   @return  Pointer to the Null-terminated Unicode result string.
 | |
| 
 | |
| **/
 | |
| EFI_STRING
 | |
| EFIAPI
 | |
| InternalHiiLowerConfigString (
 | |
|   IN EFI_STRING  ConfigString
 | |
|   )
 | |
| {
 | |
|   EFI_STRING  String;
 | |
|   BOOLEAN     Lower;
 | |
| 
 | |
|   ASSERT (ConfigString != NULL);
 | |
| 
 | |
|   //
 | |
|   // Convert all hex digits in range [A-F] in the configuration header to [a-f]
 | |
|   //
 | |
|   for (String = ConfigString, Lower = FALSE; *String != L'\0'; String++) {
 | |
|     if (*String == L'=') {
 | |
|       Lower = TRUE;
 | |
|     } else if (*String == L'&') {
 | |
|       Lower = FALSE;
 | |
|     } else if (Lower && *String >= L'A' && *String <= L'F') {
 | |
|       *String = (CHAR16) (*String - L'A' + L'a');
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ConfigString;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Uses the BlockToConfig() service of the Config Routing Protocol to 
 | |
|   convert <ConfigRequest> and a buffer to a <ConfigResp>
 | |
| 
 | |
|   If ConfigRequest is NULL, then ASSERT().
 | |
|   If Block is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in] ConfigRequest  Pointer to a Null-terminated Unicode string.
 | |
|   @param[in] Block          Pointer to a block of data.
 | |
|   @param[in] BlockSize      The zie, in bytes, of Block.
 | |
| 
 | |
|   @retval NULL   The <ConfigResp> string could not be generated.
 | |
|   @retval Other  Pointer to the Null-terminated Unicode <ConfigResp> string.
 | |
| 
 | |
| **/
 | |
| EFI_STRING
 | |
| EFIAPI
 | |
| InternalHiiBlockToConfig (
 | |
|   IN CONST EFI_STRING  ConfigRequest,
 | |
|   IN CONST UINT8       *Block,
 | |
|   IN UINTN             BlockSize
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   EFI_STRING  ConfigResp;
 | |
|   CHAR16      *Progress;
 | |
| 
 | |
|   ASSERT (ConfigRequest != NULL);
 | |
|   ASSERT (Block != NULL);
 | |
| 
 | |
|   //
 | |
|   // Convert <ConfigRequest> to <ConfigResp>
 | |
|   //
 | |
|   Status = gHiiConfigRouting->BlockToConfig (
 | |
|                                 gHiiConfigRouting,
 | |
|                                 ConfigRequest,
 | |
|                                 Block,
 | |
|                                 BlockSize,
 | |
|                                 &ConfigResp,
 | |
|                                 &Progress
 | |
|                                 );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return NULL;
 | |
|   }
 | |
|   return ConfigResp;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Uses the BrowserCallback() service of the Form Browser Protocol to retrieve 
 | |
|   or set uncommitted data.  If sata i being retrieved, then the buffer is 
 | |
|   allocated using AllocatePool().  The caller is then responsible for freeing 
 | |
|   the buffer using FreePool().
 | |
| 
 | |
|   @param[in]  VariableName    Pointer to a Null-terminated Unicode string.  This 
 | |
|                               is an optional parameter that may be NULL.
 | |
|   @param[in]  VariableGuid    Pointer to an EFI_GUID structure.  This is an optional 
 | |
|                               parameter that may be NULL.
 | |
|   @param[in]  SetResultsData  If not NULL, then this parameter specified the buffer
 | |
|                               of uncommited data to set.  If this parameter is NULL,
 | |
|                               then the caller is requesting to get the uncommited data
 | |
|                               from the Form Browser.
 | |
| 
 | |
|   @retval NULL   The uncommitted data could not be retrieved.
 | |
|   @retval Other  A pointer to a buffer containing the uncommitted data.
 | |
| 
 | |
| **/
 | |
| EFI_STRING
 | |
| EFIAPI
 | |
| InternalHiiBrowserCallback (
 | |
|   IN CONST EFI_GUID    *VariableGuid,  OPTIONAL
 | |
|   IN CONST CHAR16      *VariableName,  OPTIONAL
 | |
|   IN CONST EFI_STRING  SetResultsData  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   UINTN       ResultsDataSize;
 | |
|   EFI_STRING  ResultsData;
 | |
|   CHAR16      TempResultsData;
 | |
| 
 | |
|   //
 | |
|   // Locate protocols
 | |
|   //
 | |
|   if (mUefiFormBrowser2 == NULL) {
 | |
|     Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &mUefiFormBrowser2);
 | |
|     if (EFI_ERROR (Status) || mUefiFormBrowser2 == NULL) {
 | |
|       return NULL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ResultsDataSize = 0;
 | |
| 
 | |
|   if (SetResultsData != NULL) {
 | |
|     //
 | |
|     // Request to to set data in the uncommitted browser state information
 | |
|     //
 | |
|     ResultsData = SetResultsData;
 | |
|   } else {
 | |
|     //
 | |
|     // Retrieve the length of the buffer required ResultsData from the Browser Callback
 | |
|     //
 | |
|     Status = mUefiFormBrowser2->BrowserCallback (
 | |
|                               mUefiFormBrowser2,
 | |
|                               &ResultsDataSize,
 | |
|                               &TempResultsData,
 | |
|                               TRUE,
 | |
|                               VariableGuid,
 | |
|                               VariableName
 | |
|                               );
 | |
|     
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // No Resluts Data, only allocate one char for '\0'
 | |
|       //
 | |
|       ResultsData = AllocateZeroPool (sizeof (CHAR16));
 | |
|       return ResultsData;
 | |
|     }
 | |
| 
 | |
|     if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Allocate the ResultsData buffer
 | |
|     //
 | |
|     ResultsData = AllocateZeroPool (ResultsDataSize);
 | |
|     if (ResultsData == NULL) {
 | |
|       return NULL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve or set the ResultsData from the Browser Callback
 | |
|   //
 | |
|   Status = mUefiFormBrowser2->BrowserCallback (
 | |
|                             mUefiFormBrowser2,
 | |
|                             &ResultsDataSize,
 | |
|                             ResultsData,
 | |
|                             (BOOLEAN)(SetResultsData == NULL),
 | |
|                             VariableGuid,
 | |
|                             VariableName
 | |
|                             );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   return ResultsData;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Allocates and returns a Null-terminated Unicode <ConfigHdr> string using routing 
 | |
|   information that includes a GUID, an optional Unicode string name, and a device
 | |
|   path.  The string returned is allocated with AllocatePool().  The caller is 
 | |
|   responsible for freeing the allocated string with FreePool().
 | |
|   
 | |
|   The format of a <ConfigHdr> is as follows:
 | |
| 
 | |
|     GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize<Null>
 | |
| 
 | |
|   @param[in]  Guid          Pointer to an EFI_GUID that is the routing information
 | |
|                             GUID.  Each of the 16 bytes in Guid is converted to 
 | |
|                             a 2 Unicode character hexidecimal string.  This is 
 | |
|                             an optional parameter that may be NULL.
 | |
|   @param[in]  Name          Pointer to a Null-terminated Unicode string that is 
 | |
|                             the routing information NAME.  This is an optional 
 | |
|                             parameter that may be NULL.  Each 16-bit Unicode 
 | |
|                             character in Name is converted to a 4 character Unicode 
 | |
|                             hexidecimal string.                        
 | |
|   @param[in]  DriverHandle  The driver handle which supports a Device Path Protocol
 | |
|                             that is the routing information PATH.  Each byte of
 | |
|                             the Device Path associated with DriverHandle is converted
 | |
|                             to a 2 Unicode character hexidecimal string.
 | |
| 
 | |
|   @retval NULL   DriverHandle does not support the Device Path Protocol.
 | |
|   @retval Other  A pointer to the Null-terminate Unicode <ConfigHdr> string
 | |
| 
 | |
| **/
 | |
| EFI_STRING
 | |
| EFIAPI
 | |
| HiiConstructConfigHdr (
 | |
|   IN CONST EFI_GUID  *Guid,  OPTIONAL
 | |
|   IN CONST CHAR16    *Name,  OPTIONAL
 | |
|   IN EFI_HANDLE      DriverHandle
 | |
|   )
 | |
| {
 | |
|   UINTN                     NameLength;
 | |
|   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | |
|   UINTN                     DevicePathSize;
 | |
|   CHAR16                    *String;
 | |
|   CHAR16                    *ReturnString;
 | |
|   UINTN                     Index;
 | |
|   UINT8                     *Buffer;
 | |
| 
 | |
|   //
 | |
|   // Compute the length of Name in Unicode characters.  
 | |
|   // If Name is NULL, then the length is 0.
 | |
|   //
 | |
|   NameLength = 0;
 | |
|   if (Name != NULL) {
 | |
|     NameLength = StrLen (Name);
 | |
|   }
 | |
| 
 | |
|   DevicePath = NULL;
 | |
|   DevicePathSize = 0;
 | |
|   //
 | |
|   // Retrieve DevicePath Protocol associated with DriverHandle
 | |
|   //
 | |
|   if (DriverHandle != NULL) {
 | |
|     DevicePath = DevicePathFromHandle (DriverHandle);
 | |
|     if (DevicePath == NULL) {
 | |
|       return NULL;
 | |
|     }
 | |
|     //
 | |
|     // Compute the size of the device path in bytes
 | |
|     //
 | |
|     DevicePathSize = GetDevicePathSize (DevicePath);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // GUID=<HexCh>32&NAME=<Char>NameLength&PATH=<HexChar>DevicePathSize <Null>
 | |
|   // | 5 | sizeof (EFI_GUID) * 2 | 6 | NameStrLen*4 | 6 | DevicePathSize * 2 | 1 |
 | |
|   //
 | |
|   String = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathSize * 2 + 1) * sizeof (CHAR16));
 | |
|   if (String == NULL) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Start with L"GUID="
 | |
|   //
 | |
|   ReturnString = StrCpy (String, L"GUID=");
 | |
|   String += StrLen (String);
 | |
| 
 | |
|   if (Guid != NULL) {
 | |
|     //
 | |
|     // Append Guid converted to <HexCh>32
 | |
|     //
 | |
|     for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {
 | |
|       String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Append L"&NAME="
 | |
|   //
 | |
|   StrCpy (String, L"&NAME=");
 | |
|   String += StrLen (String);
 | |
| 
 | |
|   if (Name != NULL) {
 | |
|     //
 | |
|     // Append Name converted to <Char>NameLength
 | |
|     //
 | |
|     for (; *Name != L'\0'; Name++) {
 | |
|       String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *Name, 4);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Append L"&PATH="
 | |
|   //
 | |
|   StrCpy (String, L"&PATH=");
 | |
|   String += StrLen (String);
 | |
| 
 | |
|   //
 | |
|   // Append the device path associated with DriverHandle converted to <HexChar>DevicePathSize
 | |
|   //
 | |
|   for (Index = 0, Buffer = (UINT8 *)DevicePath; Index < DevicePathSize; Index++) {
 | |
|     String += UnicodeValueToString (String, PREFIX_ZERO | RADIX_HEX, *(Buffer++), 2);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Null terminate the Unicode string
 | |
|   //
 | |
|   *String = L'\0';
 | |
| 
 | |
|   //
 | |
|   // Convert all hex digits in range [A-F] in the configuration header to [a-f]
 | |
|   //
 | |
|   return InternalHiiLowerConfigString (ReturnString);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the hex UNICODE encoding string of UEFI GUID, NAME or device path 
 | |
|   to binary buffer from <ConfigHdr>.
 | |
| 
 | |
|   This is a internal function.
 | |
| 
 | |
|   @param  String                 UEFI configuration string.
 | |
|   @param  Flag                   Flag specifies what type buffer will be retrieved.
 | |
|   @param  Buffer                 Binary of Guid, Name or Device path.
 | |
| 
 | |
|   @retval EFI_INVALID_PARAMETER  Any incoming parameter is invalid.
 | |
|   @retval EFI_OUT_OF_RESOURCES   Lake of resources to store neccesary structures.
 | |
|   @retval EFI_SUCCESS            The buffer data is retrieved and translated to
 | |
|                                  binary format.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| InternalHiiGetBufferFromString (
 | |
|   IN  EFI_STRING                 String,
 | |
|   IN  UINT8                      Flag,
 | |
|   OUT UINT8                      **Buffer
 | |
|   )
 | |
| {
 | |
|   UINTN      Length;
 | |
|   EFI_STRING ConfigHdr;
 | |
|   CHAR16     *StringPtr;
 | |
|   UINT8      *DataBuffer;
 | |
|   CHAR16     TemStr[5];
 | |
|   UINTN      Index;
 | |
|   UINT8      DigitUint8;
 | |
| 
 | |
|   if (String == NULL || Buffer == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   
 | |
|   DataBuffer = NULL;
 | |
|   StringPtr  = NULL;
 | |
|   ConfigHdr  = String;
 | |
|   //
 | |
|   // The content between 'GUID', 'NAME', 'PATH' of <ConfigHdr> and '&' of next element
 | |
|   // or '\0' (end of configuration string) is the UNICODE %02x bytes encoding string.
 | |
|   //
 | |
|   for (Length = 0; *String != 0 && *String != L'&'; String++, Length++);
 | |
| 
 | |
|   switch (Flag) {
 | |
|   case GUID_CONFIG_STRING_TYPE:
 | |
|   case PATH_CONFIG_STRING_TYPE:
 | |
|     //
 | |
|     // The data in <ConfigHdr> is encoded as hex UNICODE %02x bytes in the same order
 | |
|     // as the device path and Guid resides in RAM memory.
 | |
|     // Translate the data into binary.
 | |
|     //
 | |
|     DataBuffer = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
 | |
|     if (DataBuffer == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     //
 | |
|     // Convert binary byte one by one
 | |
|     //
 | |
|     ZeroMem (TemStr, sizeof (TemStr));
 | |
|     for (Index = 0; Index < Length; Index ++) {
 | |
|       TemStr[0] = ConfigHdr[Index];
 | |
|       DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
 | |
|       if ((Index & 1) == 0) {
 | |
|         DataBuffer [Index/2] = DigitUint8;
 | |
|       } else {
 | |
|         DataBuffer [Index/2] = (UINT8) ((DataBuffer [Index/2] << 4) + DigitUint8);
 | |
|       }
 | |
|     }
 | |
|     
 | |
|     *Buffer = DataBuffer;
 | |
|     break;
 | |
| 
 | |
|   case NAME_CONFIG_STRING_TYPE:
 | |
|     //
 | |
|     // Convert Config String to Unicode String, e.g. "0041004200430044" => "ABCD"
 | |
|     // 
 | |
| 
 | |
|     //
 | |
|     // Add the tailling char L'\0'
 | |
|     //
 | |
|     DataBuffer = (UINT8 *) AllocateZeroPool ((Length/4 + 1) * sizeof (CHAR16));
 | |
|     if (DataBuffer == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     //
 | |
|     // Convert character one by one
 | |
|     //
 | |
|     StringPtr = (CHAR16 *) DataBuffer;
 | |
|     ZeroMem (TemStr, sizeof (TemStr));
 | |
|     for (Index = 0; Index < Length; Index += 4) {
 | |
|       StrnCpy (TemStr, ConfigHdr + Index, 4);
 | |
|       StringPtr[Index/4] = (CHAR16) StrHexToUint64 (TemStr);
 | |
|     }
 | |
|     //
 | |
|     // Add tailing L'\0' character
 | |
|     //
 | |
|     StringPtr[Index/4] = L'\0';
 | |
| 
 | |
|     *Buffer = DataBuffer;
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function checks VarOffset and VarWidth is in the block range.
 | |
| 
 | |
|   @param  BlockArray         The block array is to be checked. 
 | |
|   @param  VarOffset          Offset of var to the structure
 | |
|   @param  VarWidth           Width of var.
 | |
|   
 | |
|   @retval TRUE   This Var is in the block range.
 | |
|   @retval FALSE  This Var is not in the block range.
 | |
| **/
 | |
| BOOLEAN
 | |
| BlockArrayCheck (
 | |
|   IN IFR_BLOCK_DATA  *BlockArray,
 | |
|   IN UINT16          VarOffset,
 | |
|   IN UINT16          VarWidth
 | |
|   )
 | |
| {
 | |
|   LIST_ENTRY          *Link;
 | |
|   IFR_BLOCK_DATA      *BlockData;
 | |
|   
 | |
|   //
 | |
|   // No Request Block array, all vars are got.
 | |
|   //
 | |
|   if (BlockArray == NULL) {
 | |
|     return TRUE;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Check the input var is in the request block range.
 | |
|   //
 | |
|   for (Link = BlockArray->Entry.ForwardLink; Link != &BlockArray->Entry; Link = Link->ForwardLink) {
 | |
|     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
 | |
|     if ((VarOffset >= BlockData->Offset) && ((VarOffset + VarWidth) <= (BlockData->Offset + BlockData->Width))) {
 | |
|       return TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the value of <Number> in <BlockConfig> format, i.e. the value of OFFSET
 | |
|   or WIDTH or VALUE.
 | |
|   <BlockConfig> ::= 'OFFSET='<Number>&'WIDTH='<Number>&'VALUE'=<Number>
 | |
| 
 | |
|   @param  ValueString            String in <BlockConfig> format and points to the
 | |
|                                  first character of <Number>.
 | |
|   @param  ValueData              The output value. Caller takes the responsibility
 | |
|                                  to free memory.
 | |
|   @param  ValueLength            Length of the <Number>, in characters.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES   Insufficient resources to store neccessary
 | |
|                                  structures.
 | |
|   @retval EFI_SUCCESS            Value of <Number> is outputted in Number
 | |
|                                  successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InternalHiiGetValueOfNumber (
 | |
|   IN  EFI_STRING           ValueString,
 | |
|   OUT UINT8                **ValueData,
 | |
|   OUT UINTN                *ValueLength
 | |
|   )
 | |
| {
 | |
|   EFI_STRING               StringPtr;
 | |
|   UINTN                    Length;
 | |
|   UINT8                    *Buf;
 | |
|   UINT8                    DigitUint8;
 | |
|   UINTN                    Index;
 | |
|   CHAR16                   TemStr[2];
 | |
| 
 | |
|   ASSERT (ValueString != NULL && ValueData != NULL && ValueLength != NULL);
 | |
|   ASSERT (*ValueString != L'\0');
 | |
| 
 | |
|   //
 | |
|   // Get the length of value string
 | |
|   //
 | |
|   StringPtr = ValueString;
 | |
|   while (*StringPtr != L'\0' && *StringPtr != L'&') {
 | |
|     StringPtr++;
 | |
|   }
 | |
|   Length = StringPtr - ValueString;
 | |
|   
 | |
|   //
 | |
|   // Allocate buffer to store the value
 | |
|   //
 | |
|   Buf = (UINT8 *) AllocateZeroPool ((Length + 1) / 2);
 | |
|   if (Buf == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Convert character one by one to the value buffer
 | |
|   //
 | |
|   ZeroMem (TemStr, sizeof (TemStr));
 | |
|   for (Index = 0; Index < Length; Index ++) {
 | |
|     TemStr[0] = ValueString[Length - Index - 1];
 | |
|     DigitUint8 = (UINT8) StrHexToUint64 (TemStr);
 | |
|     if ((Index & 1) == 0) {
 | |
|       Buf [Index/2] = DigitUint8;
 | |
|     } else {
 | |
|       Buf [Index/2] = (UINT8) ((DigitUint8 << 4) + Buf [Index/2]);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Set the converted value and string length.
 | |
|   //
 | |
|   *ValueData    = Buf;
 | |
|   *ValueLength  = Length;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This internal function parses IFR data to validate current setting.
 | |
| 
 | |
|   @param ConfigResp         ConfigResp string contains the current setting.
 | |
|   @param HiiPackageList     Point to Hii package list.
 | |
|   @param PackageListLength  The length of the pacakge.
 | |
|   @param VarGuid            Guid of the buffer storage.
 | |
|   @param VarName            Name of the buffer storage.
 | |
|   
 | |
|   @retval EFI_SUCCESS            The current setting is valid.
 | |
|   @retval EFI_OUT_OF_RESOURCES   The memory is not enough.
 | |
|   @retval EFI_INVALID_PARAMETER  The config string or the Hii package is invalid.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InternalHiiValidateCurrentSetting (
 | |
|   IN EFI_STRING                    ConfigResp,
 | |
|   IN EFI_HII_PACKAGE_LIST_HEADER   *HiiPackageList,
 | |
|   IN UINTN                         PackageListLength,
 | |
|   IN EFI_GUID                      *VarGuid,
 | |
|   IN CHAR16                        *VarName
 | |
|   )
 | |
| { 
 | |
|   IFR_BLOCK_DATA               *CurrentBlockArray;
 | |
|   IFR_BLOCK_DATA               *BlockData;
 | |
|   IFR_BLOCK_DATA               *NewBlockData;
 | |
|   IFR_BLOCK_DATA               VarBlockData;
 | |
|   EFI_STRING                   StringPtr;
 | |
|   UINTN                        Length;
 | |
|   UINT8                        *TmpBuffer;
 | |
|   UINT16                       Offset;
 | |
|   UINT16                       Width;
 | |
|   UINT64                       VarValue;
 | |
|   LIST_ENTRY                   *Link;
 | |
|   UINT8                        *VarBuffer;
 | |
|   UINTN                        MaxBufferSize;
 | |
|   EFI_STATUS                   Status;
 | |
|   EFI_HII_PACKAGE_HEADER       PacakgeHeader;
 | |
|   UINT32                       PackageOffset;
 | |
|   UINT8                        *PackageData;
 | |
|   UINTN                        IfrOffset;
 | |
|   EFI_IFR_OP_HEADER            *IfrOpHdr;
 | |
|   EFI_IFR_VARSTORE             *IfrVarStore;
 | |
|   EFI_IFR_ONE_OF               *IfrOneOf;
 | |
|   EFI_IFR_NUMERIC              *IfrNumeric;
 | |
|   EFI_IFR_ONE_OF_OPTION        *IfrOneOfOption;
 | |
|   EFI_IFR_CHECKBOX             *IfrCheckBox;
 | |
|   EFI_IFR_STRING               *IfrString;
 | |
|   CHAR8                        *VarStoreName;
 | |
|   UINTN                        Index;
 | |
|   
 | |
|   //
 | |
|   // 1. Get the current setting to current block data array and Convert them into VarBuffer
 | |
|   //
 | |
| 
 | |
|   //
 | |
|   // Skip ConfigHdr string
 | |
|   //
 | |
|   StringPtr = ConfigResp;
 | |
|   StringPtr = StrStr (ConfigResp, L"&OFFSET");
 | |
|   if (StringPtr == NULL) {
 | |
|     //
 | |
|     // No ConfigBlock value is requied to be validated.
 | |
|     // EFI_SUCCESS directly return.
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|    
 | |
|   //
 | |
|   // Initialize the local variables.
 | |
|   //
 | |
|   Index         = 0;
 | |
|   VarStoreName  = NULL;
 | |
|   Status        = EFI_SUCCESS;
 | |
|   BlockData     = NULL;
 | |
|   NewBlockData  = NULL;
 | |
|   TmpBuffer     = NULL;
 | |
|   MaxBufferSize = HII_LIB_DEFAULT_VARSTORE_SIZE;
 | |
|   VarBuffer     = AllocateZeroPool (MaxBufferSize);
 | |
|   if (VarBuffer == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Init CurrentBlockArray
 | |
|   //
 | |
|   CurrentBlockArray = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
 | |
|   if (CurrentBlockArray == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
|   InitializeListHead (&CurrentBlockArray->Entry);
 | |
|   
 | |
|   //
 | |
|   // Parse each <RequestElement> if exists
 | |
|   // Only <BlockName> format is supported by this help function.
 | |
|   // <BlockName> ::= &'OFFSET='<Number>&'WIDTH='<Number>
 | |
|   //
 | |
|   while (*StringPtr != 0 && StrnCmp (StringPtr, L"&OFFSET=", StrLen (L"&OFFSET=")) == 0) {
 | |
|     //
 | |
|     // Skip the &OFFSET= string
 | |
|     // 
 | |
|     StringPtr += StrLen (L"&OFFSET=");
 | |
| 
 | |
|     //
 | |
|     // Get Offset
 | |
|     //
 | |
|     Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
|     Offset = 0;
 | |
|     CopyMem (
 | |
|       &Offset,
 | |
|       TmpBuffer,
 | |
|       (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
 | |
|       );
 | |
|     FreePool (TmpBuffer);
 | |
|     TmpBuffer = NULL;
 | |
| 
 | |
|     StringPtr += Length;
 | |
|     if (StrnCmp (StringPtr, L"&WIDTH=", StrLen (L"&WIDTH=")) != 0) {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
|     StringPtr += StrLen (L"&WIDTH=");
 | |
| 
 | |
|     //
 | |
|     // Get Width
 | |
|     //
 | |
|     Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
|     Width = 0;
 | |
|     CopyMem (
 | |
|       &Width,
 | |
|       TmpBuffer,
 | |
|       (((Length + 1) / 2) < sizeof (UINT16)) ? ((Length + 1) / 2) : sizeof (UINT16)
 | |
|       );
 | |
|     FreePool (TmpBuffer);
 | |
|     TmpBuffer = NULL;
 | |
| 
 | |
|     StringPtr += Length;
 | |
|     if (*StringPtr != 0 && *StringPtr != L'&') {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (StrnCmp (StringPtr, L"&VALUE=", StrLen (L"&VALUE=")) != 0) {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
|     StringPtr += StrLen (L"&VALUE=");
 | |
| 
 | |
|     //
 | |
|     // Get Value
 | |
|     //
 | |
|     Status = InternalHiiGetValueOfNumber (StringPtr, &TmpBuffer, &Length);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StringPtr += Length;
 | |
|     if (*StringPtr != 0 && *StringPtr != L'&') {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Check whether VarBuffer is enough
 | |
|     //
 | |
|     if ((UINTN) (Offset + Width) > MaxBufferSize) {
 | |
|       VarBuffer = ReallocatePool (
 | |
|                     MaxBufferSize,
 | |
|                     Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE,
 | |
|                     VarBuffer
 | |
|                     );
 | |
|       if (VarBuffer == NULL) {
 | |
|         Status = EFI_OUT_OF_RESOURCES;
 | |
|         goto Done;
 | |
|       }
 | |
|       MaxBufferSize = Offset + Width + HII_LIB_DEFAULT_VARSTORE_SIZE;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Update the Block with configuration info
 | |
|     //
 | |
|     CopyMem (VarBuffer + Offset, TmpBuffer, Width);
 | |
|     FreePool (TmpBuffer);
 | |
|     TmpBuffer = NULL;
 | |
| 
 | |
|     //
 | |
|     // Set new Block Data
 | |
|     //
 | |
|     NewBlockData = (IFR_BLOCK_DATA *) AllocateZeroPool (sizeof (IFR_BLOCK_DATA));
 | |
|     if (NewBlockData == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
|     NewBlockData->Offset = Offset;
 | |
|     NewBlockData->Width  = Width;
 | |
| 
 | |
|     //
 | |
|     // Insert the new block data into the block data array.
 | |
|     //
 | |
|     for (Link = CurrentBlockArray->Entry.ForwardLink; Link != &CurrentBlockArray->Entry; Link = Link->ForwardLink) {
 | |
|       BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
 | |
|       if (NewBlockData->Offset == BlockData->Offset) {
 | |
|         if (NewBlockData->Width > BlockData->Width) {
 | |
|           BlockData->Width = NewBlockData->Width;
 | |
|         }
 | |
|         FreePool (NewBlockData);
 | |
|         break;
 | |
|       } else if (NewBlockData->Offset < BlockData->Offset) {
 | |
|         //
 | |
|         // Insert new block data as the previous one of this link.
 | |
|         //
 | |
|         InsertTailList (Link, &NewBlockData->Entry);
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Insert new block data into the array tail.
 | |
|     //
 | |
|     if (Link == &CurrentBlockArray->Entry) {
 | |
|       InsertTailList (Link, &NewBlockData->Entry);
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // If '\0', parsing is finished. 
 | |
|     //
 | |
|     if (*StringPtr == 0) {
 | |
|       break;
 | |
|     }
 | |
|     //
 | |
|     // Go to next ConfigBlock 
 | |
|     //
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Merge the aligned block data into the single block data.
 | |
|   //
 | |
|   Link = CurrentBlockArray->Entry.ForwardLink;
 | |
|   while ((Link != &CurrentBlockArray->Entry) && (Link->ForwardLink != &CurrentBlockArray->Entry)) {
 | |
|     BlockData = BASE_CR (Link, IFR_BLOCK_DATA, Entry);
 | |
|     NewBlockData = BASE_CR (Link->ForwardLink, IFR_BLOCK_DATA, Entry);
 | |
|     if ((NewBlockData->Offset >= BlockData->Offset) && (NewBlockData->Offset <= (BlockData->Offset + BlockData->Width))) {
 | |
|       if ((NewBlockData->Offset + NewBlockData->Width) > (BlockData->Offset + BlockData->Width)) {
 | |
|         BlockData->Width = (UINT16) (NewBlockData->Offset + NewBlockData->Width - BlockData->Offset);
 | |
|       }
 | |
|       RemoveEntryList (Link->ForwardLink);
 | |
|       FreePool (NewBlockData);
 | |
|       continue;
 | |
|     }
 | |
|     Link = Link->ForwardLink;      
 | |
|   }
 | |
|   
 | |
|   if (IsListEmpty (&CurrentBlockArray->Entry)) {
 | |
|     Status = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // 2. Check IFR value is in block data, then Validate Vaule
 | |
|   //
 | |
|   ZeroMem (&VarBlockData, sizeof (VarBlockData));
 | |
|   VarValue      = 0;
 | |
|   IfrVarStore   = NULL;
 | |
|   PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
 | |
|   while (PackageOffset < PackageListLength) {
 | |
|     CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));
 | |
|     
 | |
|     //
 | |
|     // Parse IFR opcode from the form package.
 | |
|     //
 | |
|     if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {
 | |
|       IfrOffset   = sizeof (PacakgeHeader);
 | |
|       PackageData = (UINT8 *) HiiPackageList + PackageOffset;
 | |
|       while (IfrOffset < PacakgeHeader.Length) {
 | |
|         IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);
 | |
|         //
 | |
|         // Validate current setting to the value built in IFR opcode
 | |
|         //
 | |
|         switch (IfrOpHdr->OpCode) {
 | |
|         case EFI_IFR_VARSTORE_OP:          
 | |
|           //
 | |
|           // VarStoreId has been found. No further found.
 | |
|           //
 | |
|           if (IfrVarStore != NULL) {
 | |
|             break;
 | |
|           }
 | |
|           //
 | |
|           // Find the matched VarStoreId to the input VarGuid and VarName
 | |
|           //
 | |
|           IfrVarStore = (EFI_IFR_VARSTORE *) IfrOpHdr;
 | |
|           if (CompareGuid ((EFI_GUID *) (VOID *) &IfrVarStore->Guid, VarGuid)) {
 | |
|             VarStoreName = (CHAR8 *) IfrVarStore->Name;
 | |
|             for (Index = 0; VarStoreName[Index] != 0; Index ++) {
 | |
|               if ((CHAR16) VarStoreName[Index] != VarName[Index]) {
 | |
|                 break;
 | |
|               }
 | |
|             }
 | |
|             //
 | |
|             // The matched VarStore is found.
 | |
|             //
 | |
|             if ((VarStoreName[Index] != 0) || (VarName[Index] != 0)) {
 | |
|               IfrVarStore = NULL;
 | |
|             }
 | |
|           } else {
 | |
|             IfrVarStore = NULL;
 | |
|           }
 | |
|           break;
 | |
|         case EFI_IFR_FORM_OP:
 | |
|           //
 | |
|           // Check the matched VarStoreId is found.
 | |
|           //
 | |
|           if (IfrVarStore == NULL) {
 | |
|             Status = EFI_SUCCESS;
 | |
|             goto Done;
 | |
|           }
 | |
|           break;
 | |
|         case EFI_IFR_ONE_OF_OP:
 | |
|           //
 | |
|           // Check whether current value is the one of option.
 | |
|           //
 | |
| 
 | |
|           //
 | |
|           // OneOf question is not in IFR Form. This IFR form is not valid. 
 | |
|           //
 | |
|           if (IfrVarStore == NULL) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
|           // 
 | |
|           // Check whether this question is for the requested varstore.
 | |
|           //
 | |
|           IfrOneOf = (EFI_IFR_ONE_OF *) IfrOpHdr;
 | |
|           if (IfrOneOf->Question.VarStoreId != IfrVarStore->VarStoreId) {
 | |
|             break;
 | |
|           }
 | |
|           
 | |
|           //
 | |
|           // Get Offset by Question header and Width by DataType Flags
 | |
|           //
 | |
|           Offset = IfrOneOf->Question.VarStoreInfo.VarOffset;
 | |
|           Width  = (UINT16) (1 << (IfrOneOf->Flags & EFI_IFR_NUMERIC_SIZE));
 | |
|           //
 | |
|           // Check whether this question is in current block array.
 | |
|           //
 | |
|           if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
 | |
|             //
 | |
|             // This question is not in the current configuration string. Skip it.
 | |
|             //
 | |
|             break;
 | |
|           }
 | |
|           //
 | |
|           // Check this var question is in the var storage 
 | |
|           //
 | |
|           if ((Offset + Width) > IfrVarStore->Size) {
 | |
|             //
 | |
|             // This question exceeds the var store size. 
 | |
|             //
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Get the current value for oneof opcode
 | |
|           //
 | |
|           VarValue = 0;
 | |
|           CopyMem (&VarValue, VarBuffer +  Offset, Width);
 | |
|           //
 | |
|           // Set Block Data, to be checked in the following Oneof option opcode.
 | |
|           //
 | |
|           VarBlockData.Offset     = Offset;
 | |
|           VarBlockData.Width      = Width;
 | |
|           VarBlockData.OpCode     = IfrOpHdr->OpCode;
 | |
|           VarBlockData.Scope      = IfrOpHdr->Scope;
 | |
|           break;
 | |
|         case EFI_IFR_NUMERIC_OP:
 | |
|           //
 | |
|           // Check the current value is in the numeric range.
 | |
|           //
 | |
| 
 | |
|           //
 | |
|           // Numeric question is not in IFR Form. This IFR form is not valid. 
 | |
|           //
 | |
|           if (IfrVarStore == NULL) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
|           //
 | |
|           // Check whether this question is for the requested varstore.
 | |
|           //
 | |
|           IfrNumeric = (EFI_IFR_NUMERIC *) IfrOpHdr;
 | |
|           if (IfrNumeric->Question.VarStoreId != IfrVarStore->VarStoreId) {
 | |
|             break;
 | |
|           }
 | |
|           
 | |
|           //
 | |
|           // Get Offset by Question header and Width by DataType Flags
 | |
|           //
 | |
|           Offset = IfrNumeric->Question.VarStoreInfo.VarOffset;
 | |
|           Width  = (UINT16) (1 << (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE));
 | |
|           //
 | |
|           // Check whether this question is in current block array.
 | |
|           //
 | |
|           if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
 | |
|             //
 | |
|             // This question is not in the current configuration string. Skip it.
 | |
|             //
 | |
|             break;
 | |
|           }
 | |
|           //
 | |
|           // Check this var question is in the var storage 
 | |
|           //
 | |
|           if ((Offset + Width) > IfrVarStore->Size) {
 | |
|             //
 | |
|             // This question exceeds the var store size. 
 | |
|             //
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Check the current value is in the numeric range.
 | |
|           //
 | |
|           VarValue = 0;
 | |
|           CopyMem (&VarValue, VarBuffer +  Offset, Width);
 | |
|           switch (IfrNumeric->Flags & EFI_IFR_NUMERIC_SIZE) {
 | |
|           case EFI_IFR_NUMERIC_SIZE_1:
 | |
|             if ((UINT8) VarValue < IfrNumeric->data.u8.MinValue || (UINT8) VarValue > IfrNumeric->data.u8.MaxValue) {
 | |
|               //
 | |
|               // Not in the valid range.
 | |
|               //
 | |
|               Status = EFI_INVALID_PARAMETER;
 | |
|               goto Done;
 | |
|             }
 | |
|             break;
 | |
|           case EFI_IFR_NUMERIC_SIZE_2:
 | |
|             if ((UINT16) VarValue < IfrNumeric->data.u16.MinValue || (UINT16) VarValue > IfrNumeric->data.u16.MaxValue) {
 | |
|               //
 | |
|               // Not in the valid range.
 | |
|               //
 | |
|               Status = EFI_INVALID_PARAMETER;
 | |
|               goto Done;
 | |
|             }
 | |
|             break;
 | |
|           case EFI_IFR_NUMERIC_SIZE_4:
 | |
|             if ((UINT32) VarValue < IfrNumeric->data.u32.MinValue || (UINT32) VarValue > IfrNumeric->data.u32.MaxValue) {
 | |
|               //
 | |
|               // Not in the valid range.
 | |
|               //
 | |
|               Status = EFI_INVALID_PARAMETER;
 | |
|               goto Done;
 | |
|             }
 | |
|             break;
 | |
|           case EFI_IFR_NUMERIC_SIZE_8:
 | |
|             if ((UINT64) VarValue < IfrNumeric->data.u64.MinValue || (UINT64) VarValue > IfrNumeric->data.u64.MaxValue) {
 | |
|               //
 | |
|               // Not in the valid range.
 | |
|               //
 | |
|               Status = EFI_INVALID_PARAMETER;
 | |
|               goto Done;
 | |
|             }
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         case EFI_IFR_CHECKBOX_OP:
 | |
|           //
 | |
|           // Check value is BOOLEAN type, only 0 and 1 is valid.
 | |
|           //
 | |
| 
 | |
|           //
 | |
|           // CheckBox question is not in IFR Form. This IFR form is not valid. 
 | |
|           //
 | |
|           if (IfrVarStore == NULL) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Check whether this question is for the requested varstore.
 | |
|           //
 | |
|           IfrCheckBox = (EFI_IFR_CHECKBOX *) IfrOpHdr;
 | |
|           if (IfrCheckBox->Question.VarStoreId != IfrVarStore->VarStoreId) {
 | |
|             break;
 | |
|           }
 | |
|           
 | |
|           //
 | |
|           // Get Offset by Question header
 | |
|           //
 | |
|           Offset = IfrCheckBox->Question.VarStoreInfo.VarOffset;
 | |
|           Width  = sizeof (BOOLEAN);
 | |
|           //
 | |
|           // Check whether this question is in current block array.
 | |
|           //
 | |
|           if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
 | |
|             //
 | |
|             // This question is not in the current configuration string. Skip it.
 | |
|             //
 | |
|             break;
 | |
|           }
 | |
|           //
 | |
|           // Check this var question is in the var storage 
 | |
|           //
 | |
|           if ((Offset + Width) > IfrVarStore->Size) {
 | |
|             //
 | |
|             // This question exceeds the var store size. 
 | |
|             //
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Boolean type, only 1 and 0 is valid.
 | |
|           //
 | |
|           if (*(VarBuffer + Offset) > 1) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;            
 | |
|           }
 | |
|           
 | |
|           break;
 | |
|         case EFI_IFR_STRING_OP:
 | |
|           //
 | |
|           // Check current string length is less than maxsize
 | |
|           //
 | |
| 
 | |
|           //
 | |
|           // CheckBox question is not in IFR Form. This IFR form is not valid. 
 | |
|           //
 | |
|           if (IfrVarStore == NULL) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Check whether this question is for the requested varstore.
 | |
|           //
 | |
|           IfrString = (EFI_IFR_STRING *) IfrOpHdr;
 | |
|           if (IfrString->Question.VarStoreId != IfrVarStore->VarStoreId) {
 | |
|             break;
 | |
|           }
 | |
|           
 | |
|           //
 | |
|           // Get Offset/Width by Question header and OneOf Flags
 | |
|           //
 | |
|           Offset = IfrString->Question.VarStoreInfo.VarOffset;
 | |
|           Width  = (UINT16) (IfrString->MaxSize * sizeof (UINT16));
 | |
|           //
 | |
|           // Check whether this question is in current block array.
 | |
|           //
 | |
|           if (!BlockArrayCheck (CurrentBlockArray, Offset, Width)) {
 | |
|             //
 | |
|             // This question is not in the current configuration string. Skip it.
 | |
|             //
 | |
|             break;
 | |
|           }
 | |
|           //
 | |
|           // Check this var question is in the var storage 
 | |
|           //
 | |
|           if ((Offset + Width) > IfrVarStore->Size) {
 | |
|             //
 | |
|             // This question exceeds the var store size. 
 | |
|             //
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
|           
 | |
|           //
 | |
|           // Check current string length is less than maxsize
 | |
|           //
 | |
|           if (StrSize ((CHAR16 *) (VarBuffer + Offset)) > Width) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;            
 | |
|           }
 | |
|           break;
 | |
|         case EFI_IFR_ONE_OF_OPTION_OP:
 | |
|           //
 | |
|           // Opcode Scope is zero. This one of option is not to be checked. 
 | |
|           //
 | |
|           if (VarBlockData.Scope == 0) {
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // Only check for OneOf and OrderList opcode
 | |
|           //
 | |
|           IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) IfrOpHdr;
 | |
|           if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {
 | |
|             //
 | |
|             // Check current value is the value of one of option.
 | |
|             //
 | |
|             if (VarValue == IfrOneOfOption->Value.u64) {
 | |
|               //
 | |
|               // The value is one of option value.
 | |
|               // Set OpCode to Zero, don't need check again.
 | |
|               //
 | |
|               VarBlockData.OpCode = 0;
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         case EFI_IFR_END_OP:
 | |
|           //
 | |
|           // Decrease opcode scope for the validated opcode
 | |
|           //
 | |
|           if (VarBlockData.Scope > 0) {
 | |
|             VarBlockData.Scope --;
 | |
|           }
 | |
| 
 | |
|           //
 | |
|           // OneOf value doesn't belong to one of option value. 
 | |
|           //
 | |
|           if (VarBlockData.OpCode == EFI_IFR_ONE_OF_OP) {
 | |
|             Status = EFI_INVALID_PARAMETER;
 | |
|             goto Done;
 | |
|           }
 | |
|           break;
 | |
|         default:
 | |
|           //
 | |
|           // Increase Scope for the validated opcode
 | |
|           //
 | |
|           if (VarBlockData.Scope > 0) {
 | |
|             VarBlockData.Scope = (UINT8) (VarBlockData.Scope + IfrOpHdr->Scope);
 | |
|           }
 | |
|           break;
 | |
|         }
 | |
|         //
 | |
|         // Go to the next opcode
 | |
|         //
 | |
|         IfrOffset += IfrOpHdr->Length;
 | |
|       }
 | |
|       //
 | |
|       // Only one form is in a package list.
 | |
|       //
 | |
|       break;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // Go to next package.
 | |
|     //
 | |
|     PackageOffset += PacakgeHeader.Length;      
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (VarBuffer != NULL) {
 | |
|     FreePool (VarBuffer);
 | |
|   }
 | |
|   
 | |
|   if (CurrentBlockArray != NULL) {
 | |
|     //
 | |
|     // Free Link Array CurrentBlockArray
 | |
|     //
 | |
|     while (!IsListEmpty (&CurrentBlockArray->Entry)) {
 | |
|       BlockData = BASE_CR (CurrentBlockArray->Entry.ForwardLink, IFR_BLOCK_DATA, Entry);
 | |
|       RemoveEntryList (&BlockData->Entry);
 | |
|       FreePool (BlockData);
 | |
|     }
 | |
|     FreePool (CurrentBlockArray);    
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function parses the input ConfigRequest string and its matched IFR code
 | |
|   string for setting default value and validating current setting.
 | |
| 
 | |
|   1. For setting default action, Reset the default value specified by DefaultId 
 | |
|   to the driver configuration got by Request string.
 | |
|   2. For validating current setting, Validate the current configuration 
 | |
|   by parsing HII form IFR opcode.
 | |
| 
 | |
|   NULL request string support depends on the ExportConfig interface of
 | |
|   HiiConfigRouting protocol in UEFI specification.
 | |
|   
 | |
|   @param Request    A null-terminated Unicode string in 
 | |
|                     <MultiConfigRequest> format. It can be NULL.
 | |
|                     If it is NULL, all current configuration for the
 | |
|                     entirety of the current HII database will be validated.
 | |
|                     If it is NULL, all configuration for the
 | |
|                     entirety of the current HII database will be reset.
 | |
|   @param DefaultId  Specifies the type of defaults to retrieve only for setting default action.
 | |
|   @param ActionType Action supports setting defaults and validate current setting.
 | |
|   
 | |
|   @retval TURE    Action runs successfully.
 | |
|   @retval FALSE   Action is not valid or Action can't be executed successfully..
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| InternalHiiIfrValueAction (
 | |
|   IN CONST EFI_STRING Request,  OPTIONAL
 | |
|   IN UINT16           DefaultId,
 | |
|   IN UINT8            ActionType
 | |
|   )
 | |
| {
 | |
|   EFI_STRING     ConfigAltResp;
 | |
|   EFI_STRING     ConfigAltHdr;
 | |
|   EFI_STRING     ConfigResp;
 | |
|   EFI_STRING     Progress;
 | |
|   EFI_STRING     StringPtr;
 | |
|   EFI_STRING     StringHdr;
 | |
|   EFI_STATUS     Status;
 | |
|   EFI_HANDLE     DriverHandle;
 | |
|   EFI_HANDLE     TempDriverHandle;
 | |
|   EFI_HII_HANDLE *HiiHandleBuffer;
 | |
|   EFI_HII_HANDLE HiiHandle;
 | |
|   UINT32         Index;
 | |
|   EFI_GUID       *VarGuid;
 | |
|   EFI_STRING     VarName;
 | |
|   EFI_STRING_ID  DefaultName;
 | |
| 
 | |
|   UINT8                        *PackageData;
 | |
|   UINTN                        IfrOffset;
 | |
|   EFI_IFR_OP_HEADER            *IfrOpHdr;
 | |
|   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
 | |
|   UINT32                       PackageOffset;  
 | |
|   UINTN                        PackageListLength;
 | |
|   EFI_HII_PACKAGE_HEADER       PacakgeHeader;
 | |
|   EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
 | |
|   EFI_DEVICE_PATH_PROTOCOL     *TempDevicePath;
 | |
|   
 | |
|   ConfigAltResp = NULL;
 | |
|   ConfigResp    = NULL;
 | |
|   VarGuid       = NULL;
 | |
|   VarName       = NULL;
 | |
|   DevicePath    = NULL;
 | |
|   ConfigAltHdr  = NULL;
 | |
|   HiiHandleBuffer  = NULL;
 | |
|   Index            = 0;
 | |
|   TempDriverHandle = NULL;
 | |
|   HiiHandle        = NULL;
 | |
|   PackageData      = NULL;
 | |
|   HiiPackageList   = NULL;
 | |
|   
 | |
|   //
 | |
|   // Only support set default and validate setting action.
 | |
|   //
 | |
|   if ((ActionType != ACTION_SET_DEFAUTL_VALUE) && (ActionType != ACTION_VALIDATE_SETTING)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get the full requested value and deault value string.
 | |
|   //
 | |
|   if (Request != NULL) {
 | |
|     Status = gHiiConfigRouting->ExtractConfig (
 | |
|                                   gHiiConfigRouting,
 | |
|                                   Request,
 | |
|                                   &Progress,
 | |
|                                   &ConfigAltResp
 | |
|                                 );
 | |
|   } else {
 | |
|     Status = gHiiConfigRouting->ExportConfig (
 | |
|                                   gHiiConfigRouting,
 | |
|                                   &ConfigAltResp
 | |
|                                 );
 | |
|   }
 | |
|   
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return FALSE;
 | |
|   }
 | |
|   
 | |
|   StringPtr = ConfigAltResp;
 | |
|   
 | |
|   while (StringPtr != L'\0') {
 | |
|     //
 | |
|     // 1. Find <ConfigHdr> GUID=...&NAME=...&PATH=...
 | |
|     //
 | |
|     StringHdr = StringPtr;
 | |
| 
 | |
|     //
 | |
|     // Get Guid value
 | |
|     //
 | |
|     if (StrnCmp (StringPtr, L"GUID=", StrLen (L"GUID=")) != 0) {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
|     StringPtr += StrLen (L"GUID=");
 | |
|     Status = InternalHiiGetBufferFromString (StringPtr, GUID_CONFIG_STRING_TYPE, (UINT8 **) &VarGuid);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Get Name value VarName
 | |
|     //
 | |
|     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&NAME=", StrLen (L"&NAME=")) != 0) {
 | |
|       StringPtr++;
 | |
|     }
 | |
|     if (*StringPtr == L'\0') {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
|     StringPtr += StrLen (L"&NAME=");
 | |
|     Status = InternalHiiGetBufferFromString (StringPtr, NAME_CONFIG_STRING_TYPE, (UINT8 **) &VarName);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // Get Path value DevicePath
 | |
|     //
 | |
|     while (*StringPtr != L'\0' && StrnCmp (StringPtr, L"&PATH=", StrLen (L"&PATH=")) != 0) {
 | |
|       StringPtr++;
 | |
|     }
 | |
|     if (*StringPtr == L'\0') {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
|     StringPtr += StrLen (L"&PATH=");
 | |
|     Status = InternalHiiGetBufferFromString (StringPtr, PATH_CONFIG_STRING_TYPE, (UINT8 **) &DevicePath);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Get the Driver handle by the got device path.
 | |
|     //
 | |
|     TempDevicePath = DevicePath;
 | |
|     Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDevicePath, &DriverHandle);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // Find the matched Hii Handle for the found Driver handle
 | |
|     //
 | |
|     HiiHandleBuffer = HiiGetHiiHandles (NULL);
 | |
|     if (HiiHandleBuffer == NULL) {
 | |
|       Status = EFI_NOT_FOUND;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     for (Index = 0; HiiHandleBuffer[Index] != NULL; Index ++) {
 | |
|       gHiiDatabase->GetPackageListHandle (gHiiDatabase, HiiHandleBuffer[Index], &TempDriverHandle);
 | |
|       if (TempDriverHandle == DriverHandle) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     HiiHandle = HiiHandleBuffer[Index];
 | |
|     FreePool (HiiHandleBuffer);
 | |
| 
 | |
|     if (HiiHandle == NULL) {
 | |
|       //
 | |
|       // This request string has no its Hii package.
 | |
|       // Its default value and validating can't execute by parsing IFR data.
 | |
|       // Directly jump into the next ConfigAltResp string for another pair Guid, Name, and Path.   
 | |
|       //
 | |
| 	  Status = EFI_SUCCESS;
 | |
|       goto NextConfigAltResp;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // 2. Get DefaultName string ID by parsing the PacakgeList 
 | |
|     //
 | |
| 
 | |
|     //
 | |
|     // Get HiiPackage by HiiHandle
 | |
|     //
 | |
|     PackageListLength  = 0;
 | |
|     HiiPackageList     = NULL;
 | |
|     Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);
 | |
|   
 | |
|     //
 | |
|     // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
 | |
|     //
 | |
|     if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
|   
 | |
|     HiiPackageList = AllocatePool (PackageListLength);
 | |
|     if (HiiPackageList == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
|   
 | |
|     //
 | |
|     // Get PackageList on HiiHandle
 | |
|     //
 | |
|     Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &PackageListLength, HiiPackageList);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // Parse the form package and get the default name string ID.
 | |
|     //
 | |
|     if (ActionType == ACTION_SET_DEFAUTL_VALUE) {
 | |
|       PackageOffset = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
 | |
|       Status = EFI_NOT_FOUND;
 | |
|       while (PackageOffset < PackageListLength) {
 | |
|         CopyMem (&PacakgeHeader, (UINT8 *) HiiPackageList + PackageOffset, sizeof (PacakgeHeader));
 | |
|         
 | |
|         //
 | |
|         // Parse IFR opcode to get default store opcode
 | |
|         //
 | |
|         if (PacakgeHeader.Type == EFI_HII_PACKAGE_FORMS) {
 | |
|           IfrOffset = sizeof (PacakgeHeader);
 | |
|           PackageData = (UINT8 *) HiiPackageList + PackageOffset;
 | |
|           while (IfrOffset < PacakgeHeader.Length) {
 | |
|             IfrOpHdr = (EFI_IFR_OP_HEADER *) (PackageData + IfrOffset);
 | |
|             //
 | |
|             // Match DefaultId to find its DefaultName
 | |
|             //
 | |
|             if (IfrOpHdr->OpCode == EFI_IFR_DEFAULTSTORE_OP) {
 | |
|               if (((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultId == DefaultId) {
 | |
|                 DefaultName = ((EFI_IFR_DEFAULTSTORE *) IfrOpHdr)->DefaultName;
 | |
|                 Status = EFI_SUCCESS;
 | |
|                 break;
 | |
|               }
 | |
|             }
 | |
|             IfrOffset += IfrOpHdr->Length;
 | |
|           }
 | |
|           //
 | |
|           // Only one form is in a package list.
 | |
|           //
 | |
|           break;
 | |
|         }
 | |
|         
 | |
|         //
 | |
|         // Go to next package.
 | |
|         //
 | |
|         PackageOffset += PacakgeHeader.Length;      
 | |
|       }
 | |
|       
 | |
|       //
 | |
|       // Not found the matched default string ID
 | |
|       //
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         Status = EFI_SUCCESS;
 | |
|         goto NextConfigAltResp;
 | |
|       }
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // 3. Call ConfigRouting GetAltCfg(ConfigRoute, <ConfigResponse>, Guid, Name, DevicePath, AltCfgId, AltCfgResp)
 | |
|     //    Get the default configuration string according to the found defaultname string ID.
 | |
|     //
 | |
|     Status = gHiiConfigRouting->GetAltConfig (
 | |
|                                   gHiiConfigRouting,
 | |
|                                   ConfigAltResp,
 | |
|                                   VarGuid,
 | |
|                                   VarName,
 | |
|                                   DevicePath,
 | |
|                                   (ActionType == ACTION_SET_DEFAUTL_VALUE) ? &DefaultName:NULL,  // it can be NULL to get the current setting.
 | |
|                                   &ConfigResp
 | |
|                                 );
 | |
|     
 | |
|     //
 | |
|     // The required setting can't be found. So, it is not required to be validated and set.
 | |
|     //
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto NextConfigAltResp;
 | |
|     }
 | |
|     //
 | |
|     // Only the ConfigHdr is found. Not any block data is found. No data is required to be validated and set.
 | |
|     //
 | |
|     if (StrStr (ConfigResp, L"&OFFSET=") == NULL) {
 | |
|       goto NextConfigAltResp;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // 4. Set the default configuration information or Validate current setting by parse IFR code.
 | |
|     //    Current Setting is in ConfigResp, will be set into buffer, then check it again.
 | |
|     //
 | |
|     if (ActionType == ACTION_SET_DEFAUTL_VALUE) {
 | |
|       //
 | |
|       // Set the default configuration information.
 | |
|       //
 | |
|       Status = gHiiConfigRouting->RouteConfig (gHiiConfigRouting, ConfigResp, &Progress);
 | |
|     } else {
 | |
|       //
 | |
|       // Current Setting is in ConfigResp, will be set into buffer, then check it again.
 | |
|       //
 | |
|       Status = InternalHiiValidateCurrentSetting (ConfigResp, HiiPackageList, PackageListLength, VarGuid, VarName);
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
| NextConfigAltResp:
 | |
|     //
 | |
|     // Free the allocated pacakge buffer and the got ConfigResp string.
 | |
|     //
 | |
|     if (HiiPackageList != NULL) {
 | |
|       FreePool (HiiPackageList);
 | |
|       HiiPackageList = NULL;
 | |
|     }
 | |
|     
 | |
|   	if (ConfigResp != NULL) {
 | |
|   	  FreePool (ConfigResp);
 | |
|   	  ConfigResp = NULL;
 | |
|   	}
 | |
| 
 | |
|     //
 | |
|     // Free the allocated buffer.
 | |
|     //
 | |
|     FreePool (VarGuid);
 | |
|     VarGuid = NULL;
 | |
|   
 | |
|     FreePool (VarName);
 | |
|     VarName = NULL;
 | |
|   
 | |
|     FreePool (DevicePath);
 | |
|     DevicePath = NULL;
 | |
| 
 | |
|     //
 | |
|     // 5. Jump to next ConfigAltResp for another Guid, Name, Path.
 | |
|     //
 | |
| 
 | |
|     //
 | |
|     // Get and Skip ConfigHdr
 | |
|     //
 | |
|     while (*StringPtr != L'\0' && *StringPtr != L'&') {
 | |
|       StringPtr++;
 | |
|     }
 | |
|     if (*StringPtr == L'\0') {
 | |
|       break;
 | |
|     }
 | |
|         
 | |
|     //
 | |
|     // Construct ConfigAltHdr string  "&<ConfigHdr>&ALTCFG=\0" 
 | |
|     //                               | 1 | StrLen (ConfigHdr) | 8 | 1 |
 | |
|     //
 | |
|     ConfigAltHdr = AllocateZeroPool ((1 + StringPtr - StringHdr + 8 + 1) * sizeof (CHAR16));
 | |
|     if (ConfigAltHdr == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
|     StrCpy (ConfigAltHdr, L"&");
 | |
|     StrnCat (ConfigAltHdr, StringHdr, StringPtr - StringHdr);
 | |
|     StrCat (ConfigAltHdr, L"&ALTCFG=");
 | |
|     
 | |
|     //
 | |
|     // Skip all AltResp (AltConfigHdr ConfigBody) for the same ConfigHdr
 | |
|     //
 | |
|     while ((StringHdr = StrStr (StringPtr, ConfigAltHdr)) != NULL) {
 | |
|       StringPtr = StringHdr + StrLen (ConfigAltHdr);
 | |
|       if (*StringPtr == L'\0') {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // Free the allocated ConfigAltHdr string
 | |
|     //
 | |
|     FreePool (ConfigAltHdr);
 | |
|     if (*StringPtr == L'\0') {
 | |
|       break;
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // Find &GUID as the next ConfigHdr
 | |
|     //
 | |
|     StringPtr = StrStr (StringPtr, L"&GUID");
 | |
|     if (StringPtr == NULL) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Skip char '&'
 | |
|     //
 | |
|     StringPtr ++;
 | |
|   }
 | |
|   
 | |
| Done:
 | |
|   if (VarGuid != NULL) {
 | |
|     FreePool (VarGuid);
 | |
|   }
 | |
| 
 | |
|   if (VarName != NULL) {
 | |
|     FreePool (VarName);
 | |
|   }
 | |
| 
 | |
|   if (DevicePath != NULL) {
 | |
|     FreePool (DevicePath);
 | |
|   }
 | |
| 
 | |
|   if (ConfigResp != NULL) {
 | |
|     FreePool (ConfigResp);
 | |
|   }
 | |
| 
 | |
|   if (ConfigAltResp != NULL) {
 | |
|     FreePool (ConfigAltResp);
 | |
|   }
 | |
|  
 | |
|   if (HiiPackageList != NULL) {
 | |
|     FreePool (HiiPackageList);
 | |
|   }
 | |
|   
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Validate the current configuration by parsing HII form IFR opcode.
 | |
| 
 | |
|   NULL request string support depends on the ExtractConfig interface of
 | |
|   HiiConfigRouting protocol in UEFI specification.
 | |
|   
 | |
|   @param  Request   A null-terminated Unicode string in 
 | |
|                     <MultiConfigRequest> format. It can be NULL.
 | |
|                     If it is NULL, all current configuration for the
 | |
|                     entirety of the current HII database will be validated.
 | |
|   
 | |
|   @retval TURE    Current configuration is valid.
 | |
|   @retval FALSE   Current configuration is invalid.
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI                               
 | |
| HiiValidateSettings (
 | |
|   IN CONST EFI_STRING Request  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   return InternalHiiIfrValueAction (Request, 0, ACTION_VALIDATE_SETTING);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reset the default value specified by DefaultId to the driver
 | |
|   configuration got by Request string. 
 | |
| 
 | |
|   NULL request string support depends on the ExportConfig interface of
 | |
|   HiiConfigRouting protocol in UEFI specification.
 | |
|   
 | |
|   @param Request    A null-terminated Unicode string in 
 | |
|                     <MultiConfigRequest> format. It can be NULL.
 | |
|                     If it is NULL, all configuration for the
 | |
|                     entirety of the current HII database will be reset.
 | |
|   @param DefaultId  Specifies the type of defaults to retrieve.
 | |
|   
 | |
|   @retval TURE    The default value is set successfully.
 | |
|   @retval FALSE   The default value can't be found and set.
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| HiiSetToDefaults (
 | |
|   IN CONST EFI_STRING Request,  OPTIONAL
 | |
|   IN UINT16        DefaultId
 | |
|   )
 | |
| {
 | |
|   return InternalHiiIfrValueAction (Request, DefaultId, ACTION_SET_DEFAUTL_VALUE);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Determines if two values in config strings match.
 | |
| 
 | |
|   Compares the substring between StartSearchString and StopSearchString in 
 | |
|   FirstString to the substring between StartSearchString and StopSearchString 
 | |
|   in SecondString.  If the two substrings match, then TRUE is returned.  If the
 | |
|   two substrings do not match, then FALSE is returned.
 | |
| 
 | |
|   If FirstString is NULL, then ASSERT().
 | |
|   If SecondString is NULL, then ASSERT().
 | |
|   If StartSearchString is NULL, then ASSERT().
 | |
|   If StopSearchString is NULL, then ASSERT().
 | |
| 
 | |
|   @param FirstString        Pointer to the first Null-terminated Unicode string.
 | |
|   @param SecondString       Pointer to the second Null-terminated Unicode string.
 | |
|   @param StartSearchString  Pointer to the Null-terminated Unicode string that 
 | |
|                             marks the start of the value string to compare.
 | |
|   @param StopSearchString   Pointer to the Null-terminated Unicode string that 
 | |
|                             marks the end of the vakue string to compare.
 | |
| 
 | |
|   @retval FALSE             StartSearchString is not present in FirstString. 
 | |
|   @retval FALSE             StartSearchString is not present in SecondString.
 | |
|   @retval FALSE             StopSearchString is not present in FirstString. 
 | |
|   @retval FALSE             StopSearchString is not present in SecondString.
 | |
|   @retval FALSE             The length of the substring in FirstString is not the 
 | |
|                             same length as the substring in SecondString.
 | |
|   @retval FALSE             The value string in FirstString does not matche the 
 | |
|                             value string in SecondString.
 | |
|   @retval TRUE              The value string in FirstString matches the value 
 | |
|                             string in SecondString.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| InternalHiiCompareSubString (
 | |
|   IN CHAR16  *FirstString,
 | |
|   IN CHAR16  *SecondString,
 | |
|   IN CHAR16  *StartSearchString,
 | |
|   IN CHAR16  *StopSearchString
 | |
|   )
 | |
| {
 | |
|   CHAR16  *EndFirstString;
 | |
|   CHAR16  *EndSecondString;
 | |
| 
 | |
|   ASSERT (FirstString != NULL);
 | |
|   ASSERT (SecondString != NULL);
 | |
|   ASSERT (StartSearchString != NULL);
 | |
|   ASSERT (StopSearchString != NULL);
 | |
| 
 | |
|   FirstString = StrStr (FirstString, StartSearchString);
 | |
|   if (FirstString == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   SecondString = StrStr (SecondString, StartSearchString);
 | |
|   if (SecondString == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   EndFirstString = StrStr (FirstString, StopSearchString);
 | |
|   if (EndFirstString == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   EndSecondString = StrStr (SecondString, StopSearchString);
 | |
|   if (EndSecondString == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if ((EndFirstString - FirstString) != (EndSecondString - SecondString)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return (BOOLEAN)(StrnCmp (FirstString, SecondString, EndFirstString - FirstString) == 0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Determines if the routing data specified by GUID and NAME match a <ConfigHdr>.
 | |
| 
 | |
|   If ConfigHdr is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in] ConfigHdr  Either <ConfigRequest> or <ConfigResp>.
 | |
|   @param[in] Guid       GUID of the storage.
 | |
|   @param[in] Name       NAME of the storage.
 | |
| 
 | |
|   @retval TRUE   Routing information matches <ConfigHdr>.
 | |
|   @retval FALSE  Routing information does not match <ConfigHdr>.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| HiiIsConfigHdrMatch (
 | |
|   IN CONST EFI_STRING  ConfigHdr,
 | |
|   IN CONST EFI_GUID    *Guid,     OPTIONAL
 | |
|   IN CONST CHAR16      *Name      OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STRING  CompareConfigHdr;
 | |
|   BOOLEAN     Result;
 | |
| 
 | |
|   ASSERT (ConfigHdr != NULL);
 | |
| 
 | |
|   //
 | |
|   // Use Guid and Name to generate a <ConfigHdr> string
 | |
|   //
 | |
|   CompareConfigHdr = HiiConstructConfigHdr (Guid, Name, NULL);
 | |
|   if (CompareConfigHdr == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   Result = TRUE;
 | |
|   if (Guid != NULL) {
 | |
|     //
 | |
|     // Compare GUID value strings
 | |
|     //
 | |
|     Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"GUID=", L"&NAME=");
 | |
|   }
 | |
| 
 | |
|   if (Result && Name != NULL) {
 | |
|     //
 | |
|     // Compare NAME value strings
 | |
|     //
 | |
|     Result = InternalHiiCompareSubString (ConfigHdr, CompareConfigHdr, L"&NAME=", L"&PATH=");
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Free the <ConfigHdr> string
 | |
|   //
 | |
|   FreePool (CompareConfigHdr);
 | |
| 
 | |
|   return Result;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Retrieves uncommited data from the Form Browser and converts it to a binary
 | |
|   buffer.
 | |
| 
 | |
|   @param[in]  VariableName  Pointer to a Null-terminated Unicode string.  This 
 | |
|                             is an optional parameter that may be NULL.
 | |
|   @param[in]  VariableGuid  Pointer to an EFI_GUID structure.  This is an optional 
 | |
|                             parameter that may be NULL.
 | |
|   @param[in]  BufferSize    Length in bytes of buffer to hold retrived data. 
 | |
|   @param[out] Block         Buffer of data to be updated.
 | |
| 
 | |
|   @retval FALSE  The uncommitted data could not be retrieved.
 | |
|   @retval TRUE   The uncommitted data was retrieved.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| HiiGetBrowserData (
 | |
|   IN CONST EFI_GUID  *VariableGuid,  OPTIONAL
 | |
|   IN CONST CHAR16    *VariableName,  OPTIONAL
 | |
|   IN UINTN           BlockSize,
 | |
|   OUT UINT8          *Block
 | |
|   )
 | |
| {
 | |
|   EFI_STRING  ResultsData;
 | |
|   UINTN       Size;
 | |
|   EFI_STRING  ConfigResp;
 | |
|   EFI_STATUS  Status;
 | |
|   CHAR16      *Progress;
 | |
| 
 | |
|   //
 | |
|   // Retrieve the results data from the Browser Callback
 | |
|   //
 | |
|   ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, NULL);
 | |
|   if (ResultsData == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Construct <ConfigResp> mConfigHdrTemplate L'&' ResultsData L'\0'
 | |
|   //
 | |
|   Size = (StrLen (mConfigHdrTemplate) + 1) * sizeof (CHAR16);
 | |
|   Size = Size + (StrLen (ResultsData) + 1) * sizeof (CHAR16);
 | |
|   ConfigResp = AllocateZeroPool (Size);
 | |
|   UnicodeSPrint (ConfigResp, Size, L"%s&%s", mConfigHdrTemplate, ResultsData);
 | |
|   
 | |
|   //
 | |
|   // Free the allocated buffer
 | |
|   //
 | |
|   FreePool (ResultsData);
 | |
|   if (ConfigResp == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Convert <ConfigResp> to a buffer
 | |
|   //
 | |
|   Status = gHiiConfigRouting->ConfigToBlock (
 | |
|                                 gHiiConfigRouting,
 | |
|                                 ConfigResp,
 | |
|                                 Block,
 | |
|                                 &BlockSize,
 | |
|                                 &Progress
 | |
|                                 );
 | |
|   //
 | |
|   // Free the allocated buffer
 | |
|   //
 | |
|   FreePool (ConfigResp);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Updates uncommitted data in the Form Browser.
 | |
| 
 | |
|   If Buffer is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in]  VariableName    Pointer to a Null-terminated Unicode string.  This
 | |
|                               is an optional parameter that may be NULL.
 | |
|   @param[in]  VariableGuid    Pointer to an EFI_GUID structure.  This is an optional
 | |
|                               parameter that may be NULL.
 | |
|   @param[in]  BufferSize      Length, in bytes, of Buffer.
 | |
|   @param[in]  Buffer          Buffer of data to commit.
 | |
|   @param[in]  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 FALSE  The uncommitted data could not be updated.
 | |
|   @retval TRUE   The uncommitted data was updated.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| HiiSetBrowserData (
 | |
|   IN CONST EFI_GUID  *VariableGuid, OPTIONAL
 | |
|   IN CONST CHAR16    *VariableName, OPTIONAL
 | |
|   IN UINTN           BufferSize,
 | |
|   IN CONST UINT8     *Buffer,
 | |
|   IN CONST CHAR16    *RequestElement  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   UINTN       Size;
 | |
|   EFI_STRING  ConfigRequest;
 | |
|   EFI_STRING  ConfigResp;
 | |
|   EFI_STRING  ResultsData;
 | |
| 
 | |
|   ASSERT (Buffer != NULL);
 | |
| 
 | |
|   //
 | |
|   // Construct <ConfigRequest>
 | |
|   //
 | |
|   if (RequestElement == NULL) {
 | |
|     //
 | |
|     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template 
 | |
|     // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
 | |
|     //
 | |
|     Size = (StrLen (mConfigHdrTemplate) + 32 + 1) * sizeof (CHAR16);
 | |
|     ConfigRequest = AllocateZeroPool (Size);
 | |
|     UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", mConfigHdrTemplate, (UINT64)BufferSize);
 | |
|   } else {
 | |
|     //
 | |
|     // Allocate and fill a buffer large enough to hold the <ConfigHdr> template 
 | |
|     // followed by <RequestElement> followed by a Null-terminator
 | |
|     //
 | |
|     Size = StrLen (mConfigHdrTemplate) * sizeof (CHAR16);
 | |
|     Size = Size + (StrLen (RequestElement) + 1) * sizeof (CHAR16);
 | |
|     ConfigRequest = AllocateZeroPool (Size);
 | |
|     UnicodeSPrint (ConfigRequest, Size, L"%s%s", mConfigHdrTemplate, RequestElement);
 | |
|   }
 | |
|   if (ConfigRequest == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Convert <ConfigRequest> to <ConfigResp>
 | |
|   //
 | |
|   ConfigResp = InternalHiiBlockToConfig (ConfigRequest, Buffer, BufferSize);
 | |
|   FreePool (ConfigRequest);
 | |
|   if (ConfigResp == NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set data in the uncommitted browser state information
 | |
|   //
 | |
|   ResultsData = InternalHiiBrowserCallback (VariableGuid, VariableName, ConfigResp + StrLen(mConfigHdrTemplate) + 1);
 | |
|   FreePool (ConfigResp);
 | |
| 
 | |
|   return (BOOLEAN)(ResultsData != NULL);
 | |
| }
 | |
| 
 | |
| /////////////////////////////////////////
 | |
| /////////////////////////////////////////
 | |
| /// IFR Functions
 | |
| /////////////////////////////////////////
 | |
| /////////////////////////////////////////
 | |
| 
 | |
| #define HII_LIB_OPCODE_ALLOCATION_SIZE  0x200
 | |
| 
 | |
| typedef struct {
 | |
|   UINT8  *Buffer;
 | |
|   UINTN  BufferSize;
 | |
|   UINTN  Position;
 | |
| } HII_LIB_OPCODE_BUFFER;
 | |
| 
 | |
| ///
 | |
| /// Lookup table that converts EFI_IFR_TYPE_X enum values to a width in bytes
 | |
| ///
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 mHiiDefaultTypeToWidth[] = {
 | |
|   1, // EFI_IFR_TYPE_NUM_SIZE_8
 | |
|   2, // EFI_IFR_TYPE_NUM_SIZE_16
 | |
|   4, // EFI_IFR_TYPE_NUM_SIZE_32
 | |
|   8, // EFI_IFR_TYPE_NUM_SIZE_64
 | |
|   1, // EFI_IFR_TYPE_BOOLEAN
 | |
|   3, // EFI_IFR_TYPE_TIME
 | |
|   4, // EFI_IFR_TYPE_DATE
 | |
|   2  // EFI_IFR_TYPE_STRING
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Allocates and returns a new OpCode Handle.  OpCode Handles must be freed with 
 | |
|   HiiFreeOpCodeHandle().
 | |
| 
 | |
|   @retval NULL   There are not enough resources to allocate a new OpCode Handle.
 | |
|   @retval Other  A new OpCode handle.
 | |
| 
 | |
| **/
 | |
| VOID *
 | |
| EFIAPI
 | |
| HiiAllocateOpCodeHandle (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;
 | |
| 
 | |
|   OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)AllocatePool (sizeof (HII_LIB_OPCODE_BUFFER));
 | |
|   if (OpCodeBuffer == NULL) {
 | |
|     return NULL;
 | |
|   }
 | |
|   OpCodeBuffer->Buffer = (UINT8 *)AllocatePool (HII_LIB_OPCODE_ALLOCATION_SIZE);
 | |
|   if (OpCodeBuffer->Buffer == NULL) {
 | |
|     FreePool (OpCodeBuffer);
 | |
|     return NULL;
 | |
|   }
 | |
|   OpCodeBuffer->BufferSize = HII_LIB_OPCODE_ALLOCATION_SIZE;
 | |
|   OpCodeBuffer->Position = 0;
 | |
|   return (VOID *)OpCodeBuffer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Frees an OpCode Handle that was peviously allocated with HiiAllocateOpCodeHandle().
 | |
|   When an OpCode Handle is freed, all of the opcodes associated with the OpCode
 | |
|   Handle are also freed.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| HiiFreeOpCodeHandle (
 | |
|   VOID  *OpCodeHandle
 | |
|   )
 | |
| {
 | |
|   HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;
 | |
| 
 | |
|   ASSERT (OpCodeHandle != NULL);
 | |
| 
 | |
|   OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
 | |
|   if (OpCodeBuffer->Buffer != NULL) {
 | |
|     FreePool (OpCodeBuffer->Buffer);
 | |
|   }
 | |
|   FreePool (OpCodeBuffer);
 | |
| }
 | |
| 
 | |
| UINTN
 | |
| EFIAPI
 | |
| InternalHiiOpCodeHandlePosition (
 | |
|   IN VOID  *OpCodeHandle
 | |
|   )
 | |
| {
 | |
|   return ((HII_LIB_OPCODE_BUFFER  *)OpCodeHandle)->Position;
 | |
| }
 | |
| 
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| InternalHiiOpCodeHandleBuffer (
 | |
|   IN VOID  *OpCodeHandle
 | |
|   )
 | |
| {
 | |
|   return ((HII_LIB_OPCODE_BUFFER  *)OpCodeHandle)->Buffer;
 | |
| }
 | |
| 
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| InternalHiiGrowOpCodeHandle (
 | |
|   VOID   *OpCodeHandle,
 | |
|   UINTN  Size
 | |
|   )
 | |
| {
 | |
|   HII_LIB_OPCODE_BUFFER  *OpCodeBuffer;
 | |
|   UINT8                  *Buffer;
 | |
| 
 | |
|   ASSERT (OpCodeHandle != NULL);
 | |
| 
 | |
|   OpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)OpCodeHandle;
 | |
|   if (OpCodeBuffer->Position + Size > OpCodeBuffer->BufferSize) {
 | |
|     Buffer = ReallocatePool (
 | |
|               OpCodeBuffer->BufferSize, 
 | |
|               OpCodeBuffer->BufferSize + (Size + HII_LIB_OPCODE_ALLOCATION_SIZE),
 | |
|               OpCodeBuffer->Buffer
 | |
|               );
 | |
|     if (Buffer == NULL) {
 | |
|       return NULL;
 | |
|     }
 | |
|     OpCodeBuffer->Buffer = Buffer;
 | |
|     OpCodeBuffer->BufferSize += (Size + HII_LIB_OPCODE_ALLOCATION_SIZE);
 | |
|   }
 | |
|   Buffer = OpCodeBuffer->Buffer + OpCodeBuffer->Position;
 | |
|   OpCodeBuffer->Position += Size;
 | |
|   return Buffer;
 | |
| }
 | |
| 
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| InternalHiiCreateOpCodeExtended (
 | |
|   IN VOID   *OpCodeHandle,
 | |
|   IN VOID   *OpCodeTemplate,
 | |
|   IN UINT8  OpCode,
 | |
|   IN UINTN  OpCodeSize,
 | |
|   IN UINTN  ExtensionSize,
 | |
|   IN UINT8  Scope
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_OP_HEADER  *Header;
 | |
|   UINT8              *Buffer;
 | |
| 
 | |
|   ASSERT (OpCodeTemplate != NULL);
 | |
|   ASSERT ((OpCodeSize + ExtensionSize) <= 0x7F);
 | |
| 
 | |
|   Header = (EFI_IFR_OP_HEADER *)OpCodeTemplate;
 | |
|   Header->OpCode = OpCode;
 | |
|   Header->Scope  = Scope;
 | |
|   Header->Length = (UINT8)(OpCodeSize + ExtensionSize);
 | |
|   Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, Header->Length);
 | |
|   return (UINT8 *)CopyMem (Buffer, Header, OpCodeSize);
 | |
| }
 | |
| 
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| InternalHiiCreateOpCode (
 | |
|   IN VOID   *OpCodeHandle,
 | |
|   IN VOID   *OpCodeTemplate,
 | |
|   IN UINT8  OpCode,
 | |
|   IN UINTN  OpCodeSize
 | |
|   )
 | |
| {
 | |
|   return InternalHiiCreateOpCodeExtended (OpCodeHandle, OpCodeTemplate, OpCode, OpCodeSize, 0, 0);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Append raw opcodes to an OpCodeHandle.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If RawBuffer is NULL, then ASSERT();
 | |
| 
 | |
|   @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
 | |
|   @param[in]  RawBuffer      Buffer of opcodes to append.
 | |
|   @param[in]  RawBufferSize  The size, in bytes, of Buffer.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the appended opcodes.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateRawOpCodes (
 | |
|   IN VOID   *OpCodeHandle,
 | |
|   IN UINT8  *RawBuffer,
 | |
|   IN UINTN  RawBufferSize
 | |
|   )
 | |
| {
 | |
|   UINT8  *Buffer;
 | |
| 
 | |
|   ASSERT (RawBuffer != NULL);
 | |
| 
 | |
|   Buffer = InternalHiiGrowOpCodeHandle (OpCodeHandle, RawBufferSize);
 | |
|   return (UINT8 *)CopyMem (Buffer, RawBuffer, RawBufferSize);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Append opcodes from one OpCode Handle to another OpCode handle.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If RawOpCodeHandle is NULL, then ASSERT();
 | |
| 
 | |
|   @param[in]  OpCodeHandle     Handle to the buffer of opcodes.
 | |
|   @param[in]  RawOpCodeHandle  Handle to the buffer of opcodes.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the appended opcodes.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| InternalHiiAppendOpCodes (
 | |
|   IN VOID  *OpCodeHandle,
 | |
|   IN VOID  *RawOpCodeHandle
 | |
|   )
 | |
| {
 | |
|   HII_LIB_OPCODE_BUFFER  *RawOpCodeBuffer;
 | |
| 
 | |
|   ASSERT (RawOpCodeHandle != NULL);
 | |
| 
 | |
|   RawOpCodeBuffer = (HII_LIB_OPCODE_BUFFER *)RawOpCodeHandle;
 | |
|   return HiiCreateRawOpCodes (OpCodeHandle, RawOpCodeBuffer->Buffer, RawOpCodeBuffer->Position);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_END_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateEndOpCode (
 | |
|   IN VOID  *OpCodeHandle
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_END  OpCode;
 | |
| 
 | |
|   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_END_OP, sizeof (OpCode));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_ONE_OF_OPTION_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If Type is invalid, then ASSERT().
 | |
|   If Flags is invalid, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
 | |
|   @param[in]  StringId      StringId for the option
 | |
|   @param[in]  Flags         Flags for the option
 | |
|   @param[in]  Type          Type for the option
 | |
|   @param[in]  Value         Value for the option
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateOneOfOptionOpCode (
 | |
|   IN VOID    *OpCodeHandle,
 | |
|   IN UINT16  StringId,
 | |
|   IN UINT8   Flags,
 | |
|   IN UINT8   Type,
 | |
|   IN UINT64  Value
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_ONE_OF_OPTION  OpCode;
 | |
| 
 | |
|   ASSERT (Type < EFI_IFR_TYPE_OTHER);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Option = StringId;
 | |
|   OpCode.Flags  = (UINT8) (Flags & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG));
 | |
|   OpCode.Type   = Type;
 | |
|   CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
 | |
| 
 | |
|   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OPTION_OP, sizeof (OpCode));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_DEFAULT_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If Type is invalid, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
 | |
|   @param[in]  DefaultId     DefaultId for the default
 | |
|   @param[in]  Type          Type for the default
 | |
|   @param[in]  Value         Value for the default
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateDefaultOpCode (
 | |
|   IN VOID    *OpCodeHandle,
 | |
|   IN UINT16  DefaultId,
 | |
|   IN UINT8   Type,
 | |
|   IN UINT64  Value
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_DEFAULT  OpCode;
 | |
| 
 | |
|   ASSERT (Type < EFI_IFR_TYPE_OTHER);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Type      = Type;
 | |
|   OpCode.DefaultId = DefaultId;
 | |
|   CopyMem (&OpCode.Value, &Value, mHiiDefaultTypeToWidth[Type]);
 | |
| 
 | |
|   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_DEFAULT_OP, sizeof (OpCode));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_GUID opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If Guid is NULL, then ASSERT().
 | |
|   If OpCodeSize < sizeof (EFI_IFR_GUID), then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
 | |
|   @param[in]  Guid          Pointer to EFI_GUID of this guided opcode.
 | |
|   @param[in]  GuidOpCode    Pointer to an EFI_IFR_GUID opcode.  This is an 
 | |
|                             optional parameter that may be NULL.  If this
 | |
|                             parameter is NULL, then the GUID extension 
 | |
|                             region of the created opcode is filled with zeros.
 | |
|                             If this parameter is not NULL, then the GUID 
 | |
|                             extension region of GuidData will be copied to 
 | |
|                             the GUID extension region of the created opcode.
 | |
|   @param[in]  OpCodeSize    The size, in bytes, of created opcode.  This value 
 | |
|                             must be >= sizeof(EFI_IFR_GUID).
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateGuidOpCode (
 | |
|   IN VOID            *OpCodeHandle,
 | |
|   IN CONST EFI_GUID  *Guid,
 | |
|   IN CONST VOID      *GuidOpCode,    OPTIONAL
 | |
|   IN UINTN           OpCodeSize
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_GUID  OpCode;
 | |
|   EFI_IFR_GUID  *OpCodePointer;
 | |
| 
 | |
|   ASSERT (Guid != NULL);
 | |
|   ASSERT (OpCodeSize >= sizeof (OpCode));
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   CopyGuid ((EFI_GUID *)(VOID *)&OpCode.Guid, Guid);
 | |
| 
 | |
|   OpCodePointer = (EFI_IFR_GUID *)InternalHiiCreateOpCodeExtended (
 | |
|                                     OpCodeHandle, 
 | |
|                                     &OpCode,
 | |
|                                     EFI_IFR_GUID_OP,
 | |
|                                     sizeof (OpCode),
 | |
|                                     OpCodeSize - sizeof (OpCode),
 | |
|                                     0
 | |
|                                     );
 | |
|   if (OpCodePointer != NULL && GuidOpCode != NULL) {
 | |
|     CopyMem (OpCodePointer + 1, (EFI_IFR_GUID *)GuidOpCode + 1, OpCodeSize - sizeof (OpCode));
 | |
|   }
 | |
|   return (UINT8 *)OpCodePointer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_ACTION_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If any reserved bits are set in QuestionFlags, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
 | |
|   @param[in]  QuestionId      Question ID
 | |
|   @param[in]  Prompt          String ID for Prompt
 | |
|   @param[in]  Help            String ID for Help
 | |
|   @param[in]  QuestionFlags   Flags in Question Header
 | |
|   @param[in]  QuestionConfig  String ID for configuration
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateActionOpCode (
 | |
|   IN VOID             *OpCodeHandle,
 | |
|   IN EFI_QUESTION_ID  QuestionId,
 | |
|   IN EFI_STRING_ID    Prompt,
 | |
|   IN EFI_STRING_ID    Help,
 | |
|   IN UINT8            QuestionFlags,
 | |
|   IN EFI_STRING_ID    QuestionConfig
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_ACTION  OpCode;
 | |
| 
 | |
|   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Question.QuestionId    = QuestionId;
 | |
|   OpCode.Question.Header.Prompt = Prompt;
 | |
|   OpCode.Question.Header.Help   = Help;
 | |
|   OpCode.Question.Flags         = QuestionFlags;
 | |
|   OpCode.QuestionConfig         = QuestionConfig;
 | |
| 
 | |
|   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_ACTION_OP, sizeof (OpCode));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_SUBTITLE_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If any reserved bits are set in Flags, then ASSERT().
 | |
|   If Scope > 1, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle  Handle to the buffer of opcodes.
 | |
|   @param[in]  Prompt      String ID for Prompt
 | |
|   @param[in]  Help        String ID for Help
 | |
|   @param[in]  Flags       Subtitle opcode flags
 | |
|   @param[in]  Scope       1 if this opcpde is the beginning of a new scope.
 | |
|                           0 if this opcode is within the current scope.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateSubTitleOpCode (
 | |
|   IN VOID           *OpCodeHandle,
 | |
|   IN EFI_STRING_ID  Prompt,
 | |
|   IN EFI_STRING_ID  Help,
 | |
|   IN UINT8          Flags,
 | |
|   IN UINT8          Scope
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_SUBTITLE  OpCode;
 | |
| 
 | |
|   ASSERT (Scope <= 1);
 | |
|   ASSERT ((Flags & (~(EFI_IFR_FLAGS_HORIZONTAL))) == 0);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Statement.Prompt = Prompt;
 | |
|   OpCode.Statement.Help   = Help;
 | |
|   OpCode.Flags            = Flags;
 | |
| 
 | |
|   return InternalHiiCreateOpCodeExtended (
 | |
|            OpCodeHandle, 
 | |
|            &OpCode,
 | |
|            EFI_IFR_SUBTITLE_OP, 
 | |
|            sizeof (OpCode), 
 | |
|            0, 
 | |
|            Scope
 | |
|            );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_REF_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If any reserved bits are set in QuestionFlags, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle   Handle to the buffer of opcodes.
 | |
|   @param[in]  FormId         Destination Form ID
 | |
|   @param[in]  Prompt         String ID for Prompt
 | |
|   @param[in]  Help           String ID for Help
 | |
|   @param[in]  QuestionFlags  Flags in Question Header
 | |
|   @param[in]  QuestionId     Question ID
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateGotoOpCode (
 | |
|   IN VOID             *OpCodeHandle,
 | |
|   IN EFI_FORM_ID      FormId,
 | |
|   IN EFI_STRING_ID    Prompt,
 | |
|   IN EFI_STRING_ID    Help,
 | |
|   IN UINT8            QuestionFlags,
 | |
|   IN EFI_QUESTION_ID  QuestionId
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_REF  OpCode;
 | |
| 
 | |
|   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Question.Header.Prompt = Prompt;
 | |
|   OpCode.Question.Header.Help   = Help;
 | |
|   OpCode.Question.QuestionId    = QuestionId;
 | |
|   OpCode.Question.Flags         = QuestionFlags;
 | |
|   OpCode.FormId                 = FormId;
 | |
| 
 | |
|   return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_REF_OP, sizeof (OpCode));
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_CHECKBOX_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If any reserved bits are set in QuestionFlags, then ASSERT().
 | |
|   If any reserved bits are set in CheckBoxFlags, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
 | |
|   @param[in]  QuestionId            Question ID
 | |
|   @param[in]  VarStoreId            Storage ID
 | |
|   @param[in]  VarOffset             Offset in Storage
 | |
|   @param[in]  Prompt                String ID for Prompt
 | |
|   @param[in]  Help                  String ID for Help
 | |
|   @param[in]  QuestionFlags         Flags in Question Header
 | |
|   @param[in]  CheckBoxFlags         Flags for checkbox opcode
 | |
|   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
 | |
|                                     is an optional parameter that may be NULL.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateCheckBoxOpCode (
 | |
|   IN VOID             *OpCodeHandle,
 | |
|   IN EFI_QUESTION_ID  QuestionId,
 | |
|   IN EFI_VARSTORE_ID  VarStoreId,
 | |
|   IN UINT16           VarOffset,
 | |
|   IN EFI_STRING_ID    Prompt,
 | |
|   IN EFI_STRING_ID    Help,
 | |
|   IN UINT8            QuestionFlags,
 | |
|   IN UINT8            CheckBoxFlags,
 | |
|   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_CHECKBOX  OpCode;
 | |
|   UINTN             Position;
 | |
| 
 | |
|   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Question.QuestionId             = QuestionId;
 | |
|   OpCode.Question.VarStoreId             = VarStoreId;
 | |
|   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
 | |
|   OpCode.Question.Header.Prompt          = Prompt;
 | |
|   OpCode.Question.Header.Help            = Help;
 | |
|   OpCode.Question.Flags                  = QuestionFlags;
 | |
|   OpCode.Flags                           = CheckBoxFlags;
 | |
| 
 | |
|   if (DefaultsOpCodeHandle == NULL) {
 | |
|     return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode));
 | |
|   }
 | |
| 
 | |
|   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
 | |
|   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_CHECKBOX_OP, sizeof (OpCode), 0, 1);
 | |
|   InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
 | |
|   HiiCreateEndOpCode (OpCodeHandle);
 | |
|   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_NUMERIC_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If any reserved bits are set in QuestionFlags, then ASSERT().
 | |
|   If any reserved bits are set in NumericFlags, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
 | |
|   @param[in]  QuestionId            Question ID
 | |
|   @param[in]  VarStoreId            Storage ID
 | |
|   @param[in]  VarOffset             Offset in Storage
 | |
|   @param[in]  Prompt                String ID for Prompt
 | |
|   @param[in]  Help                  String ID for Help
 | |
|   @param[in]  QuestionFlags         Flags in Question Header
 | |
|   @param[in]  NumericFlags          Flags for numeric opcode
 | |
|   @param[in]  Minimum               Numeric minimum value
 | |
|   @param[in]  Maximum               Numeric maximum value
 | |
|   @param[in]  Step                  Numeric step for edit
 | |
|   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
 | |
|                                     is an optional parameter that may be NULL.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateNumericOpCode (
 | |
|   IN VOID             *OpCodeHandle,
 | |
|   IN EFI_QUESTION_ID  QuestionId,
 | |
|   IN EFI_VARSTORE_ID  VarStoreId,
 | |
|   IN UINT16           VarOffset,
 | |
|   IN EFI_STRING_ID    Prompt,
 | |
|   IN EFI_STRING_ID    Help,
 | |
|   IN UINT8            QuestionFlags,
 | |
|   IN UINT8            NumericFlags,
 | |
|   IN UINT64           Minimum,
 | |
|   IN UINT64           Maximum,
 | |
|   IN UINT64           Step,
 | |
|   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_NUMERIC  OpCode;
 | |
|   UINTN            Position;
 | |
| 
 | |
|   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Question.QuestionId             = QuestionId;
 | |
|   OpCode.Question.VarStoreId             = VarStoreId;
 | |
|   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
 | |
|   OpCode.Question.Header.Prompt          = Prompt;
 | |
|   OpCode.Question.Header.Help            = Help;
 | |
|   OpCode.Question.Flags                  = QuestionFlags;
 | |
|   OpCode.Flags                           = NumericFlags;
 | |
| 
 | |
|   switch (NumericFlags & EFI_IFR_NUMERIC_SIZE) {
 | |
|   case EFI_IFR_NUMERIC_SIZE_1:
 | |
|     OpCode.data.u8.MinValue = (UINT8)Minimum;
 | |
|     OpCode.data.u8.MaxValue = (UINT8)Maximum;
 | |
|     OpCode.data.u8.Step     = (UINT8)Step;
 | |
|     break;
 | |
| 
 | |
|   case EFI_IFR_NUMERIC_SIZE_2:
 | |
|     OpCode.data.u16.MinValue = (UINT16)Minimum;
 | |
|     OpCode.data.u16.MaxValue = (UINT16)Maximum;
 | |
|     OpCode.data.u16.Step     = (UINT16)Step;
 | |
|     break;
 | |
| 
 | |
|   case EFI_IFR_NUMERIC_SIZE_4:
 | |
|     OpCode.data.u32.MinValue = (UINT32)Minimum;
 | |
|     OpCode.data.u32.MaxValue = (UINT32)Maximum;
 | |
|     OpCode.data.u32.Step     = (UINT32)Step;
 | |
|     break;
 | |
| 
 | |
|   case EFI_IFR_NUMERIC_SIZE_8:
 | |
|     OpCode.data.u64.MinValue = Minimum;
 | |
|     OpCode.data.u64.MaxValue = Maximum;
 | |
|     OpCode.data.u64.Step     = Step;
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   if (DefaultsOpCodeHandle == NULL) {
 | |
|     return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode));
 | |
|   }
 | |
| 
 | |
|   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
 | |
|   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_NUMERIC_OP, sizeof (OpCode), 0, 1);
 | |
|   InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
 | |
|   HiiCreateEndOpCode (OpCodeHandle);
 | |
|   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_STRING_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If any reserved bits are set in QuestionFlags, then ASSERT().
 | |
|   If any reserved bits are set in StringFlags, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
 | |
|   @param[in]  QuestionId            Question ID
 | |
|   @param[in]  VarStoreId            Storage ID
 | |
|   @param[in]  VarOffset             Offset in Storage
 | |
|   @param[in]  Prompt                String ID for Prompt
 | |
|   @param[in]  Help                  String ID for Help
 | |
|   @param[in]  QuestionFlags         Flags in Question Header
 | |
|   @param[in]  StringFlags           Flags for string opcode
 | |
|   @param[in]  MinSize               String minimum length
 | |
|   @param[in]  MaxSize               String maximum length
 | |
|   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
 | |
|                                     is an optional parameter that may be NULL.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateStringOpCode (
 | |
|   IN VOID             *OpCodeHandle,
 | |
|   IN EFI_QUESTION_ID  QuestionId,
 | |
|   IN EFI_VARSTORE_ID  VarStoreId,
 | |
|   IN UINT16           VarOffset,
 | |
|   IN EFI_STRING_ID    Prompt,
 | |
|   IN EFI_STRING_ID    Help,
 | |
|   IN UINT8            QuestionFlags,
 | |
|   IN UINT8            StringFlags,
 | |
|   IN UINT8            MinSize,
 | |
|   IN UINT8            MaxSize,
 | |
|   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_STRING  OpCode;
 | |
|   UINTN           Position;
 | |
| 
 | |
|   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Question.Header.Prompt          = Prompt;
 | |
|   OpCode.Question.Header.Help            = Help;
 | |
|   OpCode.Question.QuestionId             = QuestionId;
 | |
|   OpCode.Question.VarStoreId             = VarStoreId;
 | |
|   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
 | |
|   OpCode.Question.Flags                  = QuestionFlags;
 | |
|   OpCode.MinSize                         = MinSize;
 | |
|   OpCode.MaxSize                         = MaxSize;
 | |
|   OpCode.Flags                           = (UINT8) (StringFlags & EFI_IFR_STRING_MULTI_LINE);
 | |
| 
 | |
|   if (DefaultsOpCodeHandle == NULL) {
 | |
|     return InternalHiiCreateOpCode (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode));
 | |
|   }
 | |
| 
 | |
|   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
 | |
|   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_STRING_OP, sizeof (OpCode), 0, 1);
 | |
|   InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
 | |
|   HiiCreateEndOpCode (OpCodeHandle);
 | |
|   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_ONE_OF_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If any reserved bits are set in QuestionFlags, then ASSERT().
 | |
|   If any reserved bits are set in OneOfFlags, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
 | |
|   @param[in]  QuestionId            Question ID
 | |
|   @param[in]  VarStoreId            Storage ID
 | |
|   @param[in]  VarOffset             Offset in Storage
 | |
|   @param[in]  Prompt                String ID for Prompt
 | |
|   @param[in]  Help                  String ID for Help
 | |
|   @param[in]  QuestionFlags         Flags in Question Header
 | |
|   @param[in]  OneOfFlags            Flags for oneof opcode
 | |
|   @param[in]  OptionsOpCodeHandle   Handle for a buffer of ONE_OF_OPTION opcodes.
 | |
|   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
 | |
|                                     is an optional parameter that may be NULL.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateOneOfOpCode (
 | |
|   IN VOID             *OpCodeHandle,
 | |
|   IN EFI_QUESTION_ID  QuestionId,
 | |
|   IN EFI_VARSTORE_ID  VarStoreId,
 | |
|   IN UINT16           VarOffset,
 | |
|   IN EFI_STRING_ID    Prompt,
 | |
|   IN EFI_STRING_ID    Help,
 | |
|   IN UINT8            QuestionFlags,
 | |
|   IN UINT8            OneOfFlags,
 | |
|   IN VOID             *OptionsOpCodeHandle,
 | |
|   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_ONE_OF  OpCode;
 | |
|   UINTN           Position;
 | |
| 
 | |
|   ASSERT (OptionsOpCodeHandle != NULL);
 | |
|   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Question.Header.Prompt          = Prompt;
 | |
|   OpCode.Question.Header.Help            = Help;
 | |
|   OpCode.Question.QuestionId             = QuestionId;
 | |
|   OpCode.Question.VarStoreId             = VarStoreId;
 | |
|   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
 | |
|   OpCode.Question.Flags                  = QuestionFlags;
 | |
|   OpCode.Flags                           = OneOfFlags;
 | |
| 
 | |
|   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
 | |
|   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ONE_OF_OP, sizeof (OpCode), 0, 1);
 | |
|   InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
 | |
|   if (DefaultsOpCodeHandle != NULL) {
 | |
|     InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
 | |
|   }
 | |
|   HiiCreateEndOpCode (OpCodeHandle);
 | |
|   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create EFI_IFR_ORDERED_LIST_OP opcode.
 | |
| 
 | |
|   If OpCodeHandle is NULL, then ASSERT().
 | |
|   If any reserved bits are set in QuestionFlags, then ASSERT().
 | |
|   If any reserved bits are set in OrderedListFlags, then ASSERT().
 | |
| 
 | |
|   @param[in]  OpCodeHandle          Handle to the buffer of opcodes.
 | |
|   @param[in]  QuestionId            Question ID
 | |
|   @param[in]  VarStoreId            Storage ID
 | |
|   @param[in]  VarOffset             Offset in Storage
 | |
|   @param[in]  Prompt                String ID for Prompt
 | |
|   @param[in]  Help                  String ID for Help
 | |
|   @param[in]  QuestionFlags         Flags in Question Header
 | |
|   @param[in]  OrderedListFlags      Flags for ordered list opcode
 | |
|   @param[in]  DataType              Type for option value
 | |
|   @param[in]  MaxContainers         Maximum count for options in this ordered list
 | |
|   @param[in]  OptionsOpCodeHandle   Handle for a buffer of ONE_OF_OPTION opcodes.
 | |
|   @param[in]  DefaultsOpCodeHandle  Handle for a buffer of DEFAULT opcodes.  This
 | |
|                                     is an optional parameter that may be NULL.
 | |
| 
 | |
|   @retval NULL   There is not enough space left in Buffer to add the opcode.
 | |
|   @retval Other  A pointer to the created opcode.
 | |
| 
 | |
| **/
 | |
| UINT8 *
 | |
| EFIAPI
 | |
| HiiCreateOrderedListOpCode (
 | |
|   IN VOID             *OpCodeHandle,
 | |
|   IN EFI_QUESTION_ID  QuestionId,
 | |
|   IN EFI_VARSTORE_ID  VarStoreId,
 | |
|   IN UINT16           VarOffset,
 | |
|   IN EFI_STRING_ID    Prompt,
 | |
|   IN EFI_STRING_ID    Help,
 | |
|   IN UINT8            QuestionFlags,
 | |
|   IN UINT8            OrderedListFlags,
 | |
|   IN UINT8            DataType,
 | |
|   IN UINT8            MaxContainers,
 | |
|   IN VOID             *OptionsOpCodeHandle,
 | |
|   IN VOID             *DefaultsOpCodeHandle  OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_IFR_ORDERED_LIST  OpCode;
 | |
|   UINTN                 Position;
 | |
| 
 | |
|   ASSERT (OptionsOpCodeHandle != NULL);
 | |
|   ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
 | |
| 
 | |
|   ZeroMem (&OpCode, sizeof (OpCode));
 | |
|   OpCode.Question.Header.Prompt          = Prompt;
 | |
|   OpCode.Question.Header.Help            = Help;
 | |
|   OpCode.Question.QuestionId             = QuestionId;
 | |
|   OpCode.Question.VarStoreId             = VarStoreId;
 | |
|   OpCode.Question.VarStoreInfo.VarOffset = VarOffset;
 | |
|   OpCode.Question.Flags                  = QuestionFlags;
 | |
|   OpCode.MaxContainers                   = MaxContainers;
 | |
|   OpCode.Flags                           = OrderedListFlags;
 | |
| 
 | |
|   Position = InternalHiiOpCodeHandlePosition (OpCodeHandle);
 | |
|   InternalHiiCreateOpCodeExtended (OpCodeHandle, &OpCode, EFI_IFR_ORDERED_LIST_OP, sizeof (OpCode), 0, 1);
 | |
|   InternalHiiAppendOpCodes (OpCodeHandle, OptionsOpCodeHandle);
 | |
|   if (DefaultsOpCodeHandle != NULL) {
 | |
|     InternalHiiAppendOpCodes (OpCodeHandle, DefaultsOpCodeHandle);
 | |
|   }
 | |
|   HiiCreateEndOpCode (OpCodeHandle);
 | |
|   return InternalHiiOpCodeHandleBuffer (OpCodeHandle) + Position;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This is the internal worker function to update the data in
 | |
|   a form specified by FormSetGuid, FormId and Label.
 | |
| 
 | |
|   @param FormSetGuid     The optional Formset GUID.
 | |
|   @param FormId          The Form ID.
 | |
|   @param Package         The package header.
 | |
| 
 | |
|   @param TempPacakge     The resultant package.
 | |
| 
 | |
|   @retval EFI_SUCCESS    The function completes successfully.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| InternalHiiUpdateFormPackageData (
 | |
|   IN  EFI_GUID               *FormSetGuid, OPTIONAL
 | |
|   IN  EFI_FORM_ID            FormId,
 | |
|   IN  EFI_HII_PACKAGE_HEADER *Package,
 | |
|   IN  HII_LIB_OPCODE_BUFFER  *OpCodeBufferStart,
 | |
|   IN  HII_LIB_OPCODE_BUFFER  *OpCodeBufferEnd,    OPTIONAL
 | |
|   OUT EFI_HII_PACKAGE_HEADER *TempPackage
 | |
|   )
 | |
| {
 | |
|   UINTN                     AddSize;
 | |
|   UINT8                     *BufferPos;
 | |
|   EFI_HII_PACKAGE_HEADER    PackageHeader;
 | |
|   UINTN                     Offset;
 | |
|   EFI_IFR_OP_HEADER         *IfrOpHdr;
 | |
|   EFI_IFR_OP_HEADER         *UpdateIfrOpHdr;
 | |
|   BOOLEAN                   GetFormSet;
 | |
|   BOOLEAN                   GetForm;
 | |
|   BOOLEAN                   Updated;
 | |
|   UINTN                     UpdatePackageLength;
 | |
| 
 | |
|   CopyMem (TempPackage, Package, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
|   UpdatePackageLength = sizeof (EFI_HII_PACKAGE_HEADER);
 | |
|   BufferPos           = (UINT8 *) (TempPackage + 1);
 | |
| 
 | |
|   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;
 | |
|     UpdatePackageLength += IfrOpHdr->Length;
 | |
|     
 | |
|     //
 | |
|     // Find the matched FormSet and Form
 | |
|     //
 | |
|     if ((IfrOpHdr->OpCode == EFI_IFR_FORM_SET_OP) && (FormSetGuid != NULL)) {
 | |
|       if (CompareGuid((GUID *)(VOID *)&((EFI_IFR_FORM_SET *) IfrOpHdr)->Guid, FormSetGuid)) {
 | |
|         GetFormSet = TRUE;
 | |
|       } else {
 | |
|         GetFormSet = FALSE;
 | |
|       }
 | |
|     } else if (IfrOpHdr->OpCode == EFI_IFR_FORM_OP) {
 | |
|       if (CompareMem (&((EFI_IFR_FORM *) IfrOpHdr)->FormId, &FormId, sizeof (EFI_FORM_ID)) == 0) {
 | |
|         GetForm = TRUE;
 | |
|       } else {
 | |
|         GetForm = FALSE;
 | |
|       }
 | |
|     }
 | |
|     
 | |
|     //
 | |
|     // The matched Form is found, and Update data in this form
 | |
|     //
 | |
|     if (GetFormSet && GetForm) {
 | |
|       UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer;
 | |
|       if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
 | |
|           (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
 | |
|         //
 | |
|         // Remove the original data when End OpCode buffer exist.
 | |
|         //
 | |
|         if (OpCodeBufferEnd != NULL) {
 | |
|           Offset        += IfrOpHdr->Length;
 | |
|           IfrOpHdr       = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
 | |
|           UpdateIfrOpHdr = (EFI_IFR_OP_HEADER *) OpCodeBufferEnd->Buffer;
 | |
|           while (Offset < PackageHeader.Length) {
 | |
|             //
 | |
|             // Search the matched end opcode
 | |
|             //
 | |
|             if ((UpdateIfrOpHdr->Length == IfrOpHdr->Length) && \
 | |
|                 (CompareMem (IfrOpHdr, UpdateIfrOpHdr, UpdateIfrOpHdr->Length) == 0)) {
 | |
|               break;
 | |
|             }
 | |
|             //
 | |
|             // Go to the next Op-Code
 | |
|             //
 | |
|             Offset        += IfrOpHdr->Length;
 | |
|             IfrOpHdr       = (EFI_IFR_OP_HEADER *) ((UINT8 *) (IfrOpHdr) + IfrOpHdr->Length);
 | |
|           }
 | |
|           
 | |
|           if (Offset >= PackageHeader.Length) {
 | |
|             //
 | |
|             // The end opcode is not found.
 | |
|             //
 | |
|             return EFI_NOT_FOUND;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Insert the updated data
 | |
|         //
 | |
|         AddSize = ((EFI_IFR_OP_HEADER *) OpCodeBufferStart->Buffer)->Length;
 | |
|         CopyMem (BufferPos, OpCodeBufferStart->Buffer + AddSize, OpCodeBufferStart->Position - AddSize);
 | |
|         BufferPos           += OpCodeBufferStart->Position - AddSize;
 | |
|         UpdatePackageLength += OpCodeBufferStart->Position - AddSize;
 | |
| 
 | |
|         if (OpCodeBufferEnd != NULL) {
 | |
|           //
 | |
|           // Add the end opcode
 | |
|           //
 | |
|           CopyMem (BufferPos, IfrOpHdr, IfrOpHdr->Length);
 | |
|           BufferPos           += IfrOpHdr->Length;
 | |
|           UpdatePackageLength += IfrOpHdr->Length;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Copy the left package data.
 | |
|         //
 | |
|         Offset += IfrOpHdr->Length;
 | |
|         CopyMem (BufferPos, (UINT8 *) Package + Offset, PackageHeader.Length - Offset);
 | |
|         UpdatePackageLength += PackageHeader.Length - Offset;
 | |
| 
 | |
|         //
 | |
|         // Set update flag
 | |
|         //
 | |
|         Updated = TRUE;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Go to the next Op-Code
 | |
|     //
 | |
|     Offset   += IfrOpHdr->Length;
 | |
|     IfrOpHdr = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (IfrOpHdr) + IfrOpHdr->Length);
 | |
|   }
 | |
|   
 | |
|   if (!Updated) {
 | |
|     //
 | |
|     // The updated opcode buffer is not found.
 | |
|     //
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
|   //
 | |
|   // Update the package length.
 | |
|   //
 | |
|   PackageHeader.Length = (UINT32) UpdatePackageLength;
 | |
|   CopyMem (TempPackage, &PackageHeader, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function updates a form that has previously been registered with the HII 
 | |
|   Database.  This function will perform at most one update operation.
 | |
|     
 | |
|   The form to update is specified by Handle, FormSetGuid, and FormId.  Binary 
 | |
|   comparisons of IFR opcodes are performed from the beginning of the form being 
 | |
|   updated until an IFR opcode is found that exactly matches the first IFR opcode 
 | |
|   specifed by StartOpCodeHandle.  The following rules are used to determine if
 | |
|   an insert, replace, or delete operation is performed.
 | |
|   
 | |
|   1) If no matches are found, then NULL is returned.  
 | |
|   2) If a match is found, and EndOpCodeHandle is NULL, then all of the IFR opcodes
 | |
|      from StartOpcodeHandle except the first opcode are inserted immediately after 
 | |
|      the matching IFR opcode in the form beng updated.
 | |
|   3) If a match is found, and EndOpCodeHandle is not NULL, then a search is made 
 | |
|      from the matching IFR opcode until an IFR opcode exatly matches the first 
 | |
|      IFR opcode specified by EndOpCodeHandle.  If no match is found for the first
 | |
|      IFR opcode specified by EndOpCodeHandle, then NULL is returned.  If a match
 | |
|      is found, then all of the IFR opcodes between the start match and the end 
 | |
|      match are deleted from the form being updated and all of the IFR opcodes
 | |
|      from StartOpcodeHandle except the first opcode are inserted immediately after 
 | |
|      the matching start IFR opcode.  If StartOpCcodeHandle only contains one
 | |
|      IFR instruction, then the result of ths operation will delete all of the IFR
 | |
|      opcodes between the start end matches.
 | |
| 
 | |
|   If HiiHandle is NULL, then ASSERT().
 | |
|   If StartOpCodeHandle is NULL, then ASSERT().
 | |
| 
 | |
|   @param[in]  HiiHandle          The HII Handle of the form to update.
 | |
|   @param[in]  FormSetGuid        The Formset GUID of the form to update.  This
 | |
|                                  is an optional parameter that may be NULL.
 | |
|                                  If it is NULL, all FormSet will be updated.
 | |
|   @param[in]  FormId             The ID of the form to update.
 | |
|   @param[in]  StartOpCodeHandle  An OpCode Handle that contains the set of IFR 
 | |
|                                  opcodes to be inserted or replaced in the form.
 | |
|                                  The first IFR instruction in StartOpCodeHandle 
 | |
|                                  is used to find matching IFR opcode in the 
 | |
|                                  form. 
 | |
|   @param[in]  EndOpCodeHandle    An OpCcode Handle that contains the IFR opcode
 | |
|                                  that marks the end of a replace operation in
 | |
|                                  the form.  This is an optional parameter that
 | |
|                                  may be NULL.  If it is NULL, then an the IFR
 | |
|                                  opcodes specified by StartOpCodeHandle are 
 | |
|                                  inserted into the form.
 | |
|   
 | |
|   @retval EFI_OUT_OF_RESOURCES   No enough memory resource is allocated.
 | |
|   @retval EFI_NOT_FOUND          The following cases will return EFI_NOT_FOUND.
 | |
|                                  1) The form specified by HiiHandle, FormSetGuid, 
 | |
|                                  and FormId could not be found in the HII Database.
 | |
|                                  2) No IFR opcodes in the target form match the first
 | |
|                                  IFR opcode in StartOpCodeHandle.
 | |
|                                  3) EndOpCOde is not NULL, and no IFR opcodes in the 
 | |
|                                  target form following a matching start opcode match 
 | |
|                                  the first IFR opcode in EndOpCodeHandle.
 | |
|   @retval EFI_SUCCESS            The matched form is updated by StartOpcode.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| HiiUpdateForm (
 | |
|   IN EFI_HII_HANDLE  HiiHandle,           
 | |
|   IN EFI_GUID        *FormSetGuid,        OPTIONAL
 | |
|   IN EFI_FORM_ID     FormId,
 | |
|   IN VOID            *StartOpcodeHandle,
 | |
|   IN VOID            *EndOpcodeHandle     OPTIONAL
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                   Status;
 | |
|   EFI_HII_PACKAGE_LIST_HEADER  *HiiPackageList;
 | |
|   UINT32                       PackageListLength;  
 | |
|   UINT32                       Offset;
 | |
|   EFI_HII_PACKAGE_LIST_HEADER  *UpdatePackageList;
 | |
|   UINTN                        BufferSize;
 | |
|   UINT8                        *UpdateBufferPos;
 | |
|   EFI_HII_PACKAGE_HEADER       *Package;
 | |
|   EFI_HII_PACKAGE_HEADER       *TempPacakge;
 | |
|   EFI_HII_PACKAGE_HEADER       PackageHeader;
 | |
|   BOOLEAN                      Updated;
 | |
|   HII_LIB_OPCODE_BUFFER        *OpCodeBufferStart;
 | |
|   HII_LIB_OPCODE_BUFFER        *OpCodeBufferEnd;
 | |
|   
 | |
|   //
 | |
|   // Input update data can't be NULL.
 | |
|   //
 | |
|   ASSERT (HiiHandle != NULL);
 | |
|   ASSERT (StartOpcodeHandle != NULL);
 | |
|   UpdatePackageList = NULL;
 | |
|   TempPacakge       = NULL;
 | |
|   HiiPackageList    = NULL;
 | |
|   
 | |
|   //
 | |
|   // Restrive buffer data from Opcode Handle
 | |
|   //
 | |
|   OpCodeBufferStart = (HII_LIB_OPCODE_BUFFER *) StartOpcodeHandle;
 | |
|   OpCodeBufferEnd   = (HII_LIB_OPCODE_BUFFER *) EndOpcodeHandle;
 | |
|   
 | |
|   //
 | |
|   // Get the orginal package list
 | |
|   //
 | |
|   BufferSize = 0;
 | |
|   HiiPackageList   = NULL;
 | |
|   Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
 | |
|   //
 | |
|   // The return status should always be EFI_BUFFER_TOO_SMALL as input buffer's size is 0.
 | |
|   //
 | |
|   if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   HiiPackageList = AllocatePool (BufferSize);
 | |
|   if (HiiPackageList == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Finish;
 | |
|   }
 | |
| 
 | |
|   Status = gHiiDatabase->ExportPackageLists (gHiiDatabase, HiiHandle, &BufferSize, HiiPackageList);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Finish;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Calculate and allocate space for retrieval of IFR data
 | |
|   //
 | |
|   BufferSize += OpCodeBufferStart->Position;
 | |
|   UpdatePackageList = AllocateZeroPool (BufferSize);
 | |
|   if (UpdatePackageList == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Finish;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Allocate temp buffer to store the temp updated package buffer
 | |
|   //
 | |
|   TempPacakge = AllocateZeroPool (BufferSize);
 | |
|   if (TempPacakge == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Finish;
 | |
|   }
 | |
| 
 | |
|   UpdateBufferPos = (UINT8 *) UpdatePackageList;
 | |
| 
 | |
|   //
 | |
|   // Copy the package list header
 | |
|   //
 | |
|   CopyMem (UpdateBufferPos, HiiPackageList, sizeof (EFI_HII_PACKAGE_LIST_HEADER));
 | |
|   UpdateBufferPos += sizeof (EFI_HII_PACKAGE_LIST_HEADER);
 | |
|   
 | |
|   //
 | |
|   // Go through each package to find the matched pacakge and update one by one
 | |
|   //
 | |
|   Updated = FALSE;
 | |
|   Offset  = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
 | |
|   PackageListLength = ReadUnaligned32 (&HiiPackageList->PackageLength);
 | |
|   while (Offset < PackageListLength) {
 | |
|     Package = (EFI_HII_PACKAGE_HEADER *) (((UINT8 *) HiiPackageList) + Offset);
 | |
|     CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
|     Offset += Package->Length;
 | |
| 
 | |
|     if (Package->Type == EFI_HII_PACKAGE_FORMS) {
 | |
|       //
 | |
|       // Check this package is the matched package.
 | |
|       //
 | |
|       Status = InternalHiiUpdateFormPackageData (FormSetGuid, FormId, Package, OpCodeBufferStart, OpCodeBufferEnd, TempPacakge);
 | |
|       //
 | |
|       // The matched package is found. Its pacakge buffer will be updated by the input new data.
 | |
|       //
 | |
|       if (!EFI_ERROR(Status)) {
 | |
|         //
 | |
|         // Set Update Flag
 | |
|         //        
 | |
|         Updated = TRUE;
 | |
|         //
 | |
|         // Add updated package buffer
 | |
|         //
 | |
|         Package = TempPacakge;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Add pacakge buffer
 | |
|     //
 | |
|     CopyMem (&PackageHeader, Package, sizeof (EFI_HII_PACKAGE_HEADER));
 | |
|     CopyMem (UpdateBufferPos, Package, PackageHeader.Length);
 | |
|     UpdateBufferPos += PackageHeader.Length;
 | |
|   }
 | |
|   
 | |
|   if (Updated) {
 | |
|     //
 | |
|     // Update package list length
 | |
|     //
 | |
|     BufferSize = UpdateBufferPos - (UINT8 *) UpdatePackageList;
 | |
|     WriteUnaligned32 (&UpdatePackageList->PackageLength, (UINT32) BufferSize);
 | |
|     
 | |
|     //
 | |
|     // Update Pacakge to show form
 | |
|     //
 | |
|     Status = gHiiDatabase->UpdatePackageList (gHiiDatabase, HiiHandle, UpdatePackageList);
 | |
|   } else {
 | |
|     //
 | |
|     // Not matched form is found and updated.
 | |
|     //
 | |
|     Status = EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
| Finish:
 | |
|   if (HiiPackageList != NULL) {
 | |
|     FreePool (HiiPackageList);
 | |
|   }
 | |
|   
 | |
|   if (UpdatePackageList != NULL) {
 | |
|     FreePool (UpdatePackageList);
 | |
|   }
 | |
|   
 | |
|   if (TempPacakge != NULL) {
 | |
|     FreePool (TempPacakge);
 | |
|   }
 | |
| 
 | |
|   return Status; 
 | |
| }
 |