2 Copyright (c) 2004 - 2008, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 Provide boot option support for Application "BootMaint"
19 Include file system navigation, system handle selection
21 Boot option manipulation
27 #include "BootMaint.h"
28 #include "BBSsupport.h"
31 BOpt_CreateMenuEntry (
37 Create Menu Entry for future use, make all types together
38 in order to reduce code size
41 MenuType Use this parameter to identify current
45 NULL Cannot allocate memory for current menu
47 Others A valid pointer pointing to the allocated
48 memory pool for current menu entry
52 BM_MENU_ENTRY
*MenuEntry
;
56 case BM_LOAD_CONTEXT_SELECT
:
57 ContextSize
= sizeof (BM_LOAD_CONTEXT
);
60 case BM_FILE_CONTEXT_SELECT
:
61 ContextSize
= sizeof (BM_FILE_CONTEXT
);
64 case BM_CONSOLE_CONTEXT_SELECT
:
65 ContextSize
= sizeof (BM_CONSOLE_CONTEXT
);
68 case BM_TERMINAL_CONTEXT_SELECT
:
69 ContextSize
= sizeof (BM_TERMINAL_CONTEXT
);
72 case BM_HANDLE_CONTEXT_SELECT
:
73 ContextSize
= sizeof (BM_HANDLE_CONTEXT
);
76 case BM_LEGACY_DEV_CONTEXT_SELECT
:
77 ContextSize
= sizeof (BM_LEGACY_DEVICE_CONTEXT
);
86 if (0 == ContextSize
) {
90 MenuEntry
= EfiAllocateZeroPool (sizeof (BM_MENU_ENTRY
));
91 if (NULL
== MenuEntry
) {
95 MenuEntry
->VariableContext
= EfiAllocateZeroPool (ContextSize
);
96 if (NULL
== MenuEntry
->VariableContext
) {
97 SafeFreePool (MenuEntry
);
102 MenuEntry
->Signature
= BM_MENU_ENTRY_SIGNATURE
;
103 MenuEntry
->ContextSelection
= MenuType
;
108 BOpt_DestroyMenuEntry (
109 BM_MENU_ENTRY
*MenuEntry
112 Routine Description :
113 Destroy the menu entry passed in
116 The menu entry need to be destroyed
123 BM_LOAD_CONTEXT
*LoadContext
;
124 BM_FILE_CONTEXT
*FileContext
;
125 BM_CONSOLE_CONTEXT
*ConsoleContext
;
126 BM_TERMINAL_CONTEXT
*TerminalContext
;
127 BM_HANDLE_CONTEXT
*HandleContext
;
128 BM_LEGACY_DEVICE_CONTEXT
*LegacyDevContext
;
131 // Select by the type in Menu entry for current context type
133 switch (MenuEntry
->ContextSelection
) {
134 case BM_LOAD_CONTEXT_SELECT
:
135 LoadContext
= (BM_LOAD_CONTEXT
*) MenuEntry
->VariableContext
;
136 SafeFreePool (LoadContext
->FilePathList
);
137 SafeFreePool (LoadContext
->LoadOption
);
138 SafeFreePool (LoadContext
->OptionalData
);
139 SafeFreePool (LoadContext
);
142 case BM_FILE_CONTEXT_SELECT
:
143 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
145 if (!FileContext
->IsRoot
) {
146 SafeFreePool (FileContext
->DevicePath
);
148 if (FileContext
->FHandle
!= NULL
) {
149 FileContext
->FHandle
->Close (FileContext
->FHandle
);
153 SafeFreePool (FileContext
->FileName
);
154 SafeFreePool (FileContext
->Info
);
155 SafeFreePool (FileContext
);
158 case BM_CONSOLE_CONTEXT_SELECT
:
159 ConsoleContext
= (BM_CONSOLE_CONTEXT
*) MenuEntry
->VariableContext
;
160 SafeFreePool (ConsoleContext
->DevicePath
);
161 SafeFreePool (ConsoleContext
);
164 case BM_TERMINAL_CONTEXT_SELECT
:
165 TerminalContext
= (BM_TERMINAL_CONTEXT
*) MenuEntry
->VariableContext
;
166 SafeFreePool (TerminalContext
->DevicePath
);
167 SafeFreePool (TerminalContext
);
170 case BM_HANDLE_CONTEXT_SELECT
:
171 HandleContext
= (BM_HANDLE_CONTEXT
*) MenuEntry
->VariableContext
;
172 SafeFreePool (HandleContext
);
175 case BM_LEGACY_DEV_CONTEXT_SELECT
:
176 LegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) MenuEntry
->VariableContext
;
177 SafeFreePool (LegacyDevContext
);
183 SafeFreePool (MenuEntry
->DisplayString
);
184 if (NULL
!= MenuEntry
->HelpString
) {
185 SafeFreePool (MenuEntry
->HelpString
);
188 SafeFreePool (MenuEntry
);
193 BM_MENU_OPTION
*MenuOption
,
197 Rountine Description :
198 Use this routine to get one particular menu entry in specified
202 MenuOption The menu that we will search
204 MenuNumber The menunubmer that we want
207 The desired menu entry
211 BM_MENU_ENTRY
*NewMenuEntry
;
215 if (MenuNumber
>= MenuOption
->MenuNumber
) {
219 List
= MenuOption
->Head
.ForwardLink
;
220 for (Index
= 0; Index
< MenuNumber
; Index
++) {
221 List
= List
->ForwardLink
;
224 NewMenuEntry
= CR (List
, BM_MENU_ENTRY
, Link
, BM_MENU_ENTRY_SIGNATURE
);
230 BOpt_FindFileSystem (
231 IN BMM_CALLBACK_DATA
*CallbackData
236 Find file systems for current Extensible Firmware
237 Including Handles that support Simple File System
238 protocol, Load File protocol.
240 Building up the FileSystem Menu for user selection
241 All file system will be stored in FsOptionMenu
245 CallbackData - BMM context data
248 EFI_SUCCESS - Success find the file system
249 EFI_OUT_OF_RESOURCES - Can not create menu entry
253 UINTN NoBlkIoHandles
;
254 UINTN NoSimpleFsHandles
;
255 UINTN NoLoadFileHandles
;
256 EFI_HANDLE
*BlkIoHandle
;
257 EFI_HANDLE
*SimpleFsHandle
;
258 EFI_HANDLE
*LoadFileHandle
;
260 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
263 BM_MENU_ENTRY
*MenuEntry
;
264 BM_FILE_CONTEXT
*FileContext
;
268 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
270 BBS_BBS_DEVICE_PATH BbsDevicePathNode
;
271 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
272 BOOLEAN RemovableMedia
;
275 NoSimpleFsHandles
= 0;
276 NoLoadFileHandles
= 0;
278 InitializeListHead (&FsOptionMenu
.Head
);
281 // Locate Handles that support BlockIo protocol
283 Status
= gBS
->LocateHandleBuffer (
285 &gEfiBlockIoProtocolGuid
,
290 if (!EFI_ERROR (Status
)) {
292 for (Index
= 0; Index
< NoBlkIoHandles
; Index
++) {
293 Status
= gBS
->HandleProtocol (
295 &gEfiBlockIoProtocolGuid
,
299 if (EFI_ERROR (Status
)) {
304 // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
306 if (BlkIo
->Media
->RemovableMedia
) {
307 Buffer
= EfiAllocateZeroPool (BlkIo
->Media
->BlockSize
);
308 if (NULL
== Buffer
) {
309 SafeFreePool (BlkIoHandle
);
310 return EFI_OUT_OF_RESOURCES
;
315 BlkIo
->Media
->MediaId
,
317 BlkIo
->Media
->BlockSize
,
320 SafeFreePool (Buffer
);
323 SafeFreePool (BlkIoHandle
);
327 // Locate Handles that support Simple File System protocol
329 Status
= gBS
->LocateHandleBuffer (
331 &gEfiSimpleFileSystemProtocolGuid
,
336 if (!EFI_ERROR (Status
)) {
338 // Find all the instances of the File System prototocol
340 for (Index
= 0; Index
< NoSimpleFsHandles
; Index
++) {
341 Status
= gBS
->HandleProtocol (
342 SimpleFsHandle
[Index
],
343 &gEfiBlockIoProtocolGuid
,
346 if (EFI_ERROR (Status
)) {
348 // If no block IO exists assume it's NOT a removable media
350 RemovableMedia
= FALSE
;
353 // If block IO exists check to see if it's remobable media
355 RemovableMedia
= BlkIo
->Media
->RemovableMedia
;
359 // Allocate pool for this load option
361 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
362 if (NULL
== MenuEntry
) {
363 SafeFreePool (SimpleFsHandle
);
364 return EFI_OUT_OF_RESOURCES
;
367 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
369 FileContext
->Handle
= SimpleFsHandle
[Index
];
370 MenuEntry
->OptionNumber
= Index
;
371 FileContext
->FHandle
= EfiLibOpenRoot (FileContext
->Handle
);
372 if (!FileContext
->FHandle
) {
373 BOpt_DestroyMenuEntry (MenuEntry
);
377 MenuEntry
->HelpString
= DevicePathToStr (DevicePathFromHandle (FileContext
->Handle
));
378 FileContext
->Info
= EfiLibFileSystemVolumeLabelInfo (FileContext
->FHandle
);
379 FileContext
->FileName
= EfiStrDuplicate (L
"\\");
380 FileContext
->DevicePath
= FileDevicePath (
382 FileContext
->FileName
384 FileContext
->IsDir
= TRUE
;
385 FileContext
->IsRoot
= TRUE
;
386 FileContext
->IsRemovableMedia
= RemovableMedia
;
387 FileContext
->IsLoadFile
= FALSE
;
390 // Get current file system's Volume Label
392 if (FileContext
->Info
== NULL
) {
393 VolumeLabel
= L
"NO FILE SYSTEM INFO";
395 if (FileContext
->Info
->VolumeLabel
== NULL
) {
396 VolumeLabel
= L
"NULL VOLUME LABEL";
398 VolumeLabel
= FileContext
->Info
->VolumeLabel
;
399 if (*VolumeLabel
== 0x0000) {
400 VolumeLabel
= L
"NO VOLUME LABEL";
405 TempStr
= MenuEntry
->HelpString
;
406 MenuEntry
->DisplayString
= EfiAllocateZeroPool (MAX_CHAR
);
407 ASSERT (MenuEntry
->DisplayString
!= NULL
);
409 MenuEntry
->DisplayString
,
416 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
420 if (NoSimpleFsHandles
!= 0) {
421 SafeFreePool (SimpleFsHandle
);
424 // Searching for handles that support Load File protocol
426 Status
= gBS
->LocateHandleBuffer (
428 &gEfiLoadFileProtocolGuid
,
434 if (!EFI_ERROR (Status
)) {
435 for (Index
= 0; Index
< NoLoadFileHandles
; Index
++) {
436 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
437 if (NULL
== MenuEntry
) {
438 SafeFreePool (LoadFileHandle
);
439 return EFI_OUT_OF_RESOURCES
;
442 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
443 FileContext
->IsRemovableMedia
= FALSE
;
444 FileContext
->IsLoadFile
= TRUE
;
445 FileContext
->Handle
= LoadFileHandle
[Index
];
446 FileContext
->IsRoot
= TRUE
;
448 FileContext
->DevicePath
= DevicePathFromHandle (FileContext
->Handle
);
450 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
452 TempStr
= MenuEntry
->HelpString
;
453 MenuEntry
->DisplayString
= EfiAllocateZeroPool (MAX_CHAR
);
454 ASSERT (MenuEntry
->DisplayString
!= NULL
);
456 MenuEntry
->DisplayString
,
462 MenuEntry
->OptionNumber
= OptionNumber
;
464 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
468 if (NoLoadFileHandles
!= 0) {
469 SafeFreePool (LoadFileHandle
);
473 // Add Legacy Boot Option Support Here
475 Status
= gBS
->LocateProtocol (
476 &gEfiLegacyBiosProtocolGuid
,
478 (VOID
**) &LegacyBios
480 if (!EFI_ERROR (Status
)) {
482 for (Index
= BBS_TYPE_FLOPPY
; Index
<= BBS_TYPE_EMBEDDED_NETWORK
; Index
++) {
483 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
484 if (NULL
== MenuEntry
) {
485 return EFI_OUT_OF_RESOURCES
;
488 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
490 FileContext
->IsRemovableMedia
= FALSE
;
491 FileContext
->IsLoadFile
= TRUE
;
492 FileContext
->IsBootLegacy
= TRUE
;
493 DeviceType
= (UINT16
) Index
;
494 BbsDevicePathNode
.Header
.Type
= BBS_DEVICE_PATH
;
495 BbsDevicePathNode
.Header
.SubType
= BBS_BBS_DP
;
496 SetDevicePathNodeLength (
497 &BbsDevicePathNode
.Header
,
498 sizeof (BBS_BBS_DEVICE_PATH
)
500 BbsDevicePathNode
.DeviceType
= DeviceType
;
501 BbsDevicePathNode
.StatusFlag
= 0;
502 BbsDevicePathNode
.String
[0] = 0;
503 DevicePath
= AppendDevicePathNode (
505 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevicePathNode
508 FileContext
->DevicePath
= DevicePath
;
509 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
511 TempStr
= MenuEntry
->HelpString
;
512 MenuEntry
->DisplayString
= EfiAllocateZeroPool (MAX_CHAR
);
513 ASSERT (MenuEntry
->DisplayString
!= NULL
);
515 MenuEntry
->DisplayString
,
520 MenuEntry
->OptionNumber
= OptionNumber
;
522 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
526 // Remember how many file system options are here
528 FsOptionMenu
.MenuNumber
= OptionNumber
;
534 BM_MENU_OPTION
*FreeMenu
539 Free resources allocated in Allocate Rountine
542 FreeMenu Menu to be freed
549 BM_MENU_ENTRY
*MenuEntry
;
550 while (!IsListEmpty (&FreeMenu
->Head
)) {
552 FreeMenu
->Head
.ForwardLink
,
555 BM_MENU_ENTRY_SIGNATURE
557 RemoveEntryList (&MenuEntry
->Link
);
558 BOpt_DestroyMenuEntry (MenuEntry
);
564 IN BMM_CALLBACK_DATA
*CallbackData
,
565 IN BM_MENU_ENTRY
*MenuEntry
570 Find files under current directory
571 All files and sub-directories in current directory
572 will be stored in DirectoryMenu for future use.
575 FileOption -- Pointer for Dir to explore
578 TRUE -- Get files from current dir successfully
579 FALSE -- Can't get files from current dir
583 EFI_FILE_HANDLE NewDir
;
585 EFI_FILE_INFO
*DirInfo
;
588 BM_MENU_ENTRY
*NewMenuEntry
;
589 BM_FILE_CONTEXT
*FileContext
;
590 BM_FILE_CONTEXT
*NewFileContext
;
595 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
596 Dir
= FileContext
->FHandle
;
599 // Open current directory to get files from it
604 FileContext
->FileName
,
608 if (!FileContext
->IsRoot
) {
612 if (EFI_ERROR (Status
)) {
616 DirInfo
= EfiLibFileInfo (NewDir
);
618 return EFI_NOT_FOUND
;
621 if (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
622 return EFI_INVALID_PARAMETER
;
625 FileContext
->DevicePath
= FileDevicePath (
627 FileContext
->FileName
630 DirBufferSize
= sizeof (EFI_FILE_INFO
) + 1024;
631 DirInfo
= EfiAllocateZeroPool (DirBufferSize
);
633 return EFI_OUT_OF_RESOURCES
;
636 // Get all files in current directory
637 // Pass 1 to get Directories
638 // Pass 2 to get files that are EFI images
640 for (Pass
= 1; Pass
<= 2; Pass
++) {
641 NewDir
->SetPosition (NewDir
, 0);
643 BufferSize
= DirBufferSize
;
644 Status
= NewDir
->Read (NewDir
, &BufferSize
, DirInfo
);
645 if (EFI_ERROR (Status
) || BufferSize
== 0) {
649 if ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
&& Pass
== 2) ||
650 (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) && Pass
== 1)
653 // Pass 1 is for Directories
654 // Pass 2 is for file names
659 if (!(BOpt_IsEfiImageName (DirInfo
->FileName
) || DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
661 // Slip file unless it is a directory entry or a .EFI file
666 NewMenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
667 if (NULL
== NewMenuEntry
) {
668 return EFI_OUT_OF_RESOURCES
;
671 NewFileContext
= (BM_FILE_CONTEXT
*) NewMenuEntry
->VariableContext
;
672 NewFileContext
->Handle
= FileContext
->Handle
;
673 NewFileContext
->FileName
= BOpt_AppendFileName (
674 FileContext
->FileName
,
677 NewFileContext
->FHandle
= NewDir
;
678 NewFileContext
->DevicePath
= FileDevicePath (
679 NewFileContext
->Handle
,
680 NewFileContext
->FileName
682 NewMenuEntry
->HelpString
= NULL
;
684 MenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
686 FileOptionStrDepository
689 NewFileContext
->IsDir
= (BOOLEAN
) ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
);
691 if (NewFileContext
->IsDir
) {
692 BufferSize
= StrLen (DirInfo
->FileName
) * 2 + 6;
693 NewMenuEntry
->DisplayString
= EfiAllocateZeroPool (BufferSize
);
696 NewMenuEntry
->DisplayString
,
703 NewMenuEntry
->DisplayString
= EfiStrDuplicate (DirInfo
->FileName
);
706 NewFileContext
->IsRoot
= FALSE
;
707 NewFileContext
->IsLoadFile
= FALSE
;
708 NewFileContext
->IsRemovableMedia
= FALSE
;
710 NewMenuEntry
->OptionNumber
= OptionNumber
;
712 InsertTailList (&DirectoryMenu
.Head
, &NewMenuEntry
->Link
);
716 DirectoryMenu
.MenuNumber
= OptionNumber
;
717 SafeFreePool (DirInfo
);
722 BOpt_GetLegacyOptions (
728 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
734 The device info of legacy device.
738 BM_MENU_ENTRY
*NewMenuEntry
;
739 BM_LEGACY_DEVICE_CONTEXT
*NewLegacyDevContext
;
741 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
747 CHAR16 DescString
[100];
760 // Initialize Bbs Table Context from BBS info data
762 InitializeListHead (&LegacyFDMenu
.Head
);
763 InitializeListHead (&LegacyHDMenu
.Head
);
764 InitializeListHead (&LegacyCDMenu
.Head
);
765 InitializeListHead (&LegacyNETMenu
.Head
);
766 InitializeListHead (&LegacyBEVMenu
.Head
);
768 Status
= gBS
->LocateProtocol (
769 &gEfiLegacyBiosProtocolGuid
,
771 (VOID
**) &LegacyBios
773 if (!EFI_ERROR (Status
)) {
774 Status
= LegacyBios
->GetBbsInfo (
781 if (EFI_ERROR (Status
)) {
792 for (Index
= 0; Index
< BbsCount
; Index
++) {
793 if ((BBS_IGNORE_ENTRY
== BbsTable
[Index
].BootPriority
) ||
794 (BBS_DO_NOT_BOOT_FROM
== BbsTable
[Index
].BootPriority
)
799 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT
);
800 if (NULL
== NewMenuEntry
) {
804 NewLegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) NewMenuEntry
->VariableContext
;
805 NewLegacyDevContext
->BbsTable
= &BbsTable
[Index
];
806 NewLegacyDevContext
->Index
= Index
;
807 NewLegacyDevContext
->BbsCount
= BbsCount
;
808 BdsBuildLegacyDevNameString (
814 NewLegacyDevContext
->Description
= EfiAllocateZeroPool (StrSize (DescString
));
815 if (NULL
== NewLegacyDevContext
->Description
) {
819 CopyMem (NewLegacyDevContext
->Description
, DescString
, StrSize (DescString
));
820 NewMenuEntry
->DisplayString
= NewLegacyDevContext
->Description
;
821 NewMenuEntry
->HelpString
= NULL
;
823 switch (BbsTable
[Index
].DeviceType
) {
825 InsertTailList (&LegacyFDMenu
.Head
, &NewMenuEntry
->Link
);
830 InsertTailList (&LegacyHDMenu
.Head
, &NewMenuEntry
->Link
);
835 InsertTailList (&LegacyCDMenu
.Head
, &NewMenuEntry
->Link
);
839 case BBS_EMBED_NETWORK
:
840 InsertTailList (&LegacyNETMenu
.Head
, &NewMenuEntry
->Link
);
845 InsertTailList (&LegacyBEVMenu
.Head
, &NewMenuEntry
->Link
);
851 if (Index
!= BbsCount
) {
852 BOpt_FreeLegacyOptions ();
853 return EFI_OUT_OF_RESOURCES
;
856 LegacyFDMenu
.MenuNumber
= FDNum
;
857 LegacyHDMenu
.MenuNumber
= HDNum
;
858 LegacyCDMenu
.MenuNumber
= CDNum
;
859 LegacyNETMenu
.MenuNumber
= NETNum
;
860 LegacyBEVMenu
.MenuNumber
= BEVNum
;
865 BOpt_FreeLegacyOptions (
869 BOpt_FreeMenu (&LegacyFDMenu
);
870 BOpt_FreeMenu (&LegacyHDMenu
);
871 BOpt_FreeMenu (&LegacyCDMenu
);
872 BOpt_FreeMenu (&LegacyNETMenu
);
873 BOpt_FreeMenu (&LegacyBEVMenu
);
877 BOpt_GetBootOptions (
878 IN BMM_CALLBACK_DATA
*CallbackData
884 Build the BootOptionMenu according to BootOrder Variable.
885 This Routine will access the Boot#### to get EFI_LOAD_OPTION
891 The number of the Var Boot####
896 UINT16 BootString
[10];
897 UINT8
*LoadOptionFromVar
;
899 UINTN BootOptionSize
;
900 BOOLEAN BootNextFlag
;
901 UINT16
*BootOrderList
;
902 UINTN BootOrderListSize
;
905 BM_MENU_ENTRY
*NewMenuEntry
;
906 BM_LOAD_CONTEXT
*NewLoadContext
;
907 UINT8
*LoadOptionPtr
;
909 UINTN OptionalDataSize
;
910 UINT8
*LoadOptionEnd
;
911 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
916 BootOrderListSize
= 0;
918 BootOrderList
= NULL
;
920 LoadOptionFromVar
= NULL
;
921 BOpt_FreeMenu (&BootOptionMenu
);
922 InitializeListHead (&BootOptionMenu
.Head
);
925 // Get the BootOrder from the Var
927 BootOrderList
= BdsLibGetVariableAndSize (
929 &gEfiGlobalVariableGuid
,
934 // Get the BootNext from the Var
936 BootNext
= BdsLibGetVariableAndSize (
938 &gEfiGlobalVariableGuid
,
943 if (BootNextSize
!= sizeof (UINT16
)) {
944 SafeFreePool (BootNext
);
949 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
950 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", BootOrderList
[Index
]);
952 // Get all loadoptions from the VAR
954 LoadOptionFromVar
= BdsLibGetVariableAndSize (
956 &gEfiGlobalVariableGuid
,
959 if (!LoadOptionFromVar
) {
963 LoadOption
= EfiAllocateZeroPool (BootOptionSize
);
968 CopyMem (LoadOption
, LoadOptionFromVar
, BootOptionSize
);
969 SafeFreePool (LoadOptionFromVar
);
972 BootNextFlag
= (BOOLEAN
) (*BootNext
== BootOrderList
[Index
]);
974 BootNextFlag
= FALSE
;
977 if (0 == (*((UINT32
*) LoadOption
) & LOAD_OPTION_ACTIVE
)) {
978 SafeFreePool (LoadOption
);
982 // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
983 // the buffer allocated already should be freed before returning.
985 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
986 if (NULL
== NewMenuEntry
) {
987 return EFI_OUT_OF_RESOURCES
;
990 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
992 LoadOptionPtr
= LoadOption
;
993 LoadOptionEnd
= LoadOption
+ BootOptionSize
;
995 NewMenuEntry
->OptionNumber
= BootOrderList
[Index
];
996 NewLoadContext
->LoadOptionModified
= FALSE
;
997 NewLoadContext
->Deleted
= FALSE
;
998 NewLoadContext
->IsBootNext
= BootNextFlag
;
1001 // Is a Legacy Device?
1003 Ptr
= (UINT8
*) LoadOption
;
1006 // Attribute = *(UINT32 *)Ptr;
1008 Ptr
+= sizeof (UINT32
);
1011 // FilePathSize = *(UINT16 *)Ptr;
1013 Ptr
+= sizeof (UINT16
);
1016 // Description = (CHAR16 *)Ptr;
1018 Ptr
+= StrSize ((CHAR16
*) Ptr
);
1021 // Now Ptr point to Device Path
1023 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1024 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
1025 NewLoadContext
->IsLegacy
= TRUE
;
1027 NewLoadContext
->IsLegacy
= FALSE
;
1030 // LoadOption is a pointer type of UINT8
1031 // for easy use with following LOAD_OPTION
1032 // embedded in this struct
1034 NewLoadContext
->LoadOption
= LoadOption
;
1035 NewLoadContext
->LoadOptionSize
= BootOptionSize
;
1037 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1038 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1040 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1042 LoadOptionPtr
+= sizeof (UINT32
);
1044 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1045 LoadOptionPtr
+= sizeof (UINT16
);
1047 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1048 NewLoadContext
->Description
= EfiAllocateZeroPool (StringSize
);
1049 ASSERT (NewLoadContext
->Description
!= NULL
);
1051 NewLoadContext
->Description
,
1052 (UINT16
*) LoadOptionPtr
,
1055 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1057 LoadOptionPtr
+= StringSize
;
1059 NewLoadContext
->FilePathList
= EfiAllocateZeroPool (NewLoadContext
->FilePathListLength
);
1060 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1062 NewLoadContext
->FilePathList
,
1063 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1064 NewLoadContext
->FilePathListLength
1067 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1068 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1070 BootOptionStrDepository
1072 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1074 BootOptionHelpStrDepository
1076 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1078 if (LoadOptionPtr
< LoadOptionEnd
) {
1079 OptionalDataSize
= BootOptionSize
-
1083 NewLoadContext
->FilePathListLength
;
1085 NewLoadContext
->OptionalData
= EfiAllocateZeroPool (OptionalDataSize
);
1086 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1088 NewLoadContext
->OptionalData
,
1093 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1096 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
1100 SafeFreePool (BootNext
);
1101 SafeFreePool (BootOrderList
);
1102 BootOptionMenu
.MenuNumber
= MenuCount
;
1107 BOpt_AppendFileName (
1114 Append file name to existing file name.
1117 Str1 - existing file name
1118 Str2 - file name to be appended
1121 Allocate a new string to hold the appended result.
1122 Caller is responsible to free the returned string.
1132 Size1
= StrSize (Str1
);
1133 Size2
= StrSize (Str2
);
1134 Str
= EfiAllocateZeroPool (Size1
+ Size2
+ sizeof (CHAR16
));
1135 ASSERT (Str
!= NULL
);
1138 if (!((*Str
== '\\') && (*(Str
+ 1) == 0))) {
1139 StrCat (Str
, L
"\\");
1147 if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '.' && *(Ptr
+ 3) != 0) {
1149 // Convert \Name\..\ to \
1150 // DO NOT convert the .. if it is at the end of the string. This will
1151 // break the .. behavior in changing directories.
1153 StrCpy (LastSlash
, Ptr
+ 3);
1155 } else if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '\\') {
1157 // Convert a \.\ to a \
1159 StrCpy (Ptr
, Ptr
+ 2);
1161 } else if (*Ptr
== '\\') {
1172 BOpt_IsEfiImageName (
1178 Check whether current FileName point to a valid
1182 FileName - File need to be checked.
1186 FALSE - Not a valid Efi Image
1191 // Search for ".efi" extension
1194 if (FileName
[0] == '.') {
1195 if (FileName
[1] == 'e' || FileName
[1] == 'E') {
1196 if (FileName
[2] == 'f' || FileName
[2] == 'F') {
1197 if (FileName
[3] == 'i' || FileName
[3] == 'I') {
1199 } else if (FileName
[3] == 0x0000) {
1202 } else if (FileName
[2] == 0x0000) {
1205 } else if (FileName
[1] == 0x0000) {
1218 IN EFI_FILE_HANDLE Dir
,
1223 Routine Description:
1224 Check whether current FileName point to a valid Efi Application
1227 Dir - Pointer to current Directory
1228 FileName - Pointer to current File name.
1231 TRUE - Is a valid Efi Application
1232 FALSE - not a valid Efi Application
1237 EFI_IMAGE_DOS_HEADER DosHdr
;
1238 EFI_IMAGE_NT_HEADERS PeHdr
;
1239 EFI_IMAGE_OPTIONAL_HEADER32
*PeOpt32
;
1240 EFI_IMAGE_OPTIONAL_HEADER64
*PeOpt64
;
1242 EFI_FILE_HANDLE File
;
1245 Status
= Dir
->Open (Dir
, &File
, FileName
, EFI_FILE_MODE_READ
, 0);
1247 if (EFI_ERROR (Status
)) {
1251 BufferSize
= sizeof (EFI_IMAGE_DOS_HEADER
);
1252 File
->Read (File
, &BufferSize
, &DosHdr
);
1253 if (DosHdr
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1258 File
->SetPosition (File
, DosHdr
.e_lfanew
);
1259 BufferSize
= sizeof (EFI_IMAGE_NT_HEADERS
);
1260 File
->Read (File
, &BufferSize
, &PeHdr
);
1261 if (PeHdr
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1266 // Determine PE type and read subsytem
1267 // BugBug : We should be using EFI_IMAGE_MACHINE_TYPE_SUPPORTED (machine)
1268 // macro to detect the machine type.
1269 // We should not be using EFI_IMAGE_OPTIONAL_HEADER32 and
1270 // EFI_IMAGE_OPTIONAL_HEADER64
1272 if (PeHdr
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1273 PeOpt32
= (EFI_IMAGE_OPTIONAL_HEADER32
*) &(PeHdr
.OptionalHeader
);
1274 Subsystem
= PeOpt32
->Subsystem
;
1275 } else if (PeHdr
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1276 PeOpt64
= (EFI_IMAGE_OPTIONAL_HEADER64
*) &(PeHdr
.OptionalHeader
);
1277 Subsystem
= PeOpt64
->Subsystem
;
1282 if (Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1298 Find drivers that will be added as Driver#### variables from handles
1299 in current system environment
1300 All valid handles in the system except those consume SimpleFs, LoadFile
1301 are stored in DriverMenu for future use.
1312 UINTN NoDevicePathHandles
;
1313 EFI_HANDLE
*DevicePathHandle
;
1316 BM_MENU_ENTRY
*NewMenuEntry
;
1317 BM_HANDLE_CONTEXT
*NewHandleContext
;
1318 EFI_HANDLE CurHandle
;
1320 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFs
;
1321 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1326 InitializeListHead (&DriverMenu
.Head
);
1329 // At first, get all handles that support Device Path
1330 // protocol which is the basic requirement for
1333 Status
= gBS
->LocateHandleBuffer (
1335 &gEfiDevicePathProtocolGuid
,
1337 &NoDevicePathHandles
,
1340 if (EFI_ERROR (Status
)) {
1345 for (Index
= 0; Index
< NoDevicePathHandles
; Index
++) {
1346 CurHandle
= DevicePathHandle
[Index
];
1349 // Check whether this handle support
1352 Status
= gBS
->HandleProtocol (
1354 &gEfiSimpleFileSystemProtocolGuid
,
1357 if (Status
== EFI_SUCCESS
) {
1361 Status
= gBS
->HandleProtocol (
1363 &gEfiLoadFileProtocolGuid
,
1366 if (Status
== EFI_SUCCESS
) {
1370 NewMenuEntry
= BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT
);
1371 if (NULL
== NewMenuEntry
) {
1372 SafeFreePool (DevicePathHandle
);
1373 return EFI_OUT_OF_RESOURCES
;
1376 NewHandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1377 NewHandleContext
->Handle
= CurHandle
;
1378 NewHandleContext
->DevicePath
= DevicePathFromHandle (CurHandle
);
1379 NewMenuEntry
->DisplayString
= DevicePathToStr (NewHandleContext
->DevicePath
);
1380 NewMenuEntry
->HelpString
= NULL
;
1381 NewMenuEntry
->OptionNumber
= OptionNumber
;
1383 InsertTailList (&DriverMenu
.Head
, &NewMenuEntry
->Link
);
1386 SafeFreePool (DevicePathHandle
);
1388 DriverMenu
.MenuNumber
= OptionNumber
;
1393 BOpt_GetBootOptionNumber (
1398 Routine Description:
1399 Get the Option Number that does not used
1408 BM_MENU_ENTRY
*NewMenuEntry
;
1409 UINT16
*BootOrderList
;
1410 UINTN BootOrderListSize
;
1415 CHAR16 StrTemp
[100];
1416 UINT16
*OptionBuffer
;
1419 BootOrderListSize
= 0;
1420 BootOrderList
= NULL
;
1422 BootOrderList
= BdsLibGetVariableAndSize (
1424 &gEfiGlobalVariableGuid
,
1427 if (BootOrderList
) {
1429 // already have Boot####
1431 // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
1433 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
1435 for (Index2
= 0; Index2
< BootOptionMenu
.MenuNumber
; Index2
++) {
1436 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index2
);
1437 if (Index
== NewMenuEntry
->OptionNumber
) {
1444 UnicodeSPrint (StrTemp
, 100, L
"Boot%04x", Index
);
1445 DEBUG((DEBUG_ERROR
,"INdex= %s\n", StrTemp
));
1446 OptionBuffer
= BdsLibGetVariableAndSize (
1448 &gEfiGlobalVariableGuid
,
1451 if (NULL
== OptionBuffer
)
1458 Number
= (UINT16
) Index
;
1470 BOpt_GetDriverOptionNumber (
1475 Routine Description:
1476 Get the Option Number that does not used
1485 BM_MENU_ENTRY
*NewMenuEntry
;
1486 UINT16
*DriverOrderList
;
1487 UINTN DriverOrderListSize
;
1493 DriverOrderListSize
= 0;
1494 DriverOrderList
= NULL
;
1496 DriverOrderList
= BdsLibGetVariableAndSize (
1498 &gEfiGlobalVariableGuid
,
1499 &DriverOrderListSize
1501 if (DriverOrderList
) {
1503 // already have Driver####
1505 // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
1507 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1509 for (Index2
= 0; Index2
< DriverOptionMenu
.MenuNumber
; Index2
++) {
1510 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index2
);
1511 if (Index
== NewMenuEntry
->OptionNumber
) {
1524 Number
= (UINT16
) Index
;
1536 BOpt_GetDriverOptions (
1537 IN BMM_CALLBACK_DATA
*CallbackData
1541 Routine Description:
1542 Build up all DriverOptionMenu
1552 UINT16 DriverString
[12];
1553 UINT8
*LoadOptionFromVar
;
1555 UINTN DriverOptionSize
;
1557 UINT16
*DriverOrderList
;
1558 UINTN DriverOrderListSize
;
1559 BM_MENU_ENTRY
*NewMenuEntry
;
1560 BM_LOAD_CONTEXT
*NewLoadContext
;
1561 UINT8
*LoadOptionPtr
;
1563 UINTN OptionalDataSize
;
1564 UINT8
*LoadOptionEnd
;
1566 DriverOrderListSize
= 0;
1567 DriverOrderList
= NULL
;
1568 DriverOptionSize
= 0;
1569 LoadOptionFromVar
= NULL
;
1570 BOpt_FreeMenu (&DriverOptionMenu
);
1571 InitializeListHead (&DriverOptionMenu
.Head
);
1573 // Get the DriverOrder from the Var
1575 DriverOrderList
= BdsLibGetVariableAndSize (
1577 &gEfiGlobalVariableGuid
,
1578 &DriverOrderListSize
1581 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1584 sizeof (DriverString
),
1586 DriverOrderList
[Index
]
1589 // Get all loadoptions from the VAR
1591 LoadOptionFromVar
= BdsLibGetVariableAndSize (
1593 &gEfiGlobalVariableGuid
,
1596 if (!LoadOptionFromVar
) {
1600 LoadOption
= EfiAllocateZeroPool (DriverOptionSize
);
1605 CopyMem (LoadOption
, LoadOptionFromVar
, DriverOptionSize
);
1606 SafeFreePool (LoadOptionFromVar
);
1608 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
1609 if (NULL
== NewMenuEntry
) {
1610 return EFI_OUT_OF_RESOURCES
;
1613 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1614 LoadOptionPtr
= LoadOption
;
1615 LoadOptionEnd
= LoadOption
+ DriverOptionSize
;
1616 NewMenuEntry
->OptionNumber
= DriverOrderList
[Index
];
1617 NewLoadContext
->LoadOptionModified
= FALSE
;
1618 NewLoadContext
->Deleted
= FALSE
;
1619 NewLoadContext
->IsLegacy
= FALSE
;
1622 // LoadOption is a pointer type of UINT8
1623 // for easy use with following LOAD_OPTION
1624 // embedded in this struct
1626 NewLoadContext
->LoadOption
= LoadOption
;
1627 NewLoadContext
->LoadOptionSize
= DriverOptionSize
;
1629 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1630 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1632 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1634 LoadOptionPtr
+= sizeof (UINT32
);
1636 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1637 LoadOptionPtr
+= sizeof (UINT16
);
1639 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1640 NewLoadContext
->Description
= EfiAllocateZeroPool (StringSize
);
1641 ASSERT (NewLoadContext
->Description
!= NULL
);
1643 NewLoadContext
->Description
,
1644 (UINT16
*) LoadOptionPtr
,
1647 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1649 LoadOptionPtr
+= StringSize
;
1651 NewLoadContext
->FilePathList
= EfiAllocateZeroPool (NewLoadContext
->FilePathListLength
);
1652 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1654 NewLoadContext
->FilePathList
,
1655 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1656 NewLoadContext
->FilePathListLength
1659 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1660 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1662 DriverOptionStrDepository
1664 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1666 DriverOptionHelpStrDepository
1668 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1670 if (LoadOptionPtr
< LoadOptionEnd
) {
1671 OptionalDataSize
= DriverOptionSize
-
1675 NewLoadContext
->FilePathListLength
;
1677 NewLoadContext
->OptionalData
= EfiAllocateZeroPool (OptionalDataSize
);
1678 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1680 NewLoadContext
->OptionalData
,
1685 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1688 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
1692 SafeFreePool (DriverOrderList
);
1693 DriverOptionMenu
.MenuNumber
= Index
;