The resource free includes to un-register the ram disk device and free the memory occupied by the ram disk.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu...@intel.com> Cc: Siyuan Fu <siyuan...@intel.com> Cc: Feng Tian <feng.t...@intel.com> --- MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c | 128 ++++++++++++++++++++- .../Library/UefiBootManagerLib/InternalBm.h | 1 + .../UefiBootManagerLib/UefiBootManagerLib.inf | 1 + 3 files changed, 126 insertions(+), 4 deletions(-) diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index fb60bee..eb65f14 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -1095,6 +1095,7 @@ BmMatchHttpBootDevicePath ( @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. @return The load option buffer. **/ @@ -1102,7 +1103,8 @@ VOID * BmGetFileBufferFromLoadFileSystem ( IN EFI_HANDLE LoadFileHandle, OUT EFI_DEVICE_PATH_PROTOCOL **FullPath, - OUT UINTN *FileSize + OUT UINTN *FileSize, + OUT EFI_HANDLE *RamDiskHandle ) { EFI_STATUS Status; @@ -1140,7 +1142,13 @@ BmGetFileBufferFromLoadFileSystem ( FreePool (Handles); } - if (Index != HandleCount) { + if (Index == HandleCount) { + Handle = NULL; + } + + *RamDiskHandle = Handle; + + if (Handle != NULL) { return BmExpandMediaDevicePath (DevicePathFromHandle (Handle), FullPath, FileSize); } else { return NULL; @@ -1149,6 +1157,97 @@ BmGetFileBufferFromLoadFileSystem ( /** + Return the RAM DISK handle created by LoadFile. + + @param FilePath The source file path. + + @return RAM DISK handle. +**/ +EFI_HANDLE +BmGetLoadFileRamDisk ( + EFI_DEVICE_PATH_PROTOCOL *FilePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_HANDLE Handle; + + Node = FilePath; + Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle); + if (!EFI_ERROR (Status) && + (DevicePathType (Node) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP) + ) { + + // + // Construct the device path pointing to RAM Disk + // + Node = NextDevicePathNode (Node); + RamDiskDevicePath = DuplicateDevicePath (FilePath); + ASSERT (RamDiskDevicePath != NULL); + SetDevicePathEndNode ((VOID *) ((UINTN) RamDiskDevicePath + ((UINTN) Node - (UINTN) FilePath))); + + // + // Query the RAM Disk handle using the constructed device path. + // + Node = RamDiskDevicePath; + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &Node, &Handle); + ASSERT ((Status == EFI_SUCCESS) && IsDevicePathEnd (Node)); + FreePool (RamDiskDevicePath); + return Handle; + } + + return NULL; +} + +/** + Destroy the RAM Disk handle. + + 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, and free the RamDiskDevicePath. + + @param RamDiskHandle RAM Disk handle. +**/ +VOID +BmDestroyRamDisk ( + EFI_HANDLE RamDiskHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_HANDLE Handle; + EFI_RAM_DISK_PROTOCOL *RamDisk; + VOID *RamDiskBuffer; + + if (RamDiskHandle == NULL) { + return; + } + RamDiskDevicePath = DevicePathFromHandle (RamDiskHandle); + + // + // Get the buffer occupied by RAM Disk. + // + Node = RamDiskDevicePath; + Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &Node, &Handle); + ASSERT_EFI_ERROR (Status); + ASSERT ((DevicePathType (Node) == MEDIA_DEVICE_PATH) && (DevicePathSubType (Node) == MEDIA_RAM_DISK_DP)); + RamDiskBuffer = (VOID *) (UINTN) ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) Node)->StartingAddr); + + Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID *) &RamDisk); + ASSERT_EFI_ERROR (Status); + + // + // Destroy RAM Disk. + // + Status = RamDisk->Unregister (RamDiskDevicePath); + ASSERT_EFI_ERROR (Status); + FreePool (RamDiskBuffer); +} + +/** Get the file buffer from the specified Load File instance. @param LoadFileHandle The specified Load File instance. @@ -1170,6 +1269,7 @@ BmGetFileBufferFromLoadFile ( EFI_LOAD_FILE_PROTOCOL *LoadFile; VOID *FileBuffer; BOOLEAN LoadFileSystem; + EFI_HANDLE RamDiskHandle; UINTN BufferSize; *FileSize = 0; @@ -1204,7 +1304,13 @@ BmGetFileBufferFromLoadFile ( } if (LoadFileSystem) { - FileBuffer = BmGetFileBufferFromLoadFileSystem (LoadFileHandle, FullPath, FileSize); + FileBuffer = BmGetFileBufferFromLoadFileSystem (LoadFileHandle, FullPath, FileSize, &RamDiskHandle); + if (FileBuffer == NULL) { + // + // If there is no bootable executable in the populated + // + BmDestroyRamDisk (RamDiskHandle); + } } else { *FileSize = BufferSize; *FullPath = DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle)); @@ -1432,6 +1538,7 @@ EfiBootManagerBoot ( UINTN OriginalOptionNumber; EFI_DEVICE_PATH_PROTOCOL *FilePath; EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_HANDLE RamDiskHandle; EFI_HANDLE FvHandle; VOID *FileBuffer; UINTN FileSize; @@ -1512,10 +1619,14 @@ EfiBootManagerBoot ( // // 5. Load EFI boot option to ImageHandle // - ImageHandle = NULL; + ImageHandle = NULL; + RamDiskHandle = NULL; if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) { Status = EFI_NOT_FOUND; FileBuffer = BmGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize); + if (FileBuffer != NULL) { + RamDiskHandle = BmGetLoadFileRamDisk (FilePath); + } DEBUG_CODE ( if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) { DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: ")); @@ -1552,6 +1663,10 @@ EfiBootManagerBoot ( (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR) ); BootOption->Status = Status; + // + // Destroy the RAM disk + // + BmDestroyRamDisk (RamDiskHandle); return; } } @@ -1648,6 +1763,11 @@ EfiBootManagerBoot ( PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber); // + // Destroy the RAM disk + // + BmDestroyRamDisk (RamDiskHandle); + + // // Clear the Watchdog Timer after the image returns // gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h index a4430dd..79f86a2 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h +++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h @@ -43,6 +43,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include <Protocol/DriverHealth.h> #include <Protocol/FormBrowser2.h> #include <Protocol/VariableLock.h> +#include <Protocol/RamDisk.h> #include <Guid/ZeroGuid.h> #include <Guid/MemoryTypeInformation.h> diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf index e9e74b1..9d62d3d 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf +++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf @@ -108,6 +108,7 @@ gEfiDiskInfoProtocolGuid ## SOMETIMES_CONSUMES gEfiDriverHealthProtocolGuid ## SOMETIMES_CONSUMES gEfiFormBrowser2ProtocolGuid ## SOMETIMES_CONSUMES + gEfiRamDiskProtocolGuid ## SOMETIMES_CONSUMES [Pcd] gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange ## SOMETIMES_CONSUMES -- 2.7.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel