The RamDiskDxe driver will:
1. Produce the EFI RAM Disk Protocol
2. Install RAM disk device path and block I/O related protocols on the
   RAM disk device handle.
3. Install RAM disk configuration form to HII database

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a...@intel.com>
---
 MdeModulePkg/Include/Guid/RamDiskHii.h             |  25 +
 MdeModulePkg/MdeModulePkg.dec                      |   3 +
 MdeModulePkg/MdeModulePkg.dsc                      |   1 +
 .../Universal/Disk/RamDiskDxe/RamDiskBlockIo.c     | 258 +++++++
 .../Universal/Disk/RamDiskDxe/RamDiskDriver.c      | 170 +++++
 .../Universal/Disk/RamDiskDxe/RamDiskDxe.inf       |  78 ++
 .../Universal/Disk/RamDiskDxe/RamDiskDxe.uni       |  20 +
 .../Disk/RamDiskDxe/RamDiskFileExplorer.c          | 253 +++++++
 .../Universal/Disk/RamDiskDxe/RamDiskHii.vfr       |  93 +++
 .../Disk/RamDiskDxe/RamDiskHiiStrings.uni          |  42 ++
 .../Universal/Disk/RamDiskDxe/RamDiskImpl.c        | 807 +++++++++++++++++++++
 .../Universal/Disk/RamDiskDxe/RamDiskImpl.h        | 499 +++++++++++++
 .../Universal/Disk/RamDiskDxe/RamDiskNVData.h      |  43 ++
 .../Universal/Disk/RamDiskDxe/RamDiskProtocol.c    | 356 +++++++++
 14 files changed, 2648 insertions(+)
 create mode 100644 MdeModulePkg/Include/Guid/RamDiskHii.h
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDriver.c
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.uni
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskFileExplorer.c
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHii.vfr
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHiiStrings.uni
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.h
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskNVData.h
 create mode 100644 MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskProtocol.c

