MdeModulePkg: Add RamDiskDxe driver implementation

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>
This commit is contained in:
Hao Wu 2016-02-03 14:14:47 +08:00
parent 7b0a1ead7d
commit 20752cb8e7
14 changed files with 2648 additions and 0 deletions

View File

@ -0,0 +1,25 @@
/** @file
GUIDs used as HII FormSet and HII Package list GUID in RamDiskDxe driver.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __RAM_DISK_HII_GUID_H__
#define __RAM_DISK_HII_GUID_H__
#define RAM_DISK_FORM_SET_GUID \
{ \
0x2a46715f, 0x3581, 0x4a55, {0x8e, 0x73, 0x2b, 0x76, 0x9a, 0xaa, 0x30, 0xc5} \
}
extern EFI_GUID gRamDiskFormSetGuid;
#endif

View File

@ -343,6 +343,9 @@
gEfiIfrFrontPageGuid = { 0xe58809f8, 0xfbc1, 0x48e2, { 0x88, 0x3a, 0xa3, 0x0f, 0xdc, 0x4b, 0x44, 0x1e } }
## Include/Guid/RamDiskHii.h
gRamDiskFormSetGuid = { 0x2a46715f, 0x3581, 0x4a55, { 0x8e, 0x73, 0x2b, 0x76, 0x9a, 0xaa, 0x30, 0xc5 }}
[Ppis]
## Include/Ppi/AtaController.h

View File

@ -322,6 +322,7 @@
MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
MdeModulePkg/Universal/Disk/CdExpressPei/CdExpressPei.inf
MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf

View File

@ -0,0 +1,258 @@
/** @file
Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "RamDiskImpl.h"
//
// The EFI_BLOCK_IO_PROTOCOL instances that is installed onto the handle
// for newly registered RAM disks
//
EFI_BLOCK_IO_PROTOCOL mRamDiskBlockIoTemplate = {
EFI_BLOCK_IO_PROTOCOL_REVISION,
(EFI_BLOCK_IO_MEDIA *) 0,
RamDiskBlkIoReset,
RamDiskBlkIoReadBlocks,
RamDiskBlkIoWriteBlocks,
RamDiskBlkIoFlushBlocks
};
/**
Initialize the BlockIO protocol of a RAM disk device.
@param[in] PrivateData Points to RAM disk private data.
**/
VOID
RamDiskInitBlockIo (
IN RAM_DISK_PRIVATE_DATA *PrivateData
)
{
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_BLOCK_IO_MEDIA *Media;
BlockIo = &PrivateData->BlockIo;
Media = &PrivateData->Media;
CopyMem (BlockIo, &mRamDiskBlockIoTemplate, sizeof (EFI_BLOCK_IO_PROTOCOL));
BlockIo->Media = Media;
Media->RemovableMedia = FALSE;
Media->MediaPresent = TRUE;
Media->LogicalPartition = FALSE;
Media->ReadOnly = FALSE;
Media->WriteCaching = FALSE;
Media->BlockSize = RAM_DISK_BLOCK_SIZE;
Media->LastBlock = DivU64x32 (
PrivateData->Size + RAM_DISK_BLOCK_SIZE - 1,
RAM_DISK_BLOCK_SIZE
) - 1;
}
/**
Reset the Block Device.
@param This Indicates a pointer to the calling context.
@param ExtendedVerification Driver may perform diagnostics on reset.
@retval EFI_SUCCESS The device was reset.
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
not be reset.
**/
EFI_STATUS
EFIAPI
RamDiskBlkIoReset (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
return EFI_SUCCESS;
}
/**
Read BufferSize bytes from Lba into Buffer.
@param[in] This Indicates a pointer to the calling context.
@param[in] MediaId Id of the media, changes every time the media is
replaced.
@param[in] Lba The starting Logical Block Address to read from.
@param[in] BufferSize Size of Buffer, must be a multiple of device block
size.
@param[out] Buffer A pointer to the destination buffer for the data.
The caller is responsible for either having
implicit or explicit ownership of the buffer.
@retval EFI_SUCCESS The data was read correctly from the device.
@retval EFI_DEVICE_ERROR The device reported an error while performing
the read.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_MEDIA_CHANGED The MediaId does not matched the current
device.
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
size of the device.
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
valid, or the buffer is not on proper alignment.
**/
EFI_STATUS
EFIAPI
RamDiskBlkIoReadBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
)
{
RAM_DISK_PRIVATE_DATA *PrivateData;
UINTN NumberOfBlocks;
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize == 0) {
return EFI_SUCCESS;
}
PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
if (MediaId != PrivateData->Media.MediaId) {
return EFI_MEDIA_CHANGED;
}
if ((BufferSize % PrivateData->Media.BlockSize) != 0) {
return EFI_BAD_BUFFER_SIZE;
}
if (Lba > PrivateData->Media.LastBlock) {
return EFI_INVALID_PARAMETER;
}
NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;
if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {
return EFI_INVALID_PARAMETER;
}
CopyMem (
Buffer,
(VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),
BufferSize
);
return EFI_SUCCESS;
}
/**
Write BufferSize bytes from Lba into Buffer.
@param[in] This Indicates a pointer to the calling context.
@param[in] MediaId The media ID that the write request is for.
@param[in] Lba The starting logical block address to be written.
The caller is responsible for writing to only
legitimate locations.
@param[in] BufferSize Size of Buffer, must be a multiple of device block
size.
@param[in] Buffer A pointer to the source buffer for the data.
@retval EFI_SUCCESS The data was written correctly to the device.
@retval EFI_WRITE_PROTECTED The device can not be written to.
@retval EFI_DEVICE_ERROR The device reported an error while performing
the write.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
device.
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
size of the device.
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
valid, or the buffer is not on proper alignment.
**/
EFI_STATUS
EFIAPI
RamDiskBlkIoWriteBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
)
{
RAM_DISK_PRIVATE_DATA *PrivateData;
UINTN NumberOfBlocks;
if (Buffer == NULL) {
return EFI_INVALID_PARAMETER;
}
if (BufferSize == 0) {
return EFI_SUCCESS;
}
PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
if (MediaId != PrivateData->Media.MediaId) {
return EFI_MEDIA_CHANGED;
}
if (TRUE == PrivateData->Media.ReadOnly) {
return EFI_WRITE_PROTECTED;
}
if ((BufferSize % PrivateData->Media.BlockSize) != 0) {
return EFI_BAD_BUFFER_SIZE;
}
if (Lba > PrivateData->Media.LastBlock) {
return EFI_INVALID_PARAMETER;
}
NumberOfBlocks = BufferSize / PrivateData->Media.BlockSize;
if ((Lba + NumberOfBlocks - 1) > PrivateData->Media.LastBlock) {
return EFI_INVALID_PARAMETER;
}
CopyMem (
(VOID *)(UINTN)(PrivateData->StartingAddr + MultU64x32 (Lba, PrivateData->Media.BlockSize)),
Buffer,
BufferSize
);
return EFI_SUCCESS;
}
/**
Flush the Block Device.
@param[in] This Indicates a pointer to the calling context.
@retval EFI_SUCCESS All outstanding data was written to the device.
@retval EFI_DEVICE_ERROR The device reported an error while writting
back the data
@retval EFI_NO_MEDIA There is no media in the device.
**/
EFI_STATUS
EFIAPI
RamDiskBlkIoFlushBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This
)
{
return EFI_SUCCESS;
}

View File

