+++ /dev/null
-/** @file\r
- Provide boot option support for Application "BootMaint"\r
-\r
- Include file system navigation, system handle selection\r
-\r
- Boot option manipulation\r
-\r
-Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "BootMaint.h"\r
-#include "BBSsupport.h"\r
-\r
-/**\r
- Create a menu entry by given menu type.\r
-\r
- @param MenuType The Menu type to be created.\r
-\r
- @retval NULL If failed to create the menu.\r
- @return the new menu entry.\r
-\r
-**/\r
-BM_MENU_ENTRY *\r
-BOpt_CreateMenuEntry (\r
- UINTN MenuType\r
- )\r
-{\r
- BM_MENU_ENTRY *MenuEntry;\r
- UINTN ContextSize;\r
-\r
- //\r
- // Get context size according to menu type\r
- //\r
- switch (MenuType) {\r
- case BM_LOAD_CONTEXT_SELECT:\r
- ContextSize = sizeof (BM_LOAD_CONTEXT);\r
- break;\r
-\r
- case BM_FILE_CONTEXT_SELECT:\r
- ContextSize = sizeof (BM_FILE_CONTEXT);\r
- break;\r
-\r
- case BM_CONSOLE_CONTEXT_SELECT:\r
- ContextSize = sizeof (BM_CONSOLE_CONTEXT);\r
- break;\r
-\r
- case BM_TERMINAL_CONTEXT_SELECT:\r
- ContextSize = sizeof (BM_TERMINAL_CONTEXT);\r
- break;\r
-\r
- case BM_HANDLE_CONTEXT_SELECT:\r
- ContextSize = sizeof (BM_HANDLE_CONTEXT);\r
- break;\r
-\r
- case BM_LEGACY_DEV_CONTEXT_SELECT:\r
- ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT);\r
- break;\r
-\r
- default:\r
- ContextSize = 0;\r
- break;\r
- }\r
-\r
- if (ContextSize == 0) {\r
- return NULL;\r
- }\r
-\r
- //\r
- // Create new menu entry\r
- //\r
- MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY));\r
- if (MenuEntry == NULL) {\r
- return NULL;\r
- }\r
-\r
- MenuEntry->VariableContext = AllocateZeroPool (ContextSize);\r
- if (MenuEntry->VariableContext == NULL) {\r
- FreePool (MenuEntry);\r
- return NULL;\r
- }\r
-\r
- MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE;\r
- MenuEntry->ContextSelection = MenuType;\r
- return MenuEntry;\r
-}\r
-\r
-/**\r
- Free up all resource allocated for a BM_MENU_ENTRY.\r
-\r
- @param MenuEntry A pointer to BM_MENU_ENTRY.\r
-\r
-**/\r
-VOID\r
-BOpt_DestroyMenuEntry (\r
- BM_MENU_ENTRY *MenuEntry\r
- )\r
-{\r
- BM_LOAD_CONTEXT *LoadContext;\r
- BM_FILE_CONTEXT *FileContext;\r
- BM_CONSOLE_CONTEXT *ConsoleContext;\r
- BM_TERMINAL_CONTEXT *TerminalContext;\r
- BM_HANDLE_CONTEXT *HandleContext;\r
- BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext;\r
-\r
- //\r
- // Select by the type in Menu entry for current context type\r
- //\r
- switch (MenuEntry->ContextSelection) {\r
- case BM_LOAD_CONTEXT_SELECT:\r
- LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext;\r
- FreePool (LoadContext->FilePathList);\r
- FreePool (LoadContext->LoadOption);\r
- if (LoadContext->OptionalData != NULL) {\r
- FreePool (LoadContext->OptionalData);\r
- }\r
- FreePool (LoadContext);\r
- break;\r
-\r
- case BM_FILE_CONTEXT_SELECT:\r
- FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
-\r
- if (!FileContext->IsRoot) {\r
- FreePool (FileContext->DevicePath);\r
- } else {\r
- if (FileContext->FHandle != NULL) {\r
- FileContext->FHandle->Close (FileContext->FHandle);\r
- }\r
- }\r
-\r
- if (FileContext->FileName != NULL) {\r
- FreePool (FileContext->FileName);\r
- }\r
- if (FileContext->Info != NULL) {\r
- FreePool (FileContext->Info);\r
- }\r
- FreePool (FileContext);\r
- break;\r
-\r
- case BM_CONSOLE_CONTEXT_SELECT:\r
- ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext;\r
- FreePool (ConsoleContext->DevicePath);\r
- FreePool (ConsoleContext);\r
- break;\r
-\r
- case BM_TERMINAL_CONTEXT_SELECT:\r
- TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext;\r
- FreePool (TerminalContext->DevicePath);\r
- FreePool (TerminalContext);\r
- break;\r
-\r
- case BM_HANDLE_CONTEXT_SELECT:\r
- HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext;\r
- FreePool (HandleContext);\r
- break;\r
-\r
- case BM_LEGACY_DEV_CONTEXT_SELECT:\r
- LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext;\r
- FreePool (LegacyDevContext);\r
-\r
- default:\r
- break;\r
- }\r
-\r
- FreePool (MenuEntry->DisplayString);\r
- if (MenuEntry->HelpString != NULL) {\r
- FreePool (MenuEntry->HelpString);\r
- }\r
-\r
- FreePool (MenuEntry);\r
-}\r
-\r
-/**\r
- Get the Menu Entry from the list in Menu Entry List.\r
-\r
- If MenuNumber is great or equal to the number of Menu\r
- Entry in the list, then ASSERT.\r
-\r
- @param MenuOption The Menu Entry List to read the menu entry.\r
- @param MenuNumber The index of Menu Entry.\r
-\r
- @return The Menu Entry.\r
-\r
-**/\r
-BM_MENU_ENTRY *\r
-BOpt_GetMenuEntry (\r
- BM_MENU_OPTION *MenuOption,\r
- UINTN MenuNumber\r
- )\r
-{\r
- BM_MENU_ENTRY *NewMenuEntry;\r
- UINTN Index;\r
- LIST_ENTRY *List;\r
-\r
- ASSERT (MenuNumber < MenuOption->MenuNumber);\r
-\r
- List = MenuOption->Head.ForwardLink;\r
- for (Index = 0; Index < MenuNumber; Index++) {\r
- List = List->ForwardLink;\r
- }\r
-\r
- NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE);\r
-\r
- return NewMenuEntry;\r
-}\r
-\r
-/**\r
- This function build the FsOptionMenu list which records all\r
- available file system in the system. They includes all instances\r
- of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM\r
- and all type of legacy boot device.\r
-\r
- @param CallbackData BMM context data\r
-\r
- @retval EFI_SUCCESS Success find the file system\r
- @retval EFI_OUT_OF_RESOURCES Can not create menu entry\r
-\r
-**/\r
-EFI_STATUS\r
-BOpt_FindFileSystem (\r
- IN BMM_CALLBACK_DATA *CallbackData\r
- )\r
-{\r
- UINTN NoBlkIoHandles;\r
- UINTN NoSimpleFsHandles;\r
- UINTN NoLoadFileHandles;\r
- EFI_HANDLE *BlkIoHandle;\r
- EFI_HANDLE *SimpleFsHandle;\r
- EFI_HANDLE *LoadFileHandle;\r
- UINT16 *VolumeLabel;\r
- EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- BM_MENU_ENTRY *MenuEntry;\r
- BM_FILE_CONTEXT *FileContext;\r
- UINT16 *TempStr;\r
- UINTN OptionNumber;\r
- VOID *Buffer;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINT16 DeviceType;\r
- BBS_BBS_DEVICE_PATH BbsDevicePathNode;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- BOOLEAN RemovableMedia;\r
-\r
-\r
- NoSimpleFsHandles = 0;\r
- NoLoadFileHandles = 0;\r
- OptionNumber = 0;\r
- InitializeListHead (&FsOptionMenu.Head);\r
-\r
- //\r
- // Locate Handles that support BlockIo protocol\r
- //\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiBlockIoProtocolGuid,\r
- NULL,\r
- &NoBlkIoHandles,\r
- &BlkIoHandle\r
- );\r
- if (!EFI_ERROR (Status)) {\r
-\r
- for (Index = 0; Index < NoBlkIoHandles; Index++) {\r
- Status = gBS->HandleProtocol (\r
- BlkIoHandle[Index],\r
- &gEfiBlockIoProtocolGuid,\r
- (VOID **) &BlkIo\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
-\r
- //\r
- // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media\r
- //\r
- if (BlkIo->Media->RemovableMedia) {\r
- Buffer = AllocateZeroPool (BlkIo->Media->BlockSize);\r
- if (NULL == Buffer) {\r
- FreePool (BlkIoHandle);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- BlkIo->ReadBlocks (\r
- BlkIo,\r
- BlkIo->Media->MediaId,\r
- 0,\r
- BlkIo->Media->BlockSize,\r
- Buffer\r
- );\r
- FreePool (Buffer);\r
- }\r
- }\r
- FreePool (BlkIoHandle);\r
- }\r
-\r
- //\r
- // Locate Handles that support Simple File System protocol\r
- //\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- NULL,\r
- &NoSimpleFsHandles,\r
- &SimpleFsHandle\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Find all the instances of the File System prototocol\r
- //\r
- for (Index = 0; Index < NoSimpleFsHandles; Index++) {\r
- Status = gBS->HandleProtocol (\r
- SimpleFsHandle[Index],\r
- &gEfiBlockIoProtocolGuid,\r
- (VOID **) &BlkIo\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // If no block IO exists assume it's NOT a removable media\r
- //\r
- RemovableMedia = FALSE;\r
- } else {\r
- //\r
- // If block IO exists check to see if it's remobable media\r
- //\r
- RemovableMedia = BlkIo->Media->RemovableMedia;\r
- }\r
-\r
- //\r
- // Allocate pool for this load option\r
- //\r
- MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
- if (NULL == MenuEntry) {\r
- FreePool (SimpleFsHandle);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
-\r
- FileContext->Handle = SimpleFsHandle[Index];\r
- MenuEntry->OptionNumber = Index;\r
- FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle);\r
- if (FileContext->FHandle == NULL) {\r
- BOpt_DestroyMenuEntry (MenuEntry);\r
- continue;\r
- }\r
-\r
- MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle));\r
- FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle);\r
- FileContext->FileName = EfiStrDuplicate (L"\\");\r
- FileContext->DevicePath = FileDevicePath (\r
- FileContext->Handle,\r
- FileContext->FileName\r
- );\r
- FileContext->IsDir = TRUE;\r
- FileContext->IsRoot = TRUE;\r
- FileContext->IsRemovableMedia = RemovableMedia;\r
- FileContext->IsLoadFile = FALSE;\r
-\r
- //\r
- // Get current file system's Volume Label\r
- //\r
- if (FileContext->Info == NULL) {\r
- VolumeLabel = L"NO FILE SYSTEM INFO";\r
- } else {\r
- VolumeLabel = FileContext->Info->VolumeLabel;\r
- if (*VolumeLabel == 0x0000) {\r
- VolumeLabel = L"NO VOLUME LABEL";\r
- }\r
- }\r
-\r
- TempStr = MenuEntry->HelpString;\r
- MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
- ASSERT (MenuEntry->DisplayString != NULL);\r
- UnicodeSPrint (\r
- MenuEntry->DisplayString,\r
- MAX_CHAR,\r
- L"%s, [%s]",\r
- VolumeLabel,\r
- TempStr\r
- );\r
- OptionNumber++;\r
- InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
- }\r
- }\r
-\r
- if (NoSimpleFsHandles != 0) {\r
- FreePool (SimpleFsHandle);\r
- }\r
- //\r
- // Searching for handles that support Load File protocol\r
- //\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiLoadFileProtocolGuid,\r
- NULL,\r
- &NoLoadFileHandles,\r
- &LoadFileHandle\r
- );\r
-\r
- if (!EFI_ERROR (Status)) {\r
- for (Index = 0; Index < NoLoadFileHandles; Index++) {\r
- MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
- if (NULL == MenuEntry) {\r
- FreePool (LoadFileHandle);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
- FileContext->IsRemovableMedia = FALSE;\r
- FileContext->IsLoadFile = TRUE;\r
- FileContext->Handle = LoadFileHandle[Index];\r
- FileContext->IsRoot = TRUE;\r
-\r
- FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle);\r
- FileContext->FileName = DevicePathToStr (FileContext->DevicePath);\r
-\r
- MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
-\r
- TempStr = MenuEntry->HelpString;\r
- MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
- ASSERT (MenuEntry->DisplayString != NULL);\r
- UnicodeSPrint (\r
- MenuEntry->DisplayString,\r
- MAX_CHAR,\r
- L"Load File [%s]",\r
- TempStr\r
- );\r
-\r
- MenuEntry->OptionNumber = OptionNumber;\r
- OptionNumber++;\r
- InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
- }\r
- }\r
-\r
- if (NoLoadFileHandles != 0) {\r
- FreePool (LoadFileHandle);\r
- }\r
-\r
- //\r
- // Add Legacy Boot Option Support Here\r
- //\r
- Status = gBS->LocateProtocol (\r
- &gEfiLegacyBiosProtocolGuid,\r
- NULL,\r
- (VOID **) &LegacyBios\r
- );\r
- if (!EFI_ERROR (Status)) {\r
-\r
- for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) {\r
- MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
- if (NULL == MenuEntry) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
-\r
- FileContext->IsRemovableMedia = FALSE;\r
- FileContext->IsLoadFile = TRUE;\r
- FileContext->IsBootLegacy = TRUE;\r
- DeviceType = (UINT16) Index;\r
- BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH;\r
- BbsDevicePathNode.Header.SubType = BBS_BBS_DP;\r
- SetDevicePathNodeLength (\r
- &BbsDevicePathNode.Header,\r
- sizeof (BBS_BBS_DEVICE_PATH)\r
- );\r
- BbsDevicePathNode.DeviceType = DeviceType;\r
- BbsDevicePathNode.StatusFlag = 0;\r
- BbsDevicePathNode.String[0] = 0;\r
- DevicePath = AppendDevicePathNode (\r
- EndDevicePath,\r
- (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode\r
- );\r
-\r
- FileContext->DevicePath = DevicePath;\r
- MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath);\r
-\r
- TempStr = MenuEntry->HelpString;\r
- MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);\r
- ASSERT (MenuEntry->DisplayString != NULL);\r
- UnicodeSPrint (\r
- MenuEntry->DisplayString,\r
- MAX_CHAR,\r
- L"Boot Legacy [%s]",\r
- TempStr\r
- );\r
- MenuEntry->OptionNumber = OptionNumber;\r
- OptionNumber++;\r
- InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link);\r
- }\r
- }\r
- //\r
- // Remember how many file system options are here\r
- //\r
- FsOptionMenu.MenuNumber = OptionNumber;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Free resources allocated in Allocate Rountine.\r
-\r
- @param FreeMenu Menu to be freed\r
-**/\r
-VOID\r
-BOpt_FreeMenu (\r
- BM_MENU_OPTION *FreeMenu\r
- )\r
-{\r
- BM_MENU_ENTRY *MenuEntry;\r
- while (!IsListEmpty (&FreeMenu->Head)) {\r
- MenuEntry = CR (\r
- FreeMenu->Head.ForwardLink,\r
- BM_MENU_ENTRY,\r
- Link,\r
- BM_MENU_ENTRY_SIGNATURE\r
- );\r
- RemoveEntryList (&MenuEntry->Link);\r
- BOpt_DestroyMenuEntry (MenuEntry);\r
- }\r
- FreeMenu->MenuNumber = 0;\r
-}\r
-\r
-/**\r
- Find files under current directory\r
- All files and sub-directories in current directory\r
- will be stored in DirectoryMenu for future use.\r
-\r
- @param CallbackData The BMM context data.\r
- @param MenuEntry The Menu Entry.\r
-\r
- @retval EFI_SUCCESS Get files from current dir successfully.\r
- @return Other value if can't get files from current dir.\r
-\r
-**/\r
-EFI_STATUS\r
-BOpt_FindFiles (\r
- IN BMM_CALLBACK_DATA *CallbackData,\r
- IN BM_MENU_ENTRY *MenuEntry\r
- )\r
-{\r
- EFI_FILE_HANDLE NewDir;\r
- EFI_FILE_HANDLE Dir;\r
- EFI_FILE_INFO *DirInfo;\r
- UINTN BufferSize;\r
- UINTN DirBufferSize;\r
- BM_MENU_ENTRY *NewMenuEntry;\r
- BM_FILE_CONTEXT *FileContext;\r
- BM_FILE_CONTEXT *NewFileContext;\r
- UINTN Pass;\r
- EFI_STATUS Status;\r
- UINTN OptionNumber;\r
-\r
- FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext;\r
- Dir = FileContext->FHandle;\r
- OptionNumber = 0;\r
- //\r
- // Open current directory to get files from it\r
- //\r
- Status = Dir->Open (\r
- Dir,\r
- &NewDir,\r
- FileContext->FileName,\r
- EFI_FILE_READ_ONLY,\r
- 0\r
- );\r
- if (!FileContext->IsRoot) {\r
- Dir->Close (Dir);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- DirInfo = EfiLibFileInfo (NewDir);\r
- if (DirInfo == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- if ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- FileContext->DevicePath = FileDevicePath (\r
- FileContext->Handle,\r
- FileContext->FileName\r
- );\r
-\r
- DirBufferSize = sizeof (EFI_FILE_INFO) + 1024;\r
- DirInfo = AllocateZeroPool (DirBufferSize);\r
- if (DirInfo == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- //\r
- // Get all files in current directory\r
- // Pass 1 to get Directories\r
- // Pass 2 to get files that are EFI images\r
- //\r
- for (Pass = 1; Pass <= 2; Pass++) {\r
- NewDir->SetPosition (NewDir, 0);\r
- for (;;) {\r
- BufferSize = DirBufferSize;\r
- Status = NewDir->Read (NewDir, &BufferSize, DirInfo);\r
- if (EFI_ERROR (Status) || BufferSize == 0) {\r
- break;\r
- }\r
-\r
- if (((DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0 && Pass == 2) ||\r
- ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && Pass == 1)\r
- ) {\r
- //\r
- // Pass 1 is for Directories\r
- // Pass 2 is for file names\r
- //\r
- continue;\r
- }\r
-\r
- if (!(BOpt_IsEfiImageName (DirInfo->FileName) || (DirInfo->Attribute & EFI_FILE_DIRECTORY) != 0)) {\r
- //\r
- // Slip file unless it is a directory entry or a .EFI file\r
- //\r
- continue;\r
- }\r
-\r
- NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT);\r
- if (NULL == NewMenuEntry) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext;\r
- NewFileContext->Handle = FileContext->Handle;\r
- NewFileContext->FileName = BOpt_AppendFileName (\r
- FileContext->FileName,\r
- DirInfo->FileName\r
- );\r
- NewFileContext->FHandle = NewDir;\r
- NewFileContext->DevicePath = FileDevicePath (\r
- NewFileContext->Handle,\r
- NewFileContext->FileName\r
- );\r
- NewMenuEntry->HelpString = NULL;\r
-\r
- MenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
- CallbackData,\r
- FileOptionStrDepository\r
- );\r
-\r
- NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY);\r
-\r
- if (NewFileContext->IsDir) {\r
- BufferSize = StrLen (DirInfo->FileName) * 2 + 6;\r
- NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize);\r
-\r
- UnicodeSPrint (\r
- NewMenuEntry->DisplayString,\r
- BufferSize,\r
- L"<%s>",\r
- DirInfo->FileName\r
- );\r
-\r
- } else {\r
- NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName);\r
- }\r
-\r
- NewFileContext->IsRoot = FALSE;\r
- NewFileContext->IsLoadFile = FALSE;\r
- NewFileContext->IsRemovableMedia = FALSE;\r
-\r
- NewMenuEntry->OptionNumber = OptionNumber;\r
- OptionNumber++;\r
- InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link);\r
- }\r
- }\r
-\r
- DirectoryMenu.MenuNumber = OptionNumber;\r
- FreePool (DirInfo);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().\r
-\r
- @retval EFI_SUCCESS The function complete successfully.\r
- @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.\r
-\r
-**/\r
-EFI_STATUS\r
-BOpt_GetLegacyOptions (\r
- VOID\r
- )\r
-{\r
- BM_MENU_ENTRY *NewMenuEntry;\r
- BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext;\r
- EFI_STATUS Status;\r
- EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
- UINT16 HddCount;\r
- HDD_INFO *HddInfo;\r
- UINT16 BbsCount;\r
- BBS_TABLE *BbsTable;\r
- UINT16 Index;\r
- CHAR16 DescString[100];\r
- UINTN FDNum;\r
- UINTN HDNum;\r
- UINTN CDNum;\r
- UINTN NETNum;\r
- UINTN BEVNum;\r
-\r
- NewMenuEntry = NULL;\r
- HddInfo = NULL;\r
- BbsTable = NULL;\r
- BbsCount = 0;\r
-\r
- //\r
- // Initialize Bbs Table Context from BBS info data\r
- //\r
- InitializeListHead (&LegacyFDMenu.Head);\r
- InitializeListHead (&LegacyHDMenu.Head);\r
- InitializeListHead (&LegacyCDMenu.Head);\r
- InitializeListHead (&LegacyNETMenu.Head);\r
- InitializeListHead (&LegacyBEVMenu.Head);\r
-\r
- Status = gBS->LocateProtocol (\r
- &gEfiLegacyBiosProtocolGuid,\r
- NULL,\r
- (VOID **) &LegacyBios\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- Status = LegacyBios->GetBbsInfo (\r
- LegacyBios,\r
- &HddCount,\r
- &HddInfo,\r
- &BbsCount,\r
- &BbsTable\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- FDNum = 0;\r
- HDNum = 0;\r
- CDNum = 0;\r
- NETNum = 0;\r
- BEVNum = 0;\r
-\r
- for (Index = 0; Index < BbsCount; Index++) {\r
- if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) ||\r
- (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority)\r
- ) {\r
- continue;\r
- }\r
-\r
- NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT);\r
- if (NULL == NewMenuEntry) {\r
- break;\r
- }\r
-\r
- NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext;\r
- NewLegacyDevContext->BbsEntry = &BbsTable[Index];\r
- NewLegacyDevContext->BbsIndex = Index;\r
- NewLegacyDevContext->BbsCount = BbsCount;\r
- BdsBuildLegacyDevNameString (\r
- &BbsTable[Index],\r
- Index,\r
- sizeof (DescString),\r
- DescString\r
- );\r
- NewLegacyDevContext->Description = AllocateCopyPool (StrSize (DescString), DescString);\r
- if (NULL == NewLegacyDevContext->Description) {\r
- break;\r
- }\r
-\r
- NewMenuEntry->DisplayString = NewLegacyDevContext->Description;\r
- NewMenuEntry->HelpString = NULL;\r
-\r
- switch (BbsTable[Index].DeviceType) {\r
- case BBS_FLOPPY:\r
- InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link);\r
- FDNum++;\r
- break;\r
-\r
- case BBS_HARDDISK:\r
- InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link);\r
- HDNum++;\r
- break;\r
-\r
- case BBS_CDROM:\r
- InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link);\r
- CDNum++;\r
- break;\r
-\r
- case BBS_EMBED_NETWORK:\r
- InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link);\r
- NETNum++;\r
- break;\r
-\r
- case BBS_BEV_DEVICE:\r
- InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link);\r
- BEVNum++;\r
- break;\r
- }\r
- }\r
-\r
- if (Index != BbsCount) {\r
- BOpt_FreeLegacyOptions ();\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- LegacyFDMenu.MenuNumber = FDNum;\r
- LegacyHDMenu.MenuNumber = HDNum;\r
- LegacyCDMenu.MenuNumber = CDNum;\r
- LegacyNETMenu.MenuNumber = NETNum;\r
- LegacyBEVMenu.MenuNumber = BEVNum;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Free out resouce allocated from Legacy Boot Options.\r
-\r
-**/\r
-VOID\r
-BOpt_FreeLegacyOptions (\r
- VOID\r
- )\r
-{\r
- BOpt_FreeMenu (&LegacyFDMenu);\r
- BOpt_FreeMenu (&LegacyHDMenu);\r
- BOpt_FreeMenu (&LegacyCDMenu);\r
- BOpt_FreeMenu (&LegacyNETMenu);\r
- BOpt_FreeMenu (&LegacyBEVMenu);\r
-}\r
-\r
-/**\r
-\r
- Build the BootOptionMenu according to BootOrder Variable.\r
- This Routine will access the Boot#### to get EFI_LOAD_OPTION.\r
-\r
- @param CallbackData The BMM context data.\r
-\r
- @return EFI_NOT_FOUND Fail to find "BootOrder" variable.\r
- @return EFI_SUCESS Success build boot option menu.\r
-\r
-**/\r
-EFI_STATUS\r
-BOpt_GetBootOptions (\r
- IN BMM_CALLBACK_DATA *CallbackData\r
- )\r
-{\r
- UINTN Index;\r
- UINT16 BootString[10];\r
- UINT8 *LoadOptionFromVar;\r
- UINT8 *LoadOption;\r
- UINTN BootOptionSize;\r
- BOOLEAN BootNextFlag;\r
- UINT16 *BootOrderList;\r
- UINTN BootOrderListSize;\r
- UINT16 *BootNext;\r
- UINTN BootNextSize;\r
- BM_MENU_ENTRY *NewMenuEntry;\r
- BM_LOAD_CONTEXT *NewLoadContext;\r
- UINT8 *LoadOptionPtr;\r
- UINTN StringSize;\r
- UINTN OptionalDataSize;\r
- UINT8 *LoadOptionEnd;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- UINTN MenuCount;\r
- UINT8 *Ptr;\r
-\r
- MenuCount = 0;\r
- BootOrderListSize = 0;\r
- BootNextSize = 0;\r
- BootOrderList = NULL;\r
- BootNext = NULL;\r
- LoadOptionFromVar = NULL;\r
- BOpt_FreeMenu (&BootOptionMenu);\r
- InitializeListHead (&BootOptionMenu.Head);\r
-\r
- //\r
- // Get the BootOrder from the Var\r
- //\r
- BootOrderList = BdsLibGetVariableAndSize (\r
- L"BootOrder",\r
- &gEfiGlobalVariableGuid,\r
- &BootOrderListSize\r
- );\r
- if (BootOrderList == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Get the BootNext from the Var\r
- //\r
- BootNext = BdsLibGetVariableAndSize (\r
- L"BootNext",\r
- &gEfiGlobalVariableGuid,\r
- &BootNextSize\r
- );\r
-\r
- if (BootNext != NULL) {\r
- if (BootNextSize != sizeof (UINT16)) {\r
- FreePool (BootNext);\r
- BootNext = NULL;\r
- }\r
- }\r
-\r
- for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) {\r
- UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]);\r
- //\r
- // Get all loadoptions from the VAR\r
- //\r
- LoadOptionFromVar = BdsLibGetVariableAndSize (\r
- BootString,\r
- &gEfiGlobalVariableGuid,\r
- &BootOptionSize\r
- );\r
- if (LoadOptionFromVar == NULL) {\r
- continue;\r
- }\r
-\r
- LoadOption = AllocateZeroPool (BootOptionSize);\r
- if (LoadOption == NULL) {\r
- continue;\r
- }\r
-\r
- CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize);\r
- FreePool (LoadOptionFromVar);\r
-\r
- if (BootNext != NULL) {\r
- BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]);\r
- } else {\r
- BootNextFlag = FALSE;\r
- }\r
-\r
- if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) {\r
- FreePool (LoadOption);\r
- continue;\r
- }\r
- //\r
- // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.\r
- // the buffer allocated already should be freed before returning.\r
- //\r
- NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
- if (NULL == NewMenuEntry) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
-\r
- LoadOptionPtr = LoadOption;\r
- LoadOptionEnd = LoadOption + BootOptionSize;\r
-\r
- NewMenuEntry->OptionNumber = BootOrderList[Index];\r
- NewLoadContext->LoadOptionModified = FALSE;\r
- NewLoadContext->Deleted = FALSE;\r
- NewLoadContext->IsBootNext = BootNextFlag;\r
-\r
- //\r
- // Is a Legacy Device?\r
- //\r
- Ptr = (UINT8 *) LoadOption;\r
-\r
- //\r
- // Attribute = *(UINT32 *)Ptr;\r
- //\r
- Ptr += sizeof (UINT32);\r
-\r
- //\r
- // FilePathSize = *(UINT16 *)Ptr;\r
- //\r
- Ptr += sizeof (UINT16);\r
-\r
- //\r
- // Description = (CHAR16 *)Ptr;\r
- //\r
- Ptr += StrSize ((CHAR16 *) Ptr);\r
-\r
- //\r
- // Now Ptr point to Device Path\r
- //\r
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr;\r
- if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) {\r
- NewLoadContext->IsLegacy = TRUE;\r
- } else {\r
- NewLoadContext->IsLegacy = FALSE;\r
- }\r
- //\r
- // LoadOption is a pointer type of UINT8\r
- // for easy use with following LOAD_OPTION\r
- // embedded in this struct\r
- //\r
- NewLoadContext->LoadOption = LoadOption;\r
- NewLoadContext->LoadOptionSize = BootOptionSize;\r
-\r
- NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
- NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
-\r
- NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
-\r
- LoadOptionPtr += sizeof (UINT32);\r
-\r
- NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
- LoadOptionPtr += sizeof (UINT16);\r
-\r
- StringSize = StrSize((UINT16*)LoadOptionPtr);\r
-\r
- NewLoadContext->Description = AllocateCopyPool (StrSize((UINT16*)LoadOptionPtr), LoadOptionPtr);\r
- ASSERT (NewLoadContext->Description != NULL);\r
-\r
- NewMenuEntry->DisplayString = NewLoadContext->Description;\r
-\r
- LoadOptionPtr += StringSize;\r
-\r
- NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
- ASSERT (NewLoadContext->FilePathList != NULL);\r
- CopyMem (\r
- NewLoadContext->FilePathList,\r
- (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
- NewLoadContext->FilePathListLength\r
- );\r
-\r
- NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
- NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
- CallbackData,\r
- BootOptionStrDepository\r
- );\r
- NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
- CallbackData,\r
- BootOptionHelpStrDepository\r
- );\r
- LoadOptionPtr += NewLoadContext->FilePathListLength;\r
-\r
- if (LoadOptionPtr < LoadOptionEnd) {\r
- OptionalDataSize = BootOptionSize -\r
- sizeof (UINT32) -\r
- sizeof (UINT16) -\r
- StringSize -\r
- NewLoadContext->FilePathListLength;\r
-\r
- NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
- ASSERT (NewLoadContext->OptionalData != NULL);\r
- CopyMem (\r
- NewLoadContext->OptionalData,\r
- LoadOptionPtr,\r
- OptionalDataSize\r
- );\r
-\r
- NewLoadContext->OptionalDataSize = OptionalDataSize;\r
- }\r
-\r
- InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link);\r
- MenuCount++;\r
- }\r
-\r
- if (BootNext != NULL) {\r
- FreePool (BootNext);\r
- }\r
- if (BootOrderList != NULL) {\r
- FreePool (BootOrderList);\r
- }\r
- BootOptionMenu.MenuNumber = MenuCount;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-\r
- Append file name to existing file name.\r
-\r
- @param Str1 The existing file name\r
- @param Str2 The file name to be appended\r
-\r
- @return Allocate a new string to hold the appended result.\r
- Caller is responsible to free the returned string.\r
-\r
-**/\r
-CHAR16 *\r
-BOpt_AppendFileName (\r
- IN CHAR16 *Str1,\r
- IN CHAR16 *Str2\r
- )\r
-{\r
- UINTN Size1;\r
- UINTN Size2;\r
- UINTN MaxLen;\r
- CHAR16 *Str;\r
- CHAR16 *TmpStr;\r
- CHAR16 *Ptr;\r
- CHAR16 *LastSlash;\r
-\r
- Size1 = StrSize (Str1);\r
- Size2 = StrSize (Str2);\r
- MaxLen = (Size1 + Size2 + sizeof (CHAR16)) / sizeof (CHAR16);\r
- Str = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
- ASSERT (Str != NULL);\r
-\r
- TmpStr = AllocateZeroPool (MaxLen * sizeof (CHAR16));\r
- ASSERT (TmpStr != NULL);\r
-\r
- StrCatS (Str, MaxLen, Str1);\r
- if (!((*Str == '\\') && (*(Str + 1) == 0))) {\r
- StrCatS (Str, MaxLen, L"\\");\r
- }\r
-\r
- StrCatS (Str, MaxLen, Str2);\r
-\r
- Ptr = Str;\r
- LastSlash = Str;\r
- while (*Ptr != 0) {\r
- if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) == L'\\') {\r
- //\r
- // Convert "\Name\..\" to "\"\r
- // DO NOT convert the .. if it is at the end of the string. This will\r
- // break the .. behavior in changing directories.\r
- //\r
-\r
- //\r
- // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings\r
- // that overlap.\r
- //\r
- StrCpyS (TmpStr, MaxLen, Ptr + 3);\r
- StrCpyS (LastSlash, MaxLen - ((UINTN) LastSlash - (UINTN) Str) / sizeof (CHAR16), TmpStr);\r
- Ptr = LastSlash;\r
- } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') {\r
- //\r
- // Convert a "\.\" to a "\"\r
- //\r
-\r
- //\r
- // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings\r
- // that overlap.\r
- //\r
- StrCpyS (TmpStr, MaxLen, Ptr + 2);\r
- StrCpyS (Ptr, MaxLen - ((UINTN) Ptr - (UINTN) Str) / sizeof (CHAR16), TmpStr);\r
- Ptr = LastSlash;\r
- } else if (*Ptr == '\\') {\r
- LastSlash = Ptr;\r
- }\r
-\r
- Ptr++;\r
- }\r
-\r
- FreePool (TmpStr);\r
-\r
- return Str;\r
-}\r
-\r
-/**\r
-\r
- Check whether current FileName point to a valid\r
- Efi Image File.\r
-\r
- @param FileName File need to be checked.\r
-\r
- @retval TRUE Is Efi Image\r
- @retval FALSE Not a valid Efi Image\r
-\r
-**/\r
-BOOLEAN\r
-BOpt_IsEfiImageName (\r
- IN UINT16 *FileName\r
- )\r
-{\r
- //\r
- // Search for ".efi" extension\r
- //\r
- while (*FileName != L'\0') {\r
- if (FileName[0] == '.') {\r
- if (FileName[1] == 'e' || FileName[1] == 'E') {\r
- if (FileName[2] == 'f' || FileName[2] == 'F') {\r
- if (FileName[3] == 'i' || FileName[3] == 'I') {\r
- return TRUE;\r
- } else if (FileName[3] == 0x0000) {\r
- return FALSE;\r
- }\r
- } else if (FileName[2] == 0x0000) {\r
- return FALSE;\r
- }\r
- } else if (FileName[1] == 0x0000) {\r
- return FALSE;\r
- }\r
- }\r
-\r
- FileName += 1;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-\r
-/**\r
-\r
- Find drivers that will be added as Driver#### variables from handles\r
- in current system environment\r
- All valid handles in the system except those consume SimpleFs, LoadFile\r
- are stored in DriverMenu for future use.\r
-\r
- @retval EFI_SUCCESS The function complets successfully.\r
- @return Other value if failed to build the DriverMenu.\r
-\r
-**/\r
-EFI_STATUS\r
-BOpt_FindDrivers (\r
- VOID\r
- )\r
-{\r
- UINTN NoDevicePathHandles;\r
- EFI_HANDLE *DevicePathHandle;\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- BM_MENU_ENTRY *NewMenuEntry;\r
- BM_HANDLE_CONTEXT *NewHandleContext;\r
- EFI_HANDLE CurHandle;\r
- UINTN OptionNumber;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;\r
- EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
-\r
- SimpleFs = NULL;\r
- LoadFile = NULL;\r
-\r
- InitializeListHead (&DriverMenu.Head);\r
-\r
- //\r
- // At first, get all handles that support Device Path\r
- // protocol which is the basic requirement for\r
- // Driver####\r
- //\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiDevicePathProtocolGuid,\r
- NULL,\r
- &NoDevicePathHandles,\r
- &DevicePathHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- OptionNumber = 0;\r
- for (Index = 0; Index < NoDevicePathHandles; Index++) {\r
- CurHandle = DevicePathHandle[Index];\r
-\r
- Status = gBS->HandleProtocol (\r
- CurHandle,\r
- &gEfiSimpleFileSystemProtocolGuid,\r
- (VOID **) &SimpleFs\r
- );\r
- if (Status == EFI_SUCCESS) {\r
- continue;\r
- }\r
-\r
- Status = gBS->HandleProtocol (\r
- CurHandle,\r
- &gEfiLoadFileProtocolGuid,\r
- (VOID **) &LoadFile\r
- );\r
- if (Status == EFI_SUCCESS) {\r
- continue;\r
- }\r
-\r
- NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT);\r
- if (NULL == NewMenuEntry) {\r
- FreePool (DevicePathHandle);\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext;\r
- NewHandleContext->Handle = CurHandle;\r
- NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle);\r
- NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath);\r
- NewMenuEntry->HelpString = NULL;\r
- NewMenuEntry->OptionNumber = OptionNumber;\r
- OptionNumber++;\r
- InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link);\r
-\r
- }\r
-\r
- if (DevicePathHandle != NULL) {\r
- FreePool (DevicePathHandle);\r
- }\r
-\r
- DriverMenu.MenuNumber = OptionNumber;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-\r
- Get the Option Number that has not been allocated for use.\r
-\r
- @param Type The type of Option.\r
-\r
- @return The available Option Number.\r
-\r
-**/\r
-UINT16\r
-BOpt_GetOptionNumber (\r
- CHAR16 *Type\r
- )\r
-{\r
- UINT16 *OrderList;\r
- UINTN OrderListSize;\r
- UINTN Index;\r
- CHAR16 StrTemp[20];\r
- UINT16 *OptionBuffer;\r
- UINT16 OptionNumber;\r
- UINTN OptionSize;\r
-\r
- OrderListSize = 0;\r
- OrderList = NULL;\r
- OptionNumber = 0;\r
- Index = 0;\r
-\r
- UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%sOrder", Type);\r
-\r
- OrderList = BdsLibGetVariableAndSize (\r
- StrTemp,\r
- &gEfiGlobalVariableGuid,\r
- &OrderListSize\r
- );\r
-\r
- for (OptionNumber = 0; ; OptionNumber++) {\r
- if (OrderList != NULL) {\r
- for (Index = 0; Index < OrderListSize / sizeof (UINT16); Index++) {\r
- if (OptionNumber == OrderList[Index]) {\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if (Index < OrderListSize / sizeof (UINT16)) {\r
- //\r
- // The OptionNumber occurs in the OrderList, continue to use next one\r
- //\r
- continue;\r
- }\r
- UnicodeSPrint (StrTemp, sizeof (StrTemp), L"%s%04x", Type, (UINTN) OptionNumber);\r
- DEBUG((EFI_D_ERROR,"Option = %s\n", StrTemp));\r
- OptionBuffer = BdsLibGetVariableAndSize (\r
- StrTemp,\r
- &gEfiGlobalVariableGuid,\r
- &OptionSize\r
- );\r
- if (NULL == OptionBuffer) {\r
- //\r
- // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it\r
- //\r
- break;\r
- }\r
- }\r
-\r
- return OptionNumber;\r
-}\r
-\r
-/**\r
-\r
- Get the Option Number for Boot#### that does not used.\r
-\r
- @return The available Option Number.\r
-\r
-**/\r
-UINT16\r
-BOpt_GetBootOptionNumber (\r
- VOID\r
- )\r
-{\r
- return BOpt_GetOptionNumber (L"Boot");\r
-}\r
-\r
-/**\r
-\r
- Get the Option Number for Driver#### that does not used.\r
-\r
- @return The unused Option Number.\r
-\r
-**/\r
-UINT16\r
-BOpt_GetDriverOptionNumber (\r
- VOID\r
- )\r
-{\r
- return BOpt_GetOptionNumber (L"Driver");\r
-}\r
-\r
-/**\r
-\r
- Build up all DriverOptionMenu\r
-\r
- @param CallbackData The BMM context data.\r
-\r
- @retval EFI_SUCESS The functin completes successfully.\r
- @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.\r
- @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.\r
-\r
-**/\r
-EFI_STATUS\r
-BOpt_GetDriverOptions (\r
- IN BMM_CALLBACK_DATA *CallbackData\r
- )\r
-{\r
- UINTN Index;\r
- UINT16 DriverString[12];\r
- UINT8 *LoadOptionFromVar;\r
- UINT8 *LoadOption;\r
- UINTN DriverOptionSize;\r
-\r
- UINT16 *DriverOrderList;\r
- UINTN DriverOrderListSize;\r
- BM_MENU_ENTRY *NewMenuEntry;\r
- BM_LOAD_CONTEXT *NewLoadContext;\r
- UINT8 *LoadOptionPtr;\r
- UINTN StringSize;\r
- UINTN OptionalDataSize;\r
- UINT8 *LoadOptionEnd;\r
-\r
- DriverOrderListSize = 0;\r
- DriverOrderList = NULL;\r
- DriverOptionSize = 0;\r
- LoadOptionFromVar = NULL;\r
- BOpt_FreeMenu (&DriverOptionMenu);\r
- InitializeListHead (&DriverOptionMenu.Head);\r
- //\r
- // Get the DriverOrder from the Var\r
- //\r
- DriverOrderList = BdsLibGetVariableAndSize (\r
- L"DriverOrder",\r
- &gEfiGlobalVariableGuid,\r
- &DriverOrderListSize\r
- );\r
- if (DriverOrderList == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) {\r
- UnicodeSPrint (\r
- DriverString,\r
- sizeof (DriverString),\r
- L"Driver%04x",\r
- DriverOrderList[Index]\r
- );\r
- //\r
- // Get all loadoptions from the VAR\r
- //\r
- LoadOptionFromVar = BdsLibGetVariableAndSize (\r
- DriverString,\r
- &gEfiGlobalVariableGuid,\r
- &DriverOptionSize\r
- );\r
- if (LoadOptionFromVar == NULL) {\r
- continue;\r
- }\r
-\r
- LoadOption = AllocateZeroPool (DriverOptionSize);\r
- if (LoadOption == NULL) {\r
- continue;\r
- }\r
-\r
- CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize);\r
- FreePool (LoadOptionFromVar);\r
-\r
- NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT);\r
- if (NULL == NewMenuEntry) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
- LoadOptionPtr = LoadOption;\r
- LoadOptionEnd = LoadOption + DriverOptionSize;\r
- NewMenuEntry->OptionNumber = DriverOrderList[Index];\r
- NewLoadContext->LoadOptionModified = FALSE;\r
- NewLoadContext->Deleted = FALSE;\r
- NewLoadContext->IsLegacy = FALSE;\r
-\r
- //\r
- // LoadOption is a pointer type of UINT8\r
- // for easy use with following LOAD_OPTION\r
- // embedded in this struct\r
- //\r
- NewLoadContext->LoadOption = LoadOption;\r
- NewLoadContext->LoadOptionSize = DriverOptionSize;\r
-\r
- NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr;\r
- NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE);\r
-\r
- NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT);\r
-\r
- LoadOptionPtr += sizeof (UINT32);\r
-\r
- NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr;\r
- LoadOptionPtr += sizeof (UINT16);\r
-\r
- StringSize = StrSize ((UINT16 *) LoadOptionPtr);\r
- NewLoadContext->Description = AllocateZeroPool (StringSize);\r
- ASSERT (NewLoadContext->Description != NULL);\r
- CopyMem (\r
- NewLoadContext->Description,\r
- (UINT16 *) LoadOptionPtr,\r
- StringSize\r
- );\r
- NewMenuEntry->DisplayString = NewLoadContext->Description;\r
-\r
- LoadOptionPtr += StringSize;\r
-\r
- NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength);\r
- ASSERT (NewLoadContext->FilePathList != NULL);\r
- CopyMem (\r
- NewLoadContext->FilePathList,\r
- (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr,\r
- NewLoadContext->FilePathListLength\r
- );\r
-\r
- NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList);\r
- NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository (\r
- CallbackData,\r
- DriverOptionStrDepository\r
- );\r
- NewMenuEntry->HelpStringToken = GetStringTokenFromDepository (\r
- CallbackData,\r
- DriverOptionHelpStrDepository\r
- );\r
- LoadOptionPtr += NewLoadContext->FilePathListLength;\r
-\r
- if (LoadOptionPtr < LoadOptionEnd) {\r
- OptionalDataSize = DriverOptionSize -\r
- sizeof (UINT32) -\r
- sizeof (UINT16) -\r
- StringSize -\r
- NewLoadContext->FilePathListLength;\r
-\r
- NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize);\r
- ASSERT (NewLoadContext->OptionalData != NULL);\r
- CopyMem (\r
- NewLoadContext->OptionalData,\r
- LoadOptionPtr,\r
- OptionalDataSize\r
- );\r
-\r
- NewLoadContext->OptionalDataSize = OptionalDataSize;\r
- }\r
-\r
- InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link);\r
-\r
- }\r
-\r
- if (DriverOrderList != NULL) {\r
- FreePool (DriverOrderList);\r
- }\r
- DriverOptionMenu.MenuNumber = Index;\r
- return EFI_SUCCESS;\r
-\r
-}\r
-\r
-/**\r
- Get option number according to Boot#### and BootOrder variable.\r
- The value is saved as #### + 1.\r
-\r
- @param CallbackData The BMM context data.\r
-**/\r
-VOID\r
-GetBootOrder (\r
- IN BMM_CALLBACK_DATA *CallbackData\r
- )\r
-{\r
- BMM_FAKE_NV_DATA *BmmConfig;\r
- UINT16 Index;\r
- UINT16 OptionOrderIndex;\r
- UINTN DeviceType;\r
- BM_MENU_ENTRY *NewMenuEntry;\r
- BM_LOAD_CONTEXT *NewLoadContext;\r
-\r
- ASSERT (CallbackData != NULL);\r
-\r
- DeviceType = (UINTN) -1;\r
- BmmConfig = &CallbackData->BmmFakeNvData;\r
- ZeroMem (BmmConfig->BootOptionOrder, sizeof (BmmConfig->BootOptionOrder));\r
-\r
- for (Index = 0, OptionOrderIndex = 0; ((Index < BootOptionMenu.MenuNumber) &&\r
- (OptionOrderIndex < (sizeof (BmmConfig->BootOptionOrder) / sizeof (BmmConfig->BootOptionOrder[0]))));\r
- Index++) {\r
- NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index);\r
- NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
-\r
- if (NewLoadContext->IsLegacy) {\r
- if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {\r
- DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;\r
- } else {\r
- //\r
- // Only show one legacy boot option for the same device type\r
- // assuming the boot options are grouped by the device type\r
- //\r
- continue;\r
- }\r
- }\r
- BmmConfig->BootOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);\r
- }\r
-}\r
-\r
-/**\r
- According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV\r
- devices list .\r
-\r
- @param CallbackData The BMM context data.\r
-**/\r
-VOID\r
-GetLegacyDeviceOrder (\r
- IN BMM_CALLBACK_DATA *CallbackData\r
- )\r
-{\r
- UINTN Index;\r
- UINTN OptionIndex;\r
- UINT16 PageIdList[5];\r
- UINTN PageNum;\r
- UINTN VarSize;\r
- UINT8 *VarData;\r
- UINT8 *WorkingVarData;\r
- LEGACY_DEV_ORDER_ENTRY *DevOrder;\r
- UINT16 VarDevOrder;\r
- UINT8 *DisMap;\r
- BM_MENU_OPTION *OptionMenu;\r
- BBS_TYPE BbsType;\r
- UINT8 *LegacyOrder;\r
- UINT8 *OldData;\r
- UINTN Pos;\r
- UINTN Bit;\r
-\r
- ASSERT (CallbackData != NULL);\r
-\r
- PageIdList[0] = FORM_SET_FD_ORDER_ID;\r
- PageIdList[1] = FORM_SET_HD_ORDER_ID;\r
- PageIdList[2] = FORM_SET_CD_ORDER_ID;\r
- PageIdList[3] = FORM_SET_NET_ORDER_ID;\r
- PageIdList[4] = FORM_SET_BEV_ORDER_ID;\r
- OptionMenu = NULL;\r
- BbsType = 0;\r
- LegacyOrder = NULL;\r
- OldData = NULL;\r
- DisMap = ZeroMem (CallbackData->BmmFakeNvData.DisableMap, sizeof (CallbackData->BmmFakeNvData.DisableMap));\r
- PageNum = ARRAY_SIZE (PageIdList);\r
- VarData = BdsLibGetVariableAndSize (\r
- VAR_LEGACY_DEV_ORDER,\r
- &gEfiLegacyDevOrderVariableGuid,\r
- &VarSize\r
- );\r
-\r
- for (Index = 0; Index < PageNum; Index++) {\r
- switch (PageIdList[Index]) {\r
-\r
- case FORM_SET_FD_ORDER_ID:\r
- OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu;\r
- BbsType = BBS_FLOPPY;\r
- LegacyOrder = CallbackData->BmmFakeNvData.LegacyFD;\r
- OldData = CallbackData->BmmOldFakeNVData.LegacyFD;\r
- break;\r
-\r
- case FORM_SET_HD_ORDER_ID:\r
- OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu;\r
- BbsType = BBS_HARDDISK;\r
- LegacyOrder = CallbackData->BmmFakeNvData.LegacyHD;\r
- OldData = CallbackData->BmmOldFakeNVData.LegacyHD;\r
- break;\r
-\r
- case FORM_SET_CD_ORDER_ID:\r
- OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu;\r
- BbsType = BBS_CDROM;\r
- LegacyOrder = CallbackData->BmmFakeNvData.LegacyCD;\r
- OldData = CallbackData->BmmOldFakeNVData.LegacyCD;\r
- break;\r
-\r
- case FORM_SET_NET_ORDER_ID:\r
- OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu;\r
- BbsType = BBS_EMBED_NETWORK;\r
- LegacyOrder = CallbackData->BmmFakeNvData.LegacyNET;\r
- OldData = CallbackData->BmmOldFakeNVData.LegacyNET;\r
- break;\r
-\r
- default:\r
- ASSERT (PageIdList[Index] == FORM_SET_BEV_ORDER_ID);\r
- OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu;\r
- BbsType = BBS_BEV_DEVICE;\r
- LegacyOrder = CallbackData->BmmFakeNvData.LegacyBEV;\r
- OldData = CallbackData->BmmOldFakeNVData.LegacyBEV;\r
- break;\r
- }\r
-\r
- if (NULL != VarData) {\r
- WorkingVarData = VarData;\r
- DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData;\r
- while (WorkingVarData < VarData + VarSize) {\r
- if (DevOrder->BbsType == BbsType) {\r
- break;\r
- }\r
-\r
- WorkingVarData = (UINT8 *)((UINTN)WorkingVarData + sizeof (BBS_TYPE));\r
- WorkingVarData += *(UINT16 *) WorkingVarData;\r
- DevOrder = (LEGACY_DEV_ORDER_ENTRY *) WorkingVarData;\r
- }\r
- for (OptionIndex = 0; OptionIndex < OptionMenu->MenuNumber; OptionIndex++) {\r
- VarDevOrder = *(UINT16 *) ((UINTN) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + OptionIndex * sizeof (UINT16));\r
- if (0xFF00 == (VarDevOrder & 0xFF00)) {\r
- LegacyOrder[OptionIndex] = 0xFF;\r
- Pos = (VarDevOrder & 0xFF) / 8;\r
- Bit = 7 - ((VarDevOrder & 0xFF) % 8);\r
- DisMap[Pos] = (UINT8) (DisMap[Pos] | (UINT8) (1 << Bit));\r
- } else {\r
- LegacyOrder[OptionIndex] = (UINT8) (VarDevOrder & 0xFF);\r
- }\r
- }\r
- CopyMem (OldData, LegacyOrder, 100);\r
- }\r
- }\r
-}\r
-\r
-/**\r
- Get driver option order from globalc DriverOptionMenu.\r
-\r
- @param CallbackData The BMM context data.\r
-\r
-**/\r
-VOID\r
-GetDriverOrder (\r
- IN BMM_CALLBACK_DATA *CallbackData\r
- )\r
-{\r
- BMM_FAKE_NV_DATA *BmmConfig;\r
- UINT16 Index;\r
- UINT16 OptionOrderIndex;\r
- UINTN DeviceType;\r
- BM_MENU_ENTRY *NewMenuEntry;\r
- BM_LOAD_CONTEXT *NewLoadContext;\r
-\r
- ASSERT (CallbackData != NULL);\r
-\r
- DeviceType = (UINTN) -1;\r
- BmmConfig = &CallbackData->BmmFakeNvData;\r
- ZeroMem (BmmConfig->DriverOptionOrder, sizeof (BmmConfig->DriverOptionOrder));\r
-\r
- for (Index = 0, OptionOrderIndex = 0; ((Index < DriverOptionMenu.MenuNumber) &&\r
- (OptionOrderIndex < (sizeof (BmmConfig->DriverOptionOrder) / sizeof (BmmConfig->DriverOptionOrder[0]))));\r
- Index++) {\r
- NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index);\r
- NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext;\r
-\r
- if (NewLoadContext->IsLegacy) {\r
- if (((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType != DeviceType) {\r
- DeviceType = ((BBS_BBS_DEVICE_PATH *) NewLoadContext->FilePathList)->DeviceType;\r
- } else {\r
- //\r
- // Only show one legacy boot option for the same device type\r
- // assuming the boot options are grouped by the device type\r
- //\r
- continue;\r
- }\r
- }\r
- BmmConfig->DriverOptionOrder[OptionOrderIndex++] = (UINT32) (NewMenuEntry->OptionNumber + 1);\r
- }\r
-}\r