git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2368 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1686 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1686 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
Copyright (c) 2006, Intel Corporation                                                         
 | 
						|
All rights reserved. This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  BootOption.c
 | 
						|
  
 | 
						|
Abstract:
 | 
						|
 | 
						|
  Provide boot option support for Application "BootMaint"
 | 
						|
 | 
						|
  Include file system navigation, system handle selection
 | 
						|
 | 
						|
  Boot option manipulation
 | 
						|
  
 | 
						|
Revision History
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include "BootMaint.h"
 | 
						|
#include "BBSsupport.h"
 | 
						|
 | 
						|
BM_MENU_ENTRY *
 | 
						|
BOpt_CreateMenuEntry (
 | 
						|
  UINTN           MenuType
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description
 | 
						|
  Create Menu Entry for future use, make all types together
 | 
						|
  in order to reduce code size
 | 
						|
 | 
						|
Arguments:
 | 
						|
  MenuType            Use this parameter to identify current
 | 
						|
                      Menu type
 | 
						|
 | 
						|
Returns:
 | 
						|
  NULL                Cannot allocate memory for current menu 
 | 
						|
                      entry
 | 
						|
  Others              A valid pointer pointing to the allocated
 | 
						|
                      memory pool for current menu entry
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  BM_MENU_ENTRY *MenuEntry;
 | 
						|
  UINTN         ContextSize;
 | 
						|
 | 
						|
  switch (MenuType) {
 | 
						|
  case BM_LOAD_CONTEXT_SELECT:
 | 
						|
    ContextSize = sizeof (BM_LOAD_CONTEXT);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_FILE_CONTEXT_SELECT:
 | 
						|
    ContextSize = sizeof (BM_FILE_CONTEXT);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_CONSOLE_CONTEXT_SELECT:
 | 
						|
    ContextSize = sizeof (BM_CONSOLE_CONTEXT);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_TERMINAL_CONTEXT_SELECT:
 | 
						|
    ContextSize = sizeof (BM_TERMINAL_CONTEXT);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_HANDLE_CONTEXT_SELECT:
 | 
						|
    ContextSize = sizeof (BM_HANDLE_CONTEXT);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_LEGACY_DEV_CONTEXT_SELECT:
 | 
						|
    ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    ContextSize = 0;
 | 
						|
    break;
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  if (0 == ContextSize) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));
 | 
						|
  if (NULL == MenuEntry) {
 | 
						|
    return MenuEntry;
 | 
						|
  }
 | 
						|
 | 
						|
  MenuEntry->VariableContext = AllocateZeroPool (ContextSize);
 | 
						|
  if (NULL == MenuEntry->VariableContext) {
 | 
						|
    SafeFreePool (MenuEntry);
 | 
						|
    MenuEntry = NULL;
 | 
						|
    return MenuEntry;
 | 
						|
  }
 | 
						|
 | 
						|
  MenuEntry->Signature        = BM_MENU_ENTRY_SIGNATURE;
 | 
						|
  MenuEntry->ContextSelection = MenuType;
 | 
						|
  return MenuEntry;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
