2 Provide boot option support for Application "BootMaint"
4 Include file system navigation, system handle selection
6 Boot option manipulation
8 Copyright (c) 2004 - 2008, Intel Corporation. <BR>
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include "BootMaint.h"
20 #include "BBSsupport.h"
23 BOpt_CreateMenuEntry (
29 Create Menu Entry for future use, make all types together
30 in order to reduce code size
33 MenuType Use this parameter to identify current
37 NULL Cannot allocate memory for current menu
39 Others A valid pointer pointing to the allocated
40 memory pool for current menu entry
44 BM_MENU_ENTRY
*MenuEntry
;
48 case BM_LOAD_CONTEXT_SELECT
:
49 ContextSize
= sizeof (BM_LOAD_CONTEXT
);
52 case BM_FILE_CONTEXT_SELECT
:
53 ContextSize
= sizeof (BM_FILE_CONTEXT
);
56 case BM_CONSOLE_CONTEXT_SELECT
:
57 ContextSize
= sizeof (BM_CONSOLE_CONTEXT
);
60 case BM_TERMINAL_CONTEXT_SELECT
:
61 ContextSize
= sizeof (BM_TERMINAL_CONTEXT
);
64 case BM_HANDLE_CONTEXT_SELECT
:
65 ContextSize
= sizeof (BM_HANDLE_CONTEXT
);
68 case BM_LEGACY_DEV_CONTEXT_SELECT
:
69 ContextSize
= sizeof (BM_LEGACY_DEVICE_CONTEXT
);
78 if (0 == ContextSize
) {
82 MenuEntry
= EfiAllocateZeroPool (sizeof (BM_MENU_ENTRY
));
83 if (NULL
== MenuEntry
) {
87 MenuEntry
->VariableContext
= EfiAllocateZeroPool (ContextSize
);
88 if (NULL
== MenuEntry
->VariableContext
) {
89 SafeFreePool (MenuEntry
);
94 MenuEntry
->Signature
= BM_MENU_ENTRY_SIGNATURE
;
95 MenuEntry
->ContextSelection
= MenuType
;
100 BOpt_DestroyMenuEntry (
101 BM_MENU_ENTRY
*MenuEntry
104 Routine Description :
105 Destroy the menu entry passed in
108 The menu entry need to be destroyed
115 BM_LOAD_CONTEXT
*LoadContext
;
116 BM_FILE_CONTEXT
*FileContext
;
117 BM_CONSOLE_CONTEXT
*ConsoleContext
;
118 BM_TERMINAL_CONTEXT
*TerminalContext
;
119 BM_HANDLE_CONTEXT
*HandleContext
;
120 BM_LEGACY_DEVICE_CONTEXT
*LegacyDevContext
;
123 // Select by the type in Menu entry for current context type
125 switch (MenuEntry
->ContextSelection
) {
126 case BM_LOAD_CONTEXT_SELECT
:
127 LoadContext
= (BM_LOAD_CONTEXT
*) MenuEntry
->VariableContext
;
128 SafeFreePool (LoadContext
->FilePathList
);
129 SafeFreePool (LoadContext
->LoadOption
);
130 SafeFreePool (LoadContext
->OptionalData
);
131 SafeFreePool (LoadContext
);
134 case BM_FILE_CONTEXT_SELECT
:
135 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
137 if (!FileContext
->IsRoot
) {
138 SafeFreePool (FileContext
->DevicePath
);
140 if (FileContext
->FHandle
!= NULL
) {
141 FileContext
->FHandle
->Close (FileContext
->FHandle
);
145 SafeFreePool (FileContext
->FileName
);
146 SafeFreePool (FileContext
->Info
);
147 SafeFreePool (FileContext
);
150 case BM_CONSOLE_CONTEXT_SELECT
:
151 ConsoleContext
= (BM_CONSOLE_CONTEXT
*) MenuEntry
->VariableContext
;
152 SafeFreePool (ConsoleContext
->DevicePath
);
153 SafeFreePool (ConsoleContext
);
156 case BM_TERMINAL_CONTEXT_SELECT
:
157 TerminalContext
= (BM_TERMINAL_CONTEXT
*) MenuEntry
->VariableContext
;
158 SafeFreePool (TerminalContext
->DevicePath
);
159 SafeFreePool (TerminalContext
);
162 case BM_HANDLE_CONTEXT_SELECT
:
163 HandleContext
= (BM_HANDLE_CONTEXT
*) MenuEntry
->VariableContext
;
164 SafeFreePool (HandleContext
);
167 case BM_LEGACY_DEV_CONTEXT_SELECT
:
168 LegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) MenuEntry
->VariableContext
;
169 SafeFreePool (LegacyDevContext
);
175 SafeFreePool (MenuEntry
->DisplayString
);
176 if (NULL
!= MenuEntry
->HelpString
) {
177 SafeFreePool (MenuEntry
->HelpString
);
180 SafeFreePool (MenuEntry
);
185 BM_MENU_OPTION
*MenuOption
,
189 Rountine Description :
190 Use this routine to get one particular menu entry in specified
194 MenuOption The menu that we will search
196 MenuNumber The menunubmer that we want
199 The desired menu entry
203 BM_MENU_ENTRY
*NewMenuEntry
;
207 if (MenuNumber
>= MenuOption
->MenuNumber
) {
211 List
= MenuOption
->Head
.ForwardLink
;
212 for (Index
= 0; Index
< MenuNumber
; Index
++) {
213 List
= List
->ForwardLink
;
216 NewMenuEntry
= CR (List
, BM_MENU_ENTRY
, Link
, BM_MENU_ENTRY_SIGNATURE
);
222 BOpt_FindFileSystem (
223 IN BMM_CALLBACK_DATA
*CallbackData
228 Find file systems for current Extensible Firmware
229 Including Handles that support Simple File System
230 protocol, Load File protocol.
232 Building up the FileSystem Menu for user selection
233 All file system will be stored in FsOptionMenu
237 CallbackData - BMM context data
240 EFI_SUCCESS - Success find the file system
241 EFI_OUT_OF_RESOURCES - Can not create menu entry
245 UINTN NoBlkIoHandles
;
246 UINTN NoSimpleFsHandles
;
247 UINTN NoLoadFileHandles
;
248 EFI_HANDLE
*BlkIoHandle
;
249 EFI_HANDLE
*SimpleFsHandle
;
250 EFI_HANDLE
*LoadFileHandle
;
252 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
255 BM_MENU_ENTRY
*MenuEntry
;
256 BM_FILE_CONTEXT
*FileContext
;
260 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
262 BBS_BBS_DEVICE_PATH BbsDevicePathNode
;
263 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
264 BOOLEAN RemovableMedia
;
267 NoSimpleFsHandles
= 0;
268 NoLoadFileHandles
= 0;
270 InitializeListHead (&FsOptionMenu
.Head
);
273 // Locate Handles that support BlockIo protocol
275 Status
= gBS
->LocateHandleBuffer (
277 &gEfiBlockIoProtocolGuid
,
282 if (!EFI_ERROR (Status
)) {
284 for (Index
= 0; Index
< NoBlkIoHandles
; Index
++) {
285 Status
= gBS
->HandleProtocol (
287 &gEfiBlockIoProtocolGuid
,
291 if (EFI_ERROR (Status
)) {
296 // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
298 if (BlkIo
->Media
->RemovableMedia
) {
299 Buffer
= EfiAllocateZeroPool (BlkIo
->Media
->BlockSize
);
300 if (NULL
== Buffer
) {
301 SafeFreePool (BlkIoHandle
);
302 return EFI_OUT_OF_RESOURCES
;
307 BlkIo
->Media
->MediaId
,
309 BlkIo
->Media
->BlockSize
,
312 SafeFreePool (Buffer
);
315 SafeFreePool (BlkIoHandle
);
319 // Locate Handles that support Simple File System protocol
321 Status
= gBS
->LocateHandleBuffer (
323 &gEfiSimpleFileSystemProtocolGuid
,
328 if (!EFI_ERROR (Status
)) {
330 // Find all the instances of the File System prototocol
332 for (Index
= 0; Index
< NoSimpleFsHandles
; Index
++) {
333 Status
= gBS
->HandleProtocol (
334 SimpleFsHandle
[Index
],
335 &gEfiBlockIoProtocolGuid
,
338 if (EFI_ERROR (Status
)) {
340 // If no block IO exists assume it's NOT a removable media
342 RemovableMedia
= FALSE
;
345 // If block IO exists check to see if it's remobable media
347 RemovableMedia
= BlkIo
->Media
->RemovableMedia
;
351 // Allocate pool for this load option
353 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
354 if (NULL
== MenuEntry
) {
355 SafeFreePool (SimpleFsHandle
);
356 return EFI_OUT_OF_RESOURCES
;
359 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
361 FileContext
->Handle
= SimpleFsHandle
[Index
];
362 MenuEntry
->OptionNumber
= Index
;
363 FileContext
->FHandle
= EfiLibOpenRoot (FileContext
->Handle
);
364 if (!FileContext
->FHandle
) {
365 BOpt_DestroyMenuEntry (MenuEntry
);
369 MenuEntry
->HelpString
= DevicePathToStr (DevicePathFromHandle (FileContext
->Handle
));
370 FileContext
->Info
= EfiLibFileSystemVolumeLabelInfo (FileContext
->FHandle
);
371 FileContext
->FileName
= EfiStrDuplicate (L
"\\");
372 FileContext
->DevicePath
= FileDevicePath (
374 FileContext
->FileName
376 FileContext
->IsDir
= TRUE
;
377 FileContext
->IsRoot
= TRUE
;
378 FileContext
->IsRemovableMedia
= RemovableMedia
;
379 FileContext
->IsLoadFile
= FALSE
;
382 // Get current file system's Volume Label
384 if (FileContext
->Info
== NULL
) {
385 VolumeLabel
= L
"NO FILE SYSTEM INFO";
387 if (FileContext
->Info
->VolumeLabel
== NULL
) {
388 VolumeLabel
= L
"NULL VOLUME LABEL";
390 VolumeLabel
= FileContext
->Info
->VolumeLabel
;
391 if (*VolumeLabel
== 0x0000) {
392 VolumeLabel
= L
"NO VOLUME LABEL";
397 TempStr
= MenuEntry
->HelpString
;
398 MenuEntry
->DisplayString
= EfiAllocateZeroPool (MAX_CHAR
);
399 ASSERT (MenuEntry
->DisplayString
!= NULL
);
401 MenuEntry
->DisplayString
,
408 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
412 if (NoSimpleFsHandles
!= 0) {
413 SafeFreePool (SimpleFsHandle
);
416 // Searching for handles that support Load File protocol
418 Status
= gBS
->LocateHandleBuffer (
420 &gEfiLoadFileProtocolGuid
,
426 if (!EFI_ERROR (Status
)) {
427 for (Index
= 0; Index
< NoLoadFileHandles
; Index
++) {
428 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
429 if (NULL
== MenuEntry
) {
430 SafeFreePool (LoadFileHandle
);
431 return EFI_OUT_OF_RESOURCES
;
434 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
435 FileContext
->IsRemovableMedia
= FALSE
;
436 FileContext
->IsLoadFile
= TRUE
;
437 FileContext
->Handle
= LoadFileHandle
[Index
];
438 FileContext
->IsRoot
= TRUE
;
440 FileContext
->DevicePath
= DevicePathFromHandle (FileContext
->Handle
);
442 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
444 TempStr
= MenuEntry
->HelpString
;
445 MenuEntry
->DisplayString
= EfiAllocateZeroPool (MAX_CHAR
);
446 ASSERT (MenuEntry
->DisplayString
!= NULL
);
448 MenuEntry
->DisplayString
,
454 MenuEntry
->OptionNumber
= OptionNumber
;
456 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
460 if (NoLoadFileHandles
!= 0) {
461 SafeFreePool (LoadFileHandle
);
465 // Add Legacy Boot Option Support Here
467 Status
= gBS
->LocateProtocol (
468 &gEfiLegacyBiosProtocolGuid
,
470 (VOID
**) &LegacyBios
472 if (!EFI_ERROR (Status
)) {
474 for (Index
= BBS_TYPE_FLOPPY
; Index
<= BBS_TYPE_EMBEDDED_NETWORK
; Index
++) {
475 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
476 if (NULL
== MenuEntry
) {
477 return EFI_OUT_OF_RESOURCES
;
480 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
482 FileContext
->IsRemovableMedia
= FALSE
;
483 FileContext
->IsLoadFile
= TRUE
;
484 FileContext
->IsBootLegacy
= TRUE
;
485 DeviceType
= (UINT16
) Index
;
486 BbsDevicePathNode
.Header
.Type
= BBS_DEVICE_PATH
;
487 BbsDevicePathNode
.Header
.SubType
= BBS_BBS_DP
;
488 SetDevicePathNodeLength (
489 &BbsDevicePathNode
.Header
,
490 sizeof (BBS_BBS_DEVICE_PATH
)
492 BbsDevicePathNode
.DeviceType
= DeviceType
;
493 BbsDevicePathNode
.StatusFlag
= 0;
494 BbsDevicePathNode
.String
[0] = 0;
495 DevicePath
= AppendDevicePathNode (
497 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevicePathNode
500 FileContext
->DevicePath
= DevicePath
;
501 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
503 TempStr
= MenuEntry
->HelpString
;
504 MenuEntry
->DisplayString
= EfiAllocateZeroPool (MAX_CHAR
);
505 ASSERT (MenuEntry
->DisplayString
!= NULL
);
507 MenuEntry
->DisplayString
,
512 MenuEntry
->OptionNumber
= OptionNumber
;
514 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
518 // Remember how many file system options are here
520 FsOptionMenu
.MenuNumber
= OptionNumber
;
526 BM_MENU_OPTION
*FreeMenu
531 Free resources allocated in Allocate Rountine
534 FreeMenu Menu to be freed
541 BM_MENU_ENTRY
*MenuEntry
;
542 while (!IsListEmpty (&FreeMenu
->Head
)) {
544 FreeMenu
->Head
.ForwardLink
,
547 BM_MENU_ENTRY_SIGNATURE
549 RemoveEntryList (&MenuEntry
->Link
);
550 BOpt_DestroyMenuEntry (MenuEntry
);
556 IN BMM_CALLBACK_DATA
*CallbackData
,
557 IN BM_MENU_ENTRY
*MenuEntry
562 Find files under current directory
563 All files and sub-directories in current directory
564 will be stored in DirectoryMenu for future use.
567 FileOption -- Pointer for Dir to explore
570 TRUE -- Get files from current dir successfully
571 FALSE -- Can't get files from current dir
575 EFI_FILE_HANDLE NewDir
;
577 EFI_FILE_INFO
*DirInfo
;
580 BM_MENU_ENTRY
*NewMenuEntry
;
581 BM_FILE_CONTEXT
*FileContext
;
582 BM_FILE_CONTEXT
*NewFileContext
;
587 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
588 Dir
= FileContext
->FHandle
;
591 // Open current directory to get files from it
596 FileContext
->FileName
,
600 if (!FileContext
->IsRoot
) {
604 if (EFI_ERROR (Status
)) {
608 DirInfo
= EfiLibFileInfo (NewDir
);
610 return EFI_NOT_FOUND
;
613 if (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
614 return EFI_INVALID_PARAMETER
;
617 FileContext
->DevicePath
= FileDevicePath (
619 FileContext
->FileName
622 DirBufferSize
= sizeof (EFI_FILE_INFO
) + 1024;
623 DirInfo
= EfiAllocateZeroPool (DirBufferSize
);
625 return EFI_OUT_OF_RESOURCES
;
628 // Get all files in current directory
629 // Pass 1 to get Directories
630 // Pass 2 to get files that are EFI images
632 for (Pass
= 1; Pass
<= 2; Pass
++) {
633 NewDir
->SetPosition (NewDir
, 0);
635 BufferSize
= DirBufferSize
;
636 Status
= NewDir
->Read (NewDir
, &BufferSize
, DirInfo
);
637 if (EFI_ERROR (Status
) || BufferSize
== 0) {
641 if ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
&& Pass
== 2) ||
642 (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) && Pass
== 1)
645 // Pass 1 is for Directories
646 // Pass 2 is for file names
651 if (!(BOpt_IsEfiImageName (DirInfo
->FileName
) || DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
653 // Slip file unless it is a directory entry or a .EFI file
658 NewMenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
659 if (NULL
== NewMenuEntry
) {
660 return EFI_OUT_OF_RESOURCES
;
663 NewFileContext
= (BM_FILE_CONTEXT
*) NewMenuEntry
->VariableContext
;
664 NewFileContext
->Handle
= FileContext
->Handle
;
665 NewFileContext
->FileName
= BOpt_AppendFileName (
666 FileContext
->FileName
,
669 NewFileContext
->FHandle
= NewDir
;
670 NewFileContext
->DevicePath
= FileDevicePath (
671 NewFileContext
->Handle
,
672 NewFileContext
->FileName
674 NewMenuEntry
->HelpString
= NULL
;
676 MenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
678 FileOptionStrDepository
681 NewFileContext
->IsDir
= (BOOLEAN
) ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
);
683 if (NewFileContext
->IsDir
) {
684 BufferSize
= StrLen (DirInfo
->FileName
) * 2 + 6;
685 NewMenuEntry
->DisplayString
= EfiAllocateZeroPool (BufferSize
);
688 NewMenuEntry
->DisplayString
,
695 NewMenuEntry
->DisplayString
= EfiStrDuplicate (DirInfo
->FileName
);
698 NewFileContext
->IsRoot
= FALSE
;
699 NewFileContext
->IsLoadFile
= FALSE
;
700 NewFileContext
->IsRemovableMedia
= FALSE
;
702 NewMenuEntry
->OptionNumber
= OptionNumber
;
704 InsertTailList (&DirectoryMenu
.Head
, &NewMenuEntry
->Link
);
708 DirectoryMenu
.MenuNumber
= OptionNumber
;
709 SafeFreePool (DirInfo
);
714 BOpt_GetLegacyOptions (
720 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
726 The device info of legacy device.
730 BM_MENU_ENTRY
*NewMenuEntry
;
731 BM_LEGACY_DEVICE_CONTEXT
*NewLegacyDevContext
;
733 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
739 CHAR16 DescString
[100];
752 // Initialize Bbs Table Context from BBS info data
754 InitializeListHead (&LegacyFDMenu
.Head
);
755 InitializeListHead (&LegacyHDMenu
.Head
);
756 InitializeListHead (&LegacyCDMenu
.Head
);
757 InitializeListHead (&LegacyNETMenu
.Head
);
758 InitializeListHead (&LegacyBEVMenu
.Head
);
760 Status
= gBS
->LocateProtocol (
761 &gEfiLegacyBiosProtocolGuid
,
763 (VOID
**) &LegacyBios
765 if (!EFI_ERROR (Status
)) {
766 Status
= LegacyBios
->GetBbsInfo (
773 if (EFI_ERROR (Status
)) {
784 for (Index
= 0; Index
< BbsCount
; Index
++) {
785 if ((BBS_IGNORE_ENTRY
== BbsTable
[Index
].BootPriority
) ||
786 (BBS_DO_NOT_BOOT_FROM
== BbsTable
[Index
].BootPriority
)
791 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT
);
792 if (NULL
== NewMenuEntry
) {
796 NewLegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) NewMenuEntry
->VariableContext
;
797 NewLegacyDevContext
->BbsTable
= &BbsTable
[Index
];
798 NewLegacyDevContext
->Index
= Index
;
799 NewLegacyDevContext
->BbsCount
= BbsCount
;
800 BdsBuildLegacyDevNameString (
806 NewLegacyDevContext
->Description
= EfiAllocateZeroPool (StrSize (DescString
));
807 if (NULL
== NewLegacyDevContext
->Description
) {
811 CopyMem (NewLegacyDevContext
->Description
, DescString
, StrSize (DescString
));
812 NewMenuEntry
->DisplayString
= NewLegacyDevContext
->Description
;
813 NewMenuEntry
->HelpString
= NULL
;
815 switch (BbsTable
[Index
].DeviceType
) {
817 InsertTailList (&LegacyFDMenu
.Head
, &NewMenuEntry
->Link
);
822 InsertTailList (&LegacyHDMenu
.Head
, &NewMenuEntry
->Link
);
827 InsertTailList (&LegacyCDMenu
.Head
, &NewMenuEntry
->Link
);
831 case BBS_EMBED_NETWORK
:
832 InsertTailList (&LegacyNETMenu
.Head
, &NewMenuEntry
->Link
);
837 InsertTailList (&LegacyBEVMenu
.Head
, &NewMenuEntry
->Link
);
843 if (Index
!= BbsCount
) {
844 BOpt_FreeLegacyOptions ();
845 return EFI_OUT_OF_RESOURCES
;
848 LegacyFDMenu
.MenuNumber
= FDNum
;
849 LegacyHDMenu
.MenuNumber
= HDNum
;
850 LegacyCDMenu
.MenuNumber
= CDNum
;
851 LegacyNETMenu
.MenuNumber
= NETNum
;
852 LegacyBEVMenu
.MenuNumber
= BEVNum
;
857 BOpt_FreeLegacyOptions (
861 BOpt_FreeMenu (&LegacyFDMenu
);
862 BOpt_FreeMenu (&LegacyHDMenu
);
863 BOpt_FreeMenu (&LegacyCDMenu
);
864 BOpt_FreeMenu (&LegacyNETMenu
);
865 BOpt_FreeMenu (&LegacyBEVMenu
);
869 BOpt_GetBootOptions (
870 IN BMM_CALLBACK_DATA
*CallbackData
876 Build the BootOptionMenu according to BootOrder Variable.
877 This Routine will access the Boot#### to get EFI_LOAD_OPTION
883 The number of the Var Boot####
888 UINT16 BootString
[10];
889 UINT8
*LoadOptionFromVar
;
891 UINTN BootOptionSize
;
892 BOOLEAN BootNextFlag
;
893 UINT16
*BootOrderList
;
894 UINTN BootOrderListSize
;
897 BM_MENU_ENTRY
*NewMenuEntry
;
898 BM_LOAD_CONTEXT
*NewLoadContext
;
899 UINT8
*LoadOptionPtr
;
901 UINTN OptionalDataSize
;
902 UINT8
*LoadOptionEnd
;
903 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
908 BootOrderListSize
= 0;
910 BootOrderList
= NULL
;
912 LoadOptionFromVar
= NULL
;
913 BOpt_FreeMenu (&BootOptionMenu
);
914 InitializeListHead (&BootOptionMenu
.Head
);
917 // Get the BootOrder from the Var
919 BootOrderList
= BdsLibGetVariableAndSize (
921 &gEfiGlobalVariableGuid
,
926 // Get the BootNext from the Var
928 BootNext
= BdsLibGetVariableAndSize (
930 &gEfiGlobalVariableGuid
,
935 if (BootNextSize
!= sizeof (UINT16
)) {
936 SafeFreePool (BootNext
);
941 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
942 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", BootOrderList
[Index
]);
944 // Get all loadoptions from the VAR
946 LoadOptionFromVar
= BdsLibGetVariableAndSize (
948 &gEfiGlobalVariableGuid
,
951 if (!LoadOptionFromVar
) {
955 LoadOption
= EfiAllocateZeroPool (BootOptionSize
);
960 CopyMem (LoadOption
, LoadOptionFromVar
, BootOptionSize
);
961 SafeFreePool (LoadOptionFromVar
);
964 BootNextFlag
= (BOOLEAN
) (*BootNext
== BootOrderList
[Index
]);
966 BootNextFlag
= FALSE
;
969 if (0 == (*((UINT32
*) LoadOption
) & LOAD_OPTION_ACTIVE
)) {
970 SafeFreePool (LoadOption
);
974 // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
975 // the buffer allocated already should be freed before returning.
977 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
978 if (NULL
== NewMenuEntry
) {
979 return EFI_OUT_OF_RESOURCES
;
982 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
984 LoadOptionPtr
= LoadOption
;
985 LoadOptionEnd
= LoadOption
+ BootOptionSize
;
987 NewMenuEntry
->OptionNumber
= BootOrderList
[Index
];
988 NewLoadContext
->LoadOptionModified
= FALSE
;
989 NewLoadContext
->Deleted
= FALSE
;
990 NewLoadContext
->IsBootNext
= BootNextFlag
;
993 // Is a Legacy Device?
995 Ptr
= (UINT8
*) LoadOption
;
998 // Attribute = *(UINT32 *)Ptr;
1000 Ptr
+= sizeof (UINT32
);
1003 // FilePathSize = *(UINT16 *)Ptr;
1005 Ptr
+= sizeof (UINT16
);
1008 // Description = (CHAR16 *)Ptr;
1010 Ptr
+= StrSize ((CHAR16
*) Ptr
);
1013 // Now Ptr point to Device Path
1015 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
1016 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
1017 NewLoadContext
->IsLegacy
= TRUE
;
1019 NewLoadContext
->IsLegacy
= FALSE
;
1022 // LoadOption is a pointer type of UINT8
1023 // for easy use with following LOAD_OPTION
1024 // embedded in this struct
1026 NewLoadContext
->LoadOption
= LoadOption
;
1027 NewLoadContext
->LoadOptionSize
= BootOptionSize
;
1029 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1030 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1032 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1034 LoadOptionPtr
+= sizeof (UINT32
);
1036 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1037 LoadOptionPtr
+= sizeof (UINT16
);
1039 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1040 NewLoadContext
->Description
= EfiAllocateZeroPool (StringSize
);
1041 ASSERT (NewLoadContext
->Description
!= NULL
);
1043 NewLoadContext
->Description
,
1044 (UINT16
*) LoadOptionPtr
,
1047 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1049 LoadOptionPtr
+= StringSize
;
1051 NewLoadContext
->FilePathList
= EfiAllocateZeroPool (NewLoadContext
->FilePathListLength
);
1052 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1054 NewLoadContext
->FilePathList
,
1055 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1056 NewLoadContext
->FilePathListLength
1059 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1060 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1062 BootOptionStrDepository
1064 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1066 BootOptionHelpStrDepository
1068 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1070 if (LoadOptionPtr
< LoadOptionEnd
) {
1071 OptionalDataSize
= BootOptionSize
-
1075 NewLoadContext
->FilePathListLength
;
1077 NewLoadContext
->OptionalData
= EfiAllocateZeroPool (OptionalDataSize
);
1078 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1080 NewLoadContext
->OptionalData
,
1085 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1088 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
1092 SafeFreePool (BootNext
);
1093 SafeFreePool (BootOrderList
);
1094 BootOptionMenu
.MenuNumber
= MenuCount
;
1100 OUT CHAR16
*Destination
,
1101 IN CONST CHAR16
*Source
1104 CHAR16
*ReturnValue
;
1107 // Destination cannot be NULL
1109 ASSERT (Destination
!= NULL
);
1111 ReturnValue
= Destination
;
1113 *(Destination
++) = *(Source
++);
1120 BOpt_AppendFileName (
1127 Append file name to existing file name.
1130 Str1 - existing file name
1131 Str2 - file name to be appended
1134 Allocate a new string to hold the appended result.
1135 Caller is responsible to free the returned string.
1145 Size1
= StrSize (Str1
);
1146 Size2
= StrSize (Str2
);
1147 Str
= EfiAllocateZeroPool (Size1
+ Size2
+ sizeof (CHAR16
));
1148 ASSERT (Str
!= NULL
);
1151 if (!((*Str
== '\\') && (*(Str
+ 1) == 0))) {
1152 StrCat (Str
, L
"\\");
1160 if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '.' && *(Ptr
+ 3) == L
'\\') {
1162 // Convert "\Name\..\" to "\"
1163 // DO NOT convert the .. if it is at the end of the string. This will
1164 // break the .. behavior in changing directories.
1166 BdsStrCpy (LastSlash
, Ptr
+ 3);
1168 } else if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '\\') {
1170 // Convert a "\.\" to a "\"
1172 BdsStrCpy (Ptr
, Ptr
+ 2);
1174 } else if (*Ptr
== '\\') {
1185 BOpt_IsEfiImageName (
1191 Check whether current FileName point to a valid
1195 FileName - File need to be checked.
1199 FALSE - Not a valid Efi Image
1204 // Search for ".efi" extension
1207 if (FileName
[0] == '.') {
1208 if (FileName
[1] == 'e' || FileName
[1] == 'E') {
1209 if (FileName
[2] == 'f' || FileName
[2] == 'F') {
1210 if (FileName
[3] == 'i' || FileName
[3] == 'I') {
1212 } else if (FileName
[3] == 0x0000) {
1215 } else if (FileName
[2] == 0x0000) {
1218 } else if (FileName
[1] == 0x0000) {
1231 IN EFI_FILE_HANDLE Dir
,
1236 Routine Description:
1237 Check whether current FileName point to a valid Efi Application
1240 Dir - Pointer to current Directory
1241 FileName - Pointer to current File name.
1244 TRUE - Is a valid Efi Application
1245 FALSE - not a valid Efi Application
1250 EFI_IMAGE_DOS_HEADER DosHdr
;
1252 EFI_FILE_HANDLE File
;
1254 EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr
;
1256 Status
= Dir
->Open (Dir
, &File
, FileName
, EFI_FILE_MODE_READ
, 0);
1258 if (EFI_ERROR (Status
)) {
1262 BufferSize
= sizeof (EFI_IMAGE_DOS_HEADER
);
1263 File
->Read (File
, &BufferSize
, &DosHdr
);
1264 if (DosHdr
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1269 File
->SetPosition (File
, DosHdr
.e_lfanew
);
1270 BufferSize
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
1271 File
->Read (File
, &BufferSize
, &PeHdr
);
1272 if (PeHdr
.Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1277 // Determine PE type and read subsytem
1279 if (PeHdr
.Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1280 Subsystem
= PeHdr
.Pe32
.OptionalHeader
.Subsystem
;
1281 } else if (PeHdr
.Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1282 Subsystem
= PeHdr
.Pe32Plus
.OptionalHeader
.Subsystem
;
1287 if (Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1303 Find drivers that will be added as Driver#### variables from handles
1304 in current system environment
1305 All valid handles in the system except those consume SimpleFs, LoadFile
1306 are stored in DriverMenu for future use.
1317 UINTN NoDevicePathHandles
;
1318 EFI_HANDLE
*DevicePathHandle
;
1321 BM_MENU_ENTRY
*NewMenuEntry
;
1322 BM_HANDLE_CONTEXT
*NewHandleContext
;
1323 EFI_HANDLE CurHandle
;
1325 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFs
;
1326 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1331 InitializeListHead (&DriverMenu
.Head
);
1334 // At first, get all handles that support Device Path
1335 // protocol which is the basic requirement for
1338 Status
= gBS
->LocateHandleBuffer (
1340 &gEfiDevicePathProtocolGuid
,
1342 &NoDevicePathHandles
,
1345 if (EFI_ERROR (Status
)) {
1350 for (Index
= 0; Index
< NoDevicePathHandles
; Index
++) {
1351 CurHandle
= DevicePathHandle
[Index
];
1354 // Check whether this handle support
1357 Status
= gBS
->HandleProtocol (
1359 &gEfiSimpleFileSystemProtocolGuid
,
1362 if (Status
== EFI_SUCCESS
) {
1366 Status
= gBS
->HandleProtocol (
1368 &gEfiLoadFileProtocolGuid
,
1371 if (Status
== EFI_SUCCESS
) {
1375 NewMenuEntry
= BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT
);
1376 if (NULL
== NewMenuEntry
) {
1377 SafeFreePool (DevicePathHandle
);
1378 return EFI_OUT_OF_RESOURCES
;
1381 NewHandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1382 NewHandleContext
->Handle
= CurHandle
;
1383 NewHandleContext
->DevicePath
= DevicePathFromHandle (CurHandle
);
1384 NewMenuEntry
->DisplayString
= DevicePathToStr (NewHandleContext
->DevicePath
);
1385 NewMenuEntry
->HelpString
= NULL
;
1386 NewMenuEntry
->OptionNumber
= OptionNumber
;
1388 InsertTailList (&DriverMenu
.Head
, &NewMenuEntry
->Link
);
1391 SafeFreePool (DevicePathHandle
);
1393 DriverMenu
.MenuNumber
= OptionNumber
;
1398 BOpt_GetBootOptionNumber (
1403 Routine Description:
1404 Get the Option Number that does not used
1413 BM_MENU_ENTRY
*NewMenuEntry
;
1414 UINT16
*BootOrderList
;
1415 UINTN BootOrderListSize
;
1420 CHAR16 StrTemp
[100];
1421 UINT16
*OptionBuffer
;
1424 BootOrderListSize
= 0;
1425 BootOrderList
= NULL
;
1427 BootOrderList
= BdsLibGetVariableAndSize (
1429 &gEfiGlobalVariableGuid
,
1432 if (BootOrderList
) {
1434 // already have Boot####
1436 // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
1438 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
1440 for (Index2
= 0; Index2
< BootOptionMenu
.MenuNumber
; Index2
++) {
1441 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index2
);
1442 if (Index
== NewMenuEntry
->OptionNumber
) {
1449 UnicodeSPrint (StrTemp
, 100, L
"Boot%04x", Index
);
1450 DEBUG((DEBUG_ERROR
,"INdex= %s\n", StrTemp
));
1451 OptionBuffer
= BdsLibGetVariableAndSize (
1453 &gEfiGlobalVariableGuid
,
1456 if (NULL
== OptionBuffer
)
1463 Number
= (UINT16
) Index
;
1475 BOpt_GetDriverOptionNumber (
1480 Routine Description:
1481 Get the Option Number that does not used
1490 BM_MENU_ENTRY
*NewMenuEntry
;
1491 UINT16
*DriverOrderList
;
1492 UINTN DriverOrderListSize
;
1498 DriverOrderListSize
= 0;
1499 DriverOrderList
= NULL
;
1501 DriverOrderList
= BdsLibGetVariableAndSize (
1503 &gEfiGlobalVariableGuid
,
1504 &DriverOrderListSize
1506 if (DriverOrderList
) {
1508 // already have Driver####
1510 // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
1512 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1514 for (Index2
= 0; Index2
< DriverOptionMenu
.MenuNumber
; Index2
++) {
1515 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index2
);
1516 if (Index
== NewMenuEntry
->OptionNumber
) {
1529 Number
= (UINT16
) Index
;
1541 BOpt_GetDriverOptions (
1542 IN BMM_CALLBACK_DATA
*CallbackData
1546 Routine Description:
1547 Build up all DriverOptionMenu
1557 UINT16 DriverString
[12];
1558 UINT8
*LoadOptionFromVar
;
1560 UINTN DriverOptionSize
;
1562 UINT16
*DriverOrderList
;
1563 UINTN DriverOrderListSize
;
1564 BM_MENU_ENTRY
*NewMenuEntry
;
1565 BM_LOAD_CONTEXT
*NewLoadContext
;
1566 UINT8
*LoadOptionPtr
;
1568 UINTN OptionalDataSize
;
1569 UINT8
*LoadOptionEnd
;
1571 DriverOrderListSize
= 0;
1572 DriverOrderList
= NULL
;
1573 DriverOptionSize
= 0;
1574 LoadOptionFromVar
= NULL
;
1575 BOpt_FreeMenu (&DriverOptionMenu
);
1576 InitializeListHead (&DriverOptionMenu
.Head
);
1578 // Get the DriverOrder from the Var
1580 DriverOrderList
= BdsLibGetVariableAndSize (
1582 &gEfiGlobalVariableGuid
,
1583 &DriverOrderListSize
1586 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1589 sizeof (DriverString
),
1591 DriverOrderList
[Index
]
1594 // Get all loadoptions from the VAR
1596 LoadOptionFromVar
= BdsLibGetVariableAndSize (
1598 &gEfiGlobalVariableGuid
,
1601 if (!LoadOptionFromVar
) {
1605 LoadOption
= EfiAllocateZeroPool (DriverOptionSize
);
1610 CopyMem (LoadOption
, LoadOptionFromVar
, DriverOptionSize
);
1611 SafeFreePool (LoadOptionFromVar
);
1613 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
1614 if (NULL
== NewMenuEntry
) {
1615 return EFI_OUT_OF_RESOURCES
;
1618 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1619 LoadOptionPtr
= LoadOption
;
1620 LoadOptionEnd
= LoadOption
+ DriverOptionSize
;
1621 NewMenuEntry
->OptionNumber
= DriverOrderList
[Index
];
1622 NewLoadContext
->LoadOptionModified
= FALSE
;
1623 NewLoadContext
->Deleted
= FALSE
;
1624 NewLoadContext
->IsLegacy
= FALSE
;
1627 // LoadOption is a pointer type of UINT8
1628 // for easy use with following LOAD_OPTION
1629 // embedded in this struct
1631 NewLoadContext
->LoadOption
= LoadOption
;
1632 NewLoadContext
->LoadOptionSize
= DriverOptionSize
;
1634 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1635 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1637 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1639 LoadOptionPtr
+= sizeof (UINT32
);
1641 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1642 LoadOptionPtr
+= sizeof (UINT16
);
1644 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1645 NewLoadContext
->Description
= EfiAllocateZeroPool (StringSize
);
1646 ASSERT (NewLoadContext
->Description
!= NULL
);
1648 NewLoadContext
->Description
,
1649 (UINT16
*) LoadOptionPtr
,
1652 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1654 LoadOptionPtr
+= StringSize
;
1656 NewLoadContext
->FilePathList
= EfiAllocateZeroPool (NewLoadContext
->FilePathListLength
);
1657 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1659 NewLoadContext
->FilePathList
,
1660 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1661 NewLoadContext
->FilePathListLength
1664 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1665 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1667 DriverOptionStrDepository
1669 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1671 DriverOptionHelpStrDepository
1673 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1675 if (LoadOptionPtr
< LoadOptionEnd
) {
1676 OptionalDataSize
= DriverOptionSize
-
1680 NewLoadContext
->FilePathListLength
;
1682 NewLoadContext
->OptionalData
= EfiAllocateZeroPool (OptionalDataSize
);
1683 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1685 NewLoadContext
->OptionalData
,
1690 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1693 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
1697 SafeFreePool (DriverOrderList
);
1698 DriverOptionMenu
.MenuNumber
= Index
;