\r
#include "InternalBm.h"\r
\r
+EFI_RAM_DISK_PROTOCOL *mRamDisk = NULL;\r
+\r
EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION mBmRefreshLegacyBootOption = NULL;\r
EFI_BOOT_MANAGER_LEGACY_BOOT mBmLegacyBoot = NULL;\r
\r
UINTN Index;\r
UINTN HandleCount;\r
EFI_HANDLE *Handles;\r
- EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
VOID *FileBuffer;\r
\r
EfiBootManagerConnectAll ();\r
}\r
\r
FileBuffer = NULL;\r
-\r
for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (Handles[Index], &gEfiLoadFileProtocolGuid, (VOID *) &LoadFile);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- FileBuffer = NULL;\r
- Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, FileSize, FileBuffer);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- FileBuffer = AllocatePool (*FileSize);\r
- if (FileBuffer == NULL) {\r
- break;\r
- }\r
- Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, FileSize, FileBuffer);\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // LoadFile() returns a file buffer mapping to a file system.\r
- //\r
- if (Status == EFI_WARN_FILE_SYSTEM) {\r
- return BmGetFileBufferFromLoadFileFileSystem (Handles[Index], FullPath, FileSize);\r
- }\r
-\r
- ASSERT (Status == EFI_SUCCESS);\r
- *FullPath = DuplicateDevicePath (DevicePathFromHandle (Handles[Index]));\r
- break;\r
- }\r
-\r
+ FileBuffer = BmGetFileBufferFromLoadFile (Handles[Index], FilePath, FullPath, FileSize);\r
if (FileBuffer != NULL) {\r
- FreePool (FileBuffer);\r
+ break;\r
}\r
}\r
\r
@param LoadFileHandle The handle of LoadFile instance.\r
@param FullPath Return the full device path pointing to the load option.\r
@param FileSize Return the size of the load option.\r
+ @param RamDiskHandle Return the RAM Disk handle.\r
\r
@return The load option buffer.\r
**/\r
VOID *\r
-BmGetFileBufferFromLoadFileFileSystem (\r
+BmGetFileBufferFromLoadFileSystem (\r
IN EFI_HANDLE LoadFileHandle,\r
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
- OUT UINTN *FileSize\r
+ OUT UINTN *FileSize,\r
+ OUT EFI_HANDLE *RamDiskHandle\r
)\r
{\r
EFI_STATUS Status;\r
FreePool (Handles);\r
}\r
\r
- if (Index != HandleCount) {\r
+ if (Index == HandleCount) {\r
+ Handle = NULL;\r
+ }\r
+\r
+ *RamDiskHandle = Handle;\r
+\r
+ if (Handle != NULL) {\r
return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), FullPath, FileSize);\r
} else {\r
return NULL;\r
}\r
}\r
\r
+\r
+/**\r
+ Return the RAM Disk device path created by LoadFile.\r
+\r
+ @param FilePath The source file path.\r
+\r
+ @return Callee-to-free RAM Disk device path\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+BmGetRamDiskDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_HANDLE Handle;\r
+\r
+ Node = FilePath;\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle);\r
+ if (!EFI_ERROR (Status) &&\r
+ (DevicePathType (Node) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)\r
+ ) {\r
+\r
+ //\r
+ // Construct the device path pointing to RAM Disk\r
+ //\r
+ Node = NextDevicePathNode (Node);\r
+ RamDiskDevicePath = DuplicateDevicePath (FilePath);\r
+ ASSERT (RamDiskDevicePath != NULL);\r
+ SetDevicePathEndNode ((VOID *) ((UINTN) RamDiskDevicePath + ((UINTN) Node - (UINTN) FilePath)));\r
+ return RamDiskDevicePath;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Return the buffer and buffer size occupied by the RAM Disk.\r
+\r
+ @param RamDiskDevicePath RAM Disk device path.\r
+ @param RamDiskSizeInPages Return RAM Disk size in pages.\r
+\r
+ @retval RAM Disk buffer.\r
+**/\r
+VOID *\r
+BmGetRamDiskMemoryInfo (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath,\r
+ OUT UINTN *RamDiskSizeInPages\r
+ )\r
+{\r
+\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Handle;\r
+ UINT64 StartingAddr;\r
+ UINT64 EndingAddr;\r
+\r
+ ASSERT (RamDiskDevicePath != NULL);\r
+\r
+ *RamDiskSizeInPages = 0;\r
+\r
+ //\r
+ // Get the buffer occupied by RAM Disk.\r
+ //\r
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &RamDiskDevicePath, &Handle);\r
+ ASSERT_EFI_ERROR (Status);\r
+ ASSERT ((DevicePathType (RamDiskDevicePath) == MEDIA_DEVICE_PATH) &&\r
+ (DevicePathSubType (RamDiskDevicePath) == MEDIA_RAM_DISK_DP));\r
+ StartingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) RamDiskDevicePath)->StartingAddr);\r
+ EndingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) RamDiskDevicePath)->EndingAddr);\r
+ *RamDiskSizeInPages = EFI_SIZE_TO_PAGES ((UINTN) (EndingAddr - StartingAddr + 1));\r
+ return (VOID *) (UINTN) StartingAddr;\r
+}\r
+\r
+/**\r
+ Destroy the RAM Disk.\r
+\r
+ The destroy operation includes to call RamDisk.Unregister to\r
+ unregister the RAM DISK from RAM DISK driver, free the memory\r
+ allocated for the RAM Disk.\r
+\r
+ @param RamDiskDevicePath RAM Disk device path.\r
+**/\r
+VOID\r
+BmDestroyRamDisk (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *RamDiskBuffer;\r
+ UINTN RamDiskSizeInPages;\r
+\r
+ ASSERT (RamDiskDevicePath != NULL);\r
+\r
+ RamDiskBuffer = BmGetRamDiskMemoryInfo (RamDiskDevicePath, &RamDiskSizeInPages);\r
+\r
+ //\r
+ // Destroy RAM Disk.\r
+ //\r
+ if (mRamDisk == NULL) {\r
+ Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID *) &mRamDisk);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+ Status = mRamDisk->Unregister (RamDiskDevicePath);\r
+ ASSERT_EFI_ERROR (Status);\r
+ FreePages (RamDiskBuffer, RamDiskSizeInPages);\r
+}\r
+\r
/**\r
- Get the file buffer from Load File instance.\r
+ Get the file buffer from the specified Load File instance.\r
+\r
+ @param LoadFileHandle The specified Load File instance.\r
+ @param FilePath The file path which will pass to LoadFile().\r
+ @param FullPath Return the full device path pointing to the load option.\r
+ @param FileSize Return the size of the load option.\r
+\r
+ @return The load option buffer or NULL if fails.\r
+**/\r
+VOID *\r
+BmGetFileBufferFromLoadFile (\r
+ IN EFI_HANDLE LoadFileHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
+ OUT UINTN *FileSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
+ VOID *FileBuffer;\r
+ BOOLEAN LoadFileSystem;\r
+ EFI_HANDLE RamDiskHandle;\r
+ UINTN BufferSize;\r
+\r
+ *FileSize = 0;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ LoadFileHandle,\r
+ &gEfiLoadFileProtocolGuid,\r
+ (VOID **) &LoadFile,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ FileBuffer = NULL;\r
+ BufferSize = 0;\r
+ Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
+ if ((Status != EFI_WARN_FILE_SYSTEM) && (Status != EFI_BUFFER_TOO_SMALL)) {\r
+ return NULL;\r
+ }\r
+\r
+ LoadFileSystem = (BOOLEAN) (Status == EFI_WARN_FILE_SYSTEM);\r
+ FileBuffer = LoadFileSystem ? AllocateReservedPages (EFI_SIZE_TO_PAGES (BufferSize)) : AllocatePool (BufferSize);\r
+ if (FileBuffer == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
+ if (EFI_ERROR (Status)) {\r
+ if (LoadFileSystem) {\r
+ FreePages (FileBuffer, EFI_SIZE_TO_PAGES (BufferSize));\r
+ } else {\r
+ FreePool (FileBuffer);\r
+ }\r
+ return NULL;\r
+ }\r
+\r
+ if (LoadFileSystem) {\r
+ FileBuffer = BmGetFileBufferFromLoadFileSystem (LoadFileHandle, FullPath, FileSize, &RamDiskHandle);\r
+ if (FileBuffer == NULL) {\r
+ //\r
+ // If there is no bootable executable in the populated\r
+ //\r
+ BmDestroyRamDisk (DevicePathFromHandle (RamDiskHandle));\r
+ }\r
+ } else {\r
+ *FileSize = BufferSize;\r
+ *FullPath = DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle));\r
+ }\r
+\r
+ return FileBuffer;\r
+}\r
+\r
+/**\r
+ Get the file buffer from all the Load File instances.\r
\r
@param FilePath The media device path pointing to a LoadFile instance.\r
@param FullPath Return the full device path pointing to the load option.\r
@return The load option buffer.\r
**/\r
VOID *\r
-BmGetFileBufferFromLoadFile (\r
+BmGetFileBufferFromLoadFiles (\r
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
OUT UINTN *FileSize\r
{\r
EFI_STATUS Status;\r
EFI_HANDLE Handle;\r
- VOID *FileBuffer;\r
EFI_HANDLE *Handles;\r
UINTN HandleCount;\r
UINTN Index;\r
EFI_DEVICE_PATH_PROTOCOL *Node;\r
- EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
- UINTN BufferSize;\r
\r
//\r
// Get file buffer from load file instance.\r
return NULL;\r
}\r
\r
- Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **) &LoadFile);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- BufferSize = 0;\r
- FileBuffer = NULL;\r
- Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
- if (Status == EFI_BUFFER_TOO_SMALL) {\r
- FileBuffer = AllocatePool (BufferSize);\r
- if (FileBuffer != NULL) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- Status = LoadFile->LoadFile (LoadFile, FilePath, TRUE, &BufferSize, FileBuffer);\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // LoadFile() returns a file buffer mapping to a file system.\r
- //\r
- if (Status == EFI_WARN_FILE_SYSTEM) {\r
- return BmGetFileBufferFromLoadFileFileSystem (Handle, FullPath, FileSize);\r
- }\r
-\r
- ASSERT (Status == EFI_SUCCESS);\r
- //\r
- // LoadFile () may cause the device path of the Handle be updated.\r
- //\r
- *FullPath = DuplicateDevicePath (DevicePathFromHandle (Handle));\r
- *FileSize = BufferSize;\r
- return FileBuffer;\r
- } else {\r
- return NULL;\r
- }\r
+ return BmGetFileBufferFromLoadFile (Handle, FilePath, FullPath, FileSize);\r
}\r
\r
/**\r
return FileBuffer;\r
}\r
\r
- return BmGetFileBufferFromLoadFile (FilePath, FullPath, FileSize);\r
+ return BmGetFileBufferFromLoadFiles (FilePath, FullPath, FileSize);\r
}\r
\r
/**\r
UINTN OriginalOptionNumber;\r
EFI_DEVICE_PATH_PROTOCOL *FilePath;\r
EFI_DEVICE_PATH_PROTOCOL *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;\r
EFI_HANDLE FvHandle;\r
VOID *FileBuffer;\r
UINTN FileSize;\r
EFI_BOOT_LOGO_PROTOCOL *BootLogo;\r
EFI_EVENT LegacyBootEvent;\r
+ UINTN RamDiskSizeInPages;\r
\r
if (BootOption == NULL) {\r
return;\r
//\r
// 5. Load EFI boot option to ImageHandle\r
//\r
- ImageHandle = NULL;\r
+ ImageHandle = NULL;\r
+ RamDiskDevicePath = NULL;\r
if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {\r
Status = EFI_NOT_FOUND;\r
FileBuffer = BmGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);\r
+ if (FileBuffer != NULL) {\r
+ RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);\r
+ }\r
DEBUG_CODE (\r
if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {\r
DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));\r
(EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)\r
);\r
BootOption->Status = Status;\r
+ //\r
+ // Destroy the RAM disk\r
+ //\r
+ if (RamDiskDevicePath != NULL) {\r
+ BmDestroyRamDisk (RamDiskDevicePath);\r
+ FreePool (RamDiskDevicePath);\r
+ }\r
return;\r
}\r
}\r
// 6. Adjust the different type memory page number just before booting\r
// and save the updated info into the variable for next boot to use\r
//\r
+ if (RamDiskDevicePath == NULL) {\r
+ RamDiskSizeInPages = 0;\r
+ } else {\r
+ BmGetRamDiskMemoryInfo (RamDiskDevicePath, &RamDiskSizeInPages);\r
+ }\r
BmSetMemoryTypeInformationVariable (\r
- (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT)\r
+ (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT),\r
+ RamDiskSizeInPages\r
);\r
\r
DEBUG_CODE_BEGIN();\r
}\r
PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
\r
+ //\r
+ // Destroy the RAM disk\r
+ //\r
+ if (RamDiskDevicePath != NULL) {\r
+ BmDestroyRamDisk (RamDiskDevicePath);\r
+ FreePool (RamDiskDevicePath);\r
+ }\r
+\r
//\r
// Clear the Watchdog Timer after the image returns\r
//\r