Hi Ray, For this patch, I just found a minor issue and also have a suggestion below. Others look good to me.
Minor issue: The following newly created functions' parameter lack IN and/or OUT modifiers: 1. BmGetLoadFileRamDisk 2. BmGetRamDiskMemoryInfo 3. BmDestroyRamDisk Suggestion: It looks like both BmGetLoadFileRamDisk and BmGetFileBufferFromLoadFileSystem) should be better to return RamDiskDevicePath instead of RamDiskHandle because both BmDestroyRamDisk and BmGetRamDiskMemoryInfo only need RamDisk's device path. In other words, if we change to return RamDiskDevicePath, we will NOT need to have DevicePathFromHandle function calls in newly added code. What do you think? By the way, if you agree with my suggestion above, we may also consider to directly use FullPath instead of adding new output parameter RamDiskHandle/RamDiskDevicePath to BmGetFileBufferFromLoadFileSystem(). For this one, I didn't take a deep look, so it maybe is not feasible. Just mention it here for your reference. Regards, Sunny Wang -----Original Message----- From: edk2-devel [mailto:edk2-devel-boun...@lists.01.org] On Behalf Of Ruiyu Ni Sent: Wednesday, March 30, 2016 8:29 AM To: edk2-devel@lists.01.org Cc: Ruiyu Ni <ruiyu...@intel.com>; Siyuan Fu <siyuan...@intel.com>; Feng Tian <feng.t...@intel.com> Subject: [edk2] [Patch v3 2/3] MdeModulePkg/Bds: Free resources after ram disk boot finishes 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 | 155 ++++++++++++++++++++- .../Library/UefiBootManagerLib/InternalBm.h | 1 + .../UefiBootManagerLib/UefiBootManagerLib.inf | 1 + 3 files changed, 153 insertions(+), 4 deletions(-) diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index 6e5c13b..598de26 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,124 @@ 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; +} + +/** + Return the buffer and buffer size occupied by the RAM Disk. + + @param RamDiskHandle RAM Disk handle. + @param RamDiskSizeInPages Return RAM Disk size in pages. + + @retval RAM Disk buffer. +**/ +VOID * +BmGetRamDiskMemoryInfo ( + EFI_HANDLE RamDiskHandle, + UINTN *RamDiskSizeInPages + ) +{ + + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE Handle; + UINT64 StartingAddr; + UINT64 EndingAddr; + + *RamDiskSizeInPages = 0; + if (RamDiskHandle == NULL) { + return NULL; + } + DevicePath = DevicePathFromHandle (RamDiskHandle); + + // + // Get the buffer occupied by RAM Disk. + // + Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, +&DevicePath, &Handle); + ASSERT_EFI_ERROR (Status); + ASSERT ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && +(DevicePathSubType (DevicePath) == MEDIA_RAM_DISK_DP)); + StartingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) DevicePath)->StartingAddr); + EndingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) DevicePath)->EndingAddr); + *RamDiskSizeInPages = EFI_SIZE_TO_PAGES ((UINTN) (EndingAddr - +StartingAddr + 1)); + return (VOID *) (UINTN) StartingAddr; } + +/** + 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. + + @param RamDiskHandle RAM Disk handle. +**/ +VOID +BmDestroyRamDisk ( + EFI_HANDLE RamDiskHandle + ) +{ + EFI_STATUS Status; + EFI_RAM_DISK_PROTOCOL *RamDisk; + VOID *RamDiskBuffer; + UINTN RamDiskSizeInPages; + + if (RamDiskHandle == NULL) { + return; + } + RamDiskBuffer = BmGetRamDiskMemoryInfo (RamDiskHandle, + &RamDiskSizeInPages); + + // + // Destroy RAM Disk. + // + Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID +*) &RamDisk); + ASSERT_EFI_ERROR (Status); + Status = RamDisk->Unregister (DevicePathFromHandle (RamDiskHandle)); + ASSERT_EFI_ERROR (Status); + FreePages (RamDiskBuffer, RamDiskSizeInPages); } + +/** Get the file buffer from the specified Load File instance. @param LoadFileHandle The specified Load File instance. @@ -1170,6 +1296,7 @@ BmGetFileBufferFromLoadFile ( EFI_LOAD_FILE_PROTOCOL *LoadFile; VOID *FileBuffer; BOOLEAN LoadFileSystem; + EFI_HANDLE RamDiskHandle; UINTN BufferSize; *FileSize = 0; @@ -1204,7 +1331,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 +1565,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 +1646,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 +1690,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 +1790,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 7b6252a..4660323 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 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel