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..4572644 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));
+  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

Reply via email to