diff options
author | Ni, Ruiyu <ruiyu.ni@intel.com> | 2016-03-30 08:29:10 +0800 |
---|---|---|
committer | Ruiyu Ni <ruiyu.ni@intel.com> | 2016-04-06 13:27:09 +0800 |
commit | 339ae051f6d095629b39d8d486c4f3a8a31e6480 (patch) | |
tree | 21bb12b86bc303b7bf27b969d24a56df38ba7d65 /MdeModulePkg/Library | |
parent | 026ede493c70af6fe16be21e9cb73580a22b8159 (diff) | |
download | edk2-339ae051f6d095629b39d8d486c4f3a8a31e6480.zip edk2-339ae051f6d095629b39d8d486c4f3a8a31e6480.tar.gz edk2-339ae051f6d095629b39d8d486c4f3a8a31e6480.tar.bz2 |
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.ni@intel.com>
Reviewed-by: Siyuan Fu <siyuan.fu@intel.com>
Reviewed-by: Samer El-Haj-Mahmoud <elhaj@hpe.com>
Diffstat (limited to 'MdeModulePkg/Library')
-rw-r--r-- | MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c | 155 | ||||
-rw-r--r-- | MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h | 1 | ||||
-rw-r--r-- | MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf | 1 |
3 files changed, 152 insertions, 5 deletions
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c index a582b90..61a8345 100644 --- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c +++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c @@ -15,6 +15,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "InternalBm.h"
+EFI_RAM_DISK_PROTOCOL *mRamDisk = NULL;
+
EFI_BOOT_MANAGER_REFRESH_LEGACY_BOOT_OPTION mBmRefreshLegacyBootOption = NULL;
EFI_BOOT_MANAGER_LEGACY_BOOT mBmLegacyBoot = NULL;
@@ -1095,6 +1097,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 +1105,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 +1144,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 +1159,114 @@ BmGetFileBufferFromLoadFileSystem ( /**
+ Return the RAM Disk device path created by LoadFile.
+
+ @param FilePath The source file path.
+
+ @return Callee-to-free RAM Disk device path
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+BmGetRamDiskDevicePath (
+ IN 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)));
+ return RamDiskDevicePath;
+ }
+
+ return NULL;
+}
+
+/**
+ Return the buffer and buffer size occupied by the RAM Disk.
+
+ @param RamDiskDevicePath RAM Disk device path.
+ @param RamDiskSizeInPages Return RAM Disk size in pages.
+
+ @retval RAM Disk buffer.
+**/
+VOID *
+BmGetRamDiskMemoryInfo (
+ IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath,
+ OUT UINTN *RamDiskSizeInPages
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ UINT64 StartingAddr;
+ UINT64 EndingAddr;
+
+ ASSERT (RamDiskDevicePath != NULL);
+
+ *RamDiskSizeInPages = 0;
+
+ //
+ // Get the buffer occupied by RAM Disk.
+ //
+ Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &RamDiskDevicePath, &Handle);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT ((DevicePathType (RamDiskDevicePath) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType (RamDiskDevicePath) == MEDIA_RAM_DISK_DP));
+ StartingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) RamDiskDevicePath)->StartingAddr);
+ EndingAddr = ReadUnaligned64 ((UINT64 *) ((MEDIA_RAM_DISK_DEVICE_PATH *) RamDiskDevicePath)->EndingAddr);
+ *RamDiskSizeInPages = EFI_SIZE_TO_PAGES ((UINTN) (EndingAddr - StartingAddr + 1));
+ return (VOID *) (UINTN) StartingAddr;
+}
+
+/**
+ Destroy the RAM Disk.
+
+ 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 RamDiskDevicePath RAM Disk device path.
+**/
+VOID
+BmDestroyRamDisk (
+ IN EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath
+ )
+{
+ EFI_STATUS Status;
+ VOID *RamDiskBuffer;
+ UINTN RamDiskSizeInPages;
+
+ ASSERT (RamDiskDevicePath != NULL);
+
+ RamDiskBuffer = BmGetRamDiskMemoryInfo (RamDiskDevicePath, &RamDiskSizeInPages);
+
+ //
+ // Destroy RAM Disk.
+ //
+ if (mRamDisk == NULL) {
+ Status = gBS->LocateProtocol (&gEfiRamDiskProtocolGuid, NULL, (VOID *) &mRamDisk);
+ ASSERT_EFI_ERROR (Status);
+ }
+ Status = mRamDisk->Unregister (RamDiskDevicePath);
+ ASSERT_EFI_ERROR (Status);
+ FreePages (RamDiskBuffer, RamDiskSizeInPages);
+}
+
+/**
Get the file buffer from the specified Load File instance.
@param LoadFileHandle The specified Load File instance.
@@ -1160,7 +1278,7 @@ BmGetFileBufferFromLoadFileSystem ( **/
VOID *
BmGetFileBufferFromLoadFile (
- EFI_HANDLE LoadFileHandle,
+ IN EFI_HANDLE LoadFileHandle,
IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
OUT EFI_DEVICE_PATH_PROTOCOL **FullPath,
OUT UINTN *FileSize
@@ -1170,6 +1288,7 @@ BmGetFileBufferFromLoadFile ( EFI_LOAD_FILE_PROTOCOL *LoadFile;
VOID *FileBuffer;
BOOLEAN LoadFileSystem;
+ EFI_HANDLE RamDiskHandle;
UINTN BufferSize;
*FileSize = 0;
@@ -1208,7 +1327,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 (DevicePathFromHandle (RamDiskHandle));
+ }
} else {
*FileSize = BufferSize;
*FullPath = DuplicateDevicePath (DevicePathFromHandle (LoadFileHandle));
@@ -1436,6 +1561,7 @@ EfiBootManagerBoot ( UINTN OriginalOptionNumber;
EFI_DEVICE_PATH_PROTOCOL *FilePath;
EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *RamDiskDevicePath;
EFI_HANDLE FvHandle;
VOID *FileBuffer;
UINTN FileSize;
@@ -1516,10 +1642,14 @@ EfiBootManagerBoot ( //
// 5. Load EFI boot option to ImageHandle
//
- ImageHandle = NULL;
+ ImageHandle = NULL;
+ RamDiskDevicePath = NULL;
if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {
Status = EFI_NOT_FOUND;
FileBuffer = BmGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);
+ if (FileBuffer != NULL) {
+ RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);
+ }
DEBUG_CODE (
if (FileBuffer != NULL && CompareMem (BootOption->FilePath, FilePath, GetDevicePathSize (FilePath)) != 0) {
DEBUG ((EFI_D_INFO, "[Bds] DevicePath expand: "));
@@ -1556,6 +1686,13 @@ EfiBootManagerBoot ( (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR)
);
BootOption->Status = Status;
+ //
+ // Destroy the RAM disk
+ //
+ if (RamDiskDevicePath != NULL) {
+ BmDestroyRamDisk (RamDiskDevicePath);
+ FreePool (RamDiskDevicePath);
+ }
return;
}
}
@@ -1652,6 +1789,14 @@ EfiBootManagerBoot ( PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);
//
+ // Destroy the RAM disk
+ //
+ if (RamDiskDevicePath != NULL) {
+ BmDestroyRamDisk (RamDiskDevicePath);
+ FreePool (RamDiskDevicePath);
+ }
+
+ //
// 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
|