Generated mechanically with:
find OvmfPkg -type f -exec sed -i -e 's/EFI_D_/DEBUG_/g' {} \;
Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
Cc: Philippe Mathieu-Daude <philmd@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20200429215327.606467-1-rebecca@bsdio.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
		
	
		
			
				
	
	
		
			271 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			271 lines
		
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   BlockIo implementation for Xen PV Block driver.
 | |
| 
 | |
|   This file is implementing the interface between the actual driver in
 | |
|   BlockFront.c to the BlockIo protocol.
 | |
| 
 | |
|   Copyright (C) 2014, Citrix Ltd.
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "XenPvBlkDxe.h"
 | |
| 
 | |
| #include "BlockFront.h"
 | |
| 
 | |
| ///
 | |
| /// Block I/O Media structure
 | |
| ///
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED
 | |
| EFI_BLOCK_IO_MEDIA  gXenPvBlkDxeBlockIoMedia = {
 | |
|   0,      // MediaId
 | |
|   FALSE,  // RemovableMedia
 | |
|   FALSE,  // MediaPresent
 | |
|   FALSE,  // LogicalPartition
 | |
|   TRUE,   // ReadOnly
 | |
|   FALSE,  // WriteCaching
 | |
|   512,    // BlockSize
 | |
|   512,    // IoAlign, BlockFront does not support less than 512 bits-aligned.
 | |
|   0,      // LastBlock
 | |
|   0,      // LowestAlignedLba
 | |
|   0,      // LogicalBlocksPerPhysicalBlock
 | |
|   0       // OptimalTransferLengthGranularity
 | |
| };
 | |
| 
 | |
| ///
 | |
| /// Block I/O Protocol instance
 | |
| ///
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED
 | |
| EFI_BLOCK_IO_PROTOCOL  gXenPvBlkDxeBlockIo = {
 | |
|   EFI_BLOCK_IO_PROTOCOL_REVISION3,          // Revision
 | |
|   &gXenPvBlkDxeBlockIoMedia,                // Media
 | |
|   XenPvBlkDxeBlockIoReset,                  // Reset
 | |
|   XenPvBlkDxeBlockIoReadBlocks,             // ReadBlocks
 | |
|   XenPvBlkDxeBlockIoWriteBlocks,            // WriteBlocks
 | |
|   XenPvBlkDxeBlockIoFlushBlocks             // FlushBlocks
 | |
| };
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Read/Write BufferSize bytes from Lba into Buffer.
 | |
| 
 | |
|   This function is common to XenPvBlkDxeBlockIoReadBlocks and
 | |
|   XenPvBlkDxeBlockIoWriteBlocks.
 | |
| 
 | |
|   @param  This       Indicates a pointer to the calling context.
 | |
|   @param  MediaId    Id of the media, changes every time the media is replaced.
 | |
|   @param  Lba        The starting Logical Block Address to read from/write to.
 | |
|   @param  BufferSize Size of Buffer, must be a multiple of device block size.
 | |
|   @param  Buffer     A pointer to the destination/source buffer for the data.
 | |
|   @param  IsWrite    Indicate if the operation is write or read.
 | |
| 
 | |
|   @return See description of XenPvBlkDxeBlockIoReadBlocks and
 | |
|           XenPvBlkDxeBlockIoWriteBlocks.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| XenPvBlkDxeBlockIoReadWriteBlocks (
 | |
|   IN     EFI_BLOCK_IO_PROTOCOL  *This,
 | |
|   IN     UINT32                 MediaId,
 | |
|   IN     EFI_LBA                Lba,
 | |
|   IN     UINTN                  BufferSize,
 | |
|   IN OUT VOID                   *Buffer,
 | |
|   IN     BOOLEAN                IsWrite
 | |
|   )
 | |