@ -0,0 +1,170 @@
/** @file
The driver entry point for RamDiskDxe driver.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "RamDiskImpl.h"
//
// Handle for the EFI_RAM_DISK_PROTOCOL instance
//
EFI_HANDLE mRamDiskHandle = NULL;
//
// The EFI_RAM_DISK_PROTOCOL instances that is installed onto the driver
// handle
//
EFI_RAM_DISK_PROTOCOL mRamDiskProtocol = {
RamDiskRegister,
RamDiskUnregister
};
//
// RamDiskDxe driver maintains a list of registered RAM disks.
//
LIST_ENTRY RegisteredRamDisks;
UINTN ListEntryNum;
/**
The entry point for RamDiskDxe driver.
@param[in] ImageHandle The image handle of the driver.
@param[in] SystemTable The system table.
@retval EFI_ALREADY_STARTED The driver already exists in system.
@retval EFI_OUT_OF_RESOURCES Fail to execute entry point due to lack of
resources.
@retval EFI_SUCCES All the related protocols are installed on
the driver.
**/
EFI_STATUS
EFIAPI
RamDiskDxeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate;
VOID *DummyInterface;
//
// If already started, return.
//
Status = gBS->LocateProtocol (
&gEfiRamDiskProtocolGuid,
NULL,
&DummyInterface
);
if (!EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "Driver already started!\n"));
return EFI_ALREADY_STARTED;
}
//
// Create a private data structure.
//
ConfigPrivate = AllocateCopyPool (sizeof (RAM_DISK_CONFIG_PRIVATE_DATA), &mRamDiskConfigPrivateDataTemplate);
if (ConfigPrivate == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Install RAM disk configuration form
//
Status = InstallRamDiskConfigForm (ConfigPrivate);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Install the EFI_RAM_DISK_PROTOCOL and RAM disk private data onto a
// new handle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&mRamDiskHandle,
&gEfiRamDiskProtocolGuid,
&mRamDiskProtocol,
&gEfiCallerIdGuid,
ConfigPrivate,
NULL
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Initialize the list of registered RAM disks maintained by the driver
//
InitializeListHead (&RegisteredRamDisks);
return EFI_SUCCESS;
ErrorExit:
if (ConfigPrivate != NULL) {
UninstallRamDiskConfigForm (ConfigPrivate);
}
return Status;
}
/**
Unload the RamDiskDxe driver and its configuration form.
@param[in] ImageHandle The driver's image handle.
@retval EFI_SUCCESS The RamDiskDxe driver and its configuration
form is unloaded.
@retval Others Failed to unload the form.
**/
EFI_STATUS
EFIAPI
RamDiskDxeUnload (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate;
Status = gBS->HandleProtocol (
mRamDiskHandle,
&gEfiCallerIdGuid,
(VOID **) &ConfigPrivate
);
if (EFI_ERROR (Status)) {
return Status;
}
ASSERT (ConfigPrivate->Signature == RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE);
//
// Unregister all registered RAM disks
//
UnregisterAllRamDisks ();
gBS->UninstallMultipleProtocolInterfaces (
mRamDiskHandle,
&gEfiRamDiskProtocolGuid,
&mRamDiskProtocol,
&gEfiCallerIdGuid,
ConfigPrivate,
NULL
);
UninstallRamDiskConfigForm (ConfigPrivate);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,78 @@
## @file
# Produces EFI_RAM_DISK_PROTOCOL and provides the capability to
# create/remove RAM disks in a setup browser.
#
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = RamDiskDxe
MODULE_UNI_FILE = RamDiskDxe.uni
FILE_GUID = 28A03FF4-12B3-4305-A417-BB1A4F94081E
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = RamDiskDxeEntryPoint
UNLOAD_IMAGE = RamDiskDxeUnload
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
RamDiskDriver.c
RamDiskImpl.c
RamDiskBlockIo.c
RamDiskProtocol.c
RamDiskFileExplorer.c
RamDiskImpl.h
RamDiskHii.vfr
RamDiskHiiStrings.uni
RamDiskNVData.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
BaseLib
BaseMemoryLib
DebugLib
UefiLib
UefiDriverEntryPoint
UefiBootServicesTableLib
UefiHiiServicesLib
MemoryAllocationLib
HiiLib
FileExplorerLib
DevicePathLib
PrintLib
[Guids]
gEfiIfrTianoGuid ## PRODUCES ## GUID # HII opcode
## PRODUCES ## HII
## CONSUMES ## HII
gRamDiskFormSetGuid
gEfiVirtualDiskGuid ## SOMETIMES_CONSUMES ## GUID
gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID # Indicate the information type
[Protocols]
gEfiRamDiskProtocolGuid ## PRODUCES
gEfiHiiConfigAccessProtocolGuid ## PRODUCES
gEfiDevicePathProtocolGuid ## PRODUCES
gEfiBlockIoProtocolGuid ## PRODUCES
gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
[Depex]
gEfiHiiConfigRoutingProtocolGuid AND
gEfiHiiDatabaseProtocolGuid

View File

@ -0,0 +1,20 @@
// /** @file
// Produces EFI_RAM_DISK_PROTOCOL and provides the capability to
// create/remove RAM disks in a setup browser.
//
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
//
// This program and the accompanying materials
// are licensed and made available under the terms and conditions of the BSD License
// which accompanies this distribution. The full text of the license may be found at
// http://opensource.org/licenses/bsd-license.php
//
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Produces EFI_RAM_DISK_PROTOCOL and provides the capability to create/remove RAM disks in a setup browser."
#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI_RAM_DISK_PROTOCOL and provides the capability to create/remove RAM disks in a setup browser."

View File

@ -0,0 +1,253 @@
/** @file
Internal file explorer helper functions for RamDiskDxe driver.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "RamDiskImpl.h"
/**
Helper function called as part of the code needed to allocate the proper
sized buffer for various EFI interfaces.
@param[in, out] Status Current status.
@param[in, out] Buffer Current allocated buffer, or NULL.
@param[in] BufferSize Current buffer size needed.
@retval TRUE If the buffer was reallocated and the caller should
try the API again.
@retval FALSE The caller should not call this function again.
**/
BOOLEAN
GrowBuffer (
IN OUT EFI_STATUS *Status,
IN OUT VOID **Buffer,
IN UINTN BufferSize
)
{
BOOLEAN TryAgain;
//
// If this is an initial request, buffer will be null with a new buffer size
//
if ((*Buffer == NULL) && (BufferSize != 0)) {
*Status = EFI_BUFFER_TOO_SMALL;
}
//
// If the status code is "buffer too small", resize the buffer
//
TryAgain = FALSE;
if (*Status == EFI_BUFFER_TOO_SMALL) {
if (*Buffer != NULL) {
FreePool (*Buffer);
}
*Buffer = AllocateZeroPool (BufferSize);
if (*Buffer != NULL) {
TryAgain = TRUE;
} else {
*Status = EFI_OUT_OF_RESOURCES;
}
}
//
// If there's an error, free the buffer
//
if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {
FreePool (*Buffer);
*Buffer = NULL;
}
return TryAgain;
}
/**
This function gets the file information from an open file descriptor,
and stores it in a buffer allocated from pool.
@param[in] FHand File Handle.
@return A pointer to a buffer with file information or NULL is returned.
**/
EFI_FILE_INFO *
FileInfo (
IN EFI_FILE_HANDLE FHand
)
{
EFI_STATUS Status;
EFI_FILE_INFO *Buffer;
UINTN BufferSize;
//
// Initialize for GrowBuffer loop
//
Buffer = NULL;
BufferSize = SIZE_OF_EFI_FILE_INFO + 200;
//
// Call the real function
//
while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
Status = FHand->GetInfo (
FHand,
&gEfiFileInfoGuid,
&BufferSize,
Buffer
);
}
return Buffer;
}
/**
This function will open a file or directory referenced by DevicePath.
This function opens a file with the open mode according to the file path. The
Attributes is valid only for EFI_FILE_MODE_CREATE.
@param[in, out] FilePath On input, the device path to the file.
On output, the remaining device path.
@param[out] FileHandle Pointer to the file handle.
@param[in] OpenMode The mode to open the file with.
@param[in] Attributes The file's file attributes.
@retval EFI_SUCCESS The information was set.
@retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
@retval EFI_UNSUPPORTED Could not open the file path.
@retval EFI_NOT_FOUND The specified file could not be found on the
device or the file system could not be found
on the device.
@retval EFI_NO_MEDIA The device has no medium.
@retval EFI_MEDIA_CHANGED The device has a different medium in it or
the medium is no longer supported.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
@retval EFI_WRITE_PROTECTED The file or medium is write protected.
@retval EFI_ACCESS_DENIED The file was opened read only.
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open
the file.
@retval EFI_VOLUME_FULL The volume is full.
**/
EFI_STATUS
EFIAPI
OpenFileByDevicePath(
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
OUT EFI_FILE_HANDLE *FileHandle,
IN UINT64 OpenMode,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
EFI_FILE_PROTOCOL *Handle1;
EFI_FILE_PROTOCOL *Handle2;
EFI_HANDLE DeviceHandle;
if ((FilePath == NULL || FileHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
Status = gBS->LocateDevicePath (
&gEfiSimpleFileSystemProtocolGuid,
FilePath,
&DeviceHandle
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->OpenProtocol(
DeviceHandle,
&gEfiSimpleFileSystemProtocolGuid,
(VOID**)&EfiSimpleFileSystemProtocol,
gImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
if (EFI_ERROR (Status)) {
FileHandle = NULL;
return Status;
}
//
// go down directories one node at a time.
//
while (!IsDevicePathEnd (*FilePath)) {
//
// For file system access each node should be a file path component
//
if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||
DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
) {
FileHandle = NULL;
return (EFI_INVALID_PARAMETER);
}
//
// Open this file path node
//
Handle2 = Handle1;
Handle1 = NULL;
//
// Try to test opening an existing file
//
Status = Handle2->Open (
Handle2,
&Handle1,
((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
OpenMode &~EFI_FILE_MODE_CREATE,
0
);
//
// see if the error was that it needs to be created
//
if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
Status = Handle2->Open (
Handle2,
&Handle1,
((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
OpenMode,
Attributes
);
}
//
// Close the last node
//
Handle2->Close (Handle2);
if (EFI_ERROR(Status)) {
return (Status);
}
//
// Get the next node
//
*FilePath = NextDevicePathNode (*FilePath);
}
//
// This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
//
*FileHandle = (VOID*)Handle1;
return EFI_SUCCESS;
}

View File

@ -0,0 +1,93 @@
///** @file
// VFR file used by the RamDiskDxe driver.
//
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
// This program and the accompanying materials
// are licensed and made available under the terms and conditions of the BSD License
// which accompanies this distribution. The full text of the license may be found at
// http://opensource.org/licenses/bsd-license.php
//
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
//**/
#include "RamDiskNVData.h"
formset
guid = RAM_DISK_FORM_SET_GUID,
title = STRING_TOKEN(STR_FORM_SET_TITLE),
help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP),
classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID,
varstore RAM_DISK_CONFIGURATION,
varid = RAM_DISK_CONFIGURATION_VARSTORE_ID,
name = RAM_DISK_CONFIGURATION,
guid = RAM_DISK_FORM_SET_GUID;
//
// Form #1 "Main Form - Add/Remove/Show RAM Disks"
//
form formid = MAIN_FORM_ID,
title = STRING_TOKEN(STR_MAIN_FORM_TITLE);
goto CREATE_RAW_RAM_DISK_FORM_ID,
prompt = STRING_TOKEN(STR_GOTO_ADD_RAW_FORM),
help = STRING_TOKEN(STR_GOTO_ADD_RAW_FORM_HELP);
goto MAIN_FORM_ID,
prompt = STRING_TOKEN(STR_GOTO_ADD_FROM_FILE_FORM),
help = STRING_TOKEN(STR_GOTO_ADD_FROM_FILE_FORM_HELP),
flags = INTERACTIVE,
key = MAIN_GOTO_FILE_EXPLORER_ID;
subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING);
subtitle text = STRING_TOKEN(STR_RAM_DISK_LIST_TEXT);
label MAIN_LABEL_LIST_START;
label MAIN_LABEL_LIST_END;
subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING);
text
help = STRING_TOKEN(STR_REMOVE_SEL_HELP),
text = STRING_TOKEN(STR_REMOVE_SEL_TEXT),
flags = INTERACTIVE,
key = MAIN_REMOVE_RD_QUESTION_ID;
endform;
//
// Form #2 "Add New Raw RAM Disk"
//
form formid = CREATE_RAW_RAM_DISK_FORM_ID,
title = STRING_TOKEN(STR_ADD_RAW_FORM_TITLE);
subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING);
numeric varid = RAM_DISK_CONFIGURATION.Size,
questionid = CREATE_RAW_SIZE_QUESTION_ID,
prompt = STRING_TOKEN(STR_SIZE_PROMPT),
help = STRING_TOKEN(STR_SIZE_HELP),
flags = DISPLAY_UINT_HEX | INTERACTIVE,
minimum = 1,
maximum = 0xFFFFFFFFFFFFFFFF,
endnumeric;
subtitle text = STRING_TOKEN(STR_RAM_DISK_NULL_STRING);
text
help = STRING_TOKEN(STR_CREATE_AND_EXIT_HELP),
text = STRING_TOKEN(STR_CREATE_AND_EXIT_PROMPT),
flags = INTERACTIVE,
key = CREATE_RAW_SUBMIT_QUESTION_ID;
text
help = STRING_TOKEN(STR_DISCARD_AND_EXIT_HELP),
text = STRING_TOKEN(STR_DISCARD_AND_EXIT_PROMPT),
flags = INTERACTIVE,
key = CREATE_RAW_DISCARD_QUESTION_ID;
endform;
endformset;

View File

@ -0,0 +1,42 @@
// /** @file
// String definitions for RamDiskDxe driver form.
//
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
//
// This program and the accompanying materials
// are licensed and made available under the terms and conditions of the BSD License
// which accompanies this distribution. The full text of the license may be found at
// http://opensource.org/licenses/bsd-license.php
//
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
// **/
#langdef en-US "English"
#string STR_FORM_SET_TITLE #language en-US "RAM Disk Configutation"
#string STR_FORM_SET_TITLE_HELP #language en-US "Press <Enter> to add/remove RAM disks."
#string STR_MAIN_FORM_TITLE #language en-US "RAM Disk HII Main Screen"
#string STR_RAM_DISK_NULL_STRING #language en-US ""
#string STR_RAM_DISK_LIST_TEXT #language en-US "Created RAM disk list:"
#string STR_RAM_DISK_LIST_HELP #language en-US "Select for remove"
#string STR_GOTO_ADD_RAW_FORM #language en-US "Create raw"
#string STR_GOTO_ADD_RAW_FORM_HELP #language en-US "Create a raw RAM disk."
#string STR_GOTO_ADD_FROM_FILE_FORM #language en-US "Create from file"
#string STR_GOTO_ADD_FROM_FILE_FORM_HELP #language en-US "Create a RAM disk from a given file."
#string STR_REMOVE_SEL_HELP #language en-US "Remove selected RAM disk(s)"
#string STR_REMOVE_SEL_TEXT #language en-US "Remove selected RAM disk(s)."
#string STR_ADD_RAW_FORM_TITLE #language en-US "Add A Raw RAM Disk"
#string STR_ADD_RAW_FORM_SUBTITLE_TEXT #language en-US " "
#string STR_SIZE_PROMPT #language en-US "Size (Hex):"
#string STR_SIZE_HELP #language en-US "The valid RAM disk size should be multiples of the RAM disk block size."
#string STR_CREATE_AND_EXIT_HELP #language en-US "Create a new RAM disk with the given starting and ending address."
#string STR_CREATE_AND_EXIT_PROMPT #language en-US "Create & Exit"
#string STR_DISCARD_AND_EXIT_HELP #language en-US "Discard and exit."
#string STR_DISCARD_AND_EXIT_PROMPT #language en-US "Discard & Exit"

View File

@ -0,0 +1,807 @@
/** @file
HII Config Access protocol implementation of RamDiskDxe driver.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "RamDiskImpl.h"
CHAR16 mRamDiskStorageName[] = L"RAM_DISK_CONFIGURATION";
RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate = {
RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE,
{
RamDiskExtractConfig,
RamDiskRouteConfig,
RamDiskCallback
}
};
HII_VENDOR_DEVICE_PATH mRamDiskHiiVendorDevicePath = {
{
{
HARDWARE_DEVICE_PATH,
HW_VENDOR_DP,
{
(UINT8) (sizeof (VENDOR_DEVICE_PATH)),
(UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
}
},
RAM_DISK_FORM_SET_GUID
},
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
{
(UINT8) (END_DEVICE_PATH_LENGTH),
(UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
}
}
};
/**
This function publish the RAM disk configuration Form.
@param[in, out] ConfigPrivateData
Points to RAM disk configuration private data.
@retval EFI_SUCCESS HII Form is installed successfully.
@retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
@retval Others Other errors as indicated.
**/
EFI_STATUS
InstallRamDiskConfigForm (
IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivateData
)
{
EFI_STATUS Status;
EFI_HII_HANDLE HiiHandle;
EFI_HANDLE DriverHandle;
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
DriverHandle = NULL;
ConfigAccess = &ConfigPrivateData->ConfigAccess;
Status = gBS->InstallMultipleProtocolInterfaces (
&DriverHandle,
&gEfiDevicePathProtocolGuid,
&mRamDiskHiiVendorDevicePath,
&gEfiHiiConfigAccessProtocolGuid,
ConfigAccess,
NULL
);
if (EFI_ERROR (Status)) {
return Status;
}
ConfigPrivateData->DriverHandle = DriverHandle;
//
// Publish the HII package list
//
HiiHandle = HiiAddPackages (
&gRamDiskFormSetGuid,
DriverHandle,
RamDiskDxeStrings,
RamDiskHiiBin,
NULL
);
if (HiiHandle == NULL) {
gBS->UninstallMultipleProtocolInterfaces (
DriverHandle,
&gEfiDevicePathProtocolGuid,
&mRamDiskHiiVendorDevicePath,
&gEfiHiiConfigAccessProtocolGuid,
ConfigAccess,
NULL
);
return EFI_OUT_OF_RESOURCES;
}
ConfigPrivateData->HiiHandle = HiiHandle;
return EFI_SUCCESS;
}
/**
This function removes RAM disk configuration Form.
@param[in, out] ConfigPrivateData
Points to RAM disk configuration private data.
**/
VOID
UninstallRamDiskConfigForm (
IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivateData
)
{
//
// Uninstall HII package list
//
if (ConfigPrivateData->HiiHandle != NULL) {
HiiRemovePackages (ConfigPrivateData->HiiHandle);
ConfigPrivateData->HiiHandle = NULL;
}
//
// Uninstall HII Config Access Protocol
//
if (ConfigPrivateData->DriverHandle != NULL) {
gBS->UninstallMultipleProtocolInterfaces (
ConfigPrivateData->DriverHandle,
&gEfiDevicePathProtocolGuid,
&mRamDiskHiiVendorDevicePath,
&gEfiHiiConfigAccessProtocolGuid,
&ConfigPrivateData->ConfigAccess,
NULL
);
ConfigPrivateData->DriverHandle = NULL;
}
FreePool (ConfigPrivateData);
}
/**
Unregister all registered RAM disks.
**/
VOID
UnregisterAllRamDisks (
VOID
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *NextEntry;
RAM_DISK_PRIVATE_DATA *PrivateData;
if (!IsListEmpty(&RegisteredRamDisks)) {
EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) {
PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
gBS->UninstallMultipleProtocolInterfaces (
PrivateData->Handle,
&gEfiBlockIoProtocolGuid,
&PrivateData->BlockIo,
&gEfiDevicePathProtocolGuid,
(EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath,
NULL
);
RemoveEntryList (&PrivateData->ThisInstance);
if (RamDiskCreateHii == PrivateData->CreateMethod) {
//
// If a RAM disk is created within HII, then the RamDiskDxe driver
// driver is responsible for freeing the allocated memory for the
// RAM disk.
//
FreePool ((VOID *)(UINTN) PrivateData->StartingAddr);
}
gBS->DisconnectController (PrivateData->Handle, NULL, NULL);
FreePool (PrivateData->DevicePath);
FreePool (PrivateData);
ListEntryNum--;
}
}
}
/**
This function allows a caller to extract the current configuration for one
or more named elements from the target driver.
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param[in] Request A null-terminated Unicode string in
<ConfigRequest> format.
@param[out] Progress On return, points to a character in the Request
string. Points to the string's null terminator if
request was successful. Points to the most recent
'&' before the first failing name/value pair (or
the beginning of the string if the failure is in
the first name/value pair) if the request was not
successful.
@param[out] Results A null-terminated Unicode string in
<ConfigAltResp> format which has all values filled
in for the names in the Request string. String to
be allocated by the called function.
@retval EFI_SUCCESS The Results is filled with the requested
values.
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
@retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
@retval EFI_NOT_FOUND Routing data doesn't match any storage in
this driver.
**/
EFI_STATUS
EFIAPI
RamDiskExtractConfig (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Request,
OUT EFI_STRING *Progress,
OUT EFI_STRING *Results
)
{
EFI_STATUS Status;
UINTN BufferSize;
RAM_DISK_CONFIGURATION *Configuration;
EFI_STRING ConfigRequest;
EFI_STRING ConfigRequestHdr;
RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate;
UINTN Size;
BOOLEAN AllocatedRequest;
if (Progress == NULL || Results == NULL) {
return EFI_INVALID_PARAMETER;
}
*Progress = Request;
if ((Request != NULL) &&
!HiiIsConfigHdrMatch (Request, &gRamDiskFormSetGuid, mRamDiskStorageName)) {
return EFI_NOT_FOUND;
}
ConfigRequestHdr = NULL;
ConfigRequest = NULL;
AllocatedRequest = FALSE;
Size = 0;
//
// Convert buffer data to <ConfigResp> by helper function BlockToConfig()
//
ConfigPrivate = RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This);
BufferSize = sizeof (RAM_DISK_CONFIGURATION) + ListEntryNum;
Configuration = AllocateZeroPool (BufferSize);
if (Configuration == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ConfigRequest = Request;
if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
//
// Request has no request element, construct full request string.
// Allocate and fill a buffer large enough to hold the <ConfigHdr> template
// followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
//
ConfigRequestHdr = HiiConstructConfigHdr (
&gRamDiskFormSetGuid,
mRamDiskStorageName,
ConfigPrivate->DriverHandle
);
Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
ConfigRequest = AllocateZeroPool (Size);
ASSERT (ConfigRequest != NULL);
AllocatedRequest = TRUE;
UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
FreePool (ConfigRequestHdr);
}
Status = gHiiConfigRouting->BlockToConfig (
gHiiConfigRouting,
ConfigRequest,
(UINT8 *) &Configuration,
BufferSize,
Results,
Progress
);
//
// Free the allocated config request string and RAM disk configuration data.
//
if (AllocatedRequest) {
FreePool (ConfigRequest);
ConfigRequest = NULL;
}
FreePool (Configuration);
//
// Set Progress string to the original request string.
//
if (Request == NULL) {
*Progress = NULL;
} else if (StrStr (Request, L"OFFSET") == NULL) {
*Progress = Request + StrLen (Request);
}
return Status;
}
/**
This function processes the results of changes in configuration.
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param[in] Configuration A null-terminated Unicode string in <ConfigResp>
format.
@param[out] Progress A pointer to a string filled in with the offset of
the most recent '&' before the first failing
name/value pair (or the beginning of the string if
the failure is in the first name/value pair) or
the terminating NULL if all was successful.
@retval EFI_SUCCESS The Results is processed successfully.
@retval EFI_INVALID_PARAMETER Configuration is NULL.
@retval EFI_NOT_FOUND Routing data doesn't match any storage in
this driver.
**/
EFI_STATUS
EFIAPI
RamDiskRouteConfig (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Configuration,
OUT EFI_STRING *Progress
)
{
if (Configuration == NULL || Progress == NULL) {
return EFI_INVALID_PARAMETER;
}
*Progress = Configuration;
if (!HiiIsConfigHdrMatch (Configuration, &gRamDiskFormSetGuid, mRamDiskStorageName)) {
return EFI_NOT_FOUND;
}
*Progress = Configuration + StrLen (Configuration);
return EFI_SUCCESS;
}
/**
Allocate memory and register the RAM disk created within RamDiskDxe
driver HII.
@param[in] Size If creating raw, size of the RAM disk to create.
If creating from file, zero.
@param[in] FileHandle If creating raw, NULL. If creating from file, the
file handle.
@retval EFI_SUCCESS RAM disk is created and registered.
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to match the
size required.
**/
EFI_STATUS
HiiCreateRamDisk (
IN UINT64 Size,
IN EFI_FILE_HANDLE FileHandle
)
{
EFI_STATUS Status;
UINTN BufferSize;
UINT64 StartingAddr;
EFI_INPUT_KEY Key;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
RAM_DISK_PRIVATE_DATA *PrivateData;
EFI_FILE_INFO *FileInformation;
FileInformation = NULL;
if (FileHandle != NULL) {
//
// Create from file.
//
FileInformation = FileInfo (FileHandle);
if (NULL == FileInformation) {
do {
CreatePopUp (
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
&Key,
L"",
L"Not enough memory to get the file information!",
L"Press ENTER to continue ...",
L"",
NULL
);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
return EFI_OUT_OF_RESOURCES;
}
//
// Update the size of RAM disk according to the file size.
//
Size = FileInformation->FileSize;
}
StartingAddr = (UINTN) AllocatePool ((UINTN) Size);
if (0 == StartingAddr) {
do {
CreatePopUp (
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
&Key,
L"",
L"Not enough memory to create the RAM disk!",
L"Press ENTER to continue ...",
L"",
NULL
);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
return EFI_OUT_OF_RESOURCES;
}
if (FileHandle != NULL) {
//
// Copy the file content to the RAM disk.
//
BufferSize = (UINTN) Size;
FileHandle->Read (
FileHandle,
&BufferSize,
(VOID *)(UINTN) StartingAddr
);
if (BufferSize != FileInformation->FileSize) {
do {
CreatePopUp (
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
&Key,
L"",
L"File content read error!",
L"Press ENTER to continue ...",
L"",
NULL
);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
return EFI_DEVICE_ERROR;
}
}
//
// Register the newly created RAM disk.
//
Status = RamDiskRegister (
StartingAddr,
Size,
&gEfiVirtualDiskGuid,
NULL,
&DevicePath
);
if (EFI_ERROR (Status)) {
do {
CreatePopUp (
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
&Key,
L"",
L"Fail to register the newly created RAM disk!",
L"Press ENTER to continue ...",
L"",
NULL
);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
return Status;
}
//
// If RAM disk is created within HII, memory should be freed when the
// RAM disk is unregisterd.
//
PrivateData = RAM_DISK_PRIVATE_FROM_THIS (RegisteredRamDisks.BackLink);
PrivateData->CreateMethod = RamDiskCreateHii;
return EFI_SUCCESS;
}
/**
This function updates the registered RAM disks list on the main form.
@param[in, out] ConfigPrivate
Private data for configurating hii data for RAM
disks.
**/
VOID
UpdateMainForm (
IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate
)
{
VOID *StartOpCodeHandle;
VOID *EndOpCodeHandle;
EFI_IFR_GUID_LABEL *StartLabel;
EFI_IFR_GUID_LABEL *EndLabel;
LIST_ENTRY *Entry;
UINTN Index;
RAM_DISK_PRIVATE_DATA *PrivateData;
CHAR16 *String;
CHAR16 RamDiskStr[128];
EFI_STRING_ID StringId;
EFI_TPL OldTpl;
//
// Init OpCode Handle
//
StartOpCodeHandle = HiiAllocateOpCodeHandle ();
ASSERT (StartOpCodeHandle != NULL);
EndOpCodeHandle = HiiAllocateOpCodeHandle ();
ASSERT (EndOpCodeHandle != NULL);
//
// Create Hii Extend Label OpCode as the start opcode
//
StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
StartOpCodeHandle,
&gEfiIfrTianoGuid,
NULL,
sizeof (EFI_IFR_GUID_LABEL)
);
StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
StartLabel->Number = MAIN_LABEL_LIST_START;
//
// Create Hii Extend Label OpCode as the end opcode
//
EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
EndOpCodeHandle,
&gEfiIfrTianoGuid,
NULL,
sizeof (EFI_IFR_GUID_LABEL)
);
EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
EndLabel->Number = MAIN_LABEL_LIST_END;
Index = 0;
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) {
PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
String = RamDiskStr;
UnicodeSPrint (
String,
sizeof (RamDiskStr),
L" RAM Disk %d: [0x%lx, 0x%lx]\n",
Index,
PrivateData->StartingAddr,
PrivateData->StartingAddr + PrivateData->Size
);
StringId = HiiSetString (ConfigPrivate->HiiHandle, 0, RamDiskStr, NULL);
ASSERT (StringId != 0);
HiiCreateCheckBoxOpCode (
StartOpCodeHandle,
(EFI_QUESTION_ID) (MAIN_CHECKBOX_QUESTION_ID_START + Index),
RAM_DISK_CONFIGURATION_VARSTORE_ID,
(UINT16) (RAM_DISK_LIST_VAR_OFFSET + Index),
StringId,
STRING_TOKEN (STR_RAM_DISK_LIST_HELP),
0,
0,
NULL
);
Index++;
}
gBS->RestoreTPL (OldTpl);
HiiUpdateForm (
ConfigPrivate->HiiHandle,
&gRamDiskFormSetGuid,
MAIN_FORM_ID,
StartOpCodeHandle,
EndOpCodeHandle
);
HiiFreeOpCodeHandle (StartOpCodeHandle);
HiiFreeOpCodeHandle (EndOpCodeHandle);
}
/**
This function processes the results of changes in configuration.
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param[in] Action Specifies the type of action taken by the browser.
@param[in] QuestionId A unique value which is sent to the original
exporting driver so that it can identify the type
of data to expect.
@param[in] Type The type of value for the question.
@param[in] Value A pointer to the data being sent to the original
exporting driver.
@param[out] ActionRequest On return, points to the action requested by the
callback function.
@retval EFI_SUCCESS The callback successfully handled the action.
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
variable and its data.
@retval EFI_DEVICE_ERROR The variable could not be saved.
@retval EFI_UNSUPPORTED The specified Action is not supported by the
callback.
**/
EFI_STATUS
EFIAPI
RamDiskCallback (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN EFI_BROWSER_ACTION Action,
IN EFI_QUESTION_ID QuestionId,
IN UINT8 Type,
IN EFI_IFR_TYPE_VALUE *Value,
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
)
{
EFI_STATUS Status;
UINTN Index;
RAM_DISK_PRIVATE_DATA *PrivateData;
RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivate;
RAM_DISK_CONFIGURATION *Configuration;
EFI_DEVICE_PATH_PROTOCOL *FileDevPath;
EFI_FILE_HANDLE FileHandle;
LIST_ENTRY *Entry;
LIST_ENTRY *NextEntry;
EFI_TPL OldTpl;
if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Action == EFI_BROWSER_ACTION_RETRIEVE) {
Status = EFI_UNSUPPORTED;
if (QuestionId == CREATE_RAW_SIZE_QUESTION_ID) {
Value->u64 = EFI_PAGE_SIZE;
Status = EFI_SUCCESS;
}
return Status;
}
if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
(Action != EFI_BROWSER_ACTION_CHANGING) &&
(Action != EFI_BROWSER_ACTION_FORM_OPEN)) {
return EFI_UNSUPPORTED;
}
ConfigPrivate = RAM_DISK_CONFIG_PRIVATE_FROM_THIS (This);
//
// Update the RAM disk list show at the main form first.
//
if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
Status = EFI_UNSUPPORTED;
if (QuestionId == MAIN_GOTO_FILE_EXPLORER_ID) {
UpdateMainForm (ConfigPrivate);
Status = EFI_SUCCESS;
}
return Status;
}
//
// Get Browser data
//
Configuration = AllocateZeroPool (sizeof (RAM_DISK_CONFIGURATION) + ListEntryNum);
if (Configuration == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = EFI_SUCCESS;
HiiGetBrowserData (
&gRamDiskFormSetGuid,
mRamDiskStorageName,
sizeof (RAM_DISK_CONFIGURATION) + ListEntryNum,
(UINT8 *) Configuration
);
if (Action == EFI_BROWSER_ACTION_CHANGING) {
switch (QuestionId) {
case MAIN_GOTO_FILE_EXPLORER_ID:
Status = ChooseFile (NULL, NULL, NULL, &FileDevPath);
if (EFI_ERROR (Status)) {
break;
}
if (FileDevPath != NULL) {
//
// Open the file.
//
Status = OpenFileByDevicePath (
&FileDevPath,
&FileHandle,
EFI_FILE_MODE_READ,
0
);
if (EFI_ERROR (Status)) {
break;
}
//
// Create from file, RAM disk size is zero. It will be updated
// according to the file size.
//
Status = HiiCreateRamDisk (0, FileHandle);
if (EFI_ERROR (Status)) {
break;
}
//
// Refresh the registered RAM disks list.
//
UpdateMainForm (ConfigPrivate);
}
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
break;
default:
break;
}
} else if (Action == EFI_BROWSER_ACTION_CHANGED) {
switch (QuestionId) {
case MAIN_REMOVE_RD_QUESTION_ID:
//
// Remove the selected RAM disks
//
Index = 0;
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) {
if (Configuration->RamDiskList[Index++] != 0) {
PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
RamDiskUnregister (
(EFI_DEVICE_PATH_PROTOCOL *) PrivateData->DevicePath
);
}
}
gBS->RestoreTPL (OldTpl);
UpdateMainForm (ConfigPrivate);
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
ZeroMem (Configuration->RamDiskList, ListEntryNum);
break;
case CREATE_RAW_SUBMIT_QUESTION_ID:
//
// Create raw, FileHandle is NULL.
//
Status = HiiCreateRamDisk (Configuration->Size, NULL);
if (EFI_ERROR (Status)) {
break;
}
//
// Refresh the registered RAM disks list.
//
UpdateMainForm (ConfigPrivate);
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
break;
case CREATE_RAW_DISCARD_QUESTION_ID:
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
break;
default:
break;
}
}
if (!EFI_ERROR (Status)) {
HiiSetBrowserData (
&gRamDiskFormSetGuid,
mRamDiskStorageName,
sizeof (RAM_DISK_CONFIGURATION) + ListEntryNum,
(UINT8 *) Configuration,
NULL
);
}
FreePool (Configuration);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,499 @@
/** @file
The header file of RamDiskDxe driver.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _RAM_DISK_IMPL_H_
#define _RAM_DISK_IMPL_H_
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiHiiServicesLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/HiiLib.h>
#include <Library/FileExplorerLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PrintLib.h>
#include <Protocol/RamDisk.h>
#include <Protocol/BlockIo.h>
#include <Protocol/HiiConfigAccess.h>
#include <Protocol/SimpleFileSystem.h>
#include <Guid/MdeModuleHii.h>
#include <Guid/RamDiskHii.h>
#include <Guid/FileInfo.h>
#include "RamDiskNVData.h"
///
/// RAM disk general definitions and declarations
///
//
// Block size for RAM disk
//
#define RAM_DISK_BLOCK_SIZE 512
//
// Iterate through the doule linked list. NOT delete safe
//
#define EFI_LIST_FOR_EACH(Entry, ListHead) \
for(Entry = (ListHead)->ForwardLink; Entry != (ListHead); Entry = Entry->ForwardLink)
//
// Iterate through the doule linked list. This is delete-safe.
// Do not touch NextEntry
//
#define EFI_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead) \
for(Entry = (ListHead)->ForwardLink, NextEntry = Entry->ForwardLink;\
Entry != (ListHead); Entry = NextEntry, NextEntry = Entry->ForwardLink)
//
// RamDiskDxe driver maintains a list of registered RAM disks.
//
extern LIST_ENTRY RegisteredRamDisks;
extern UINTN ListEntryNum;
//
// RAM Disk create method.
//
typedef enum _RAM_DISK_CREATE_METHOD {
RamDiskCreateOthers = 0,
RamDiskCreateHii
} RAM_DISK_CREATE_METHOD;
//
// RamDiskDxe driver maintains a list of registered RAM disks.
// The struct contains the list entry and the information of each RAM
// disk
//
typedef struct {
UINTN Signature;
EFI_HANDLE Handle;
EFI_BLOCK_IO_PROTOCOL BlockIo;
EFI_BLOCK_IO_MEDIA Media;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINT64 StartingAddr;
UINT64 Size;
EFI_GUID TypeGuid;
UINT16 InstanceNumber;
RAM_DISK_CREATE_METHOD CreateMethod;
LIST_ENTRY ThisInstance;
} RAM_DISK_PRIVATE_DATA;
#define RAM_DISK_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('R', 'D', 'S', 'K')
#define RAM_DISK_PRIVATE_FROM_BLKIO(a) CR (a, RAM_DISK_PRIVATE_DATA, BlockIo, RAM_DISK_PRIVATE_DATA_SIGNATURE)
#define RAM_DISK_PRIVATE_FROM_THIS(a) CR (a, RAM_DISK_PRIVATE_DATA, ThisInstance, RAM_DISK_PRIVATE_DATA_SIGNATURE)
///
/// RAM disk HII-related definitions and declarations
///
//
// Tool generated IFR binary data and String package data
//
extern UINT8 RamDiskHiiBin[];
extern UINT8 RamDiskDxeStrings[];
typedef struct {
VENDOR_DEVICE_PATH VendorDevicePath;
EFI_DEVICE_PATH_PROTOCOL End;
} HII_VENDOR_DEVICE_PATH;
typedef struct {
UINTN Signature;
EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess;
EFI_HANDLE DriverHandle;
EFI_HII_HANDLE HiiHandle;
} RAM_DISK_CONFIG_PRIVATE_DATA;
extern RAM_DISK_CONFIG_PRIVATE_DATA mRamDiskConfigPrivateDataTemplate;
#define RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('R', 'C', 'F', 'G')
#define RAM_DISK_CONFIG_PRIVATE_FROM_THIS(a) CR (a, RAM_DISK_CONFIG_PRIVATE_DATA, ConfigAccess, RAM_DISK_CONFIG_PRIVATE_DATA_SIGNATURE)
#define RAM_DISK_LIST_VAR_OFFSET ((UINT16) OFFSET_OF (RAM_DISK_CONFIGURATION, RamDiskList))
/**
Register a RAM disk with specified address, size and type.
@param[in] RamDiskBase The base address of registered RAM disk.
@param[in] RamDiskSize The size of registered RAM disk.
@param[in] RamDiskType The type of registered RAM disk. The GUID can be
any of the values defined in section 9.3.6.9, or a
vendor defined GUID.
@param[in] ParentDevicePath
Pointer to the parent device path. If there is no
parent device path then ParentDevicePath is NULL.
@param[out] DevicePath On return, points to a pointer to the device path
of the RAM disk device.
If ParentDevicePath is not NULL, the returned
DevicePath is created by appending a RAM disk node
to the parent device path. If ParentDevicePath is
NULL, the returned DevicePath is a RAM disk device
path without appending. This function is
responsible for allocating the buffer DevicePath
with the boot service AllocatePool().
@retval EFI_SUCCESS The RAM disk is registered successfully.
@retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL.
RamDiskSize is 0.
@retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created
is already present in the handle database.
@retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to
resource limitation.
**/
EFI_STATUS
EFIAPI
RamDiskRegister (
IN UINT64 RamDiskBase,
IN UINT64 RamDiskSize,
IN EFI_GUID *RamDiskType,
IN EFI_DEVICE_PATH *ParentDevicePath OPTIONAL,
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
);
/**
Unregister a RAM disk specified by DevicePath.
@param[in] DevicePath A pointer to the device path that describes a RAM
Disk device.
@retval EFI_SUCCESS The RAM disk is unregistered successfully.
@retval EFI_INVALID_PARAMETER DevicePath is NULL.
@retval EFI_UNSUPPORTED The device specified by DevicePath is not a
valid ramdisk device path and not supported
by the driver.
@retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't
exist.
**/
EFI_STATUS
EFIAPI
RamDiskUnregister (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
);
/**
Initialize the BlockIO protocol of a RAM disk device.
@param[in] PrivateData Points to RAM disk private data.
**/
VOID
RamDiskInitBlockIo (
IN RAM_DISK_PRIVATE_DATA *PrivateData
);
/**
Reset the Block Device.
@param[in] This Indicates a pointer to the calling context.
@param[in] ExtendedVerification
Driver may perform diagnostics on reset.
@retval EFI_SUCCESS The device was reset.
@retval EFI_DEVICE_ERROR The device is not functioning properly and
could not be reset.
**/
EFI_STATUS
EFIAPI
RamDiskBlkIoReset (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
/**
Read BufferSize bytes from Lba into Buffer.
@param[in] This Indicates a pointer to the calling context.
@param[in] MediaId Id of the media, changes every time the media is
replaced.
@param[in] Lba The starting Logical Block Address to read from.
@param[in] BufferSize Size of Buffer, must be a multiple of device block
size.
@param[out] Buffer A pointer to the destination buffer for the data.
The caller is responsible for either having
implicit or explicit ownership of the buffer.
@retval EFI_SUCCESS The data was read correctly from the device.
@retval EFI_DEVICE_ERROR The device reported an error while performing
the read.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_MEDIA_CHANGED The MediaId does not matched the current
device.
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
size of the device.
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
valid, or the buffer is not on proper alignment.
**/
EFI_STATUS
EFIAPI
RamDiskBlkIoReadBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
OUT VOID *Buffer
);
/**
Write BufferSize bytes from Lba into Buffer.
@param[in] This Indicates a pointer to the calling context.
@param[in] MediaId The media ID that the write request is for.
@param[in] Lba The starting logical block address to be written.
The caller is responsible for writing to only
legitimate locations.
@param[in] BufferSize Size of Buffer, must be a multiple of device block
size.
@param[in] Buffer A pointer to the source buffer for the data.
@retval EFI_SUCCESS The data was written correctly to the device.
@retval EFI_WRITE_PROTECTED The device can not be written to.
@retval EFI_DEVICE_ERROR The device reported an error while performing
the write.
@retval EFI_NO_MEDIA There is no media in the device.
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current
device.
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block
size of the device.
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not
valid, or the buffer is not on proper alignment.
**/
EFI_STATUS
EFIAPI
RamDiskBlkIoWriteBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN UINT32 MediaId,
IN EFI_LBA Lba,
IN UINTN BufferSize,
IN VOID *Buffer
);
/**
Flush the Block Device.
@param[in] This Indicates a pointer to the calling context.
@retval EFI_SUCCESS All outstanding data was written to the device.
@retval EFI_DEVICE_ERROR The device reported an error while writting
back the data
@retval EFI_NO_MEDIA There is no media in the device.
**/
EFI_STATUS
EFIAPI
RamDiskBlkIoFlushBlocks (
IN EFI_BLOCK_IO_PROTOCOL *This
);
/**
This function publish the RAM disk configuration Form.
@param[in, out] ConfigPrivateData
Points to RAM disk configuration private data.
@retval EFI_SUCCESS HII Form is installed successfully.
@retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
@retval Others Other errors as indicated.
**/
EFI_STATUS
InstallRamDiskConfigForm (
IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivateData
);
/**
This function removes RAM disk configuration Form.
@param[in, out] ConfigPrivateData
Points to RAM disk configuration private data.
**/
VOID
UninstallRamDiskConfigForm (
IN OUT RAM_DISK_CONFIG_PRIVATE_DATA *ConfigPrivateData
);
/**
Unregister all registered RAM disks.
**/
VOID
UnregisterAllRamDisks (
VOID
);
/**
This function allows a caller to extract the current configuration for one
or more named elements from the target driver.
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param[in] Request A null-terminated Unicode string in
<ConfigRequest> format.
@param[out] Progress On return, points to a character in the Request
string. Points to the string's null terminator if
request was successful. Points to the most recent
'&' before the first failing name/value pair (or
the beginning of the string if the failure is in
the first name/value pair) if the request was not
successful.
@param[out] Results A null-terminated Unicode string in
<ConfigAltResp> format which has all values filled
in for the names in the Request string. String to
be allocated by the called function.
@retval EFI_SUCCESS The Results is filled with the requested
values.
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
@retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
@retval EFI_NOT_FOUND Routing data doesn't match any storage in
this driver.
**/
EFI_STATUS
EFIAPI
RamDiskExtractConfig (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Request,
OUT EFI_STRING *Progress,
OUT EFI_STRING *Results
);
/**
This function processes the results of changes in configuration.
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param[in] Configuration A null-terminated Unicode string in <ConfigResp>
format.
@param[out] Progress A pointer to a string filled in with the offset of
the most recent '&' before the first failing
name/value pair (or the beginning of the string if
the failure is in the first name/value pair) or
the terminating NULL if all was successful.
@retval EFI_SUCCESS The Results is processed successfully.
@retval EFI_INVALID_PARAMETER Configuration is NULL.
@retval EFI_NOT_FOUND Routing data doesn't match any storage in
this driver.
**/
EFI_STATUS
EFIAPI
RamDiskRouteConfig (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN CONST EFI_STRING Configuration,
OUT EFI_STRING *Progress
);
/**
This function processes the results of changes in configuration.
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
@param[in] Action Specifies the type of action taken by the browser.
@param[in] QuestionId A unique value which is sent to the original
exporting driver so that it can identify the type
of data to expect.
@param[in] Type The type of value for the question.
@param[in] Value A pointer to the data being sent to the original
exporting driver.
@param[out] ActionRequest On return, points to the action requested by the
callback function.
@retval EFI_SUCCESS The callback successfully handled the action.
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
variable and its data.
@retval EFI_DEVICE_ERROR The variable could not be saved.
@retval EFI_UNSUPPORTED The specified Action is not supported by the
callback.
**/
EFI_STATUS
EFIAPI
RamDiskCallback (
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
IN EFI_BROWSER_ACTION Action,
IN EFI_QUESTION_ID QuestionId,
IN UINT8 Type,
IN EFI_IFR_TYPE_VALUE *Value,
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
);
/**
This function gets the file information from an open file descriptor,
and stores it in a buffer allocated from pool.
@param[in] FHand File Handle.
@return A pointer to a buffer with file information or NULL is returned.
**/
EFI_FILE_INFO *
FileInfo (
IN EFI_FILE_HANDLE FHand
);
/**
This function will open a file or directory referenced by DevicePath.
This function opens a file with the open mode according to the file path. The
Attributes is valid only for EFI_FILE_MODE_CREATE.
@param[in, out] FilePath On input, the device path to the file.
On output, the remaining device path.
@param[out] FileHandle Pointer to the file handle.
@param[in] OpenMode The mode to open the file with.
@param[in] Attributes The file's file attributes.
@retval EFI_SUCCESS The information was set.
@retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
@retval EFI_UNSUPPORTED Could not open the file path.
@retval EFI_NOT_FOUND The specified file could not be found on the
device or the file system could not be found
on the device.
@retval EFI_NO_MEDIA The device has no medium.
@retval EFI_MEDIA_CHANGED The device has a different medium in it or
the medium is no longer supported.
@retval EFI_DEVICE_ERROR The device reported an error.
@retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
@retval EFI_WRITE_PROTECTED The file or medium is write protected.
@retval EFI_ACCESS_DENIED The file was opened read only.
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open
the file.
@retval EFI_VOLUME_FULL The volume is full.
**/
EFI_STATUS
EFIAPI
OpenFileByDevicePath(
IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
OUT EFI_FILE_HANDLE *FileHandle,
IN UINT64 OpenMode,
IN UINT64 Attributes
);
#endif

