2. Update API ForceClearPK() to UserPhysicalPresent() in PlatformSecureLib. 2. Update SecureBootConfigDxe driver and AuthVariable driver to support Custom Secure Boot Mode feature. 3. Fix some bugs in AuthVariable driver. Signed-off-by: sfu5 Reviewed-by: tye Reviewed-by: gdong1 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13144 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1228 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1228 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Internal file explorer functions for SecureBoot configuration module.
 | |
| 
 | |
| Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
 | |
| 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 "SecureBootConfigImpl.h"
 | |
| 
 | |
| ///
 | |
| /// File system selection menu
 | |
| ///
 | |
| SECUREBOOT_MENU_OPTION      FsOptionMenu = {
 | |
|   SECUREBOOT_MENU_OPTION_SIGNATURE,
 | |
|   {NULL},
 | |
|   0
 | |
| };
 | |
| 
 | |
| ///
 | |
| /// Files and sub-directories in current directory menu
 | |
| ///
 | |
| SECUREBOOT_MENU_OPTION      DirectoryMenu = {
 | |
|   SECUREBOOT_MENU_OPTION_SIGNATURE,
 | |
|   {NULL},
 | |
|   0
 | |
| };
 | |
| 
 | |
| VOID                  *mStartOpCodeHandle = NULL;
 | |
| VOID                  *mEndOpCodeHandle = NULL;
 | |
| EFI_IFR_GUID_LABEL    *mStartLabel = NULL;
 | |
| EFI_IFR_GUID_LABEL    *mEndLabel = NULL;
 | |
| 
 | |
| /**
 | |
|   Duplicate a string.
 | |
| 
 | |
|   @param[in]    Src             The source string.
 | |
| 
 | |
|   @return      A new string which is duplicated copy of the source,
 | |
|                or NULL if there is not enough memory.
 | |
| 
 | |
| **/
 | |
| CHAR16 *
 | |
| StrDuplicate (
 | |
|   IN CHAR16   *Src
 | |
|   )
 | |
