2 Provide boot option support for Application "BootMaint"
4 Include file system navigation, system handle selection
6 Boot option manipulation
8 Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
9 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 by given menu type.
25 @param MenuType The Menu type to be created.
27 @retval NULL If failed to create the menu.
28 @return the new menu entry.
32 BOpt_CreateMenuEntry (
36 BM_MENU_ENTRY
*MenuEntry
;
40 // Get context size according to menu type
43 case BM_LOAD_CONTEXT_SELECT
:
44 ContextSize
= sizeof (BM_LOAD_CONTEXT
);
47 case BM_FILE_CONTEXT_SELECT
:
48 ContextSize
= sizeof (BM_FILE_CONTEXT
);
51 case BM_CONSOLE_CONTEXT_SELECT
:
52 ContextSize
= sizeof (BM_CONSOLE_CONTEXT
);
55 case BM_TERMINAL_CONTEXT_SELECT
:
56 ContextSize
= sizeof (BM_TERMINAL_CONTEXT
);
59 case BM_HANDLE_CONTEXT_SELECT
:
60 ContextSize
= sizeof (BM_HANDLE_CONTEXT
);
63 case BM_LEGACY_DEV_CONTEXT_SELECT
:
64 ContextSize
= sizeof (BM_LEGACY_DEVICE_CONTEXT
);
72 if (ContextSize
== 0) {
77 // Create new menu entry
79 MenuEntry
= AllocateZeroPool (sizeof (BM_MENU_ENTRY
));
80 if (MenuEntry
== NULL
) {
84 MenuEntry
->VariableContext
= AllocateZeroPool (ContextSize
);
85 if (MenuEntry
->VariableContext
== NULL
) {
90 MenuEntry
->Signature
= BM_MENU_ENTRY_SIGNATURE
;
91 MenuEntry
->ContextSelection
= MenuType
;
96 Free up all resource allocated for a BM_MENU_ENTRY.
98 @param MenuEntry A pointer to BM_MENU_ENTRY.
102 BOpt_DestroyMenuEntry (
103 BM_MENU_ENTRY
*MenuEntry
106 BM_LOAD_CONTEXT
*LoadContext
;
107 BM_FILE_CONTEXT
*FileContext
;
108 BM_CONSOLE_CONTEXT
*ConsoleContext
;
109 BM_TERMINAL_CONTEXT
*TerminalContext
;
110 BM_HANDLE_CONTEXT
*HandleContext
;
111 BM_LEGACY_DEVICE_CONTEXT
*LegacyDevContext
;
114 // Select by the type in Menu entry for current context type
116 switch (MenuEntry
->ContextSelection
) {
117 case BM_LOAD_CONTEXT_SELECT
:
118 LoadContext
= (BM_LOAD_CONTEXT
*) MenuEntry
->VariableContext
;
119 FreePool (LoadContext
->FilePathList
);
120 FreePool (LoadContext
->LoadOption
);
121 if (LoadContext
->OptionalData
!= NULL
) {
122 FreePool (LoadContext
->OptionalData
);
124 FreePool (LoadContext
);
127 case BM_FILE_CONTEXT_SELECT
:
128 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
130 if (!FileContext
->IsRoot
) {
131 FreePool (FileContext
->DevicePath
);
133 if (FileContext
->FHandle
!= NULL
) {
134 FileContext
->FHandle
->Close (FileContext
->FHandle
);
138 if (FileContext
->FileName
!= NULL
) {
139 FreePool (FileContext
->FileName
);
141 if (FileContext
->Info
!= NULL
) {
142 FreePool (FileContext
->Info
);
144 FreePool (FileContext
);
147 case BM_CONSOLE_CONTEXT_SELECT
:
148 ConsoleContext
= (BM_CONSOLE_CONTEXT
*) MenuEntry
->VariableContext
;
149 FreePool (ConsoleContext
->DevicePath
);
150 FreePool (ConsoleContext
);
153 case BM_TERMINAL_CONTEXT_SELECT
:
154 TerminalContext
= (BM_TERMINAL_CONTEXT
*) MenuEntry
->VariableContext
;
155 FreePool (TerminalContext
->DevicePath
);
156 FreePool (TerminalContext
);
159 case BM_HANDLE_CONTEXT_SELECT
:
160 HandleContext
= (BM_HANDLE_CONTEXT
*) MenuEntry
->VariableContext
;
161 FreePool (HandleContext
);
164 case BM_LEGACY_DEV_CONTEXT_SELECT
:
165 LegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) MenuEntry
->VariableContext
;
166 FreePool (LegacyDevContext
);
172 FreePool (MenuEntry
->DisplayString
);
173 if (MenuEntry
->HelpString
!= NULL
) {
174 FreePool (MenuEntry
->HelpString
);
177 FreePool (MenuEntry
);
181 Get the Menu Entry from the list in Menu Entry List.
183 If MenuNumber is great or equal to the number of Menu
184 Entry in the list, then ASSERT.
186 @param MenuOption The Menu Entry List to read the menu entry.
187 @param MenuNumber The index of Menu Entry.
189 @return The Menu Entry.
194 BM_MENU_OPTION
*MenuOption
,
198 BM_MENU_ENTRY
*NewMenuEntry
;
202 ASSERT (MenuNumber
< MenuOption
->MenuNumber
);
204 List
= MenuOption
->Head
.ForwardLink
;
205 for (Index
= 0; Index
< MenuNumber
; Index
++) {
206 List
= List
->ForwardLink
;
209 NewMenuEntry
= CR (List
, BM_MENU_ENTRY
, Link
, BM_MENU_ENTRY_SIGNATURE
);
215 This function build the FsOptionMenu list which records all
216 available file system in the system. They includes all instances
217 of EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, all instances of EFI_LOAD_FILE_SYSTEM
218 and all type of legacy boot device.
220 @param CallbackData BMM context data
222 @retval EFI_SUCCESS Success find the file system
223 @retval EFI_OUT_OF_RESOURCES Can not create menu entry
227 BOpt_FindFileSystem (
228 IN BMM_CALLBACK_DATA
*CallbackData
231 UINTN NoBlkIoHandles
;
232 UINTN NoSimpleFsHandles
;
233 UINTN NoLoadFileHandles
;
234 EFI_HANDLE
*BlkIoHandle
;
235 EFI_HANDLE
*SimpleFsHandle
;
236 EFI_HANDLE
*LoadFileHandle
;
238 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
241 BM_MENU_ENTRY
*MenuEntry
;
242 BM_FILE_CONTEXT
*FileContext
;
246 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
248 BBS_BBS_DEVICE_PATH BbsDevicePathNode
;
249 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
250 BOOLEAN RemovableMedia
;
253 NoSimpleFsHandles
= 0;
254 NoLoadFileHandles
= 0;
256 InitializeListHead (&FsOptionMenu
.Head
);
259 // Locate Handles that support BlockIo protocol
261 Status
= gBS
->LocateHandleBuffer (
263 &gEfiBlockIoProtocolGuid
,
268 if (!EFI_ERROR (Status
)) {
270 for (Index
= 0; Index
< NoBlkIoHandles
; Index
++) {
271 Status
= gBS
->HandleProtocol (
273 &gEfiBlockIoProtocolGuid
,
277 if (EFI_ERROR (Status
)) {
282 // Issue a dummy read to trigger reinstall of BlockIo protocol for removable media
284 if (BlkIo
->Media
->RemovableMedia
) {
285 Buffer
= AllocateZeroPool (BlkIo
->Media
->BlockSize
);
286 if (NULL
== Buffer
) {
287 FreePool (BlkIoHandle
);
288 return EFI_OUT_OF_RESOURCES
;
293 BlkIo
->Media
->MediaId
,
295 BlkIo
->Media
->BlockSize
,
301 FreePool (BlkIoHandle
);
305 // Locate Handles that support Simple File System protocol
307 Status
= gBS
->LocateHandleBuffer (
309 &gEfiSimpleFileSystemProtocolGuid
,
314 if (!EFI_ERROR (Status
)) {
316 // Find all the instances of the File System prototocol
318 for (Index
= 0; Index
< NoSimpleFsHandles
; Index
++) {
319 Status
= gBS
->HandleProtocol (
320 SimpleFsHandle
[Index
],
321 &gEfiBlockIoProtocolGuid
,
324 if (EFI_ERROR (Status
)) {
326 // If no block IO exists assume it's NOT a removable media
328 RemovableMedia
= FALSE
;
331 // If block IO exists check to see if it's remobable media
333 RemovableMedia
= BlkIo
->Media
->RemovableMedia
;
337 // Allocate pool for this load option
339 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
340 if (NULL
== MenuEntry
) {
341 FreePool (SimpleFsHandle
);
342 return EFI_OUT_OF_RESOURCES
;
345 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
347 FileContext
->Handle
= SimpleFsHandle
[Index
];
348 MenuEntry
->OptionNumber
= Index
;
349 FileContext
->FHandle
= EfiLibOpenRoot (FileContext
->Handle
);
350 if (FileContext
->FHandle
== NULL
) {
351 BOpt_DestroyMenuEntry (MenuEntry
);
355 MenuEntry
->HelpString
= DevicePathToStr (DevicePathFromHandle (FileContext
->Handle
));
356 FileContext
->Info
= EfiLibFileSystemVolumeLabelInfo (FileContext
->FHandle
);
357 FileContext
->FileName
= EfiStrDuplicate (L
"\\");
358 FileContext
->DevicePath
= FileDevicePath (
360 FileContext
->FileName
362 FileContext
->IsDir
= TRUE
;
363 FileContext
->IsRoot
= TRUE
;
364 FileContext
->IsRemovableMedia
= RemovableMedia
;
365 FileContext
->IsLoadFile
= FALSE
;
368 // Get current file system's Volume Label
370 if (FileContext
->Info
== NULL
) {
371 VolumeLabel
= L
"NO FILE SYSTEM INFO";
373 VolumeLabel
= FileContext
->Info
->VolumeLabel
;
374 if (*VolumeLabel
== 0x0000) {
375 VolumeLabel
= L
"NO VOLUME LABEL";
379 TempStr
= MenuEntry
->HelpString
;
380 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
381 ASSERT (MenuEntry
->DisplayString
!= NULL
);
383 MenuEntry
->DisplayString
,
390 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
394 if (NoSimpleFsHandles
!= 0) {
395 FreePool (SimpleFsHandle
);
398 // Searching for handles that support Load File protocol
400 Status
= gBS
->LocateHandleBuffer (
402 &gEfiLoadFileProtocolGuid
,
408 if (!EFI_ERROR (Status
)) {
409 for (Index
= 0; Index
< NoLoadFileHandles
; Index
++) {
410 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
411 if (NULL
== MenuEntry
) {
412 FreePool (LoadFileHandle
);
413 return EFI_OUT_OF_RESOURCES
;
416 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
417 FileContext
->IsRemovableMedia
= FALSE
;
418 FileContext
->IsLoadFile
= TRUE
;
419 FileContext
->Handle
= LoadFileHandle
[Index
];
420 FileContext
->IsRoot
= TRUE
;
422 FileContext
->DevicePath
= DevicePathFromHandle (FileContext
->Handle
);
423 FileContext
->FileName
= DevicePathToStr (FileContext
->DevicePath
);
425 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
427 TempStr
= MenuEntry
->HelpString
;
428 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
429 ASSERT (MenuEntry
->DisplayString
!= NULL
);
431 MenuEntry
->DisplayString
,
437 MenuEntry
->OptionNumber
= OptionNumber
;
439 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
443 if (NoLoadFileHandles
!= 0) {
444 FreePool (LoadFileHandle
);
448 // Add Legacy Boot Option Support Here
450 Status
= gBS
->LocateProtocol (
451 &gEfiLegacyBiosProtocolGuid
,
453 (VOID
**) &LegacyBios
455 if (!EFI_ERROR (Status
)) {
457 for (Index
= BBS_TYPE_FLOPPY
; Index
<= BBS_TYPE_EMBEDDED_NETWORK
; Index
++) {
458 MenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
459 if (NULL
== MenuEntry
) {
460 return EFI_OUT_OF_RESOURCES
;
463 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
465 FileContext
->IsRemovableMedia
= FALSE
;
466 FileContext
->IsLoadFile
= TRUE
;
467 FileContext
->IsBootLegacy
= TRUE
;
468 DeviceType
= (UINT16
) Index
;
469 BbsDevicePathNode
.Header
.Type
= BBS_DEVICE_PATH
;
470 BbsDevicePathNode
.Header
.SubType
= BBS_BBS_DP
;
471 SetDevicePathNodeLength (
472 &BbsDevicePathNode
.Header
,
473 sizeof (BBS_BBS_DEVICE_PATH
)
475 BbsDevicePathNode
.DeviceType
= DeviceType
;
476 BbsDevicePathNode
.StatusFlag
= 0;
477 BbsDevicePathNode
.String
[0] = 0;
478 DevicePath
= AppendDevicePathNode (
480 (EFI_DEVICE_PATH_PROTOCOL
*) &BbsDevicePathNode
483 FileContext
->DevicePath
= DevicePath
;
484 MenuEntry
->HelpString
= DevicePathToStr (FileContext
->DevicePath
);
486 TempStr
= MenuEntry
->HelpString
;
487 MenuEntry
->DisplayString
= AllocateZeroPool (MAX_CHAR
);
488 ASSERT (MenuEntry
->DisplayString
!= NULL
);
490 MenuEntry
->DisplayString
,
495 MenuEntry
->OptionNumber
= OptionNumber
;
497 InsertTailList (&FsOptionMenu
.Head
, &MenuEntry
->Link
);
501 // Remember how many file system options are here
503 FsOptionMenu
.MenuNumber
= OptionNumber
;
508 Free resources allocated in Allocate Rountine.
510 @param FreeMenu Menu to be freed
514 BM_MENU_OPTION
*FreeMenu
517 BM_MENU_ENTRY
*MenuEntry
;
518 while (!IsListEmpty (&FreeMenu
->Head
)) {
520 FreeMenu
->Head
.ForwardLink
,
523 BM_MENU_ENTRY_SIGNATURE
525 RemoveEntryList (&MenuEntry
->Link
);
526 BOpt_DestroyMenuEntry (MenuEntry
);
528 FreeMenu
->MenuNumber
= 0;
532 Find files under current directory
533 All files and sub-directories in current directory
534 will be stored in DirectoryMenu for future use.
536 @param CallbackData The BMM context data.
537 @param MenuEntry The Menu Entry.
539 @retval EFI_SUCCESS Get files from current dir successfully.
540 @return Other value if can't get files from current dir.
545 IN BMM_CALLBACK_DATA
*CallbackData
,
546 IN BM_MENU_ENTRY
*MenuEntry
549 EFI_FILE_HANDLE NewDir
;
551 EFI_FILE_INFO
*DirInfo
;
554 BM_MENU_ENTRY
*NewMenuEntry
;
555 BM_FILE_CONTEXT
*FileContext
;
556 BM_FILE_CONTEXT
*NewFileContext
;
561 FileContext
= (BM_FILE_CONTEXT
*) MenuEntry
->VariableContext
;
562 Dir
= FileContext
->FHandle
;
565 // Open current directory to get files from it
570 FileContext
->FileName
,
574 if (!FileContext
->IsRoot
) {
578 if (EFI_ERROR (Status
)) {
582 DirInfo
= EfiLibFileInfo (NewDir
);
583 if (DirInfo
== NULL
) {
584 return EFI_NOT_FOUND
;
587 if ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == 0) {
588 return EFI_INVALID_PARAMETER
;
591 FileContext
->DevicePath
= FileDevicePath (
593 FileContext
->FileName
596 DirBufferSize
= sizeof (EFI_FILE_INFO
) + 1024;
597 DirInfo
= AllocateZeroPool (DirBufferSize
);
598 if (DirInfo
== NULL
) {
599 return EFI_OUT_OF_RESOURCES
;
602 // Get all files in current directory
603 // Pass 1 to get Directories
604 // Pass 2 to get files that are EFI images
606 for (Pass
= 1; Pass
<= 2; Pass
++) {
607 NewDir
->SetPosition (NewDir
, 0);
609 BufferSize
= DirBufferSize
;
610 Status
= NewDir
->Read (NewDir
, &BufferSize
, DirInfo
);
611 if (EFI_ERROR (Status
) || BufferSize
== 0) {
615 if (((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0 && Pass
== 2) ||
616 ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == 0 && Pass
== 1)
619 // Pass 1 is for Directories
620 // Pass 2 is for file names
625 if (!(BOpt_IsEfiImageName (DirInfo
->FileName
) || (DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) != 0)) {
627 // Slip file unless it is a directory entry or a .EFI file
632 NewMenuEntry
= BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT
);
633 if (NULL
== NewMenuEntry
) {
634 return EFI_OUT_OF_RESOURCES
;
637 NewFileContext
= (BM_FILE_CONTEXT
*) NewMenuEntry
->VariableContext
;
638 NewFileContext
->Handle
= FileContext
->Handle
;
639 NewFileContext
->FileName
= BOpt_AppendFileName (
640 FileContext
->FileName
,
643 NewFileContext
->FHandle
= NewDir
;
644 NewFileContext
->DevicePath
= FileDevicePath (
645 NewFileContext
->Handle
,
646 NewFileContext
->FileName
648 NewMenuEntry
->HelpString
= NULL
;
650 MenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
652 FileOptionStrDepository
655 NewFileContext
->IsDir
= (BOOLEAN
) ((DirInfo
->Attribute
& EFI_FILE_DIRECTORY
) == EFI_FILE_DIRECTORY
);
657 if (NewFileContext
->IsDir
) {
658 BufferSize
= StrLen (DirInfo
->FileName
) * 2 + 6;
659 NewMenuEntry
->DisplayString
= AllocateZeroPool (BufferSize
);
662 NewMenuEntry
->DisplayString
,
669 NewMenuEntry
->DisplayString
= EfiStrDuplicate (DirInfo
->FileName
);
672 NewFileContext
->IsRoot
= FALSE
;
673 NewFileContext
->IsLoadFile
= FALSE
;
674 NewFileContext
->IsRemovableMedia
= FALSE
;
676 NewMenuEntry
->OptionNumber
= OptionNumber
;
678 InsertTailList (&DirectoryMenu
.Head
, &NewMenuEntry
->Link
);
682 DirectoryMenu
.MenuNumber
= OptionNumber
;
688 Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo().
690 @retval EFI_SUCCESS The function complete successfully.
691 @retval EFI_OUT_OF_RESOURCES No enough memory to complete this function.
695 BOpt_GetLegacyOptions (
699 BM_MENU_ENTRY
*NewMenuEntry
;
700 BM_LEGACY_DEVICE_CONTEXT
*NewLegacyDevContext
;
702 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
708 CHAR16 DescString
[100];
721 // Initialize Bbs Table Context from BBS info data
723 InitializeListHead (&LegacyFDMenu
.Head
);
724 InitializeListHead (&LegacyHDMenu
.Head
);
725 InitializeListHead (&LegacyCDMenu
.Head
);
726 InitializeListHead (&LegacyNETMenu
.Head
);
727 InitializeListHead (&LegacyBEVMenu
.Head
);
729 Status
= gBS
->LocateProtocol (
730 &gEfiLegacyBiosProtocolGuid
,
732 (VOID
**) &LegacyBios
734 if (!EFI_ERROR (Status
)) {
735 Status
= LegacyBios
->GetBbsInfo (
742 if (EFI_ERROR (Status
)) {
753 for (Index
= 0; Index
< BbsCount
; Index
++) {
754 if ((BBS_IGNORE_ENTRY
== BbsTable
[Index
].BootPriority
) ||
755 (BBS_DO_NOT_BOOT_FROM
== BbsTable
[Index
].BootPriority
)
760 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT
);
761 if (NULL
== NewMenuEntry
) {
765 NewLegacyDevContext
= (BM_LEGACY_DEVICE_CONTEXT
*) NewMenuEntry
->VariableContext
;
766 NewLegacyDevContext
->BbsEntry
= &BbsTable
[Index
];
767 NewLegacyDevContext
->BbsIndex
= Index
;
768 NewLegacyDevContext
->BbsCount
= BbsCount
;
769 BdsBuildLegacyDevNameString (
775 NewLegacyDevContext
->Description
= AllocateCopyPool (StrSize (DescString
), DescString
);
776 if (NULL
== NewLegacyDevContext
->Description
) {
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.
829 BOpt_FreeLegacyOptions (
833 BOpt_FreeMenu (&LegacyFDMenu
);
834 BOpt_FreeMenu (&LegacyHDMenu
);
835 BOpt_FreeMenu (&LegacyCDMenu
);
836 BOpt_FreeMenu (&LegacyNETMenu
);
837 BOpt_FreeMenu (&LegacyBEVMenu
);
842 Build the BootOptionMenu according to BootOrder Variable.
843 This Routine will access the Boot#### to get EFI_LOAD_OPTION.
845 @param CallbackData The BMM context data.
847 @return EFI_NOT_FOUND Fail to find "BootOrder" variable.
848 @return EFI_SUCESS Success build boot option menu.
852 BOpt_GetBootOptions (
853 IN BMM_CALLBACK_DATA
*CallbackData
857 UINT16 BootString
[10];
858 UINT8
*LoadOptionFromVar
;
860 UINTN BootOptionSize
;
861 BOOLEAN BootNextFlag
;
862 UINT16
*BootOrderList
;
863 UINTN BootOrderListSize
;
866 BM_MENU_ENTRY
*NewMenuEntry
;
867 BM_LOAD_CONTEXT
*NewLoadContext
;
868 UINT8
*LoadOptionPtr
;
870 UINTN OptionalDataSize
;
871 UINT8
*LoadOptionEnd
;
872 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
877 BootOrderListSize
= 0;
879 BootOrderList
= NULL
;
881 LoadOptionFromVar
= NULL
;
882 BOpt_FreeMenu (&BootOptionMenu
);
883 InitializeListHead (&BootOptionMenu
.Head
);
886 // Get the BootOrder from the Var
888 BootOrderList
= BdsLibGetVariableAndSize (
890 &gEfiGlobalVariableGuid
,
893 if (BootOrderList
== NULL
) {
894 return EFI_NOT_FOUND
;
898 // Get the BootNext from the Var
900 BootNext
= BdsLibGetVariableAndSize (
902 &gEfiGlobalVariableGuid
,
906 if (BootNext
!= NULL
) {
907 if (BootNextSize
!= sizeof (UINT16
)) {
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 FreePool (LoadOptionFromVar
);
935 if (BootNext
!= NULL
) {
936 BootNextFlag
= (BOOLEAN
) (*BootNext
== BootOrderList
[Index
]);
938 BootNextFlag
= FALSE
;
941 if (0 == (*((UINT32
*) LoadOption
) & LOAD_OPTION_ACTIVE
)) {
942 FreePool (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
);
1013 NewLoadContext
->Description
= AllocateCopyPool (StrSize((UINT16
*)LoadOptionPtr
), LoadOptionPtr
);
1014 ASSERT (NewLoadContext
->Description
!= NULL
);
1016 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1018 LoadOptionPtr
+= StringSize
;
1020 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1021 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1023 NewLoadContext
->FilePathList
,
1024 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1025 NewLoadContext
->FilePathListLength
1028 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1029 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1031 BootOptionStrDepository
1033 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1035 BootOptionHelpStrDepository
1037 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1039 if (LoadOptionPtr
< LoadOptionEnd
) {
1040 OptionalDataSize
= BootOptionSize
-
1044 NewLoadContext
->FilePathListLength
;
1046 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1047 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1049 NewLoadContext
->OptionalData
,
1054 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1057 InsertTailList (&BootOptionMenu
.Head
, &NewMenuEntry
->Link
);
1061 if (BootNext
!= NULL
) {
1062 FreePool (BootNext
);
1064 if (BootOrderList
!= NULL
) {
1065 FreePool (BootOrderList
);
1067 BootOptionMenu
.MenuNumber
= MenuCount
;
1073 Append file name to existing file name.
1075 @param Str1 The existing file name
1076 @param Str2 The file name to be appended
1078 @return Allocate a new string to hold the appended result.
1079 Caller is responsible to free the returned string.
1083 BOpt_AppendFileName (
1096 Size1
= StrSize (Str1
);
1097 Size2
= StrSize (Str2
);
1098 MaxLen
= (Size1
+ Size2
+ sizeof (CHAR16
)) / sizeof (CHAR16
);
1099 Str
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1100 ASSERT (Str
!= NULL
);
1102 TmpStr
= AllocateZeroPool (MaxLen
* sizeof (CHAR16
));
1103 ASSERT (TmpStr
!= NULL
);
1105 StrCatS (Str
, MaxLen
, Str1
);
1106 if (!((*Str
== '\\') && (*(Str
+ 1) == 0))) {
1107 StrCatS (Str
, MaxLen
, L
"\\");
1110 StrCatS (Str
, MaxLen
, Str2
);
1115 if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '.' && *(Ptr
+ 3) == L
'\\') {
1117 // Convert "\Name\..\" to "\"
1118 // DO NOT convert the .. if it is at the end of the string. This will
1119 // break the .. behavior in changing directories.
1123 // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings
1126 StrCpyS (TmpStr
, MaxLen
, Ptr
+ 3);
1127 StrCpyS (LastSlash
, MaxLen
- ((UINTN
) LastSlash
- (UINTN
) Str
) / sizeof (CHAR16
), TmpStr
);
1129 } else if (*Ptr
== '\\' && *(Ptr
+ 1) == '.' && *(Ptr
+ 2) == '\\') {
1131 // Convert a "\.\" to a "\"
1135 // Use TmpStr as a backup, as StrCpyS in BaseLib does not handle copy of two strings
1138 StrCpyS (TmpStr
, MaxLen
, Ptr
+ 2);
1139 StrCpyS (Ptr
, MaxLen
- ((UINTN
) Ptr
- (UINTN
) Str
) / sizeof (CHAR16
), TmpStr
);
1141 } else if (*Ptr
== '\\') {
1155 Check whether current FileName point to a valid
1158 @param FileName File need to be checked.
1160 @retval TRUE Is Efi Image
1161 @retval FALSE Not a valid Efi Image
1165 BOpt_IsEfiImageName (
1170 // Search for ".efi" extension
1172 while (*FileName
!= L
'\0') {
1173 if (FileName
[0] == '.') {
1174 if (FileName
[1] == 'e' || FileName
[1] == 'E') {
1175 if (FileName
[2] == 'f' || FileName
[2] == 'F') {
1176 if (FileName
[3] == 'i' || FileName
[3] == 'I') {
1178 } else if (FileName
[3] == 0x0000) {
1181 } else if (FileName
[2] == 0x0000) {
1184 } else if (FileName
[1] == 0x0000) {
1197 Check whether current FileName point to a valid Efi Application
1199 @param Dir Pointer to current Directory
1200 @param FileName Pointer to current File name.
1202 @retval TRUE Is a valid Efi Application
1203 @retval FALSE not a valid Efi Application
1208 IN EFI_FILE_HANDLE Dir
,
1213 EFI_IMAGE_DOS_HEADER DosHdr
;
1215 EFI_FILE_HANDLE File
;
1217 EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr
;
1219 Status
= Dir
->Open (Dir
, &File
, FileName
, EFI_FILE_MODE_READ
, 0);
1221 if (EFI_ERROR (Status
)) {
1225 BufferSize
= sizeof (EFI_IMAGE_DOS_HEADER
);
1226 File
->Read (File
, &BufferSize
, &DosHdr
);
1227 if (DosHdr
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
1232 File
->SetPosition (File
, DosHdr
.e_lfanew
);
1233 BufferSize
= sizeof (EFI_IMAGE_OPTIONAL_HEADER_UNION
);
1234 File
->Read (File
, &BufferSize
, &PeHdr
);
1235 if (PeHdr
.Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1240 // Determine PE type and read subsytem
1242 if (PeHdr
.Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1243 Subsystem
= PeHdr
.Pe32
.OptionalHeader
.Subsystem
;
1244 } else if (PeHdr
.Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1245 Subsystem
= PeHdr
.Pe32Plus
.OptionalHeader
.Subsystem
;
1250 if (Subsystem
== EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
) {
1261 Find drivers that will be added as Driver#### variables from handles
1262 in current system environment
1263 All valid handles in the system except those consume SimpleFs, LoadFile
1264 are stored in DriverMenu for future use.
1266 @retval EFI_SUCCESS The function complets successfully.
1267 @return Other value if failed to build the DriverMenu.
1275 UINTN NoDevicePathHandles
;
1276 EFI_HANDLE
*DevicePathHandle
;
1279 BM_MENU_ENTRY
*NewMenuEntry
;
1280 BM_HANDLE_CONTEXT
*NewHandleContext
;
1281 EFI_HANDLE CurHandle
;
1283 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFs
;
1284 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1289 InitializeListHead (&DriverMenu
.Head
);
1292 // At first, get all handles that support Device Path
1293 // protocol which is the basic requirement for
1296 Status
= gBS
->LocateHandleBuffer (
1298 &gEfiDevicePathProtocolGuid
,
1300 &NoDevicePathHandles
,
1303 if (EFI_ERROR (Status
)) {
1308 for (Index
= 0; Index
< NoDevicePathHandles
; Index
++) {
1309 CurHandle
= DevicePathHandle
[Index
];
1311 Status
= gBS
->HandleProtocol (
1313 &gEfiSimpleFileSystemProtocolGuid
,
1316 if (Status
== EFI_SUCCESS
) {
1320 Status
= gBS
->HandleProtocol (
1322 &gEfiLoadFileProtocolGuid
,
1325 if (Status
== EFI_SUCCESS
) {
1329 NewMenuEntry
= BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT
);
1330 if (NULL
== NewMenuEntry
) {
1331 FreePool (DevicePathHandle
);
1332 return EFI_OUT_OF_RESOURCES
;
1335 NewHandleContext
= (BM_HANDLE_CONTEXT
*) NewMenuEntry
->VariableContext
;
1336 NewHandleContext
->Handle
= CurHandle
;
1337 NewHandleContext
->DevicePath
= DevicePathFromHandle (CurHandle
);
1338 NewMenuEntry
->DisplayString
= DevicePathToStr (NewHandleContext
->DevicePath
);
1339 NewMenuEntry
->HelpString
= NULL
;
1340 NewMenuEntry
->OptionNumber
= OptionNumber
;
1342 InsertTailList (&DriverMenu
.Head
, &NewMenuEntry
->Link
);
1346 if (DevicePathHandle
!= NULL
) {
1347 FreePool (DevicePathHandle
);
1350 DriverMenu
.MenuNumber
= OptionNumber
;
1356 Get the Option Number that has not been allocated for use.
1358 @param Type The type of Option.
1360 @return The available Option Number.
1364 BOpt_GetOptionNumber (
1369 UINTN OrderListSize
;
1372 UINT16
*OptionBuffer
;
1373 UINT16 OptionNumber
;
1381 UnicodeSPrint (StrTemp
, sizeof (StrTemp
), L
"%sOrder", Type
);
1383 OrderList
= BdsLibGetVariableAndSize (
1385 &gEfiGlobalVariableGuid
,
1389 for (OptionNumber
= 0; ; OptionNumber
++) {
1390 if (OrderList
!= NULL
) {
1391 for (Index
= 0; Index
< OrderListSize
/ sizeof (UINT16
); Index
++) {
1392 if (OptionNumber
== OrderList
[Index
]) {
1398 if (Index
< OrderListSize
/ sizeof (UINT16
)) {
1400 // The OptionNumber occurs in the OrderList, continue to use next one
1404 UnicodeSPrint (StrTemp
, sizeof (StrTemp
), L
"%s%04x", Type
, (UINTN
) OptionNumber
);
1405 DEBUG((EFI_D_ERROR
,"Option = %s\n", StrTemp
));
1406 OptionBuffer
= BdsLibGetVariableAndSize (
1408 &gEfiGlobalVariableGuid
,
1411 if (NULL
== OptionBuffer
) {
1413 // The Boot[OptionNumber] / Driver[OptionNumber] NOT occurs, we found it
1419 return OptionNumber
;
1424 Get the Option Number for Boot#### that does not used.
1426 @return The available Option Number.
1430 BOpt_GetBootOptionNumber (
1434 return BOpt_GetOptionNumber (L
"Boot");
1439 Get the Option Number for Driver#### that does not used.
1441 @return The unused Option Number.
1445 BOpt_GetDriverOptionNumber (
1449 return BOpt_GetOptionNumber (L
"Driver");
1454 Build up all DriverOptionMenu
1456 @param CallbackData The BMM context data.
1458 @retval EFI_SUCESS The functin completes successfully.
1459 @retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
1460 @retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.
1464 BOpt_GetDriverOptions (
1465 IN BMM_CALLBACK_DATA
*CallbackData
1469 UINT16 DriverString
[12];
1470 UINT8
*LoadOptionFromVar
;
1472 UINTN DriverOptionSize
;
1474 UINT16
*DriverOrderList
;
1475 UINTN DriverOrderListSize
;
1476 BM_MENU_ENTRY
*NewMenuEntry
;
1477 BM_LOAD_CONTEXT
*NewLoadContext
;
1478 UINT8
*LoadOptionPtr
;
1480 UINTN OptionalDataSize
;
1481 UINT8
*LoadOptionEnd
;
1483 DriverOrderListSize
= 0;
1484 DriverOrderList
= NULL
;
1485 DriverOptionSize
= 0;
1486 LoadOptionFromVar
= NULL
;
1487 BOpt_FreeMenu (&DriverOptionMenu
);
1488 InitializeListHead (&DriverOptionMenu
.Head
);
1490 // Get the DriverOrder from the Var
1492 DriverOrderList
= BdsLibGetVariableAndSize (
1494 &gEfiGlobalVariableGuid
,
1495 &DriverOrderListSize
1497 if (DriverOrderList
== NULL
) {
1498 return EFI_NOT_FOUND
;
1501 for (Index
= 0; Index
< DriverOrderListSize
/ sizeof (UINT16
); Index
++) {
1504 sizeof (DriverString
),
1506 DriverOrderList
[Index
]
1509 // Get all loadoptions from the VAR
1511 LoadOptionFromVar
= BdsLibGetVariableAndSize (
1513 &gEfiGlobalVariableGuid
,
1516 if (LoadOptionFromVar
== NULL
) {
1520 LoadOption
= AllocateZeroPool (DriverOptionSize
);
1521 if (LoadOption
== NULL
) {
1525 CopyMem (LoadOption
, LoadOptionFromVar
, DriverOptionSize
);
1526 FreePool (LoadOptionFromVar
);
1528 NewMenuEntry
= BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT
);
1529 if (NULL
== NewMenuEntry
) {
1530 return EFI_OUT_OF_RESOURCES
;
1533 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1534 LoadOptionPtr
= LoadOption
;
1535 LoadOptionEnd
= LoadOption
+ DriverOptionSize
;
1536 NewMenuEntry
->OptionNumber
= DriverOrderList
[Index
];
1537 NewLoadContext
->LoadOptionModified
= FALSE
;
1538 NewLoadContext
->Deleted
= FALSE
;
1539 NewLoadContext
->IsLegacy
= FALSE
;
1542 // LoadOption is a pointer type of UINT8
1543 // for easy use with following LOAD_OPTION
1544 // embedded in this struct
1546 NewLoadContext
->LoadOption
= LoadOption
;
1547 NewLoadContext
->LoadOptionSize
= DriverOptionSize
;
1549 NewLoadContext
->Attributes
= *(UINT32
*) LoadOptionPtr
;
1550 NewLoadContext
->IsActive
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_ACTIVE
);
1552 NewLoadContext
->ForceReconnect
= (BOOLEAN
) (NewLoadContext
->Attributes
& LOAD_OPTION_FORCE_RECONNECT
);
1554 LoadOptionPtr
+= sizeof (UINT32
);
1556 NewLoadContext
->FilePathListLength
= *(UINT16
*) LoadOptionPtr
;
1557 LoadOptionPtr
+= sizeof (UINT16
);
1559 StringSize
= StrSize ((UINT16
*) LoadOptionPtr
);
1560 NewLoadContext
->Description
= AllocateZeroPool (StringSize
);
1561 ASSERT (NewLoadContext
->Description
!= NULL
);
1563 NewLoadContext
->Description
,
1564 (UINT16
*) LoadOptionPtr
,
1567 NewMenuEntry
->DisplayString
= NewLoadContext
->Description
;
1569 LoadOptionPtr
+= StringSize
;
1571 NewLoadContext
->FilePathList
= AllocateZeroPool (NewLoadContext
->FilePathListLength
);
1572 ASSERT (NewLoadContext
->FilePathList
!= NULL
);
1574 NewLoadContext
->FilePathList
,
1575 (EFI_DEVICE_PATH_PROTOCOL
*) LoadOptionPtr
,
1576 NewLoadContext
->FilePathListLength
1579 NewMenuEntry
->HelpString
= DevicePathToStr (NewLoadContext
->FilePathList
);
1580 NewMenuEntry
->DisplayStringToken
= GetStringTokenFromDepository (
1582 DriverOptionStrDepository
1584 NewMenuEntry
->HelpStringToken
= GetStringTokenFromDepository (
1586 DriverOptionHelpStrDepository
1588 LoadOptionPtr
+= NewLoadContext
->FilePathListLength
;
1590 if (LoadOptionPtr
< LoadOptionEnd
) {
1591 OptionalDataSize
= DriverOptionSize
-
1595 NewLoadContext
->FilePathListLength
;
1597 NewLoadContext
->OptionalData
= AllocateZeroPool (OptionalDataSize
);
1598 ASSERT (NewLoadContext
->OptionalData
!= NULL
);
1600 NewLoadContext
->OptionalData
,
1605 NewLoadContext
->OptionalDataSize
= OptionalDataSize
;
1608 InsertTailList (&DriverOptionMenu
.Head
, &NewMenuEntry
->Link
);
1612 if (DriverOrderList
!= NULL
) {
1613 FreePool (DriverOrderList
);
1615 DriverOptionMenu
.MenuNumber
= Index
;
1621 Get option number according to Boot#### and BootOrder variable.
1622 The value is saved as #### + 1.
1624 @param CallbackData The BMM context data.
1628 IN BMM_CALLBACK_DATA
*CallbackData
1631 BMM_FAKE_NV_DATA
*BmmConfig
;
1633 UINT16 OptionOrderIndex
;
1635 BM_MENU_ENTRY
*NewMenuEntry
;
1636 BM_LOAD_CONTEXT
*NewLoadContext
;
1638 ASSERT (CallbackData
!= NULL
);
1640 DeviceType
= (UINTN
) -1;
1641 BmmConfig
= &CallbackData
->BmmFakeNvData
;
1642 ZeroMem (BmmConfig
->BootOptionOrder
, sizeof (BmmConfig
->BootOptionOrder
));
1644 for (Index
= 0, OptionOrderIndex
= 0; ((Index
< BootOptionMenu
.MenuNumber
) &&
1645 (OptionOrderIndex
< (sizeof (BmmConfig
->BootOptionOrder
) / sizeof (BmmConfig
->BootOptionOrder
[0]))));
1647 NewMenuEntry
= BOpt_GetMenuEntry (&BootOptionMenu
, Index
);
1648 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1650 if (NewLoadContext
->IsLegacy
) {
1651 if (((BBS_BBS_DEVICE_PATH
*) NewLoadContext
->FilePathList
)->DeviceType
!= DeviceType
) {
1652 DeviceType
= ((BBS_BBS_DEVICE_PATH
*) NewLoadContext
->FilePathList
)->DeviceType
;
1655 // Only show one legacy boot option for the same device type
1656 // assuming the boot options are grouped by the device type
1661 BmmConfig
->BootOptionOrder
[OptionOrderIndex
++] = (UINT32
) (NewMenuEntry
->OptionNumber
+ 1);
1666 According to LegacyDevOrder variable to get legacy FD\HD\CD\NET\BEV
1669 @param CallbackData The BMM context data.
1672 GetLegacyDeviceOrder (
1673 IN BMM_CALLBACK_DATA
*CallbackData
1678 UINT16 PageIdList
[5];
1682 UINT8
*WorkingVarData
;
1683 LEGACY_DEV_ORDER_ENTRY
*DevOrder
;
1686 BM_MENU_OPTION
*OptionMenu
;
1693 ASSERT (CallbackData
!= NULL
);
1695 PageIdList
[0] = FORM_SET_FD_ORDER_ID
;
1696 PageIdList
[1] = FORM_SET_HD_ORDER_ID
;
1697 PageIdList
[2] = FORM_SET_CD_ORDER_ID
;
1698 PageIdList
[3] = FORM_SET_NET_ORDER_ID
;
1699 PageIdList
[4] = FORM_SET_BEV_ORDER_ID
;
1704 DisMap
= ZeroMem (CallbackData
->BmmFakeNvData
.DisableMap
, sizeof (CallbackData
->BmmFakeNvData
.DisableMap
));
1705 PageNum
= ARRAY_SIZE (PageIdList
);
1706 VarData
= BdsLibGetVariableAndSize (
1707 VAR_LEGACY_DEV_ORDER
,
1708 &gEfiLegacyDevOrderVariableGuid
,
1712 for (Index
= 0; Index
< PageNum
; Index
++) {
1713 switch (PageIdList
[Index
]) {
1715 case FORM_SET_FD_ORDER_ID
:
1716 OptionMenu
= (BM_MENU_OPTION
*) &LegacyFDMenu
;
1717 BbsType
= BBS_FLOPPY
;
1718 LegacyOrder
= CallbackData
->BmmFakeNvData
.LegacyFD
;
1719 OldData
= CallbackData
->BmmOldFakeNVData
.LegacyFD
;
1722 case FORM_SET_HD_ORDER_ID
:
1723 OptionMenu
= (BM_MENU_OPTION
*) &LegacyHDMenu
;
1724 BbsType
= BBS_HARDDISK
;
1725 LegacyOrder
= CallbackData
->BmmFakeNvData
.LegacyHD
;
1726 OldData
= CallbackData
->BmmOldFakeNVData
.LegacyHD
;
1729 case FORM_SET_CD_ORDER_ID
:
1730 OptionMenu
= (BM_MENU_OPTION
*) &LegacyCDMenu
;
1731 BbsType
= BBS_CDROM
;
1732 LegacyOrder
= CallbackData
->BmmFakeNvData
.LegacyCD
;
1733 OldData
= CallbackData
->BmmOldFakeNVData
.LegacyCD
;
1736 case FORM_SET_NET_ORDER_ID
:
1737 OptionMenu
= (BM_MENU_OPTION
*) &LegacyNETMenu
;
1738 BbsType
= BBS_EMBED_NETWORK
;
1739 LegacyOrder
= CallbackData
->BmmFakeNvData
.LegacyNET
;
1740 OldData
= CallbackData
->BmmOldFakeNVData
.LegacyNET
;
1744 ASSERT (PageIdList
[Index
] == FORM_SET_BEV_ORDER_ID
);
1745 OptionMenu
= (BM_MENU_OPTION
*) &LegacyBEVMenu
;
1746 BbsType
= BBS_BEV_DEVICE
;
1747 LegacyOrder
= CallbackData
->BmmFakeNvData
.LegacyBEV
;
1748 OldData
= CallbackData
->BmmOldFakeNVData
.LegacyBEV
;
1752 if (NULL
!= VarData
) {
1753 WorkingVarData
= VarData
;
1754 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) WorkingVarData
;
1755 while (WorkingVarData
< VarData
+ VarSize
) {
1756 if (DevOrder
->BbsType
== BbsType
) {
1760 WorkingVarData
= (UINT8
*)((UINTN
)WorkingVarData
+ sizeof (BBS_TYPE
));
1761 WorkingVarData
+= *(UINT16
*) WorkingVarData
;
1762 DevOrder
= (LEGACY_DEV_ORDER_ENTRY
*) WorkingVarData
;
1764 for (OptionIndex
= 0; OptionIndex
< OptionMenu
->MenuNumber
; OptionIndex
++) {
1765 VarDevOrder
= *(UINT16
*) ((UINTN
) DevOrder
+ sizeof (BBS_TYPE
) + sizeof (UINT16
) + OptionIndex
* sizeof (UINT16
));
1766 if (0xFF00 == (VarDevOrder
& 0xFF00)) {
1767 LegacyOrder
[OptionIndex
] = 0xFF;
1768 Pos
= (VarDevOrder
& 0xFF) / 8;
1769 Bit
= 7 - ((VarDevOrder
& 0xFF) % 8);
1770 DisMap
[Pos
] = (UINT8
) (DisMap
[Pos
] | (UINT8
) (1 << Bit
));
1772 LegacyOrder
[OptionIndex
] = (UINT8
) (VarDevOrder
& 0xFF);
1775 CopyMem (OldData
, LegacyOrder
, 100);
1781 Get driver option order from globalc DriverOptionMenu.
1783 @param CallbackData The BMM context data.
1788 IN BMM_CALLBACK_DATA
*CallbackData
1791 BMM_FAKE_NV_DATA
*BmmConfig
;
1793 UINT16 OptionOrderIndex
;
1795 BM_MENU_ENTRY
*NewMenuEntry
;
1796 BM_LOAD_CONTEXT
*NewLoadContext
;
1798 ASSERT (CallbackData
!= NULL
);
1800 DeviceType
= (UINTN
) -1;
1801 BmmConfig
= &CallbackData
->BmmFakeNvData
;
1802 ZeroMem (BmmConfig
->DriverOptionOrder
, sizeof (BmmConfig
->DriverOptionOrder
));
1804 for (Index
= 0, OptionOrderIndex
= 0; ((Index
< DriverOptionMenu
.MenuNumber
) &&
1805 (OptionOrderIndex
< (sizeof (BmmConfig
->DriverOptionOrder
) / sizeof (BmmConfig
->DriverOptionOrder
[0]))));
1807 NewMenuEntry
= BOpt_GetMenuEntry (&DriverOptionMenu
, Index
);
1808 NewLoadContext
= (BM_LOAD_CONTEXT
*) NewMenuEntry
->VariableContext
;
1810 if (NewLoadContext
->IsLegacy
) {
1811 if (((BBS_BBS_DEVICE_PATH
*) NewLoadContext
->FilePathList
)->DeviceType
!= DeviceType
) {
1812 DeviceType
= ((BBS_BBS_DEVICE_PATH
*) NewLoadContext
->FilePathList
)->DeviceType
;
1815 // Only show one legacy boot option for the same device type
1816 // assuming the boot options are grouped by the device type
1821 BmmConfig
->DriverOptionOrder
[OptionOrderIndex
++] = (UINT32
) (NewMenuEntry
->OptionNumber
+ 1);