MdeModulePkg/UefiBootManagerLib: Enhance short-form expanding logic
Old implementation only finds first matched full device path for a given short-form device path. The patch adds internal function BmGetNextLoadOptionBuffer() to finds all matched full device path for a given short-form device path. There are 6 kinds of device paths. Some of them match to multiple load options, some of them don't. 1. Media device path: Returns multiple load options: The media device path may point to a physical BlockIo which contains multiple logic partitions, each logic partitions contains \EFI\BOOT\BOOT${ARCH}.EFI. 2. Short-form hard-drive device path: Returns one load option because the partition signature is unique. 3. Short-form file-path device path: Returns multiple load options: There are multiple SimpleFileSystem instances and each contains the same file. 4. Short-form URI device path: Returns multiple load options: There are multiple LoadFile instances and each can boot. 5. Short-form USB device path: Returns multiple load options: There are multiple UsbIo instances and each contains the boot-able file. 6. FV device path, device path pointing to SimpleFileSystem, device path pointing to LoadFile Returns one load option. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com> Cc: Eric Dong <eric.dong@intel.com> Cc: Jeff Fan <jeff.fan@intel.com>
This commit is contained in:
@ -131,21 +131,16 @@ BmFindBootOptionInVariable (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the file buffer using a Memory Mapped Device Path.
|
Return the correct FV file path.
|
||||||
|
|
||||||
FV address may change across reboot. This routine promises the FV file device path is right.
|
FV address may change across reboot. This routine promises the FV file device path is right.
|
||||||
|
|
||||||
@param FilePath The Memory Mapped Device Path to get the file buffer.
|
@param FilePath The Memory Mapped Device Path to get the file buffer.
|
||||||
@param FullPath Receive the updated FV Device Path pointint to the file.
|
|
||||||
@param FileSize Receive the file buffer size.
|
|
||||||
|
|
||||||
@return The file buffer.
|
@return The updated FV Device Path pointint to the file.
|
||||||
**/
|
**/
|
||||||
VOID *
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
BmGetFileBufferByFvFilePath (
|
BmAdjustFvFilePath (
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
|
||||||
OUT UINTN *FileSize
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
@ -153,11 +148,10 @@ BmGetFileBufferByFvFilePath (
|
|||||||
EFI_DEVICE_PATH_PROTOCOL *FvFileNode;
|
EFI_DEVICE_PATH_PROTOCOL *FvFileNode;
|
||||||
EFI_HANDLE FvHandle;
|
EFI_HANDLE FvHandle;
|
||||||
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
|
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
|
||||||
UINT32 AuthenticationStatus;
|
|
||||||
UINTN FvHandleCount;
|
UINTN FvHandleCount;
|
||||||
EFI_HANDLE *FvHandles;
|
EFI_HANDLE *FvHandles;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
|
||||||
VOID *FileBuffer;
|
EFI_DEVICE_PATH_PROTOCOL *FullPath;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get the file buffer by using the exactly FilePath.
|
// Get the file buffer by using the exactly FilePath.
|
||||||
@ -165,11 +159,7 @@ BmGetFileBufferByFvFilePath (
|
|||||||
FvFileNode = FilePath;
|
FvFileNode = FilePath;
|
||||||
Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &FvFileNode, &FvHandle);
|
Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &FvFileNode, &FvHandle);
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);
|
return DuplicateDevicePath (FilePath);
|
||||||
if (FileBuffer != NULL) {
|
|
||||||
*FullPath = DuplicateDevicePath (FilePath);
|
|
||||||
}
|
|
||||||
return FileBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -190,11 +180,10 @@ BmGetFileBufferByFvFilePath (
|
|||||||
(VOID **) &LoadedImage
|
(VOID **) &LoadedImage
|
||||||
);
|
);
|
||||||
NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), FvFileNode);
|
NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (LoadedImage->DeviceHandle), FvFileNode);
|
||||||
FileBuffer = BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, FileSize);
|
FullPath = BmAdjustFvFilePath (NewDevicePath);
|
||||||
FreePool (NewDevicePath);
|
FreePool (NewDevicePath);
|
||||||
|
if (FullPath != NULL) {
|
||||||
if (FileBuffer != NULL) {
|
return FullPath;
|
||||||
return FileBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -207,22 +196,25 @@ BmGetFileBufferByFvFilePath (
|
|||||||
&FvHandleCount,
|
&FvHandleCount,
|
||||||
&FvHandles
|
&FvHandles
|
||||||
);
|
);
|
||||||
for (Index = 0; (Index < FvHandleCount) && (FileBuffer == NULL); Index++) {
|
for (Index = 0; Index < FvHandleCount; Index++) {
|
||||||
if (FvHandles[Index] == LoadedImage->DeviceHandle) {
|
if (FvHandles[Index] == LoadedImage->DeviceHandle) {
|
||||||
//
|
//
|
||||||
// Skip current FV
|
// Skip current FV, it was handed in first step.
|
||||||
//
|
//
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (FvHandles[Index]), FvFileNode);
|
NewDevicePath = AppendDevicePathNode (DevicePathFromHandle (FvHandles[Index]), FvFileNode);
|
||||||
FileBuffer = BmGetFileBufferByFvFilePath (NewDevicePath, FullPath, FileSize);
|
FullPath = BmAdjustFvFilePath (NewDevicePath);
|
||||||
FreePool (NewDevicePath);
|
FreePool (NewDevicePath);
|
||||||
|
if (FullPath != NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FvHandles != NULL) {
|
if (FvHandles != NULL) {
|
||||||
FreePool (FvHandles);
|
FreePool (FvHandles);
|
||||||
}
|
}
|
||||||
return FileBuffer;
|
return FullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -555,46 +547,64 @@ BmFindUsbDevice (
|
|||||||
|
|
||||||
@param FilePath The device path pointing to a load option.
|
@param FilePath The device path pointing to a load option.
|
||||||
It could be a short-form device path.
|
It could be a short-form device path.
|
||||||
@param FullPath Return the full device path of the load option after
|
@param FullPath The full path returned by the routine in last call.
|
||||||
short-form device path expanding.
|
Set to NULL in first call.
|
||||||
Caller is responsible to free it.
|
|
||||||
@param FileSize Return the load option size.
|
|
||||||
@param ShortformNode Pointer to the USB short-form device path node in the FilePath buffer.
|
@param ShortformNode Pointer to the USB short-form device path node in the FilePath buffer.
|
||||||
|
|
||||||
@return The load option buffer. Caller is responsible to free the memory.
|
@return The next possible full path pointing to the load option.
|
||||||
|
Caller is responsible to free the memory.
|
||||||
**/
|
**/
|
||||||
VOID *
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
BmExpandUsbDevicePath (
|
BmExpandUsbDevicePath (
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FullPath,
|
||||||
OUT UINTN *FileSize,
|
IN EFI_DEVICE_PATH_PROTOCOL *ShortformNode
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *ShortformNode
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINTN ParentDevicePathSize;
|
UINTN ParentDevicePathSize;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *NextFullPath;
|
||||||
EFI_HANDLE *Handles;
|
EFI_HANDLE *Handles;
|
||||||
UINTN HandleCount;
|
UINTN HandleCount;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
VOID *FileBuffer;
|
BOOLEAN GetNext;
|
||||||
|
|
||||||
|
NextFullPath = NULL;
|
||||||
|
GetNext = (BOOLEAN)(FullPath == NULL);
|
||||||
ParentDevicePathSize = (UINTN) ShortformNode - (UINTN) FilePath;
|
ParentDevicePathSize = (UINTN) ShortformNode - (UINTN) FilePath;
|
||||||
RemainingDevicePath = NextDevicePathNode (ShortformNode);
|
RemainingDevicePath = NextDevicePathNode (ShortformNode);
|
||||||
FileBuffer = NULL;
|
|
||||||
Handles = BmFindUsbDevice (FilePath, ParentDevicePathSize, &HandleCount);
|
Handles = BmFindUsbDevice (FilePath, ParentDevicePathSize, &HandleCount);
|
||||||
|
|
||||||
for (Index = 0; (Index < HandleCount) && (FileBuffer == NULL); Index++) {
|
for (Index = 0; Index < HandleCount; Index++) {
|
||||||
FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);
|
FilePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);
|
||||||
FileBuffer = EfiBootManagerGetLoadOptionBuffer (FullDevicePath, FullPath, FileSize);
|
if (FilePath == NULL) {
|
||||||
FreePool (FullDevicePath);
|
//
|
||||||
|
// Out of memory.
|
||||||
|
//
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NextFullPath = BmGetNextLoadOptionDevicePath (FilePath, NULL);
|
||||||
|
FreePool (FilePath);
|
||||||
|
if (NextFullPath == NULL) {
|
||||||
|
//
|
||||||
|
// No BlockIo or SimpleFileSystem under FilePath.
|
||||||
|
//
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (GetNext) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);
|
||||||
|
FreePool (NextFullPath);
|
||||||
|
NextFullPath = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Handles != NULL) {
|
if (Handles != NULL) {
|
||||||
FreePool (Handles);
|
FreePool (Handles);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FileBuffer;
|
return NextFullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -602,18 +612,16 @@ BmExpandUsbDevicePath (
|
|||||||
|
|
||||||
@param FilePath The device path pointing to a load option.
|
@param FilePath The device path pointing to a load option.
|
||||||
It could be a short-form device path.
|
It could be a short-form device path.
|
||||||
@param FullPath Return the full device path of the load option after
|
@param FullPath The full path returned by the routine in last call.
|
||||||
short-form device path expanding.
|
Set to NULL in first call.
|
||||||
Caller is responsible to free it.
|
|
||||||
@param FileSize Return the load option size.
|
|
||||||
|
|
||||||
@return The load option buffer. Caller is responsible to free the memory.
|
@return The next possible full path pointing to the load option.
|
||||||
|
Caller is responsible to free the memory.
|
||||||
**/
|
**/
|
||||||
VOID *
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
BmExpandFileDevicePath (
|
BmExpandFileDevicePath (
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FullPath
|
||||||
OUT UINTN *FileSize
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
@ -622,9 +630,8 @@ BmExpandFileDevicePath (
|
|||||||
EFI_HANDLE *Handles;
|
EFI_HANDLE *Handles;
|
||||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||||
UINTN MediaType;
|
UINTN MediaType;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *FullDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *NextFullPath;
|
||||||
VOID *FileBuffer;
|
BOOLEAN GetNext;
|
||||||
UINT32 AuthenticationStatus;
|
|
||||||
|
|
||||||
EfiBootManagerConnectAll ();
|
EfiBootManagerConnectAll ();
|
||||||
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &Handles);
|
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &Handles);
|
||||||
@ -633,6 +640,8 @@ BmExpandFileDevicePath (
|
|||||||
Handles = NULL;
|
Handles = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GetNext = (BOOLEAN)(FullPath == NULL);
|
||||||
|
NextFullPath = NULL;
|
||||||
//
|
//
|
||||||
// Enumerate all removable media devices followed by all fixed media devices,
|
// Enumerate all removable media devices followed by all fixed media devices,
|
||||||
// followed by media devices which don't layer on block io.
|
// followed by media devices which don't layer on block io.
|
||||||
@ -647,62 +656,17 @@ BmExpandFileDevicePath (
|
|||||||
(MediaType == 1 && BlockIo != NULL && !BlockIo->Media->RemovableMedia) ||
|
(MediaType == 1 && BlockIo != NULL && !BlockIo->Media->RemovableMedia) ||
|
||||||
(MediaType == 2 && BlockIo == NULL)
|
(MediaType == 2 && BlockIo == NULL)
|
||||||
) {
|
) {
|
||||||
FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), FilePath);
|
NextFullPath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), FilePath);
|
||||||
FileBuffer = GetFileBufferByFilePath (TRUE, FullDevicePath, FileSize, &AuthenticationStatus);
|
if (GetNext) {
|
||||||
if (FileBuffer != NULL) {
|
break;
|
||||||
*FullPath = FullDevicePath;
|
} else {
|
||||||
FreePool (Handles);
|
GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);
|
||||||
return FileBuffer;
|
FreePool (NextFullPath);
|
||||||
|
NextFullPath = NULL;
|
||||||
}
|
}
|
||||||
FreePool (FullDevicePath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (NextFullPath != NULL) {
|
||||||
|
|
||||||
if (Handles != NULL) {
|
|
||||||
FreePool (Handles);
|
|
||||||
}
|
|
||||||
|
|
||||||
*FullPath = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Expand URI device path node to be full device path in platform.
|
|
||||||
|
|
||||||
@param FilePath The device path pointing to a load option.
|
|
||||||
It could be a short-form device path.
|
|
||||||
@param FullPath Return the full device path of the load option after
|
|
||||||
short-form device path expanding.
|
|
||||||
Caller is responsible to free it.
|
|
||||||
@param FileSize Return the load option size.
|
|
||||||
|
|
||||||
@return The load option buffer. Caller is responsible to free the memory.
|
|
||||||
**/
|
|
||||||
VOID *
|
|
||||||
BmExpandUriDevicePath (
|
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
|
||||||
OUT UINTN *FileSize
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINTN Index;
|
|
||||||
UINTN HandleCount;
|
|
||||||
EFI_HANDLE *Handles;
|
|
||||||
VOID *FileBuffer;
|
|
||||||
|
|
||||||
EfiBootManagerConnectAll ();
|
|
||||||
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &HandleCount, &Handles);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
HandleCount = 0;
|
|
||||||
Handles = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileBuffer = NULL;
|
|
||||||
for (Index = 0; Index < HandleCount; Index++) {
|
|
||||||
FileBuffer = BmGetFileBufferFromLoadFile (Handles[Index], FilePath, FullPath, FileSize);
|
|
||||||
if (FileBuffer != NULL) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -711,7 +675,72 @@ BmExpandUriDevicePath (
|
|||||||
FreePool (Handles);
|
FreePool (Handles);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FileBuffer;
|
return NextFullPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Expand URI device path node to be full device path in platform.
|
||||||
|
|
||||||
|
@param FilePath The device path pointing to a load option.
|
||||||
|
It could be a short-form device path.
|
||||||
|
@param FullPath The full path returned by the routine in last call.
|
||||||
|
Set to NULL in first call.
|
||||||
|
|
||||||
|
@return The next possible full path pointing to the load option.
|
||||||
|
Caller is responsible to free the memory.
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmExpandUriDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FullPath
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
|
UINTN HandleCount;
|
||||||
|
EFI_HANDLE *Handles;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *NextFullPath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;
|
||||||
|
BOOLEAN GetNext;
|
||||||
|
|
||||||
|
EfiBootManagerConnectAll ();
|
||||||
|
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiLoadFileProtocolGuid, NULL, &HandleCount, &Handles);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
HandleCount = 0;
|
||||||
|
Handles = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NextFullPath = NULL;
|
||||||
|
GetNext = (BOOLEAN)(FullPath == NULL);
|
||||||
|
for (Index = 0; Index < HandleCount; Index++) {
|
||||||
|
NextFullPath = BmExpandLoadFile (Handles[Index], FilePath);
|
||||||
|
|
||||||
|
if (NextFullPath == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetNext) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);
|
||||||
|
//
|
||||||
|
// Free the resource occupied by the RAM disk.
|
||||||
|
//
|
||||||
|
RamDiskDevicePath = BmGetRamDiskDevicePath (NextFullPath);
|
||||||
|
if (RamDiskDevicePath != NULL) {
|
||||||
|
BmDestroyRamDisk (RamDiskDevicePath);
|
||||||
|
FreePool (RamDiskDevicePath);
|
||||||
|
}
|
||||||
|
FreePool (NextFullPath);
|
||||||
|
NextFullPath = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Handles != NULL) {
|
||||||
|
FreePool (Handles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextFullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -781,35 +810,28 @@ BmCachePartitionDevicePath (
|
|||||||
|
|
||||||
@param FilePath The device path pointing to a load option.
|
@param FilePath The device path pointing to a load option.
|
||||||
It could be a short-form device path.
|
It could be a short-form device path.
|
||||||
@param FullPath Return the full device path of the load option after
|
|
||||||
short-form device path expanding.
|
|
||||||
Caller is responsible to free it.
|
|
||||||
@param FileSize Return the load option size.
|
|
||||||
|
|
||||||
@return The load option buffer. Caller is responsible to free the memory.
|
@return The full device path pointing to the load option.
|
||||||
**/
|
**/
|
||||||
VOID *
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
BmExpandPartitionDevicePath (
|
BmExpandPartitionDevicePath (
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
|
||||||
OUT UINTN *FileSize
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINTN BlockIoHandleCount;
|
UINTN BlockIoHandleCount;
|
||||||
EFI_HANDLE *BlockIoBuffer;
|
EFI_HANDLE *BlockIoBuffer;
|
||||||
VOID *FileBuffer;
|
|
||||||
EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *CachedDevicePath;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *TempNewDevicePath;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *FullPath;
|
||||||
UINTN CachedDevicePathSize;
|
UINTN CachedDevicePathSize;
|
||||||
BOOLEAN NeedAdjust;
|
BOOLEAN NeedAdjust;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *Instance;
|
EFI_DEVICE_PATH_PROTOCOL *Instance;
|
||||||
UINTN Size;
|
UINTN Size;
|
||||||
|
|
||||||
FileBuffer = NULL;
|
|
||||||
//
|
//
|
||||||
// Check if there is prestore 'HDDP' variable.
|
// Check if there is prestore 'HDDP' variable.
|
||||||
// If exist, search the front path which point to partition node in the variable instants.
|
// If exist, search the front path which point to partition node in the variable instants.
|
||||||
@ -833,6 +855,7 @@ BmExpandPartitionDevicePath (
|
|||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FullPath = NULL;
|
||||||
if (CachedDevicePath != NULL) {
|
if (CachedDevicePath != NULL) {
|
||||||
TempNewDevicePath = CachedDevicePath;
|
TempNewDevicePath = CachedDevicePath;
|
||||||
NeedAdjust = FALSE;
|
NeedAdjust = FALSE;
|
||||||
@ -851,10 +874,20 @@ BmExpandPartitionDevicePath (
|
|||||||
Status = EfiBootManagerConnectDevicePath (Instance, NULL);
|
Status = EfiBootManagerConnectDevicePath (Instance, NULL);
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
TempDevicePath = AppendDevicePath (Instance, NextDevicePathNode (FilePath));
|
TempDevicePath = AppendDevicePath (Instance, NextDevicePathNode (FilePath));
|
||||||
FileBuffer = EfiBootManagerGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);
|
//
|
||||||
|
// TempDevicePath = ACPI()/PCI()/ATA()/Partition()
|
||||||
|
// or = ACPI()/PCI()/ATA()/Partition()/.../A.EFI
|
||||||
|
//
|
||||||
|
// When TempDevicePath = ACPI()/PCI()/ATA()/Partition(),
|
||||||
|
// it may expand to two potienal full paths (nested partition, rarely happen):
|
||||||
|
// 1. ACPI()/PCI()/ATA()/Partition()/Partition(A1)/EFI/BootX64.EFI
|
||||||
|
// 2. ACPI()/PCI()/ATA()/Partition()/Partition(A2)/EFI/BootX64.EFI
|
||||||
|
// For simplicity, only #1 is returned.
|
||||||
|
//
|
||||||
|
FullPath = BmGetNextLoadOptionDevicePath (TempDevicePath, NULL);
|
||||||
FreePool (TempDevicePath);
|
FreePool (TempDevicePath);
|
||||||
|
|
||||||
if (FileBuffer != NULL) {
|
if (FullPath != NULL) {
|
||||||
//
|
//
|
||||||
// Adjust the 'HDDP' instances sequence if the matched one is not first one.
|
// Adjust the 'HDDP' instances sequence if the matched one is not first one.
|
||||||
//
|
//
|
||||||
@ -875,7 +908,7 @@ BmExpandPartitionDevicePath (
|
|||||||
|
|
||||||
FreePool (Instance);
|
FreePool (Instance);
|
||||||
FreePool (CachedDevicePath);
|
FreePool (CachedDevicePath);
|
||||||
return FileBuffer;
|
return FullPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -911,10 +944,10 @@ BmExpandPartitionDevicePath (
|
|||||||
// Find the matched partition device path
|
// Find the matched partition device path
|
||||||
//
|
//
|
||||||
TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));
|
TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));
|
||||||
FileBuffer = EfiBootManagerGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);
|
FullPath = BmGetNextLoadOptionDevicePath (TempDevicePath, NULL);
|
||||||
FreePool (TempDevicePath);
|
FreePool (TempDevicePath);
|
||||||
|
|
||||||
if (FileBuffer != NULL) {
|
if (FullPath != NULL) {
|
||||||
BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);
|
BmCachePartitionDevicePath (&CachedDevicePath, BlockIoDevicePath);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -940,7 +973,7 @@ BmExpandPartitionDevicePath (
|
|||||||
if (BlockIoBuffer != NULL) {
|
if (BlockIoBuffer != NULL) {
|
||||||
FreePool (BlockIoBuffer);
|
FreePool (BlockIoBuffer);
|
||||||
}
|
}
|
||||||
return FileBuffer;
|
return FullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -948,16 +981,16 @@ BmExpandPartitionDevicePath (
|
|||||||
by appending EFI_REMOVABLE_MEDIA_FILE_NAME.
|
by appending EFI_REMOVABLE_MEDIA_FILE_NAME.
|
||||||
|
|
||||||
@param DevicePath The media device path pointing to a BlockIo or SimpleFileSystem instance.
|
@param DevicePath The media device path pointing to a BlockIo or SimpleFileSystem instance.
|
||||||
@param FullPath Return the full device path pointing to the load option.
|
@param FullPath The full path returned by the routine in last call.
|
||||||
@param FileSize Return the size of the load option.
|
Set to NULL in first call.
|
||||||
|
|
||||||
@return The load option buffer.
|
@return The next possible full path pointing to the load option.
|
||||||
|
Caller is responsible to free the memory.
|
||||||
**/
|
**/
|
||||||
VOID *
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
BmExpandMediaDevicePath (
|
BmExpandMediaDevicePath (
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FullPath
|
||||||
OUT UINTN *FileSize
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
@ -965,14 +998,15 @@ BmExpandMediaDevicePath (
|
|||||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||||
VOID *Buffer;
|
VOID *Buffer;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *NextFullPath;
|
||||||
UINTN Size;
|
UINTN Size;
|
||||||
UINTN TempSize;
|
UINTN TempSize;
|
||||||
EFI_HANDLE *SimpleFileSystemHandles;
|
EFI_HANDLE *SimpleFileSystemHandles;
|
||||||
UINTN NumberSimpleFileSystemHandles;
|
UINTN NumberSimpleFileSystemHandles;
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
VOID *FileBuffer;
|
BOOLEAN GetNext;
|
||||||
UINT32 AuthenticationStatus;
|
|
||||||
|
|
||||||
|
GetNext = (BOOLEAN)(FullPath == NULL);
|
||||||
//
|
//
|
||||||
// Check whether the device is connected
|
// Check whether the device is connected
|
||||||
//
|
//
|
||||||
@ -981,14 +1015,16 @@ BmExpandMediaDevicePath (
|
|||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
ASSERT (IsDevicePathEnd (TempDevicePath));
|
ASSERT (IsDevicePathEnd (TempDevicePath));
|
||||||
|
|
||||||
TempDevicePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);
|
NextFullPath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME);
|
||||||
FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);
|
//
|
||||||
if (FileBuffer == NULL) {
|
// For device path pointing to simple file system, it only expands to one full path.
|
||||||
FreePool (TempDevicePath);
|
//
|
||||||
TempDevicePath = NULL;
|
if (GetNext) {
|
||||||
|
return NextFullPath;
|
||||||
|
} else {
|
||||||
|
FreePool (NextFullPath);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
*FullPath = TempDevicePath;
|
|
||||||
return FileBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);
|
Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);
|
||||||
@ -1025,8 +1061,7 @@ BmExpandMediaDevicePath (
|
|||||||
//
|
//
|
||||||
// Detect the the default boot file from removable Media
|
// Detect the the default boot file from removable Media
|
||||||
//
|
//
|
||||||
FileBuffer = NULL;
|
NextFullPath = NULL;
|
||||||
*FullPath = NULL;
|
|
||||||
Size = GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH;
|
Size = GetDevicePathSize (DevicePath) - END_DEVICE_PATH_LENGTH;
|
||||||
gBS->LocateHandleBuffer (
|
gBS->LocateHandleBuffer (
|
||||||
ByProtocol,
|
ByProtocol,
|
||||||
@ -1045,13 +1080,14 @@ BmExpandMediaDevicePath (
|
|||||||
// Check whether the device path of boot option is part of the SimpleFileSystem handle's device path
|
// Check whether the device path of boot option is part of the SimpleFileSystem handle's device path
|
||||||
//
|
//
|
||||||
if ((Size <= TempSize) && (CompareMem (TempDevicePath, DevicePath, Size) == 0)) {
|
if ((Size <= TempSize) && (CompareMem (TempDevicePath, DevicePath, Size) == 0)) {
|
||||||
TempDevicePath = FileDevicePath (SimpleFileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);
|
NextFullPath = FileDevicePath (SimpleFileSystemHandles[Index], EFI_REMOVABLE_MEDIA_FILE_NAME);
|
||||||
FileBuffer = GetFileBufferByFilePath (TRUE, TempDevicePath, FileSize, &AuthenticationStatus);
|
if (GetNext) {
|
||||||
if (FileBuffer != NULL) {
|
|
||||||
*FullPath = TempDevicePath;
|
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
GetNext = (BOOLEAN)(CompareMem (NextFullPath, FullPath, GetDevicePathSize (NextFullPath)) == 0);
|
||||||
|
FreePool (NextFullPath);
|
||||||
|
NextFullPath = NULL;
|
||||||
}
|
}
|
||||||
FreePool (TempDevicePath);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1059,7 +1095,7 @@ BmExpandMediaDevicePath (
|
|||||||
FreePool (SimpleFileSystemHandles);
|
FreePool (SimpleFileSystemHandles);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FileBuffer;
|
return NextFullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1098,17 +1134,14 @@ BmMatchHttpBootDevicePath (
|
|||||||
Get the file buffer from the file system produced by Load File instance.
|
Get the file buffer from the file system produced by Load File instance.
|
||||||
|
|
||||||
@param LoadFileHandle The handle of LoadFile instance.
|
@param LoadFileHandle The handle of LoadFile instance.
|
||||||
@param FullPath Return the full device path pointing to the load option.
|
|
||||||
@param FileSize Return the size of the load option.
|
|
||||||
@param RamDiskHandle Return the RAM Disk handle.
|
@param RamDiskHandle Return the RAM Disk handle.
|
||||||
|
|
||||||
@return The load option buffer.
|
@return The next possible full path pointing to the load option.
|
||||||
|
Caller is responsible to free the memory.
|
||||||
**/
|
**/
|
||||||
VOID *
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
BmGetFileBufferFromLoadFileSystem (
|
BmExpandNetworkFileSystem (
|
||||||
IN EFI_HANDLE LoadFileHandle,
|
IN EFI_HANDLE LoadFileHandle,
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
|
||||||
OUT UINTN *FileSize,
|
|
||||||
OUT EFI_HANDLE *RamDiskHandle
|
OUT EFI_HANDLE *RamDiskHandle
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -1138,6 +1171,9 @@ BmGetFileBufferFromLoadFileSystem (
|
|||||||
if (!EFI_ERROR (Status) &&
|
if (!EFI_ERROR (Status) &&
|
||||||
(Handle == LoadFileHandle) &&
|
(Handle == LoadFileHandle) &&
|
||||||
(DevicePathType (Node) == MEDIA_DEVICE_PATH) && (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)) {
|
(DevicePathType (Node) == MEDIA_DEVICE_PATH) && (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)) {
|
||||||
|
//
|
||||||
|
// Find the BlockIo instance populated from the LoadFile.
|
||||||
|
//
|
||||||
Handle = Handles[Index];
|
Handle = Handles[Index];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1154,13 +1190,16 @@ BmGetFileBufferFromLoadFileSystem (
|
|||||||
*RamDiskHandle = Handle;
|
*RamDiskHandle = Handle;
|
||||||
|
|
||||||
if (Handle != NULL) {
|
if (Handle != NULL) {
|
||||||
return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), FullPath, FileSize);
|
//
|
||||||
|
// Re-use BmExpandMediaDevicePath() to get the full device path of load option.
|
||||||
|
// But assume only one SimpleFileSystem can be found under the BlockIo.
|
||||||
|
//
|
||||||
|
return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), NULL);
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Return the RAM Disk device path created by LoadFile.
|
Return the RAM Disk device path created by LoadFile.
|
||||||
|
|
||||||
@ -1274,27 +1313,21 @@ BmDestroyRamDisk (
|
|||||||
|
|
||||||
@param LoadFileHandle The specified Load File instance.
|
@param LoadFileHandle The specified Load File instance.
|
||||||
@param FilePath The file path which will pass to LoadFile().
|
@param FilePath The file path which will pass to LoadFile().
|
||||||
@param FullPath Return the full device path pointing to the load option.
|
|
||||||
@param FileSize Return the size of the load option.
|
|
||||||
|
|
||||||
@return The load option buffer or NULL if fails.
|
@return The full device path pointing to the load option buffer.
|
||||||
**/
|
**/
|
||||||
VOID *
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
BmGetFileBufferFromLoadFile (
|
BmExpandLoadFile (
|
||||||
IN EFI_HANDLE LoadFileHandle,
|
IN EFI_HANDLE LoadFileHandle,
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
|
||||||
OUT UINTN *FileSize
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_LOAD_FILE_PROTOCOL *LoadFile;
|
EFI_LOAD_FILE_PROTOCOL *LoadFile;
|
||||||
VOID *FileBuffer;
|
VOID *FileBuffer;
|
||||||
BOOLEAN LoadFileSystem;
|
|
||||||
EFI_HANDLE RamDiskHandle;
|
EFI_HANDLE RamDiskHandle;
|
||||||
UINTN BufferSize;
|
UINTN BufferSize;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *FullPath;
|
||||||
*FileSize = 0;
|
|
||||||
|
|
||||||
Status = gBS->OpenProtocol (
|
Status = gBS->OpenProtocol (
|
||||||
LoadFileHandle,
|
LoadFileHandle,
|
||||||
@ -1313,52 +1346,60 @@ BmGetFileBufferFromLoadFile (
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadFileSystem = (BOOLEAN) (Status == EFI_WARN_FILE_SYSTEM);
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||||
FileBuffer = LoadFileSystem ? AllocateReservedPages (EFI_SIZE_TO_PAGES (BufferSize)) : AllocatePool (BufferSize);
|
//
|
||||||
|
// The load option buffer is directly returned by LoadFile.
|
||||||
|
//
|
||||||
|
return DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle));
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The load option resides in a RAM disk.
|
||||||
|
//
|
||||||
|
FileBuffer = AllocateReservedPages (EFI_SIZE_TO_PAGES (BufferSize));
|
||||||
if (FileBuffer == NULL) {
|
if (FileBuffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);
|
Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
if (LoadFileSystem) {
|
FreePages (FileBuffer, EFI_SIZE_TO_PAGES (BufferSize));
|
||||||
FreePages (FileBuffer, EFI_SIZE_TO_PAGES (BufferSize));
|
|
||||||
} else {
|
|
||||||
FreePool (FileBuffer);
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LoadFileSystem) {
|
FullPath = BmExpandNetworkFileSystem (LoadFileHandle, &RamDiskHandle);
|
||||||
FileBuffer = BmGetFileBufferFromLoadFileSystem (LoadFileHandle, FullPath, FileSize, &RamDiskHandle);
|
if (FullPath == NULL) {
|
||||||
if (FileBuffer == NULL) {
|
//
|
||||||
//
|
// Free the memory occupied by the RAM disk if there is no BlockIo or SimpleFileSystem instance.
|
||||||
// If there is no bootable executable in the populated
|
//
|
||||||
//
|
BmDestroyRamDisk (DevicePathFromHandle (RamDiskHandle));
|
||||||
BmDestroyRamDisk (DevicePathFromHandle (RamDiskHandle));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*FileSize = BufferSize;
|
|
||||||
*FullPath = DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FileBuffer;
|
return FullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the file buffer from all the Load File instances.
|
Return the full device path pointing to the load option.
|
||||||
|
|
||||||
|
FilePath may:
|
||||||
|
1. Exactly matches to a LoadFile instance.
|
||||||
|
2. Cannot match to any LoadFile instance. Wide match is required.
|
||||||
|
In either case, the routine may return:
|
||||||
|
1. A copy of FilePath when FilePath matches to a LoadFile instance and
|
||||||
|
the LoadFile returns a load option buffer.
|
||||||
|
2. A new device path with IP and URI information updated when wide match
|
||||||
|
happens.
|
||||||
|
3. A new device path pointing to a load option in RAM disk.
|
||||||
|
In either case, only one full device path is returned for a specified
|
||||||
|
FilePath.
|
||||||
|
|
||||||
@param FilePath The media device path pointing to a LoadFile instance.
|
@param FilePath The media device path pointing to a LoadFile instance.
|
||||||
@param FullPath Return the full device path pointing to the load option.
|
|
||||||
@param FileSize Return the size of the load option.
|
|
||||||
|
|
||||||
@return The load option buffer.
|
@return The load option buffer.
|
||||||
**/
|
**/
|
||||||
VOID *
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
BmGetFileBufferFromLoadFiles (
|
BmExpandLoadFiles (
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
|
||||||
OUT UINTN *FileSize
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
@ -1411,7 +1452,7 @@ BmGetFileBufferFromLoadFiles (
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return BmGetFileBufferFromLoadFile (Handle, FilePath, FullPath, FileSize);
|
return BmExpandLoadFile (Handle, FilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1433,20 +1474,38 @@ EfiBootManagerGetLoadOptionBuffer (
|
|||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
||||||
OUT UINTN *FileSize
|
OUT UINTN *FileSize
|
||||||
)
|
)
|
||||||
|
{
|
||||||
|
*FullPath = NULL;
|
||||||
|
|
||||||
|
EfiBootManagerConnectDevicePath (FilePath, NULL);
|
||||||
|
return BmGetNextLoadOptionBuffer (LoadOptionTypeMax, FilePath, FullPath, FileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the next possible full path pointing to the load option.
|
||||||
|
The routine doesn't guarantee the returned full path points to an existing
|
||||||
|
file, and it also doesn't guarantee the existing file is a valid load option.
|
||||||
|
BmGetNextLoadOptionBuffer() guarantees.
|
||||||
|
|
||||||
|
@param FilePath The device path pointing to a load option.
|
||||||
|
It could be a short-form device path.
|
||||||
|
@param FullPath The full path returned by the routine in last call.
|
||||||
|
Set to NULL in first call.
|
||||||
|
|
||||||
|
@return The next possible full path pointing to the load option.
|
||||||
|
Caller is responsible to free the memory.
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmGetNextLoadOptionDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FullPath
|
||||||
|
)
|
||||||
{
|
{
|
||||||
EFI_HANDLE Handle;
|
EFI_HANDLE Handle;
|
||||||
VOID *FileBuffer;
|
|
||||||
UINT32 AuthenticationStatus;
|
|
||||||
EFI_DEVICE_PATH_PROTOCOL *Node;
|
EFI_DEVICE_PATH_PROTOCOL *Node;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
|
||||||
ASSERT ((FilePath != NULL) && (FullPath != NULL) && (FileSize != NULL));
|
ASSERT (FilePath != NULL);
|
||||||
|
|
||||||
EfiBootManagerConnectDevicePath (FilePath, NULL);
|
|
||||||
|
|
||||||
*FullPath = NULL;
|
|
||||||
*FileSize = 0;
|
|
||||||
FileBuffer = NULL;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Boot from media device by adding a default file name \EFI\BOOT\BOOT{machine type short-name}.EFI
|
// Boot from media device by adding a default file name \EFI\BOOT\BOOT{machine type short-name}.EFI
|
||||||
@ -1458,7 +1517,7 @@ EfiBootManagerGetLoadOptionBuffer (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {
|
if (!EFI_ERROR (Status) && IsDevicePathEnd (Node)) {
|
||||||
return BmExpandMediaDevicePath (FilePath, FullPath, FileSize);
|
return BmExpandMediaDevicePath (FilePath, FullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1469,19 +1528,23 @@ EfiBootManagerGetLoadOptionBuffer (
|
|||||||
//
|
//
|
||||||
// Expand the Harddrive device path
|
// Expand the Harddrive device path
|
||||||
//
|
//
|
||||||
return BmExpandPartitionDevicePath (FilePath, FullPath, FileSize);
|
if (FullPath == NULL) {
|
||||||
|
return BmExpandPartitionDevicePath (FilePath);
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
} else if ((DevicePathType (FilePath) == MEDIA_DEVICE_PATH) &&
|
} else if ((DevicePathType (FilePath) == MEDIA_DEVICE_PATH) &&
|
||||||
(DevicePathSubType (FilePath) == MEDIA_FILEPATH_DP)) {
|
(DevicePathSubType (FilePath) == MEDIA_FILEPATH_DP)) {
|
||||||
//
|
//
|
||||||
// Expand the File-path device path
|
// Expand the File-path device path
|
||||||
//
|
//
|
||||||
return BmExpandFileDevicePath (FilePath, FullPath, FileSize);
|
return BmExpandFileDevicePath (FilePath, FullPath);
|
||||||
} else if ((DevicePathType (FilePath) == MESSAGING_DEVICE_PATH) &&
|
} else if ((DevicePathType (FilePath) == MESSAGING_DEVICE_PATH) &&
|
||||||
(DevicePathSubType (FilePath) == MSG_URI_DP)) {
|
(DevicePathSubType (FilePath) == MSG_URI_DP)) {
|
||||||
//
|
//
|
||||||
// Expand the URI device path
|
// Expand the URI device path
|
||||||
//
|
//
|
||||||
return BmExpandUriDevicePath (FilePath, FullPath, FileSize);
|
return BmExpandUriDevicePath (FilePath, FullPath);
|
||||||
} else {
|
} else {
|
||||||
for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
|
for (Node = FilePath; !IsDevicePathEnd (Node); Node = NextDevicePathNode (Node)) {
|
||||||
if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&
|
if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) &&
|
||||||
@ -1490,45 +1553,50 @@ EfiBootManagerGetLoadOptionBuffer (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Expand the USB WWID/Class device path
|
||||||
|
//
|
||||||
if (!IsDevicePathEnd (Node)) {
|
if (!IsDevicePathEnd (Node)) {
|
||||||
//
|
if (FilePath == Node) {
|
||||||
// Expand the USB WWID/Class device path
|
|
||||||
//
|
|
||||||
FileBuffer = BmExpandUsbDevicePath (FilePath, FullPath, FileSize, Node);
|
|
||||||
if ((FileBuffer == NULL) && (FilePath == Node)) {
|
|
||||||
//
|
//
|
||||||
// Boot Option device path starts with USB Class or USB WWID device path.
|
// Boot Option device path starts with USB Class or USB WWID device path.
|
||||||
// For Boot Option device path which doesn't begin with the USB Class or
|
// For Boot Option device path which doesn't begin with the USB Class or
|
||||||
// USB WWID device path, it's not needed to connect again here.
|
// USB WWID device path, it's not needed to connect again here.
|
||||||
//
|
//
|
||||||
BmConnectUsbShortFormDevicePath (FilePath);
|
BmConnectUsbShortFormDevicePath (FilePath);
|
||||||
FileBuffer = BmExpandUsbDevicePath (FilePath, FullPath, FileSize, Node);
|
|
||||||
}
|
}
|
||||||
return FileBuffer;
|
return BmExpandUsbDevicePath (FilePath, FullPath, Node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get file buffer from FV file path.
|
// For the below cases, FilePath only expands to one Full path.
|
||||||
|
// So just handle the case when FullPath == NULL.
|
||||||
//
|
//
|
||||||
if (BmIsFvFilePath (FilePath)) {
|
if (FullPath != NULL) {
|
||||||
return BmGetFileBufferByFvFilePath (FilePath, FullPath, FileSize);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get file buffer from simple file system.
|
// Load option resides in FV.
|
||||||
|
//
|
||||||
|
if (BmIsFvFilePath (FilePath)) {
|
||||||
|
return BmAdjustFvFilePath (FilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Load option resides in Simple File System.
|
||||||
//
|
//
|
||||||
Node = FilePath;
|
Node = FilePath;
|
||||||
Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &Node, &Handle);
|
Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid, &Node, &Handle);
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
FileBuffer = GetFileBufferByFilePath (TRUE, FilePath, FileSize, &AuthenticationStatus);
|
return DuplicateDevicePath (FilePath);
|
||||||
if (FileBuffer != NULL) {
|
|
||||||
*FullPath = DuplicateDevicePath (FilePath);
|
|
||||||
}
|
|
||||||
return FileBuffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return BmGetFileBufferFromLoadFiles (FilePath, FullPath, FileSize);
|
//
|
||||||
|
// Last chance to try: Load option may be loaded through LoadFile.
|
||||||
|
//
|
||||||
|
return BmExpandLoadFiles (FilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1686,21 +1754,13 @@ EfiBootManagerBoot (
|
|||||||
ImageHandle = NULL;
|
ImageHandle = NULL;
|
||||||
RamDiskDevicePath = NULL;
|
RamDiskDevicePath = NULL;
|
||||||
if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {
|
if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {
|
||||||
Status = EFI_NOT_FOUND;
|
Status = EFI_NOT_FOUND;
|
||||||
FileBuffer = EfiBootManagerGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);
|
FilePath = NULL;
|
||||||
|
EfiBootManagerConnectDevicePath (BootOption->FilePath, NULL);
|
||||||
|
FileBuffer = BmGetNextLoadOptionBuffer (LoadOptionTypeBoot, BootOption->FilePath, &FilePath, &FileSize);
|
||||||
if (FileBuffer != NULL) {
|
if (FileBuffer != NULL) {
|
||||||
RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);
|
RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);
|
||||||
}
|
|
||||||
DEBUG_CODE (
|
|
||||||
if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {
|
|
||||||
DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));
|
|
||||||
BmPrintDp (BootOption->FilePath);
|
|
||||||
DEBUG ((EFI_D_INFO, " -> "));
|
|
||||||
BmPrintDp (FilePath);
|
|
||||||
DEBUG ((EFI_D_INFO, "\n"));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (BmIsLoadOptionPeHeaderValid (BootOption->OptionType, FileBuffer, FileSize)) {
|
|
||||||
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));
|
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdProgressCodeOsLoaderLoad));
|
||||||
Status = gBS->LoadImage (
|
Status = gBS->LoadImage (
|
||||||
TRUE,
|
TRUE,
|
||||||
|
@ -1167,6 +1167,10 @@ EfiBootManagerFreeLoadOptions (
|
|||||||
Return whether the PE header of the load option is valid or not.
|
Return whether the PE header of the load option is valid or not.
|
||||||
|
|
||||||
@param[in] Type The load option type.
|
@param[in] Type The load option type.
|
||||||
|
It's used to check whether the load option is valid.
|
||||||
|
When it's LoadOptionTypeMax, the routine only guarantees
|
||||||
|
the load option is a valid PE image but doesn't guarantee
|
||||||
|
the PE's subsystem type is valid.
|
||||||
@param[in] FileBuffer The PE file buffer of the load option.
|
@param[in] FileBuffer The PE file buffer of the load option.
|
||||||
@param[in] FileSize The size of the load option file.
|
@param[in] FileSize The size of the load option file.
|
||||||
|
|
||||||
@ -1217,7 +1221,8 @@ BmIsLoadOptionPeHeaderValid (
|
|||||||
// SysPrep####, Boot####, OsRecovery####, PlatformRecovery#### must be of type Application
|
// SysPrep####, Boot####, OsRecovery####, PlatformRecovery#### must be of type Application
|
||||||
//
|
//
|
||||||
Subsystem = OptionalHeader->Subsystem;
|
Subsystem = OptionalHeader->Subsystem;
|
||||||
if ((Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
|
if ((Type == LoadOptionTypeMax) ||
|
||||||
|
(Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
|
||||||
(Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ||
|
(Type == LoadOptionTypeDriver && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ||
|
||||||
(Type == LoadOptionTypeSysPrep && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
|
(Type == LoadOptionTypeSysPrep && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
|
||||||
(Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
|
(Type == LoadOptionTypeBoot && Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) ||
|
||||||
@ -1232,6 +1237,91 @@ BmIsLoadOptionPeHeaderValid (
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the next matched load option buffer.
|
||||||
|
The routine keeps calling BmGetNextLoadOptionDevicePath() until a valid
|
||||||
|
load option is read.
|
||||||
|
|
||||||
|
@param Type The load option type.
|
||||||
|
It's used to check whether the load option is valid.
|
||||||
|
When it's LoadOptionTypeMax, the routine only guarantees
|
||||||
|
the load option is a valid PE image but doesn't guarantee
|
||||||
|
the PE's subsystem type is valid.
|
||||||
|
@param FilePath The device path pointing to a load option.
|
||||||
|
It could be a short-form device path.
|
||||||
|
@param FullPath Return the next full device path of the load option after
|
||||||
|
short-form device path expanding.
|
||||||
|
Caller is responsible to free it.
|
||||||
|
NULL to return the first matched full device path.
|
||||||
|
@param FileSize Return the load option size.
|
||||||
|
|
||||||
|
@return The load option buffer. Caller is responsible to free the memory.
|
||||||
|
**/
|
||||||
|
VOID *
|
||||||
|
BmGetNextLoadOptionBuffer (
|
||||||
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
||||||
|
OUT UINTN *FileSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
VOID *FileBuffer;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *PreFullPath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *CurFullPath;
|
||||||
|
UINTN LocalFileSize;
|
||||||
|
UINT32 AuthenticationStatus;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;
|
||||||
|
|
||||||
|
LocalFileSize = 0;
|
||||||
|
FileBuffer = NULL;
|
||||||
|
CurFullPath = *FullPath;
|
||||||
|
do {
|
||||||
|
PreFullPath = CurFullPath;
|
||||||
|
CurFullPath = BmGetNextLoadOptionDevicePath (FilePath, CurFullPath);
|
||||||
|
//
|
||||||
|
// Only free the full path created *inside* this routine
|
||||||
|
//
|
||||||
|
if ((PreFullPath != NULL) && (PreFullPath != *FullPath)) {
|
||||||
|
FreePool (PreFullPath);
|
||||||
|
}
|
||||||
|
if (CurFullPath == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FileBuffer = GetFileBufferByFilePath (TRUE, CurFullPath, &LocalFileSize, &AuthenticationStatus);
|
||||||
|
if ((FileBuffer != NULL) && !BmIsLoadOptionPeHeaderValid (Type, FileBuffer, LocalFileSize)) {
|
||||||
|
//
|
||||||
|
// Free the RAM disk file system if the load option is invalid.
|
||||||
|
//
|
||||||
|
RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);
|
||||||
|
if (RamDiskDevicePath != NULL) {
|
||||||
|
BmDestroyRamDisk (RamDiskDevicePath);
|
||||||
|
FreePool (RamDiskDevicePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free the invalid load option buffer.
|
||||||
|
//
|
||||||
|
FreePool (FileBuffer);
|
||||||
|
FileBuffer = NULL;
|
||||||
|
}
|
||||||
|
} while (FileBuffer == NULL);
|
||||||
|
|
||||||
|
if (FileBuffer == NULL) {
|
||||||
|
CurFullPath = NULL;
|
||||||
|
LocalFileSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "[Bds] Expand "));
|
||||||
|
BmPrintDp (FilePath);
|
||||||
|
DEBUG ((DEBUG_INFO, " -> "));
|
||||||
|
BmPrintDp (CurFullPath);
|
||||||
|
DEBUG ((DEBUG_INFO, "\n"));
|
||||||
|
|
||||||
|
*FullPath = CurFullPath;
|
||||||
|
*FileSize = LocalFileSize;
|
||||||
|
return FileBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Process (load and execute) the load option.
|
Process (load and execute) the load option.
|
||||||
|
|
||||||
@ -1249,7 +1339,8 @@ EfiBootManagerProcessLoadOption (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
EFI_DEVICE_PATH_PROTOCOL *FilePath;
|
EFI_DEVICE_PATH_PROTOCOL *PreFullPath;
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *CurFullPath;
|
||||||
EFI_HANDLE ImageHandle;
|
EFI_HANDLE ImageHandle;
|
||||||
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
|
EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;
|
||||||
VOID *FileBuffer;
|
VOID *FileBuffer;
|
||||||
@ -1271,8 +1362,6 @@ EfiBootManagerProcessLoadOption (
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = EFI_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Load and start the load option.
|
// Load and start the load option.
|
||||||
//
|
//
|
||||||
@ -1282,54 +1371,62 @@ EfiBootManagerProcessLoadOption (
|
|||||||
LoadOption->Description
|
LoadOption->Description
|
||||||
));
|
));
|
||||||
ImageHandle = NULL;
|
ImageHandle = NULL;
|
||||||
FileBuffer = EfiBootManagerGetLoadOptionBuffer (LoadOption->FilePath, &FilePath, &FileSize);
|
CurFullPath = NULL;
|
||||||
DEBUG_CODE (
|
EfiBootManagerConnectDevicePath (LoadOption->FilePath, NULL);
|
||||||
if (FileBuffer != NULL && CompareMem (LoadOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {
|
|
||||||
DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));
|
//
|
||||||
BmPrintDp (LoadOption->FilePath);
|
// while() loop is to keep starting next matched load option if the PlatformRecovery#### returns failure status.
|
||||||
DEBUG ((EFI_D_INFO, " -> "));
|
//
|
||||||
BmPrintDp (FilePath);
|
while (TRUE) {
|
||||||
DEBUG ((EFI_D_INFO, "\n"));
|
Status = EFI_INVALID_PARAMETER;
|
||||||
|
PreFullPath = CurFullPath;
|
||||||
|
FileBuffer = BmGetNextLoadOptionBuffer (LoadOption->OptionType, LoadOption->FilePath, &CurFullPath, &FileSize);
|
||||||
|
if (PreFullPath != NULL) {
|
||||||
|
FreePool (PreFullPath);
|
||||||
|
}
|
||||||
|
if (FileBuffer == NULL) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
if (BmIsLoadOptionPeHeaderValid (LoadOption->OptionType, FileBuffer, FileSize)) {
|
|
||||||
Status = gBS->LoadImage (
|
Status = gBS->LoadImage (
|
||||||
FALSE,
|
FALSE,
|
||||||
gImageHandle,
|
gImageHandle,
|
||||||
FilePath,
|
CurFullPath,
|
||||||
FileBuffer,
|
FileBuffer,
|
||||||
FileSize,
|
FileSize,
|
||||||
&ImageHandle
|
&ImageHandle
|
||||||
);
|
);
|
||||||
}
|
|
||||||
if (FilePath != NULL) {
|
|
||||||
FreePool (FilePath);
|
|
||||||
}
|
|
||||||
if (FileBuffer != NULL) {
|
|
||||||
FreePool (FileBuffer);
|
FreePool (FileBuffer);
|
||||||
}
|
|
||||||
|
|
||||||
if (!EFI_ERROR (Status)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);
|
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&ImageInfo);
|
||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
ImageInfo->LoadOptionsSize = LoadOption->OptionalDataSize;
|
ImageInfo->LoadOptionsSize = LoadOption->OptionalDataSize;
|
||||||
ImageInfo->LoadOptions = LoadOption->OptionalData;
|
ImageInfo->LoadOptions = LoadOption->OptionalData;
|
||||||
//
|
//
|
||||||
// Before calling the image, enable the Watchdog Timer for the 5-minute period
|
// Before calling the image, enable the Watchdog Timer for the 5-minute period
|
||||||
//
|
//
|
||||||
gBS->SetWatchdogTimer (5 * 60, 0, 0, NULL);
|
gBS->SetWatchdogTimer (5 * 60, 0, 0, NULL);
|
||||||
|
|
||||||
LoadOption->Status = gBS->StartImage (ImageHandle, &LoadOption->ExitDataSize, &LoadOption->ExitData);
|
LoadOption->Status = gBS->StartImage (ImageHandle, &LoadOption->ExitDataSize, &LoadOption->ExitData);
|
||||||
DEBUG ((
|
DEBUG ((
|
||||||
DEBUG_INFO | DEBUG_LOAD, "%s%04x Return Status = %r\n",
|
DEBUG_INFO | DEBUG_LOAD, "%s%04x Return Status = %r\n",
|
||||||
mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber, LoadOption->Status
|
mBmLoadOptionName[LoadOption->OptionType], LoadOption->OptionNumber, LoadOption->Status
|
||||||
));
|
));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clear the Watchdog Timer after the image returns
|
// Clear the Watchdog Timer after the image returns
|
||||||
//
|
//
|
||||||
gBS->SetWatchdogTimer (0, 0, 0, NULL);
|
gBS->SetWatchdogTimer (0, 0, 0, NULL);
|
||||||
|
|
||||||
|
if ((LoadOption->OptionType != LoadOptionTypePlatformRecovery) || (LoadOption->Status == EFI_SUCCESS)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurFullPath != NULL) {
|
||||||
|
FreePool (CurFullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
|
@ -309,23 +309,6 @@ BmSetVariableAndReportStatusCodeOnError (
|
|||||||
IN VOID *Data
|
IN VOID *Data
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
Return whether the PE header of the load option is valid or not.
|
|
||||||
|
|
||||||
@param[in] Type The load option type.
|
|
||||||
@param[in] FileBuffer The PE file buffer of the load option.
|
|
||||||
@param[in] FileSize The size of the load option file.
|
|
||||||
|
|
||||||
@retval TRUE The PE header of the load option is valid.
|
|
||||||
@retval FALSE The PE header of the load option is not valid.
|
|
||||||
**/
|
|
||||||
BOOLEAN
|
|
||||||
BmIsLoadOptionPeHeaderValid (
|
|
||||||
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
|
|
||||||
IN VOID *FileBuffer,
|
|
||||||
IN UINTN FileSize
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Function compares a device path data structure to that of all the nodes of a
|
Function compares a device path data structure to that of all the nodes of a
|
||||||
second device path instance.
|
second device path instance.
|
||||||
@ -425,16 +408,83 @@ BmMakeBootOptionDescriptionUnique (
|
|||||||
|
|
||||||
@param LoadFileHandle The specified Load File instance.
|
@param LoadFileHandle The specified Load File instance.
|
||||||
@param FilePath The file path which will pass to LoadFile().
|
@param FilePath The file path which will pass to LoadFile().
|
||||||
@param FullPath Return the full device path pointing to the load option.
|
|
||||||
@param FileSize Return the size of the load option.
|
|
||||||
|
|
||||||
@return The load option buffer or NULL if fails.
|
@return The full device path pointing to the load option buffer.
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmExpandLoadFile (
|
||||||
|
IN EFI_HANDLE LoadFileHandle,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the RAM Disk device path created by LoadFile.
|
||||||
|
|
||||||
|
@param FilePath The source file path.
|
||||||
|
|
||||||
|
@return Callee-to-free RAM Disk device path
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmGetRamDiskDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Destroy the RAM Disk.
|
||||||
|
|
||||||
|
The destroy operation includes to call RamDisk.Unregister to
|
||||||
|
unregister the RAM DISK from RAM DISK driver, free the memory
|
||||||
|
allocated for the RAM Disk.
|
||||||
|
|
||||||
|
@param RamDiskDevicePath RAM Disk device path.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
BmDestroyRamDisk (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the next possible full path pointing to the load option.
|
||||||
|
|
||||||
|
@param FilePath The device path pointing to a load option.
|
||||||
|
It could be a short-form device path.
|
||||||
|
@param FullPath The full path returned by the routine in last call.
|
||||||
|
Set to NULL in first call.
|
||||||
|
|
||||||
|
@return The next possible full path pointing to the load option.
|
||||||
|
Caller is responsible to free the memory.
|
||||||
|
**/
|
||||||
|
EFI_DEVICE_PATH_PROTOCOL *
|
||||||
|
BmGetNextLoadOptionDevicePath (
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
|
IN EFI_DEVICE_PATH_PROTOCOL *FullPath
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the next matched load option buffer.
|
||||||
|
The routine keeps calling BmGetNextLoadOptionDevicePath() until a valid
|
||||||
|
load option is read.
|
||||||
|
|
||||||
|
@param Type The load option type.
|
||||||
|
It's used to check whether the load option is valid.
|
||||||
|
When it's LoadOptionTypeMax, the routine only guarantees
|
||||||
|
the load option is a valid PE image but doesn't guarantee
|
||||||
|
the PE's subsystem type is valid.
|
||||||
|
@param FilePath The device path pointing to a load option.
|
||||||
|
It could be a short-form device path.
|
||||||
|
@param FullPath Return the next full device path of the load option after
|
||||||
|
short-form device path expanding.
|
||||||
|
Caller is responsible to free it.
|
||||||
|
NULL to return the first matched full device path.
|
||||||
|
@param FileSize Return the load option size.
|
||||||
|
|
||||||
|
@return The load option buffer. Caller is responsible to free the memory.
|
||||||
**/
|
**/
|
||||||
VOID *
|
VOID *
|
||||||
BmGetFileBufferFromLoadFile (
|
BmGetNextLoadOptionBuffer (
|
||||||
EFI_HANDLE LoadFileHandle,
|
IN EFI_BOOT_MANAGER_LOAD_OPTION_TYPE Type,
|
||||||
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
|
||||||
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
|
||||||
OUT UINTN *FileSize
|
OUT UINTN *FileSize
|
||||||
);
|
);
|
||||||
#endif // _INTERNAL_BM_H_
|
#endif // _INTERNAL_BM_H_
|
||||||
|
Reference in New Issue
Block a user