]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Add RamDiskDxe driver implementation
authorHao Wu <hao.a.wu@intel.com>
Wed, 3 Feb 2016 06:14:47 +0000 (14:14 +0800)
committerHao Wu <hao.a.wu@intel.com>
Mon, 29 Feb 2016 05:51:08 +0000 (13:51 +0800)
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.wu@intel.com>
Reviewed-by: Samer El-Haj-Mahmoud <elhaj@hpe.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
14 files changed:
MdeModulePkg/Include/Guid/RamDiskHii.h [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDriver.c [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.uni [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskFileExplorer.c [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHii.vfr [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskHiiStrings.uni [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.h [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskNVData.h [new file with mode: 0644]
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskProtocol.c [new file with mode: 0644]

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