View File

@ -0,0 +1,43 @@
/** @file
Header file for NV data structure definition.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef _RAM_DISK_NVDATA_H_
#define _RAM_DISK_NVDATA_H_
#include <Guid/HiiPlatformSetupFormset.h>
#include <Guid/RamDiskHii.h>
#define RAM_DISK_CONFIGURATION_VARSTORE_ID 0x0001
#define MAIN_FORM_ID 0x1000
#define MAIN_GOTO_FILE_EXPLORER_ID 0x1001
#define MAIN_REMOVE_RD_QUESTION_ID 0x1002
#define MAIN_CHECKBOX_QUESTION_ID_START 0x1003
#define MAIN_LABEL_LIST_START 0x1004
#define MAIN_LABEL_LIST_END 0x1005
#define CREATE_RAW_RAM_DISK_FORM_ID 0x2000
#define CREATE_RAW_SIZE_QUESTION_ID 0x2001
#define CREATE_RAW_SUBMIT_QUESTION_ID 0x2002
#define CREATE_RAW_DISCARD_QUESTION_ID 0x2003
typedef struct {
UINT64 Size;
//
// CheckBox status for created RAM disks
//
UINT8 RamDiskList[0];
} RAM_DISK_CONFIGURATION;
#endif

View File

@ -0,0 +1,356 @@
/** @file
The realization of EFI_RAM_DISK_PROTOCOL.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "RamDiskImpl.h"
RAM_DISK_PRIVATE_DATA mRamDiskPrivateDataTemplate = {
RAM_DISK_PRIVATE_DATA_SIGNATURE,
NULL
};
MEDIA_RAM_DISK_DEVICE_PATH mRamDiskDeviceNodeTemplate = {
{
MEDIA_DEVICE_PATH,
MEDIA_RAM_DISK_DP,
{
(UINT8) (sizeof (MEDIA_RAM_DISK_DEVICE_PATH)),
(UINT8) ((sizeof (MEDIA_RAM_DISK_DEVICE_PATH)) >> 8)
}
}
};
/**
Initialize the RAM disk device node.
@param[in] PrivateData Points to RAM disk private data.
@param[in, out] RamDiskDevNode Points to the RAM disk device node.
**/
VOID
RamDiskInitDeviceNode (
IN RAM_DISK_PRIVATE_DATA *PrivateData,
IN OUT MEDIA_RAM_DISK_DEVICE_PATH *RamDiskDevNode
)
{
WriteUnaligned64 (
(UINT64 *) &(RamDiskDevNode->StartingAddr[0]),
(UINT64) PrivateData->StartingAddr
);
WriteUnaligned64 (
(UINT64 *) &(RamDiskDevNode->EndingAddr[0]),
(UINT64) PrivateData->StartingAddr + PrivateData->Size
);
CopyGuid (&RamDiskDevNode->TypeGuid, &PrivateData->TypeGuid);
RamDiskDevNode->Instance = PrivateData->InstanceNumber;
}
/**
Register a RAM disk with specified address, size and type.
@param[in] RamDiskBase The base address of registered RAM disk.
@param[in] RamDiskSize The size of registered RAM disk.
@param[in] RamDiskType The type of registered RAM disk. The GUID can be
any of the values defined in section 9.3.6.9, or a
vendor defined GUID.
@param[in] ParentDevicePath
Pointer to the parent device path. If there is no
parent device path then ParentDevicePath is NULL.
@param[out] DevicePath On return, points to a pointer to the device path
of the RAM disk device.
If ParentDevicePath is not NULL, the returned
DevicePath is created by appending a RAM disk node
to the parent device path. If ParentDevicePath is
NULL, the returned DevicePath is a RAM disk device
path without appending. This function is
responsible for allocating the buffer DevicePath
with the boot service AllocatePool().
@retval EFI_SUCCESS The RAM disk is registered successfully.
@retval EFI_INVALID_PARAMETER DevicePath or RamDiskType is NULL.
RamDiskSize is 0.
@retval EFI_ALREADY_STARTED A Device Path Protocol instance to be created
is already present in the handle database.
@retval EFI_OUT_OF_RESOURCES The RAM disk register operation fails due to
resource limitation.
**/
EFI_STATUS
EFIAPI
RamDiskRegister (
IN UINT64 RamDiskBase,
IN UINT64 RamDiskSize,
IN EFI_GUID *RamDiskType,
IN EFI_DEVICE_PATH *ParentDevicePath OPTIONAL,
OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
)
{
EFI_STATUS Status;
RAM_DISK_PRIVATE_DATA *PrivateData;
RAM_DISK_PRIVATE_DATA *RegisteredPrivateData;
MEDIA_RAM_DISK_DEVICE_PATH *RamDiskDevNode;
UINTN DevicePathSize;
LIST_ENTRY *Entry;
EFI_TPL OldTpl;
if ((0 == RamDiskSize) || (NULL == RamDiskType) || (NULL == DevicePath)) {
return EFI_INVALID_PARAMETER;
}
//
// Add check to prevent data read across the memory boundary
//
if (RamDiskBase + RamDiskSize > ((UINTN) -1) - RAM_DISK_BLOCK_SIZE + 1) {
return EFI_INVALID_PARAMETER;
}
RamDiskDevNode = NULL;
//
// Create a new RAM disk instance and initialize its private data
//
PrivateData = AllocateCopyPool (
sizeof (RAM_DISK_PRIVATE_DATA),
&mRamDiskPrivateDataTemplate
);
if (NULL == PrivateData) {
return EFI_OUT_OF_RESOURCES;
}
PrivateData->StartingAddr = RamDiskBase;
PrivateData->Size = RamDiskSize;
CopyGuid (&PrivateData->TypeGuid, RamDiskType);
InitializeListHead (&PrivateData->ThisInstance);
//
// Generate device path information for the registered RAM disk
//
RamDiskDevNode = AllocateCopyPool (
sizeof (MEDIA_RAM_DISK_DEVICE_PATH),
&mRamDiskDeviceNodeTemplate
);
if (NULL == RamDiskDevNode) {
Status = EFI_OUT_OF_RESOURCES;
goto ErrorExit;
}
RamDiskInitDeviceNode (PrivateData, RamDiskDevNode);
*DevicePath = AppendDevicePathNode (
ParentDevicePath,
(EFI_DEVICE_PATH_PROTOCOL *) RamDiskDevNode
);
if (NULL == *DevicePath) {
Status = EFI_OUT_OF_RESOURCES;
goto ErrorExit;
}
PrivateData->DevicePath = *DevicePath;
//
// Check whether the created device path is already present in the handle
// database
//
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
if (!IsListEmpty(&RegisteredRamDisks)) {
DevicePathSize = GetDevicePathSize (PrivateData->DevicePath);
EFI_LIST_FOR_EACH (Entry, &RegisteredRamDisks) {
RegisteredPrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
if (DevicePathSize == GetDevicePathSize (RegisteredPrivateData->DevicePath)) {
//
// Compare device path
//
if ((CompareMem (
PrivateData->DevicePath,
RegisteredPrivateData->DevicePath,
DevicePathSize)) == 0) {
*DevicePath = NULL;
Status = EFI_ALREADY_STARTED;
goto ErrorExit;
}
}
}
}
gBS->RestoreTPL (OldTpl);
//
// Fill Block IO protocol informations for the RAM disk
//
RamDiskInitBlockIo (PrivateData);
//
// Install EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO_PROTOCOL on a new
// handle
//
Status = gBS->InstallMultipleProtocolInterfaces (
&PrivateData->Handle,
&gEfiBlockIoProtocolGuid,
&PrivateData->BlockIo,
&gEfiDevicePathProtocolGuid,
PrivateData->DevicePath,
NULL
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Insert the newly created one to the registered RAM disk list
//
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
InsertTailList (&RegisteredRamDisks, &PrivateData->ThisInstance);
ListEntryNum++;
gBS->RestoreTPL (OldTpl);
gBS->ConnectController (PrivateData->Handle, NULL, NULL, TRUE);
FreePool (RamDiskDevNode);
return EFI_SUCCESS;
ErrorExit:
if (RamDiskDevNode != NULL) {
FreePool (RamDiskDevNode);
}
if (PrivateData != NULL) {
if (PrivateData->DevicePath) {
FreePool (PrivateData->DevicePath);
}
FreePool (PrivateData);
}
return Status;
}
/**
Unregister a RAM disk specified by DevicePath.
@param[in] DevicePath A pointer to the device path that describes a RAM
Disk device.
@retval EFI_SUCCESS The RAM disk is unregistered successfully.
@retval EFI_INVALID_PARAMETER DevicePath is NULL.
@retval EFI_UNSUPPORTED The device specified by DevicePath is not a
valid ramdisk device path and not supported
by the driver.
@retval EFI_NOT_FOUND The RAM disk pointed by DevicePath doesn't
exist.
**/
EFI_STATUS
EFIAPI
RamDiskUnregister (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
LIST_ENTRY *Entry;
LIST_ENTRY *NextEntry;
BOOLEAN Found;
UINT64 StartingAddr;
UINT64 EndingAddr;
EFI_DEVICE_PATH_PROTOCOL *Header;
MEDIA_RAM_DISK_DEVICE_PATH *RamDiskDevNode;
RAM_DISK_PRIVATE_DATA *PrivateData;
EFI_TPL OldTpl;
if (NULL == DevicePath) {
return EFI_INVALID_PARAMETER;
}
//
// Locate the RAM disk device node.
//
RamDiskDevNode = NULL;
Header = DevicePath;
do {
//
// Test if the current device node is a RAM disk.
//
if ((MEDIA_DEVICE_PATH == Header->Type) &&
(MEDIA_RAM_DISK_DP == Header->SubType)) {
RamDiskDevNode = (MEDIA_RAM_DISK_DEVICE_PATH *) Header;
break;
}
Header = NextDevicePathNode (Header);
} while ((Header->Type != END_DEVICE_PATH_TYPE));
if (NULL == RamDiskDevNode) {
return EFI_UNSUPPORTED;
}
Found = FALSE;
StartingAddr = ReadUnaligned64 ((UINT64 *) &(RamDiskDevNode->StartingAddr[0]));
EndingAddr = ReadUnaligned64 ((UINT64 *) &(RamDiskDevNode->EndingAddr[0]));
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
if (!IsListEmpty(&RegisteredRamDisks)) {
EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &RegisteredRamDisks) {
PrivateData = RAM_DISK_PRIVATE_FROM_THIS (Entry);
//
// Unregister the RAM disk given by its starting address, ending address
// and type guid.
//
if ((StartingAddr == PrivateData->StartingAddr) &&
(EndingAddr == PrivateData->StartingAddr + PrivateData->Size) &&
(CompareGuid (&RamDiskDevNode->TypeGuid, &PrivateData->TypeGuid))) {
//
// Uninstall the EFI_DEVICE_PATH_PROTOCOL & EFI_BLOCK_IO_PROTOCOL
//
gBS->UninstallMultipleProtocolInterfaces (
PrivateData->Handle,
&gEfiBlockIoProtocolGuid,
&PrivateData->BlockIo,
&gEfiDevicePathProtocolGuid,
DevicePath,
NULL
);
RemoveEntryList (&PrivateData->ThisInstance);
if (RamDiskCreateHii == PrivateData->CreateMethod) {
//
// If a RAM disk is created within HII, then the RamDiskDxe driver
// driver is responsible for freeing the allocated memory for the
// RAM disk.
//
FreePool ((VOID *)(UINTN) PrivateData->StartingAddr);
}
gBS->DisconnectController (PrivateData->Handle, NULL, NULL);
FreePool (PrivateData->DevicePath);
FreePool (PrivateData);
ListEntryNum--;
Found = TRUE;
break;
}
}
}
gBS->RestoreTPL (OldTpl);
if (TRUE == Found) {
return EFI_SUCCESS;
} else {
return EFI_NOT_FOUND;
}
}