| {
 | |
|   XEN_BLOCK_FRONT_IO IoData;
 | |
|   EFI_BLOCK_IO_MEDIA *Media = This->Media;
 | |
|   UINTN Sector;
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   if (Buffer == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   if (BufferSize == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (BufferSize % Media->BlockSize != 0) {
 | |
|     DEBUG ((DEBUG_ERROR, "XenPvBlkDxe: Bad buffer size: 0x%Lx\n",
 | |
|       (UINT64)BufferSize));
 | |
|     return EFI_BAD_BUFFER_SIZE;
 | |
|   }
 | |
| 
 | |
|   if (Lba > Media->LastBlock ||
 | |
|       (BufferSize / Media->BlockSize) - 1 > Media->LastBlock - Lba) {
 | |
|     DEBUG ((DEBUG_ERROR,
 | |
|       "XenPvBlkDxe: %a with invalid LBA: 0x%Lx, size: 0x%Lx\n",
 | |
|       IsWrite ? "Write" : "Read", Lba, (UINT64)BufferSize));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (IsWrite && Media->ReadOnly) {
 | |
|     return EFI_WRITE_PROTECTED;
 | |
|   }
 | |
| 
 | |
|   if ((Media->IoAlign > 1) && (UINTN)Buffer & (Media->IoAlign - 1)) {
 | |
|     //
 | |
|     // Grub2 does not appear to respect IoAlign of 512, so reallocate the
 | |
|     // buffer here.
 | |
|     //
 | |
|     VOID *NewBuffer;
 | |
| 
 | |
|     //
 | |
|     // Try again with a properly aligned buffer.
 | |
|     //
 | |
|     NewBuffer = AllocateAlignedPages((BufferSize + EFI_PAGE_SIZE) / EFI_PAGE_SIZE,
 | |
|                                      Media->IoAlign);
 | |
|     if (!IsWrite) {
 | |
|       Status = XenPvBlkDxeBlockIoReadBlocks (This, MediaId,
 | |
|                                              Lba, BufferSize, NewBuffer);
 | |
|       CopyMem (Buffer, NewBuffer, BufferSize);
 | |
|     } else {
 | |
|       CopyMem (NewBuffer, Buffer, BufferSize);
 | |
|       Status = XenPvBlkDxeBlockIoWriteBlocks (This, MediaId,
 | |
|                                               Lba, BufferSize, NewBuffer);
 | |
|     }
 | |
|     FreeAlignedPages (NewBuffer, (BufferSize + EFI_PAGE_SIZE) / EFI_PAGE_SIZE);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   IoData.Dev = XEN_BLOCK_FRONT_FROM_BLOCK_IO (This);
 | |
|   Sector = (UINTN)MultU64x32 (Lba, Media->BlockSize / 512);
 | |
| 
 | |
|   while (BufferSize > 0) {
 | |
|     if (((UINTN)Buffer & EFI_PAGE_MASK) == 0) {
 | |
|       IoData.Size = MIN (BLKIF_MAX_SEGMENTS_PER_REQUEST * EFI_PAGE_SIZE,
 | |
|                          BufferSize);
 | |
|     } else {
 | |
|       IoData.Size = MIN ((BLKIF_MAX_SEGMENTS_PER_REQUEST - 1) * EFI_PAGE_SIZE,
 | |
|                          BufferSize);
 | |
|     }
 | |
| 
 | |
|     IoData.Buffer = Buffer;
 | |
|     IoData.Sector = Sector;
 | |
|     BufferSize -= IoData.Size;
 | |
|     Buffer = (VOID*) ((UINTN) Buffer + IoData.Size);
 | |
|     Sector += IoData.Size / 512;
 | |
|     Status = XenPvBlockIo (&IoData, IsWrite);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((DEBUG_ERROR, "XenPvBlkDxe: Error during %a operation.\n",
 | |
|               IsWrite ? "write" : "read"));
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Read BufferSize bytes from Lba into Buffer.
 | |
| 
 | |
|   @param  This       Indicates a pointer to the calling context.
 | |
|   @param  MediaId    Id of the media, changes every time the media is replaced.
 | |
|   @param  Lba        The starting Logical Block Address to read from
 | |
|   @param  BufferSize Size of Buffer, must be a multiple of device block size.
 | |
|   @param  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 match 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
 | |
| XenPvBlkDxeBlockIoReadBlocks (
 | |
|   IN  EFI_BLOCK_IO_PROTOCOL         *This,
 | |
|   IN  UINT32                        MediaId,
 | |
|   IN  EFI_LBA                       Lba,
 | |
|   IN  UINTN                         BufferSize,
 | |
|   OUT VOID                          *Buffer
 | |
|   )
 | |
| {
 | |
|   return XenPvBlkDxeBlockIoReadWriteBlocks (This,
 | |
|       MediaId, Lba, BufferSize, Buffer, FALSE);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Write BufferSize bytes from Lba into Buffer.
 | |
| 
 | |
|   @param  This       Indicates a pointer to the calling context.
 | |
|   @param  MediaId    The media ID that the write request is for.
 | |
|   @param  Lba        The starting logical block address to be written. The caller is
 | |
|                      responsible for writing to only legitimate locations.
 | |
|   @param  BufferSize Size of Buffer, must be a multiple of device block size.
 | |
|   @param  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_CHANGED     The MediaId does not match 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
 | |
| XenPvBlkDxeBlockIoWriteBlocks (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL          *This,
 | |
|   IN UINT32                         MediaId,
 | |
|   IN EFI_LBA                        Lba,
 | |
|   IN UINTN                          BufferSize,
 | |
|   IN VOID                           *Buffer
 | |
|   )
 | |
| {
 | |
|   return XenPvBlkDxeBlockIoReadWriteBlocks (This,
 | |
|       MediaId, Lba, BufferSize, Buffer, TRUE);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Flush the Block Device.
 | |
| 
 | |
|   @param  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 writing back the data
 | |
|   @retval EFI_NO_MEDIA      There is no media in the device.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| XenPvBlkDxeBlockIoFlushBlocks (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   XenPvBlockSync (XEN_BLOCK_FRONT_FROM_BLOCK_IO (This));
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reset the block device hardware.
 | |
| 
 | |
|   @param[in]  This                 Indicates a pointer to the calling context.
 | |
|   @param[in]  ExtendedVerification Not used.
 | |
| 
 | |
|   @retval EFI_SUCCESS          The device was reset.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| XenPvBlkDxeBlockIoReset (
 | |
|   IN EFI_BLOCK_IO_PROTOCOL   *This,
 | |
|   IN BOOLEAN                 ExtendedVerification
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Since the initialization of the devices is done, then the device is
 | |
|   // working correctly.
 | |
|   //
 | |
|   return EFI_SUCCESS;
 | |
| }
 |