3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 BDS Lib functions which relate with create or process the boot
23 #include "EdkGenericBdsLibInternal.h"
25 BOOLEAN mEnumBootDevice
= FALSE
;
29 IN BDS_COMMON_OPTION
*Option
35 Boot the legacy system with the boot option
39 Option - The legacy boot option which have BBS device path
43 EFI_UNSUPPORTED - There is no legacybios protocol, do not support
46 EFI_STATUS - Return the status of LegacyBios->LegacyBoot ().
51 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
53 Status
= gBS
->LocateProtocol (&gEfiLegacyBiosProtocolGuid
, NULL
, &LegacyBios
);
54 if (EFI_ERROR (Status
)) {
56 // If no LegacyBios protocol we do not support legacy boot
58 return EFI_UNSUPPORTED
;
61 // Notes: if we seperate the int 19, then we don't need to refresh BBS
63 BdsRefreshBbsTableForBoot (Option
);
66 // Write boot to OS performance data to a file
69 WriteBootToOsPerformanceData ();
73 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Legacy Boot: %S\n", Option
->Description
));
74 return LegacyBios
->LegacyBoot (
76 (BBS_BBS_DEVICE_PATH
*) Option
->DevicePath
,
77 Option
->LoadOptionsSize
,
83 BdsLibBootViaBootOption (
84 IN BDS_COMMON_OPTION
* Option
,
85 IN EFI_DEVICE_PATH_PROTOCOL
* DevicePath
,
86 OUT UINTN
*ExitDataSize
,
87 OUT CHAR16
**ExitData OPTIONAL
93 Process the boot option follow the UEFI 2.0 specification and
94 special treat the legacy boot option with BBS_DEVICE_PATH.
98 Option - The boot option need to be processed
100 DevicePath - The device path which describe where to load
101 the boot image or the legcy BBS device path
102 to boot the legacy OS
104 ExitDataSize - Returned directly from gBS->StartImage ()
106 ExitData - Returned directly from gBS->StartImage ()
110 EFI_SUCCESS - Status from gBS->StartImage (),
111 or BdsBootByDiskSignatureAndPartition ()
113 EFI_NOT_FOUND - If the Device Path is not found in the system
119 EFI_HANDLE ImageHandle
;
120 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
121 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
122 EFI_LOADED_IMAGE_PROTOCOL
*ImageInfo
;
123 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
125 LIST_ENTRY TempBootLists
;
128 // Record the performance data for End of BDS
130 PERF_END (0, BDS_TOK
, NULL
, 0);
136 // Notes: put EFI64 ROM Shadow Solution
138 EFI64_SHADOW_ALL_LEGACY_ROM ();
141 // If it's Device Path that starts with a hard drive path,
142 // this routine will do the booting.
144 Status
= BdsBootByDiskSignatureAndPartition (
146 (HARDDRIVE_DEVICE_PATH
*) DevicePath
,
147 Option
->LoadOptionsSize
,
152 if (!EFI_ERROR (Status
)) {
154 // If we found a disk signature and partition device path return success
159 // Signal the EFI_EVENT_SIGNAL_READY_TO_BOOT event
161 EfiSignalEventReadyToBoot ();
168 &gEfiGlobalVariableGuid
,
169 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
174 if ((DevicePathType (Option
->DevicePath
) == BBS_DEVICE_PATH
) &&
175 (DevicePathSubType (Option
->DevicePath
) == BBS_BBS_DP
)
178 // Check to see if we should legacy BOOT. If yes then do the legacy boot
180 return BdsLibDoLegacyBoot (Option
);
184 // If the boot option point to Internal FV shell, make sure it is valid
186 Status
= UpdateFvFileDevicePath (&DevicePath
, &gEfiShellFileGuid
);
187 if (!EFI_ERROR(Status
)) {
188 if (Option
->DevicePath
!= NULL
) {
189 FreePool (Option
->DevicePath
);
191 Option
->DevicePath
= AllocateZeroPool (GetDevicePathSize (DevicePath
));
192 CopyMem (Option
->DevicePath
, DevicePath
, GetDevicePathSize (DevicePath
));
194 // Update the shell boot option
196 InitializeListHead (&TempBootLists
);
197 BdsLibRegisterNewOption (&TempBootLists
, DevicePath
, L
"EFI Internal Shell", L
"BootOrder");
200 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Booting UEFI 2.0 way %S\n", Option
->Description
));
202 Status
= gBS
->LoadImage (
212 // If we didn't find an image, we may need to load the default
213 // boot behavior for the device.
215 if (EFI_ERROR (Status
)) {
217 // Find a Simple File System protocol on the device path. If the remaining
218 // device path is set to end then no Files are being specified, so try
219 // the removable media file name.
221 TempDevicePath
= DevicePath
;
222 Status
= gBS
->LocateDevicePath (
223 &gEfiSimpleFileSystemProtocolGuid
,
227 if (!EFI_ERROR (Status
) && IsDevicePathEnd (TempDevicePath
)) {
228 FilePath
= FileDevicePath (Handle
, EFI_REMOVABLE_MEDIA_FILE_NAME
);
231 // Issue a dummy read to the device to check for media change.
232 // When the removable media is changed, any Block IO read/write will
233 // cause the BlockIo protocol be reinstalled and EFI_MEDIA_CHANGED is
234 // returned. After the Block IO protocol is reinstalled, subsequent
235 // Block IO read/write will success.
237 Status
= gBS
->HandleProtocol (
239 &gEfiBlockIoProtocolGuid
,
242 if (!EFI_ERROR (Status
)) {
243 Buffer
= AllocatePool (BlkIo
->Media
->BlockSize
);
244 if (Buffer
!= NULL
) {
247 BlkIo
->Media
->MediaId
,
249 BlkIo
->Media
->BlockSize
,
256 Status
= gBS
->LoadImage (
264 if (EFI_ERROR (Status
)) {
266 // The DevicePath failed, and it's not a valid
267 // removable media device.
273 Status
= EFI_NOT_FOUND
;
277 if (EFI_ERROR (Status
)) {
279 // It there is any error from the Boot attempt exit now.
284 // Provide the image with it's load options
286 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiLoadedImageProtocolGuid
, &ImageInfo
);
287 ASSERT_EFI_ERROR (Status
);
289 if (Option
->LoadOptionsSize
!= 0) {
290 ImageInfo
->LoadOptionsSize
= Option
->LoadOptionsSize
;
291 ImageInfo
->LoadOptions
= Option
->LoadOptions
;
294 // Before calling the image, enable the Watchdog Timer for
295 // the 5 Minute period
297 gBS
->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL
);
299 Status
= gBS
->StartImage (ImageHandle
, ExitDataSize
, ExitData
);
300 DEBUG ((EFI_D_INFO
| EFI_D_LOAD
, "Image Return Status = %r\n", Status
));
303 // Clear the Watchdog Timer after the image returns
305 gBS
->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL
);
309 // Clear Boot Current
313 &gEfiGlobalVariableGuid
,
314 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
,
323 BdsBootByDiskSignatureAndPartition (
324 IN BDS_COMMON_OPTION
* Option
,
325 IN HARDDRIVE_DEVICE_PATH
* HardDriveDevicePath
,
326 IN UINT32 LoadOptionsSize
,
327 IN VOID
*LoadOptions
,
328 OUT UINTN
*ExitDataSize
,
329 OUT CHAR16
**ExitData OPTIONAL
335 Check to see if a hard ware device path was passed in. If it was then search
336 all the block IO devices for the passed in hard drive device path.
340 Option - The current processing boot option.
342 HardDriveDevicePath - EFI Device Path to boot, if it starts with a hard
345 LoadOptionsSize - Passed into gBS->StartImage ()
346 via the loaded image protocol.
348 LoadOptions - Passed into gBS->StartImage ()
349 via the loaded image protocol.
351 ExitDataSize - returned directly from gBS->StartImage ()
353 ExitData - returned directly from gBS->StartImage ()
357 EFI_SUCCESS - Status from gBS->StartImage (),
358 or BootByDiskSignatureAndPartition ()
360 EFI_NOT_FOUND - If the Device Path is not found in the system
365 UINTN BlockIoHandleCount
;
366 EFI_HANDLE
*BlockIoBuffer
;
367 EFI_DEVICE_PATH_PROTOCOL
*BlockIoDevicePath
;
368 EFI_DEVICE_PATH_PROTOCOL
*BlockIoHdDevicePath
;
369 HARDDRIVE_DEVICE_PATH
*TmpHdPath
;
370 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
371 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
373 BOOLEAN DevicePathMatch
;
374 HARDDRIVE_DEVICE_PATH
*TempPath
;
379 if ( !((DevicePathType (&HardDriveDevicePath
->Header
) == MEDIA_DEVICE_PATH
) &&
380 (DevicePathSubType (&HardDriveDevicePath
->Header
) == MEDIA_HARDDRIVE_DP
))
383 // If the HardDriveDevicePath does not start with a Hard Drive Device Path
386 return EFI_NOT_FOUND
;
389 // The boot device have already been connected
391 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiBlockIoProtocolGuid
, NULL
, &BlockIoHandleCount
, &BlockIoBuffer
);
392 if (EFI_ERROR (Status
) || BlockIoHandleCount
== 0) {
394 // If there was an error or there are no device handles that support
395 // the BLOCK_IO Protocol, then return.
397 return EFI_NOT_FOUND
;
400 // Loop through all the device handles that support the BLOCK_IO Protocol
402 for (Index
= 0; Index
< BlockIoHandleCount
; Index
++) {
404 Status
= gBS
->HandleProtocol (BlockIoBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*) &BlockIoDevicePath
);
405 if (EFI_ERROR (Status
) || BlockIoDevicePath
== NULL
) {
409 // Make PreviousDevicePath == the device path node before the end node
411 DevicePath
= BlockIoDevicePath
;
412 BlockIoHdDevicePath
= NULL
;
415 // find HardDriver device path node
417 while (!IsDevicePathEnd (DevicePath
)) {
418 if ((DevicePathType (DevicePath
) == MEDIA_DEVICE_PATH
) &&
419 (DevicePathSubType (DevicePath
) == MEDIA_HARDDRIVE_DP
)
421 BlockIoHdDevicePath
= DevicePath
;
425 DevicePath
= NextDevicePathNode (DevicePath
);
428 if (BlockIoHdDevicePath
== NULL
) {
432 // See if the harddrive device path in blockio matches the orig Hard Drive Node
434 DevicePathMatch
= FALSE
;
436 TmpHdPath
= (HARDDRIVE_DEVICE_PATH
*) BlockIoHdDevicePath
;
437 TempPath
= (HARDDRIVE_DEVICE_PATH
*) BdsLibUnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL
*) HardDriveDevicePath
);
440 // Only several fields will be checked. NOT whole NODE
442 if ( TmpHdPath
->PartitionNumber
== TempPath
->PartitionNumber
&&
443 TmpHdPath
->MBRType
== TempPath
->MBRType
&&
444 TmpHdPath
->SignatureType
== TempPath
->SignatureType
&&
445 CompareGuid ((EFI_GUID
*) TmpHdPath
->Signature
, (EFI_GUID
*) TempPath
->Signature
)) {
447 // Get the matched device path
449 DevicePathMatch
= TRUE
;
452 // Only do the boot, when devicepath match
454 if (DevicePathMatch
) {
456 // Combine the Block IO and Hard Drive Device path together and try
459 DevicePath
= NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL
*) HardDriveDevicePath
);
460 NewDevicePath
= AppendDevicePath (BlockIoDevicePath
, DevicePath
);
463 // Recursive boot with new device path
465 Status
= BdsLibBootViaBootOption (Option
, NewDevicePath
, ExitDataSize
, ExitData
);
466 if (!EFI_ERROR (Status
)) {
472 FreePool (BlockIoBuffer
);
477 BdsLibDeleteOptionFromHandle (
484 Delete the boot option associated with the handle passed in
488 Handle - The handle which present the device path to create boot option
492 EFI_SUCCESS - Delete the boot option success
494 EFI_NOT_FOUND - If the Device Path is not found in the system
496 EFI_OUT_OF_RESOURCES - Lack of memory resource
498 Other - Error return value from SetVariable()
503 UINT8
*BootOptionVar
;
505 UINTN BootOptionSize
;
508 UINT16 BootOption
[BOOT_OPTION_MAX_CHAR
];
509 UINTN DevicePathSize
;
510 UINTN OptionDevicePathSize
;
511 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
512 EFI_DEVICE_PATH_PROTOCOL
*OptionDevicePath
;
516 Status
= EFI_SUCCESS
;
520 BootOrder
= BdsLibGetVariableAndSize (
522 &gEfiGlobalVariableGuid
,
525 if (NULL
== BootOrder
) {
526 return EFI_NOT_FOUND
;
529 DevicePath
= DevicePathFromHandle (Handle
);
530 if (DevicePath
== NULL
) {
531 return EFI_NOT_FOUND
;
533 DevicePathSize
= GetDevicePathSize (DevicePath
);
536 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
537 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
538 BootOptionVar
= BdsLibGetVariableAndSize (
540 &gEfiGlobalVariableGuid
,
543 if (NULL
== BootOptionVar
) {
544 FreePool (BootOrder
);
545 return EFI_OUT_OF_RESOURCES
;
548 TempPtr
= BootOptionVar
;
549 TempPtr
+= sizeof (UINT32
) + sizeof (UINT16
);
550 Description
= (CHAR16
*) TempPtr
;
551 TempPtr
+= StrSize ((CHAR16
*) TempPtr
);
552 OptionDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) TempPtr
;
553 OptionDevicePathSize
= GetDevicePathSize (OptionDevicePath
);
556 // Check whether the device path match
558 if ((OptionDevicePathSize
== DevicePathSize
) &&
559 (CompareMem (DevicePath
, OptionDevicePath
, DevicePathSize
) == 0)) {
560 BdsDeleteBootOption (BootOrder
[Index
], BootOrder
, &BootOrderSize
);
561 FreePool (BootOptionVar
);
565 FreePool (BootOptionVar
);
569 Status
= gRT
->SetVariable (
571 &gEfiGlobalVariableGuid
,
572 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
577 FreePool (BootOrder
);
583 BdsDeleteAllInvalidEfiBootOption (
590 Delete all invalid EFI boot options. The probable invalid boot option could
591 be Removable media or Network boot device.
599 EFI_SUCCESS - Delete all invalid boot option success
601 EFI_NOT_FOUND - Variable "BootOrder" is not found
603 EFI_OUT_OF_RESOURCES - Lack of memory resource
605 Other - Error return value from SetVariable()
610 UINT8
*BootOptionVar
;
612 UINTN BootOptionSize
;
616 UINT16 BootOption
[BOOT_OPTION_MAX_CHAR
];
617 UINTN OptionDevicePathSize
;
618 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
619 EFI_DEVICE_PATH_PROTOCOL
*LastDeviceNode
;
620 EFI_DEVICE_PATH_PROTOCOL
*OptionDevicePath
;
626 Status
= EFI_SUCCESS
;
630 BootOrder
= BdsLibGetVariableAndSize (
632 &gEfiGlobalVariableGuid
,
635 if (NULL
== BootOrder
) {
636 return EFI_NOT_FOUND
;
640 while (Index
< BootOrderSize
/ sizeof (UINT16
)) {
641 UnicodeSPrint (BootOption
, sizeof (BootOption
), L
"Boot%04x", BootOrder
[Index
]);
642 BootOptionVar
= BdsLibGetVariableAndSize (
644 &gEfiGlobalVariableGuid
,
647 if (NULL
== BootOptionVar
) {
648 FreePool (BootOrder
);
649 return EFI_OUT_OF_RESOURCES
;
652 TempPtr
= BootOptionVar
;
653 TempPtr
+= sizeof (UINT32
) + sizeof (UINT16
);
654 Description
= (CHAR16
*) TempPtr
;
655 TempPtr
+= StrSize ((CHAR16
*) TempPtr
);
656 OptionDevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) TempPtr
;
657 OptionDevicePathSize
= GetDevicePathSize (OptionDevicePath
);
660 // Skip legacy boot option (BBS boot device)
662 if ((DevicePathType (OptionDevicePath
) == BBS_DEVICE_PATH
) &&
663 (DevicePathSubType (OptionDevicePath
) == BBS_BBS_DP
)) {
664 FreePool (BootOptionVar
);
669 TempDevicePath
= OptionDevicePath
;
670 LastDeviceNode
= OptionDevicePath
;
671 while (!EfiIsDevicePathEnd (TempDevicePath
)) {
672 LastDeviceNode
= TempDevicePath
;
673 TempDevicePath
= EfiNextDevicePathNode (TempDevicePath
);
676 // Skip the boot option that point to a file, since the device path in
677 // removable media boot option doesn't contains a file name.
679 if (((DevicePathType (LastDeviceNode
) == MEDIA_DEVICE_PATH
) &&
680 (DevicePathSubType (LastDeviceNode
) == MEDIA_FILEPATH_DP
)) ||
682 // Skip boot option for internal Shell, it's always valid
684 (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) LastDeviceNode
) != NULL
)) {
685 FreePool (BootOptionVar
);
692 // Check if it's a valid boot option for removable media
694 TempDevicePath
= OptionDevicePath
;
695 Status
= gBS
->LocateDevicePath (
696 &gEfiSimpleFileSystemProtocolGuid
,
700 if (!EFI_ERROR (Status
)) {
704 // Check if it's a valid boot option for network boot device
706 TempDevicePath
= OptionDevicePath
;
707 Status
= gBS
->LocateDevicePath (
708 &gEfiLoadFileProtocolGuid
,
712 if (!EFI_ERROR (Status
)) {
718 // Delete this invalid boot option "Boot####"
720 Status
= gRT
->SetVariable (
722 &gEfiGlobalVariableGuid
,
723 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
728 // Mark this boot option in boot order as deleted
730 BootOrder
[Index
] = 0xffff;
733 FreePool (BootOptionVar
);
738 // Adjust boot order array
741 for (Index
= 0; Index
< BootOrderSize
/ sizeof (UINT16
); Index
++) {
742 if (BootOrder
[Index
] != 0xffff) {
743 BootOrder
[Index2
] = BootOrder
[Index
];
747 Status
= gRT
->SetVariable (
749 &gEfiGlobalVariableGuid
,
750 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
751 Index2
* sizeof (UINT16
),
755 FreePool (BootOrder
);
761 BdsLibEnumerateAllBootOption (
762 IN OUT LIST_ENTRY
*BdsBootOptionList
768 This function will enumerate all possible boot device in the system,
769 it will only excute once of every boot.
773 BdsBootOptionList - The header of the link list which indexed all
778 EFI_SUCCESS - Finished all the boot device enumerate and create
779 the boot option base on that boot device
784 UINT16 BootOptionNumber
;
785 UINTN NumberFileSystemHandles
;
786 EFI_HANDLE
*FileSystemHandles
;
787 EFI_BLOCK_IO_PROTOCOL
*BlkIo
;
789 UINTN NumberLoadFileHandles
;
790 EFI_HANDLE
*LoadFileHandles
;
791 VOID
*ProtocolInstance
;
792 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
794 EFI_HANDLE
*FvHandleBuffer
;
795 EFI_FV_FILETYPE Type
;
797 EFI_FV_FILE_ATTRIBUTES Attributes
;
798 UINT32 AuthenticationStatus
;
799 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
800 EFI_HANDLE ImageHandle
;
801 EFI_LOADED_IMAGE_PROTOCOL
*ImageInfo
;
804 BootOptionNumber
= 0;
807 // If the boot device enumerate happened, just get the boot
808 // device from the boot order variable
810 if (mEnumBootDevice
) {
811 BdsLibBuildOptionFromVar (BdsBootOptionList
, L
"BootOrder");
815 // Notes: this dirty code is to get the legacy boot option from the
816 // BBS table and create to variable as the EFI boot option, it should
817 // be removed after the CSM can provide legacy boot option directly
819 REFRESH_LEGACY_BOOT_OPTIONS
;
822 // Delete invalid boot option
824 BdsDeleteAllInvalidEfiBootOption ();
826 // Parse removable media
828 gBS
->LocateHandleBuffer (
830 &gEfiSimpleFileSystemProtocolGuid
,
832 &NumberFileSystemHandles
,
835 for (Index
= 0; Index
< NumberFileSystemHandles
; Index
++) {
836 Status
= gBS
->HandleProtocol (
837 FileSystemHandles
[Index
],
838 &gEfiBlockIoProtocolGuid
,
841 if (!EFI_ERROR (Status
)) {
842 if (!BlkIo
->Media
->RemovableMedia
) {
844 // If the file system handle supports a BlkIo protocol,
845 // skip the removable media devices
852 // Do the removable Media thing. \EFI\BOOT\boot{machinename}.EFI
853 // machinename is ia32, ia64, x64, ...
855 FilePath
= FileDevicePath (FileSystemHandles
[Index
], EFI_REMOVABLE_MEDIA_FILE_NAME
);
857 Status
= gBS
->LoadImage (
865 if (!EFI_ERROR(Status
)) {
867 // Verify the image is a EFI application (and not a driver)
869 Status
= gBS
->HandleProtocol (ImageHandle
, &gEfiLoadedImageProtocolGuid
, (VOID
**) &ImageInfo
);
870 ASSERT (!EFI_ERROR(Status
));
872 if (ImageInfo
->ImageCodeType
== EfiLoaderCode
) {
879 // No such file or the file is not a EFI application, delete this boot option
881 BdsLibDeleteOptionFromHandle (FileSystemHandles
[Index
]);
883 BdsLibBuildOptionFromHandle (FileSystemHandles
[Index
], BdsBootOptionList
);
888 if (NumberFileSystemHandles
) {
889 FreePool (FileSystemHandles
);
892 // Parse Network Boot Device
894 gBS
->LocateHandleBuffer (
896 &gEfiSimpleNetworkProtocolGuid
,
898 &NumberLoadFileHandles
,
901 for (Index
= 0; Index
< NumberLoadFileHandles
; Index
++) {
902 Status
= gBS
->HandleProtocol (
903 LoadFileHandles
[Index
],
904 &gEfiLoadFileProtocolGuid
,
905 (VOID
**) &ProtocolInstance
907 if (EFI_ERROR (Status
)) {
911 BdsLibBuildOptionFromHandle (LoadFileHandles
[Index
], BdsBootOptionList
);
915 if (NumberLoadFileHandles
) {
916 FreePool (LoadFileHandles
);
919 // Check if we have on flash shell
921 gBS
->LocateHandleBuffer (
923 &gEfiFirmwareVolume2ProtocolGuid
,
928 for (Index
= 0; Index
< FvHandleCount
; Index
++) {
929 gBS
->HandleProtocol (
930 FvHandleBuffer
[Index
],
931 &gEfiFirmwareVolume2ProtocolGuid
,
935 Status
= Fv
->ReadFile (
942 &AuthenticationStatus
944 if (EFI_ERROR (Status
)) {
946 // Skip if no shell file in the FV
951 // Build the shell boot option
953 BdsLibBuildOptionFromShell (FvHandleBuffer
[Index
], BdsBootOptionList
);
958 FreePool (FvHandleBuffer
);
961 // Make sure every boot only have one time
962 // boot device enumerate
964 BdsLibBuildOptionFromVar (BdsBootOptionList
, L
"BootOrder");
965 mEnumBootDevice
= TRUE
;
971 BdsLibBuildOptionFromHandle (
972 IN EFI_HANDLE Handle
,
973 IN LIST_ENTRY
*BdsBootOptionList
979 Build the boot option with the handle parsed in
983 Handle - The handle which present the device path to create boot option
985 BdsBootOptionList - The header of the link list which indexed all current
994 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
997 DevicePath
= DevicePathFromHandle (Handle
);
998 TempString
= DevicePathToStr (DevicePath
);
1001 // Create and register new boot option
1003 BdsLibRegisterNewOption (BdsBootOptionList
, DevicePath
, TempString
, L
"BootOrder");
1007 BdsLibBuildOptionFromShell (
1008 IN EFI_HANDLE Handle
,
1009 IN OUT LIST_ENTRY
*BdsBootOptionList
1013 Routine Description:
1015 Build the on flash shell boot option with the handle parsed in
1019 Handle - The handle which present the device path to create on flash shell
1022 BdsBootOptionList - The header of the link list which indexed all current
1031 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
1032 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode
;
1034 DevicePath
= DevicePathFromHandle (Handle
);
1037 // Build the shell device path
1039 EfiInitializeFwVolDevicepathNode (&ShellNode
, &gEfiShellFileGuid
);
1040 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) &ShellNode
);
1043 // Create and register the shell boot option
1045 BdsLibRegisterNewOption (BdsBootOptionList
, DevicePath
, L
"Internal EFI Shell", L
"BootOrder");
1055 Routine Description:
1057 Boot from the EFI1.1 spec defined "BootNext" variable
1072 BDS_COMMON_OPTION
*BootOption
;
1073 LIST_ENTRY TempList
;
1078 // Init the boot option name buffer and temp link list
1080 InitializeListHead (&TempList
);
1081 ZeroMem (Buffer
, sizeof (Buffer
));
1083 BootNext
= BdsLibGetVariableAndSize (
1085 &gEfiGlobalVariableGuid
,
1090 // Clear the boot next variable first
1092 if (BootNext
!= NULL
) {
1095 &gEfiGlobalVariableGuid
,
1096 EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
,
1102 // Start to build the boot option and try to boot
1104 UnicodeSPrint (Buffer
, sizeof (Buffer
), L
"Boot%04x", *BootNext
);
1105 BootOption
= BdsLibVariableToOption (&TempList
, Buffer
);
1106 BdsLibConnectDevicePath (BootOption
->DevicePath
);
1107 BdsLibBootViaBootOption (BootOption
, BootOption
->DevicePath
, &ExitDataSize
, &ExitData
);
1114 UpdateFvFileDevicePath (
1115 IN OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePath
,
1116 IN EFI_GUID
*FileGuid
1120 Routine Description:
1121 According to a file guild, check a Fv file device path is valid. If it is invalid,
1122 try to return the valid device path.
1123 FV address maybe changes for memory layout adjust from time to time, use this funciton
1124 could promise the Fv file device path is right.
1127 DevicePath - on input, the Fv file device path need to check
1128 on output, the updated valid Fv file device path
1130 FileGuid - the Fv file guild
1133 EFI_INVALID_PARAMETER - the input DevicePath or FileGuid is invalid parameter
1134 EFI_UNSUPPORTED - the input DevicePath does not contain Fv file guild at all
1135 EFI_ALREADY_STARTED - the input DevicePath has pointed to Fv file, it is valid
1136 EFI_SUCCESS - has successfully updated the invalid DevicePath, and return the updated
1137 device path in DevicePath
1141 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
1142 EFI_DEVICE_PATH_PROTOCOL
*LastDeviceNode
;
1144 EFI_GUID
*GuidPoint
;
1146 UINTN FvHandleCount
;
1147 EFI_HANDLE
*FvHandleBuffer
;
1148 EFI_FV_FILETYPE Type
;
1150 EFI_FV_FILE_ATTRIBUTES Attributes
;
1151 UINT32 AuthenticationStatus
;
1153 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
1154 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
1155 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode
;
1156 EFI_HANDLE FoundFvHandle
;
1157 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
1159 if ((DevicePath
== NULL
) || (*DevicePath
== NULL
)) {
1160 return EFI_INVALID_PARAMETER
;
1162 if (FileGuid
== NULL
) {
1163 return EFI_INVALID_PARAMETER
;
1166 // Check whether the device path point to the default the input Fv file
1168 TempDevicePath
= *DevicePath
;
1169 LastDeviceNode
= TempDevicePath
;
1170 while (!EfiIsDevicePathEnd (TempDevicePath
)) {
1171 LastDeviceNode
= TempDevicePath
;
1172 TempDevicePath
= EfiNextDevicePathNode (TempDevicePath
);
1175 GuidPoint
= EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)LastDeviceNode
);
1177 if (GuidPoint
== NULL
) {
1179 // if this option does not points to a Fv file, just return EFI_UNSUPPORTED
1181 return EFI_UNSUPPORTED
;
1184 if (!CompareGuid (GuidPoint
, FileGuid
)) {
1186 // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED
1188 return EFI_UNSUPPORTED
;
1192 // Check whether the input Fv file device path is valid
1194 TempDevicePath
= *DevicePath
;
1195 FoundFvHandle
= NULL
;
1196 Status
= gBS
->LocateDevicePath (
1197 &gEfiFirmwareVolume2ProtocolGuid
,
1201 if (!EFI_ERROR (Status
)) {
1202 Status
= gBS
->HandleProtocol (
1204 &gEfiFirmwareVolume2ProtocolGuid
,
1207 if (!EFI_ERROR (Status
)) {
1209 // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
1211 Status
= Fv
->ReadFile (
1218 &AuthenticationStatus
1220 if (!EFI_ERROR (Status
)) {
1221 return EFI_ALREADY_STARTED
;
1227 // Look for the input wanted FV file in current FV
1228 // First, try to look for in Bds own FV. Bds and input wanted FV file usually are in the same FV
1231 FoundFvHandle
= NULL
;
1232 Status
= gBS
->HandleProtocol (
1234 &gEfiLoadedImageProtocolGuid
,
1235 (VOID
**) &LoadedImage
1237 if (!EFI_ERROR (Status
)) {
1238 Status
= gBS
->HandleProtocol (
1239 LoadedImage
->DeviceHandle
,
1240 &gEfiFirmwareVolume2ProtocolGuid
,
1243 if (!EFI_ERROR (Status
)) {
1244 Status
= Fv
->ReadFile (
1251 &AuthenticationStatus
1253 if (!EFI_ERROR (Status
)) {
1255 FoundFvHandle
= LoadedImage
->DeviceHandle
;
1260 // Second, if fail to find, try to enumerate all FV
1263 gBS
->LocateHandleBuffer (
1265 &gEfiFirmwareVolume2ProtocolGuid
,
1270 for (Index
= 0; Index
< FvHandleCount
; Index
++) {
1271 gBS
->HandleProtocol (
1272 FvHandleBuffer
[Index
],
1273 &gEfiFirmwareVolume2ProtocolGuid
,
1277 Status
= Fv
->ReadFile (
1284 &AuthenticationStatus
1286 if (EFI_ERROR (Status
)) {
1288 // Skip if input Fv file not in the FV
1293 FoundFvHandle
= FvHandleBuffer
[Index
];
1300 // Build the shell device path
1302 NewDevicePath
= DevicePathFromHandle (FoundFvHandle
);
1303 EfiInitializeFwVolDevicepathNode (&FvFileNode
, FileGuid
);
1304 NewDevicePath
= AppendDevicePathNode (NewDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) &FvFileNode
);
1305 *DevicePath
= NewDevicePath
;
1309 return EFI_NOT_FOUND
;