2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 Provide boot option support for Application "BootMaint"
19 Include file system navigation, system handle selection
21 Boot option manipulation
27 #include "bootmaint.h"
28 #include "BBSsupport.h"
31 BOpt_CreateMenuEntry (
37 Create Menu Entry for future use, make all types together
38 in order to reduce code size
41 MenuType Use this parameter to identify current
45 NULL Cannot allocate memory for current menu
47 Others A valid pointer pointing to the allocated
48 memory pool for current menu entry
52 BM_MENU_ENTRY
*MenuEntry
;
56 case BM_LOAD_CONTEXT_SELECT
:
57 ContextSize
= sizeof (BM_LOAD_CONTEXT
);
60 case BM_FILE_CONTEXT_SELECT
:
61 ContextSize
= sizeof (BM_FILE_CONTEXT
);
64 case BM_CONSOLE_CONTEXT_SELECT
:
65 ContextSize
= sizeof (BM_CONSOLE_CONTEXT
);
68 case BM_TERMINAL_CONTEXT_SELECT
:
69 ContextSize
= sizeof (BM_TERMINAL_CONTEXT
);
72 case BM_HANDLE_CONTEXT_SELECT
:
73 ContextSize
= sizeof (BM_HANDLE_CONTEXT
);
76 case BM_LEGACY_DEV_CONTEXT_SELECT
:
77 ContextSize
= sizeof (BM_LEGACY_DEVICE_CONTEXT
);
86 if (0 == ContextSize
) {
90 MenuEntry
= AllocateZeroPool (sizeof (BM_MENU_ENTRY
));
91 if (NULL
== MenuEntry
) {
95 MenuEntry
->VariableContext
= AllocateZeroPool (ContextSize
);
96 if (NULL
== MenuEntry
->VariableContext
) {
97 SafeFreePool (MenuEntry
);
102 MenuEntry
->Signature
= BM_MENU_ENTRY_SIGNATURE
;
103 MenuEntry
->ContextSelection
= MenuType
;
108 BOpt_DestroyMenuEntry (
109 BM_MENU_ENTRY
*MenuEntry
112 Routine Description :
113 Destroy the menu entry passed in
116 The menu entry need to be destroyed
123 BM_LOAD_CONTEXT
*LoadContext
;
124 BM_FILE_CONTEXT
*FileContext
;
125 BM_CONSOLE_CONTEXT
*ConsoleContext
;
126 BM_TERMINAL_CONTEXT
*TerminalContext
;
127 BM_HANDLE_CONTEXT
*HandleContext
;
128 BM_LEGACY_DEVICE_CONTEXT
*LegacyDevContext
;
131 // Select by the type in Menu entry for current context type
133 switch (MenuEntry
->ContextSelection
) {
134 case BM_LOAD_CONTEXT_SELECT
:
135 LoadContext
= (BM_LOAD_CONTEXT
*) MenuEntry
->VariableContext
;
136 SafeFreePool (LoadContext
->FilePathList
);
137 SafeFreePool (LoadContext
->LoadOption
);
138 SafeFreePool (LoadContext
->OptionalData
);
139 SafeFreePool (LoadContext
);
142 case BM_FILE_CONTEXT_SELECT
:
143 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
145 if (!FileContext
->IsRoot
) {
146 SafeFreePool (FileContext
->DevicePath
);
148 if (FileContext
->FHandle
!= NULL
) {
149 FileContext
->FHandle
->Close (FileContext
->FHandle
);
153 SafeFreePool (FileContext
->FileName
);
154 SafeFreePool (FileContext
->Info
);
155 SafeFreePool (FileContext
);
158 case BM_CONSOLE_CONTEXT_SELECT
:
159 ConsoleContext
= (BM_CONSOLE_CONTEXT
*) MenuEntry
->VariableContext
;
160 SafeFreePool (ConsoleContext
->DevicePath
);
161 SafeFreePool (ConsoleContext
);
164 case BM_TERMINAL_CONTEXT_SELECT
:
165 TerminalContext
= (BM_TERMINAL_CONTEXT
*) MenuEntry
->VariableContext
;
166 SafeFreePool (TerminalContext
->DevicePath
);
167 SafeFreePool (TerminalContext
);
170 case BM_HANDLE_CONTEXT_SELECT
:
171 HandleContext
= (BM_HANDLE_CONTEXT
*) MenuEntry
->VariableContext
;
172 SafeFreePool (HandleContext
);
175 case BM_LEGACY_DEV_CONTEXT_SELECT
:
176 LegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) MenuEntry
->VariableContext
;
177 SafeFreePool (LegacyDevContext
);
183 SafeFreePool (MenuEntry
->DisplayString
);
184 if (NULL
!= MenuEntry
->HelpString
) {
185 SafeFreePool (MenuEntry
->HelpString
);
188 SafeFreePool (MenuEntry
);
193 BM_MENU_OPTION
*MenuOption
,
197 Rountine Description :
198 Use this routine to get one particular menu entry in specified
202 MenuOption The menu that we will search
204 MenuNumber The menunubmer that we want
207 The desired menu entry
211 BM_MENU_ENTRY
*NewMenuEntry
;
215 if (MenuNumber
>= MenuOption
->MenuNumber
) {
219 List
= MenuOption
->Head
.ForwardLink
;
220 for (Index
= 0; Index
< MenuNumber
; Index
++) {
221 List
= List
->ForwardLink
;
224 NewMenuEntry
= CR (List
, BM_MENU_ENTRY
, Link
, BM_MENU_ENTRY_SIGNATURE
);
230 BOpt_FindFileSystem (
231 IN BMM_CALLBACK_DATA
*CallbackData
236 Find file systems for current Extensible Firmware
237 Including Handles that support Simple File System
238 protocol, Load File protocol.
240 Building up the FileSystem Menu for user selection
241 All file system will be stored in FsOptionMenu
245 CallbackData - BMM context data
248 EFI_SUCCESS - Success find the file system
249 EFI_OUT_OF_RESOURCES - Can not create menu entry
253 UINTN NoSimpleFsHandles
;
254 UINTN NoLoadFileHandles
;
255 EFI_HANDLE
*SimpleFsHandle
;
256 EFI_HANDLE
*LoadFileHandle
;
258 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
261 BM_MENU_ENTRY
*MenuEntry
;
262 BM_FILE_CONTEXT
*FileContext
;
265 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
267 BBS_BBS_DEVICE_PATH BbsDevicePathNode
;
268 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
269 BOOLEAN RemovableMedia
;
272 NoSimpleFsHandles
= 0;
273 NoLoadFileHandles
= 0;
275 InitializeListHead (&FsOptionMenu
.Head
);
278 // Locate Handles that support Simple File System protocol
280 Status
= gBS
->LocateHandleBuffer (
282 &gEfiSimpleFileSystemProtocolGuid
,
287 if (!EFI_ERROR (Status
)) {
289 // Find all the instances of the File System prototocol
291 for (Index
= 0; Index
< NoSimpleFsHandles
; Index
++) {
292 Status
= gBS
->HandleProtocol (
293 SimpleFsHandle
[Index
],
294 &gEfiBlockIoProtocolGuid
,
297 if (EFI_ERROR (Status
)) {
299 // If no block IO exists assume it's NOT a removable media
301 RemovableMedia
= FALSE
;
304 // If block IO exists check to see if it's remobable media
306 RemovableMedia
= BlkIo
->Media
->RemovableMedia
;
310 // Allocate pool for this load option
312 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
313 if (NULL
== MenuEntry
) {
314 SafeFreePool (SimpleFsHandle
);
315 return EFI_OUT_OF_RESOURCES
;
318 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
320 FileContext
->Handle
= SimpleFsHandle
[Index
];
321 MenuEntry
->OptionNumber
= Index
;
322 FileContext
->FHandle
= EfiLibOpenRoot (FileContext
->Handle
);
323 if (!FileContext
->FHandle
) {
324 BOpt_DestroyMenuEntry (MenuEntry
);
328 MenuEntry
->HelpString
= DevicePathToStr (DevicePathFromHandle (FileContext
->Handle
));
329 FileContext
->Info
= EfiLibFileSystemVolumeLabelInfo (FileContext
->FHandle
);
330 FileContext
->FileName
= EfiStrDuplicate (L
"\\");
331 FileContext
->DevicePath
= FileDevicePath (
333 FileContext
->FileName
335 FileContext
->IsDir
= TRUE
;
336 FileContext
->IsRoot
= TRUE
;
337 FileContext
->IsRemovableMedia
= FALSE
;
338 FileContext
->IsLoadFile
= FALSE
;
341 // Get current file system's Volume Label
343 if (FileContext
->Info
== NULL
) {
344 VolumeLabel
= L
"NO FILE SYSTEM INFO";
346 if (FileContext
->Info
->VolumeLabel
== NULL
) {
347 VolumeLabel
= L
"NULL VOLUME LABEL";
349 VolumeLabel
= FileContext
->Info
->VolumeLabel
;
350 if (*VolumeLabel
== 0x0000) {
351 VolumeLabel
= L
"NO VOLUME LABEL";
356 TempStr
= MenuEntry
->HelpString
;
357 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
358 ASSERT (MenuEntry
->DisplayString
!= NULL
);
360 MenuEntry
->DisplayString
,
367 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
371 if (NoSimpleFsHandles
!= 0) {
372 SafeFreePool (SimpleFsHandle
);
375 // Searching for handles that support Load File protocol
377 Status
= gBS
->LocateHandleBuffer (
379 &gEfiLoadFileProtocolGuid
,
385 if (!EFI_ERROR (Status
)) {
386 for (Index
= 0; Index
< NoLoadFileHandles
; Index
++) {
387 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
388 if (NULL
== MenuEntry
) {
389 SafeFreePool (LoadFileHandle
);
390 return EFI_OUT_OF_RESOURCES
;
393 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
394 FileContext
->IsRemovableMedia
= FALSE
;
395 FileContext
->IsLoadFile
= TRUE
;
396 FileContext
->Handle
= LoadFileHandle
[Index
];
397 FileContext
->IsRoot
= TRUE
;
399 FileContext
->DevicePath
= DevicePathFromHandle (FileContext
->Handle
);
401 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
403 TempStr
= MenuEntry
->HelpString
;
404 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
405 ASSERT (MenuEntry
->DisplayString
!= NULL
);
407 MenuEntry
->DisplayString
,
413 MenuEntry
->OptionNumber
= OptionNumber
;
415 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
419 if (NoLoadFileHandles
!= 0) {
420 SafeFreePool (LoadFileHandle
);
424 // Add Legacy Boot Option Support Here
426 Status
= gBS
->LocateProtocol (
427 &gEfiLegacyBiosProtocolGuid
,
431 if (!EFI_ERROR (Status
)) {
433 for (Index
= BBS_TYPE_FLOPPY
; Index
<= BBS_TYPE_EMBEDDED_NETWORK
; Index
++) {
434 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
435 if (NULL
== MenuEntry
) {
436 return EFI_OUT_OF_RESOURCES
;
439 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
441 FileContext
->IsRemovableMedia
= FALSE
;
442 FileContext
->IsLoadFile
= TRUE
;
443 FileContext
->IsBootLegacy
= TRUE
;
444 DeviceType
= (UINT16
) Index
;
445 BbsDevicePathNode
.Header
.Type
= BBS_DEVICE_PATH
;
446 BbsDevicePathNode
.Header
.SubType
= BBS_BBS_DP
;
447 SetDevicePathNodeLength (
448 &BbsDevicePathNode
.Header
,
449 sizeof (BBS_BBS_DEVICE_PATH
)
451 BbsDevicePathNode
.DeviceType
= DeviceType
;
452 BbsDevicePathNode
.StatusFlag
= 0;
453 BbsDevicePathNode
.String
[0] = 0;
454 DevicePath
= AppendDevicePathNode (
456 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevicePathNode
459 FileContext
->DevicePath
= DevicePath
;
460 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
462 TempStr
= MenuEntry
->HelpString
;
463 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
464 ASSERT (MenuEntry
->DisplayString
!= NULL
);
466 MenuEntry
->DisplayString
,
471 MenuEntry
->OptionNumber
= OptionNumber
;
473 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
477 // Remember how many file system options are here
479 FsOptionMenu
.MenuNumber
= OptionNumber
;
485 BM_MENU_OPTION
*FreeMenu
490 Free resources allocated in Allocate Rountine
493 FreeMenu Menu to be freed
500 BM_MENU_ENTRY
*MenuEntry
;
501 while (!IsListEmpty (&FreeMenu
->Head
)) {
503 FreeMenu
->Head
.ForwardLink
,
506 BM_MENU_ENTRY_SIGNATURE
508 RemoveEntryList (&MenuEntry
->Link
);
509 BOpt_DestroyMenuEntry (MenuEntry
);
515 IN BMM_CALLBACK_DATA
*CallbackData
,
516 IN BM_MENU_ENTRY
*MenuEntry
521 Find files under current directory
522 All files and sub-directories in current directory
523 will be stored in DirectoryMenu for future use.
526 FileOption -- Pointer for Dir to explore
529 TRUE -- Get files from current dir successfully
530 FALSE -- Can't get files from current dir
534 EFI_FILE_HANDLE NewDir
;
536 EFI_FILE_INFO
*DirInfo
;
539 BM_MENU_ENTRY
*NewMenuEntry
;
540 BM_FILE_CONTEXT
*FileContext
;
541 BM_FILE_CONTEXT
*NewFileContext
;
546 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
547 Dir
= FileContext
->FHandle
;
550 // Open current directory to get files from it
555 FileContext
->FileName
,
559 if (!FileContext
->IsRoot
) {
563 if (EFI_ERROR (Status
)) {
567 DirInfo
= EfiLibFileInfo (NewDir
);
569 return EFI_NOT_FOUND
;
572 if (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
573 return EFI_INVALID_PARAMETER
;
576 FileContext
->DevicePath
= FileDevicePath (
578 FileContext
->FileName
581 DirBufferSize
= sizeof (EFI_FILE_INFO
) + 1024;
582 DirInfo
= AllocateZeroPool (DirBufferSize
);
584 return EFI_OUT_OF_RESOURCES
;
587 // Get all files in current directory
588 // Pass 1 to get Directories
589 // Pass 2 to get files that are EFI images
591 for (Pass
= 1; Pass
<= 2; Pass
++) {
592 NewDir
->SetPosition (NewDir
, 0);
594 BufferSize
= DirBufferSize
;
595 Status
= NewDir
->Read (NewDir
, &BufferSize
, DirInfo
);
596 if (EFI_ERROR (Status
) || BufferSize
== 0) {
600 if ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
&& Pass
== 2) ||
601 (!(DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) && Pass
== 1)
604 // Pass 1 is for Directories
605 // Pass 2 is for file names
610 if (!(BOpt_IsEfiImageName (DirInfo
->FileName
) || DirInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
612 // Slip file unless it is a directory entry or a .EFI file
617 NewMenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
618 if (NULL
== NewMenuEntry
) {
619 return EFI_OUT_OF_RESOURCES
;
622 NewFileContext
= (BM_FILE_CONTEXT
*) NewMenuEntry
->VariableContext
;
623 NewFileContext
->Handle
= FileContext
->Handle
;
624 NewFileContext
->FileName
= BOpt_AppendFileName (
625 FileContext
->FileName
,
628 NewFileContext
->FHandle
= NewDir
;
629 NewFileContext
->DevicePath
= FileDevicePath (
630 NewFileContext
->Handle
,
631 NewFileContext
->FileName
633 NewMenuEntry
->HelpString
= NULL
;
635 MenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
637 FileOptionStrDepository
640 NewFileContext
->IsDir
= (BOOLEAN
) ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
);
642 if (NewFileContext
->IsDir
) {
643 BufferSize
= StrLen (DirInfo
->FileName
) * 2 + 6;
644 NewMenuEntry
->DisplayString
= AllocateZeroPool (BufferSize
);
647 NewMenuEntry
->DisplayString
,
654 NewMenuEntry
->DisplayString
= EfiStrDuplicate (DirInfo
->FileName
);
657 NewFileContext
->IsRoot
= FALSE
;
658 NewFileContext
->IsLoadFile
= FALSE
;
659 NewFileContext
->IsRemovableMedia
= FALSE
;
661 NewMenuEntry
->OptionNumber
= OptionNumber
;
663 InsertTailList (&DirectoryMenu
.Head
, &NewMenuEntry
->Link
);
667 DirectoryMenu
.MenuNumber
= OptionNumber
;
668 SafeFreePool (DirInfo
);
673 BOpt_GetLegacyOptions (
679 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
685 The device info of legacy device.
689 BM_MENU_ENTRY
*NewMenuEntry
;
690 BM_LEGACY_DEVICE_CONTEXT
*NewLegacyDevContext
;
692 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
698 CHAR16 DescString
[100];
711 // Initialize Bbs Table Context from BBS info data
713 InitializeListHead (&LegacyFDMenu
.Head
);
714 InitializeListHead (&LegacyHDMenu
.Head
);
715 InitializeListHead (&LegacyCDMenu
.Head
);
716 InitializeListHead (&LegacyNETMenu
.Head
);
717 InitializeListHead (&LegacyBEVMenu
.Head
);
719 Status
= gBS
->LocateProtocol (
720 &gEfiLegacyBiosProtocolGuid
,
724 if (!EFI_ERROR (Status
)) {
725 Status
= LegacyBios
->GetBbsInfo (
732 if (EFI_ERROR (Status
)) {
743 for (Index
= 0; Index
< BbsCount
; Index
++) {
744 if ((BBS_IGNORE_ENTRY
== BbsTable
[Index
].BootPriority
) ||
745 (BBS_DO_NOT_BOOT_FROM
== BbsTable
[Index
].BootPriority
) ||
746 (BBS_LOWEST_PRIORITY
== BbsTable
[Index
].BootPriority
)
751 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT
);
752 if (NULL
== NewMenuEntry
) {
756 NewLegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) NewMenuEntry
->VariableContext
;
757 NewLegacyDevContext
->BbsTable
= &BbsTable
[Index
];
758 NewLegacyDevContext
->Index
= Index
;
759 NewLegacyDevContext
->BbsCount
= BbsCount
;
760 BdsBuildLegacyDevNameString (
766 NewLegacyDevContext
->Description
= AllocateZeroPool (StrSize (DescString
));
767 if (NULL
== NewLegacyDevContext
->Description
) {
771 CopyMem (NewLegacyDevContext
->Description
, DescString
, StrSize (DescString
));
772 NewMenuEntry
->DisplayString
= NewLegacyDevContext
->Description
;
773 NewMenuEntry
->HelpString
= NULL
;
775 switch (BbsTable
[Index
].DeviceType
) {
777 InsertTailList (&LegacyFDMenu
.Head
, &NewMenuEntry
->Link
);
782 InsertTailList (&LegacyHDMenu
.Head
, &NewMenuEntry
->Link
);
787 InsertTailList (&LegacyCDMenu
.Head
, &NewMenuEntry
->Link
);
791 case BBS_EMBED_NETWORK
:
792 InsertTailList (&LegacyNETMenu
.Head
, &NewMenuEntry
->Link
);
797 InsertTailList (&LegacyBEVMenu
.Head
, &NewMenuEntry
->Link
);
803 if (Index
!= BbsCount
) {
804 BOpt_FreeLegacyOptions ();
805 return EFI_OUT_OF_RESOURCES
;
808 LegacyFDMenu
.MenuNumber
= FDNum
;
809 LegacyHDMenu
.MenuNumber
= HDNum
;
810 LegacyCDMenu
.MenuNumber
= CDNum
;
811 LegacyNETMenu
.MenuNumber
= NETNum
;
812 LegacyBEVMenu
.MenuNumber
= BEVNum
;
817 BOpt_FreeLegacyOptions (
821 BOpt_FreeMenu (&LegacyFDMenu
);
822 BOpt_FreeMenu (&LegacyHDMenu
);
823 BOpt_FreeMenu (&LegacyCDMenu
);
824 BOpt_FreeMenu (&LegacyNETMenu
);
825 BOpt_FreeMenu (&LegacyBEVMenu
);
829 BOpt_GetBootOptions (
830 IN BMM_CALLBACK_DATA
*CallbackData
836 Build the BootOptionMenu according to BootOrder Variable.
837 This Routine will access the Boot#### to get EFI_LOAD_OPTION
843 The number of the Var Boot####
848 UINT16 BootString
[10];
849 UINT8
*LoadOptionFromVar
;
851 UINTN BootOptionSize
;
852 BOOLEAN BootNextFlag
;
853 UINT16
*BootOrderList
;
854 UINTN BootOrderListSize
;
857 BM_MENU_ENTRY
*NewMenuEntry
;
858 BM_LOAD_CONTEXT
*NewLoadContext
;
859 UINT8
*LoadOptionPtr
;
861 UINTN OptionalDataSize
;
862 UINT8
*LoadOptionEnd
;
863 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
868 BootOrderListSize
= 0;
870 BootOrderList
= NULL
;
872 LoadOptionFromVar
= NULL
;
873 BOpt_FreeMenu (&BootOptionMenu
);
874 InitializeListHead (&BootOptionMenu
.Head
);
877 // Get the BootOrder from the Var
879 BootOrderList
= BdsLibGetVariableAndSize (
881 &gEfiGlobalVariableGuid
,
886 // Get the BootNext from the Var
888 BootNext
= BdsLibGetVariableAndSize (
890 &gEfiGlobalVariableGuid
,
895 if (BootNextSize
!= sizeof (UINT16
)) {
896 SafeFreePool (BootNext
);
901 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
902 UnicodeSPrint (BootString
, sizeof (BootString
), L
"Boot%04x", BootOrderList
[Index
]);
904 // Get all loadoptions from the VAR
906 LoadOptionFromVar
= BdsLibGetVariableAndSize (
908 &gEfiGlobalVariableGuid
,
911 if (!LoadOptionFromVar
) {
915 LoadOption
= AllocateZeroPool (BootOptionSize
);
920 CopyMem (LoadOption
, LoadOptionFromVar
, BootOptionSize
);
921 SafeFreePool (LoadOptionFromVar
);
924 BootNextFlag
= (BOOLEAN
) (*BootNext
== BootOrderList
[Index
]);
926 BootNextFlag
= FALSE
;
929 if (0 == (*((UINT32
*) LoadOption
) & LOAD_OPTION_ACTIVE
)) {
930 SafeFreePool (LoadOption
);
934 // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly.
935 // the buffer allocated already should be freed before returning.
937 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
938 if (NULL
== NewMenuEntry
) {
939 return EFI_OUT_OF_RESOURCES
;
942 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
944 LoadOptionPtr
= LoadOption
;
945 LoadOptionEnd
= LoadOption
+ BootOptionSize
;
947 NewMenuEntry
->OptionNumber
= BootOrderList
[Index
];
948 NewLoadContext
->LoadOptionModified
= FALSE
;
949 NewLoadContext
->Deleted
= FALSE
;
950 NewLoadContext
->IsBootNext
= BootNextFlag
;
953 // Is a Legacy Device?
955 Ptr
= (UINT8
*) LoadOption
;
958 // Attribute = *(UINT32 *)Ptr;
960 Ptr
+= sizeof (UINT32
);
963 // FilePathSize = *(UINT16 *)Ptr;
965 Ptr
+= sizeof (UINT16
);
968 // Description = (CHAR16 *)Ptr;
970 Ptr
+= StrSize ((CHAR16
*) Ptr
);
973 // Now Ptr point to Device Path
975 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) Ptr
;
976 if ((BBS_DEVICE_PATH
== DevicePath
->Type
) && (BBS_BBS_DP
== DevicePath
->SubType
)) {
977 NewLoadContext
->IsLegacy
= TRUE
;
979 NewLoadContext
->IsLegacy
= FALSE
;
982 // LoadOption is a pointer type of UINT8
983 // for easy use with following LOAD_OPTION
984 // embedded in this struct
986 NewLoadContext
->LoadOption
= LoadOption
;
987 NewLoadContext
->LoadOptionSize
= BootOptionSize
;
989 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
990 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
992 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
994 LoadOptionPtr
+= sizeof (UINT32
);
996 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
997 LoadOptionPtr
+= sizeof (UINT16
);
999 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1000 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1001 ASSERT (NewLoadContext
->Description
!= NULL
);
1003 NewLoadContext
->Description
,
1004 (UINT16
*) LoadOptionPtr
,
1007 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1009 LoadOptionPtr
+= StringSize
;
1011 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1012 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1014 NewLoadContext
->FilePathList
,
1015 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1016 NewLoadContext
->FilePathListLength
1019 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1020 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1022 BootOptionStrDepository
1024 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1026 BootOptionHelpStrDepository
1028 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1030 if (LoadOptionPtr
< LoadOptionEnd
) {
1031 OptionalDataSize
= BootOptionSize
-
1035 NewLoadContext
->FilePathListLength
;
1037 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1038 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1040 NewLoadContext
->OptionalData
,
1045 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1048 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
1052 SafeFreePool (BootNext
);
1053 SafeFreePool (BootOrderList
);
1054 BootOptionMenu
.MenuNumber
= MenuCount
;
1059 BOpt_AppendFileName (
1066 Append file name to existing file name.
1069 Str1 - existing file name
1070 Str2 - file name to be appended
1073 Allocate a new string to hold the appended result.
1074 Caller is responsible to free the returned string.
1084 Size1
= StrSize (Str1
);
1085 Size2
= StrSize (Str2
);
1086 Str
= AllocateZeroPool (Size1
+ Size2
+ sizeof (CHAR16
));
1087 ASSERT (Str
!= NULL
);
1090 if (!((*Str
== '\\') && (*(Str
+ 1) == 0))) {
1091 StrCat (Str
, L
"\\");
1099 if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '.' && *(Ptr
+ 3) != 0) {
1101 // Convert \Name\..\ to \
1102 // DO NOT convert the .. if it is at the end of the string. This will
1103 // break the .. behavior in changing directories.
1105 StrCpy (LastSlash
, Ptr
+ 3);
1107 } else if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '\\') {
1109 // Convert a \.\ to a \
1111 StrCpy (Ptr
, Ptr
+ 2);
1113 } else if (*Ptr
== '\\') {
1124 BOpt_IsEfiImageName (
1130 Check whether current FileName point to a valid
1134 FileName - File need to be checked.
1138 FALSE - Not a valid Efi Image
1143 // Search for ".efi" extension
1146 if (FileName
[0] == '.') {
1147 if (FileName
[1] == 'e' || FileName
[1] == 'E') {
1148 if (FileName
[2] == 'f' || FileName
[2] == 'F') {
1149 if (FileName
[3] == 'i' || FileName
[3] == 'I') {
1151 } else if (FileName
[3] == 0x0000) {
1154 } else if (FileName
[2] == 0x0000) {
1157 } else if (FileName
[1] == 0x0000) {
1170 IN EFI_FILE_HANDLE Dir
,
1175 Routine Description:
1176 Check whether current FileName point to a valid Efi Application
1179 Dir - Pointer to current Directory
1180 FileName - Pointer to current File name.
1183 TRUE - Is a valid Efi Application
1184 FALSE - not a valid Efi Application
1189 EFI_IMAGE_DOS_HEADER DosHdr
;
1190 EFI_IMAGE_NT_HEADERS PeHdr
;
1191 EFI_IMAGE_OPTIONAL_HEADER32
*PeOpt32
;
1192 EFI_IMAGE_OPTIONAL_HEADER64
*PeOpt64
;
1194 EFI_FILE_HANDLE File
;
1197 Status
= Dir
->Open (Dir
, &File
, FileName
, EFI_FILE_MODE_READ
, 0);
1199 if (EFI_ERROR (Status
)) {
1203 BufferSize
= sizeof (EFI_IMAGE_DOS_HEADER
);
1204 File
->Read (File
, &BufferSize
, &DosHdr
);
1205 if (DosHdr
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1210 File
->SetPosition (File
, DosHdr
.e_lfanew
);
1211 BufferSize
= sizeof (EFI_IMAGE_NT_HEADERS
);
1212 File
->Read (File
, &BufferSize
, &PeHdr
);
1213 if (PeHdr
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1218 // Determine PE type and read subsytem
1219 // BugBug : We should be using EFI_IMAGE_MACHINE_TYPE_SUPPORTED (machine)
1220 // macro to detect the machine type.
1221 // We should not be using EFI_IMAGE_OPTIONAL_HEADER32 and
1222 // EFI_IMAGE_OPTIONAL_HEADER64
1224 if (PeHdr
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1225 PeOpt32
= (EFI_IMAGE_OPTIONAL_HEADER32
*) &(PeHdr
.OptionalHeader
);
1226 Subsystem
= PeOpt32
->Subsystem
;
1227 } else if (PeHdr
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1228 PeOpt64
= (EFI_IMAGE_OPTIONAL_HEADER64
*) &(PeHdr
.OptionalHeader
);
1229 Subsystem
= PeOpt64
->Subsystem
;
1234 if (Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1250 Find drivers that will be added as Driver#### variables from handles
1251 in current system environment
1252 All valid handles in the system except those consume SimpleFs, LoadFile
1253 are stored in DriverMenu for future use.
1264 UINTN NoDevicePathHandles
;
1265 EFI_HANDLE
*DevicePathHandle
;
1268 BM_MENU_ENTRY
*NewMenuEntry
;
1269 BM_HANDLE_CONTEXT
*NewHandleContext
;
1270 EFI_HANDLE CurHandle
;
1272 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFs
;
1273 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1278 InitializeListHead (&DriverMenu
.Head
);
1281 // At first, get all handles that support Device Path
1282 // protocol which is the basic requirement for
1285 Status
= gBS
->LocateHandleBuffer (
1287 &gEfiDevicePathProtocolGuid
,
1289 &NoDevicePathHandles
,
1292 if (EFI_ERROR (Status
)) {
1297 for (Index
= 0; Index
< NoDevicePathHandles
; Index
++) {
1298 CurHandle
= DevicePathHandle
[Index
];
1301 // Check whether this handle support
1304 Status
= gBS
->HandleProtocol (
1306 &gEfiSimpleFileSystemProtocolGuid
,
1309 if (Status
== EFI_SUCCESS
) {
1313 Status
= gBS
->HandleProtocol (
1315 &gEfiLoadFileProtocolGuid
,
1318 if (Status
== EFI_SUCCESS
) {
1322 NewMenuEntry
= BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT
);
1323 if (NULL
== NewMenuEntry
) {
1324 return EFI_OUT_OF_RESOURCES
;
1327 NewHandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1328 NewHandleContext
->Handle
= CurHandle
;
1329 NewHandleContext
->DevicePath
= DevicePathFromHandle (CurHandle
);
1330 NewMenuEntry
->DisplayString
= DevicePathToStr (NewHandleContext
->DevicePath
);
1331 NewMenuEntry
->HelpString
= NULL
;
1332 NewMenuEntry
->OptionNumber
= OptionNumber
;
1334 InsertTailList (&DriverMenu
.Head
, &NewMenuEntry
->Link
);
1338 DriverMenu
.MenuNumber
= OptionNumber
;
1343 BOpt_GetBootOptionNumber (
1348 Routine Description:
1349 Get the Option Number that does not used
1358 BM_MENU_ENTRY
*NewMenuEntry
;
1359 UINT16
*BootOrderList
;
1360 UINTN BootOrderListSize
;
1365 CHAR16 StrTemp
[100];
1366 UINT16
*OptionBuffer
;
1369 BootOrderListSize
= 0;
1370 BootOrderList
= NULL
;
1372 BootOrderList
= BdsLibGetVariableAndSize (
1374 &gEfiGlobalVariableGuid
,
1377 if (BootOrderList
) {
1379 // already have Boot####
1381 // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
1383 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
1385 for (Index2
= 0; Index2
< BootOptionMenu
.MenuNumber
; Index2
++) {
1386 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index2
);
1387 if (Index
== NewMenuEntry
->OptionNumber
) {
1394 UnicodeSPrint (StrTemp
, 100, L
"Boot%04x", Index
);
1395 DEBUG((EFI_D_ERROR
,"INdex= %s\n", StrTemp
));
1396 OptionBuffer
= BdsLibGetVariableAndSize (
1398 &gEfiGlobalVariableGuid
,
1401 if (NULL
== OptionBuffer
)
1408 Number
= (UINT16
) Index
;
1420 BOpt_GetDriverOptionNumber (
1425 Routine Description:
1426 Get the Option Number that does not used
1435 BM_MENU_ENTRY
*NewMenuEntry
;
1436 UINT16
*DriverOrderList
;
1437 UINTN DriverOrderListSize
;
1443 DriverOrderListSize
= 0;
1444 DriverOrderList
= NULL
;
1446 DriverOrderList
= BdsLibGetVariableAndSize (
1448 &gEfiGlobalVariableGuid
,
1449 &DriverOrderListSize
1451 if (DriverOrderList
) {
1453 // already have Driver####
1455 // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
1457 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1459 for (Index2
= 0; Index2
< DriverOptionMenu
.MenuNumber
; Index2
++) {
1460 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index2
);
1461 if (Index
== NewMenuEntry
->OptionNumber
) {
1474 Number
= (UINT16
) Index
;
1486 BOpt_GetDriverOptions (
1487 IN BMM_CALLBACK_DATA
*CallbackData
1491 Routine Description:
1492 Build up all DriverOptionMenu
1502 UINT16 DriverString
[12];
1503 UINT8
*LoadOptionFromVar
;
1505 UINTN DriverOptionSize
;
1507 UINT16
*DriverOrderList
;
1508 UINTN DriverOrderListSize
;
1509 BM_MENU_ENTRY
*NewMenuEntry
;
1510 BM_LOAD_CONTEXT
*NewLoadContext
;
1511 UINT8
*LoadOptionPtr
;
1513 UINTN OptionalDataSize
;
1514 UINT8
*LoadOptionEnd
;
1516 DriverOrderListSize
= 0;
1517 DriverOrderList
= NULL
;
1518 DriverOptionSize
= 0;
1519 LoadOptionFromVar
= NULL
;
1520 BOpt_FreeMenu (&DriverOptionMenu
);
1521 InitializeListHead (&DriverOptionMenu
.Head
);
1523 // Get the DriverOrder from the Var
1525 DriverOrderList
= BdsLibGetVariableAndSize (
1527 &gEfiGlobalVariableGuid
,
1528 &DriverOrderListSize
1531 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1534 sizeof (DriverString
),
1536 DriverOrderList
[Index
]
1539 // Get all loadoptions from the VAR
1541 LoadOptionFromVar
= BdsLibGetVariableAndSize (
1543 &gEfiGlobalVariableGuid
,
1546 if (!LoadOptionFromVar
) {
1550 LoadOption
= AllocateZeroPool (DriverOptionSize
);
1555 CopyMem (LoadOption
, LoadOptionFromVar
, DriverOptionSize
);
1556 SafeFreePool (LoadOptionFromVar
);
1558 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
1559 if (NULL
== NewMenuEntry
) {
1560 return EFI_OUT_OF_RESOURCES
;
1563 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1564 LoadOptionPtr
= LoadOption
;
1565 LoadOptionEnd
= LoadOption
+ DriverOptionSize
;
1566 NewMenuEntry
->OptionNumber
= DriverOrderList
[Index
];
1567 NewLoadContext
->LoadOptionModified
= FALSE
;
1568 NewLoadContext
->Deleted
= FALSE
;
1569 NewLoadContext
->IsLegacy
= FALSE
;
1572 // LoadOption is a pointer type of UINT8
1573 // for easy use with following LOAD_OPTION
1574 // embedded in this struct
1576 NewLoadContext
->LoadOption
= LoadOption
;
1577 NewLoadContext
->LoadOptionSize
= DriverOptionSize
;
1579 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1580 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1582 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1584 LoadOptionPtr
+= sizeof (UINT32
);
1586 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1587 LoadOptionPtr
+= sizeof (UINT16
);
1589 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1590 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1591 ASSERT (NewLoadContext
->Description
!= NULL
);
1593 NewLoadContext
->Description
,
1594 (UINT16
*) LoadOptionPtr
,
1597 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1599 LoadOptionPtr
+= StringSize
;
1601 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1602 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1604 NewLoadContext
->FilePathList
,
1605 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1606 NewLoadContext
->FilePathListLength
1609 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1610 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1612 DriverOptionStrDepository
1614 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1616 DriverOptionHelpStrDepository
1618 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1620 if (LoadOptionPtr
< LoadOptionEnd
) {
1621 OptionalDataSize
= DriverOptionSize
-
1625 NewLoadContext
->FilePathListLength
;
1627 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1628 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1630 NewLoadContext
->OptionalData
,
1635 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1638 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
1642 SafeFreePool (DriverOrderList
);
1643 DriverOptionMenu
.MenuNumber
= Index
;
1654 Routine Description:
1655 Wrap original FreePool gBS call
1656 in order to decrease code length
1664 if (Buffer
!= NULL
) {
1665 gBS
->FreePool (Buffer
);