diff --git a/MdeModulePkg/Include/Guid/RamDiskHii.h 
b/MdeModulePkg/Include/Guid/RamDiskHii.h
new file mode 100644
index 0000000..0457ee2
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/RamDiskHii.h
@@ -0,0 +1,25 @@
+/** @file
+  GUIDs used as HII FormSet and HII Package list GUID in RamDiskDxe driver.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __RAM_DISK_HII_GUID_H__
+#define __RAM_DISK_HII_GUID_H__
+
+#define RAM_DISK_FORM_SET_GUID \
+  { \
+    0x2a46715f, 0x3581, 0x4a55, {0x8e, 0x73, 0x2b, 0x76, 0x9a, 0xaa, 0x30, 
0xc5} \
+  }
+
+extern EFI_GUID gRamDiskFormSetGuid;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index af7bcab..b685132 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -343,6 +343,9 @@
 
   gEfiIfrFrontPageGuid        = { 0xe58809f8, 0xfbc1, 0x48e2, { 0x88, 0x3a, 
0xa3, 0x0f, 0xdc, 0x4b, 0x44, 0x1e } }
 
+  ## Include/Guid/RamDiskHii.h
+  gRamDiskFormSetGuid            = { 0x2a46715f, 0x3581, 0x4a55, { 0x8e, 0x73, 
0x2b, 0x76, 0x9a, 0xaa, 0x30, 0xc5 }}
+
 
 [Ppis]
   ## Include/Ppi/AtaController.h
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index ad2b913..0b54030 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -322,6 +322,7 @@
   MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
   MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
   MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
+  MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
   MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
   MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
   
MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
new file mode 100644
index 0000000..1687da3
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
@@ -0,0 +1,258 @@
+/** @file
+  Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RamDiskImpl.h"
+
+//
+// The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle
+// for newly registered RAM disks
+//
+EFI_BLOCK_IO_PROTOCOL  mRamDiskBlockIoTemplate = {
+  EFI_BLOCK_IO_PROTOCOL_REVISION,
+  (EFI_BLOCK_IO_MEDIA *) 0,
+  RamDiskBlkIoReset,
+  RamDiskBlkIoReadBlocks,
+  RamDiskBlkIoWriteBlocks,
+  RamDiskBlkIoFlushBlocks
+};
+
+
+/**
+  Initialize the BlockIO protocol of a RAM disk device.
+
+  @param[in] PrivateData     Points to RAM disk private data.
+
+**/
+VOID
+RamDiskInitBlockIo (
+  IN     RAM_DISK_PRIVATE_DATA    *PrivateData
+  )
+{
+  EFI_BLOCK_IO_PROTOCOL           *BlockIo;
+  EFI_BLOCK_IO_MEDIA              *Media;
+
+  BlockIo = &PrivateData->BlockIo;
+  Media   = &PrivateData->Media;
+
+  CopyMem (BlockIo, &mRamDiskBlockIoTemplate, sizeof (EFI_BLOCK_IO_PROTOCOL));
+
+  BlockIo->Media          = Media;
+  Media->RemovableMedia   = FALSE;
+  Media->MediaPresent     = TRUE;
+  Media->LogicalPartition = FALSE;
+  Media->ReadOnly         = FALSE;
+  Media->WriteCaching     = FALSE;
+  Media->BlockSize        = RAM_DISK_BLOCK_SIZE;
+  Media->LastBlock        = DivU64x32 (
+                              PrivateData->Size + RAM_DISK_BLOCK_SIZE - 1,
+                              RAM_DISK_BLOCK_SIZE
+                              ) - 1;
+}
+
+
+/**
+  Reset the Block Device.
+
+  @param  This                 Indicates a pointer to the calling context.
+  @param  ExtendedVerification Driver may perform diagnostics on reset.
+
+  @retval EFI_SUCCESS          The device was reset.
+  @retval EFI_DEVICE_ERROR     The device is not functioning properly and could
+                               not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIoReset (
+  IN EFI_BLOCK_IO_PROTOCOL        *This,
+  IN BOOLEAN                      ExtendedVerification
+  )
+{
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Read BufferSize bytes from Lba into Buffer.
+
+  @param[in]  This           Indicates a pointer to the calling context.
+  @param[in]  MediaId        Id of the media, changes every time the media is
+                             replaced.
+  @param[in]  Lba            The starting Logical Block Address to read from.
+  @param[in]  BufferSize     Size of Buffer, must be a multiple of device block
+                             size.
+  @param[out] Buffer         A pointer to the destination buffer for the data.
+                             The caller is responsible for either having
+                             implicit or explicit ownership of the buffer.
+
+  @retval EFI_SUCCESS             The data was read correctly from the device.
+  @retval EFI_DEVICE_ERROR        The device reported an error while performing
+                                  the read.
+  @retval EFI_NO_MEDIA            There is no media in the device.
+  @retval EFI_MEDIA_CHANGED       The MediaId does not matched the current
+                                  device.
+  @retval EFI_BAD_BUFFER_SIZE     The Buffer was not a multiple of the block
+                                  size of the device.
+  @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
+                                  valid, or the buffer is not on proper 
alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIoReadBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL        *This,
+  IN UINT32                       MediaId,
+  IN EFI_LBA                      Lba,
+  IN UINTN                        BufferSize,
+  OUT VOID                        *Buffer
+  )
+{
+  RAM_DISK_PRIVATE_DATA           *PrivateData;
+  UINTN                           NumberOfBlocks;
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BufferSize == 0) {
+    return EFI_SUCCESS;
+  }
+
+  PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
+
+  if (MediaId != PrivateData->Media.MediaId) {
+    return EFI_MEDIA_CHANGED;
+  }
+
+  if ((BufferSize % PrivateData->Media.BlockSize) != 0) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  if (Lba > PrivateData->Media.LastBlock) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;
+  if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem (
+    Buffer,
+    (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, 
PrivateData->Media.BlockSize)),
+    BufferSize
+    );
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Write BufferSize bytes from Lba into Buffer.
+
+  @param[in] This            Indicates a pointer to the calling context.
+  @param[in] MediaId         The media ID that the write request is for.
+  @param[in] Lba             The starting logical block address to be written.
+                             The caller is responsible for writing to only
+                             legitimate locations.
+  @param[in] BufferSize      Size of Buffer, must be a multiple of device block
+                             size.
+  @param[in] Buffer          A pointer to the source buffer for the data.
+
+  @retval EFI_SUCCESS             The data was written correctly to the device.
+  @retval EFI_WRITE_PROTECTED     The device can not be written to.
+  @retval EFI_DEVICE_ERROR        The device reported an error while performing
+                                  the write.
+  @retval EFI_NO_MEDIA            There is no media in the device.
+  @retval EFI_MEDIA_CHNAGED       The MediaId does not matched the current
+                                  device.
+  @retval EFI_BAD_BUFFER_SIZE     The Buffer was not a multiple of the block
+                                  size of the device.
+  @retval EFI_INVALID_PARAMETER   The write request contains LBAs that are not
+                                  valid, or the buffer is not on proper 
alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIoWriteBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL        *This,
+  IN UINT32                       MediaId,
+  IN EFI_LBA                      Lba,
+  IN UINTN                        BufferSize,
+  IN VOID                         *Buffer
+  )
+{
+  RAM_DISK_PRIVATE_DATA           *PrivateData;
+  UINTN                           NumberOfBlocks;
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (BufferSize == 0) {
+    return EFI_SUCCESS;
+  }
+
+  PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
+
+  if (MediaId != PrivateData->Media.MediaId) {
+    return EFI_MEDIA_CHANGED;
+  }
+
+  if (TRUE == PrivateData->Media.ReadOnly) {
+    return EFI_WRITE_PROTECTED;
+  }
+
+  if ((BufferSize % PrivateData->Media.BlockSize) != 0) {
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  if (Lba > PrivateData->Media.LastBlock) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;
+  if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  CopyMem (
+    (VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, 
PrivateData->Media.BlockSize)),
+    Buffer,
+    BufferSize
+    );
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Flush the Block Device.
+
+  @param[in] This            Indicates a pointer to the calling context.
+
+  @retval EFI_SUCCESS             All outstanding data was written to the 
device.
+  @retval EFI_DEVICE_ERROR        The device reported an error while writting
+                                  back the data
+  @retval EFI_NO_MEDIA            There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIoFlushBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL        *This
+  )
+{
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDriver.c 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDriver.c
new file mode 100644
index 0000000..7d068b2
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDriver.c
@@ -0,0 +1,170 @@
+/** @file
+  The driver entry point for RamDiskDxe driver.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RamDiskImpl.h"
+
+//
+// Handle for the EFI_RAM_DISK_PROTOCOL instance
+//
+EFI_HANDLE  mRamDiskHandle = NULL;
+
+//
+// The EFI_RAM_DISK_PROTOCOL instances that is installed onto the driver
+// handle
+//
+EFI_RAM_DISK_PROTOCOL  mRamDiskProtocol = {
+  RamDiskRegister,
+  RamDiskUnregister
+};
+
+//
+// RamDiskDxe driver maintains a list of registered RAM disks.
+//
+LIST_ENTRY  RegisteredRamDisks;
+UINTN       ListEntryNum;
+
+
+/**
+  The entry point for RamDiskDxe driver.
+
+  @param[in] ImageHandle     The image handle of the driver.
+  @param[in] SystemTable     The system table.
+
+  @retval EFI_ALREADY_STARTED     The driver already exists in system.
+  @retval EFI_OUT_OF_RESOURCES    Fail to execute entry point due to lack of
+                                  resources.
+  @retval EFI_SUCCES              All the related protocols are installed on
+                                  the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskDxeEntryPoint (
+  IN EFI_HANDLE                   ImageHandle,
+  IN EFI_SYSTEM_TABLE             *SystemTable
+  )
+{
+  EFI_STATUS                      Status;
+  RAM_DISK_CONFIG_PRIVATE_DATA    *ConfigPrivate;
+  VOID                            *DummyInterface;
+
+  //
+  // If already started, return.
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiRamDiskProtocolGuid,
+                  NULL,
+                  &DummyInterface
+                  );
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_INFO, "Driver already started!\n"));
+    return EFI_ALREADY_STARTED;
+  }
+
+  //
+  // Create a private data structure.
+  //
+  ConfigPrivate = AllocateCopyPool (sizeof (RAM_DISK_CONFIG_PRIVATE_DATA), 
&mRamDiskConfigPrivateDataTemplate);
+  if (ConfigPrivate == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Install RAM disk configuration form
+  //
+  Status = InstallRamDiskConfigForm (ConfigPrivate);
+  if (EFI_ERROR (Status)) {
+    goto ErrorExit;
+  }
+
+  //
+  // Install the EFI_RAM_DISK_PROTOCOL and RAM disk private data onto a
+  // new handle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &mRamDiskHandle,
+                  &gEfiRamDiskProtocolGuid,
+                  &mRamDiskProtocol,
+                  &gEfiCallerIdGuid,
+                  ConfigPrivate,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ErrorExit;
+  }
+
+  //
+  // Initialize the list of registered RAM disks maintained by the driver
+  //
+  InitializeListHead (&RegisteredRamDisks);
+
+  return EFI_SUCCESS;
+
+ErrorExit:
+  if (ConfigPrivate != NULL) {
+    UninstallRamDiskConfigForm (ConfigPrivate);
+  }
+
+  return Status;
+}
+
+
+/**
+  Unload the RamDiskDxe driver and its configuration form.
+
+  @param[in] ImageHandle     The driver's image handle.
+
+  @retval EFI_SUCCESS             The RamDiskDxe driver and its configuration
+                                  form is unloaded.
+  @retval Others                  Failed to unload the form.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskDxeUnload (
+  IN EFI_HANDLE                   ImageHandle
+  )
+{
+  EFI_STATUS                      Status;
+  RAM_DISK_CONFIG_PRIVATE_DATA    *ConfigPrivate;
+
+  Status = gBS->HandleProtocol (
+                  mRamDiskHandle,
+                  &gEfiCallerIdGuid,
+                  (VOID **) &ConfigPrivate
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ASSERT (ConfigPrivate->Signature == RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE);
+
+  //
+  // Unregister all registered RAM disks
+  //
+  UnregisterAllRamDisks ();
+
+  gBS->UninstallMultipleProtocolInterfaces (
+         mRamDiskHandle,
+         &gEfiRamDiskProtocolGuid,
+         &mRamDiskProtocol,
+         &gEfiCallerIdGuid,
+         ConfigPrivate,
+         NULL
+         );
+
+  UninstallRamDiskConfigForm (ConfigPrivate);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
new file mode 100644
index 0000000..85913c5
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
@@ -0,0 +1,78 @@
+## @file
+#  Produces EFI_RAM_DISK_PROTOCOL and provides the capability to
+#  create/remove RAM disks in a setup browser.
+#
+#  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD 
License
+#  which accompanies this distribution.  The full text of the license may be 
found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = RamDiskDxe
+  MODULE_UNI_FILE           = RamDiskDxe.uni
+  FILE_GUID                 = 28A03FF4-12B3-4305-A417-BB1A4F94081E
+  MODULE_TYPE               = DXE_DRIVER
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = RamDiskDxeEntryPoint
+  UNLOAD_IMAGE              = RamDiskDxeUnload
+
+#
+# The following information is for reference only and not required by the 
build tools.
+#
+#  VALID_ARCHITECTURES      = IA32 X64 IPF EBC
+#
+
+[Sources]
+  RamDiskDriver.c
+  RamDiskImpl.c
+  RamDiskBlockIo.c
+  RamDiskProtocol.c
+  RamDiskFileExplorer.c
+  RamDiskImpl.h
+  RamDiskHii.vfr
+  RamDiskHiiStrings.uni
+  RamDiskNVData.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  UefiLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  UefiHiiServicesLib
+  MemoryAllocationLib
+  HiiLib
+  FileExplorerLib
+  DevicePathLib
+  PrintLib
+
+[Guids]
+  gEfiIfrTianoGuid                               ## PRODUCES            ## 
GUID  # HII opcode
+  ## PRODUCES                ## HII
+  ## CONSUMES                ## HII
+  gRamDiskFormSetGuid
+  gEfiVirtualDiskGuid                            ## SOMETIMES_CONSUMES  ## GUID
+  gEfiFileInfoGuid                               ## SOMETIMES_CONSUMES  ## 
GUID  # Indicate the information type
+
+[Protocols]
+  gEfiRamDiskProtocolGuid                        ## PRODUCES
+  gEfiHiiConfigAccessProtocolGuid                ## PRODUCES
+  gEfiDevicePathProtocolGuid                     ## PRODUCES
+  gEfiBlockIoProtocolGuid                        ## PRODUCES
+  gEfiSimpleFileSystemProtocolGuid               ## SOMETIMES_CONSUMES
+
+[Depex]
+  gEfiHiiConfigRoutingProtocolGuid  AND
+  gEfiHiiDatabaseProtocolGuid
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.uni 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.uni
new file mode 100644
index 0000000..19ffdbd
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.uni
@@ -0,0 +1,20 @@
+// /** @file
+// Produces EFI_RAM_DISK_PROTOCOL and provides the capability to
+// create/remove RAM disks in a setup browser.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD 
License
+// which accompanies this distribution. The full text of the license may be 
found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "Produces 
EFI_RAM_DISK_PROTOCOL and provides the capability to create/remove RAM disks in 
a setup browser."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module produces 
EFI_RAM_DISK_PROTOCOL and provides the capability to create/remove RAM disks in 
a setup browser."
+
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskFileExplorer.c 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskFileExplorer.c
new file mode 100644
index 0000000..2cfd4bb
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskFileExplorer.c
@@ -0,0 +1,253 @@
+/** @file
+  Internal file explorer helper functions for RamDiskDxe driver.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RamDiskImpl.h"
+
+
+/**
+  Helper function called as part of the code needed to allocate the proper
+  sized buffer for various EFI interfaces.
+
+  @param[in, out] Status     Current status.
+  @param[in, out] Buffer     Current allocated buffer, or NULL.
+  @param[in]      BufferSize Current buffer size needed.
+
+  @retval  TRUE         If the buffer was reallocated and the caller should
+                        try the API again.
+  @retval  FALSE        The caller should not call this function again.
+
+**/
+BOOLEAN
+GrowBuffer (
+  IN OUT EFI_STATUS   *Status,
+  IN OUT VOID         **Buffer,
+  IN UINTN            BufferSize
+  )
+{
+  BOOLEAN TryAgain;
+
+  //
+  // If this is an initial request, buffer will be null with a new buffer size
+  //
+  if ((*Buffer == NULL) && (BufferSize != 0)) {
+    *Status = EFI_BUFFER_TOO_SMALL;
+  }
+  //
+  // If the status code is "buffer too small", resize the buffer
+  //
+  TryAgain = FALSE;
+  if (*Status == EFI_BUFFER_TOO_SMALL) {
+
+    if (*Buffer != NULL) {
+      FreePool (*Buffer);
+    }
+
+    *Buffer = AllocateZeroPool (BufferSize);
+
+    if (*Buffer != NULL) {
+      TryAgain = TRUE;
+    } else {
+      *Status = EFI_OUT_OF_RESOURCES;
+    }
+  }
+  //
+  // If there's an error, free the buffer
+  //
+  if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {
+    FreePool (*Buffer);
+    *Buffer = NULL;
+  }
+
+  return TryAgain;
+}
+
+
+/**
+  This function gets the file information from an open file descriptor,
+  and stores it in a buffer allocated from pool.
+
+  @param[in] FHand           File Handle.
+
+  @return    A pointer to a buffer with file information or NULL is returned.
+
+**/
+EFI_FILE_INFO *
+FileInfo (
+  IN EFI_FILE_HANDLE                        FHand
+  )
+{
+  EFI_STATUS                           Status;
+  EFI_FILE_INFO                        *Buffer;
+  UINTN                                BufferSize;
+
+  //
+  // Initialize for GrowBuffer loop
+  //
+  Buffer      = NULL;
+  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;
+
+  //
+  // Call the real function
+  //
+  while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
+    Status = FHand->GetInfo (
+                      FHand,
+                      &gEfiFileInfoGuid,
+                      &BufferSize,
+                      Buffer
+                      );
+  }
+
+  return Buffer;
+}
+
+
+/**
+  This function will open a file or directory referenced by DevicePath.
+
+  This function opens a file with the open mode according to the file path. The
+  Attributes is valid only for EFI_FILE_MODE_CREATE.
+
+  @param[in, out] FilePath   On input, the device path to the file.
+                             On output, the remaining device path.
+  @param[out]     FileHandle Pointer to the file handle.
+  @param[in]      OpenMode   The mode to open the file with.
+  @param[in]      Attributes The file's file attributes.
+
+  @retval EFI_SUCCESS             The information was set.
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.
+  @retval EFI_UNSUPPORTED         Could not open the file path.
+  @retval EFI_NOT_FOUND           The specified file could not be found on the
+                                  device or the file system could not be found
+                                  on the device.
+  @retval EFI_NO_MEDIA            The device has no medium.
+  @retval EFI_MEDIA_CHANGED       The device has a different medium in it or
+                                  the medium is no longer supported.
+  @retval EFI_DEVICE_ERROR        The device reported an error.
+  @retval EFI_VOLUME_CORRUPTED    The file system structures are corrupted.
+  @retval EFI_WRITE_PROTECTED     The file or medium is write protected.
+  @retval EFI_ACCESS_DENIED       The file was opened read only.
+  @retval EFI_OUT_OF_RESOURCES    Not enough resources were available to open
+                                  the file.
+  @retval EFI_VOLUME_FULL         The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+OpenFileByDevicePath(
+  IN OUT EFI_DEVICE_PATH_PROTOCOL           **FilePath,
+  OUT EFI_FILE_HANDLE                       *FileHandle,
+  IN UINT64                                 OpenMode,
+  IN UINT64                                 Attributes
+  )
+{
+  EFI_STATUS                           Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL      *EfiSimpleFileSystemProtocol;
+  EFI_FILE_PROTOCOL                    *Handle1;
+  EFI_FILE_PROTOCOL                    *Handle2;
+  EFI_HANDLE                           DeviceHandle;
+
+  if ((FilePath == NULL || FileHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gBS->LocateDevicePath (
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  FilePath,
+                  &DeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol(
+                  DeviceHandle,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID**)&EfiSimpleFileSystemProtocol,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = 
EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
+  if (EFI_ERROR (Status)) {
+    FileHandle = NULL;
+    return Status;
+  }
+
+  //
+  // go down directories one node at a time.
+  //
+  while (!IsDevicePathEnd (*FilePath)) {
+    //
+    // For file system access each node should be a file path component
+    //
+    if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
+        DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
+       ) {
+      FileHandle = NULL;
+      return (EFI_INVALID_PARAMETER);
+    }
+    //
+    // Open this file path node
+    //
+    Handle2  = Handle1;
+    Handle1 = NULL;
+
+    //
+    // Try to test opening an existing file
+    //
+    Status = Handle2->Open (
+                          Handle2,
+                          &Handle1,
+                          ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                          OpenMode &~EFI_FILE_MODE_CREATE,
+                          0
+                         );
+
+    //
+    // see if the error was that it needs to be created
+    //
+    if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode 
&~EFI_FILE_MODE_CREATE))) {
+      Status = Handle2->Open (
+                            Handle2,
+                            &Handle1,
+                            ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                            OpenMode,
+                            Attributes
+                           );
+    }
+    //
+    // Close the last node
+    //
+    Handle2->Close (Handle2);
+
+    if (EFI_ERROR(Status)) {
+      return (Status);
+    }
+
+    //
+    // Get the next node
+    //
+    *FilePath = NextDevicePathNode (*FilePath);
+  }
+
+  //
+  // This is a weak spot since if the undefined SHELL_FILE_HANDLE format 
changes this must change also!
+  //
+  *FileHandle = (VOID*)Handle1;
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHii.vfr 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHii.vfr
new file mode 100644
index 0000000..9c3e3e4
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHii.vfr
@@ -0,0 +1,93 @@
+///** @file
+//  VFR file used by the RamDiskDxe driver.
+//
+//  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//  This program and the accompanying materials
+//  are licensed and made available under the terms and conditions of the BSD 
License
+//  which accompanies this distribution.  The full text of the license may be 
found at
+//  http://opensource.org/licenses/bsd-license.php
+//
+//  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+//
+//**/
+
+#include "RamDiskNVData.h"
+
+formset
+  guid      = RAM_DISK_FORM_SET_GUID,
+  title     = STRING_TOKEN(STR_FORM_SET_TITLE),
+  help      = STRING_TOKEN(STR_FORM_SET_TITLE_HELP),
+  classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
+
+  varstore RAM_DISK_CONFIGURATION,
+    varid = RAM_DISK_CONFIGURATION_VARSTORE_ID,
+    name  = RAM_DISK_CONFIGURATION,
+    guid  = RAM_DISK_FORM_SET_GUID;
+
+  //
+  // Form #1 "Main Form - Add/Remove/Show RAM Disks"
+  //
+  form formid = MAIN_FORM_ID,
+    title  = STRING_TOKEN(STR_MAIN_FORM_TITLE);
+
+    goto CREATE_RAW_RAM_DISK_FORM_ID,
+      prompt = STRING_TOKEN(STR_GOTO_ADD_RAW_FORM),
+      help   = STRING_TOKEN(STR_GOTO_ADD_RAW_FORM_HELP);
+
+    goto MAIN_FORM_ID,
+      prompt = STRING_TOKEN(STR_GOTO_ADD_FROM_FILE_FORM),
+      help   = STRING_TOKEN(STR_GOTO_ADD_FROM_FILE_FORM_HELP),
+      flags  = INTERACTIVE,
+      key    = MAIN_GOTO_FILE_EXPLORER_ID;
+
+    subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING);
+    subtitle text = STRING_TOKEN(STR_RAM_DISK_LIST_TEXT);
+
+    label MAIN_LABEL_LIST_START;
+    label MAIN_LABEL_LIST_END;
+
+    subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING);
+
+    text
+      help   = STRING_TOKEN(STR_REMOVE_SEL_HELP),
+      text   = STRING_TOKEN(STR_REMOVE_SEL_TEXT),
+      flags  = INTERACTIVE,
+      key    = MAIN_REMOVE_RD_QUESTION_ID;
+
+  endform;
+
+  //
+  // Form #2 "Add New Raw RAM Disk"
+  //
+  form formid = CREATE_RAW_RAM_DISK_FORM_ID,
+    title  = STRING_TOKEN(STR_ADD_RAW_FORM_TITLE);
+
+    subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING);
+
+    numeric varid   = RAM_DISK_CONFIGURATION.Size,
+      questionid = CREATE_RAW_SIZE_QUESTION_ID,
+      prompt  = STRING_TOKEN(STR_SIZE_PROMPT),
+      help    = STRING_TOKEN(STR_SIZE_HELP),
+      flags   = DISPLAY_UINT_HEX | INTERACTIVE,
+      minimum = 1,
+      maximum = 0xFFFFFFFFFFFFFFFF,
+    endnumeric;
+
+    subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING);
+
+    text
+      help   = STRING_TOKEN(STR_CREATE_AND_EXIT_HELP),
+      text   = STRING_TOKEN(STR_CREATE_AND_EXIT_PROMPT),
+      flags  = INTERACTIVE,
+      key    = CREATE_RAW_SUBMIT_QUESTION_ID;
+
+    text
+      help   = STRING_TOKEN(STR_DISCARD_AND_EXIT_HELP),
+      text   = STRING_TOKEN(STR_DISCARD_AND_EXIT_PROMPT),
+      flags  = INTERACTIVE,
+      key    = CREATE_RAW_DISCARD_QUESTION_ID;
+
+  endform;
+
+endformset;
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHiiStrings.uni 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHiiStrings.uni
new file mode 100644
index 0000000..3329f90
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHiiStrings.uni
@@ -0,0 +1,42 @@
+// /** @file
+// String definitions for RamDiskDxe driver form.
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD 
License
+// which accompanies this distribution. The full text of the license may be 
found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+//
+// **/
+
+#langdef en-US  "English"
+
+#string STR_FORM_SET_TITLE             #language en-US "RAM Disk Configutation"
+#string STR_FORM_SET_TITLE_HELP        #language en-US "Press <Enter> to 
add/remove RAM disks."
+
+#string STR_MAIN_FORM_TITLE            #language en-US "RAM Disk HII Main 
Screen"
+#string STR_RAM_DISK_NULL_STRING       #language en-US ""
+
+#string STR_RAM_DISK_LIST_TEXT         #language en-US "Created RAM disk list:"
+#string STR_RAM_DISK_LIST_HELP         #language en-US "Select for remove"
+#string STR_GOTO_ADD_RAW_FORM          #language en-US "Create raw"
+#string STR_GOTO_ADD_RAW_FORM_HELP     #language en-US "Create a raw RAM disk."
+#string STR_GOTO_ADD_FROM_FILE_FORM    #language en-US "Create from file"
+#string STR_GOTO_ADD_FROM_FILE_FORM_HELP #language en-US "Create a RAM disk 
from a given file."
+#string STR_REMOVE_SEL_HELP            #language en-US "Remove selected RAM 
disk(s)"
+#string STR_REMOVE_SEL_TEXT            #language en-US "Remove selected RAM 
disk(s)."
+
+#string STR_ADD_RAW_FORM_TITLE         #language en-US "Add A Raw RAM Disk"
+#string STR_ADD_RAW_FORM_SUBTITLE_TEXT #language en-US " "
+
+#string STR_SIZE_PROMPT                #language en-US "Size (Hex):"
+#string STR_SIZE_HELP                  #language en-US "The valid RAM disk 
size should be multiples of the RAM disk block size."
+
+#string STR_CREATE_AND_EXIT_HELP       #language en-US "Create a new RAM disk 
with the given starting and ending address."
+#string STR_CREATE_AND_EXIT_PROMPT     #language en-US "Create & Exit"
+#string STR_DISCARD_AND_EXIT_HELP      #language en-US "Discard and exit."
+#string STR_DISCARD_AND_EXIT_PROMPT    #language en-US "Discard & Exit"
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c
new file mode 100644
index 0000000..a2c48b2
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c
@@ -0,0 +1,807 @@
+/** @file
+  HII Config Access protocol implementation of RamDiskDxe driver.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RamDiskImpl.h"
+
+CHAR16  mRamDiskStorageName[] = L"RAM_DISK_CONFIGURATION";
+
+RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate = {
+  RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE,
+  {
+    RamDiskExtractConfig,
+    RamDiskRouteConfig,
+    RamDiskCallback
+  }
+};
+
+HII_VENDOR_DEVICE_PATH       mRamDiskHiiVendorDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    RAM_DISK_FORM_SET_GUID
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      (UINT8) (END_DEVICE_PATH_LENGTH),
+      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+    }
+  }
+};
+
+
+/**
+  This function publish the RAM disk configuration Form.
+
+  @param[in, out]  ConfigPrivateData
+                             Points to RAM disk configuration private data.
+
+  @retval EFI_SUCCESS             HII Form is installed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Not enough resource for HII Form 
installation.
+  @retval Others                  Other errors as indicated.
+
+**/
+EFI_STATUS
+InstallRamDiskConfigForm (
+  IN OUT RAM_DISK_CONFIG_PRIVATE_DATA       *ConfigPrivateData
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_HII_HANDLE                  HiiHandle;
+  EFI_HANDLE                      DriverHandle;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  *ConfigAccess;
+
+  DriverHandle = NULL;
+  ConfigAccess = &ConfigPrivateData->ConfigAccess;
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &DriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  &mRamDiskHiiVendorDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  ConfigAccess,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ConfigPrivateData->DriverHandle = DriverHandle;
+
+  //
+  // Publish the HII package list
+  //
+  HiiHandle = HiiAddPackages (
+                &gRamDiskFormSetGuid,
+                DriverHandle,
+                RamDiskDxeStrings,
+                RamDiskHiiBin,
+                NULL
+                );
+  if (HiiHandle == NULL) {
+    gBS->UninstallMultipleProtocolInterfaces (
+           DriverHandle,
+           &gEfiDevicePathProtocolGuid,
+           &mRamDiskHiiVendorDevicePath,
+           &gEfiHiiConfigAccessProtocolGuid,
+           ConfigAccess,
+           NULL
+           );
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ConfigPrivateData->HiiHandle = HiiHandle;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This function removes RAM disk configuration Form.
+
+  @param[in, out]  ConfigPrivateData
+                             Points to RAM disk configuration private data.
+
+**/
+VOID
+UninstallRamDiskConfigForm (
+  IN OUT RAM_DISK_CONFIG_PRIVATE_DATA       *ConfigPrivateData
+  )
+{
+  //
+  // Uninstall HII package list
+  //
+  if (ConfigPrivateData->HiiHandle != NULL) {
+    HiiRemovePackages (ConfigPrivateData->HiiHandle);
+    ConfigPrivateData->HiiHandle = NULL;
+  }
+
+  //
+  // Uninstall HII Config Access Protocol
+  //
+  if (ConfigPrivateData->DriverHandle != NULL) {
+    gBS->UninstallMultipleProtocolInterfaces (
+           ConfigPrivateData->DriverHandle,
+           &gEfiDevicePathProtocolGuid,
+           &mRamDiskHiiVendorDevicePath,
+           &gEfiHiiConfigAccessProtocolGuid,
+           &ConfigPrivateData->ConfigAccess,
+           NULL
+           );
+    ConfigPrivateData->DriverHandle = NULL;
+  }
+
+  FreePool (ConfigPrivateData);
+}
+
+
+/**
+  Unregister all registered RAM disks.
+
+**/
+VOID
+UnregisterAllRamDisks (
+  VOID
+  )
+{
+  LIST_ENTRY                      *Entry;
+  LIST_ENTRY                      *NextEntry;
+  RAM_DISK_PRIVATE_DATA           *PrivateData;
+
+  if (!IsListEmpty(&RegisteredRamDisks)) {
+    EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) {
+      PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
+
+      gBS->UninstallMultipleProtocolInterfaces (
+             PrivateData->Handle,
+             &gEfiBlockIoProtocolGuid,
+             &PrivateData->BlockIo,
+             &gEfiDevicePathProtocolGuid,
+             (EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath,
+             NULL
+             );
+
+      RemoveEntryList (&PrivateData->ThisInstance);
+
+      if (RamDiskCreateHii == PrivateData->CreateMethod) {
+        //
+        // If a RAM disk is created within HII, then the RamDiskDxe driver
+        // driver is responsible for freeing the allocated memory for the
+        // RAM disk.
+        //
+        FreePool ((VOID *)(UINTN) PrivateData->StartingAddr);
+      }
+
+
+      gBS->DisconnectController (PrivateData->Handle, NULL, NULL);
+
+      FreePool (PrivateData->DevicePath);
+      FreePool (PrivateData);
+      ListEntryNum--;
+    }
+  }
+}
+
+
+/**
+  This function allows a caller to extract the current configuration for one
+  or more named elements from the target driver.
+
+  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param[in]  Request        A null-terminated Unicode string in
+                             <ConfigRequest> format.
+  @param[out] Progress       On return, points to a character in the Request
+                             string. Points to the string's null terminator if
+                             request was successful. Points to the most recent
+                             '&' before the first failing name/value pair (or
+                             the beginning of the string if the failure is in
+                             the first name/value pair) if the request was not
+                             successful.
+  @param[out] Results        A null-terminated Unicode string in
+                             <ConfigAltResp> format which has all values filled
+                             in for the names in the Request string. String to
+                             be allocated by the called function.
+
+  @retval EFI_SUCCESS             The Results is filled with the requested
+                                  values.
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the results.
+  @retval EFI_INVALID_PARAMETER   Request is illegal syntax, or unknown name.
+  @retval EFI_NOT_FOUND           Routing data doesn't match any storage in
+                                  this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskExtractConfig (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN CONST EFI_STRING                       Request,
+       OUT EFI_STRING                       *Progress,
+       OUT EFI_STRING                       *Results
+  )
+{
+  EFI_STATUS                       Status;
+  UINTN                            BufferSize;
+  RAM_DISK_CONFIGURATION           *Configuration;
+  EFI_STRING                       ConfigRequest;
+  EFI_STRING                       ConfigRequestHdr;
+  RAM_DISK_CONFIG_PRIVATE_DATA     *ConfigPrivate;
+  UINTN                            Size;
+  BOOLEAN                          AllocatedRequest;
+
+  if (Progress == NULL || Results == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Progress = Request;
+  if ((Request != NULL) &&
+    !HiiIsConfigHdrMatch (Request, &gRamDiskFormSetGuid, mRamDiskStorageName)) 
{
+    return EFI_NOT_FOUND;
+  }
+
+  ConfigRequestHdr = NULL;
+  ConfigRequest    = NULL;
+  AllocatedRequest = FALSE;
+  Size             = 0;
+
+  //
+  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
+  //
+  ConfigPrivate = RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This);
+  BufferSize = sizeof (RAM_DISK_CONFIGURATION) + ListEntryNum;
+  Configuration = AllocateZeroPool (BufferSize);
+  if (Configuration == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  ConfigRequest = Request;
+  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+    //
+    // Request has no request element, construct full request string.
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a 
Null-terminator
+    //
+    ConfigRequestHdr = HiiConstructConfigHdr (
+                         &gRamDiskFormSetGuid,
+                         mRamDiskStorageName,
+                         ConfigPrivate->DriverHandle
+                         );
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+    ConfigRequest = AllocateZeroPool (Size);
+    ASSERT (ConfigRequest != NULL);
+    AllocatedRequest = TRUE;
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", 
ConfigRequestHdr, (UINT64)BufferSize);
+    FreePool (ConfigRequestHdr);
+  }
+
+  Status = gHiiConfigRouting->BlockToConfig (
+                                gHiiConfigRouting,
+                                ConfigRequest,
+                                (UINT8 *) &Configuration,
+                                BufferSize,
+                                Results,
+                                Progress
+                                );
+  //
+  // Free the allocated config request string and RAM disk configuration data.
+  //
+  if (AllocatedRequest) {
+    FreePool (ConfigRequest);
+    ConfigRequest = NULL;
+  }
+  FreePool (Configuration);
+
+  //
+  // Set Progress string to the original request string.
+  //
+  if (Request == NULL) {
+    *Progress = NULL;
+  } else if (StrStr (Request, L"OFFSET") == NULL) {
+    *Progress = Request + StrLen (Request);
+  }
+
+  return Status;
+}
+
+
+/**
+  This function processes the results of changes in configuration.
+
+  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param[in]  Configuration  A null-terminated Unicode string in <ConfigResp>
+                             format.
+  @param[out] Progress       A pointer to a string filled in with the offset of
+                             the most recent '&' before the first failing
+                             name/value pair (or the beginning of the string if
+                             the failure is in the first name/value pair) or
+                             the terminating NULL if all was successful.
+
+  @retval EFI_SUCCESS             The Results is processed successfully.
+  @retval EFI_INVALID_PARAMETER   Configuration is NULL.
+  @retval EFI_NOT_FOUND           Routing data doesn't match any storage in
+                                  this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskRouteConfig (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN CONST EFI_STRING                       Configuration,
+       OUT EFI_STRING                       *Progress
+  )
+{
+  if (Configuration == NULL || Progress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Progress = Configuration;
+  if (!HiiIsConfigHdrMatch (Configuration, &gRamDiskFormSetGuid, 
mRamDiskStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+
+  *Progress = Configuration + StrLen (Configuration);
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Allocate memory and register the RAM disk created within RamDiskDxe
+  driver HII.
+
+  @param[in] Size            If creating raw, size of the RAM disk to create.
+                             If creating from file, zero.
+  @param[in] FileHandle      If creating raw, NULL. If creating from file, the
+                             file handle.
+
+  @retval EFI_SUCCESS             RAM disk is created and registered.
+  @retval EFI_OUT_OF_RESOURCES    Not enough storage is available to match the
+                                  size required.
+
+**/
+EFI_STATUS
+HiiCreateRamDisk (
+  IN UINT64                                 Size,
+  IN EFI_FILE_HANDLE                        FileHandle
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           BufferSize;
+  UINT64                          StartingAddr;
+  EFI_INPUT_KEY                   Key;
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
+  RAM_DISK_PRIVATE_DATA           *PrivateData;
+  EFI_FILE_INFO                   *FileInformation;
+
+  FileInformation = NULL;
+
+  if (FileHandle != NULL) {
+    //
+    // Create from file.
+    //
+    FileInformation = FileInfo (FileHandle);
+    if (NULL == FileInformation) {
+      do {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"",
+          L"Not enough memory to get the file information!",
+          L"Press ENTER to continue ...",
+          L"",
+          NULL
+          );
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    //
+    // Update the size of RAM disk according to the file size.
+    //
+    Size = FileInformation->FileSize;
+  }
+
+  StartingAddr = (UINTN) AllocatePool ((UINTN) Size);
+  if (0 == StartingAddr) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"",
+        L"Not enough memory to create the RAM disk!",
+        L"Press ENTER to continue ...",
+        L"",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  if (FileHandle != NULL) {
+    //
+    // Copy the file content to the RAM disk.
+    //
+    BufferSize = (UINTN) Size;
+    FileHandle->Read (
+                  FileHandle,
+                  &BufferSize,
+                  (VOID *)(UINTN) StartingAddr
+                  );
+    if (BufferSize != FileInformation->FileSize) {
+      do {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"",
+          L"File content read error!",
+          L"Press ENTER to continue ...",
+          L"",
+          NULL
+          );
+      } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+      return EFI_DEVICE_ERROR;
+    }
+  }
+
+  //
+  // Register the newly created RAM disk.
+  //
+  Status = RamDiskRegister (
+             StartingAddr,
+             Size,
+             &gEfiVirtualDiskGuid,
+             NULL,
+             &DevicePath
+             );
+  if (EFI_ERROR (Status)) {
+    do {
+      CreatePopUp (
+        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+        &Key,
+        L"",
+        L"Fail to register the newly created RAM disk!",
+        L"Press ENTER to continue ...",
+        L"",
+        NULL
+        );
+    } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
+
+    return Status;
+  }
+
+  //
+  // If RAM disk is created within HII, memory should be freed when the
+  // RAM disk is unregisterd.
+  //
+  PrivateData = RAM_DISK_PRIVATE_FROM_THIS (RegisteredRamDisks.BackLink);
+  PrivateData->CreateMethod = RamDiskCreateHii;
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This function updates the registered RAM disks list on the main form.
+
+  @param[in, out] ConfigPrivate
+                             Private data for configurating hii data for RAM
+                             disks.
+
+**/
+VOID
+UpdateMainForm (
+  IN OUT RAM_DISK_CONFIG_PRIVATE_DATA       *ConfigPrivate
+  )
+{
+  VOID                      *StartOpCodeHandle;
+  VOID                      *EndOpCodeHandle;
+  EFI_IFR_GUID_LABEL        *StartLabel;
+  EFI_IFR_GUID_LABEL        *EndLabel;
+  LIST_ENTRY                *Entry;
+  UINTN                     Index;
+  RAM_DISK_PRIVATE_DATA     *PrivateData;
+  CHAR16                    *String;
+  CHAR16                    RamDiskStr[128];
+  EFI_STRING_ID             StringId;
+  EFI_TPL                   OldTpl;
+
+  //
+  // Init OpCode Handle
+  //
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (StartOpCodeHandle != NULL);
+
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  ASSERT (EndOpCodeHandle != NULL);
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                        StartOpCodeHandle,
+                                        &gEfiIfrTianoGuid,
+                                        NULL,
+                                        sizeof (EFI_IFR_GUID_LABEL)
+                                        );
+  StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  StartLabel->Number       = MAIN_LABEL_LIST_START;
+
+  //
+  // Create Hii Extend Label OpCode as the end opcode
+  //
+  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                      EndOpCodeHandle,
+                                      &gEfiIfrTianoGuid,
+                                      NULL,
+                                      sizeof (EFI_IFR_GUID_LABEL)
+                                      );
+  EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  EndLabel->Number       = MAIN_LABEL_LIST_END;
+
+  Index = 0;
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+  EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) {
+    PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
+    String      = RamDiskStr;
+
+    UnicodeSPrint (
+      String,
+      sizeof (RamDiskStr),
+      L"  RAM Disk %d: [0x%lx, 0x%lx]\n",
+      Index,
+      PrivateData->StartingAddr,
+      PrivateData->StartingAddr + PrivateData->Size
+      );
+
+    StringId = HiiSetString (ConfigPrivate->HiiHandle, 0, RamDiskStr, NULL);
+    ASSERT (StringId != 0);
+
+    HiiCreateCheckBoxOpCode (
+      StartOpCodeHandle,
+      (EFI_QUESTION_ID) (MAIN_CHECKBOX_QUESTION_ID_START + Index),
+      RAM_DISK_CONFIGURATION_VARSTORE_ID,
+      (UINT16) (RAM_DISK_LIST_VAR_OFFSET + Index),
+      StringId,
+      STRING_TOKEN (STR_RAM_DISK_LIST_HELP),
+      0,
+      0,
+      NULL
+      );
+
+    Index++;
+  }
+  gBS->RestoreTPL (OldTpl);
+
+  HiiUpdateForm (
+    ConfigPrivate->HiiHandle,
+    &gRamDiskFormSetGuid,
+    MAIN_FORM_ID,
+    StartOpCodeHandle,
+    EndOpCodeHandle
+    );
+
+  HiiFreeOpCodeHandle (StartOpCodeHandle);
+  HiiFreeOpCodeHandle (EndOpCodeHandle);
+}
+
+
+/**
+  This function processes the results of changes in configuration.
+
+  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param[in]  Action         Specifies the type of action taken by the browser.
+  @param[in]  QuestionId     A unique value which is sent to the original
+                             exporting driver so that it can identify the type
+                             of data to expect.
+  @param[in]  Type           The type of value for the question.
+  @param[in]  Value          A pointer to the data being sent to the original
+                             exporting driver.
+  @param[out] ActionRequest  On return, points to the action requested by the
+                             callback function.
+
+  @retval EFI_SUCCESS             The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES    Not enough storage is available to hold the
+                                  variable and its data.
+  @retval EFI_DEVICE_ERROR        The variable could not be saved.
+  @retval EFI_UNSUPPORTED         The specified Action is not supported by the
+                                  callback.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskCallback (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                 Action,
+  IN     EFI_QUESTION_ID                    QuestionId,
+  IN     UINT8                              Type,
+  IN     EFI_IFR_TYPE_VALUE                 *Value,
+     OUT EFI_BROWSER_ACTION_REQUEST         *ActionRequest
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           Index;
+  RAM_DISK_PRIVATE_DATA           *PrivateData;
+  RAM_DISK_CONFIG_PRIVATE_DATA    *ConfigPrivate;
+  RAM_DISK_CONFIGURATION          *Configuration;
+  EFI_DEVICE_PATH_PROTOCOL        *FileDevPath;
+  EFI_FILE_HANDLE                 FileHandle;
+  LIST_ENTRY                      *Entry;
+  LIST_ENTRY                      *NextEntry;
+  EFI_TPL                         OldTpl;
+
+  if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
+    Status = EFI_UNSUPPORTED;
+    if (QuestionId == CREATE_RAW_SIZE_QUESTION_ID) {
+      Value->u64 = EFI_PAGE_SIZE;
+      Status = EFI_SUCCESS;
+    }
+    return Status;
+  }
+
+  if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
+      (Action != EFI_BROWSER_ACTION_CHANGING) &&
+      (Action != EFI_BROWSER_ACTION_FORM_OPEN)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  ConfigPrivate = RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This);
+
+  //
+  // Update the RAM disk list show at the main form first.
+  //
+  if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
+    Status = EFI_UNSUPPORTED;
+    if (QuestionId == MAIN_GOTO_FILE_EXPLORER_ID) {
+      UpdateMainForm (ConfigPrivate);
+      Status = EFI_SUCCESS;
+    }
+    return Status;
+  }
+
+  //
+  // Get Browser data
+  //
+  Configuration = AllocateZeroPool (sizeof (RAM_DISK_CONFIGURATION) + 
ListEntryNum);
+  if (Configuration == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Status = EFI_SUCCESS;
+
+  HiiGetBrowserData (
+    &gRamDiskFormSetGuid,
+    mRamDiskStorageName,
+    sizeof (RAM_DISK_CONFIGURATION) + ListEntryNum,
+    (UINT8 *) Configuration
+    );
+
+  if (Action == EFI_BROWSER_ACTION_CHANGING) {
+    switch (QuestionId) {
+    case MAIN_GOTO_FILE_EXPLORER_ID:
+      Status = ChooseFile (NULL, NULL, NULL, &FileDevPath);
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+
+      if (FileDevPath != NULL) {
+        //
+        // Open the file.
+        //
+        Status = OpenFileByDevicePath (
+                   &FileDevPath,
+                   &FileHandle,
+                   EFI_FILE_MODE_READ,
+                   0
+                   );
+        if (EFI_ERROR (Status)) {
+          break;
+        }
+
+        //
+        // Create from file, RAM disk size is zero. It will be updated
+        // according to the file size.
+        //
+        Status = HiiCreateRamDisk (0, FileHandle);
+        if (EFI_ERROR (Status)) {
+          break;
+        }
+
+        //
+        // Refresh the registered RAM disks list.
+        //
+        UpdateMainForm (ConfigPrivate);
+      }
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+      break;
+
+    default:
+      break;
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
+    switch (QuestionId) {
+    case MAIN_REMOVE_RD_QUESTION_ID:
+      //
+      // Remove the selected RAM disks
+      //
+      Index = 0;
+      OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+      EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) {
+        if (Configuration->RamDiskList[Index++] != 0) {
+          PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
+
+          RamDiskUnregister (
+            (EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath
+            );
+        }
+      }
+      gBS->RestoreTPL (OldTpl);
+
+      UpdateMainForm (ConfigPrivate);
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+      ZeroMem (Configuration->RamDiskList, ListEntryNum);
+      break;
+
+    case CREATE_RAW_SUBMIT_QUESTION_ID:
+      //
+      // Create raw, FileHandle is NULL.
+      //
+      Status = HiiCreateRamDisk (Configuration->Size, NULL);
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+
+      //
+      // Refresh the registered RAM disks list.
+      //
+      UpdateMainForm (ConfigPrivate);
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+      break;
+
+    case CREATE_RAW_DISCARD_QUESTION_ID:
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    HiiSetBrowserData (
+      &gRamDiskFormSetGuid,
+      mRamDiskStorageName,
+      sizeof (RAM_DISK_CONFIGURATION) + ListEntryNum,
+      (UINT8 *) Configuration,
+      NULL
+      );
+  }
+  FreePool (Configuration);
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.h 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.h
new file mode 100644
index 0000000..4725006
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.h
@@ -0,0 +1,499 @@
+/** @file
+  The header file of RamDiskDxe driver.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _RAM_DISK_IMPL_H_
+#define _RAM_DISK_IMPL_H_
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileExplorerLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+#include <Protocol/RamDisk.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Guid/MdeModuleHii.h>
+#include <Guid/RamDiskHii.h>
+#include <Guid/FileInfo.h>
+
+#include "RamDiskNVData.h"
+
+///
+/// RAM disk general definitions and declarations
+///
+
+//
+// Block size for RAM disk
+//
+#define RAM_DISK_BLOCK_SIZE 512
+
+//
+// Iterate through the doule linked list. NOT delete safe
+//
+#define EFI_LIST_FOR_EACH(Entry, ListHead)    \
+  for(Entry = (ListHead)->ForwardLink; Entry != (ListHead); Entry = 
Entry->ForwardLink)
+
+//
+// Iterate through the doule linked list. This is delete-safe.
+// Do not touch NextEntry
+//
+#define EFI_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead)            \
+  for(Entry = (ListHead)->ForwardLink, NextEntry = Entry->ForwardLink;\
+      Entry != (ListHead); Entry = NextEntry, NextEntry = Entry->ForwardLink)
+
+//
+// RamDiskDxe driver maintains a list of registered RAM disks.
+//
+extern  LIST_ENTRY                RegisteredRamDisks;
+extern  UINTN                     ListEntryNum;
+
+//
+// RAM Disk create method.
+//
+typedef enum _RAM_DISK_CREATE_METHOD {
+  RamDiskCreateOthers             = 0,
+  RamDiskCreateHii
+} RAM_DISK_CREATE_METHOD;
+
+//
+// RamDiskDxe driver maintains a list of registered RAM disks.
+// The struct contains the list entry and the information of each RAM
+// disk
+//
+typedef struct {
+  UINTN                           Signature;
+
+  EFI_HANDLE                      Handle;
+
+  EFI_BLOCK_IO_PROTOCOL           BlockIo;
+  EFI_BLOCK_IO_MEDIA              Media;
+  EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
+
+  UINT64                          StartingAddr;
+  UINT64                          Size;
+  EFI_GUID                        TypeGuid;
+  UINT16                          InstanceNumber;
+  RAM_DISK_CREATE_METHOD          CreateMethod;
+
+  LIST_ENTRY                      ThisInstance;
+} RAM_DISK_PRIVATE_DATA;
+
+#define RAM_DISK_PRIVATE_DATA_SIGNATURE     SIGNATURE_32 ('R', 'D', 'S', 'K')
+#define RAM_DISK_PRIVATE_FROM_BLKIO(a)      CR (a, RAM_DISK_PRIVATE_DATA, 
BlockIo, RAM_DISK_PRIVATE_DATA_SIGNATURE)
+#define RAM_DISK_PRIVATE_FROM_THIS(a)       CR (a, RAM_DISK_PRIVATE_DATA, 
ThisInstance, RAM_DISK_PRIVATE_DATA_SIGNATURE)
+
+///
+/// RAM disk HII-related definitions and declarations
+///
+
+//
+// Tool generated IFR binary data and String package data
+//
+extern  UINT8                     RamDiskHiiBin[];
+extern  UINT8                     RamDiskDxeStrings[];
+
+typedef struct {
+  VENDOR_DEVICE_PATH              VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL        End;
+} HII_VENDOR_DEVICE_PATH;
+
+typedef struct {
+  UINTN                           Signature;
+
+  EFI_HII_CONFIG_ACCESS_PROTOCOL  ConfigAccess;
+  EFI_HANDLE                      DriverHandle;
+  EFI_HII_HANDLE                  HiiHandle;
+} RAM_DISK_CONFIG_PRIVATE_DATA;
+
+extern RAM_DISK_CONFIG_PRIVATE_DATA    mRamDiskConfigPrivateDataTemplate;
+
+#define RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE   SIGNATURE_32 ('R', 'C', 'F', 
'G')
+#define RAM_DISK_CONFIG_PRIVATE_FROM_THIS(a)     CR (a, 
RAM_DISK_CONFIG_PRIVATE_DATA, ConfigAccess, 
RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE)
+
+#define RAM_DISK_LIST_VAR_OFFSET                 ((UINT16) OFFSET_OF 
(RAM_DISK_CONFIGURATION, RamDiskList))
+
+/**
+  Register a RAM disk with specified address, size and type.
+
+  @param[in]  RamDiskBase    The base address of registered RAM disk.
+  @param[in]  RamDiskSize    The size of registered RAM disk.
+  @param[in]  RamDiskType    The type of registered RAM disk. The GUID can be
+                             any of the values defined in section 9.3.6.9, or a
+                             vendor defined GUID.
+  @param[in]  ParentDevicePath
+                             Pointer to the parent device path. If there is no
+                             parent device path then ParentDevicePath is NULL.
+  @param[out] DevicePath     On return, points to a pointer to the device path
+                             of the RAM disk device.
+                             If ParentDevicePath is not NULL, the returned
+                             DevicePath is created by appending a RAM disk node
+                             to the parent device path. If ParentDevicePath is
+                             NULL, the returned DevicePath is a RAM disk device
+                             path without appending. This function is
+                             responsible for allocating the buffer DevicePath
+                             with the boot service AllocatePool().
+
+  @retval EFI_SUCCESS             The RAM disk is registered successfully.
+  @retval EFI_INVALID_PARAMETER   DevicePath or RamDiskType is NULL.
+                                  RamDiskSize is 0.
+  @retval EFI_ALREADY_STARTED     A Device Path Protocol instance to be created
+                                  is already present in the handle database.
+  @retval EFI_OUT_OF_RESOURCES    The RAM disk register operation fails due to
+                                  resource limitation.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskRegister (
+  IN UINT64                       RamDiskBase,
+  IN UINT64                       RamDiskSize,
+  IN EFI_GUID                     *RamDiskType,
+  IN EFI_DEVICE_PATH              *ParentDevicePath     OPTIONAL,
+  OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
+  );
+
+/**
+  Unregister a RAM disk specified by DevicePath.
+
+  @param[in] DevicePath      A pointer to the device path that describes a RAM
+                             Disk device.
+
+  @retval EFI_SUCCESS             The RAM disk is unregistered successfully.
+  @retval EFI_INVALID_PARAMETER   DevicePath is NULL.
+  @retval EFI_UNSUPPORTED         The device specified by DevicePath is not a
+                                  valid ramdisk device path and not supported
+                                  by the driver.
+  @retval EFI_NOT_FOUND           The RAM disk pointed by DevicePath doesn't
+                                  exist.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskUnregister (
+  IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath
+  );
+
+/**
+  Initialize the BlockIO protocol of a RAM disk device.
+
+  @param[in] PrivateData     Points to RAM disk private data.
+
+**/
+VOID
+RamDiskInitBlockIo (
+  IN     RAM_DISK_PRIVATE_DATA    *PrivateData
+  );
+
+/**
+  Reset the Block Device.
+
+  @param[in] This            Indicates a pointer to the calling context.
+  @param[in] ExtendedVerification
+                             Driver may perform diagnostics on reset.
+
+  @retval EFI_SUCCESS             The device was reset.
+  @retval EFI_DEVICE_ERROR        The device is not functioning properly and
+                                  could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIoReset (
+  IN EFI_BLOCK_IO_PROTOCOL        *This,
+  IN BOOLEAN                      ExtendedVerification
+  );
+
+/**
+  Read BufferSize bytes from Lba into Buffer.
+
+  @param[in]  This           Indicates a pointer to the calling context.
+  @param[in]  MediaId        Id of the media, changes every time the media is
+                             replaced.
+  @param[in]  Lba            The starting Logical Block Address to read from.
+  @param[in]  BufferSize     Size of Buffer, must be a multiple of device block
+                             size.
+  @param[out] Buffer         A pointer to the destination buffer for the data.
+                             The caller is responsible for either having
+                             implicit or explicit ownership of the buffer.
+
+  @retval EFI_SUCCESS             The data was read correctly from the device.
+  @retval EFI_DEVICE_ERROR        The device reported an error while performing
+                                  the read.
+  @retval EFI_NO_MEDIA            There is no media in the device.
+  @retval EFI_MEDIA_CHANGED       The MediaId does not matched the current
+                                  device.
+  @retval EFI_BAD_BUFFER_SIZE     The Buffer was not a multiple of the block
+                                  size of the device.
+  @retval EFI_INVALID_PARAMETER   The read request contains LBAs that are not
+                                  valid, or the buffer is not on proper 
alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIoReadBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL        *This,
+  IN UINT32                       MediaId,
+  IN EFI_LBA                      Lba,
+  IN UINTN                        BufferSize,
+  OUT VOID                        *Buffer
+  );
+
+/**
+  Write BufferSize bytes from Lba into Buffer.
+
+  @param[in] This            Indicates a pointer to the calling context.
+  @param[in] MediaId         The media ID that the write request is for.
+  @param[in] Lba             The starting logical block address to be written.
+                             The caller is responsible for writing to only
+                             legitimate locations.
+  @param[in] BufferSize      Size of Buffer, must be a multiple of device block
+                             size.
+  @param[in] Buffer          A pointer to the source buffer for the data.
+
+  @retval EFI_SUCCESS             The data was written correctly to the device.
+  @retval EFI_WRITE_PROTECTED     The device can not be written to.
+  @retval EFI_DEVICE_ERROR        The device reported an error while performing
+                                  the write.
+  @retval EFI_NO_MEDIA            There is no media in the device.
+  @retval EFI_MEDIA_CHNAGED       The MediaId does not matched the current
+                                  device.
+  @retval EFI_BAD_BUFFER_SIZE     The Buffer was not a multiple of the block
+                                  size of the device.
+  @retval EFI_INVALID_PARAMETER   The write request contains LBAs that are not
+                                  valid, or the buffer is not on proper 
alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIoWriteBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL        *This,
+  IN UINT32                       MediaId,
+  IN EFI_LBA                      Lba,
+  IN UINTN                        BufferSize,
+  IN VOID                         *Buffer
+  );
+
+/**
+  Flush the Block Device.
+
+  @param[in] This            Indicates a pointer to the calling context.
+
+  @retval EFI_SUCCESS             All outstanding data was written to the 
device.
+  @retval EFI_DEVICE_ERROR        The device reported an error while writting
+                                  back the data
+  @retval EFI_NO_MEDIA            There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIoFlushBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL        *This
+  );
+
+/**
+  This function publish the RAM disk configuration Form.
+
+  @param[in, out]  ConfigPrivateData
+                             Points to RAM disk configuration private data.
+
+  @retval EFI_SUCCESS             HII Form is installed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Not enough resource for HII Form 
installation.
+  @retval Others                  Other errors as indicated.
+
+**/
+EFI_STATUS
+InstallRamDiskConfigForm (
+  IN OUT RAM_DISK_CONFIG_PRIVATE_DATA       *ConfigPrivateData
+  );
+
+/**
+  This function removes RAM disk configuration Form.
+
+  @param[in, out]  ConfigPrivateData
+                             Points to RAM disk configuration private data.
+
+**/
+VOID
+UninstallRamDiskConfigForm (
+  IN OUT RAM_DISK_CONFIG_PRIVATE_DATA       *ConfigPrivateData
+  );
+
+/**
+  Unregister all registered RAM disks.
+
+**/
+VOID
+UnregisterAllRamDisks (
+  VOID
+  );
+
+/**
+  This function allows a caller to extract the current configuration for one
+  or more named elements from the target driver.
+
+  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param[in]  Request        A null-terminated Unicode string in
+                             <ConfigRequest> format.
+  @param[out] Progress       On return, points to a character in the Request
+                             string. Points to the string's null terminator if
+                             request was successful. Points to the most recent
+                             '&' before the first failing name/value pair (or
+                             the beginning of the string if the failure is in
+                             the first name/value pair) if the request was not
+                             successful.
+  @param[out] Results        A null-terminated Unicode string in
+                             <ConfigAltResp> format which has all values filled
+                             in for the names in the Request string. String to
+                             be allocated by the called function.
+
+  @retval EFI_SUCCESS             The Results is filled with the requested
+                                  values.
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the results.
+  @retval EFI_INVALID_PARAMETER   Request is illegal syntax, or unknown name.
+  @retval EFI_NOT_FOUND           Routing data doesn't match any storage in
+                                  this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskExtractConfig (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN CONST EFI_STRING                       Request,
+       OUT EFI_STRING                       *Progress,
+       OUT EFI_STRING                       *Results
+  );
+
+/**
+  This function processes the results of changes in configuration.
+
+  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param[in]  Configuration  A null-terminated Unicode string in <ConfigResp>
+                             format.
+  @param[out] Progress       A pointer to a string filled in with the offset of
+                             the most recent '&' before the first failing
+                             name/value pair (or the beginning of the string if
+                             the failure is in the first name/value pair) or
+                             the terminating NULL if all was successful.
+
+  @retval EFI_SUCCESS             The Results is processed successfully.
+  @retval EFI_INVALID_PARAMETER   Configuration is NULL.
+  @retval EFI_NOT_FOUND           Routing data doesn't match any storage in
+                                  this driver.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskRouteConfig (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN CONST EFI_STRING                       Configuration,
+       OUT EFI_STRING                       *Progress
+  );
+
+/**
+  This function processes the results of changes in configuration.
+
+  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param[in]  Action         Specifies the type of action taken by the browser.
+  @param[in]  QuestionId     A unique value which is sent to the original
+                             exporting driver so that it can identify the type
+                             of data to expect.
+  @param[in]  Type           The type of value for the question.
+  @param[in]  Value          A pointer to the data being sent to the original
+                             exporting driver.
+  @param[out] ActionRequest  On return, points to the action requested by the
+                             callback function.
+
+  @retval EFI_SUCCESS             The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES    Not enough storage is available to hold the
+                                  variable and its data.
+  @retval EFI_DEVICE_ERROR        The variable could not be saved.
+  @retval EFI_UNSUPPORTED         The specified Action is not supported by the
+                                  callback.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskCallback (
+  IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                 Action,
+  IN     EFI_QUESTION_ID                    QuestionId,
+  IN     UINT8                              Type,
+  IN     EFI_IFR_TYPE_VALUE                 *Value,
+     OUT EFI_BROWSER_ACTION_REQUEST         *ActionRequest
+  );
+
+
+/**
+  This function gets the file information from an open file descriptor,
+  and stores it in a buffer allocated from pool.
+
+  @param[in] FHand           File Handle.
+
+  @return    A pointer to a buffer with file information or NULL is returned.
+
+**/
+EFI_FILE_INFO *
+FileInfo (
+  IN EFI_FILE_HANDLE                        FHand
+  );
+
+
+/**
+  This function will open a file or directory referenced by DevicePath.
+
+  This function opens a file with the open mode according to the file path. The
+  Attributes is valid only for EFI_FILE_MODE_CREATE.
+
+  @param[in, out] FilePath   On input, the device path to the file.
+                             On output, the remaining device path.
+  @param[out]     FileHandle Pointer to the file handle.
+  @param[in]      OpenMode   The mode to open the file with.
+  @param[in]      Attributes The file's file attributes.
+
+  @retval EFI_SUCCESS             The information was set.
+  @retval EFI_INVALID_PARAMETER   One of the parameters has an invalid value.
+  @retval EFI_UNSUPPORTED         Could not open the file path.
+  @retval EFI_NOT_FOUND           The specified file could not be found on the
+                                  device or the file system could not be found
+                                  on the device.
+  @retval EFI_NO_MEDIA            The device has no medium.
+  @retval EFI_MEDIA_CHANGED       The device has a different medium in it or
+                                  the medium is no longer supported.
+  @retval EFI_DEVICE_ERROR        The device reported an error.
+  @retval EFI_VOLUME_CORRUPTED    The file system structures are corrupted.
+  @retval EFI_WRITE_PROTECTED     The file or medium is write protected.
+  @retval EFI_ACCESS_DENIED       The file was opened read only.
+  @retval EFI_OUT_OF_RESOURCES    Not enough resources were available to open
+                                  the file.
+  @retval EFI_VOLUME_FULL         The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+OpenFileByDevicePath(
+  IN OUT EFI_DEVICE_PATH_PROTOCOL           **FilePath,
+  OUT EFI_FILE_HANDLE                       *FileHandle,
+  IN UINT64                                 OpenMode,
+  IN UINT64                                 Attributes
+  );
+
+#endif
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskNVData.h 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskNVData.h
new file mode 100644
index 0000000..2b5d045
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskNVData.h
@@ -0,0 +1,43 @@
+/** @file
+  Header file for NV data structure definition.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _RAM_DISK_NVDATA_H_
+#define _RAM_DISK_NVDATA_H_
+
+#include <Guid/HiiPlatformSetupFormset.h>
+#include <Guid/RamDiskHii.h>
+
+#define RAM_DISK_CONFIGURATION_VARSTORE_ID  0x0001
+
+#define MAIN_FORM_ID                        0x1000
+#define MAIN_GOTO_FILE_EXPLORER_ID          0x1001
+#define MAIN_REMOVE_RD_QUESTION_ID          0x1002
+#define MAIN_CHECKBOX_QUESTION_ID_START     0x1003
+#define MAIN_LABEL_LIST_START               0x1004
+#define MAIN_LABEL_LIST_END                 0x1005
+
+#define CREATE_RAW_RAM_DISK_FORM_ID         0x2000
+#define CREATE_RAW_SIZE_QUESTION_ID         0x2001
+#define CREATE_RAW_SUBMIT_QUESTION_ID       0x2002
+#define CREATE_RAW_DISCARD_QUESTION_ID      0x2003
+
+typedef struct {
+  UINT64                          Size;
+  //
+  // CheckBox status for created RAM disks
+  //
+  UINT8                           RamDiskList[0];
+} RAM_DISK_CONFIGURATION;
+
+#endif
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskProtocol.c 
b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskProtocol.c
new file mode 100644
index 0000000..9fe888e
--- /dev/null
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskProtocol.c
@@ -0,0 +1,356 @@
+/** @file
+  The realization of EFI_RAM_DISK_PROTOCOL.
+
+  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD 
License
+  which accompanies this distribution.  The full text of the license may be 
found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "RamDiskImpl.h"
+
+RAM_DISK_PRIVATE_DATA mRamDiskPrivateDataTemplate = {
+  RAM_DISK_PRIVATE_DATA_SIGNATURE,
+  NULL
+};
+
+MEDIA_RAM_DISK_DEVICE_PATH  mRamDiskDeviceNodeTemplate = {
+  {
+    MEDIA_DEVICE_PATH,
+    MEDIA_RAM_DISK_DP,
+    {
+      (UINT8) (sizeof (MEDIA_RAM_DISK_DEVICE_PATH)),
+      (UINT8) ((sizeof (MEDIA_RAM_DISK_DEVICE_PATH)) >> 8)
+    }
+  }
+};
+
+
+/**
+  Initialize the RAM disk device node.
+
+  @param[in]      PrivateData     Points to RAM disk private data.
+  @param[in, out] RamDiskDevNode  Points to the RAM disk device node.
+
+**/
+VOID
+RamDiskInitDeviceNode (
+  IN     RAM_DISK_PRIVATE_DATA         *PrivateData,
+  IN OUT MEDIA_RAM_DISK_DEVICE_PATH    *RamDiskDevNode
+  )
+{
+  WriteUnaligned64 (
+    (UINT64 *) &(RamDiskDevNode->StartingAddr[0]),
+    (UINT64) PrivateData->StartingAddr
+    );
+  WriteUnaligned64 (
+    (UINT64 *) &(RamDiskDevNode->EndingAddr[0]),
+    (UINT64) PrivateData->StartingAddr + PrivateData->Size
+    );
+  CopyGuid (&RamDiskDevNode->TypeGuid, &PrivateData->TypeGuid);
+  RamDiskDevNode->Instance = PrivateData->InstanceNumber;
+}
+
+
+/**
+  Register a RAM disk with specified address, size and type.
+
+  @param[in]  RamDiskBase    The base address of registered RAM disk.
+  @param[in]  RamDiskSize    The size of registered RAM disk.
+  @param[in]  RamDiskType    The type of registered RAM disk. The GUID can be
+                             any of the values defined in section 9.3.6.9, or a
+                             vendor defined GUID.
+  @param[in]  ParentDevicePath
+                             Pointer to the parent device path. If there is no
+                             parent device path then ParentDevicePath is NULL.
+  @param[out] DevicePath     On return, points to a pointer to the device path
+                             of the RAM disk device.
+                             If ParentDevicePath is not NULL, the returned
+                             DevicePath is created by appending a RAM disk node
+                             to the parent device path. If ParentDevicePath is
+                             NULL, the returned DevicePath is a RAM disk device
+                             path without appending. This function is
+                             responsible for allocating the buffer DevicePath
+                             with the boot service AllocatePool().
+
+  @retval EFI_SUCCESS             The RAM disk is registered successfully.
+  @retval EFI_INVALID_PARAMETER   DevicePath or RamDiskType is NULL.
+                                  RamDiskSize is 0.
+  @retval EFI_ALREADY_STARTED     A Device Path Protocol instance to be created
+                                  is already present in the handle database.
+  @retval EFI_OUT_OF_RESOURCES    The RAM disk register operation fails due to
+                                  resource limitation.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskRegister (
+  IN UINT64                       RamDiskBase,
+  IN UINT64                       RamDiskSize,
+  IN EFI_GUID                     *RamDiskType,
+  IN EFI_DEVICE_PATH              *ParentDevicePath     OPTIONAL,
+  OUT EFI_DEVICE_PATH_PROTOCOL    **DevicePath
+  )
+{
+  EFI_STATUS                      Status;
+  RAM_DISK_PRIVATE_DATA           *PrivateData;
+  RAM_DISK_PRIVATE_DATA           *RegisteredPrivateData;
+  MEDIA_RAM_DISK_DEVICE_PATH      *RamDiskDevNode;
+  UINTN                           DevicePathSize;
+  LIST_ENTRY                      *Entry;
+  EFI_TPL                         OldTpl;
+
+  if ((0 == RamDiskSize) || (NULL == RamDiskType) || (NULL == DevicePath)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Add check to prevent data read across the memory boundary
+  //
+  if (RamDiskBase + RamDiskSize > ((UINTN) -1) - RAM_DISK_BLOCK_SIZE + 1) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  RamDiskDevNode = NULL;
+
+  //
+  // Create a new RAM disk instance and initialize its private data
+  //
+  PrivateData = AllocateCopyPool (
+                  sizeof (RAM_DISK_PRIVATE_DATA),
+                  &mRamDiskPrivateDataTemplate
+                  );
+  if (NULL == PrivateData) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  PrivateData->StartingAddr = RamDiskBase;
+  PrivateData->Size         = RamDiskSize;
+  CopyGuid (&PrivateData->TypeGuid, RamDiskType);
+  InitializeListHead (&PrivateData->ThisInstance);
+
+  //
+  // Generate device path information for the registered RAM disk
+  //
+  RamDiskDevNode = AllocateCopyPool (
+                     sizeof (MEDIA_RAM_DISK_DEVICE_PATH),
+                     &mRamDiskDeviceNodeTemplate
+                     );
+  if (NULL == RamDiskDevNode) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ErrorExit;
+  }
+
+  RamDiskInitDeviceNode (PrivateData, RamDiskDevNode);
+
+  *DevicePath = AppendDevicePathNode (
+                  ParentDevicePath,
+                  (EFI_DEVICE_PATH_PROTOCOL *) RamDiskDevNode
+                  );
+  if (NULL == *DevicePath) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ErrorExit;
+  }
+
+  PrivateData->DevicePath = *DevicePath;
+
+  //
+  // Check whether the created device path is already present in the handle
+  // database
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+  if (!IsListEmpty(&RegisteredRamDisks)) {
+    DevicePathSize = GetDevicePathSize (PrivateData->DevicePath);
+
+    EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) {
+      RegisteredPrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
+      if (DevicePathSize == GetDevicePathSize 
(RegisteredPrivateData->DevicePath)) {
+        //
+        // Compare device path
+        //
+        if ((CompareMem (
+               PrivateData->DevicePath,
+               RegisteredPrivateData->DevicePath,
+               DevicePathSize)) == 0) {
+          *DevicePath = NULL;
+          Status      = EFI_ALREADY_STARTED;
+          goto ErrorExit;
+        }
+      }
+    }
+  }
+  gBS->RestoreTPL (OldTpl);
+
+  //
+  // Fill Block IO protocol informations for the RAM disk
+  //
+  RamDiskInitBlockIo (PrivateData);
+
+  //
+  // Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO_PROTOCOL on a new
+  // handle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &PrivateData->Handle,
+                  &gEfiBlockIoProtocolGuid,
+                  &PrivateData->BlockIo,
+                  &gEfiDevicePathProtocolGuid,
+                  PrivateData->DevicePath,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ErrorExit;
+  }
+
+  //
+  // Insert the newly created one to the registered RAM disk list
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+  InsertTailList (&RegisteredRamDisks, &PrivateData->ThisInstance);
+  ListEntryNum++;
+  gBS->RestoreTPL (OldTpl);
+
+  gBS->ConnectController (PrivateData->Handle, NULL, NULL, TRUE);
+
+  FreePool (RamDiskDevNode);
+
+  return EFI_SUCCESS;
+
+ErrorExit:
+  if (RamDiskDevNode != NULL) {
+    FreePool (RamDiskDevNode);
+  }
+
+  if (PrivateData != NULL) {
+    if (PrivateData->DevicePath) {
+      FreePool (PrivateData->DevicePath);
+    }
+
+    FreePool (PrivateData);
+  }
+
+  return Status;
+}
+
+
+/**
+  Unregister a RAM disk specified by DevicePath.
+
+  @param[in] DevicePath      A pointer to the device path that describes a RAM
+                             Disk device.
+
+  @retval EFI_SUCCESS             The RAM disk is unregistered successfully.
+  @retval EFI_INVALID_PARAMETER   DevicePath is NULL.
+  @retval EFI_UNSUPPORTED         The device specified by DevicePath is not a
+                                  valid ramdisk device path and not supported
+                                  by the driver.
+  @retval EFI_NOT_FOUND           The RAM disk pointed by DevicePath doesn't
+                                  exist.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskUnregister (
+  IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath
+  )
+{
+  LIST_ENTRY                      *Entry;
+  LIST_ENTRY                      *NextEntry;
+  BOOLEAN                         Found;
+  UINT64                          StartingAddr;
+  UINT64                          EndingAddr;
+  EFI_DEVICE_PATH_PROTOCOL        *Header;
+  MEDIA_RAM_DISK_DEVICE_PATH      *RamDiskDevNode;
+  RAM_DISK_PRIVATE_DATA           *PrivateData;
+  EFI_TPL                         OldTpl;
+
+  if (NULL == DevicePath) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Locate the RAM disk device node.
+  //
+  RamDiskDevNode = NULL;
+  Header         = DevicePath;
+  do {
+    //
+    // Test if the current device node is a RAM disk.
+    //
+    if ((MEDIA_DEVICE_PATH == Header->Type) &&
+      (MEDIA_RAM_DISK_DP == Header->SubType)) {
+      RamDiskDevNode = (MEDIA_RAM_DISK_DEVICE_PATH *) Header;
+
+      break;
+    }
+
+    Header = NextDevicePathNode (Header);
+  } while ((Header->Type != END_DEVICE_PATH_TYPE));
+
+  if (NULL == RamDiskDevNode) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Found          = FALSE;
+  StartingAddr   = ReadUnaligned64 ((UINT64 *) 
&(RamDiskDevNode->StartingAddr[0]));
+  EndingAddr     = ReadUnaligned64 ((UINT64 *) 
&(RamDiskDevNode->EndingAddr[0]));
+
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+  if (!IsListEmpty(&RegisteredRamDisks)) {
+    EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) {
+      PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
+
+      //
+      // Unregister the RAM disk given by its starting address, ending address
+      // and type guid.
+      //
+      if ((StartingAddr == PrivateData->StartingAddr) &&
+          (EndingAddr == PrivateData->StartingAddr + PrivateData->Size) &&
+          (CompareGuid (&RamDiskDevNode->TypeGuid, &PrivateData->TypeGuid))) {
+        //
+        // Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO_PROTOCOL
+        //
+        gBS->UninstallMultipleProtocolInterfaces (
+               PrivateData->Handle,
+               &gEfiBlockIoProtocolGuid,
+               &PrivateData->BlockIo,
+               &gEfiDevicePathProtocolGuid,
+               DevicePath,
+               NULL
+               );
+
+        RemoveEntryList (&PrivateData->ThisInstance);
+
+        if (RamDiskCreateHii == PrivateData->CreateMethod) {
+          //
+          // If a RAM disk is created within HII, then the RamDiskDxe driver
+          // driver is responsible for freeing the allocated memory for the
+          // RAM disk.
+          //
+          FreePool ((VOID *)(UINTN) PrivateData->StartingAddr);
+        }
+
+        gBS->DisconnectController (PrivateData->Handle, NULL, NULL);
+
+        FreePool (PrivateData->DevicePath);
+        FreePool (PrivateData);
+        ListEntryNum--;
+        Found = TRUE;
+
+        break;
+      }
+    }
+  }
+  gBS->RestoreTPL (OldTpl);
+
+  if (TRUE == Found) {
+    return EFI_SUCCESS;
+  } else {
+    return EFI_NOT_FOUND;
+  }
+}
-- 
1.9.5.msysgit.0

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to