\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
@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
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
+ 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 the specified Load File instance.\r
\r
**/\r
VOID *\r
BmGetFileBufferFromLoadFile (\r
- EFI_HANDLE LoadFileHandle,\r
+ IN EFI_HANDLE LoadFileHandle,\r
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,\r
OUT UINTN *FileSize\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
\r
if (LoadFileSystem) {\r
- FileBuffer = BmGetFileBufferFromLoadFileSystem (LoadFileHandle, FullPath, FileSize);\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
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
//\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
}\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