aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c')
-rw-r--r--roms/edk2/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c487
1 files changed, 487 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c b/roms/edk2/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
new file mode 100644
index 000000000..13f81bae1
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskBlockIo.c
@@ -0,0 +1,487 @@
+/** @file
+ Produce EFI_BLOCK_IO_PROTOCOL on a RAM disk device.
+
+ Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+};
+
+//
+// The EFI_BLOCK_IO_PROTOCOL2 instances that is installed onto the handle
+// for newly registered RAM disks
+//
+EFI_BLOCK_IO2_PROTOCOL mRamDiskBlockIo2Template = {
+ (EFI_BLOCK_IO_MEDIA *) 0,
+ RamDiskBlkIo2Reset,
+ RamDiskBlkIo2ReadBlocksEx,
+ RamDiskBlkIo2WriteBlocksEx,
+ RamDiskBlkIo2FlushBlocksEx
+};
+
+
+/**
+ Initialize the BlockIO & BlockIO2 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_IO2_PROTOCOL *BlockIo2;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINT32 Remainder;
+
+ BlockIo = &PrivateData->BlockIo;
+ BlockIo2 = &PrivateData->BlockIo2;
+ Media = &PrivateData->Media;
+
+ CopyMem (BlockIo, &mRamDiskBlockIoTemplate, sizeof (EFI_BLOCK_IO_PROTOCOL));
+ CopyMem (BlockIo2, &mRamDiskBlockIo2Template, sizeof (EFI_BLOCK_IO2_PROTOCOL));
+
+ BlockIo->Media = Media;
+ BlockIo2->Media = Media;
+ Media->RemovableMedia = FALSE;
+ Media->MediaPresent = TRUE;
+ Media->LogicalPartition = FALSE;
+ Media->ReadOnly = FALSE;
+ Media->WriteCaching = FALSE;
+
+ for (Media->BlockSize = RAM_DISK_DEFAULT_BLOCK_SIZE;
+ Media->BlockSize >= 1;
+ Media->BlockSize = Media->BlockSize >> 1) {
+ Media->LastBlock = DivU64x32Remainder (PrivateData->Size, Media->BlockSize, &Remainder) - 1;
+ if (Remainder == 0) {
+ break;
+ }
+ }
+ ASSERT (Media->BlockSize != 0);
+
+ return;
+}
+
+
+/**
+ 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;
+
+ PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO (This);
+
+ if (MediaId != PrivateData->Media.MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ 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;
+
+ 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 (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ 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;
+}
+
+
+/**
+ Resets the block device hardware.
+
+ @param[in] This The pointer of EFI_BLOCK_IO2_PROTOCOL.
+ @param[in] ExtendedVerification The flag about if extend verificate.
+
+ @retval EFI_SUCCESS The device was reset.
+ @retval EFI_DEVICE_ERROR The block device is not functioning correctly
+ and could not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIo2Reset (
+ IN EFI_BLOCK_IO2_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reads the requested number of blocks from the device.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the read request is for.
+ @param[in] Lba The starting logical block address to read
+ from on the device.
+ @param[in, out] Token A pointer to the token associated with the
+ transaction.
+ @param[in] BufferSize The size of the Buffer in bytes. This must be
+ a multiple of the intrinsic block size of the
+ device.
+ @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 read request was queued if Token->Event
+ is not NULL. The data was read correctly from
+ the device if the Token->Event is NULL.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting
+ to perform the read operation.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+ @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
+ the intrinsic 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.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIo2ReadBlocksEx (
+ IN EFI_BLOCK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ RAM_DISK_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+
+ PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);
+
+ Status = RamDiskBlkIoReadBlocks (
+ &PrivateData->BlockIo,
+ MediaId,
+ Lba,
+ BufferSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If caller's event is given, signal it after the memory read completes.
+ //
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Token->TransactionStatus = EFI_SUCCESS;
+ gBS->SignalEvent (Token->Event);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Writes a specified number of blocks to the device.
+
+ @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, out] Token A pointer to the token associated with the
+ transaction.
+ @param[in] BufferSize The size in bytes of Buffer. This must be a
+ multiple of the intrinsic block size of the
+ device.
+ @param[in] Buffer A pointer to the source buffer for the data.
+
+ @retval EFI_SUCCESS The write request was queued if Event is not
+ NULL. The data was written correctly to the
+ device if the Event is NULL.
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting
+ to perform the write operation.
+ @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
+ the intrinsic 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.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIo2WriteBlocksEx (
+ IN EFI_BLOCK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ RAM_DISK_PRIVATE_DATA *PrivateData;
+ EFI_STATUS Status;
+
+ PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);
+
+ Status = RamDiskBlkIoWriteBlocks (
+ &PrivateData->BlockIo,
+ MediaId,
+ Lba,
+ BufferSize,
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If caller's event is given, signal it after the memory write completes.
+ //
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Token->TransactionStatus = EFI_SUCCESS;
+ gBS->SignalEvent (Token->Event);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Flushes all modified data to a physical block device.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in, out] Token A pointer to the token associated with the
+ transaction.
+
+ @retval EFI_SUCCESS The flush request was queued if Event is not
+ NULL. All outstanding data was written
+ correctly to the device if the Event is NULL.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting
+ to write data.
+ @retval EFI_WRITE_PROTECTED The device cannot be written to.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RamDiskBlkIo2FlushBlocksEx (
+ IN EFI_BLOCK_IO2_PROTOCOL *This,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token
+ )
+{
+ RAM_DISK_PRIVATE_DATA *PrivateData;
+
+ PrivateData = RAM_DISK_PRIVATE_FROM_BLKIO2 (This);
+
+ if (TRUE == PrivateData->Media.ReadOnly) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ //
+ // If caller's event is given, signal it directly.
+ //
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Token->TransactionStatus = EFI_SUCCESS;
+ gBS->SignalEvent (Token->Event);
+ }
+
+ return EFI_SUCCESS;
+}