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.
28 @retval NULL If failed to create the menu.
33 BOpt_CreateMenuEntry (
37 BM_MENU_ENTRY
*MenuEntry
;
41 case BM_LOAD_CONTEXT_SELECT
:
42 ContextSize
= sizeof (BM_LOAD_CONTEXT
);
45 case BM_FILE_CONTEXT_SELECT
:
46 ContextSize
= sizeof (BM_FILE_CONTEXT
);
49 case BM_CONSOLE_CONTEXT_SELECT
:
50 ContextSize
= sizeof (BM_CONSOLE_CONTEXT
);
53 case BM_TERMINAL_CONTEXT_SELECT
:
54 ContextSize
= sizeof (BM_TERMINAL_CONTEXT
);
57 case BM_HANDLE_CONTEXT_SELECT
:
58 ContextSize
= sizeof (BM_HANDLE_CONTEXT
);
61 case BM_LEGACY_DEV_CONTEXT_SELECT
:
62 ContextSize
= sizeof (BM_LEGACY_DEVICE_CONTEXT
);
71 if (0 == ContextSize
) {
75 MenuEntry
= AllocateZeroPool (sizeof (BM_MENU_ENTRY
));
76 if (NULL
== MenuEntry
) {
80 MenuEntry
->VariableContext
= AllocateZeroPool (ContextSize
);
81 if (NULL
== MenuEntry
->VariableContext
) {
82 SafeFreePool (MenuEntry
);
87 MenuEntry
->Signature
= BM_MENU_ENTRY_SIGNATURE
;
88 MenuEntry
->ContextSelection
= MenuType
;
93 Free up all resource allocated for a BM_MENU_ENTRY.
95 @param MenuEntry A pointer to BM_MENU_ENTRY.
101 BOpt_DestroyMenuEntry (
102 BM_MENU_ENTRY
*MenuEntry
105 BM_LOAD_CONTEXT
*LoadContext
;
106 BM_FILE_CONTEXT
*FileContext
;
107 BM_CONSOLE_CONTEXT
*ConsoleContext
;
108 BM_TERMINAL_CONTEXT
*TerminalContext
;
109 BM_HANDLE_CONTEXT
*HandleContext
;
110 BM_LEGACY_DEVICE_CONTEXT
*LegacyDevContext
;
113 // Select by the type in Menu entry for current context type
115 switch (MenuEntry
->ContextSelection
) {
116 case BM_LOAD_CONTEXT_SELECT
:
117 LoadContext
= (BM_LOAD_CONTEXT
*) MenuEntry
->VariableContext
;
118 SafeFreePool (LoadContext
->FilePathList
);
119 SafeFreePool (LoadContext
->LoadOption
);
120 SafeFreePool (LoadContext
->OptionalData
);
121 SafeFreePool (LoadContext
);
124 case BM_FILE_CONTEXT_SELECT
:
125 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
127 if (!FileContext
->IsRoot
) {
128 SafeFreePool (FileContext
->DevicePath
);
130 if (FileContext
->FHandle
!= NULL
) {
131 FileContext
->FHandle
->Close (FileContext
->FHandle
);
135 SafeFreePool (FileContext
->FileName
);
136 SafeFreePool (FileContext
->Info
);
137 SafeFreePool (FileContext
);
140 case BM_CONSOLE_CONTEXT_SELECT
:
141 ConsoleContext
= (BM_CONSOLE_CONTEXT
*) MenuEntry
->VariableContext
;
142 SafeFreePool (ConsoleContext
->DevicePath
);
143 SafeFreePool (ConsoleContext
);
146 case BM_TERMINAL_CONTEXT_SELECT
:
147 TerminalContext
= (BM_TERMINAL_CONTEXT
*) MenuEntry
->VariableContext
;
148 SafeFreePool (TerminalContext
->DevicePath
);
149 SafeFreePool (TerminalContext
);
152 case BM_HANDLE_CONTEXT_SELECT
:
153 HandleContext
= (BM_HANDLE_CONTEXT
*) MenuEntry
->VariableContext
;
154 SafeFreePool (HandleContext
);
157 case BM_LEGACY_DEV_CONTEXT_SELECT
:
158 LegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) MenuEntry
->VariableContext
;
159 SafeFreePool (LegacyDevContext
);
165 SafeFreePool (MenuEntry
->DisplayString
);
166 if (NULL
!= MenuEntry
->HelpString
) {
167 SafeFreePool (MenuEntry
->HelpString
);
170 SafeFreePool (MenuEntry
);
174 Get the Menu Entry from the list in Menu Entry List.
176 If MenuNumber is great or equal to the number of Menu
177 Entry in the list, then ASSERT.
179 @param MenuOption The Menu Entry List to read the menu entry.
180 @param MenuNumber The index of Menu Entry.
182 @return The Menu Entry.
187 BM_MENU_OPTION
*MenuOption
,
191 BM_MENU_ENTRY
*NewMenuEntry
;
195 ASSERT (MenuNumber
< MenuOption
->MenuNumber
);
197 List
= MenuOption
->Head
.ForwardLink
;
198 for (Index
= 0; Index
< MenuNumber
; Index
++) {
199 List
= List
->ForwardLink
;
202 NewMenuEntry
= CR (List
, BM_MENU_ENTRY
, Link
, BM_MENU_ENTRY_SIGNATURE
);
208 This function build the FsOptionMenu list which records all
209 available file system in the system. They includes all instances
210 of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM
211 and all type of legacy boot device.
213 @param CallbackData BMM context data
215 @retval EFI_SUCCESS Success find the file system
216 @retval EFI_OUT_OF_RESOURCES Can not create menu entry
220 BOpt_FindFileSystem (
221 IN BMM_CALLBACK_DATA
*CallbackData
224 UINTN NoBlkIoHandles
;
225 UINTN NoSimpleFsHandles
;
226 UINTN NoLoadFileHandles
;
227 EFI_HANDLE
*BlkIoHandle
;
228 EFI_HANDLE
*SimpleFsHandle
;
229 EFI_HANDLE
*LoadFileHandle
;
231 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
234 BM_MENU_ENTRY
*MenuEntry
;
235 BM_FILE_CONTEXT
*FileContext
;
239 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
241 BBS_BBS_DEVICE_PATH BbsDevicePathNode
;
242 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
243 BOOLEAN RemovableMedia
;
246 NoSimpleFsHandles
= 0;
247 NoLoadFileHandles
= 0;
249 InitializeListHead (&FsOptionMenu
.Head
);
252 // Locate Handles that support BlockIo protocol
254 Status
= gBS
->LocateHandleBuffer (
256 &gEfiBlockIoProtocolGuid
,
261 if (!EFI_ERROR (Status
)) {
263 for (Index
= 0; Index
< NoBlkIoHandles
; Index
++) {
264 Status
= gBS
->HandleProtocol (
266 &gEfiBlockIoProtocolGuid
,
270 if (EFI_ERROR (Status
)) {
275 // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
277 if (BlkIo
->Media
->RemovableMedia
) {
278 Buffer
= AllocateZeroPool (BlkIo
->Media
->BlockSize
);
279 if (NULL
== Buffer
) {
280 SafeFreePool (BlkIoHandle
);
281 return EFI_OUT_OF_RESOURCES
;
286 BlkIo
->Media
->MediaId
,
288 BlkIo
->Media
->BlockSize
,
291 SafeFreePool (Buffer
);
294 SafeFreePool (BlkIoHandle
);
298 // Locate Handles that support Simple File System protocol
300 Status
= gBS
->LocateHandleBuffer (
302 &gEfiSimpleFileSystemProtocolGuid
,
307 if (!EFI_ERROR (Status
)) {
309 // Find all the instances of the File System prototocol
311 for (Index
= 0; Index
< NoSimpleFsHandles
; Index
++) {
312 Status
= gBS
->HandleProtocol (
313 SimpleFsHandle
[Index
],
314 &gEfiBlockIoProtocolGuid
,
317 if (EFI_ERROR (Status
)) {
319 // If no block IO exists assume it's NOT a removable media
321 RemovableMedia
= FALSE
;
324 // If block IO exists check to see if it's remobable media
326 RemovableMedia
= BlkIo
->Media
->RemovableMedia
;
330 // Allocate pool for this load option
332 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
333 if (NULL
== MenuEntry
) {
334 SafeFreePool (SimpleFsHandle
);
335 return EFI_OUT_OF_RESOURCES
;
338 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
340 FileContext
->Handle
= SimpleFsHandle
[Index
];
341 MenuEntry
->OptionNumber
= Index
;
342 FileContext
->FHandle
= EfiLibOpenRoot (FileContext
->Handle
);
343 if (FileContext
->FHandle
== NULL
) {
344 BOpt_DestroyMenuEntry (MenuEntry
);
348 MenuEntry
->HelpString
= DevicePathToStr (DevicePathFromHandle (FileContext
->Handle
));
349 FileContext
->Info
= EfiLibFileSystemVolumeLabelInfo (FileContext
->FHandle
);
350 FileContext
->FileName
= EfiStrDuplicate (L
"\\");
351 FileContext
->DevicePath
= FileDevicePath (
353 FileContext
->FileName
355 FileContext
->IsDir
= TRUE
;
356 FileContext
->IsRoot
= TRUE
;
357 FileContext
->IsRemovableMedia
= RemovableMedia
;
358 FileContext
->IsLoadFile
= FALSE
;
361 // Get current file system's Volume Label
363 if (FileContext
->Info
== NULL
) {
364 VolumeLabel
= L
"NO FILE SYSTEM INFO";
366 if (FileContext
->Info
->VolumeLabel
== NULL
) {
367 VolumeLabel
= L
"NULL VOLUME LABEL";
369 VolumeLabel
= FileContext
->Info
->VolumeLabel
;
370 if (*VolumeLabel
== 0x0000) {
371 VolumeLabel
= L
"NO VOLUME LABEL";
376 TempStr
= MenuEntry
->HelpString
;
377 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
378 ASSERT (MenuEntry
->DisplayString
!= NULL
);
380 MenuEntry
->DisplayString
,
387 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
391 if (NoSimpleFsHandles
!= 0) {
392 SafeFreePool (SimpleFsHandle
);
395 // Searching for handles that support Load File protocol
397 Status
= gBS
->LocateHandleBuffer (
399 &gEfiLoadFileProtocolGuid
,
405 if (!EFI_ERROR (Status
)) {
406 for (Index
= 0; Index
< NoLoadFileHandles
; Index
++) {
407 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
408 if (NULL
== MenuEntry
) {
409 SafeFreePool (LoadFileHandle
);
410 return EFI_OUT_OF_RESOURCES
;
413 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
414 FileContext
->IsRemovableMedia
= FALSE
;
415 FileContext
->IsLoadFile
= TRUE
;
416 FileContext
->Handle
= LoadFileHandle
[Index
];
417 FileContext
->IsRoot
= TRUE
;
419 FileContext
->DevicePath
= DevicePathFromHandle (FileContext
->Handle
);
421 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
423 TempStr
= MenuEntry
->HelpString
;
424 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
425 ASSERT (MenuEntry
->DisplayString
!= NULL
);
427 MenuEntry
->DisplayString
,
433 MenuEntry
->OptionNumber
= OptionNumber
;
435 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
439 if (NoLoadFileHandles
!= 0) {
440 SafeFreePool (LoadFileHandle
);
444 // Add Legacy Boot Option Support Here
446 Status
= gBS
->LocateProtocol (
447 &gEfiLegacyBiosProtocolGuid
,
449 (VOID
**) &LegacyBios
451 if (!EFI_ERROR (Status
)) {
453 for (Index
= BBS_TYPE_FLOPPY
; Index
<= BBS_TYPE_EMBEDDED_NETWORK
; Index
++) {
454 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
455 if (NULL
== MenuEntry
) {
456 return EFI_OUT_OF_RESOURCES
;
459 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
461 FileContext
->IsRemovableMedia
= FALSE
;
462 FileContext
->IsLoadFile
= TRUE
;
463 FileContext
->IsBootLegacy
= TRUE
;
464 DeviceType
= (UINT16
) Index
;
465 BbsDevicePathNode
.Header
.Type
= BBS_DEVICE_PATH
;
466 BbsDevicePathNode
.Header
.SubType
= BBS_BBS_DP
;
467 SetDevicePathNodeLength (
468 &BbsDevicePathNode
.Header
,
469 sizeof (BBS_BBS_DEVICE_PATH
)
471 BbsDevicePathNode
.DeviceType
= DeviceType
;
472 BbsDevicePathNode
.StatusFlag
= 0;
473 BbsDevicePathNode
.String
[0] = 0;
474 DevicePath
= AppendDevicePathNode (
476 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevicePathNode
479 FileContext
->DevicePath
= DevicePath
;
480 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
482 TempStr
= MenuEntry
->HelpString
;
483 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
484 ASSERT (MenuEntry
->DisplayString
!= NULL
);
486 MenuEntry
->DisplayString
,
491 MenuEntry
->OptionNumber
= OptionNumber
;
493 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
497 // Remember how many file system options are here
499 FsOptionMenu
.MenuNumber
= OptionNumber
;
504 Free resources allocated in Allocate Rountine
506 @param FreeMenu Menu to be freed
513 BM_MENU_OPTION
*FreeMenu
516 BM_MENU_ENTRY
*MenuEntry
;
517 while (!IsListEmpty (&FreeMenu
->Head
)) {
519 FreeMenu
->Head
.ForwardLink
,
522 BM_MENU_ENTRY_SIGNATURE
524 RemoveEntryList (&MenuEntry
->Link
);
525 BOpt_DestroyMenuEntry (MenuEntry
);
530 Find files under current directory
531 All files and sub-directories in current directory
532 will be stored in DirectoryMenu for future use.
534 @param FileOption Pointer for Dir to explore.
536 @retval TRUE Get files from current dir successfully.
537 @retval FALSE Can't get files from current dir.
542 IN BMM_CALLBACK_DATA
*CallbackData
,
543 IN BM_MENU_ENTRY
*MenuEntry
546 EFI_FILE_HANDLE NewDir
;
548 EFI_FILE_INFO
*DirInfo
;
551 BM_MENU_ENTRY
*NewMenuEntry
;
552 BM_FILE_CONTEXT
*FileContext
;
553 BM_FILE_CONTEXT
*NewFileContext
;
558 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
559 Dir
= FileContext
->FHandle
;
562 // Open current directory to get files from it
567 FileContext
->FileName
,
571 if (!FileContext
->IsRoot
) {
575 if (EFI_ERROR (Status
)) {
579 DirInfo
= EfiLibFileInfo (NewDir
);
580 if (DirInfo
== NULL
) {
581 return EFI_NOT_FOUND
;
584 if (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
585 return EFI_INVALID_PARAMETER
;
588 FileContext
->DevicePath
= FileDevicePath (
590 FileContext
->FileName
593 DirBufferSize
= sizeof (EFI_FILE_INFO
) + 1024;
594 DirInfo
= AllocateZeroPool (DirBufferSize
);
595 if (DirInfo
== NULL
) {
596 return EFI_OUT_OF_RESOURCES
;
599 // Get all files in current directory
600 // Pass 1 to get Directories
601 // Pass 2 to get files that are EFI images
603 for (Pass
= 1; Pass
<= 2; Pass
++) {
604 NewDir
->SetPosition (NewDir
, 0);
606 BufferSize
= DirBufferSize
;
607 Status
= NewDir
->Read (NewDir
, &BufferSize
, DirInfo
);
608 if (EFI_ERROR (Status
) || BufferSize
== 0) {
612 if ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
&& Pass
== 2) ||
613 (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) && Pass
== 1)
616 // Pass 1 is for Directories
617 // Pass 2 is for file names
622 if (!(BOpt_IsEfiImageName (DirInfo
->FileName
) || DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
624 // Slip file unless it is a directory entry or a .EFI file
629 NewMenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
630 if (NULL
== NewMenuEntry
) {
631 return EFI_OUT_OF_RESOURCES
;
634 NewFileContext
= (BM_FILE_CONTEXT
*) NewMenuEntry
->VariableContext
;
635 NewFileContext
->Handle
= FileContext
->Handle
;
636 NewFileContext
->FileName
= BOpt_AppendFileName (
637 FileContext
->FileName
,
640 NewFileContext
->FHandle
= NewDir
;
641 NewFileContext
->DevicePath
= FileDevicePath (
642 NewFileContext
->Handle
,
643 NewFileContext
->FileName
645 NewMenuEntry
->HelpString
= NULL
;
647 MenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
649 FileOptionStrDepository
652 NewFileContext
->IsDir
= (BOOLEAN
) ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
);
654 if (NewFileContext
->IsDir
) {
655 BufferSize
= StrLen (DirInfo
->FileName
) * 2 + 6;
656 NewMenuEntry
->DisplayString
= AllocateZeroPool (BufferSize
);
659 NewMenuEntry
->DisplayString
,
666 NewMenuEntry
->DisplayString
= EfiStrDuplicate (DirInfo
->FileName
);
669 NewFileContext
->IsRoot
= FALSE
;
670 NewFileContext
->IsLoadFile
= FALSE
;
671 NewFileContext
->IsRemovableMedia
= FALSE
;
673 NewMenuEntry
->OptionNumber
= OptionNumber
;
675 InsertTailList (&DirectoryMenu
.Head
, &NewMenuEntry
->Link
);
679 DirectoryMenu
.MenuNumber
= OptionNumber
;
680 SafeFreePool (DirInfo
);
685 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
689 @retval EFI_SUCCESS The function complete successfully.
690 @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.
694 BOpt_GetLegacyOptions (
698 BM_MENU_ENTRY
*NewMenuEntry
;
699 BM_LEGACY_DEVICE_CONTEXT
*NewLegacyDevContext
;
701 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
707 CHAR16 DescString
[100];
720 // Initialize Bbs Table Context from BBS info data
722 InitializeListHead (&LegacyFDMenu
.Head
);
723 InitializeListHead (&LegacyHDMenu
.Head
);
724 InitializeListHead (&LegacyCDMenu
.Head
);
725 InitializeListHead (&LegacyNETMenu
.Head
);
726 InitializeListHead (&LegacyBEVMenu
.Head
);
728 Status
= gBS
->LocateProtocol (
729 &gEfiLegacyBiosProtocolGuid
,
731 (VOID
**) &LegacyBios
733 if (!EFI_ERROR (Status
)) {
734 Status
= LegacyBios
->GetBbsInfo (
741 if (EFI_ERROR (Status
)) {
752 for (Index
= 0; Index
< BbsCount
; Index
++) {
753 if ((BBS_IGNORE_ENTRY
== BbsTable
[Index
].BootPriority
) ||
754 (BBS_DO_NOT_BOOT_FROM
== BbsTable
[Index
].BootPriority
)
759 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT
);
760 if (NULL
== NewMenuEntry
) {
764 NewLegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) NewMenuEntry
->VariableContext
;
765 NewLegacyDevContext
->BbsTable
= &BbsTable
[Index
];
766 NewLegacyDevContext
->Index
= Index
;
767 NewLegacyDevContext
->BbsCount
= BbsCount
;
768 BdsBuildLegacyDevNameString (
774 NewLegacyDevContext
->Description
= AllocateZeroPool (StrSize (DescString
));
775 if (NULL
== NewLegacyDevContext
->Description
) {
779 CopyMem (NewLegacyDevContext
->Description
, DescString
, StrSize (DescString
));
780 NewMenuEntry
->DisplayString
= NewLegacyDevContext
->Description
;
781 NewMenuEntry
->HelpString
= NULL
;
783 switch (BbsTable
[Index
].DeviceType
) {
785 InsertTailList (&LegacyFDMenu
.Head
, &NewMenuEntry
->Link
);
790 InsertTailList (&LegacyHDMenu
.Head
, &NewMenuEntry
->Link
);
795 InsertTailList (&LegacyCDMenu
.Head
, &NewMenuEntry
->Link
);
799 case BBS_EMBED_NETWORK
:
800 InsertTailList (&LegacyNETMenu
.Head
, &NewMenuEntry
->Link
);
805 InsertTailList (&LegacyBEVMenu
.Head
, &NewMenuEntry
->Link
);
811 if (Index
!= BbsCount
) {
812 BOpt_FreeLegacyOptions ();
813 return EFI_OUT_OF_RESOURCES
;
816 LegacyFDMenu
.MenuNumber
= FDNum
;
817 LegacyHDMenu
.MenuNumber
= HDNum
;
818 LegacyCDMenu
.MenuNumber
= CDNum
;
819 LegacyNETMenu
.MenuNumber
= NETNum
;
820 LegacyBEVMenu
.MenuNumber
= BEVNum
;
825 Free out resouce allocated from Legacy Boot Options.
833 BOpt_FreeLegacyOptions (
837 BOpt_FreeMenu (&LegacyFDMenu
);
838 BOpt_FreeMenu (&LegacyHDMenu
);
839 BOpt_FreeMenu (&LegacyCDMenu
);
840 BOpt_FreeMenu (&LegacyNETMenu
);
841 BOpt_FreeMenu (&LegacyBEVMenu
);
846 Build the BootOptionMenu according to BootOrder Variable.
847 This Routine will access the Boot#### to get EFI_LOAD_OPTION.
851 @return The number of the Var Boot####.
855 BOpt_GetBootOptions (
856 IN BMM_CALLBACK_DATA
*CallbackData
860 UINT16 BootString
[10];
861 UINT8
*LoadOptionFromVar
;
863 UINTN BootOptionSize
;
864 BOOLEAN BootNextFlag
;
865 UINT16
*BootOrderList
;
866 UINTN BootOrderListSize
;
869 BM_MENU_ENTRY
*NewMenuEntry
;
870 BM_LOAD_CONTEXT
*NewLoadContext
;
871 UINT8
*LoadOptionPtr
;
873 UINTN OptionalDataSize
;
874 UINT8
*LoadOptionEnd
;
875 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
880 BootOrderListSize
= 0;
882 BootOrderList
= NULL
;
884 LoadOptionFromVar
= NULL
;
885 BOpt_FreeMenu (&BootOptionMenu
);
886 InitializeListHead (&BootOptionMenu
.Head
);
889 // Get the BootOrder from the Var
891 BootOrderList
= BdsLibGetVariableAndSize (
893 &gEfiGlobalVariableGuid
,
898 // Get the BootNext from the Var
900 BootNext
= BdsLibGetVariableAndSize (
902 &gEfiGlobalVariableGuid
,
906 if (BootNext
!= NULL
) {
907 if (BootNextSize
!= sizeof (UINT16
)) {
908 SafeFreePool (BootNext
);
913 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
914 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", BootOrderList
[Index
]);
916 // Get all loadoptions from the VAR
918 LoadOptionFromVar
= BdsLibGetVariableAndSize (
920 &gEfiGlobalVariableGuid
,
923 if (LoadOptionFromVar
== NULL
) {
927 LoadOption
= AllocateZeroPool (BootOptionSize
);
928 if (LoadOption
== NULL
) {
932 CopyMem (LoadOption
, LoadOptionFromVar
, BootOptionSize
);
933 SafeFreePool (LoadOptionFromVar
);
935 if (BootNext
!= NULL
) {
936 BootNextFlag
= (BOOLEAN
) (*BootNext
== BootOrderList
[Index
]);
938 BootNextFlag
= FALSE
;
941 if (0 == (*((UINT32
*) LoadOption
) & LOAD_OPTION_ACTIVE
)) {
942 SafeFreePool (LoadOption
);
946 // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
947 // the buffer allocated already should be freed before returning.
949 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
950 if (NULL
== NewMenuEntry
) {
951 return EFI_OUT_OF_RESOURCES
;
954 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
956 LoadOptionPtr
= LoadOption
;
957 LoadOptionEnd
= LoadOption
+ BootOptionSize
;
959 NewMenuEntry
->OptionNumber
= BootOrderList
[Index
];
960 NewLoadContext
->LoadOptionModified
= FALSE
;
961 NewLoadContext
->Deleted
= FALSE
;
962 NewLoadContext
->IsBootNext
= BootNextFlag
;
965 // Is a Legacy Device?
967 Ptr
= (UINT8
*) LoadOption
;
970 // Attribute = *(UINT32 *)Ptr;
972 Ptr
+= sizeof (UINT32
);
975 // FilePathSize = *(UINT16 *)Ptr;
977 Ptr
+= sizeof (UINT16
);
980 // Description = (CHAR16 *)Ptr;
982 Ptr
+= StrSize ((CHAR16
*) Ptr
);
985 // Now Ptr point to Device Path
987 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
988 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
989 NewLoadContext
->IsLegacy
= TRUE
;
991 NewLoadContext
->IsLegacy
= FALSE
;
994 // LoadOption is a pointer type of UINT8
995 // for easy use with following LOAD_OPTION
996 // embedded in this struct
998 NewLoadContext
->LoadOption
= LoadOption
;
999 NewLoadContext
->LoadOptionSize
= BootOptionSize
;
1001 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1002 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1004 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1006 LoadOptionPtr
+= sizeof (UINT32
);
1008 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1009 LoadOptionPtr
+= sizeof (UINT16
);
1011 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1012 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1013 ASSERT (NewLoadContext
->Description
!= NULL
);
1015 NewLoadContext
->Description
,
1016 (UINT16
*) LoadOptionPtr
,
1019 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1021 LoadOptionPtr
+= StringSize
;
1023 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1024 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1026 NewLoadContext
->FilePathList
,
1027 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1028 NewLoadContext
->FilePathListLength
1031 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1032 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1034 BootOptionStrDepository
1036 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1038 BootOptionHelpStrDepository
1040 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1042 if (LoadOptionPtr
< LoadOptionEnd
) {
1043 OptionalDataSize
= BootOptionSize
-
1047 NewLoadContext
->FilePathListLength
;
1049 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1050 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1052 NewLoadContext
->OptionalData
,
1057 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1060 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
1064 SafeFreePool (BootNext
);
1065 SafeFreePool (BootOrderList
);
1066 BootOptionMenu
.MenuNumber
= MenuCount
;
1072 Append file name to existing file name.
1074 @param Str1 The existing file name
1075 @param Str2 The file name to be appended
1077 @return Allocate a new string to hold the appended result.
1078 Caller is responsible to free the returned string.
1082 BOpt_AppendFileName (
1093 Size1
= StrSize (Str1
);
1094 Size2
= StrSize (Str2
);
1095 Str
= AllocateZeroPool (Size1
+ Size2
+ sizeof (CHAR16
));
1096 ASSERT (Str
!= NULL
);
1099 if (!((*Str
== '\\') && (*(Str
+ 1) == 0))) {
1100 StrCat (Str
, L
"\\");
1108 if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '.' && *(Ptr
+ 3) == L
'\\') {
1110 // Convert "\Name\..\" to "\"
1111 // DO NOT convert the .. if it is at the end of the string. This will
1112 // break the .. behavior in changing directories.
1114 StrCpy (LastSlash
, Ptr
+ 3);
1116 } else if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '\\') {
1118 // Convert a "\.\" to a "\"
1120 StrCpy (Ptr
, Ptr
+ 2);
1122 } else if (*Ptr
== '\\') {
1134 Check whether current FileName point to a valid
1137 @param FileName File need to be checked.
1139 @retval TRUE Is Efi Image
1140 @retval FALSE Not a valid Efi Image
1144 BOpt_IsEfiImageName (
1149 // Search for ".efi" extension
1151 while (*FileName
!= L
'\0') {
1152 if (FileName
[0] == '.') {
1153 if (FileName
[1] == 'e' || FileName
[1] == 'E') {
1154 if (FileName
[2] == 'f' || FileName
[2] == 'F') {
1155 if (FileName
[3] == 'i' || FileName
[3] == 'I') {
1157 } else if (FileName
[3] == 0x0000) {
1160 } else if (FileName
[2] == 0x0000) {
1163 } else if (FileName
[1] == 0x0000) {
1176 Check whether current FileName point to a valid Efi Application
1178 @param Dir Pointer to current Directory
1179 @param FileName Pointer to current File name.
1181 @retval TRUE Is a valid Efi Application
1182 @retval FALSE not a valid Efi Application
1187 IN EFI_FILE_HANDLE Dir
,
1192 EFI_IMAGE_DOS_HEADER DosHdr
;
1194 EFI_FILE_HANDLE File
;
1196 EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr
;
1198 Status
= Dir
->Open (Dir
, &File
, FileName
, EFI_FILE_MODE_READ
, 0);
1200 if (EFI_ERROR (Status
)) {
1204 BufferSize
= sizeof (EFI_IMAGE_DOS_HEADER
);
1205 File
->Read (File
, &BufferSize
, &DosHdr
);
1206 if (DosHdr
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1211 File
->SetPosition (File
, DosHdr
.e_lfanew
);
1212 BufferSize
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
1213 File
->Read (File
, &BufferSize
, &PeHdr
);
1214 if (PeHdr
.Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1219 // Determine PE type and read subsytem
1221 if (PeHdr
.Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1222 Subsystem
= PeHdr
.Pe32
.OptionalHeader
.Subsystem
;
1223 } else if (PeHdr
.Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1224 Subsystem
= PeHdr
.Pe32Plus
.OptionalHeader
.Subsystem
;
1229 if (Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1240 Find drivers that will be added as Driver#### variables from handles
1241 in current system environment
1242 All valid handles in the system except those consume SimpleFs, LoadFile
1243 are stored in DriverMenu for future use.
1247 @retval EFI_SUCCESS The function complets successfully.
1248 @return Other value if failed to build the DriverMenu.
1256 UINTN NoDevicePathHandles
;
1257 EFI_HANDLE
*DevicePathHandle
;
1260 BM_MENU_ENTRY
*NewMenuEntry
;
1261 BM_HANDLE_CONTEXT
*NewHandleContext
;
1262 EFI_HANDLE CurHandle
;
1264 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFs
;
1265 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1270 InitializeListHead (&DriverMenu
.Head
);
1273 // At first, get all handles that support Device Path
1274 // protocol which is the basic requirement for
1277 Status
= gBS
->LocateHandleBuffer (
1279 &gEfiDevicePathProtocolGuid
,
1281 &NoDevicePathHandles
,
1284 if (EFI_ERROR (Status
)) {
1289 for (Index
= 0; Index
< NoDevicePathHandles
; Index
++) {
1290 CurHandle
= DevicePathHandle
[Index
];
1292 Status
= gBS
->HandleProtocol (
1294 &gEfiSimpleFileSystemProtocolGuid
,
1297 if (Status
== EFI_SUCCESS
) {
1301 Status
= gBS
->HandleProtocol (
1303 &gEfiLoadFileProtocolGuid
,
1306 if (Status
== EFI_SUCCESS
) {
1310 NewMenuEntry
= BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT
);
1311 if (NULL
== NewMenuEntry
) {
1312 SafeFreePool (DevicePathHandle
);
1313 return EFI_OUT_OF_RESOURCES
;
1316 NewHandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1317 NewHandleContext
->Handle
= CurHandle
;
1318 NewHandleContext
->DevicePath
= DevicePathFromHandle (CurHandle
);
1319 NewMenuEntry
->DisplayString
= DevicePathToStr (NewHandleContext
->DevicePath
);
1320 NewMenuEntry
->HelpString
= NULL
;
1321 NewMenuEntry
->OptionNumber
= OptionNumber
;
1323 InsertTailList (&DriverMenu
.Head
, &NewMenuEntry
->Link
);
1326 SafeFreePool (DevicePathHandle
);
1328 DriverMenu
.MenuNumber
= OptionNumber
;
1334 Get the Option Number that has not been allocated for use.
1338 @return The available Option Number.
1342 BOpt_GetBootOptionNumber (
1346 BM_MENU_ENTRY
*NewMenuEntry
;
1347 UINT16
*BootOrderList
;
1348 UINTN BootOrderListSize
;
1353 CHAR16 StrTemp
[100];
1354 UINT16
*OptionBuffer
;
1357 BootOrderListSize
= 0;
1358 BootOrderList
= NULL
;
1360 BootOrderList
= BdsLibGetVariableAndSize (
1362 &gEfiGlobalVariableGuid
,
1365 if (BootOrderList
!= NULL
) {
1367 // already have Boot####
1369 // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
1371 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
1373 for (Index2
= 0; Index2
< BootOptionMenu
.MenuNumber
; Index2
++) {
1374 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index2
);
1375 if (Index
== NewMenuEntry
->OptionNumber
) {
1382 UnicodeSPrint (StrTemp
, 100, L
"Boot%04x", Index
);
1383 DEBUG((DEBUG_ERROR
,"INdex= %s\n", StrTemp
));
1384 OptionBuffer
= BdsLibGetVariableAndSize (
1386 &gEfiGlobalVariableGuid
,
1389 if (NULL
== OptionBuffer
) {
1397 Number
= (UINT16
) Index
;
1410 Get the Option Number that is not in use.
1414 @return The unused Option Number.
1418 BOpt_GetDriverOptionNumber (
1422 BM_MENU_ENTRY
*NewMenuEntry
;
1423 UINT16
*DriverOrderList
;
1424 UINTN DriverOrderListSize
;
1430 DriverOrderListSize
= 0;
1431 DriverOrderList
= NULL
;
1433 DriverOrderList
= BdsLibGetVariableAndSize (
1435 &gEfiGlobalVariableGuid
,
1436 &DriverOrderListSize
1438 if (DriverOrderList
!= NULL
) {
1440 // already have Driver####
1442 // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
1444 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1446 for (Index2
= 0; Index2
< DriverOptionMenu
.MenuNumber
; Index2
++) {
1447 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index2
);
1448 if (Index
== NewMenuEntry
->OptionNumber
) {
1461 Number
= (UINT16
) Index
;
1474 Build up all DriverOptionMenu
1476 @param CallbackData The BMM context data.
1478 @return EFI_SUCESS The functin completes successfully.
1479 @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
1484 BOpt_GetDriverOptions (
1485 IN BMM_CALLBACK_DATA
*CallbackData
1489 UINT16 DriverString
[12];
1490 UINT8
*LoadOptionFromVar
;
1492 UINTN DriverOptionSize
;
1494 UINT16
*DriverOrderList
;
1495 UINTN DriverOrderListSize
;
1496 BM_MENU_ENTRY
*NewMenuEntry
;
1497 BM_LOAD_CONTEXT
*NewLoadContext
;
1498 UINT8
*LoadOptionPtr
;
1500 UINTN OptionalDataSize
;
1501 UINT8
*LoadOptionEnd
;
1503 DriverOrderListSize
= 0;
1504 DriverOrderList
= NULL
;
1505 DriverOptionSize
= 0;
1506 LoadOptionFromVar
= NULL
;
1507 BOpt_FreeMenu (&DriverOptionMenu
);
1508 InitializeListHead (&DriverOptionMenu
.Head
);
1510 // Get the DriverOrder from the Var
1512 DriverOrderList
= BdsLibGetVariableAndSize (
1514 &gEfiGlobalVariableGuid
,
1515 &DriverOrderListSize
1518 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1521 sizeof (DriverString
),
1523 DriverOrderList
[Index
]
1526 // Get all loadoptions from the VAR
1528 LoadOptionFromVar
= BdsLibGetVariableAndSize (
1530 &gEfiGlobalVariableGuid
,
1533 if (LoadOptionFromVar
== NULL
) {
1537 LoadOption
= AllocateZeroPool (DriverOptionSize
);
1538 if (LoadOption
== NULL
) {
1542 CopyMem (LoadOption
, LoadOptionFromVar
, DriverOptionSize
);
1543 SafeFreePool (LoadOptionFromVar
);
1545 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
1546 if (NULL
== NewMenuEntry
) {
1547 return EFI_OUT_OF_RESOURCES
;
1550 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1551 LoadOptionPtr
= LoadOption
;
1552 LoadOptionEnd
= LoadOption
+ DriverOptionSize
;
1553 NewMenuEntry
->OptionNumber
= DriverOrderList
[Index
];
1554 NewLoadContext
->LoadOptionModified
= FALSE
;
1555 NewLoadContext
->Deleted
= FALSE
;
1556 NewLoadContext
->IsLegacy
= FALSE
;
1559 // LoadOption is a pointer type of UINT8
1560 // for easy use with following LOAD_OPTION
1561 // embedded in this struct
1563 NewLoadContext
->LoadOption
= LoadOption
;
1564 NewLoadContext
->LoadOptionSize
= DriverOptionSize
;
1566 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1567 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1569 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1571 LoadOptionPtr
+= sizeof (UINT32
);
1573 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1574 LoadOptionPtr
+= sizeof (UINT16
);
1576 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1577 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1578 ASSERT (NewLoadContext
->Description
!= NULL
);
1580 NewLoadContext
->Description
,
1581 (UINT16
*) LoadOptionPtr
,
1584 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1586 LoadOptionPtr
+= StringSize
;
1588 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1589 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1591 NewLoadContext
->FilePathList
,
1592 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1593 NewLoadContext
->FilePathListLength
1596 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1597 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1599 DriverOptionStrDepository
1601 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1603 DriverOptionHelpStrDepository
1605 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1607 if (LoadOptionPtr
< LoadOptionEnd
) {
1608 OptionalDataSize
= DriverOptionSize
-
1612 NewLoadContext
->FilePathListLength
;
1614 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1615 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1617 NewLoadContext
->OptionalData
,
1622 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1625 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
1629 SafeFreePool (DriverOrderList
);
1630 DriverOptionMenu
.MenuNumber
= Index
;