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 Create a menu entry give a Menu type.
25 @param MenuType The Menu type to be created.
27 @retval NULL If failed to create the menu.
32 BOpt_CreateMenuEntry (
36 BM_MENU_ENTRY
*MenuEntry
;
40 // Get context size according to menu type
43 case BM_LOAD_CONTEXT_SELECT
:
44 ContextSize
= sizeof (BM_LOAD_CONTEXT
);
47 case BM_FILE_CONTEXT_SELECT
:
48 ContextSize
= sizeof (BM_FILE_CONTEXT
);
51 case BM_CONSOLE_CONTEXT_SELECT
:
52 ContextSize
= sizeof (BM_CONSOLE_CONTEXT
);
55 case BM_TERMINAL_CONTEXT_SELECT
:
56 ContextSize
= sizeof (BM_TERMINAL_CONTEXT
);
59 case BM_HANDLE_CONTEXT_SELECT
:
60 ContextSize
= sizeof (BM_HANDLE_CONTEXT
);
63 case BM_LEGACY_DEV_CONTEXT_SELECT
:
64 ContextSize
= sizeof (BM_LEGACY_DEVICE_CONTEXT
);
72 if (ContextSize
== 0) {
77 // Create new menu entry
79 MenuEntry
= AllocateZeroPool (sizeof (BM_MENU_ENTRY
));
80 if (NULL
== MenuEntry
) {
84 MenuEntry
->VariableContext
= AllocateZeroPool (ContextSize
);
85 if (NULL
== MenuEntry
->VariableContext
) {
90 MenuEntry
->Signature
= BM_MENU_ENTRY_SIGNATURE
;
91 MenuEntry
->ContextSelection
= MenuType
;
96 Free up all resource allocated for a BM_MENU_ENTRY.
98 @param MenuEntry A pointer to BM_MENU_ENTRY.
102 BOpt_DestroyMenuEntry (
103 BM_MENU_ENTRY
*MenuEntry
106 BM_LOAD_CONTEXT
*LoadContext
;
107 BM_FILE_CONTEXT
*FileContext
;
108 BM_CONSOLE_CONTEXT
*ConsoleContext
;
109 BM_TERMINAL_CONTEXT
*TerminalContext
;
110 BM_HANDLE_CONTEXT
*HandleContext
;
111 BM_LEGACY_DEVICE_CONTEXT
*LegacyDevContext
;
114 // Select by the type in Menu entry for current context type
116 switch (MenuEntry
->ContextSelection
) {
117 case BM_LOAD_CONTEXT_SELECT
:
118 LoadContext
= (BM_LOAD_CONTEXT
*) MenuEntry
->VariableContext
;
119 FreePool (LoadContext
->FilePathList
);
120 FreePool (LoadContext
->LoadOption
);
121 if (LoadContext
->OptionalData
!= NULL
) {
122 FreePool (LoadContext
->OptionalData
);
124 FreePool (LoadContext
);
127 case BM_FILE_CONTEXT_SELECT
:
128 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
130 if (!FileContext
->IsRoot
) {
131 FreePool (FileContext
->DevicePath
);
133 if (FileContext
->FHandle
!= NULL
) {
134 FileContext
->FHandle
->Close (FileContext
->FHandle
);
138 if (FileContext
->FileName
!= NULL
) {
139 FreePool (FileContext
->FileName
);
141 if (FileContext
->Info
!= NULL
) {
142 FreePool (FileContext
->Info
);
144 FreePool (FileContext
);
147 case BM_CONSOLE_CONTEXT_SELECT
:
148 ConsoleContext
= (BM_CONSOLE_CONTEXT
*) MenuEntry
->VariableContext
;
149 FreePool (ConsoleContext
->DevicePath
);
150 FreePool (ConsoleContext
);
153 case BM_TERMINAL_CONTEXT_SELECT
:
154 TerminalContext
= (BM_TERMINAL_CONTEXT
*) MenuEntry
->VariableContext
;
155 FreePool (TerminalContext
->DevicePath
);
156 FreePool (TerminalContext
);
159 case BM_HANDLE_CONTEXT_SELECT
:
160 HandleContext
= (BM_HANDLE_CONTEXT
*) MenuEntry
->VariableContext
;
161 FreePool (HandleContext
);
164 case BM_LEGACY_DEV_CONTEXT_SELECT
:
165 LegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) MenuEntry
->VariableContext
;
166 FreePool (LegacyDevContext
);
172 FreePool (MenuEntry
->DisplayString
);
173 if (NULL
!= MenuEntry
->HelpString
) {
174 FreePool (MenuEntry
->HelpString
);
177 FreePool (MenuEntry
);
181 Get the Menu Entry from the list in Menu Entry List.
183 If MenuNumber is great or equal to the number of Menu
184 Entry in the list, then ASSERT.
186 @param MenuOption The Menu Entry List to read the menu entry.
187 @param MenuNumber The index of Menu Entry.
189 @return The Menu Entry.
194 BM_MENU_OPTION
*MenuOption
,
198 BM_MENU_ENTRY
*NewMenuEntry
;
202 ASSERT (MenuNumber
< MenuOption
->MenuNumber
);
204 List
= MenuOption
->Head
.ForwardLink
;
205 for (Index
= 0; Index
< MenuNumber
; Index
++) {
206 List
= List
->ForwardLink
;
209 NewMenuEntry
= CR (List
, BM_MENU_ENTRY
, Link
, BM_MENU_ENTRY_SIGNATURE
);
215 This function build the FsOptionMenu list which records all
216 available file system in the system. They includes all instances
217 of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM
218 and all type of legacy boot device.
220 @param CallbackData BMM context data
222 @retval EFI_SUCCESS Success find the file system
223 @retval EFI_OUT_OF_RESOURCES Can not create menu entry
227 BOpt_FindFileSystem (
228 IN BMM_CALLBACK_DATA
*CallbackData
231 UINTN NoBlkIoHandles
;
232 UINTN NoSimpleFsHandles
;
233 UINTN NoLoadFileHandles
;
234 EFI_HANDLE
*BlkIoHandle
;
235 EFI_HANDLE
*SimpleFsHandle
;
236 EFI_HANDLE
*LoadFileHandle
;
238 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
241 BM_MENU_ENTRY
*MenuEntry
;
242 BM_FILE_CONTEXT
*FileContext
;
246 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
248 BBS_BBS_DEVICE_PATH BbsDevicePathNode
;
249 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
250 BOOLEAN RemovableMedia
;
253 NoSimpleFsHandles
= 0;
254 NoLoadFileHandles
= 0;
256 InitializeListHead (&FsOptionMenu
.Head
);
259 // Locate Handles that support BlockIo protocol
261 Status
= gBS
->LocateHandleBuffer (
263 &gEfiBlockIoProtocolGuid
,
268 if (!EFI_ERROR (Status
)) {
270 for (Index
= 0; Index
< NoBlkIoHandles
; Index
++) {
271 Status
= gBS
->HandleProtocol (
273 &gEfiBlockIoProtocolGuid
,
277 if (EFI_ERROR (Status
)) {
282 // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
284 if (BlkIo
->Media
->RemovableMedia
) {
285 Buffer
= AllocateZeroPool (BlkIo
->Media
->BlockSize
);
286 if (NULL
== Buffer
) {
287 FreePool (BlkIoHandle
);
288 return EFI_OUT_OF_RESOURCES
;
293 BlkIo
->Media
->MediaId
,
295 BlkIo
->Media
->BlockSize
,
301 FreePool (BlkIoHandle
);
305 // Locate Handles that support Simple File System protocol
307 Status
= gBS
->LocateHandleBuffer (
309 &gEfiSimpleFileSystemProtocolGuid
,
314 if (!EFI_ERROR (Status
)) {
316 // Find all the instances of the File System prototocol
318 for (Index
= 0; Index
< NoSimpleFsHandles
; Index
++) {
319 Status
= gBS
->HandleProtocol (
320 SimpleFsHandle
[Index
],
321 &gEfiBlockIoProtocolGuid
,
324 if (EFI_ERROR (Status
)) {
326 // If no block IO exists assume it's NOT a removable media
328 RemovableMedia
= FALSE
;
331 // If block IO exists check to see if it's remobable media
333 RemovableMedia
= BlkIo
->Media
->RemovableMedia
;
337 // Allocate pool for this load option
339 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
340 if (NULL
== MenuEntry
) {
341 FreePool (SimpleFsHandle
);
342 return EFI_OUT_OF_RESOURCES
;
345 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
347 FileContext
->Handle
= SimpleFsHandle
[Index
];
348 MenuEntry
->OptionNumber
= Index
;
349 FileContext
->FHandle
= EfiLibOpenRoot (FileContext
->Handle
);
350 if (FileContext
->FHandle
== NULL
) {
351 BOpt_DestroyMenuEntry (MenuEntry
);
355 MenuEntry
->HelpString
= DevicePathToStr (DevicePathFromHandle (FileContext
->Handle
));
356 FileContext
->Info
= EfiLibFileSystemVolumeLabelInfo (FileContext
->FHandle
);
357 FileContext
->FileName
= EfiStrDuplicate (L
"\\");
358 FileContext
->DevicePath
= FileDevicePath (
360 FileContext
->FileName
362 FileContext
->IsDir
= TRUE
;
363 FileContext
->IsRoot
= TRUE
;
364 FileContext
->IsRemovableMedia
= RemovableMedia
;
365 FileContext
->IsLoadFile
= FALSE
;
368 // Get current file system's Volume Label
370 if (FileContext
->Info
== NULL
) {
371 VolumeLabel
= L
"NO FILE SYSTEM INFO";
373 if (FileContext
->Info
->VolumeLabel
== NULL
) {
374 VolumeLabel
= L
"NULL VOLUME LABEL";
376 VolumeLabel
= FileContext
->Info
->VolumeLabel
;
377 if (*VolumeLabel
== 0x0000) {
378 VolumeLabel
= L
"NO VOLUME LABEL";
383 TempStr
= MenuEntry
->HelpString
;
384 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
385 ASSERT (MenuEntry
->DisplayString
!= NULL
);
387 MenuEntry
->DisplayString
,
394 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
398 if (NoSimpleFsHandles
!= 0) {
399 FreePool (SimpleFsHandle
);
402 // Searching for handles that support Load File protocol
404 Status
= gBS
->LocateHandleBuffer (
406 &gEfiLoadFileProtocolGuid
,
412 if (!EFI_ERROR (Status
)) {
413 for (Index
= 0; Index
< NoLoadFileHandles
; Index
++) {
414 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
415 if (NULL
== MenuEntry
) {
416 FreePool (LoadFileHandle
);
417 return EFI_OUT_OF_RESOURCES
;
420 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
421 FileContext
->IsRemovableMedia
= FALSE
;
422 FileContext
->IsLoadFile
= TRUE
;
423 FileContext
->Handle
= LoadFileHandle
[Index
];
424 FileContext
->IsRoot
= TRUE
;
426 FileContext
->DevicePath
= DevicePathFromHandle (FileContext
->Handle
);
428 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
430 TempStr
= MenuEntry
->HelpString
;
431 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
432 ASSERT (MenuEntry
->DisplayString
!= NULL
);
434 MenuEntry
->DisplayString
,
440 MenuEntry
->OptionNumber
= OptionNumber
;
442 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
446 if (NoLoadFileHandles
!= 0) {
447 FreePool (LoadFileHandle
);
451 // Add Legacy Boot Option Support Here
453 Status
= gBS
->LocateProtocol (
454 &gEfiLegacyBiosProtocolGuid
,
456 (VOID
**) &LegacyBios
458 if (!EFI_ERROR (Status
)) {
460 for (Index
= BBS_TYPE_FLOPPY
; Index
<= BBS_TYPE_EMBEDDED_NETWORK
; Index
++) {
461 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
462 if (NULL
== MenuEntry
) {
463 return EFI_OUT_OF_RESOURCES
;
466 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
468 FileContext
->IsRemovableMedia
= FALSE
;
469 FileContext
->IsLoadFile
= TRUE
;
470 FileContext
->IsBootLegacy
= TRUE
;
471 DeviceType
= (UINT16
) Index
;
472 BbsDevicePathNode
.Header
.Type
= BBS_DEVICE_PATH
;
473 BbsDevicePathNode
.Header
.SubType
= BBS_BBS_DP
;
474 SetDevicePathNodeLength (
475 &BbsDevicePathNode
.Header
,
476 sizeof (BBS_BBS_DEVICE_PATH
)
478 BbsDevicePathNode
.DeviceType
= DeviceType
;
479 BbsDevicePathNode
.StatusFlag
= 0;
480 BbsDevicePathNode
.String
[0] = 0;
481 DevicePath
= AppendDevicePathNode (
483 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevicePathNode
486 FileContext
->DevicePath
= DevicePath
;
487 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
489 TempStr
= MenuEntry
->HelpString
;
490 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
491 ASSERT (MenuEntry
->DisplayString
!= NULL
);
493 MenuEntry
->DisplayString
,
498 MenuEntry
->OptionNumber
= OptionNumber
;
500 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
504 // Remember how many file system options are here
506 FsOptionMenu
.MenuNumber
= OptionNumber
;
511 Free resources allocated in Allocate Rountine.
513 @param FreeMenu Menu to be freed
517 BM_MENU_OPTION
*FreeMenu
520 BM_MENU_ENTRY
*MenuEntry
;
521 while (!IsListEmpty (&FreeMenu
->Head
)) {
523 FreeMenu
->Head
.ForwardLink
,
526 BM_MENU_ENTRY_SIGNATURE
528 RemoveEntryList (&MenuEntry
->Link
);
529 BOpt_DestroyMenuEntry (MenuEntry
);
534 Find files under current directory
535 All files and sub-directories in current directory
536 will be stored in DirectoryMenu for future use.
538 @param CallbackData The BMM context data.
539 @param MenuEntry The Menu Entry.
541 @retval EFI_SUCCESS Get files from current dir successfully.
542 @return Other value if can't get files from current dir.
547 IN BMM_CALLBACK_DATA
*CallbackData
,
548 IN BM_MENU_ENTRY
*MenuEntry
551 EFI_FILE_HANDLE NewDir
;
553 EFI_FILE_INFO
*DirInfo
;
556 BM_MENU_ENTRY
*NewMenuEntry
;
557 BM_FILE_CONTEXT
*FileContext
;
558 BM_FILE_CONTEXT
*NewFileContext
;
563 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
564 Dir
= FileContext
->FHandle
;
567 // Open current directory to get files from it
572 FileContext
->FileName
,
576 if (!FileContext
->IsRoot
) {
580 if (EFI_ERROR (Status
)) {
584 DirInfo
= EfiLibFileInfo (NewDir
);
585 if (DirInfo
== NULL
) {
586 return EFI_NOT_FOUND
;
589 if (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
590 return EFI_INVALID_PARAMETER
;
593 FileContext
->DevicePath
= FileDevicePath (
595 FileContext
->FileName
598 DirBufferSize
= sizeof (EFI_FILE_INFO
) + 1024;
599 DirInfo
= AllocateZeroPool (DirBufferSize
);
600 if (DirInfo
== NULL
) {
601 return EFI_OUT_OF_RESOURCES
;
604 // Get all files in current directory
605 // Pass 1 to get Directories
606 // Pass 2 to get files that are EFI images
608 for (Pass
= 1; Pass
<= 2; Pass
++) {
609 NewDir
->SetPosition (NewDir
, 0);
611 BufferSize
= DirBufferSize
;
612 Status
= NewDir
->Read (NewDir
, &BufferSize
, DirInfo
);
613 if (EFI_ERROR (Status
) || BufferSize
== 0) {
617 if ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
&& Pass
== 2) ||
618 (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) && Pass
== 1)
621 // Pass 1 is for Directories
622 // Pass 2 is for file names
627 if (!(BOpt_IsEfiImageName (DirInfo
->FileName
) || DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
629 // Slip file unless it is a directory entry or a .EFI file
634 NewMenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
635 if (NULL
== NewMenuEntry
) {
636 return EFI_OUT_OF_RESOURCES
;
639 NewFileContext
= (BM_FILE_CONTEXT
*) NewMenuEntry
->VariableContext
;
640 NewFileContext
->Handle
= FileContext
->Handle
;
641 NewFileContext
->FileName
= BOpt_AppendFileName (
642 FileContext
->FileName
,
645 NewFileContext
->FHandle
= NewDir
;
646 NewFileContext
->DevicePath
= FileDevicePath (
647 NewFileContext
->Handle
,
648 NewFileContext
->FileName
650 NewMenuEntry
->HelpString
= NULL
;
652 MenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
654 FileOptionStrDepository
657 NewFileContext
->IsDir
= (BOOLEAN
) ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
);
659 if (NewFileContext
->IsDir
) {
660 BufferSize
= StrLen (DirInfo
->FileName
) * 2 + 6;
661 NewMenuEntry
->DisplayString
= AllocateZeroPool (BufferSize
);
664 NewMenuEntry
->DisplayString
,
671 NewMenuEntry
->DisplayString
= EfiStrDuplicate (DirInfo
->FileName
);
674 NewFileContext
->IsRoot
= FALSE
;
675 NewFileContext
->IsLoadFile
= FALSE
;
676 NewFileContext
->IsRemovableMedia
= FALSE
;
678 NewMenuEntry
->OptionNumber
= OptionNumber
;
680 InsertTailList (&DirectoryMenu
.Head
, &NewMenuEntry
->Link
);
684 DirectoryMenu
.MenuNumber
= OptionNumber
;
690 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
692 @retval EFI_SUCCESS The function complete successfully.
693 @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.
697 BOpt_GetLegacyOptions (
701 BM_MENU_ENTRY
*NewMenuEntry
;
702 BM_LEGACY_DEVICE_CONTEXT
*NewLegacyDevContext
;
704 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
710 CHAR16 DescString
[100];
723 // Initialize Bbs Table Context from BBS info data
725 InitializeListHead (&LegacyFDMenu
.Head
);
726 InitializeListHead (&LegacyHDMenu
.Head
);
727 InitializeListHead (&LegacyCDMenu
.Head
);
728 InitializeListHead (&LegacyNETMenu
.Head
);
729 InitializeListHead (&LegacyBEVMenu
.Head
);
731 Status
= gBS
->LocateProtocol (
732 &gEfiLegacyBiosProtocolGuid
,
734 (VOID
**) &LegacyBios
736 if (!EFI_ERROR (Status
)) {
737 Status
= LegacyBios
->GetBbsInfo (
744 if (EFI_ERROR (Status
)) {
755 for (Index
= 0; Index
< BbsCount
; Index
++) {
756 if ((BBS_IGNORE_ENTRY
== BbsTable
[Index
].BootPriority
) ||
757 (BBS_DO_NOT_BOOT_FROM
== BbsTable
[Index
].BootPriority
)
762 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT
);
763 if (NULL
== NewMenuEntry
) {
767 NewLegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) NewMenuEntry
->VariableContext
;
768 NewLegacyDevContext
->BbsTable
= &BbsTable
[Index
];
769 NewLegacyDevContext
->Index
= Index
;
770 NewLegacyDevContext
->BbsCount
= BbsCount
;
771 BdsBuildLegacyDevNameString (
777 NewLegacyDevContext
->Description
= AllocateZeroPool (StrSize (DescString
));
778 if (NULL
== NewLegacyDevContext
->Description
) {
782 CopyMem (NewLegacyDevContext
->Description
, DescString
, StrSize (DescString
));
783 NewMenuEntry
->DisplayString
= NewLegacyDevContext
->Description
;
784 NewMenuEntry
->HelpString
= NULL
;
786 switch (BbsTable
[Index
].DeviceType
) {
788 InsertTailList (&LegacyFDMenu
.Head
, &NewMenuEntry
->Link
);
793 InsertTailList (&LegacyHDMenu
.Head
, &NewMenuEntry
->Link
);
798 InsertTailList (&LegacyCDMenu
.Head
, &NewMenuEntry
->Link
);
802 case BBS_EMBED_NETWORK
:
803 InsertTailList (&LegacyNETMenu
.Head
, &NewMenuEntry
->Link
);
808 InsertTailList (&LegacyBEVMenu
.Head
, &NewMenuEntry
->Link
);
814 if (Index
!= BbsCount
) {
815 BOpt_FreeLegacyOptions ();
816 return EFI_OUT_OF_RESOURCES
;
819 LegacyFDMenu
.MenuNumber
= FDNum
;
820 LegacyHDMenu
.MenuNumber
= HDNum
;
821 LegacyCDMenu
.MenuNumber
= CDNum
;
822 LegacyNETMenu
.MenuNumber
= NETNum
;
823 LegacyBEVMenu
.MenuNumber
= BEVNum
;
828 Free out resouce allocated from Legacy Boot Options.
832 BOpt_FreeLegacyOptions (
836 BOpt_FreeMenu (&LegacyFDMenu
);
837 BOpt_FreeMenu (&LegacyHDMenu
);
838 BOpt_FreeMenu (&LegacyCDMenu
);
839 BOpt_FreeMenu (&LegacyNETMenu
);
840 BOpt_FreeMenu (&LegacyBEVMenu
);
845 Build the BootOptionMenu according to BootOrder Variable.
846 This Routine will access the Boot#### to get EFI_LOAD_OPTION.
848 @param CallbackData The BMM context data.
850 @return The number of the Var Boot####.
854 BOpt_GetBootOptions (
855 IN BMM_CALLBACK_DATA
*CallbackData
859 UINT16 BootString
[10];
860 UINT8
*LoadOptionFromVar
;
862 UINTN BootOptionSize
;
863 BOOLEAN BootNextFlag
;
864 UINT16
*BootOrderList
;
865 UINTN BootOrderListSize
;
868 BM_MENU_ENTRY
*NewMenuEntry
;
869 BM_LOAD_CONTEXT
*NewLoadContext
;
870 UINT8
*LoadOptionPtr
;
872 UINTN OptionalDataSize
;
873 UINT8
*LoadOptionEnd
;
874 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
879 BootOrderListSize
= 0;
881 BootOrderList
= NULL
;
883 LoadOptionFromVar
= NULL
;
884 BOpt_FreeMenu (&BootOptionMenu
);
885 InitializeListHead (&BootOptionMenu
.Head
);
888 // Get the BootOrder from the Var
890 BootOrderList
= BdsLibGetVariableAndSize (
892 &gEfiGlobalVariableGuid
,
897 // Get the BootNext from the Var
899 BootNext
= BdsLibGetVariableAndSize (
901 &gEfiGlobalVariableGuid
,
905 if (BootNext
!= NULL
) {
906 if (BootNextSize
!= sizeof (UINT16
)) {
912 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
913 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", BootOrderList
[Index
]);
915 // Get all loadoptions from the VAR
917 LoadOptionFromVar
= BdsLibGetVariableAndSize (
919 &gEfiGlobalVariableGuid
,
922 if (LoadOptionFromVar
== NULL
) {
926 LoadOption
= AllocateZeroPool (BootOptionSize
);
927 if (LoadOption
== NULL
) {
931 CopyMem (LoadOption
, LoadOptionFromVar
, BootOptionSize
);
932 FreePool (LoadOptionFromVar
);
934 if (BootNext
!= NULL
) {
935 BootNextFlag
= (BOOLEAN
) (*BootNext
== BootOrderList
[Index
]);
937 BootNextFlag
= FALSE
;
940 if (0 == (*((UINT32
*) LoadOption
) & LOAD_OPTION_ACTIVE
)) {
941 FreePool (LoadOption
);
945 // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
946 // the buffer allocated already should be freed before returning.
948 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
949 if (NULL
== NewMenuEntry
) {
950 return EFI_OUT_OF_RESOURCES
;
953 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
955 LoadOptionPtr
= LoadOption
;
956 LoadOptionEnd
= LoadOption
+ BootOptionSize
;
958 NewMenuEntry
->OptionNumber
= BootOrderList
[Index
];
959 NewLoadContext
->LoadOptionModified
= FALSE
;
960 NewLoadContext
->Deleted
= FALSE
;
961 NewLoadContext
->IsBootNext
= BootNextFlag
;
964 // Is a Legacy Device?
966 Ptr
= (UINT8
*) LoadOption
;
969 // Attribute = *(UINT32 *)Ptr;
971 Ptr
+= sizeof (UINT32
);
974 // FilePathSize = *(UINT16 *)Ptr;
976 Ptr
+= sizeof (UINT16
);
979 // Description = (CHAR16 *)Ptr;
981 Ptr
+= StrSize ((CHAR16
*) Ptr
);
984 // Now Ptr point to Device Path
986 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
987 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
988 NewLoadContext
->IsLegacy
= TRUE
;
990 NewLoadContext
->IsLegacy
= FALSE
;
993 // LoadOption is a pointer type of UINT8
994 // for easy use with following LOAD_OPTION
995 // embedded in this struct
997 NewLoadContext
->LoadOption
= LoadOption
;
998 NewLoadContext
->LoadOptionSize
= BootOptionSize
;
1000 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1001 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1003 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1005 LoadOptionPtr
+= sizeof (UINT32
);
1007 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1008 LoadOptionPtr
+= sizeof (UINT16
);
1010 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1011 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1012 ASSERT (NewLoadContext
->Description
!= NULL
);
1014 NewLoadContext
->Description
,
1015 (UINT16
*) LoadOptionPtr
,
1018 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1020 LoadOptionPtr
+= StringSize
;
1022 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1023 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1025 NewLoadContext
->FilePathList
,
1026 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1027 NewLoadContext
->FilePathListLength
1030 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1031 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1033 BootOptionStrDepository
1035 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1037 BootOptionHelpStrDepository
1039 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1041 if (LoadOptionPtr
< LoadOptionEnd
) {
1042 OptionalDataSize
= BootOptionSize
-
1046 NewLoadContext
->FilePathListLength
;
1048 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1049 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1051 NewLoadContext
->OptionalData
,
1056 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1059 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
1063 if (BootNext
!= NULL
) {
1064 FreePool (BootNext
);
1066 if (BootOrderList
!= NULL
) {
1067 FreePool (BootOrderList
);
1069 BootOptionMenu
.MenuNumber
= MenuCount
;
1075 Append file name to existing file name.
1077 @param Str1 The existing file name
1078 @param Str2 The file name to be appended
1080 @return Allocate a new string to hold the appended result.
1081 Caller is responsible to free the returned string.
1085 BOpt_AppendFileName (
1097 Size1
= StrSize (Str1
);
1098 Size2
= StrSize (Str2
);
1099 Str
= AllocateZeroPool (Size1
+ Size2
+ sizeof (CHAR16
));
1100 ASSERT (Str
!= NULL
);
1102 TmpStr
= AllocateZeroPool (Size1
+ Size2
+ sizeof (CHAR16
));
1103 ASSERT (TmpStr
!= NULL
);
1106 if (!((*Str
== '\\') && (*(Str
+ 1) == 0))) {
1107 StrCat (Str
, L
"\\");
1115 if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '.' && *(Ptr
+ 3) == L
'\\') {
1117 // Convert "\Name\..\" to "\"
1118 // DO NOT convert the .. if it is at the end of the string. This will
1119 // break the .. behavior in changing directories.
1123 // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings
1126 StrCpy (TmpStr
, Ptr
+ 3);
1127 StrCpy (LastSlash
, TmpStr
);
1129 } else if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '\\') {
1131 // Convert a "\.\" to a "\"
1135 // Use TmpStr as a backup, as StrCpy in BaseLib does not handle copy of two strings
1138 StrCpy (TmpStr
, Ptr
+ 2);
1139 StrCpy (Ptr
, TmpStr
);
1141 } else if (*Ptr
== '\\') {
1155 Check whether current FileName point to a valid
1158 @param FileName File need to be checked.
1160 @retval TRUE Is Efi Image
1161 @retval FALSE Not a valid Efi Image
1165 BOpt_IsEfiImageName (
1170 // Search for ".efi" extension
1172 while (*FileName
!= L
'\0') {
1173 if (FileName
[0] == '.') {
1174 if (FileName
[1] == 'e' || FileName
[1] == 'E') {
1175 if (FileName
[2] == 'f' || FileName
[2] == 'F') {
1176 if (FileName
[3] == 'i' || FileName
[3] == 'I') {
1178 } else if (FileName
[3] == 0x0000) {
1181 } else if (FileName
[2] == 0x0000) {
1184 } else if (FileName
[1] == 0x0000) {
1197 Check whether current FileName point to a valid Efi Application
1199 @param Dir Pointer to current Directory
1200 @param FileName Pointer to current File name.
1202 @retval TRUE Is a valid Efi Application
1203 @retval FALSE not a valid Efi Application
1208 IN EFI_FILE_HANDLE Dir
,
1213 EFI_IMAGE_DOS_HEADER DosHdr
;
1215 EFI_FILE_HANDLE File
;
1217 EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr
;
1219 Status
= Dir
->Open (Dir
, &File
, FileName
, EFI_FILE_MODE_READ
, 0);
1221 if (EFI_ERROR (Status
)) {
1225 BufferSize
= sizeof (EFI_IMAGE_DOS_HEADER
);
1226 File
->Read (File
, &BufferSize
, &DosHdr
);
1227 if (DosHdr
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1232 File
->SetPosition (File
, DosHdr
.e_lfanew
);
1233 BufferSize
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
1234 File
->Read (File
, &BufferSize
, &PeHdr
);
1235 if (PeHdr
.Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1240 // Determine PE type and read subsytem
1242 if (PeHdr
.Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1243 Subsystem
= PeHdr
.Pe32
.OptionalHeader
.Subsystem
;
1244 } else if (PeHdr
.Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1245 Subsystem
= PeHdr
.Pe32Plus
.OptionalHeader
.Subsystem
;
1250 if (Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1261 Find drivers that will be added as Driver#### variables from handles
1262 in current system environment
1263 All valid handles in the system except those consume SimpleFs, LoadFile
1264 are stored in DriverMenu for future use.
1266 @retval EFI_SUCCESS The function complets successfully.
1267 @return Other value if failed to build the DriverMenu.
1275 UINTN NoDevicePathHandles
;
1276 EFI_HANDLE
*DevicePathHandle
;
1279 BM_MENU_ENTRY
*NewMenuEntry
;
1280 BM_HANDLE_CONTEXT
*NewHandleContext
;
1281 EFI_HANDLE CurHandle
;
1283 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFs
;
1284 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1289 InitializeListHead (&DriverMenu
.Head
);
1292 // At first, get all handles that support Device Path
1293 // protocol which is the basic requirement for
1296 Status
= gBS
->LocateHandleBuffer (
1298 &gEfiDevicePathProtocolGuid
,
1300 &NoDevicePathHandles
,
1303 if (EFI_ERROR (Status
)) {
1308 for (Index
= 0; Index
< NoDevicePathHandles
; Index
++) {
1309 CurHandle
= DevicePathHandle
[Index
];
1311 Status
= gBS
->HandleProtocol (
1313 &gEfiSimpleFileSystemProtocolGuid
,
1316 if (Status
== EFI_SUCCESS
) {
1320 Status
= gBS
->HandleProtocol (
1322 &gEfiLoadFileProtocolGuid
,
1325 if (Status
== EFI_SUCCESS
) {
1329 NewMenuEntry
= BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT
);
1330 if (NULL
== NewMenuEntry
) {
1331 FreePool (DevicePathHandle
);
1332 return EFI_OUT_OF_RESOURCES
;
1335 NewHandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1336 NewHandleContext
->Handle
= CurHandle
;
1337 NewHandleContext
->DevicePath
= DevicePathFromHandle (CurHandle
);
1338 NewMenuEntry
->DisplayString
= DevicePathToStr (NewHandleContext
->DevicePath
);
1339 NewMenuEntry
->HelpString
= NULL
;
1340 NewMenuEntry
->OptionNumber
= OptionNumber
;
1342 InsertTailList (&DriverMenu
.Head
, &NewMenuEntry
->Link
);
1346 if (DevicePathHandle
!= NULL
) {
1347 FreePool (DevicePathHandle
);
1350 DriverMenu
.MenuNumber
= OptionNumber
;
1356 Get the Option Number that has not been allocated for use.
1358 @return The available Option Number.
1362 BOpt_GetBootOptionNumber (
1366 BM_MENU_ENTRY
*NewMenuEntry
;
1367 UINT16
*BootOrderList
;
1368 UINTN BootOrderListSize
;
1373 CHAR16 StrTemp
[100];
1374 UINT16
*OptionBuffer
;
1377 BootOrderListSize
= 0;
1378 BootOrderList
= NULL
;
1380 BootOrderList
= BdsLibGetVariableAndSize (
1382 &gEfiGlobalVariableGuid
,
1385 if (BootOrderList
!= NULL
) {
1387 // already have Boot####
1389 // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
1391 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
1393 for (Index2
= 0; Index2
< BootOptionMenu
.MenuNumber
; Index2
++) {
1394 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index2
);
1395 if (Index
== NewMenuEntry
->OptionNumber
) {
1402 UnicodeSPrint (StrTemp
, 100, L
"Boot%04x", Index
);
1403 DEBUG((DEBUG_ERROR
,"INdex= %s\n", StrTemp
));
1404 OptionBuffer
= BdsLibGetVariableAndSize (
1406 &gEfiGlobalVariableGuid
,
1409 if (NULL
== OptionBuffer
) {
1417 Number
= (UINT16
) Index
;
1430 Get the Option Number that is not in use.
1432 @return The unused Option Number.
1436 BOpt_GetDriverOptionNumber (
1440 BM_MENU_ENTRY
*NewMenuEntry
;
1441 UINT16
*DriverOrderList
;
1442 UINTN DriverOrderListSize
;
1448 DriverOrderListSize
= 0;
1449 DriverOrderList
= NULL
;
1451 DriverOrderList
= BdsLibGetVariableAndSize (
1453 &gEfiGlobalVariableGuid
,
1454 &DriverOrderListSize
1456 if (DriverOrderList
!= NULL
) {
1458 // already have Driver####
1460 // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
1462 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1464 for (Index2
= 0; Index2
< DriverOptionMenu
.MenuNumber
; Index2
++) {
1465 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index2
);
1466 if (Index
== NewMenuEntry
->OptionNumber
) {
1479 Number
= (UINT16
) Index
;
1492 Build up all DriverOptionMenu
1494 @param CallbackData The BMM context data.
1496 @return EFI_SUCESS The functin completes successfully.
1497 @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
1502 BOpt_GetDriverOptions (
1503 IN BMM_CALLBACK_DATA
*CallbackData
1507 UINT16 DriverString
[12];
1508 UINT8
*LoadOptionFromVar
;
1510 UINTN DriverOptionSize
;
1512 UINT16
*DriverOrderList
;
1513 UINTN DriverOrderListSize
;
1514 BM_MENU_ENTRY
*NewMenuEntry
;
1515 BM_LOAD_CONTEXT
*NewLoadContext
;
1516 UINT8
*LoadOptionPtr
;
1518 UINTN OptionalDataSize
;
1519 UINT8
*LoadOptionEnd
;
1521 DriverOrderListSize
= 0;
1522 DriverOrderList
= NULL
;
1523 DriverOptionSize
= 0;
1524 LoadOptionFromVar
= NULL
;
1525 BOpt_FreeMenu (&DriverOptionMenu
);
1526 InitializeListHead (&DriverOptionMenu
.Head
);
1528 // Get the DriverOrder from the Var
1530 DriverOrderList
= BdsLibGetVariableAndSize (
1532 &gEfiGlobalVariableGuid
,
1533 &DriverOrderListSize
1536 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1539 sizeof (DriverString
),
1541 DriverOrderList
[Index
]
1544 // Get all loadoptions from the VAR
1546 LoadOptionFromVar
= BdsLibGetVariableAndSize (
1548 &gEfiGlobalVariableGuid
,
1551 if (LoadOptionFromVar
== NULL
) {
1555 LoadOption
= AllocateZeroPool (DriverOptionSize
);
1556 if (LoadOption
== NULL
) {
1560 CopyMem (LoadOption
, LoadOptionFromVar
, DriverOptionSize
);
1561 FreePool (LoadOptionFromVar
);
1563 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
1564 if (NULL
== NewMenuEntry
) {
1565 return EFI_OUT_OF_RESOURCES
;
1568 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1569 LoadOptionPtr
= LoadOption
;
1570 LoadOptionEnd
= LoadOption
+ DriverOptionSize
;
1571 NewMenuEntry
->OptionNumber
= DriverOrderList
[Index
];
1572 NewLoadContext
->LoadOptionModified
= FALSE
;
1573 NewLoadContext
->Deleted
= FALSE
;
1574 NewLoadContext
->IsLegacy
= FALSE
;
1577 // LoadOption is a pointer type of UINT8
1578 // for easy use with following LOAD_OPTION
1579 // embedded in this struct
1581 NewLoadContext
->LoadOption
= LoadOption
;
1582 NewLoadContext
->LoadOptionSize
= DriverOptionSize
;
1584 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1585 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1587 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1589 LoadOptionPtr
+= sizeof (UINT32
);
1591 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1592 LoadOptionPtr
+= sizeof (UINT16
);
1594 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1595 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1596 ASSERT (NewLoadContext
->Description
!= NULL
);
1598 NewLoadContext
->Description
,
1599 (UINT16
*) LoadOptionPtr
,
1602 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1604 LoadOptionPtr
+= StringSize
;
1606 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1607 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1609 NewLoadContext
->FilePathList
,
1610 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1611 NewLoadContext
->FilePathListLength
1614 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1615 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1617 DriverOptionStrDepository
1619 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1621 DriverOptionHelpStrDepository
1623 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1625 if (LoadOptionPtr
< LoadOptionEnd
) {
1626 OptionalDataSize
= DriverOptionSize
-
1630 NewLoadContext
->FilePathListLength
;
1632 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1633 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1635 NewLoadContext
->OptionalData
,
1640 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1643 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
1647 if (DriverOrderList
!= NULL
) {
1648 FreePool (DriverOrderList
);
1650 DriverOptionMenu
.MenuNumber
= Index
;