| {
 | |
|   CHAR16  *Dest;
 | |
|   UINTN   Size;
 | |
| 
 | |
|   Size  = StrSize (Src);
 | |
|   Dest  = AllocateZeroPool (Size);
 | |
|   ASSERT (Dest != NULL);
 | |
|   if (Dest != NULL) {
 | |
|     CopyMem (Dest, Src, Size);
 | |
|   }
 | |
| 
 | |
|   return Dest;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Helper function called as part of the code needed to allocate 
 | |
|   the proper sized buffer for various EFI interfaces.
 | |
| 
 | |
|   @param[in, out]   Status          Current status
 | |
|   @param[in, out]   Buffer          Current allocated buffer, or NULL
 | |
|   @param[in]        BufferSize      Current buffer size needed
 | |
| 
 | |
|   @retval  TRUE         If the buffer was reallocated and the caller
 | |
|                         should try the API again.
 | |
|   @retval  FALSE        The caller should not call this function again.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| GrowBuffer (
 | |
|   IN OUT EFI_STATUS   *Status,
 | |
|   IN OUT VOID         **Buffer,
 | |
|   IN UINTN            BufferSize
 | |
|   )
 | |
| {
 | |
|   BOOLEAN TryAgain;
 | |
| 
 | |
|   //
 | |
|   // If this is an initial request, buffer will be null with a new buffer size
 | |
|   //
 | |
|   if ((*Buffer == NULL) && (BufferSize != 0)) {
 | |
|     *Status = EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
|   //
 | |
|   // If the status code is "buffer too small", resize the buffer
 | |
|   //
 | |
|   TryAgain = FALSE;
 | |
|   if (*Status == EFI_BUFFER_TOO_SMALL) {
 | |
| 
 | |
|     if (*Buffer != NULL) {
 | |
|       FreePool (*Buffer);
 | |
|     }
 | |
| 
 | |
|     *Buffer = AllocateZeroPool (BufferSize);
 | |
| 
 | |
|     if (*Buffer != NULL) {
 | |
|       TryAgain = TRUE;
 | |
|     } else {
 | |
|       *Status = EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // If there's an error, free the buffer
 | |
|   //
 | |
|   if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {
 | |
|     FreePool (*Buffer);
 | |
|     *Buffer = NULL;
 | |
|   }
 | |
| 
 | |
|   return TryAgain;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Append file name to existing file name, and allocate a new buffer 
 | |
|   to hold the appended result.
 | |
| 
 | |
|   @param[in]  Str1  The existing file name
 | |
|   @param[in]  Str2  The file name to be appended
 | |
| 
 | |
|   @return      A new string with appended result.
 | |
| 
 | |
| **/
 | |
| CHAR16 *
 | |
| AppendFileName (
 | |
|   IN  CHAR16  *Str1,
 | |
|   IN  CHAR16  *Str2
 | |
|   )
 | |
| {
 | |
|   UINTN   Size1;
 | |
|   UINTN   Size2;
 | |
|   CHAR16  *Str;
 | |
|   CHAR16  *TmpStr;
 | |
|   CHAR16  *Ptr;
 | |
|   CHAR16  *LastSlash;
 | |
| 
 | |
|   Size1 = StrSize (Str1);
 | |
|   Size2 = StrSize (Str2);
 | |
|   Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
 | |
|   ASSERT (Str != NULL);
 | |
| 
 | |
|   TmpStr = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); 
 | |
|   ASSERT (TmpStr != NULL);
 | |
| 
 | |
|   StrCat (Str, Str1);
 | |
|   if (!((*Str == '\\') && (*(Str + 1) == 0))) {
 | |
|     StrCat (Str, L"\\");
 | |
|   }
 | |
| 
 | |
|   StrCat (Str, Str2);
 | |
| 
 | |
|   Ptr       = Str;
 | |
|   LastSlash = Str;
 | |
|   while (*Ptr != 0) {
 | |
|     if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {
 | |
|       //
 | |
|       // Convert "\Name\..\" to "\"
 | |
|       // DO NOT convert the .. if it is at the end of the string. This will
 | |
|       // break the .. behavior in changing directories.
 | |
|       //
 | |
| 
 | |
|       //
 | |
|       // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings 
 | |
|       // that overlap.
 | |
|       //
 | |
|       StrCpy (TmpStr, Ptr + 3);
 | |
|       StrCpy (LastSlash, TmpStr);
 | |
|       Ptr = LastSlash;
 | |
|     } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {
 | |
|       //
 | |
|       // Convert a "\.\" to a "\"
 | |
|       //
 | |
| 
 | |
|       //
 | |
|       // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings 
 | |
|       // that overlap.
 | |
|       //
 | |
|       StrCpy (TmpStr, Ptr + 2);
 | |
|       StrCpy (Ptr, TmpStr);
 | |
|       Ptr = LastSlash;
 | |
|     } else if (*Ptr == '\\') {
 | |
|       LastSlash = Ptr;
 | |
|     }
 | |
| 
 | |
|     Ptr++;
 | |
|   }
 | |
| 
 | |
|   FreePool (TmpStr);
 | |
|   
 | |
|   return Str;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create a SECUREBOOT_MENU_ENTRY, and stores it in a buffer allocated from the pool.
 | |
| 
 | |
|   @return           The new menu entry or NULL of error happens.
 | |
| 
 | |
| **/
 | |
| SECUREBOOT_MENU_ENTRY *
 | |
| CreateMenuEntry (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   SECUREBOOT_MENU_ENTRY *MenuEntry;
 | |
|   UINTN                 ContextSize;
 | |
| 
 | |
|   //
 | |
|   // Create new menu entry
 | |
|   //
 | |
|   MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY));
 | |
|   if (MenuEntry == NULL) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   ContextSize = sizeof (SECUREBOOT_FILE_CONTEXT);
 | |
|   MenuEntry->FileContext = AllocateZeroPool (ContextSize);
 | |
|   if (MenuEntry->FileContext == NULL) {
 | |
|     FreePool (MenuEntry);
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   MenuEntry->Signature = SECUREBOOT_MENU_ENTRY_SIGNATURE;
 | |
| 
 | |
|   return MenuEntry;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get Menu Entry from the Menu Entry List by MenuNumber.
 | |
| 
 | |
|   If MenuNumber is great or equal to the number of Menu
 | |
|   Entry in the list, then ASSERT.
 | |
| 
 | |
|   @param[in]  MenuOption      The Menu Entry List to read the menu entry.
 | |
|   @param[in]  MenuNumber      The index of Menu Entry.
 | |
| 
 | |
|   @return     The Menu Entry.
 | |
| 
 | |
| **/
 | |
| SECUREBOOT_MENU_ENTRY *
 | |
| GetMenuEntry (
 | |
|   IN  SECUREBOOT_MENU_OPTION      *MenuOption,
 | |
|   IN  UINTN                       MenuNumber
 | |
|   )
 | |
| {
 | |
|   SECUREBOOT_MENU_ENTRY       *NewMenuEntry;
 | |
|   UINTN                       Index;
 | |
|   LIST_ENTRY                  *List;
 | |
| 
 | |
|   ASSERT (MenuNumber < MenuOption->MenuNumber);
 | |
| 
 | |
|   List = MenuOption->Head.ForwardLink;
 | |
|   for (Index = 0; Index < MenuNumber; Index++) {
 | |
|     List = List->ForwardLink;
 | |
|   }
 | |
| 
 | |
|   NewMenuEntry = CR (List, SECUREBOOT_MENU_ENTRY, Link, SECUREBOOT_MENU_ENTRY_SIGNATURE);
 | |
| 
 | |
|   return NewMenuEntry;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create string tokens for a menu from its help strings and display strings.
 | |
| 
 | |
|   @param[in] HiiHandle          Hii Handle of the package to be updated.
 | |
|   @param[in] MenuOption         The Menu whose string tokens need to be created.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| CreateMenuStringToken (
 | |
|   IN EFI_HII_HANDLE                          HiiHandle,
 | |
|   IN SECUREBOOT_MENU_OPTION                  *MenuOption
 | |
|   )
 | |
| {
 | |
|   SECUREBOOT_MENU_ENTRY *NewMenuEntry;
 | |
|   UINTN         Index;
 | |
| 
 | |
|   for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
 | |
|     NewMenuEntry = GetMenuEntry (MenuOption, Index);
 | |
| 
 | |
|     NewMenuEntry->DisplayStringToken = HiiSetString (
 | |
|                                          HiiHandle,
 | |
|                                          0,
 | |
|                                          NewMenuEntry->DisplayString,
 | |
|                                          NULL
 | |
|                                          );
 | |
| 
 | |
|     if (NewMenuEntry->HelpString == NULL) {
 | |
|       NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken;
 | |
|     } else {
 | |
|       NewMenuEntry->HelpStringToken = HiiSetString (
 | |
|                                         HiiHandle,
 | |
|                                         0,
 | |
|                                         NewMenuEntry->HelpString,
 | |
|                                         NULL
 | |
|                                         );
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Free up all resources allocated for a SECUREBOOT_MENU_ENTRY.
 | |
| 
 | |
|   @param[in, out]  MenuEntry   A pointer to SECUREBOOT_MENU_ENTRY.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| DestroyMenuEntry (
 | |
|   IN OUT SECUREBOOT_MENU_ENTRY         *MenuEntry
 | |
|   )
 | |
| {
 | |
|   SECUREBOOT_FILE_CONTEXT           *FileContext;
 | |
| 
 | |
| 
 | |
|   FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;
 | |
| 
 | |
|   if (!FileContext->IsRoot) {
 | |
|     FreePool (FileContext->DevicePath);
 | |
|   } else {
 | |
|     if (FileContext->FHandle != NULL) {
 | |
|       FileContext->FHandle->Close (FileContext->FHandle);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (FileContext->FileName != NULL) {
 | |
|     FreePool (FileContext->FileName);
 | |
|   }
 | |
|   if (FileContext->Info != NULL) {
 | |
|     FreePool (FileContext->Info);
 | |
|   }
 | |
| 
 | |
|   FreePool (FileContext);
 | |
| 
 | |
|   FreePool (MenuEntry->DisplayString);
 | |
|   if (MenuEntry->HelpString != NULL) {
 | |
|     FreePool (MenuEntry->HelpString);
 | |
|   }
 | |
| 
 | |
|   FreePool (MenuEntry);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Free resources allocated in Allocate Rountine.
 | |
| 
 | |
|   @param[in, out]  MenuOption        Menu to be freed
 | |
|   
 | |
| **/
 | |
| VOID
 | |
| FreeMenu (
 | |
|   IN OUT SECUREBOOT_MENU_OPTION        *MenuOption
 | |
|   )
 | |
| {
 | |
|   SECUREBOOT_MENU_ENTRY      *MenuEntry;
 | |
|   while (!IsListEmpty (&MenuOption->Head)) {
 | |
|     MenuEntry = CR (
 | |
|                   MenuOption->Head.ForwardLink,
 | |
|                   SECUREBOOT_MENU_ENTRY,
 | |
|                   Link,
 | |
|                   SECUREBOOT_MENU_ENTRY_SIGNATURE
 | |
|                   );
 | |
|     RemoveEntryList (&MenuEntry->Link);
 | |
|     DestroyMenuEntry (MenuEntry);
 | |
|   }
 | |
|   MenuOption->MenuNumber = 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the file information from an open file descriptor, and stores it
 | |
|   in a buffer allocated from pool.
 | |
| 
 | |
|   @param[in]  FHand           File Handle.
 | |
| 
 | |
|   @return    A pointer to a buffer with file information or NULL is returned
 | |
| 
 | |
| **/
 | |
| EFI_FILE_INFO *
 | |
| FileInfo (
 | |
|   IN EFI_FILE_HANDLE      FHand
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS    Status;
 | |
|   EFI_FILE_INFO *Buffer;
 | |
|   UINTN         BufferSize;
 | |
| 
 | |
|   //
 | |
|   // Initialize for GrowBuffer loop
 | |
|   //
 | |
|   Buffer      = NULL;
 | |
|   BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;
 | |
| 
 | |
|   //
 | |
|   // Call the real function
 | |
|   //
 | |
|   while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
 | |
|     Status = FHand->GetInfo (
 | |
|                       FHand,
 | |
|                       &gEfiFileInfoGuid,
 | |
|                       &BufferSize,
 | |
|                       Buffer
 | |
|                       );
 | |
|   }
 | |
| 
 | |
|   return Buffer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function gets the file system information from an open file descriptor,
 | |
|   and stores it in a buffer allocated from pool.
 | |
| 
 | |
|   @param[in] FHand       The file handle.
 | |
| 
 | |
|   @return                A pointer to a buffer with file information.
 | |
|   @retval                NULL is returned if failed to get Vaolume Label Info.
 | |
| 
 | |
| **/
 | |
| EFI_FILE_SYSTEM_VOLUME_LABEL *
 | |
| FileSystemVolumeLabelInfo (
 | |
|   IN EFI_FILE_HANDLE      FHand
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                        Status;
 | |
|   EFI_FILE_SYSTEM_VOLUME_LABEL      *Buffer;
 | |
|   UINTN                             BufferSize;
 | |
|   //
 | |
|   // Initialize for GrowBuffer loop
 | |
|   //
 | |
|   Buffer      = NULL;
 | |
|   BufferSize  = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200;
 | |
| 
 | |
|   //
 | |
|   // Call the real function
 | |
|   //
 | |
|   while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
 | |
|     Status = FHand->GetInfo (
 | |
|                       FHand,
 | |
|                       &gEfiFileSystemVolumeLabelInfoIdGuid,
 | |
|                       &BufferSize,
 | |
|                       Buffer
 | |
|                       );
 | |
|   }
 | |
| 
 | |
|   return Buffer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function will open a file or directory referenced by DevicePath.
 | |
| 
 | |
|   This function opens a file with the open mode according to the file path. The
 | |
|   Attributes is valid only for EFI_FILE_MODE_CREATE.
 | |
| 
 | |
|   @param[in, out]  FilePath        On input, the device path to the file.  
 | |
|                                    On output, the remaining device path.
 | |
|   @param[out]      FileHandle      Pointer to the file handle.
 | |
|   @param[in]       OpenMode        The mode to open the file with.
 | |
|   @param[in]       Attributes      The file's file attributes.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The information was set.
 | |
|   @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid value.
 | |
|   @retval EFI_UNSUPPORTED          Could not open the file path.
 | |
|   @retval EFI_NOT_FOUND            The specified file could not be found on the
 | |
|                                    device or the file system could not be found on
 | |
|                                    the device.
 | |
|   @retval EFI_NO_MEDIA             The device has no medium.
 | |
|   @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the
 | |
|                                    medium is no longer supported.
 | |
|   @retval EFI_DEVICE_ERROR         The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED     The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED      The file or medium is write protected.
 | |
|   @retval EFI_ACCESS_DENIED        The file was opened read only.
 | |
|   @retval EFI_OUT_OF_RESOURCES     Not enough resources were available to open the
 | |
|                                    file.
 | |
|   @retval EFI_VOLUME_FULL          The volume is full.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| OpenFileByDevicePath(
 | |
|   IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,
 | |
|   OUT EFI_FILE_HANDLE                 *FileHandle,
 | |
|   IN UINT64                           OpenMode,
 | |
|   IN UINT64                           Attributes
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
 | |
|   EFI_FILE_PROTOCOL               *Handle1;
 | |
|   EFI_FILE_PROTOCOL               *Handle2;
 | |
|   EFI_HANDLE                      DeviceHandle; 
 | |
| 
 | |
|   if ((FilePath == NULL || FileHandle == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->LocateDevicePath (
 | |
|                   &gEfiSimpleFileSystemProtocolGuid,
 | |
|                   FilePath,
 | |
|                   &DeviceHandle
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->OpenProtocol(
 | |
|                   DeviceHandle,
 | |
|                   &gEfiSimpleFileSystemProtocolGuid,
 | |
|                   (VOID**)&EfiSimpleFileSystemProtocol,
 | |
|                   gImageHandle,
 | |
|                   NULL,
 | |
|                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FileHandle = NULL;
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // go down directories one node at a time.
 | |
|   //
 | |
|   while (!IsDevicePathEnd (*FilePath)) {
 | |
|     //
 | |
|     // For file system access each node should be a file path component
 | |
|     //
 | |
|     if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
 | |
|         DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
 | |
|        ) {
 | |
|       FileHandle = NULL;
 | |
|       return (EFI_INVALID_PARAMETER);
 | |
|     }
 | |
|     //
 | |
|     // Open this file path node
 | |
|     //
 | |
|     Handle2  = Handle1;
 | |
|     Handle1 = NULL;
 | |
| 
 | |
|     //
 | |
|     // Try to test opening an existing file
 | |
|     //
 | |
|     Status = Handle2->Open (
 | |
|                           Handle2,
 | |
|                           &Handle1,
 | |
|                           ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
 | |
|                           OpenMode &~EFI_FILE_MODE_CREATE,
 | |
|                           0
 | |
|                          );
 | |
| 
 | |
|     //
 | |
|     // see if the error was that it needs to be created
 | |
|     //
 | |
|     if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
 | |
|       Status = Handle2->Open (
 | |
|                             Handle2,
 | |
|                             &Handle1,
 | |
|                             ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
 | |
|                             OpenMode,
 | |
|                             Attributes
 | |
|                            );
 | |
|     }
 | |
|     //
 | |
|     // Close the last node
 | |
|     //
 | |
|     Handle2->Close (Handle2);
 | |
| 
 | |
|     if (EFI_ERROR(Status)) {
 | |
|       return (Status);
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Get the next node
 | |
|     //
 | |
|     *FilePath = NextDevicePathNode (*FilePath);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
 | |
|   //
 | |
|   *FileHandle = (VOID*)Handle1;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function opens and returns a file handle to the root directory of a volume.
 | |
| 
 | |
|   @param[in]   DeviceHandle    A handle for a device
 | |
| 
 | |
|   @return      A valid file handle or NULL if error happens.
 | |
| 
 | |
| **/
 | |
| EFI_FILE_HANDLE
 | |
| OpenRoot (
 | |
|   IN EFI_HANDLE                   DeviceHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
 | |
|   EFI_FILE_HANDLE                 File;
 | |
| 
 | |
|   File = NULL;
 | |
| 
 | |
|   //
 | |
|   // File the file system interface to the device
 | |
|   //
 | |
|   Status = gBS->HandleProtocol (
 | |
|                   DeviceHandle,
 | |
|                   &gEfiSimpleFileSystemProtocolGuid,
 | |
|                   (VOID *) &Volume
 | |
|                   );
 | |
| 
 | |
|   //
 | |
|   // Open the root directory of the volume
 | |
|   //
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     Status = Volume->OpenVolume (
 | |
|                       Volume,
 | |
|                       &File
 | |
|                       );
 | |
|   }
 | |
|   //
 | |
|   // Done
 | |
|   //
 | |
|   return EFI_ERROR (Status) ? NULL : File;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function builds the FsOptionMenu list which records all
 | |
|   available file system in the system. They include all instances
 | |
|   of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM
 | |
|   and all type of legacy boot device.
 | |
| 
 | |
|   @retval  EFI_SUCCESS             Success find the file system
 | |
|   @retval  EFI_OUT_OF_RESOURCES    Can not create menu entry
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| FindFileSystem (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   UINTN                     NoBlkIoHandles;
 | |
|   UINTN                     NoSimpleFsHandles;
 | |
|   UINTN                     NoLoadFileHandles;
 | |
|   EFI_HANDLE                *BlkIoHandle;
 | |
|   EFI_HANDLE                *SimpleFsHandle;
 | |
|   UINT16                    *VolumeLabel;
 | |
|   EFI_BLOCK_IO_PROTOCOL     *BlkIo;
 | |
|   UINTN                     Index;
 | |
|   EFI_STATUS                Status;
 | |
|   SECUREBOOT_MENU_ENTRY     *MenuEntry;
 | |
|   SECUREBOOT_FILE_CONTEXT   *FileContext;
 | |
|   UINT16                    *TempStr;
 | |
|   UINTN                     OptionNumber;
 | |
|   VOID                      *Buffer;
 | |
| 
 | |
|   BOOLEAN                   RemovableMedia;
 | |
| 
 | |
| 
 | |
|   NoSimpleFsHandles = 0;
 | |
|   NoLoadFileHandles = 0;
 | |
|   OptionNumber      = 0;
 | |
|   InitializeListHead (&FsOptionMenu.Head);
 | |
| 
 | |
|   //
 | |
|   // Locate Handles that support BlockIo protocol
 | |
|   //
 | |
|   Status = gBS->LocateHandleBuffer (
 | |
|                   ByProtocol,
 | |
|                   &gEfiBlockIoProtocolGuid,
 | |
|                   NULL,
 | |
|                   &NoBlkIoHandles,
 | |
|                   &BlkIoHandle
 | |
|                   );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
| 
 | |
|     for (Index = 0; Index < NoBlkIoHandles; Index++) {
 | |
|       Status = gBS->HandleProtocol (
 | |
|                       BlkIoHandle[Index],
 | |
|                       &gEfiBlockIoProtocolGuid,
 | |
|                       (VOID **) &BlkIo
 | |
|                       );
 | |
| 
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
 | |
|       //
 | |
|       if (BlkIo->Media->RemovableMedia) {
 | |
|         Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);
 | |
|         if (NULL == Buffer) {
 | |
|           FreePool (BlkIoHandle);
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
| 
 | |
|         BlkIo->ReadBlocks (
 | |
|                 BlkIo,
 | |
|                 BlkIo->Media->MediaId,
 | |
|                 0,
 | |
|                 BlkIo->Media->BlockSize,
 | |
|                 Buffer
 | |
|                 );
 | |
|         FreePool (Buffer);
 | |
|       }
 | |
|     }
 | |
|     FreePool (BlkIoHandle);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Locate Handles that support Simple File System protocol
 | |
|   //
 | |
|   Status = gBS->LocateHandleBuffer (
 | |
|                   ByProtocol,
 | |
|                   &gEfiSimpleFileSystemProtocolGuid,
 | |
|                   NULL,
 | |
|                   &NoSimpleFsHandles,
 | |
|                   &SimpleFsHandle
 | |
|                   );
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Find all the instances of the File System prototocol
 | |
|     //
 | |
|     for (Index = 0; Index < NoSimpleFsHandles; Index++) {
 | |
|       Status = gBS->HandleProtocol (
 | |
|                       SimpleFsHandle[Index],
 | |
|                       &gEfiBlockIoProtocolGuid,
 | |
|                       (VOID **) &BlkIo
 | |
|                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         //
 | |
|         // If no block IO exists assume it's NOT a removable media
 | |
|         //
 | |
|         RemovableMedia = FALSE;
 | |
|       } else {
 | |
|         //
 | |
|         // If block IO exists check to see if it's remobable media
 | |
|         //
 | |
|         RemovableMedia = BlkIo->Media->RemovableMedia;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Allocate pool for this instance.
 | |
|       //
 | |
|       MenuEntry = CreateMenuEntry ();
 | |
|       if (NULL == MenuEntry) {
 | |
|         FreePool (SimpleFsHandle);
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       FileContext = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;
 | |
| 
 | |
|       FileContext->Handle     = SimpleFsHandle[Index];
 | |
|       MenuEntry->OptionNumber = Index;
 | |
|       FileContext->FHandle    = OpenRoot (FileContext->Handle);
 | |
|       if (FileContext->FHandle == NULL) {
 | |
|         DestroyMenuEntry (MenuEntry);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));
 | |
|       FileContext->Info = FileSystemVolumeLabelInfo (FileContext->FHandle);
 | |
|       FileContext->FileName = StrDuplicate (L"\\");
 | |
|       FileContext->DevicePath = FileDevicePath (
 | |
|                                   FileContext->Handle,
 | |
|                                   FileContext->FileName
 | |
|                                   );
 | |
|       FileContext->IsDir            = TRUE;
 | |
|       FileContext->IsRoot           = TRUE;
 | |
|       FileContext->IsRemovableMedia = RemovableMedia;
 | |
|       FileContext->IsLoadFile       = FALSE;
 | |
| 
 | |
|       //
 | |
|       // Get current file system's Volume Label
 | |
|       //
 | |
|       if (FileContext->Info == NULL) {
 | |
|         VolumeLabel = L"NO FILE SYSTEM INFO";
 | |
|       } else {
 | |
|         if (FileContext->Info->VolumeLabel == NULL) {
 | |
|           VolumeLabel = L"NULL VOLUME LABEL";
 | |
|         } else {
 | |
|           VolumeLabel = FileContext->Info->VolumeLabel;
 | |
|           if (*VolumeLabel == 0x0000) {
 | |
|             VolumeLabel = L"NO VOLUME LABEL";
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       TempStr                   = MenuEntry->HelpString;
 | |
|       MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);
 | |
|       ASSERT (MenuEntry->DisplayString != NULL);
 | |
|       UnicodeSPrint (
 | |
|         MenuEntry->DisplayString,
 | |
|         MAX_CHAR,
 | |
|         L"%s, [%s]",
 | |
|         VolumeLabel,
 | |
|         TempStr
 | |
|         );
 | |
|       OptionNumber++;
 | |
|       InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (NoSimpleFsHandles != 0) {
 | |
|     FreePool (SimpleFsHandle);
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Remember how many file system options are here
 | |
|   //
 | |
|   FsOptionMenu.MenuNumber = OptionNumber;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Find files under the current directory. All files and sub-directories 
 | |
|   in current directory will be stored in DirectoryMenu for future use.
 | |
| 
 | |
|   @param[in] MenuEntry     The Menu Entry.
 | |
| 
 | |
|   @retval EFI_SUCCESS      Get files from current dir successfully.
 | |
|   @return Other            Can't get files from current dir.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| FindFiles (
 | |
|   IN SECUREBOOT_MENU_ENTRY              *MenuEntry
 | |
|   )
 | |
| {
 | |
|   EFI_FILE_HANDLE           NewDir;
 | |
|   EFI_FILE_HANDLE           Dir;
 | |
|   EFI_FILE_INFO             *DirInfo;
 | |
|   UINTN                     BufferSize;
 | |
|   UINTN                     DirBufferSize;
 | |
|   SECUREBOOT_MENU_ENTRY     *NewMenuEntry;
 | |
|   SECUREBOOT_FILE_CONTEXT   *FileContext;
 | |
|   SECUREBOOT_FILE_CONTEXT   *NewFileContext;
 | |
|   UINTN                     Pass;
 | |
|   EFI_STATUS                Status;
 | |
|   UINTN                     OptionNumber;
 | |
| 
 | |
|   FileContext   = (SECUREBOOT_FILE_CONTEXT *) MenuEntry->FileContext;
 | |
|   Dir           = FileContext->FHandle;
 | |
|   OptionNumber  = 0;
 | |
|   //
 | |
|   // Open current directory to get files from it
 | |
|   //
 | |
|   Status = Dir->Open (
 | |
|                   Dir,
 | |
|                   &NewDir,
 | |
|                   FileContext->FileName,
 | |
|                   EFI_FILE_READ_ONLY,
 | |
|                   0
 | |
|                   );
 | |
|   if (!FileContext->IsRoot) {
 | |
|     Dir->Close (Dir);
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   DirInfo = FileInfo (NewDir);
 | |
|   if (DirInfo == NULL) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   FileContext->DevicePath = FileDevicePath (
 | |
|                               FileContext->Handle,
 | |
|                               FileContext->FileName
 | |
|                               );
 | |
| 
 | |
|   DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
 | |
|   DirInfo       = AllocateZeroPool (DirBufferSize);
 | |
|   if (DirInfo == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Get all files in current directory
 | |
|   // Pass 1 to get Directories
 | |
|   // Pass 2 to get files that are EFI images
 | |
|   //
 | |
|   for (Pass = 1; Pass <= 2; Pass++) {
 | |
|     NewDir->SetPosition (NewDir, 0);
 | |
|     for (;;) {
 | |
|       BufferSize  = DirBufferSize;
 | |
|       Status      = NewDir->Read (NewDir, &BufferSize, DirInfo);
 | |
|       if (EFI_ERROR (Status) || BufferSize == 0) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||
 | |
|           ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)
 | |
|           ) {
 | |
|         //
 | |
|         // Pass 1 is for Directories
 | |
|         // Pass 2 is for file names
 | |
|         //
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       NewMenuEntry = CreateMenuEntry ();
 | |
|       if (NULL == NewMenuEntry) {
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
| 
 | |
|       NewFileContext          = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext;
 | |
|       NewFileContext->Handle  = FileContext->Handle;
 | |
|       NewFileContext->FileName = AppendFileName (
 | |
|                                   FileContext->FileName,
 | |
|                                   DirInfo->FileName
 | |
|                                   );
 | |
|       NewFileContext->FHandle = NewDir;
 | |
|       NewFileContext->DevicePath = FileDevicePath (
 | |
|                                     NewFileContext->Handle,
 | |
|                                     NewFileContext->FileName
 | |
|                                     );
 | |
|       NewMenuEntry->HelpString = NULL;
 | |
|       
 | |
|       NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);
 | |
|       if (NewFileContext->IsDir) {
 | |
|         BufferSize = StrLen (DirInfo->FileName) * 2 + 6;
 | |
|         NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);
 | |
| 
 | |
|         UnicodeSPrint (
 | |
|           NewMenuEntry->DisplayString,
 | |
|           BufferSize,
 | |
|           L"<%s>",
 | |
|           DirInfo->FileName
 | |
|           );
 | |
| 
 | |
|       } else {
 | |
|         NewMenuEntry->DisplayString = StrDuplicate (DirInfo->FileName);
 | |
|       }
 | |
| 
 | |
|       NewFileContext->IsRoot            = FALSE;
 | |
|       NewFileContext->IsLoadFile        = FALSE;
 | |
|       NewFileContext->IsRemovableMedia  = FALSE;
 | |
| 
 | |
|       NewMenuEntry->OptionNumber        = OptionNumber;
 | |
|       OptionNumber++;
 | |
|       InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   DirectoryMenu.MenuNumber = OptionNumber;
 | |
|   FreePool (DirInfo);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Refresh the global UpdateData structure.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| RefreshUpdateData (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Free current updated date
 | |
|   //  
 | |
|   if (mStartOpCodeHandle != NULL) {
 | |
|     HiiFreeOpCodeHandle (mStartOpCodeHandle);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Create new OpCode Handle
 | |
|   //
 | |
|   mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
 | |
| 
 | |
|   //
 | |
|   // Create Hii Extend Label OpCode as the start opcode
 | |
|   //
 | |
|   mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
 | |
|                                          mStartOpCodeHandle,
 | |
|                                          &gEfiIfrTianoGuid,
 | |
|                                          NULL,
 | |
|                                          sizeof (EFI_IFR_GUID_LABEL)
 | |
|                                          );
 | |
|   mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update the File Explore page.
 | |
| 
 | |
|   @param[in] HiiHandle          Hii Handle of the package to be updated.
 | |
|   @param[in] MenuOption         The Menu whose string tokens need to be updated.
 | |
|   @param[in] FeCurrentState     Current file explorer state.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| UpdateFileExplorePage (
 | |
|   IN EFI_HII_HANDLE               HiiHandle,
 | |
|   IN SECUREBOOT_MENU_OPTION       *MenuOption,
 | |
|   IN FILE_EXPLORER_STATE          FeCurrentState
 | |
|   )
 | |
| {
 | |
|   UINTN                   Index;
 | |
|   SECUREBOOT_MENU_ENTRY   *NewMenuEntry;
 | |
|   SECUREBOOT_FILE_CONTEXT *NewFileContext;
 | |
|   EFI_FORM_ID             FormId;
 | |
|   EFI_FORM_ID             FileFormId;
 | |
| 
 | |
|   if (FeCurrentState == FileExplorerStateEnrollPkFile) {
 | |
|     FormId     = SECUREBOOT_ADD_PK_FILE_FORM_ID;
 | |
|     FileFormId = FORM_FILE_EXPLORER_ID_PK;
 | |
|   } else if (FeCurrentState == FileExplorerStateEnrollKekFile) {
 | |
|     FormId     = FORMID_ENROLL_KEK_FORM;
 | |
|     FileFormId = FORM_FILE_EXPLORER_ID_KEK;
 | |
|   } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDb) {
 | |
|     FormId     = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
 | |
|     FileFormId = FORM_FILE_EXPLORER_ID_DB;
 | |
|   } else if (FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) {
 | |
|     FormId     = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
 | |
|     FileFormId = FORM_FILE_EXPLORER_ID_DBX;
 | |
|   } else {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   NewMenuEntry    = NULL;
 | |
|   NewFileContext  = NULL;
 | |
| 
 | |
|   RefreshUpdateData ();
 | |
|   mStartLabel->Number = FORM_FILE_EXPLORER_ID;
 | |
| 
 | |
|   for (Index = 0; Index < MenuOption->MenuNumber; Index++) {
 | |
|     NewMenuEntry    = GetMenuEntry (MenuOption, Index);
 | |
|     NewFileContext  = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext;
 | |
| 
 | |
|     if (NewFileContext->IsDir) {
 | |
|       //
 | |
|       // Create Text opcode for directory.
 | |
|       //
 | |
|       HiiCreateActionOpCode (
 | |
|         mStartOpCodeHandle,
 | |
|         (UINT16) (FILE_OPTION_OFFSET + Index),
 | |
|         NewMenuEntry->DisplayStringToken,
 | |
|         STRING_TOKEN (STR_NULL),
 | |
|         EFI_IFR_FLAG_CALLBACK,
 | |
|         0
 | |
|         );
 | |
|     } else {
 | |
| 
 | |
|       //
 | |
|       // Create Goto opcode for file.
 | |
|       //
 | |
|       HiiCreateGotoOpCode (
 | |
|         mStartOpCodeHandle,
 | |
|         FormId,
 | |
|         NewMenuEntry->DisplayStringToken,
 | |
|         STRING_TOKEN (STR_NULL),
 | |
|         EFI_IFR_FLAG_CALLBACK,
 | |
|         (UINT16) (FILE_OPTION_OFFSET + Index)
 | |
|         );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   HiiUpdateForm (
 | |
|     HiiHandle,
 | |
|     &gSecureBootConfigFormSetGuid,
 | |
|     FileFormId,
 | |
|     mStartOpCodeHandle, // Label FORM_FILE_EXPLORER_ID
 | |
|     mEndOpCodeHandle    // LABEL_END
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Update the file explorer page with the refreshed file system.
 | |
| 
 | |
|   @param[in] PrivateData     Module private data.
 | |
|   @param[in] KeyValue        Key value to identify the type of data to expect.
 | |
| 
 | |
|   @retval  TRUE           Inform the caller to create a callback packet to exit file explorer.
 | |
|   @retval  FALSE          Indicate that there is no need to exit file explorer.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| UpdateFileExplorer (
 | |
|   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData,
 | |
|   IN UINT16                           KeyValue
 | |
|   )
 | |
| {
 | |
|   UINT16                              FileOptionMask;
 | |
|   SECUREBOOT_MENU_ENTRY               *NewMenuEntry;
 | |
|   SECUREBOOT_FILE_CONTEXT             *NewFileContext;
 | |
|   EFI_FORM_ID                         FormId;
 | |
|   BOOLEAN                             ExitFileExplorer;
 | |
|   EFI_STATUS                          Status;
 | |
|   EFI_DEVICE_PATH_PROTOCOL            *TmpDevicePath;
 | |
| 
 | |
|   NewMenuEntry      = NULL;
 | |
|   NewFileContext    = NULL;
 | |
|   ExitFileExplorer  = FALSE;
 | |
|   FileOptionMask    = (UINT16) (FILE_OPTION_MASK & KeyValue);
 | |
| 
 | |
|   if (PrivateData->FeDisplayContext == FileExplorerDisplayUnknown) {
 | |
|     //
 | |
|     // First in, display file system.
 | |
|     //
 | |
|     FreeMenu (&FsOptionMenu);
 | |
|     FindFileSystem ();
 | |
|     
 | |
|     CreateMenuStringToken (PrivateData->HiiHandle, &FsOptionMenu);
 | |
|     UpdateFileExplorePage (PrivateData->HiiHandle, &FsOptionMenu, PrivateData->FeCurrentState);
 | |
| 
 | |
|     PrivateData->FeDisplayContext = FileExplorerDisplayFileSystem;
 | |
|   } else {
 | |
|     if (PrivateData->FeDisplayContext == FileExplorerDisplayFileSystem) {
 | |
|       NewMenuEntry = GetMenuEntry (&FsOptionMenu, FileOptionMask);
 | |
|     } else if (PrivateData->FeDisplayContext == FileExplorerDisplayDirectory) {
 | |
|       NewMenuEntry = GetMenuEntry (&DirectoryMenu, FileOptionMask);
 | |
|     }
 | |
| 
 | |
|     NewFileContext = (SECUREBOOT_FILE_CONTEXT *) NewMenuEntry->FileContext;
 | |
| 
 | |
|     if (NewFileContext->IsDir ) {
 | |
|       PrivateData->FeDisplayContext = FileExplorerDisplayDirectory;
 | |
| 
 | |
|       RemoveEntryList (&NewMenuEntry->Link);
 | |
|       FreeMenu (&DirectoryMenu);
 | |
|       Status = FindFiles (NewMenuEntry);
 | |
|        if (EFI_ERROR (Status)) {
 | |
|          ExitFileExplorer = TRUE;
 | |
|          goto OnExit;
 | |
|        }
 | |
|       CreateMenuStringToken (PrivateData->HiiHandle, &DirectoryMenu);
 | |
|       DestroyMenuEntry (NewMenuEntry);
 | |
| 
 | |
|       UpdateFileExplorePage (PrivateData->HiiHandle, &DirectoryMenu, PrivateData->FeCurrentState);
 | |
| 
 | |
|     } else {
 | |
|       if (PrivateData->FeCurrentState == FileExplorerStateEnrollPkFile) {
 | |
|         FormId = SECUREBOOT_ADD_PK_FILE_FORM_ID;
 | |
|       } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollKekFile) {
 | |
|         FormId = FORMID_ENROLL_KEK_FORM;
 | |
|       } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollSignatureFileToDb) {
 | |
|         FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB;
 | |
|       } else if (PrivateData->FeCurrentState == FileExplorerStateEnrollSignatureFileToDbx) {
 | |
|         FormId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX;
 | |
|       } else {
 | |
|         return FALSE;
 | |
|       }
 | |
| 
 | |
|       PrivateData->MenuEntry = NewMenuEntry;
 | |
|       PrivateData->FileContext->FileName = NewFileContext->FileName;
 | |
|       
 | |
|       TmpDevicePath = NewFileContext->DevicePath;
 | |
|       OpenFileByDevicePath (
 | |
|         &TmpDevicePath,
 | |
|         &PrivateData->FileContext->FHandle,
 | |
|         EFI_FILE_MODE_READ,
 | |
|         0
 | |
|         );
 | |
| 
 | |
|       //
 | |
|       // Create Subtitle op-code for the display string of the option.
 | |
|       //
 | |
|       RefreshUpdateData ();
 | |
|       mStartLabel->Number = FormId;
 | |
| 
 | |
|       HiiCreateSubTitleOpCode (
 | |
|         mStartOpCodeHandle,
 | |
|         NewMenuEntry->DisplayStringToken,
 | |
|         0,
 | |
|         0,
 | |
|         0
 | |
|         );
 | |
| 
 | |
|       HiiUpdateForm (
 | |
|         PrivateData->HiiHandle,
 | |
|         &gSecureBootConfigFormSetGuid,
 | |
|         FormId,
 | |
|         mStartOpCodeHandle, // Label FormId
 | |
|         mEndOpCodeHandle    // LABEL_END
 | |
|         );
 | |
|     }
 | |
|   }
 | |
| 
 | |
| OnExit:
 | |
|   return ExitFileExplorer;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Clean up the dynamic opcode at label and form specified by both LabelId. 
 | |
| 
 | |
|   @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.
 | |
|   @param[in] PrivateData     Module private data.
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| CleanUpPage (
 | |
|   IN UINT16                           LabelId,
 | |
|   IN SECUREBOOT_CONFIG_PRIVATE_DATA   *PrivateData
 | |
|   )
 | |
| {
 | |
|   RefreshUpdateData ();
 | |
| 
 | |
|   //
 | |
|   // Remove all op-codes from dynamic page
 | |
|   //
 | |
|   mStartLabel->Number = LabelId;
 | |
|   HiiUpdateForm (
 | |
|     PrivateData->HiiHandle,
 | |
|     &gSecureBootConfigFormSetGuid,
 | |
|     LabelId,
 | |
|     mStartOpCodeHandle, // Label LabelId
 | |
|     mEndOpCodeHandle    // LABEL_END
 | |
|     );
 | |
| }
 | |
| 
 |