2 Copyright (c) 2006 - 2007, 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
28 // Include common header file for this module.
30 #include "CommonHeader.h"
32 #include "BootMaint.h"
33 #include "BBSsupport.h"
36 BOpt_CreateMenuEntry (
42 Create Menu Entry for future use, make all types together
43 in order to reduce code size
46 MenuType Use this parameter to identify current
50 NULL Cannot allocate memory for current menu
52 Others A valid pointer pointing to the allocated
53 memory pool for current menu entry
57 BM_MENU_ENTRY
*MenuEntry
;
61 case BM_LOAD_CONTEXT_SELECT
:
62 ContextSize
= sizeof (BM_LOAD_CONTEXT
);
65 case BM_FILE_CONTEXT_SELECT
:
66 ContextSize
= sizeof (BM_FILE_CONTEXT
);
69 case BM_CONSOLE_CONTEXT_SELECT
:
70 ContextSize
= sizeof (BM_CONSOLE_CONTEXT
);
73 case BM_TERMINAL_CONTEXT_SELECT
:
74 ContextSize
= sizeof (BM_TERMINAL_CONTEXT
);
77 case BM_HANDLE_CONTEXT_SELECT
:
78 ContextSize
= sizeof (BM_HANDLE_CONTEXT
);
81 case BM_LEGACY_DEV_CONTEXT_SELECT
:
82 ContextSize
= sizeof (BM_LEGACY_DEVICE_CONTEXT
);
91 if (0 == ContextSize
) {
95 MenuEntry
= AllocateZeroPool (sizeof (BM_MENU_ENTRY
));
96 if (NULL
== MenuEntry
) {
100 MenuEntry
->VariableContext
= AllocateZeroPool (ContextSize
);
101 if (NULL
== MenuEntry
->VariableContext
) {
102 SafeFreePool (MenuEntry
);
107 MenuEntry
->Signature
= BM_MENU_ENTRY_SIGNATURE
;
108 MenuEntry
->ContextSelection
= MenuType
;
113 BOpt_DestroyMenuEntry (
114 BM_MENU_ENTRY
*MenuEntry
117 Routine Description :
118 Destroy the menu entry passed in
121 The menu entry need to be destroyed
128 BM_LOAD_CONTEXT
*LoadContext
;
129 BM_FILE_CONTEXT
*FileContext
;
130 BM_CONSOLE_CONTEXT
*ConsoleContext
;
131 BM_TERMINAL_CONTEXT
*TerminalContext
;
132 BM_HANDLE_CONTEXT
*HandleContext
;
133 BM_LEGACY_DEVICE_CONTEXT
*LegacyDevContext
;
136 // Select by the type in Menu entry for current context type
138 switch (MenuEntry
->ContextSelection
) {
139 case BM_LOAD_CONTEXT_SELECT
:
140 LoadContext
= (BM_LOAD_CONTEXT
*) MenuEntry
->VariableContext
;
141 SafeFreePool (LoadContext
->FilePathList
);
142 SafeFreePool (LoadContext
->LoadOption
);
143 SafeFreePool (LoadContext
->OptionalData
);
144 SafeFreePool (LoadContext
);
147 case BM_FILE_CONTEXT_SELECT
:
148 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
150 if (!FileContext
->IsRoot
) {
151 SafeFreePool (FileContext
->DevicePath
);
153 if (FileContext
->FHandle
!= NULL
) {
154 FileContext
->FHandle
->Close (FileContext
->FHandle
);
158 SafeFreePool (FileContext
->FileName
);
159 SafeFreePool (FileContext
->Info
);
160 SafeFreePool (FileContext
);
163 case BM_CONSOLE_CONTEXT_SELECT
:
164 ConsoleContext
= (BM_CONSOLE_CONTEXT
*) MenuEntry
->VariableContext
;
165 SafeFreePool (ConsoleContext
->DevicePath
);
166 SafeFreePool (ConsoleContext
);
169 case BM_TERMINAL_CONTEXT_SELECT
:
170 TerminalContext
= (BM_TERMINAL_CONTEXT
*) MenuEntry
->VariableContext
;
171 SafeFreePool (TerminalContext
->DevicePath
);
172 SafeFreePool (TerminalContext
);
175 case BM_HANDLE_CONTEXT_SELECT
:
176 HandleContext
= (BM_HANDLE_CONTEXT
*) MenuEntry
->VariableContext
;
177 SafeFreePool (HandleContext
);
180 case BM_LEGACY_DEV_CONTEXT_SELECT
:
181 LegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) MenuEntry
->VariableContext
;
182 SafeFreePool (LegacyDevContext
);
188 SafeFreePool (MenuEntry
->DisplayString
);
189 if (NULL
!= MenuEntry
->HelpString
) {
190 SafeFreePool (MenuEntry
->HelpString
);
193 SafeFreePool (MenuEntry
);
198 BM_MENU_OPTION
*MenuOption
,
202 Rountine Description :
203 Use this routine to get one particular menu entry in specified
207 MenuOption The menu that we will search
209 MenuNumber The menunubmer that we want
212 The desired menu entry
216 BM_MENU_ENTRY
*NewMenuEntry
;
220 if (MenuNumber
>= MenuOption
->MenuNumber
) {
224 List
= MenuOption
->Head
.ForwardLink
;
225 for (Index
= 0; Index
< MenuNumber
; Index
++) {
226 List
= List
->ForwardLink
;
229 NewMenuEntry
= CR (List
, BM_MENU_ENTRY
, Link
, BM_MENU_ENTRY_SIGNATURE
);
235 BOpt_FindFileSystem (
236 IN BMM_CALLBACK_DATA
*CallbackData
241 Find file systems for current Extensible Firmware
242 Including Handles that support Simple File System
243 protocol, Load File protocol.
245 Building up the FileSystem Menu for user selection
246 All file system will be stored in FsOptionMenu
250 CallbackData - BMM context data
253 EFI_SUCCESS - Success find the file system
254 EFI_OUT_OF_RESOURCES - Can not create menu entry
258 UINTN NoSimpleFsHandles
;
259 UINTN NoLoadFileHandles
;
260 EFI_HANDLE
*SimpleFsHandle
;
261 EFI_HANDLE
*LoadFileHandle
;
263 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
266 BM_MENU_ENTRY
*MenuEntry
;
267 BM_FILE_CONTEXT
*FileContext
;
270 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
272 BBS_BBS_DEVICE_PATH BbsDevicePathNode
;
273 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
274 BOOLEAN RemovableMedia
;
277 NoSimpleFsHandles
= 0;
278 NoLoadFileHandles
= 0;
280 InitializeListHead (&FsOptionMenu
.Head
);
283 // Locate Handles that support Simple File System protocol
285 Status
= gBS
->LocateHandleBuffer (
287 &gEfiSimpleFileSystemProtocolGuid
,
292 if (!EFI_ERROR (Status
)) {
294 // Find all the instances of the File System prototocol
296 for (Index
= 0; Index
< NoSimpleFsHandles
; Index
++) {
297 Status
= gBS
->HandleProtocol (
298 SimpleFsHandle
[Index
],
299 &gEfiBlockIoProtocolGuid
,
302 if (EFI_ERROR (Status
)) {
304 // If no block IO exists assume it's NOT a removable media
306 RemovableMedia
= FALSE
;
309 // If block IO exists check to see if it's remobable media
311 RemovableMedia
= BlkIo
->Media
->RemovableMedia
;
315 // Allocate pool for this load option
317 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
318 if (NULL
== MenuEntry
) {
319 SafeFreePool (SimpleFsHandle
);
320 return EFI_OUT_OF_RESOURCES
;
323 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
325 FileContext
->Handle
= SimpleFsHandle
[Index
];
326 MenuEntry
->OptionNumber
= Index
;
327 FileContext
->FHandle
= EfiLibOpenRoot (FileContext
->Handle
);
328 if (!FileContext
->FHandle
) {
329 BOpt_DestroyMenuEntry (MenuEntry
);
333 MenuEntry
->HelpString
= DevicePathToStr (DevicePathFromHandle (FileContext
->Handle
));
334 FileContext
->Info
= EfiLibFileSystemVolumeLabelInfo (FileContext
->FHandle
);
335 FileContext
->FileName
= EfiStrDuplicate (L
"\\");
336 FileContext
->DevicePath
= FileDevicePath (
338 FileContext
->FileName
340 FileContext
->IsDir
= TRUE
;
341 FileContext
->IsRoot
= TRUE
;
342 FileContext
->IsRemovableMedia
= FALSE
;
343 FileContext
->IsLoadFile
= FALSE
;
346 // Get current file system's Volume Label
348 if (FileContext
->Info
== NULL
) {
349 VolumeLabel
= L
"NO FILE SYSTEM INFO";
351 if (FileContext
->Info
->VolumeLabel
== NULL
) {
352 VolumeLabel
= L
"NULL VOLUME LABEL";
354 VolumeLabel
= FileContext
->Info
->VolumeLabel
;
355 if (*VolumeLabel
== 0x0000) {
356 VolumeLabel
= L
"NO VOLUME LABEL";
361 TempStr
= MenuEntry
->HelpString
;
362 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
363 ASSERT (MenuEntry
->DisplayString
!= NULL
);
365 MenuEntry
->DisplayString
,
372 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
376 if (NoSimpleFsHandles
!= 0) {
377 SafeFreePool (SimpleFsHandle
);
380 // Searching for handles that support Load File protocol
382 Status
= gBS
->LocateHandleBuffer (
384 &gEfiLoadFileProtocolGuid
,
390 if (!EFI_ERROR (Status
)) {
391 for (Index
= 0; Index
< NoLoadFileHandles
; Index
++) {
392 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
393 if (NULL
== MenuEntry
) {
394 SafeFreePool (LoadFileHandle
);
395 return EFI_OUT_OF_RESOURCES
;
398 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
399 FileContext
->IsRemovableMedia
= FALSE
;
400 FileContext
->IsLoadFile
= TRUE
;
401 FileContext
->Handle
= LoadFileHandle
[Index
];
402 FileContext
->IsRoot
= TRUE
;
404 FileContext
->DevicePath
= DevicePathFromHandle (FileContext
->Handle
);
406 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
408 TempStr
= MenuEntry
->HelpString
;
409 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
410 ASSERT (MenuEntry
->DisplayString
!= NULL
);
412 MenuEntry
->DisplayString
,
418 MenuEntry
->OptionNumber
= OptionNumber
;
420 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
424 if (NoLoadFileHandles
!= 0) {
425 SafeFreePool (LoadFileHandle
);
429 // Add Legacy Boot Option Support Here
431 Status
= gBS
->LocateProtocol (
432 &gEfiLegacyBiosProtocolGuid
,
436 if (!EFI_ERROR (Status
)) {
438 for (Index
= BBS_TYPE_FLOPPY
; Index
<= BBS_TYPE_EMBEDDED_NETWORK
; Index
++) {
439 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
440 if (NULL
== MenuEntry
) {
441 return EFI_OUT_OF_RESOURCES
;
444 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
446 FileContext
->IsRemovableMedia
= FALSE
;
447 FileContext
->IsLoadFile
= TRUE
;
448 FileContext
->IsBootLegacy
= TRUE
;
449 DeviceType
= (UINT16
) Index
;
450 BbsDevicePathNode
.Header
.Type
= BBS_DEVICE_PATH
;
451 BbsDevicePathNode
.Header
.SubType
= BBS_BBS_DP
;
452 SetDevicePathNodeLength (
453 &BbsDevicePathNode
.Header
,
454 sizeof (BBS_BBS_DEVICE_PATH
)
456 BbsDevicePathNode
.DeviceType
= DeviceType
;
457 BbsDevicePathNode
.StatusFlag
= 0;
458 BbsDevicePathNode
.String
[0] = 0;
459 DevicePath
= AppendDevicePathNode (
461 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevicePathNode
464 FileContext
->DevicePath
= DevicePath
;
465 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
467 TempStr
= MenuEntry
->HelpString
;
468 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
469 ASSERT (MenuEntry
->DisplayString
!= NULL
);
471 MenuEntry
->DisplayString
,
476 MenuEntry
->OptionNumber
= OptionNumber
;
478 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
482 // Remember how many file system options are here
484 FsOptionMenu
.MenuNumber
= OptionNumber
;
490 BM_MENU_OPTION
*FreeMenu
495 Free resources allocated in Allocate Rountine
498 FreeMenu Menu to be freed
505 BM_MENU_ENTRY
*MenuEntry
;
506 while (!IsListEmpty (&FreeMenu
->Head
)) {
508 FreeMenu
->Head
.ForwardLink
,
511 BM_MENU_ENTRY_SIGNATURE
513 RemoveEntryList (&MenuEntry
->Link
);
514 BOpt_DestroyMenuEntry (MenuEntry
);
520 IN BMM_CALLBACK_DATA
*CallbackData
,
521 IN BM_MENU_ENTRY
*MenuEntry
526 Find files under current directory
527 All files and sub-directories in current directory
528 will be stored in DirectoryMenu for future use.
531 FileOption -- Pointer for Dir to explore
534 TRUE -- Get files from current dir successfully
535 FALSE -- Can't get files from current dir
539 EFI_FILE_HANDLE NewDir
;
541 EFI_FILE_INFO
*DirInfo
;
544 BM_MENU_ENTRY
*NewMenuEntry
;
545 BM_FILE_CONTEXT
*FileContext
;
546 BM_FILE_CONTEXT
*NewFileContext
;
551 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
552 Dir
= FileContext
->FHandle
;
555 // Open current directory to get files from it
560 FileContext
->FileName
,
564 if (!FileContext
->IsRoot
) {
568 if (EFI_ERROR (Status
)) {
572 DirInfo
= EfiLibFileInfo (NewDir
);
574 return EFI_NOT_FOUND
;
577 if (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
578 return EFI_INVALID_PARAMETER
;
581 FileContext
->DevicePath
= FileDevicePath (
583 FileContext
->FileName
586 DirBufferSize
= sizeof (EFI_FILE_INFO
) + 1024;
587 DirInfo
= AllocateZeroPool (DirBufferSize
);
589 return EFI_OUT_OF_RESOURCES
;
592 // Get all files in current directory
593 // Pass 1 to get Directories
594 // Pass 2 to get files that are EFI images
596 for (Pass
= 1; Pass
<= 2; Pass
++) {
597 NewDir
->SetPosition (NewDir
, 0);
599 BufferSize
= DirBufferSize
;
600 Status
= NewDir
->Read (NewDir
, &BufferSize
, DirInfo
);
601 if (EFI_ERROR (Status
) || BufferSize
== 0) {
605 if ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
&& Pass
== 2) ||
606 (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) && Pass
== 1)
609 // Pass 1 is for Directories
610 // Pass 2 is for file names
615 if (!(BOpt_IsEfiImageName (DirInfo
->FileName
) || DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
617 // Slip file unless it is a directory entry or a .EFI file
622 NewMenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
623 if (NULL
== NewMenuEntry
) {
624 return EFI_OUT_OF_RESOURCES
;
627 NewFileContext
= (BM_FILE_CONTEXT
*) NewMenuEntry
->VariableContext
;
628 NewFileContext
->Handle
= FileContext
->Handle
;
629 NewFileContext
->FileName
= BOpt_AppendFileName (
630 FileContext
->FileName
,
633 NewFileContext
->FHandle
= NewDir
;
634 NewFileContext
->DevicePath
= FileDevicePath (
635 NewFileContext
->Handle
,
636 NewFileContext
->FileName
638 NewMenuEntry
->HelpString
= NULL
;
640 MenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
642 FileOptionStrDepository
645 NewFileContext
->IsDir
= (BOOLEAN
) ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
);
647 if (NewFileContext
->IsDir
) {
648 BufferSize
= StrLen (DirInfo
->FileName
) * 2 + 6;
649 NewMenuEntry
->DisplayString
= AllocateZeroPool (BufferSize
);
652 NewMenuEntry
->DisplayString
,
659 NewMenuEntry
->DisplayString
= EfiStrDuplicate (DirInfo
->FileName
);
662 NewFileContext
->IsRoot
= FALSE
;
663 NewFileContext
->IsLoadFile
= FALSE
;
664 NewFileContext
->IsRemovableMedia
= FALSE
;
666 NewMenuEntry
->OptionNumber
= OptionNumber
;
668 InsertTailList (&DirectoryMenu
.Head
, &NewMenuEntry
->Link
);
672 DirectoryMenu
.MenuNumber
= OptionNumber
;
673 SafeFreePool (DirInfo
);
678 BOpt_GetLegacyOptions (
684 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
690 The device info of legacy device.
694 BM_MENU_ENTRY
*NewMenuEntry
;
695 BM_LEGACY_DEVICE_CONTEXT
*NewLegacyDevContext
;
697 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
703 CHAR16 DescString
[100];
716 // Initialize Bbs Table Context from BBS info data
718 InitializeListHead (&LegacyFDMenu
.Head
);
719 InitializeListHead (&LegacyHDMenu
.Head
);
720 InitializeListHead (&LegacyCDMenu
.Head
);
721 InitializeListHead (&LegacyNETMenu
.Head
);
722 InitializeListHead (&LegacyBEVMenu
.Head
);
724 Status
= gBS
->LocateProtocol (
725 &gEfiLegacyBiosProtocolGuid
,
729 if (!EFI_ERROR (Status
)) {
730 Status
= LegacyBios
->GetBbsInfo (
737 if (EFI_ERROR (Status
)) {
748 for (Index
= 0; Index
< BbsCount
; Index
++) {
749 if ((BBS_IGNORE_ENTRY
== BbsTable
[Index
].BootPriority
) ||
750 (BBS_DO_NOT_BOOT_FROM
== BbsTable
[Index
].BootPriority
) ||
751 (BBS_LOWEST_PRIORITY
== BbsTable
[Index
].BootPriority
)
756 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT
);
757 if (NULL
== NewMenuEntry
) {
761 NewLegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) NewMenuEntry
->VariableContext
;
762 NewLegacyDevContext
->BbsTable
= &BbsTable
[Index
];
763 NewLegacyDevContext
->Index
= Index
;
764 NewLegacyDevContext
->BbsCount
= BbsCount
;
765 BdsBuildLegacyDevNameString (
771 NewLegacyDevContext
->Description
= AllocateZeroPool (StrSize (DescString
));
772 if (NULL
== NewLegacyDevContext
->Description
) {
776 CopyMem (NewLegacyDevContext
->Description
, DescString
, StrSize (DescString
));
777 NewMenuEntry
->DisplayString
= NewLegacyDevContext
->Description
;
778 NewMenuEntry
->HelpString
= NULL
;
780 switch (BbsTable
[Index
].DeviceType
) {
782 InsertTailList (&LegacyFDMenu
.Head
, &NewMenuEntry
->Link
);
787 InsertTailList (&LegacyHDMenu
.Head
, &NewMenuEntry
->Link
);
792 InsertTailList (&LegacyCDMenu
.Head
, &NewMenuEntry
->Link
);
796 case BBS_EMBED_NETWORK
:
797 InsertTailList (&LegacyNETMenu
.Head
, &NewMenuEntry
->Link
);
802 InsertTailList (&LegacyBEVMenu
.Head
, &NewMenuEntry
->Link
);
808 if (Index
!= BbsCount
) {
809 BOpt_FreeLegacyOptions ();
810 return EFI_OUT_OF_RESOURCES
;
813 LegacyFDMenu
.MenuNumber
= FDNum
;
814 LegacyHDMenu
.MenuNumber
= HDNum
;
815 LegacyCDMenu
.MenuNumber
= CDNum
;
816 LegacyNETMenu
.MenuNumber
= NETNum
;
817 LegacyBEVMenu
.MenuNumber
= BEVNum
;
822 BOpt_FreeLegacyOptions (
826 BOpt_FreeMenu (&LegacyFDMenu
);
827 BOpt_FreeMenu (&LegacyHDMenu
);
828 BOpt_FreeMenu (&LegacyCDMenu
);
829 BOpt_FreeMenu (&LegacyNETMenu
);
830 BOpt_FreeMenu (&LegacyBEVMenu
);
834 BOpt_GetBootOptions (
835 IN BMM_CALLBACK_DATA
*CallbackData
841 Build the BootOptionMenu according to BootOrder Variable.
842 This Routine will access the Boot#### to get EFI_LOAD_OPTION
848 The number of the Var Boot####
853 UINT16 BootString
[10];
854 UINT8
*LoadOptionFromVar
;
856 UINTN BootOptionSize
;
857 BOOLEAN BootNextFlag
;
858 UINT16
*BootOrderList
;
859 UINTN BootOrderListSize
;
862 BM_MENU_ENTRY
*NewMenuEntry
;
863 BM_LOAD_CONTEXT
*NewLoadContext
;
864 UINT8
*LoadOptionPtr
;
866 UINTN OptionalDataSize
;
867 UINT8
*LoadOptionEnd
;
868 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
873 BootOrderListSize
= 0;
875 BootOrderList
= NULL
;
877 LoadOptionFromVar
= NULL
;
878 BOpt_FreeMenu (&BootOptionMenu
);
879 InitializeListHead (&BootOptionMenu
.Head
);
882 // Get the BootOrder from the Var
884 BootOrderList
= BdsLibGetVariableAndSize (
886 &gEfiGlobalVariableGuid
,
891 // Get the BootNext from the Var
893 BootNext
= BdsLibGetVariableAndSize (
895 &gEfiGlobalVariableGuid
,
900 if (BootNextSize
!= sizeof (UINT16
)) {
901 SafeFreePool (BootNext
);
906 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
907 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", BootOrderList
[Index
]);
909 // Get all loadoptions from the VAR
911 LoadOptionFromVar
= BdsLibGetVariableAndSize (
913 &gEfiGlobalVariableGuid
,
916 if (!LoadOptionFromVar
) {
920 LoadOption
= AllocateZeroPool (BootOptionSize
);
925 CopyMem (LoadOption
, LoadOptionFromVar
, BootOptionSize
);
926 SafeFreePool (LoadOptionFromVar
);
929 BootNextFlag
= (BOOLEAN
) (*BootNext
== BootOrderList
[Index
]);
931 BootNextFlag
= FALSE
;
934 if (0 == (*((UINT32
*) LoadOption
) & LOAD_OPTION_ACTIVE
)) {
935 SafeFreePool (LoadOption
);
939 // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
940 // the buffer allocated already should be freed before returning.
942 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
943 if (NULL
== NewMenuEntry
) {
944 return EFI_OUT_OF_RESOURCES
;
947 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
949 LoadOptionPtr
= LoadOption
;
950 LoadOptionEnd
= LoadOption
+ BootOptionSize
;
952 NewMenuEntry
->OptionNumber
= BootOrderList
[Index
];
953 NewLoadContext
->LoadOptionModified
= FALSE
;
954 NewLoadContext
->Deleted
= FALSE
;
955 NewLoadContext
->IsBootNext
= BootNextFlag
;
958 // Is a Legacy Device?
960 Ptr
= (UINT8
*) LoadOption
;
963 // Attribute = *(UINT32 *)Ptr;
965 Ptr
+= sizeof (UINT32
);
968 // FilePathSize = *(UINT16 *)Ptr;
970 Ptr
+= sizeof (UINT16
);
973 // Description = (CHAR16 *)Ptr;
975 Ptr
+= StrSize ((CHAR16
*) Ptr
);
978 // Now Ptr point to Device Path
980 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
981 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
982 NewLoadContext
->IsLegacy
= TRUE
;
984 NewLoadContext
->IsLegacy
= FALSE
;
987 // LoadOption is a pointer type of UINT8
988 // for easy use with following LOAD_OPTION
989 // embedded in this struct
991 NewLoadContext
->LoadOption
= LoadOption
;
992 NewLoadContext
->LoadOptionSize
= BootOptionSize
;
994 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
995 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
997 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
999 LoadOptionPtr
+= sizeof (UINT32
);
1001 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1002 LoadOptionPtr
+= sizeof (UINT16
);
1004 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1005 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1006 ASSERT (NewLoadContext
->Description
!= NULL
);
1008 NewLoadContext
->Description
,
1009 (UINT16
*) LoadOptionPtr
,
1012 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1014 LoadOptionPtr
+= StringSize
;
1016 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1017 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1019 NewLoadContext
->FilePathList
,
1020 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1021 NewLoadContext
->FilePathListLength
1024 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1025 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1027 BootOptionStrDepository
1029 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1031 BootOptionHelpStrDepository
1033 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1035 if (LoadOptionPtr
< LoadOptionEnd
) {
1036 OptionalDataSize
= BootOptionSize
-
1040 NewLoadContext
->FilePathListLength
;
1042 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1043 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1045 NewLoadContext
->OptionalData
,
1050 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1053 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
1057 SafeFreePool (BootNext
);
1058 SafeFreePool (BootOrderList
);
1059 BootOptionMenu
.MenuNumber
= MenuCount
;
1065 OUT CHAR16
*Destination
,
1066 IN CONST CHAR16
*Source
1069 CHAR16
*ReturnValue
;
1072 // Destination cannot be NULL
1074 ASSERT (Destination
!= NULL
);
1076 ReturnValue
= Destination
;
1078 *(Destination
++) = *(Source
++);
1085 BOpt_AppendFileName (
1092 Append file name to existing file name.
1095 Str1 - existing file name
1096 Str2 - file name to be appended
1099 Allocate a new string to hold the appended result.
1100 Caller is responsible to free the returned string.
1110 Size1
= StrSize (Str1
);
1111 Size2
= StrSize (Str2
);
1112 Str
= AllocateZeroPool (Size1
+ Size2
+ sizeof (CHAR16
));
1113 ASSERT (Str
!= NULL
);
1116 if (!((*Str
== '\\') && (*(Str
+ 1) == 0))) {
1117 StrCat (Str
, L
"\\");
1125 if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '.' && *(Ptr
+ 3) != 0) {
1127 // Convert \Name\..\ to \
1128 // DO NOT convert the .. if it is at the end of the string. This will
1129 // break the .. behavior in changing directories.
1131 BdsStrCpy (LastSlash
, Ptr
+ 3);
1133 } else if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '\\') {
1135 // Convert a \.\ to a \
1137 BdsStrCpy (Ptr
, Ptr
+ 2);
1139 } else if (*Ptr
== '\\') {
1150 BOpt_IsEfiImageName (
1156 Check whether current FileName point to a valid
1160 FileName - File need to be checked.
1164 FALSE - Not a valid Efi Image
1169 // Search for ".efi" extension
1172 if (FileName
[0] == '.') {
1173 if (FileName
[1] == 'e' || FileName
[1] == 'E') {
1174 if (FileName
[2] == 'f' || FileName
[2] == 'F') {
1175 if (FileName
[3] == 'i' || FileName
[3] == 'I') {
1177 } else if (FileName
[3] == 0x0000) {
1180 } else if (FileName
[2] == 0x0000) {
1183 } else if (FileName
[1] == 0x0000) {
1197 IsEfiAppReadFromFile (
1198 IN VOID
*FileHandle
,
1199 IN UINTN FileOffset
,
1200 IN OUT UINTN
*ReadSize
,
1205 EFI_FILE_HANDLE File
;
1207 File
= (EFI_FILE_HANDLE
)FileHandle
;
1208 Status
= File
->SetPosition (File
, FileOffset
);
1209 if (EFI_ERROR (Status
)) {
1213 return File
->Read (File
, ReadSize
, Buffer
);
1220 IN EFI_FILE_HANDLE Dir
,
1225 Routine Description:
1226 Check whether current FileName point to a valid Efi Application
1229 Dir - Pointer to current Directory
1230 FileName - Pointer to current File name.
1233 TRUE - Is a valid Efi Application
1234 FALSE - not a valid Efi Application
1239 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1240 EFI_FILE_HANDLE File
;
1242 Status
= Dir
->Open (Dir
, &File
, FileName
, EFI_FILE_MODE_READ
, 0);
1243 if (EFI_ERROR (Status
)) {
1247 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1248 ImageContext
.Handle
= (VOID
*)File
;
1249 ImageContext
.ImageRead
= IsEfiAppReadFromFile
;
1251 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1253 if (EFI_ERROR (Status
)) {
1257 if (ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1272 Find drivers that will be added as Driver#### variables from handles
1273 in current system environment
1274 All valid handles in the system except those consume SimpleFs, LoadFile
1275 are stored in DriverMenu for future use.
1286 UINTN NoDevicePathHandles
;
1287 EFI_HANDLE
*DevicePathHandle
;
1290 BM_MENU_ENTRY
*NewMenuEntry
;
1291 BM_HANDLE_CONTEXT
*NewHandleContext
;
1292 EFI_HANDLE CurHandle
;
1294 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFs
;
1295 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1300 InitializeListHead (&DriverMenu
.Head
);
1303 // At first, get all handles that support Device Path
1304 // protocol which is the basic requirement for
1307 Status
= gBS
->LocateHandleBuffer (
1309 &gEfiDevicePathProtocolGuid
,
1311 &NoDevicePathHandles
,
1314 if (EFI_ERROR (Status
)) {
1319 for (Index
= 0; Index
< NoDevicePathHandles
; Index
++) {
1320 CurHandle
= DevicePathHandle
[Index
];
1323 // Check whether this handle support
1326 Status
= gBS
->HandleProtocol (
1328 &gEfiSimpleFileSystemProtocolGuid
,
1331 if (Status
== EFI_SUCCESS
) {
1335 Status
= gBS
->HandleProtocol (
1337 &gEfiLoadFileProtocolGuid
,
1340 if (Status
== EFI_SUCCESS
) {
1344 NewMenuEntry
= BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT
);
1345 if (NULL
== NewMenuEntry
) {
1346 return EFI_OUT_OF_RESOURCES
;
1349 NewHandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1350 NewHandleContext
->Handle
= CurHandle
;
1351 NewHandleContext
->DevicePath
= DevicePathFromHandle (CurHandle
);
1352 NewMenuEntry
->DisplayString
= DevicePathToStr (NewHandleContext
->DevicePath
);
1353 NewMenuEntry
->HelpString
= NULL
;
1354 NewMenuEntry
->OptionNumber
= OptionNumber
;
1356 InsertTailList (&DriverMenu
.Head
, &NewMenuEntry
->Link
);
1360 DriverMenu
.MenuNumber
= OptionNumber
;
1365 BOpt_GetBootOptionNumber (
1370 Routine Description:
1371 Get the Option Number that does not used
1380 BM_MENU_ENTRY
*NewMenuEntry
;
1381 UINT16
*BootOrderList
;
1382 UINTN BootOrderListSize
;
1387 CHAR16 StrTemp
[100];
1388 UINT16
*OptionBuffer
;
1391 BootOrderListSize
= 0;
1392 BootOrderList
= NULL
;
1394 BootOrderList
= BdsLibGetVariableAndSize (
1396 &gEfiGlobalVariableGuid
,
1399 if (BootOrderList
) {
1401 // already have Boot####
1403 // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
1405 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
1407 for (Index2
= 0; Index2
< BootOptionMenu
.MenuNumber
; Index2
++) {
1408 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index2
);
1409 if (Index
== NewMenuEntry
->OptionNumber
) {
1416 UnicodeSPrint (StrTemp
, 100, L
"Boot%04x", Index
);
1417 DEBUG((EFI_D_ERROR
,"INdex= %s\n", StrTemp
));
1418 OptionBuffer
= BdsLibGetVariableAndSize (
1420 &gEfiGlobalVariableGuid
,
1423 if (NULL
== OptionBuffer
)
1430 Number
= (UINT16
) Index
;
1442 BOpt_GetDriverOptionNumber (
1447 Routine Description:
1448 Get the Option Number that does not used
1457 BM_MENU_ENTRY
*NewMenuEntry
;
1458 UINT16
*DriverOrderList
;
1459 UINTN DriverOrderListSize
;
1465 DriverOrderListSize
= 0;
1466 DriverOrderList
= NULL
;
1468 DriverOrderList
= BdsLibGetVariableAndSize (
1470 &gEfiGlobalVariableGuid
,
1471 &DriverOrderListSize
1473 if (DriverOrderList
) {
1475 // already have Driver####
1477 // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
1479 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1481 for (Index2
= 0; Index2
< DriverOptionMenu
.MenuNumber
; Index2
++) {
1482 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index2
);
1483 if (Index
== NewMenuEntry
->OptionNumber
) {
1496 Number
= (UINT16
) Index
;
1508 BOpt_GetDriverOptions (
1509 IN BMM_CALLBACK_DATA
*CallbackData
1513 Routine Description:
1514 Build up all DriverOptionMenu
1524 UINT16 DriverString
[12];
1525 UINT8
*LoadOptionFromVar
;
1527 UINTN DriverOptionSize
;
1529 UINT16
*DriverOrderList
;
1530 UINTN DriverOrderListSize
;
1531 BM_MENU_ENTRY
*NewMenuEntry
;
1532 BM_LOAD_CONTEXT
*NewLoadContext
;
1533 UINT8
*LoadOptionPtr
;
1535 UINTN OptionalDataSize
;
1536 UINT8
*LoadOptionEnd
;
1538 DriverOrderListSize
= 0;
1539 DriverOrderList
= NULL
;
1540 DriverOptionSize
= 0;
1541 LoadOptionFromVar
= NULL
;
1542 BOpt_FreeMenu (&DriverOptionMenu
);
1543 InitializeListHead (&DriverOptionMenu
.Head
);
1545 // Get the DriverOrder from the Var
1547 DriverOrderList
= BdsLibGetVariableAndSize (
1549 &gEfiGlobalVariableGuid
,
1550 &DriverOrderListSize
1553 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1556 sizeof (DriverString
),
1558 DriverOrderList
[Index
]
1561 // Get all loadoptions from the VAR
1563 LoadOptionFromVar
= BdsLibGetVariableAndSize (
1565 &gEfiGlobalVariableGuid
,
1568 if (!LoadOptionFromVar
) {
1572 LoadOption
= AllocateZeroPool (DriverOptionSize
);
1577 CopyMem (LoadOption
, LoadOptionFromVar
, DriverOptionSize
);
1578 SafeFreePool (LoadOptionFromVar
);
1580 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
1581 if (NULL
== NewMenuEntry
) {
1582 return EFI_OUT_OF_RESOURCES
;
1585 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1586 LoadOptionPtr
= LoadOption
;
1587 LoadOptionEnd
= LoadOption
+ DriverOptionSize
;
1588 NewMenuEntry
->OptionNumber
= DriverOrderList
[Index
];
1589 NewLoadContext
->LoadOptionModified
= FALSE
;
1590 NewLoadContext
->Deleted
= FALSE
;
1591 NewLoadContext
->IsLegacy
= FALSE
;
1594 // LoadOption is a pointer type of UINT8
1595 // for easy use with following LOAD_OPTION
1596 // embedded in this struct
1598 NewLoadContext
->LoadOption
= LoadOption
;
1599 NewLoadContext
->LoadOptionSize
= DriverOptionSize
;
1601 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1602 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1604 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1606 LoadOptionPtr
+= sizeof (UINT32
);
1608 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1609 LoadOptionPtr
+= sizeof (UINT16
);
1611 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1612 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1613 ASSERT (NewLoadContext
->Description
!= NULL
);
1615 NewLoadContext
->Description
,
1616 (UINT16
*) LoadOptionPtr
,
1619 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1621 LoadOptionPtr
+= StringSize
;
1623 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1624 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1626 NewLoadContext
->FilePathList
,
1627 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1628 NewLoadContext
->FilePathListLength
1631 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1632 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1634 DriverOptionStrDepository
1636 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1638 DriverOptionHelpStrDepository
1640 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1642 if (LoadOptionPtr
< LoadOptionEnd
) {
1643 OptionalDataSize
= DriverOptionSize
-
1647 NewLoadContext
->FilePathListLength
;
1649 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1650 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1652 NewLoadContext
->OptionalData
,
1657 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1660 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
1664 SafeFreePool (DriverOrderList
);
1665 DriverOptionMenu
.MenuNumber
= Index
;
1676 Routine Description:
1677 Wrap original FreePool gBS call
1678 in order to decrease code length
1686 if (Buffer
!= NULL
) {