BOpt_DestroyMenuEntry (
 | 
						|
  BM_MENU_ENTRY         *MenuEntry
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  Routine Description :
 | 
						|
    Destroy the menu entry passed in
 | 
						|
 | 
						|
  Arguments :
 | 
						|
    The menu entry need to be destroyed
 | 
						|
 | 
						|
  Returns :
 | 
						|
    None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  BM_LOAD_CONTEXT           *LoadContext;
 | 
						|
  BM_FILE_CONTEXT           *FileContext;
 | 
						|
  BM_CONSOLE_CONTEXT        *ConsoleContext;
 | 
						|
  BM_TERMINAL_CONTEXT       *TerminalContext;
 | 
						|
  BM_HANDLE_CONTEXT         *HandleContext;
 | 
						|
  BM_LEGACY_DEVICE_CONTEXT  *LegacyDevContext;
 | 
						|
 | 
						|
  //
 | 
						|
  //  Select by the type in Menu entry for current context type
 | 
						|
  //
 | 
						|
  switch (MenuEntry->ContextSelection) {
 | 
						|
  case BM_LOAD_CONTEXT_SELECT:
 | 
						|
    LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
    SafeFreePool (LoadContext->FilePathList);
 | 
						|
    SafeFreePool (LoadContext->LoadOption);
 | 
						|
    SafeFreePool (LoadContext->OptionalData);
 | 
						|
    SafeFreePool (LoadContext);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_FILE_CONTEXT_SELECT:
 | 
						|
    FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
 | 
						|
    if (!FileContext->IsRoot) {
 | 
						|
      SafeFreePool (FileContext->DevicePath);
 | 
						|
    } else {
 | 
						|
      if (FileContext->FHandle != NULL) {
 | 
						|
        FileContext->FHandle->Close (FileContext->FHandle);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    SafeFreePool (FileContext->FileName);
 | 
						|
    SafeFreePool (FileContext->Info);
 | 
						|
    SafeFreePool (FileContext);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_CONSOLE_CONTEXT_SELECT:
 | 
						|
    ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
    SafeFreePool (ConsoleContext->DevicePath);
 | 
						|
    SafeFreePool (ConsoleContext);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_TERMINAL_CONTEXT_SELECT:
 | 
						|
    TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
    SafeFreePool (TerminalContext->DevicePath);
 | 
						|
    SafeFreePool (TerminalContext);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_HANDLE_CONTEXT_SELECT:
 | 
						|
    HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
    SafeFreePool (HandleContext);
 | 
						|
    break;
 | 
						|
 | 
						|
  case BM_LEGACY_DEV_CONTEXT_SELECT:
 | 
						|
    LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
    SafeFreePool (LegacyDevContext);
 | 
						|
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
 | 
						|
  SafeFreePool (MenuEntry->DisplayString);
 | 
						|
  if (NULL != MenuEntry->HelpString) {
 | 
						|
    SafeFreePool (MenuEntry->HelpString);
 | 
						|
  }
 | 
						|
 | 
						|
  SafeFreePool (MenuEntry);
 | 
						|
}
 | 
						|
 | 
						|
BM_MENU_ENTRY *
 | 
						|
BOpt_GetMenuEntry (
 | 
						|
  BM_MENU_OPTION      *MenuOption,
 | 
						|
  UINTN               MenuNumber
 | 
						|
  )
 | 
						|
/*++
 | 
						|
  Rountine Description :
 | 
						|
    Use this routine to get one particular menu entry in specified 
 | 
						|
    menu
 | 
						|
 | 
						|
  Arguments :
 | 
						|
    MenuOption        The menu that we will search 
 | 
						|
 | 
						|
    MenuNumber        The menunubmer that we want
 | 
						|
 | 
						|
  Returns :
 | 
						|
    The desired menu entry
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  BM_MENU_ENTRY   *NewMenuEntry;
 | 
						|
  UINTN           Index;
 | 
						|
  LIST_ENTRY      *List;
 | 
						|
 | 
						|
  if (MenuNumber >= MenuOption->MenuNumber) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  List = MenuOption->Head.ForwardLink;
 | 
						|
  for (Index = 0; Index < MenuNumber; Index++) {
 | 
						|
    List = List->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);
 | 
						|
 | 
						|
  return NewMenuEntry;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
BOpt_FindFileSystem (
 | 
						|
  IN BMM_CALLBACK_DATA          *CallbackData
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description
 | 
						|
  Find file systems for current Extensible Firmware
 | 
						|
  Including Handles that support Simple File System
 | 
						|
  protocol, Load File protocol.
 | 
						|
 | 
						|
  Building up the FileSystem Menu for user selection
 | 
						|
  All file system will be stored in FsOptionMenu 
 | 
						|
  for future use.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  CallbackData           -   BMM context data
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS            -   Success find the file system
 | 
						|
  EFI_OUT_OF_RESOURCES   -   Can not create menu entry
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                     NoSimpleFsHandles;
 | 
						|
  UINTN                     NoLoadFileHandles;
 | 
						|
  EFI_HANDLE                *SimpleFsHandle;
 | 
						|
  EFI_HANDLE                *LoadFileHandle;
 | 
						|
  UINT16                    *VolumeLabel;
 | 
						|
  EFI_BLOCK_IO_PROTOCOL     *BlkIo;
 | 
						|
  UINTN                     Index;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  BM_MENU_ENTRY             *MenuEntry;
 | 
						|
  BM_FILE_CONTEXT           *FileContext;
 | 
						|
  UINT16                    *TempStr;
 | 
						|
  UINTN                     OptionNumber;
 | 
						|
  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | 
						|
  UINT16                    DeviceType;
 | 
						|
  BBS_BBS_DEVICE_PATH       BbsDevicePathNode;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  BOOLEAN                   RemovableMedia;
 | 
						|
 | 
						|
 | 
						|
  NoSimpleFsHandles = 0;
 | 
						|
  NoLoadFileHandles = 0;
 | 
						|
  OptionNumber      = 0;
 | 
						|
  InitializeListHead (&FsOptionMenu.Head);
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 load option
 | 
						|
      //
 | 
						|
      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
 | 
						|
      if (NULL == MenuEntry) {
 | 
						|
        SafeFreePool (SimpleFsHandle);    
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
            
 | 
						|
      FileContext->Handle     = SimpleFsHandle[Index];
 | 
						|
      MenuEntry->OptionNumber = Index;
 | 
						|
      FileContext->FHandle    = EfiLibOpenRoot (FileContext->Handle);
 | 
						|
      if (!FileContext->FHandle) {
 | 
						|
        BOpt_DestroyMenuEntry (MenuEntry);
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));
 | 
						|
      FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);
 | 
						|
      FileContext->FileName = EfiStrDuplicate (L"\\");
 | 
						|
      FileContext->DevicePath = FileDevicePath (
 | 
						|
                                  FileContext->Handle,
 | 
						|
                                  FileContext->FileName
 | 
						|
                                  );
 | 
						|
      FileContext->IsDir            = TRUE;
 | 
						|
      FileContext->IsRoot           = TRUE;
 | 
						|
      FileContext->IsRemovableMedia = FALSE;
 | 
						|
      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) {
 | 
						|
    SafeFreePool (SimpleFsHandle);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Searching for handles that support Load File protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiLoadFileProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &NoLoadFileHandles,
 | 
						|
                  &LoadFileHandle
 | 
						|
                  );
 | 
						|
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    for (Index = 0; Index < NoLoadFileHandles; Index++) {
 | 
						|
      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
 | 
						|
      if (NULL == MenuEntry) {
 | 
						|
        SafeFreePool (LoadFileHandle);    
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      FileContext                   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
      FileContext->IsRemovableMedia = FALSE;
 | 
						|
      FileContext->IsLoadFile       = TRUE;
 | 
						|
      FileContext->Handle           = LoadFileHandle[Index];
 | 
						|
      FileContext->IsRoot           = TRUE;
 | 
						|
 | 
						|
      FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);
 | 
						|
 | 
						|
      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);
 | 
						|
 | 
						|
      TempStr                   = MenuEntry->HelpString;
 | 
						|
      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);
 | 
						|
      ASSERT (MenuEntry->DisplayString != NULL);
 | 
						|
      UnicodeSPrint (
 | 
						|
        MenuEntry->DisplayString,
 | 
						|
        MAX_CHAR,
 | 
						|
        L"Load File [%s]",
 | 
						|
        TempStr
 | 
						|
        );
 | 
						|
 | 
						|
      MenuEntry->OptionNumber = OptionNumber;
 | 
						|
      OptionNumber++;
 | 
						|
      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (NoLoadFileHandles != 0) {
 | 
						|
    SafeFreePool (LoadFileHandle);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add Legacy Boot Option Support Here
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiLegacyBiosProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID**) &LegacyBios
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
 | 
						|
    for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {
 | 
						|
      MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
 | 
						|
      if (NULL == MenuEntry) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      FileContext                       = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
 | 
						|
      FileContext->IsRemovableMedia     = FALSE;
 | 
						|
      FileContext->IsLoadFile           = TRUE;
 | 
						|
      FileContext->IsBootLegacy         = TRUE;
 | 
						|
      DeviceType                        = (UINT16) Index;
 | 
						|
      BbsDevicePathNode.Header.Type     = BBS_DEVICE_PATH;
 | 
						|
      BbsDevicePathNode.Header.SubType  = BBS_BBS_DP;
 | 
						|
      SetDevicePathNodeLength (
 | 
						|
        &BbsDevicePathNode.Header,
 | 
						|
        sizeof (BBS_BBS_DEVICE_PATH)
 | 
						|
        );
 | 
						|
      BbsDevicePathNode.DeviceType  = DeviceType;
 | 
						|
      BbsDevicePathNode.StatusFlag  = 0;
 | 
						|
      BbsDevicePathNode.String[0]   = 0;
 | 
						|
      DevicePath = AppendDevicePathNode (
 | 
						|
                    EndDevicePath,
 | 
						|
                    (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode
 | 
						|
                    );
 | 
						|
 | 
						|
      FileContext->DevicePath   = DevicePath;
 | 
						|
      MenuEntry->HelpString     = DevicePathToStr (FileContext->DevicePath);
 | 
						|
 | 
						|
      TempStr                   = MenuEntry->HelpString;
 | 
						|
      MenuEntry->DisplayString  = AllocateZeroPool (MAX_CHAR);
 | 
						|
      ASSERT (MenuEntry->DisplayString != NULL);
 | 
						|
      UnicodeSPrint (
 | 
						|
        MenuEntry->DisplayString,
 | 
						|
        MAX_CHAR,
 | 
						|
        L"Boot Legacy [%s]",
 | 
						|
        TempStr
 | 
						|
        );
 | 
						|
      MenuEntry->OptionNumber = OptionNumber;
 | 
						|
      OptionNumber++;
 | 
						|
      InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Remember how many file system options are here
 | 
						|
  //
 | 
						|
  FsOptionMenu.MenuNumber = OptionNumber;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
BOpt_FreeMenu (
 | 
						|
  BM_MENU_OPTION        *FreeMenu
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description
 | 
						|
  Free resources allocated in Allocate Rountine
 | 
						|
 | 
						|
Arguments:
 | 
						|
  FreeMenu        Menu to be freed
 | 
						|
 | 
						|
Returns:
 | 
						|
  VOID
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  BM_MENU_ENTRY *MenuEntry;
 | 
						|
  while (!IsListEmpty (&FreeMenu->Head)) {
 | 
						|
    MenuEntry = CR (
 | 
						|
                  FreeMenu->Head.ForwardLink,
 | 
						|
                  BM_MENU_ENTRY,
 | 
						|
                  Link,
 | 
						|
                  BM_MENU_ENTRY_SIGNATURE
 | 
						|
                  );
 | 
						|
    RemoveEntryList (&MenuEntry->Link);
 | 
						|
    BOpt_DestroyMenuEntry (MenuEntry);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
BOpt_FindFiles (
 | 
						|
  IN BMM_CALLBACK_DATA          *CallbackData,
 | 
						|
  IN BM_MENU_ENTRY              *MenuEntry
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description
 | 
						|
  Find files under current directory
 | 
						|
  All files and sub-directories in current directory
 | 
						|
  will be stored in DirectoryMenu for future use.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  FileOption   -- Pointer for Dir to explore
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE         -- Get files from current dir successfully
 | 
						|
  FALSE        -- Can't get files from current dir
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_FILE_HANDLE NewDir;
 | 
						|
  EFI_FILE_HANDLE Dir;
 | 
						|
  EFI_FILE_INFO   *DirInfo;
 | 
						|
  UINTN           BufferSize;
 | 
						|
  UINTN           DirBufferSize;
 | 
						|
  BM_MENU_ENTRY   *NewMenuEntry;
 | 
						|
  BM_FILE_CONTEXT *FileContext;
 | 
						|
  BM_FILE_CONTEXT *NewFileContext;
 | 
						|
  UINTN           Pass;
 | 
						|
  EFI_STATUS      Status;
 | 
						|
  UINTN           OptionNumber;
 | 
						|
 | 
						|
  FileContext   = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;
 | 
						|
  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 = EfiLibFileInfo (NewDir);
 | 
						|
  if (!DirInfo) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  FileContext->DevicePath = FileDevicePath (
 | 
						|
                              FileContext->Handle,
 | 
						|
                              FileContext->FileName
 | 
						|
                              );
 | 
						|
 | 
						|
  DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;
 | 
						|
  DirInfo       = AllocateZeroPool (DirBufferSize);
 | 
						|
  if (!DirInfo) {
 | 
						|
    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 && Pass == 2) ||
 | 
						|
          (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1)
 | 
						|
          ) {
 | 
						|
        //
 | 
						|
        // Pass 1 is for Directories
 | 
						|
        // Pass 2 is for file names
 | 
						|
        //
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) {
 | 
						|
        //
 | 
						|
        // Slip file unless it is a directory entry or a .EFI file
 | 
						|
        //
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);
 | 
						|
      if (NULL == NewMenuEntry) {
 | 
						|
        return EFI_OUT_OF_RESOURCES;
 | 
						|
      }
 | 
						|
 | 
						|
      NewFileContext          = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;
 | 
						|
      NewFileContext->Handle  = FileContext->Handle;
 | 
						|
      NewFileContext->FileName = BOpt_AppendFileName (
 | 
						|
                                  FileContext->FileName,
 | 
						|
                                  DirInfo->FileName
 | 
						|
                                  );
 | 
						|
      NewFileContext->FHandle = NewDir;
 | 
						|
      NewFileContext->DevicePath = FileDevicePath (
 | 
						|
                                    NewFileContext->Handle,
 | 
						|
                                    NewFileContext->FileName
 | 
						|
                                    );
 | 
						|
      NewMenuEntry->HelpString = NULL;
 | 
						|
 | 
						|
      MenuEntry->DisplayStringToken = GetStringTokenFromDepository (
 | 
						|
                                        CallbackData,
 | 
						|
                                        FileOptionStrDepository
 | 
						|
                                        );
 | 
						|
 | 
						|
      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 = EfiStrDuplicate (DirInfo->FileName);
 | 
						|
      }
 | 
						|
 | 
						|
      NewFileContext->IsRoot            = FALSE;
 | 
						|
      NewFileContext->IsLoadFile        = FALSE;
 | 
						|
      NewFileContext->IsRemovableMedia  = FALSE;
 | 
						|
 | 
						|
      NewMenuEntry->OptionNumber        = OptionNumber;
 | 
						|
      OptionNumber++;
 | 
						|
      InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  DirectoryMenu.MenuNumber = OptionNumber;
 | 
						|
  SafeFreePool (DirInfo);
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
BOpt_GetLegacyOptions (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
Routine Description:
 | 
						|
  
 | 
						|
  Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
 | 
						|
    
 | 
						|
Arguments:
 | 
						|
  None
 | 
						|
 | 
						|
Returns:
 | 
						|
  The device info of legacy device.
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  BM_MENU_ENTRY             *NewMenuEntry;
 | 
						|
  BM_LEGACY_DEVICE_CONTEXT  *NewLegacyDevContext;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  EFI_LEGACY_BIOS_PROTOCOL  *LegacyBios;
 | 
						|
  UINT16                    HddCount;
 | 
						|
  HDD_INFO                  *HddInfo;
 | 
						|
  UINT16                    BbsCount;
 | 
						|
  BBS_TABLE                 *BbsTable;
 | 
						|
  UINTN                     Index;
 | 
						|
  CHAR16                    DescString[100];
 | 
						|
  UINTN                     FDNum;
 | 
						|
  UINTN                     HDNum;
 | 
						|
  UINTN                     CDNum;
 | 
						|
  UINTN                     NETNum;
 | 
						|
  UINTN                     BEVNum;
 | 
						|
 | 
						|
  NewMenuEntry  = NULL;
 | 
						|
  HddInfo       = NULL;
 | 
						|
  BbsTable      = NULL;
 | 
						|
  BbsCount      = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize Bbs Table Context from BBS info data
 | 
						|
  //
 | 
						|
  InitializeListHead (&LegacyFDMenu.Head);
 | 
						|
  InitializeListHead (&LegacyHDMenu.Head);
 | 
						|
  InitializeListHead (&LegacyCDMenu.Head);
 | 
						|
  InitializeListHead (&LegacyNETMenu.Head);
 | 
						|
  InitializeListHead (&LegacyBEVMenu.Head);
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiLegacyBiosProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID**) &LegacyBios
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = LegacyBios->GetBbsInfo (
 | 
						|
                          LegacyBios,
 | 
						|
                          &HddCount,
 | 
						|
                          &HddInfo,
 | 
						|
                          &BbsCount,
 | 
						|
                          &BbsTable
 | 
						|
                          );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  FDNum   = 0;
 | 
						|
  HDNum   = 0;
 | 
						|
  CDNum   = 0;
 | 
						|
  NETNum  = 0;
 | 
						|
  BEVNum  = 0;
 | 
						|
 | 
						|
  for (Index = 0; Index < BbsCount; Index++) {
 | 
						|
    if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||
 | 
						|
        (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority) ||
 | 
						|
        (BBS_LOWEST_PRIORITY == BbsTable[Index].BootPriority)
 | 
						|
        ) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);
 | 
						|
    if (NULL == NewMenuEntry) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    NewLegacyDevContext           = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;
 | 
						|
    NewLegacyDevContext->BbsTable = &BbsTable[Index];
 | 
						|
    NewLegacyDevContext->Index    = Index;
 | 
						|
    NewLegacyDevContext->BbsCount = BbsCount;
 | 
						|
    BdsBuildLegacyDevNameString (
 | 
						|
      &BbsTable[Index],
 | 
						|
      Index,
 | 
						|
      sizeof (DescString),
 | 
						|
      DescString
 | 
						|
      );
 | 
						|
    NewLegacyDevContext->Description = AllocateZeroPool (StrSize (DescString));
 | 
						|
    if (NULL == NewLegacyDevContext->Description) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString));
 | 
						|
    NewMenuEntry->DisplayString = NewLegacyDevContext->Description;
 | 
						|
    NewMenuEntry->HelpString    = NULL;
 | 
						|
 | 
						|
    switch (BbsTable[Index].DeviceType) {
 | 
						|
    case BBS_FLOPPY:
 | 
						|
      InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);
 | 
						|
      FDNum++;
 | 
						|
      break;
 | 
						|
 | 
						|
    case BBS_HARDDISK:
 | 
						|
      InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);
 | 
						|
      HDNum++;
 | 
						|
      break;
 | 
						|
 | 
						|
    case BBS_CDROM:
 | 
						|
      InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);
 | 
						|
      CDNum++;
 | 
						|
      break;
 | 
						|
 | 
						|
    case BBS_EMBED_NETWORK:
 | 
						|
      InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);
 | 
						|
      NETNum++;
 | 
						|
      break;
 | 
						|
 | 
						|
    case BBS_BEV_DEVICE:
 | 
						|
      InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);
 | 
						|
      BEVNum++;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Index != BbsCount) {
 | 
						|
    BOpt_FreeLegacyOptions ();
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  LegacyFDMenu.MenuNumber   = FDNum;
 | 
						|
  LegacyHDMenu.MenuNumber   = HDNum;
 | 
						|
  LegacyCDMenu.MenuNumber   = CDNum;
 | 
						|
  LegacyNETMenu.MenuNumber  = NETNum;
 | 
						|
  LegacyBEVMenu.MenuNumber  = BEVNum;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
BOpt_FreeLegacyOptions (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  BOpt_FreeMenu (&LegacyFDMenu);
 | 
						|
  BOpt_FreeMenu (&LegacyHDMenu);
 | 
						|
  BOpt_FreeMenu (&LegacyCDMenu);
 | 
						|
  BOpt_FreeMenu (&LegacyNETMenu);
 | 
						|
  BOpt_FreeMenu (&LegacyBEVMenu);
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
BOpt_GetBootOptions (
 | 
						|
  IN  BMM_CALLBACK_DATA         *CallbackData
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  
 | 
						|
  Build the BootOptionMenu according to BootOrder Variable.
 | 
						|
  This Routine will access the Boot#### to get EFI_LOAD_OPTION 
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  None
 | 
						|
 | 
						|
Returns:
 | 
						|
  The number of the Var Boot####
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                     Index;
 | 
						|
  UINT16                    BootString[10];
 | 
						|
  UINT8                     *LoadOptionFromVar;
 | 
						|
  UINT8                     *LoadOption;
 | 
						|
  UINTN                     BootOptionSize;
 | 
						|
  BOOLEAN                   BootNextFlag;
 | 
						|
  UINT16                    *BootOrderList;
 | 
						|
  UINTN                     BootOrderListSize;
 | 
						|
  UINT16                    *BootNext;
 | 
						|
  UINTN                     BootNextSize;
 | 
						|
  BM_MENU_ENTRY             *NewMenuEntry;
 | 
						|
  BM_LOAD_CONTEXT           *NewLoadContext;
 | 
						|
  UINT8                     *LoadOptionPtr;
 | 
						|
  UINTN                     StringSize;
 | 
						|
  UINTN                     OptionalDataSize;
 | 
						|
  UINT8                     *LoadOptionEnd;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
 | 
						|
  UINTN                     MenuCount;
 | 
						|
  UINT8                     *Ptr;
 | 
						|
 | 
						|
  MenuCount         = 0;
 | 
						|
  BootOrderListSize = 0;
 | 
						|
  BootNextSize      = 0;
 | 
						|
  BootOrderList     = NULL;
 | 
						|
  BootNext          = NULL;
 | 
						|
  LoadOptionFromVar = NULL;
 | 
						|
  BOpt_FreeMenu (&BootOptionMenu);
 | 
						|
  InitializeListHead (&BootOptionMenu.Head);
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the BootOrder from the Var
 | 
						|
  //
 | 
						|
  BootOrderList = BdsLibGetVariableAndSize (
 | 
						|
                    L"BootOrder",
 | 
						|
                    &gEfiGlobalVariableGuid,
 | 
						|
                    &BootOrderListSize
 | 
						|
                    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the BootNext from the Var
 | 
						|
  //
 | 
						|
  BootNext = BdsLibGetVariableAndSize (
 | 
						|
              L"BootNext",
 | 
						|
              &gEfiGlobalVariableGuid,
 | 
						|
              &BootNextSize
 | 
						|
              );
 | 
						|
 | 
						|
  if (BootNext) {
 | 
						|
    if (BootNextSize != sizeof (UINT16)) {
 | 
						|
      SafeFreePool (BootNext);
 | 
						|
      BootNext = NULL;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
 | 
						|
    UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);
 | 
						|
    //
 | 
						|
    //  Get all loadoptions from the VAR
 | 
						|
    //
 | 
						|
    LoadOptionFromVar = BdsLibGetVariableAndSize (
 | 
						|
                          BootString,
 | 
						|
                          &gEfiGlobalVariableGuid,
 | 
						|
                          &BootOptionSize
 | 
						|
                          );
 | 
						|
    if (!LoadOptionFromVar) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    LoadOption = AllocateZeroPool (BootOptionSize);
 | 
						|
    if (!LoadOption) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);
 | 
						|
    SafeFreePool (LoadOptionFromVar);
 | 
						|
 | 
						|
    if (BootNext) {
 | 
						|
      BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);
 | 
						|
    } else {
 | 
						|
      BootNextFlag = FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {
 | 
						|
      SafeFreePool (LoadOption);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
 | 
						|
    // the buffer allocated already should be freed before returning.
 | 
						|
    //
 | 
						|
    NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
 | 
						|
    if (NULL == NewMenuEntry) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    NewLoadContext                      = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
 | 
						|
 | 
						|
    LoadOptionPtr                       = LoadOption;
 | 
						|
    LoadOptionEnd                       = LoadOption + BootOptionSize;
 | 
						|
 | 
						|
    NewMenuEntry->OptionNumber          = BootOrderList[Index];
 | 
						|
    NewLoadContext->LoadOptionModified  = FALSE;
 | 
						|
    NewLoadContext->Deleted             = FALSE;
 | 
						|
    NewLoadContext->IsBootNext          = BootNextFlag;
 | 
						|
 | 
						|
    //
 | 
						|
    // Is a Legacy Device?
 | 
						|
    //
 | 
						|
    Ptr = (UINT8 *) LoadOption;
 | 
						|
 | 
						|
    //
 | 
						|
    // Attribute = *(UINT32 *)Ptr;
 | 
						|
    //
 | 
						|
    Ptr += sizeof (UINT32);
 | 
						|
 | 
						|
    //
 | 
						|
    // FilePathSize = *(UINT16 *)Ptr;
 | 
						|
    //
 | 
						|
    Ptr += sizeof (UINT16);
 | 
						|
 | 
						|
    //
 | 
						|
    // Description = (CHAR16 *)Ptr;
 | 
						|
    //
 | 
						|
    Ptr += StrSize ((CHAR16 *) Ptr);
 | 
						|
 | 
						|
    //
 | 
						|
    // Now Ptr point to Device Path
 | 
						|
    //
 | 
						|
    DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;
 | 
						|
    if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {
 | 
						|
      NewLoadContext->IsLegacy = TRUE;
 | 
						|
    } else {
 | 
						|
      NewLoadContext->IsLegacy = FALSE;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // LoadOption is a pointer type of UINT8
 | 
						|
    // for easy use with following LOAD_OPTION
 | 
						|
    // embedded in this struct
 | 
						|
    //
 | 
						|
    NewLoadContext->LoadOption      = LoadOption;
 | 
						|
    NewLoadContext->LoadOptionSize  = BootOptionSize;
 | 
						|
 | 
						|
    NewLoadContext->Attributes      = *(UINT32 *) LoadOptionPtr;
 | 
						|
    NewLoadContext->IsActive        = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);
 | 
						|
 | 
						|
    NewLoadContext->ForceReconnect  = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
 | 
						|
 | 
						|
    LoadOptionPtr += sizeof (UINT32);
 | 
						|
 | 
						|
    NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
 | 
						|
    LoadOptionPtr += sizeof (UINT16);
 | 
						|
 | 
						|
    StringSize                  = StrSize ((UINT16 *) LoadOptionPtr);
 | 
						|
    NewLoadContext->Description = AllocateZeroPool (StringSize);
 | 
						|
    ASSERT (NewLoadContext->Description != NULL);
 | 
						|
    CopyMem (
 | 
						|
      NewLoadContext->Description,
 | 
						|
      (UINT16 *) LoadOptionPtr,
 | 
						|
      StringSize
 | 
						|
      );
 | 
						|
    NewMenuEntry->DisplayString = NewLoadContext->Description;
 | 
						|
 | 
						|
    LoadOptionPtr += StringSize;
 | 
						|
 | 
						|
    NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
 | 
						|
    ASSERT (NewLoadContext->FilePathList != NULL);
 | 
						|
    CopyMem (
 | 
						|
      NewLoadContext->FilePathList,
 | 
						|
      (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
 | 
						|
      NewLoadContext->FilePathListLength
 | 
						|
      );
 | 
						|
 | 
						|
    NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
 | 
						|
    NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
 | 
						|
                                        CallbackData,
 | 
						|
                                        BootOptionStrDepository
 | 
						|
                                        );
 | 
						|
    NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
 | 
						|
                                      CallbackData,
 | 
						|
                                      BootOptionHelpStrDepository
 | 
						|
                                      );
 | 
						|
    LoadOptionPtr += NewLoadContext->FilePathListLength;
 | 
						|
 | 
						|
    if (LoadOptionPtr < LoadOptionEnd) {
 | 
						|
      OptionalDataSize = BootOptionSize -
 | 
						|
        sizeof (UINT32) -
 | 
						|
        sizeof (UINT16) -
 | 
						|
        StringSize -
 | 
						|
        NewLoadContext->FilePathListLength;
 | 
						|
 | 
						|
      NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
 | 
						|
      ASSERT (NewLoadContext->OptionalData != NULL);
 | 
						|
      CopyMem (
 | 
						|
        NewLoadContext->OptionalData,
 | 
						|
        LoadOptionPtr,
 | 
						|
        OptionalDataSize
 | 
						|
        );
 | 
						|
 | 
						|
      NewLoadContext->OptionalDataSize = OptionalDataSize;
 | 
						|
    }
 | 
						|
 | 
						|
    InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);
 | 
						|
    MenuCount++;
 | 
						|
  }
 | 
						|
 | 
						|
  SafeFreePool (BootNext);
 | 
						|
  SafeFreePool (BootOrderList);
 | 
						|
  BootOptionMenu.MenuNumber = MenuCount;
 | 
						|
  return MenuCount;
 | 
						|
}
 | 
						|
 | 
						|
CHAR16 *
 | 
						|
BdsStrCpy (
 | 
						|
  OUT     CHAR16                    *Destination,
 | 
						|
  IN      CONST CHAR16              *Source
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16                            *ReturnValue;
 | 
						|
 | 
						|
  //
 | 
						|
  // Destination cannot be NULL
 | 
						|
  //
 | 
						|
  ASSERT (Destination != NULL);
 | 
						|
 | 
						|
  ReturnValue = Destination;
 | 
						|
  while (*Source) {
 | 
						|
    *(Destination++) = *(Source++);
 | 
						|
  }
 | 
						|
  *Destination = 0;
 | 
						|
  return ReturnValue;
 | 
						|
}
 | 
						|
 | 
						|
CHAR16 *
 | 
						|
BOpt_AppendFileName (
 | 
						|
  IN  CHAR16  *Str1,
 | 
						|
  IN  CHAR16  *Str2
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description
 | 
						|
  Append file name to existing file name.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Str1  -   existing file name
 | 
						|
  Str2  -   file name to be appended
 | 
						|
 | 
						|
Returns:
 | 
						|
  Allocate a new string to hold the appended result.
 | 
						|
  Caller is responsible to free the returned string.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN   Size1;
 | 
						|
  UINTN   Size2;
 | 
						|
  CHAR16  *Str;
 | 
						|
  CHAR16  *Ptr;
 | 
						|
  CHAR16  *LastSlash;
 | 
						|
 | 
						|
  Size1 = StrSize (Str1);
 | 
						|
  Size2 = StrSize (Str2);
 | 
						|
  Str   = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16));
 | 
						|
  ASSERT (Str != 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) != 0) {
 | 
						|
      //
 | 
						|
      // Convert "\Name\..\" to "\"
 | 
						|
      // DO NOT convert the .. if it is at the end of the string. This will
 | 
						|
      // break the .. behavior in changing directories.
 | 
						|
      //
 | 
						|
      BdsStrCpy (LastSlash, Ptr + 3);
 | 
						|
      Ptr = LastSlash;
 | 
						|
    } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {
 | 
						|
      //
 | 
						|
      // Convert a "\.\" to a "\"
 | 
						|
      //
 | 
						|
      BdsStrCpy (Ptr, Ptr + 2);
 | 
						|
      Ptr = LastSlash;
 | 
						|
    } else if (*Ptr == '\\') {
 | 
						|
      LastSlash = Ptr;
 | 
						|
    }
 | 
						|
 | 
						|
    Ptr++;
 | 
						|
  }
 | 
						|
 | 
						|
  return Str;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
BOpt_IsEfiImageName (
 | 
						|
  IN UINT16  *FileName
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description
 | 
						|
  Check whether current FileName point to a valid 
 | 
						|
  Efi Image File.
 | 
						|
 | 
						|
Arguments:
 | 
						|
  FileName  -   File need to be checked.
 | 
						|
 | 
						|
Returns:
 | 
						|
  TRUE  -   Is Efi Image
 | 
						|
  FALSE -   Not a valid Efi Image
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Search for ".efi" extension
 | 
						|
  //
 | 
						|
  while (*FileName) {
 | 
						|
    if (FileName[0] == '.') {
 | 
						|
      if (FileName[1] == 'e' || FileName[1] == 'E') {
 | 
						|
        if (FileName[2] == 'f' || FileName[2] == 'F') {
 | 
						|
          if (FileName[3] == 'i' || FileName[3] == 'I') {
 | 
						|
            return TRUE;
 | 
						|
          } else if (FileName[3] == 0x0000) {
 | 
						|
            return FALSE;
 | 
						|
          }
 | 
						|
        } else if (FileName[2] == 0x0000) {
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
      } else if (FileName[1] == 0x0000) {
 | 
						|
        return FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    FileName += 1;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
RETURN_STATUS
 | 
						|
EFIAPI
 | 
						|
IsEfiAppReadFromFile (
 | 
						|
  IN     VOID    *FileHandle,
 | 
						|
  IN     UINTN   FileOffset,
 | 
						|
  IN OUT UINTN   *ReadSize,
 | 
						|
  OUT    VOID    *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS        Status;
 | 
						|
  EFI_FILE_HANDLE   File;
 | 
						|
    
 | 
						|
  File = (EFI_FILE_HANDLE)FileHandle;
 | 
						|
  Status = File->SetPosition (File, FileOffset);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  return File->Read (File, ReadSize, Buffer);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
BOpt_IsEfiApp (
 | 
						|
  IN EFI_FILE_HANDLE Dir,
 | 
						|
  IN UINT16          *FileName
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Check whether current FileName point to a valid Efi Application
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  Dir       -   Pointer to current Directory
 | 
						|
  FileName  -   Pointer to current File name.
 | 
						|
  
 | 
						|
Returns:
 | 
						|
  TRUE      -   Is a valid Efi Application
 | 
						|
  FALSE     -   not a valid Efi Application
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;
 | 
						|
  EFI_FILE_HANDLE                       File;
 | 
						|
 | 
						|
  Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (&ImageContext, sizeof (ImageContext));
 | 
						|
  ImageContext.Handle    = (VOID *)File;
 | 
						|
  ImageContext.ImageRead = IsEfiAppReadFromFile;
 | 
						|
 | 
						|
  Status = PeCoffLoaderGetImageInfo (&ImageContext);
 | 
						|
  File->Close (File);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
 | 
						|
    return TRUE;
 | 
						|
  } else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
BOpt_FindDrivers (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description
 | 
						|
  Find drivers that will be added as Driver#### variables from handles
 | 
						|
  in current system environment
 | 
						|
  All valid handles in the system except those consume SimpleFs, LoadFile
 | 
						|
  are stored in DriverMenu for future use.
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
  None
 | 
						|
 | 
						|
Returns:
 | 
						|
  EFI_SUCCESS
 | 
						|
  Others
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN                           NoDevicePathHandles;
 | 
						|
  EFI_HANDLE                      *DevicePathHandle;
 | 
						|
  UINTN                           Index;
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  BM_MENU_ENTRY                   *NewMenuEntry;
 | 
						|
  BM_HANDLE_CONTEXT               *NewHandleContext;
 | 
						|
  EFI_HANDLE                      CurHandle;
 | 
						|
  UINTN                           OptionNumber;
 | 
						|
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
 | 
						|
  EFI_LOAD_FILE_PROTOCOL          *LoadFile;
 | 
						|
 | 
						|
  SimpleFs  = NULL;
 | 
						|
  LoadFile  = NULL;
 | 
						|
 | 
						|
  InitializeListHead (&DriverMenu.Head);
 | 
						|
 | 
						|
  //
 | 
						|
  // At first, get all handles that support Device Path
 | 
						|
  // protocol which is the basic requirement for
 | 
						|
  // Driver####
 | 
						|
  //
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                  ByProtocol,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  &NoDevicePathHandles,
 | 
						|
                  &DevicePathHandle
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  OptionNumber = 0;
 | 
						|
  for (Index = 0; Index < NoDevicePathHandles; Index++) {
 | 
						|
    CurHandle = DevicePathHandle[Index];
 | 
						|
 | 
						|
    //
 | 
						|
    //  Check whether this handle support
 | 
						|
    //  driver binding
 | 
						|
    //
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    CurHandle,
 | 
						|
                    &gEfiSimpleFileSystemProtocolGuid,
 | 
						|
                    (VOID**) &SimpleFs
 | 
						|
                    );
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    CurHandle,
 | 
						|
                    &gEfiLoadFileProtocolGuid,
 | 
						|
                    (VOID**) &LoadFile
 | 
						|
                    );
 | 
						|
    if (Status == EFI_SUCCESS) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);
 | 
						|
    if (NULL == NewMenuEntry) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    NewHandleContext              = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;
 | 
						|
    NewHandleContext->Handle      = CurHandle;
 | 
						|
    NewHandleContext->DevicePath  = DevicePathFromHandle (CurHandle);
 | 
						|
    NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);
 | 
						|
    NewMenuEntry->HelpString    = NULL;
 | 
						|
    NewMenuEntry->OptionNumber  = OptionNumber;
 | 
						|
    OptionNumber++;
 | 
						|
    InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  DriverMenu.MenuNumber = OptionNumber;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
UINT16
 | 
						|
BOpt_GetBootOptionNumber (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Get the Option Number that does not used 
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
  The Option Number
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  BM_MENU_ENTRY *NewMenuEntry;
 | 
						|
  UINT16        *BootOrderList;
 | 
						|
  UINTN         BootOrderListSize;
 | 
						|
  UINT16        Number;
 | 
						|
  UINTN         Index;
 | 
						|
  UINTN         Index2;
 | 
						|
  BOOLEAN       Found;
 | 
						|
  CHAR16        StrTemp[100];
 | 
						|
  UINT16        *OptionBuffer;
 | 
						|
  UINTN         OptionSize;
 | 
						|
 | 
						|
  BootOrderListSize = 0;
 | 
						|
  BootOrderList     = NULL;
 | 
						|
 | 
						|
  BootOrderList = BdsLibGetVariableAndSize (
 | 
						|
                    L"BootOrder",
 | 
						|
                    &gEfiGlobalVariableGuid,
 | 
						|
                    &BootOrderListSize
 | 
						|
                    );
 | 
						|
  if (BootOrderList) {
 | 
						|
    //
 | 
						|
    // already have Boot####
 | 
						|
    //
 | 
						|
    // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
 | 
						|
    //
 | 
						|
    for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {
 | 
						|
      Found = TRUE;
 | 
						|
      for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) {
 | 
						|
        NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2);
 | 
						|
        if (Index == NewMenuEntry->OptionNumber) {
 | 
						|
          Found = FALSE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (Found) {
 | 
						|
  	   UnicodeSPrint (StrTemp, 100, L"Boot%04x", Index);
 | 
						|
  	   DEBUG((EFI_D_ERROR,"INdex= %s\n", StrTemp));
 | 
						|
       OptionBuffer = BdsLibGetVariableAndSize (
 | 
						|
                StrTemp,
 | 
						|
                &gEfiGlobalVariableGuid,
 | 
						|
                &OptionSize
 | 
						|
                );
 | 
						|
      if (NULL == OptionBuffer) 
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // end for Index
 | 
						|
    //
 | 
						|
    Number = (UINT16) Index;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // No Boot####
 | 
						|
    //
 | 
						|
    Number = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return Number;
 | 
						|
}
 | 
						|
 | 
						|
UINT16
 | 
						|
BOpt_GetDriverOptionNumber (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Get the Option Number that does not used 
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
  The Option Number
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  BM_MENU_ENTRY *NewMenuEntry;
 | 
						|
  UINT16        *DriverOrderList;
 | 
						|
  UINTN         DriverOrderListSize;
 | 
						|
  UINT16        Number;
 | 
						|
  UINTN         Index;
 | 
						|
  UINTN         Index2;
 | 
						|
  BOOLEAN       Found;
 | 
						|
 | 
						|
  DriverOrderListSize = 0;
 | 
						|
  DriverOrderList     = NULL;
 | 
						|
 | 
						|
  DriverOrderList = BdsLibGetVariableAndSize (
 | 
						|
                      L"DriverOrder",
 | 
						|
                      &gEfiGlobalVariableGuid,
 | 
						|
                      &DriverOrderListSize
 | 
						|
                      );
 | 
						|
  if (DriverOrderList) {
 | 
						|
    //
 | 
						|
    // already have Driver####
 | 
						|
    //
 | 
						|
    // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
 | 
						|
    //
 | 
						|
    for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
 | 
						|
      Found = TRUE;
 | 
						|
      for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) {
 | 
						|
        NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2);
 | 
						|
        if (Index == NewMenuEntry->OptionNumber) {
 | 
						|
          Found = FALSE;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (Found) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // end for Index
 | 
						|
    //
 | 
						|
    Number = (UINT16) Index;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // No Driver####
 | 
						|
    //
 | 
						|
    Number = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return Number;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
BOpt_GetDriverOptions (
 | 
						|
  IN  BMM_CALLBACK_DATA         *CallbackData
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Build up all DriverOptionMenu
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
  The Option Number
 | 
						|
  
 | 
						|
--*/
 | 
						|
{
 | 
						|
  UINTN           Index;
 | 
						|
  UINT16          DriverString[12];
 | 
						|
  UINT8           *LoadOptionFromVar;
 | 
						|
  UINT8           *LoadOption;
 | 
						|
  UINTN           DriverOptionSize;
 | 
						|
 | 
						|
  UINT16          *DriverOrderList;
 | 
						|
  UINTN           DriverOrderListSize;
 | 
						|
  BM_MENU_ENTRY   *NewMenuEntry;
 | 
						|
  BM_LOAD_CONTEXT *NewLoadContext;
 | 
						|
  UINT8           *LoadOptionPtr;
 | 
						|
  UINTN           StringSize;
 | 
						|
  UINTN           OptionalDataSize;
 | 
						|
  UINT8           *LoadOptionEnd;
 | 
						|
 | 
						|
  DriverOrderListSize = 0;
 | 
						|
  DriverOrderList     = NULL;
 | 
						|
  DriverOptionSize    = 0;
 | 
						|
  LoadOptionFromVar   = NULL;
 | 
						|
  BOpt_FreeMenu (&DriverOptionMenu);
 | 
						|
  InitializeListHead (&DriverOptionMenu.Head);
 | 
						|
  //
 | 
						|
  // Get the DriverOrder from the Var
 | 
						|
  //
 | 
						|
  DriverOrderList = BdsLibGetVariableAndSize (
 | 
						|
                      L"DriverOrder",
 | 
						|
                      &gEfiGlobalVariableGuid,
 | 
						|
                      &DriverOrderListSize
 | 
						|
                      );
 | 
						|
 | 
						|
  for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {
 | 
						|
    UnicodeSPrint (
 | 
						|
      DriverString,
 | 
						|
      sizeof (DriverString),
 | 
						|
      L"Driver%04x",
 | 
						|
      DriverOrderList[Index]
 | 
						|
      );
 | 
						|
    //
 | 
						|
    //  Get all loadoptions from the VAR
 | 
						|
    //
 | 
						|
    LoadOptionFromVar = BdsLibGetVariableAndSize (
 | 
						|
                          DriverString,
 | 
						|
                          &gEfiGlobalVariableGuid,
 | 
						|
                          &DriverOptionSize
 | 
						|
                          );
 | 
						|
    if (!LoadOptionFromVar) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    LoadOption = AllocateZeroPool (DriverOptionSize);
 | 
						|
    if (!LoadOption) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);
 | 
						|
    SafeFreePool (LoadOptionFromVar);
 | 
						|
 | 
						|
    NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);
 | 
						|
    if (NULL == NewMenuEntry) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    NewLoadContext                      = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;
 | 
						|
    LoadOptionPtr                       = LoadOption;
 | 
						|
    LoadOptionEnd                       = LoadOption + DriverOptionSize;
 | 
						|
    NewMenuEntry->OptionNumber          = DriverOrderList[Index];
 | 
						|
    NewLoadContext->LoadOptionModified  = FALSE;
 | 
						|
    NewLoadContext->Deleted             = FALSE;
 | 
						|
    NewLoadContext->IsLegacy            = FALSE;
 | 
						|
 | 
						|
    //
 | 
						|
    // LoadOption is a pointer type of UINT8
 | 
						|
    // for easy use with following LOAD_OPTION
 | 
						|
    // embedded in this struct
 | 
						|
    //
 | 
						|
    NewLoadContext->LoadOption      = LoadOption;
 | 
						|
    NewLoadContext->LoadOptionSize  = DriverOptionSize;
 | 
						|
 | 
						|
    NewLoadContext->Attributes      = *(UINT32 *) LoadOptionPtr;
 | 
						|
    NewLoadContext->IsActive        = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);
 | 
						|
 | 
						|
    NewLoadContext->ForceReconnect  = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);
 | 
						|
 | 
						|
    LoadOptionPtr += sizeof (UINT32);
 | 
						|
 | 
						|
    NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;
 | 
						|
    LoadOptionPtr += sizeof (UINT16);
 | 
						|
 | 
						|
    StringSize                  = StrSize ((UINT16 *) LoadOptionPtr);
 | 
						|
    NewLoadContext->Description = AllocateZeroPool (StringSize);
 | 
						|
    ASSERT (NewLoadContext->Description != NULL);
 | 
						|
    CopyMem (
 | 
						|
      NewLoadContext->Description,
 | 
						|
      (UINT16 *) LoadOptionPtr,
 | 
						|
      StringSize
 | 
						|
      );
 | 
						|
    NewMenuEntry->DisplayString = NewLoadContext->Description;
 | 
						|
 | 
						|
    LoadOptionPtr += StringSize;
 | 
						|
 | 
						|
    NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);
 | 
						|
    ASSERT (NewLoadContext->FilePathList != NULL);
 | 
						|
    CopyMem (
 | 
						|
      NewLoadContext->FilePathList,
 | 
						|
      (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,
 | 
						|
      NewLoadContext->FilePathListLength
 | 
						|
      );
 | 
						|
 | 
						|
    NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);
 | 
						|
    NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (
 | 
						|
                                        CallbackData,
 | 
						|
                                        DriverOptionStrDepository
 | 
						|
                                        );
 | 
						|
    NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (
 | 
						|
                                      CallbackData,
 | 
						|
                                      DriverOptionHelpStrDepository
 | 
						|
                                      );
 | 
						|
    LoadOptionPtr += NewLoadContext->FilePathListLength;
 | 
						|
 | 
						|
    if (LoadOptionPtr < LoadOptionEnd) {
 | 
						|
      OptionalDataSize = DriverOptionSize -
 | 
						|
        sizeof (UINT32) -
 | 
						|
        sizeof (UINT16) -
 | 
						|
        StringSize -
 | 
						|
        NewLoadContext->FilePathListLength;
 | 
						|
 | 
						|
      NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);
 | 
						|
      ASSERT (NewLoadContext->OptionalData != NULL);
 | 
						|
      CopyMem (
 | 
						|
        NewLoadContext->OptionalData,
 | 
						|
        LoadOptionPtr,
 | 
						|
        OptionalDataSize
 | 
						|
        );
 | 
						|
 | 
						|
      NewLoadContext->OptionalDataSize = OptionalDataSize;
 | 
						|
    }
 | 
						|
 | 
						|
    InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  SafeFreePool (DriverOrderList);
 | 
						|
  DriverOptionMenu.MenuNumber = Index;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
SafeFreePool (
 | 
						|
  IN VOID    *Buffer
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  Wrap original FreePool gBS call
 | 
						|
  in order to decrease code length
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  if (Buffer != NULL) {
 | 
						|
    gBS->FreePool (Buffer);
 | 
						|
    Buffer = NULL;
 | 
						|
  }
 | 
						|
}
 |