2 Copyright (c) 2006 - 2007, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 Provide boot option support for Application "BootMaint"
19 Include file system navigation, system handle selection
21 Boot option manipulation
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
;
1060 OUT CHAR16
*Destination
,
1061 IN CONST CHAR16
*Source
1064 CHAR16
*ReturnValue
;
1067 // Destination cannot be NULL
1069 ASSERT (Destination
!= NULL
);
1071 ReturnValue
= Destination
;
1073 *(Destination
++) = *(Source
++);
1080 BOpt_AppendFileName (
1087 Append file name to existing file name.
1090 Str1 - existing file name
1091 Str2 - file name to be appended
1094 Allocate a new string to hold the appended result.
1095 Caller is responsible to free the returned string.
1105 Size1
= StrSize (Str1
);
1106 Size2
= StrSize (Str2
);
1107 Str
= AllocateZeroPool (Size1
+ Size2
+ sizeof (CHAR16
));
1108 ASSERT (Str
!= NULL
);
1111 if (!((*Str
== '\\') && (*(Str
+ 1) == 0))) {
1112 StrCat (Str
, L
"\\");
1120 if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '.' && *(Ptr
+ 3) != 0) {
1122 // Convert \Name\..\ to \
1123 // DO NOT convert the .. if it is at the end of the string. This will
1124 // break the .. behavior in changing directories.
1126 BdsStrCpy (LastSlash
, Ptr
+ 3);
1128 } else if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '\\') {
1130 // Convert a \.\ to a \
1132 BdsStrCpy (Ptr
, Ptr
+ 2);
1134 } else if (*Ptr
== '\\') {
1145 BOpt_IsEfiImageName (
1151 Check whether current FileName point to a valid
1155 FileName - File need to be checked.
1159 FALSE - Not a valid Efi Image
1164 // Search for ".efi" extension
1167 if (FileName
[0] == '.') {
1168 if (FileName
[1] == 'e' || FileName
[1] == 'E') {
1169 if (FileName
[2] == 'f' || FileName
[2] == 'F') {
1170 if (FileName
[3] == 'i' || FileName
[3] == 'I') {
1172 } else if (FileName
[3] == 0x0000) {
1175 } else if (FileName
[2] == 0x0000) {
1178 } else if (FileName
[1] == 0x0000) {
1192 IsEfiAppReadFromFile (
1193 IN VOID
*FileHandle
,
1194 IN UINTN FileOffset
,
1195 IN OUT UINTN
*ReadSize
,
1200 EFI_FILE_HANDLE File
;
1202 File
= (EFI_FILE_HANDLE
)FileHandle
;
1203 Status
= File
->SetPosition (File
, FileOffset
);
1204 if (EFI_ERROR (Status
)) {
1208 return File
->Read (File
, ReadSize
, Buffer
);
1215 IN EFI_FILE_HANDLE Dir
,
1220 Routine Description:
1221 Check whether current FileName point to a valid Efi Application
1224 Dir - Pointer to current Directory
1225 FileName - Pointer to current File name.
1228 TRUE - Is a valid Efi Application
1229 FALSE - not a valid Efi Application
1234 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1235 EFI_FILE_HANDLE File
;
1237 Status
= Dir
->Open (Dir
, &File
, FileName
, EFI_FILE_MODE_READ
, 0);
1238 if (EFI_ERROR (Status
)) {
1242 ZeroMem (&ImageContext
, sizeof (ImageContext
));
1243 ImageContext
.Handle
= (VOID
*)File
;
1244 ImageContext
.ImageRead
= IsEfiAppReadFromFile
;
1246 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1248 if (EFI_ERROR (Status
)) {
1252 if (ImageContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1267 Find drivers that will be added as Driver#### variables from handles
1268 in current system environment
1269 All valid handles in the system except those consume SimpleFs, LoadFile
1270 are stored in DriverMenu for future use.
1281 UINTN NoDevicePathHandles
;
1282 EFI_HANDLE
*DevicePathHandle
;
1285 BM_MENU_ENTRY
*NewMenuEntry
;
1286 BM_HANDLE_CONTEXT
*NewHandleContext
;
1287 EFI_HANDLE CurHandle
;
1289 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFs
;
1290 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1295 InitializeListHead (&DriverMenu
.Head
);
1298 // At first, get all handles that support Device Path
1299 // protocol which is the basic requirement for
1302 Status
= gBS
->LocateHandleBuffer (
1304 &gEfiDevicePathProtocolGuid
,
1306 &NoDevicePathHandles
,
1309 if (EFI_ERROR (Status
)) {
1314 for (Index
= 0; Index
< NoDevicePathHandles
; Index
++) {
1315 CurHandle
= DevicePathHandle
[Index
];
1318 // Check whether this handle support
1321 Status
= gBS
->HandleProtocol (
1323 &gEfiSimpleFileSystemProtocolGuid
,
1326 if (Status
== EFI_SUCCESS
) {
1330 Status
= gBS
->HandleProtocol (
1332 &gEfiLoadFileProtocolGuid
,
1335 if (Status
== EFI_SUCCESS
) {
1339 NewMenuEntry
= BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT
);
1340 if (NULL
== NewMenuEntry
) {
1341 return EFI_OUT_OF_RESOURCES
;
1344 NewHandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1345 NewHandleContext
->Handle
= CurHandle
;
1346 NewHandleContext
->DevicePath
= DevicePathFromHandle (CurHandle
);
1347 NewMenuEntry
->DisplayString
= DevicePathToStr (NewHandleContext
->DevicePath
);
1348 NewMenuEntry
->HelpString
= NULL
;
1349 NewMenuEntry
->OptionNumber
= OptionNumber
;
1351 InsertTailList (&DriverMenu
.Head
, &NewMenuEntry
->Link
);
1355 DriverMenu
.MenuNumber
= OptionNumber
;
1360 BOpt_GetBootOptionNumber (
1365 Routine Description:
1366 Get the Option Number that does not used
1375 BM_MENU_ENTRY
*NewMenuEntry
;
1376 UINT16
*BootOrderList
;
1377 UINTN BootOrderListSize
;
1382 CHAR16 StrTemp
[100];
1383 UINT16
*OptionBuffer
;
1386 BootOrderListSize
= 0;
1387 BootOrderList
= NULL
;
1389 BootOrderList
= BdsLibGetVariableAndSize (
1391 &gEfiGlobalVariableGuid
,
1394 if (BootOrderList
) {
1396 // already have Boot####
1398 // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16);
1400 for (Index
= 0; Index
< BootOrderListSize
/ sizeof (UINT16
); Index
++) {
1402 for (Index2
= 0; Index2
< BootOptionMenu
.MenuNumber
; Index2
++) {
1403 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index2
);
1404 if (Index
== NewMenuEntry
->OptionNumber
) {
1411 UnicodeSPrint (StrTemp
, 100, L
"Boot%04x", Index
);
1412 DEBUG((EFI_D_ERROR
,"INdex= %s\n", StrTemp
));
1413 OptionBuffer
= BdsLibGetVariableAndSize (
1415 &gEfiGlobalVariableGuid
,
1418 if (NULL
== OptionBuffer
)
1425 Number
= (UINT16
) Index
;
1437 BOpt_GetDriverOptionNumber (
1442 Routine Description:
1443 Get the Option Number that does not used
1452 BM_MENU_ENTRY
*NewMenuEntry
;
1453 UINT16
*DriverOrderList
;
1454 UINTN DriverOrderListSize
;
1460 DriverOrderListSize
= 0;
1461 DriverOrderList
= NULL
;
1463 DriverOrderList
= BdsLibGetVariableAndSize (
1465 &gEfiGlobalVariableGuid
,
1466 &DriverOrderListSize
1468 if (DriverOrderList
) {
1470 // already have Driver####
1472 // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16);
1474 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1476 for (Index2
= 0; Index2
< DriverOptionMenu
.MenuNumber
; Index2
++) {
1477 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index2
);
1478 if (Index
== NewMenuEntry
->OptionNumber
) {
1491 Number
= (UINT16
) Index
;
1503 BOpt_GetDriverOptions (
1504 IN BMM_CALLBACK_DATA
*CallbackData
1508 Routine Description:
1509 Build up all DriverOptionMenu
1519 UINT16 DriverString
[12];
1520 UINT8
*LoadOptionFromVar
;
1522 UINTN DriverOptionSize
;
1524 UINT16
*DriverOrderList
;
1525 UINTN DriverOrderListSize
;
1526 BM_MENU_ENTRY
*NewMenuEntry
;
1527 BM_LOAD_CONTEXT
*NewLoadContext
;
1528 UINT8
*LoadOptionPtr
;
1530 UINTN OptionalDataSize
;
1531 UINT8
*LoadOptionEnd
;
1533 DriverOrderListSize
= 0;
1534 DriverOrderList
= NULL
;
1535 DriverOptionSize
= 0;
1536 LoadOptionFromVar
= NULL
;
1537 BOpt_FreeMenu (&DriverOptionMenu
);
1538 InitializeListHead (&DriverOptionMenu
.Head
);
1540 // Get the DriverOrder from the Var
1542 DriverOrderList
= BdsLibGetVariableAndSize (
1544 &gEfiGlobalVariableGuid
,
1545 &DriverOrderListSize
1548 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1551 sizeof (DriverString
),
1553 DriverOrderList
[Index
]
1556 // Get all loadoptions from the VAR
1558 LoadOptionFromVar
= BdsLibGetVariableAndSize (
1560 &gEfiGlobalVariableGuid
,
1563 if (!LoadOptionFromVar
) {
1567 LoadOption
= AllocateZeroPool (DriverOptionSize
);
1572 CopyMem (LoadOption
, LoadOptionFromVar
, DriverOptionSize
);
1573 SafeFreePool (LoadOptionFromVar
);
1575 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
1576 if (NULL
== NewMenuEntry
) {
1577 return EFI_OUT_OF_RESOURCES
;
1580 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1581 LoadOptionPtr
= LoadOption
;
1582 LoadOptionEnd
= LoadOption
+ DriverOptionSize
;
1583 NewMenuEntry
->OptionNumber
= DriverOrderList
[Index
];
1584 NewLoadContext
->LoadOptionModified
= FALSE
;
1585 NewLoadContext
->Deleted
= FALSE
;
1586 NewLoadContext
->IsLegacy
= FALSE
;
1589 // LoadOption is a pointer type of UINT8
1590 // for easy use with following LOAD_OPTION
1591 // embedded in this struct
1593 NewLoadContext
->LoadOption
= LoadOption
;
1594 NewLoadContext
->LoadOptionSize
= DriverOptionSize
;
1596 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1597 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1599 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1601 LoadOptionPtr
+= sizeof (UINT32
);
1603 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1604 LoadOptionPtr
+= sizeof (UINT16
);
1606 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1607 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1608 ASSERT (NewLoadContext
->Description
!= NULL
);
1610 NewLoadContext
->Description
,
1611 (UINT16
*) LoadOptionPtr
,
1614 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1616 LoadOptionPtr
+= StringSize
;
1618 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1619 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1621 NewLoadContext
->FilePathList
,
1622 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1623 NewLoadContext
->FilePathListLength
1626 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1627 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1629 DriverOptionStrDepository
1631 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1633 DriverOptionHelpStrDepository
1635 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1637 if (LoadOptionPtr
< LoadOptionEnd
) {
1638 OptionalDataSize
= DriverOptionSize
-
1642 NewLoadContext
->FilePathListLength
;
1644 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1645 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1647 NewLoadContext
->OptionalData
,
1652 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1655 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
1659 SafeFreePool (DriverOrderList
);
1660 DriverOptionMenu
.MenuNumber
= Index
;